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 # 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 | python3 .github/scripts/git-filter.py --product auth | 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 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 - 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 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 | python3 ../../.github/scripts/git-filter.py --product dnsdist | 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 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 - 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 | python3 ../../.github/scripts/git-filter.py --product rec | 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 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) | grep binary | grep -v 'image/' | grep -v 'inode/x-empty')" != "" ]]; then exit 1; fi