CodeQL and clang-tidy #13498
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
name: "CodeQL and clang-tidy" | |
on: | |
push: | |
pull_request: | |
schedule: | |
- cron: '0 22 * * 2' | |
permissions: # least privileges, see https://docs.github.com/en/actions/using-workflows/workflow-syntax-for-github-actions#permissions | |
contents: read | |
# clang-tidy fun: | |
# We need to invoke clang-tidy from the correct directory, the one the product was compiled in, so that we get the correct include paths. | |
# This means the root for the auth, pdns/recursordist for the rec and pdns/dnsdistdist for dnsdist | |
# It is important that files that are used by more than one product are processed by all the products using them | |
# because they might have difference compilation flags. | |
# We have to use our own clang-tidy-diff.py because the line-filter flag only supports file names, not paths. | |
# Finally the GH annotations that we generate from clang-tidy.py, have to be relative to the path in the git repository, so we need to | |
# follow symlinks. | |
# How does that work? We use git diff to get the list of diffs, and git-filter.py to get the right folder depending on the product. | |
# Then we call clang-tidy-diff.py, which invokes clang-tidy on the correct file, deducing the line numbers from the diff, and | |
# merging the results for all processed files to a YAML file. Finally clang-tidy.py converts the YAML output to GitHub annotations | |
# (GitHub only supports 10 of these per job, the rest are not displayed) and to GitHub markdown step summary (which has no such limits). | |
jobs: | |
analyze: | |
name: Analyze | |
if: ${{ !github.event.schedule || vars.SCHEDULED_CODEQL_ANALYSIS }} | |
runs-on: ubuntu-22.04 | |
permissions: | |
actions: read # for github/codeql-action/init to get workflow details | |
contents: read # for actions/checkout to fetch code | |
security-events: write # for github/codeql-action/analyze to upload SARIF results | |
strategy: | |
fail-fast: false | |
matrix: | |
# Override automatic language detection by changing the below list | |
# Supported options are ['csharp', 'cpp', 'go', 'java', 'javascript', 'python'] | |
language: ['cpp'] | |
product: ['auth', 'rec', 'dnsdist'] | |
# Learn more... | |
# https://docs.github.com/en/github/finding-security-vulnerabilities-and-errors-in-your-code/configuring-code-scanning#overriding-automatic-language-detection | |
env: | |
COMPILER: gcc | |
UNIT_TESTS: yes | |
FUZZING_TARGETS: yes | |
COVERAGE: no | |
OPTIMIZATIONS: no | |
# for clang-tidy only, not compilation | |
CLANG_VERSION: '14' | |
REPO_HOME: ${{ github.workspace }} | |
DECAF_SUPPORT: no | |
outputs: | |
clang-tidy-annotations-auth: ${{ steps.clang-tidy-annotations-auth.outputs.failed }} | |
clang-tidy-annotations-dnsdist: ${{ steps.clang-tidy-annotations-dnsdist.outputs.failed }} | |
clang-tidy-annotations-rec: ${{ steps.clang-tidy-annotations-rec.outputs.failed }} | |
steps: | |
- uses: PowerDNS/pdns/set-ubuntu-mirror@meta | |
- name: Checkout repository | |
uses: actions/checkout@v4 | |
with: | |
# We must fetch at least the immediate parents so that if this is | |
# a pull request then we can checkout the head. | |
fetch-depth: 2 | |
- uses: actions/setup-python@v5 | |
with: | |
python-version: '3.11' | |
# Initializes the CodeQL tools for scanning. | |
- name: Initialize CodeQL | |
uses: github/codeql-action/init@v3 | |
with: | |
languages: ${{ matrix.language }} | |
queries: +security-and-quality | |
# TODO: go through +security-and-quality (400 alerts) once, then see if we can upgrade to it | |
# If you wish to specify custom queries, you can do so here or in a config file. | |
# By default, queries listed here will override any specified in a config file. | |
# Prefix the list here with "+" to use these queries and those in the config file. | |
# queries: ./path/to/local/query, your-org/your-repo/queries@main | |
# Autobuild attempts to build any compiled languages (C/C++, C#, or Java). | |
# If this step fails, then you should remove it and run the build manually (see below) | |
# - name: Autobuild | |
# uses: github/codeql-action/autobuild@v2 | |
# ℹ️ Command-line programs to run using the OS shell. | |
# 📚 https://git.io/JvXDl | |
# ✏️ If the Autobuild fails above, remove it and uncomment the following three lines | |
# and modify them (or add more) to build your code if your project | |
# uses a compiled language | |
- name: Update repository metadata | |
run: | | |
sudo apt-get update | |
- name: Install python invoke and needed libs | |
run: | | |
sudo apt-get -qq -y --no-install-recommends install python3 python3-pip python3-invoke python3-git python3-unidiff ccache | |
- name: Install clang-tidy tools | |
run: | | |
inv install-clang-tidy-tools | |
- name: Install dependencies for auth | |
if: matrix.product == 'auth' | |
run: | | |
inv install-auth-build-deps | |
- name: Autoreconf auth | |
if: matrix.product == 'auth' | |
run: | | |
inv ci-autoconf | |
- name: Configure auth | |
if: matrix.product == 'auth' | |
run: | | |
inv ci-auth-configure | |
- name: Build auth | |
if: matrix.product == 'auth' | |
run: | | |
inv ci-auth-make-bear | |
- run: ln -s .clang-tidy.full .clang-tidy | |
if: matrix.product == 'auth' | |
- name: Run clang-tidy for auth | |
if: matrix.product == 'auth' | |
run: git diff --no-prefix -U0 HEAD^..HEAD | /usr/bin/python3 .github/scripts/git-filter.py --product auth | /usr/bin/python3 .github/scripts/clang-tidy-diff.py -clang-tidy-binary /usr/bin/clang-tidy-${CLANG_VERSION} -extra-arg=-ferror-limit=0 -p0 -export-fixes clang-tidy-auth.yml | |
- name: Print clang-tidy fixes YAML for auth | |
if: matrix.product == 'auth' | |
shell: bash | |
run: | | |
if [ -f clang-tidy-auth.yml ]; then | |
cat clang-tidy-auth.yml | |
fi | |
- name: Result annotations for auth | |
if: matrix.product == 'auth' | |
id: clang-tidy-annotations-auth | |
shell: bash | |
run: | | |
if [ -f clang-tidy-auth.yml ]; then | |
set +e | |
/usr/bin/python3 .github/scripts/clang-tidy.py --fixes-file clang-tidy-auth.yml | |
echo "failed=$?" >> $GITHUB_OUTPUT | |
fi | |
- name: Install dependencies for dnsdist | |
if: matrix.product == 'dnsdist' | |
run: | | |
inv install-dnsdist-build-deps --skipXDP | |
- name: Autoreconf dnsdist | |
if: matrix.product == 'dnsdist' | |
working-directory: ./pdns/dnsdistdist/ | |
run: | | |
inv ci-autoconf | |
- run: inv ci-install-rust ${{ env.REPO_HOME }} | |
if: matrix.product == 'dnsdist' | |
working-directory: ./pdns/dnsdistdist/ | |
- run: inv ci-build-and-install-quiche ${{ env.REPO_HOME }} | |
if: matrix.product == 'dnsdist' | |
working-directory: ./pdns/dnsdistdist/ | |
- name: Configure dnsdist | |
if: matrix.product == 'dnsdist' | |
working-directory: ./pdns/dnsdistdist/ | |
run: | | |
inv ci-dnsdist-configure full | |
- name: Build dnsdist | |
if: matrix.product == 'dnsdist' | |
working-directory: ./pdns/dnsdistdist/ | |
run: | | |
inv ci-dnsdist-make-bear | |
- run: ln -s ../../.clang-tidy.full .clang-tidy | |
if: matrix.product == 'dnsdist' | |
working-directory: ./pdns/dnsdistdist/ | |
- name: Run clang-tidy for dnsdist | |
if: matrix.product == 'dnsdist' | |
working-directory: ./pdns/dnsdistdist/ | |
run: git diff --no-prefix -U0 HEAD^..HEAD | /usr/bin/python3 ../../.github/scripts/git-filter.py --product dnsdist | /usr/bin/python3 ../../.github/scripts/clang-tidy-diff.py -clang-tidy-binary /usr/bin/clang-tidy-${CLANG_VERSION} -extra-arg=-ferror-limit=0 -p0 -export-fixes clang-tidy-dnsdist.yml | |
- name: Print clang-tidy fixes YAML for dnsdist | |
if: matrix.product == 'dnsdist' | |
working-directory: ./pdns/dnsdistdist/ | |
shell: bash | |
run: | | |
if [ -f clang-tidy-dnsdist.yml ]; then | |
cat clang-tidy-dnsdist.yml | |
fi | |
- name: Result annotations for dnsdist | |
if: matrix.product == 'dnsdist' | |
id: clang-tidy-annotations-dnsdist | |
working-directory: ./pdns/dnsdistdist/ | |
shell: bash | |
run: | | |
if [ -f clang-tidy-dnsdist.yml ]; then | |
set +e | |
/usr/bin/python3 ../../.github/scripts/clang-tidy.py --fixes-file clang-tidy-dnsdist.yml | |
echo "failed=$?" >> $GITHUB_OUTPUT | |
fi | |
- name: Install dependencies for rec | |
if: matrix.product == 'rec' | |
run: | | |
inv install-rec-build-deps | |
- run: inv ci-install-rust ${{ env.REPO_HOME }} | |
if: matrix.product == 'rec' | |
working-directory: ./pdns/recursordist/ | |
- name: Autoreconf rec | |
if: matrix.product == 'rec' | |
working-directory: ./pdns/recursordist/ | |
run: | | |
inv ci-autoconf | |
- name: Configure rec | |
if: matrix.product == 'rec' | |
working-directory: ./pdns/recursordist/ | |
run: | | |
inv ci-rec-configure full | |
- name: Build rec | |
if: matrix.product == 'rec' | |
working-directory: ./pdns/recursordist/ | |
run: | | |
CONCURRENCY=4 inv ci-rec-make-bear | |
- run: ln -s ../../.clang-tidy.full .clang-tidy | |
if: matrix.product == 'rec' | |
working-directory: ./pdns/recursordist/ | |
- name: Run clang-tidy for rec | |
if: matrix.product == 'rec' | |
working-directory: ./pdns/recursordist/ | |
run: git diff --no-prefix -U0 HEAD^..HEAD | /usr/bin/python3 ../../.github/scripts/git-filter.py --product rec | /usr/bin/python3 ../../.github/scripts/clang-tidy-diff.py -clang-tidy-binary /usr/bin/clang-tidy-${CLANG_VERSION} -extra-arg=-ferror-limit=0 -p0 -export-fixes clang-tidy-rec.yml | |
- name: Print clang-tidy fixes YAML for rec | |
if: matrix.product == 'rec' | |
working-directory: ./pdns/recursordist/ | |
shell: bash | |
run: | | |
if [ -f clang-tidy-rec.yml ]; then | |
cat clang-tidy-rec.yml | |
fi | |
- name: Result annotations for rec | |
if: matrix.product == 'rec' | |
id: clang-tidy-annotations-rec | |
working-directory: ./pdns/recursordist/ | |
shell: bash | |
run: | | |
if [ -f clang-tidy-rec.yml ]; then | |
set +e | |
/usr/bin/python3 ../../.github/scripts/clang-tidy.py --fixes-file clang-tidy-rec.yml | |
echo "failed=$?" >> $GITHUB_OUTPUT | |
fi | |
- name: Perform CodeQL Analysis | |
uses: github/codeql-action/analyze@v3 | |
check-clang-tidy: | |
needs: analyze | |
runs-on: ubuntu-22.04 | |
name: Check whether clang-tidy succeeded | |
steps: | |
- run: | | |
if [ "x${{ needs.analyze.outputs.clang-tidy-annotations-auth }}" != "x" -a "${{ needs.analyze.outputs.clang-tidy-annotations-auth }}" != "0" ]; then | |
echo "::error::Auth clang-tidy failed" | |
exit 1 | |
fi | |
if [ "x${{ needs.analyze.outputs.clang-tidy-annotations-dnsdist }}" != "x" -a "${{ needs.analyze.outputs.clang-tidy-annotations-dnsdist }}" != "0" ]; then | |
echo "::error::DNSdist clang-tidy failed" | |
exit 1 | |
fi | |
if [ "x${{needs.analyze.outputs.clang-tidy-annotations-rec }}" != "x" -a "${{needs.analyze.outputs.clang-tidy-annotations-rec }}" != "0" ]; then | |
echo "::error::Rec clang-tidy failed" | |
exit 1 | |
fi | |
check-for-binaries: | |
runs-on: ubuntu-22.04 | |
name: Force failure in case there are binaries present in a pull request | |
if: ${{ github.event_name == 'pull_request' }} | |
steps: | |
- name: Checkout repository | |
uses: actions/checkout@v4 | |
with: | |
fetch-depth: 2 | |
- run: if [[ "$(file -i --dereference $(git diff --name-only HEAD^..HEAD -- . :^fuzzing/corpus) | grep binary | grep -v 'image/' | grep -v 'inode/x-empty' | grep -v 'inode/directory' | tee /dev/stderr)" != "" ]]; then exit 1; fi |