From 81671fe0e21e25f31b8100297f829744e66df4bd Mon Sep 17 00:00:00 2001 From: Tom Stellard Date: Fri, 7 Jun 2024 19:02:55 -0700 Subject: [workflows] Add post-commit job that periodically runs the clang static analyzer (#94106) This job will run once per day on the main branch, and for every commit on a release branch. It currently only builds llvm, but could add more sub-projects in the future. OpenSSF Best Practices recommends running a static analyzer on software before it is released: https://www.bestpractices.dev/en/criteria/0#0.static_analysis --- .github/workflows/ci-post-commit-analyzer-run.py | 34 +++++++++ .github/workflows/ci-post-commit-analyzer.yml | 95 ++++++++++++++++++++++++ 2 files changed, 129 insertions(+) create mode 100644 .github/workflows/ci-post-commit-analyzer-run.py create mode 100644 .github/workflows/ci-post-commit-analyzer.yml (limited to '.github') diff --git a/.github/workflows/ci-post-commit-analyzer-run.py b/.github/workflows/ci-post-commit-analyzer-run.py new file mode 100644 index 0000000..e5f52d3 --- /dev/null +++ b/.github/workflows/ci-post-commit-analyzer-run.py @@ -0,0 +1,34 @@ +import json +import multiprocessing +import os +import re +import subprocess +import sys + + +def run_analyzer(data): + os.chdir(data["directory"]) + command = ( + data["command"] + + f" --analyze --analyzer-output html -o analyzer-results -Xclang -analyzer-config -Xclang max-nodes=75000" + ) + print(command) + subprocess.run(command, shell=True, check=True) + + +def pool_error(e): + print("Error analyzing file:", e) + + +def main(): + db_path = sys.argv[1] + database = json.load(open(db_path)) + + with multiprocessing.Pool() as pool: + pool.map_async(run_analyzer, [k for k in database], error_callback=pool_error) + pool.close() + pool.join() + + +if __name__ == "__main__": + main() diff --git a/.github/workflows/ci-post-commit-analyzer.yml b/.github/workflows/ci-post-commit-analyzer.yml new file mode 100644 index 0000000..d614dd0 --- /dev/null +++ b/.github/workflows/ci-post-commit-analyzer.yml @@ -0,0 +1,95 @@ +name: Post-Commit Static Analyzer + +permissions: + contents: read + +on: + push: + branches: + - 'release/**' + paths: + - 'clang/**' + - 'llvm/**' + - '.github/workflows/ci-post-commit-analyzer.yml' + pull_request: + types: + - opened + - synchronize + - reopened + - closed + paths: + - '.github/workflows/ci-post-commit-analyzer.yml' + - '.github/workflows/ci-post-commit-analyzer-run.py' + schedule: + - cron: '30 0 * * *' + +concurrency: + group: >- + llvm-project-${{ github.workflow }}-${{ github.event_name == 'pull_request' && + ( github.event.pull_request.number || github.ref) }} + cancel-in-progress: ${{ startsWith(github.ref, 'refs/pull/') }} + +jobs: + post-commit-analyzer: + if: >- + github.repository_owner == 'llvm' && + github.event.action != 'closed' + runs-on: ubuntu-22.04 + container: + image: 'ghcr.io/llvm/ci-ubuntu-22.04:latest' + env: + LLVM_VERSION: 18 + steps: + - name: Checkout Source + uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.1.1 + + - name: Setup ccache + uses: hendrikmuhs/ccache-action@v1 + with: + # A full build of llvm, clang, lld, and lldb takes about 250MB + # of ccache space. There's not much reason to have more than this, + # because we usually won't need to save cache entries from older + # builds. Also, there is an overall 10GB cache limit, and each + # run creates a new cache entry so we want to ensure that we have + # enough cache space for all the tests to run at once and still + # fit under the 10 GB limit. + # Default to 2G to workaround: https://github.com/hendrikmuhs/ccache-action/issues/174 + max-size: 2G + key: post-commit-analyzer + variant: sccache + + - name: Configure + run: | + cmake -B build -S llvm -G Ninja \ + -DLLVM_ENABLE_ASSERTIONS=ON \ + -DLLVM_ENABLE_PROJECTS=clang \ + -DLLVM_BUILD_LLVM_DYLIB=ON \ + -DLLVM_LINK_LLVM_DYLIB=ON \ + -DCMAKE_CXX_COMPILER=clang++ \ + -DCMAKE_C_COMPILER=clang \ + -DCMAKE_CXX_COMPILER_LAUNCHER=sccache \ + -DCMAKE_C_COMPILER_LAUNCHER=sccache \ + -DCMAKE_EXPORT_COMPILE_COMMANDS=ON \ + -DLLVM_INCLUDE_TESTS=OFF \ + -DCLANG_INCLUDE_TESTS=OFF \ + -DCMAKE_BUILD_TYPE=Release + + - name: Build + run: | + # FIXME: We need to build all the generated header files in order to be able to run + # the analyzer on every file. Building libLLVM and libclang is probably overkill for + # this, but it's better than building every target. + ninja -v -C build libLLVM.so libclang.so + + # Run the analyzer. + python3 .github/workflows/ci-post-commit-analyzer-run.py build/compile_commands.json + + scan-build --generate-index-only build/analyzer-results + + - name: Upload Results + uses: actions/upload-artifact@26f96dfa697d77e81fd5907df203aa23a56210a8 #v4.3.0 + if: always() + with: + name: analyzer-results + path: 'build/analyzer-results/*' + -- cgit v1.1