Upload and run SonarCloud Analysis #4973
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
# This workflow runs as soon as the workflow from `sonarcloud.yml` has | |
# successfully finished. It downloads the created artifact and runs the | |
# SonarCloud analysis and uploader. This workflow uses the `workflow_run` trigger. This | |
# means that it will always be run from the master branch, meaning that | |
# the contents of this file will always be taken from the master branch, | |
# even if a PR changes it. Since this approach disallows several attacks | |
# from malicious PR authors, such workflows have access to the secrets | |
# stored on GitHub. For details on the `workflow_run` trigger and this | |
# security measures, see | |
# https://securitylab.github.com/research/github-actions-preventing-pwn-requests/ | |
# Credit goes to the `1c-syntax` project where I found a code snippet to make | |
# SonarCloud work with the `workflow_run` trigger: | |
# https://github.com/1c-syntax/bsl-language-server/blob/21a6bb5172cbc4591a05414d5d0ac221689e45ce/.github/workflows/qa.yml#L16 | |
name: Upload and run SonarCloud Analysis | |
on: | |
workflow_run: | |
# This has to be the `name:` of the workflow in `code_coverage.yml`. | |
# Start when this workflow has finished successfully. | |
workflows: [sonarcloud-analysis] | |
types: | |
- completed | |
concurrency: | |
group: '${{ github.workflow }} @ ${{ github.event.workflow_run.head_repository.full_name || github.ref}} @ ${{ github.event.workflow_run.head_branch || github.event.workflow_run.pull_requests[0].url || github.head_ref || github.ref }}' | |
cancel-in-progress: true | |
jobs: | |
upload: | |
runs-on: ubuntu-22.04 | |
if: github.event.workflow_run.conclusion == 'success' | |
env: | |
compiler: clang | |
compiler-version: 16 | |
warnings: "-Wall -Wextra " | |
build-type: Release | |
BUILD_WRAPPER_OUT_DIR: build_wrapper_output_directory # Directory where build-wrapper output will be placed | |
steps: | |
- name: Print concurrency key | |
run: echo "${{ github.workflow }} @ ${{ github.event.workflow_run.head_repository.full_name || github.ref}} @ ${{ github.event.workflow_run.head_branch || github.event.workflow_run.pull_requests[0].url || github.head_ref || github.ref }}" | |
- name: 'Download artifact' | |
uses: actions/github-script@v7 | |
if: github.event.workflow_run.event == 'pull_request' | |
# The following script is taken from the link stated at the | |
# beginning of this file. It manually downloads an artifact | |
# from another workflow. | |
with: | |
script: | | |
var artifacts = await github.rest.actions.listWorkflowRunArtifacts({ | |
owner: context.repo.owner, | |
repo: context.repo.repo, | |
run_id: ${{github.event.workflow_run.id }}, | |
}); | |
var matchArtifact = artifacts.data.artifacts.filter((artifact) => { | |
return artifact.name == "sonarcloud-report" | |
})[0]; | |
var download = await github.rest.actions.downloadArtifact({ | |
owner: context.repo.owner, | |
repo: context.repo.repo, | |
artifact_id: matchArtifact.id, | |
archive_format: 'zip', | |
}); | |
var fs = require('fs'); | |
fs.writeFileSync('${{github.workspace}}/sonarcloud-report.zip', Buffer.from(download.data)); | |
- run: unzip sonarcloud-report.zip | |
if: github.event.workflow_run.event == 'pull_request' | |
# Read the metadata into environment variables. | |
- name: "Read PR number" | |
run: echo "pr_number=`cat pr`" >> $GITHUB_ENV | |
if: github.event.workflow_run.event == 'pull_request' | |
- name: "Read Github Ref" | |
run: echo "original_github_ref=`cat github_ref`" >> $GITHUB_ENV; | |
if: github.event.workflow_run.event == 'pull_request' | |
- name: "Read Github Repository" | |
run: echo "original_github_repository=`cat github_repository`" >> $GITHUB_ENV; | |
if: github.event.workflow_run.event == 'pull_request' | |
# We have to check out the source code from the PR, otherwise Codecov | |
# won't process the upload properly. We first check it out into a | |
# subdirectory `qlever-source`, otherwise the coverage report will | |
# be overwritten. We then move all the files back into the working | |
# directory such that Codecov will pick them up properly. | |
- name: Request GitHub API for PR data | |
uses: octokit/[email protected] | |
id: get_pr_data | |
if: github.event.workflow_run.event == 'pull_request' | |
with: | |
route: GET /repos/{full_name}/pulls/{number} | |
number: ${{ env.pr_number }} | |
full_name: ${{ github.event.repository.full_name }} | |
env: | |
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} | |
- name: "Checkout" | |
uses: actions/checkout@v4 | |
with: | |
repository: ${{ github.event.workflow_run.head_repository.full_name }} | |
ref: ${{ github.event.workflow_run.head_branch }} | |
fetch-depth: 0 | |
submodules: "recursive" | |
path: qlever-source | |
- name: Checkout base branch | |
working-directory: qlever-source | |
if: github.event.workflow_run.event == 'pull_request' | |
run: | | |
git remote add upstream ${{ github.event.repository.clone_url }} | |
git fetch upstream --no-recurse-submodules | |
git checkout -B ${{ fromJson(steps.get_pr_data.outputs.data).base.ref }} upstream/${{ fromJson(steps.get_pr_data.outputs.data).base.ref }} | |
git checkout ${{ github.event.workflow_run.head_branch }} | |
git clean -ffdx && git reset --hard HEAD | |
- name: "Move qlever sources up" | |
run: shopt -s dotglob && mv qlever-source/* . | |
- name: Install sonar-scanner and build-wrapper | |
uses: SonarSource/sonarcloud-github-c-cpp@v2 | |
- name: Install dependencies | |
uses: ./.github/workflows/install-dependencies-ubuntu | |
- name: Install compiler | |
uses: ./.github/workflows/install-compiler-ubuntu | |
with: | |
compiler: ${{env.compiler}} | |
compiler-version: ${{env.compiler-version}} | |
- name: Configure CMake | |
# Configure CMake in a 'build' subdirectory. `CMAKE_BUILD_TYPE` is only required if you are using a single-configuration generator such as make. | |
# See https://cmake.org/cmake/help/latest/variable/CMAKE_BUILD_TYPE.html?highlight=cmake_build_type | |
run: cmake -B ${{github.workspace}}/build -DCMAKE_BUILD_TYPE=${{env.build-type}} -DCMAKE_TOOLCHAIN_FILE="$(pwd)/toolchains/${{env.compiler}}${{env.compiler-version}}.cmake" -DADDITIONAL_COMPILER_FLAGS="${{env.warnings}} ${{env.asan-flags}} ${{env.ubsan-flags}}" -DUSE_PARALLEL=false -DRUN_EXPENSIVE_TESTS=true -DENABLE_EXPENSIVE_CHECKS=true -DLOGLEVEL=TRACE | |
- name: Build | |
# Build your program with the given configuration | |
run: build-wrapper-linux-x86-64 --out-dir ${{ env.BUILD_WRAPPER_OUT_DIR }} cmake --build ${{github.workspace}}/build --config ${{env.build-type}} -- -j $(nproc) | |
- name: Run sonar-scanner on PR | |
if: github.event.workflow_run.event == 'pull_request' | |
env: | |
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} | |
SONAR_TOKEN: ${{ secrets.SONAR_TOKEN }} | |
run: | | |
sonar-scanner --define sonar.cfamily.build-wrapper-output=build_wrapper_output_directory -Dsonar.scm.revision=${{ github.event.workflow_run.head_sha }} -Dsonar.pullrequest.key=${{ fromJson(steps.get_pr_data.outputs.data).number }} -Dsonar.pullrequest.branch=${{ fromJson(steps.get_pr_data.outputs.data).head.ref }} -Dsonar.pullrequest.base=${{ fromJson(steps.get_pr_data.outputs.data).base.ref }} | |
- name: SonarCloud Scan on push | |
if: github.event.workflow_run.event == 'push' && github.event.workflow_run.head_repository.full_name == github.event.repository.full_name | |
run: | | |
sonar-scanner --define sonar.cfamily.build-wrapper-output=build_wrapper_output_directory -Dsonar.scm.revision=${{ github.event.workflow_run.head_sha }} -Dsonar.branch.name=${{ github.event.workflow_run.head_branch }} | |
env: | |
SONAR_TOKEN: ${{ secrets.SONAR_TOKEN }} | |
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} |