--- # This action is centrally managed in https://github.com//.github/ # Don't make changes to this file in this repo as they will be overwritten with changes made to the same file in # the above-mentioned repo. name: Qodana on: pull_request: branches: [master, nightly] types: [opened, synchronize, reopened] push: branches: [master, nightly] workflow_dispatch: concurrency: group: ${{ github.workflow }}-${{ github.ref }} cancel-in-progress: true jobs: qodana_initial_check: name: Qodana Initial Check permissions: actions: write # required to use workflow dispatch on fork PRs runs-on: ubuntu-latest steps: - name: Checkout uses: actions/checkout@v3 - name: Prepare id: prepare run: | # check the branch variable if [ "${{ github.event_name }}" == "push" ] then echo "This is a PUSH event" # use the branch name destination=${{ github.ref_name }} target=${{ github.ref_name }} else echo "This is a PR event" # use the PR number destination=${{ github.event.pull_request.number }} target=${{ github.event.pull_request.base.ref }} fi echo "checkout_repo=$checkout_repo" >> $GITHUB_OUTPUT echo "checkout_ref=$checkout_ref" >> $GITHUB_OUTPUT echo "destination=$destination" >> $GITHUB_OUTPUT echo "target=$target" >> $GITHUB_OUTPUT # prepare urls base=https://${{ github.repository_owner }}.github.io report_url=${base}/qodana-reports/${{ github.event.repository.name }}/${destination} echo "report_url=$report_url" >> $GITHUB_OUTPUT # build matrix files=$(find . -type f -iname "qodana*.yaml") echo "files: ${files}" # do not quote to keep this as a single line echo files=${files} >> $GITHUB_OUTPUT MATRIX_COMBINATIONS="" REPORTS_MARKDOWN="" for FILE in ${files}; do # extract the language from file name after `qodana-` and before `.yaml` language=$(echo $FILE | sed -r -z -e 's/(\.\/)*.*\/(qodana.yaml)/default/gm') if [[ $language != "default" ]]; then language=$(echo $FILE | sed -r -z -e 's/(\.\/)*.*qodana-(.*).yaml/\2/gm') fi MATRIX_COMBINATIONS="$MATRIX_COMBINATIONS {\"file\": \"$FILE\", \"language\": \"$language\"}," REPORTS_MARKDOWN="$REPORTS_MARKDOWN
- [${language}](${report_url}/${language})" done # removes the last character (i.e. comma) MATRIX_COMBINATIONS=${MATRIX_COMBINATIONS::-1} # setup matrix for later jobs matrix=$(( echo "{ \"include\": [$MATRIX_COMBINATIONS] }" ) | jq -c .) echo $matrix echo $matrix | jq . echo "matrix=$matrix" >> $GITHUB_OUTPUT echo "reports_markdown=$REPORTS_MARKDOWN" >> $GITHUB_OUTPUT - name: Setup initial notification inputs id: inputs if: >- startsWith(github.event_name, 'pull_request') && steps.prepare.outputs.files != '' run: | # workflow logs workflow_url_a=https://github.com/${{ github.repository_owner }}/${{ github.event.repository.name }} workflow_url=${workflow_url_a}/actions/runs/${{ github.run_id }} # multiline message message=$(cat <<- EOF :warning: **Qodana is checking this PR** :warning: Live results available [here](${workflow_url}) EOF ) # escape json control characters message=$(jq -n --arg message "$message" '$message' | sed -e 's/\\/\\\\/g' -e 's/"/\\"/g') secondary_inputs=$(echo '{ "issue_message": "'"${message}"'", "issue_message_id": "'"qodana"'", "issue_number": "'"${{ github.event.number }}"'", "issue_repo_owner": "'"${{ github.repository_owner }}"'", "issue_repo_name": "'"${{ github.event.repository.name }}"'" }' | jq -r .) #escape json control characters secondary_inputs=$(jq -n --arg secondary_inputs "$secondary_inputs" '$secondary_inputs' \ | sed -e 's/\\/\\\\/g' -e 's/"/\\"/g') echo $secondary_inputs # secondary input as string, not JSON # todo - change dispatch_ref to master instead of nightly primary_inputs=$(echo '{ "dispatch_repository": "'"${{ github.repository_owner }}/.github"'", "dispatch_workflow": "'"dispatch-issue-comment.yml"'", "dispatch_ref": "'"nightly"'", "dispatch_inputs": "'"${secondary_inputs}"'" }' | jq -c .) echo $primary_inputs echo $primary_inputs | jq . echo "primary_inputs=$primary_inputs" >> $GITHUB_OUTPUT - name: Workflow Dispatch if: >- startsWith(github.event_name, 'pull_request') && steps.prepare.outputs.files != '' uses: benc-uk/workflow-dispatch@v1.2.2 continue-on-error: true # this might error if the workflow is not found, but we still want to run the next job with: ref: ${{ github.base_ref || github.ref_name }} # base ref for PR and branch name for push workflow: dispatcher.yml inputs: ${{ steps.inputs.outputs.primary_inputs }} token: ${{ github.token }} outputs: destination: ${{ steps.prepare.outputs.destination }} target: ${{ steps.prepare.outputs.target }} files: ${{ steps.prepare.outputs.files }} reports_markdown: ${{ steps.prepare.outputs.reports_markdown }} matrix: ${{ steps.prepare.outputs.matrix }} qodana: if: ${{ needs.qodana_initial_check.outputs.files != '' }} needs: [qodana_initial_check] runs-on: ubuntu-latest strategy: fail-fast: false matrix: ${{ fromJson(needs.qodana_initial_check.outputs.matrix) }} name: Qodana-Scan-${{ matrix.language }} continue-on-error: true steps: - name: Checkout uses: actions/checkout@v3 with: submodules: recursive - name: Get baseline id: baseline run: | # check if destination is not an integer if ! [[ "${{ needs.qodana_initial_check.outputs.destination }}" =~ ^[0-9]+$ ]] then echo "Running for a branch update" echo "baseline_args=" >> $GITHUB_OUTPUT else echo "Running for a PR" sarif_file=qodana.sarif.json repo=${{ github.event.repository.name }} target=${{ needs.qodana_initial_check.outputs.target }} language=${{ matrix.language }} baseline_file="${repo}/${target}/${language}/results/${sarif_file}" baseline_file_url="https://lizardbyte.github.io/qodana-reports/${baseline_file}" # don't fail if file does not exist wget ${baseline_file_url} || true # check if file exists if [ -f ${sarif_file} ] then echo "baseline exists" echo "baseline_args=--baseline,${sarif_file}" >> $GITHUB_OUTPUT else echo "baseline does not exist" echo "baseline_args=" >> $GITHUB_OUTPUT fi fi - name: Rename Qodana config file id: rename run: | # rename the file if [ "${{ matrix.file }}" != "./qodana.yaml" ] then mv -f ${{ matrix.file }} ./qodana.yaml fi - name: Qodana id: qodana continue-on-error: true # ensure dispatch-qodana job is run uses: JetBrains/qodana-action@v2022.3.4 with: additional-cache-hash: ${{ github.ref }}-${{ matrix.language }} artifact-name: qodana-${{ matrix.language }} # yamllint disable-line rule:line-length args: '--print-problems,${{ steps.baseline.outputs.baseline_args }}' pr-mode: false upload-result: true use-caches: true - name: Set output status id: status run: | # check if qodana failed echo "qodana_status=${{ steps.qodana.outcome }}" >> $GITHUB_OUTPUT outputs: qodana_status: ${{ steps.status.outputs.qodana_status }} dispatch-qodana: # trigger qodana-reports to download artifacts from the matrix runs needs: [qodana_initial_check, qodana] runs-on: ubuntu-latest name: Dispatch Qodana permissions: actions: write # required to use workflow dispatch on fork PRs if: ${{ needs.qodana_initial_check.outputs.files != '' }} steps: - name: Setup qodana publish inputs id: inputs run: | # get the artifacts artifacts=${{ toJson(steps.artifacts.outputs.result) }} artifacts=$(echo $artifacts | jq -c .) # get the target branch target=${{ needs.qodana_initial_check.outputs.target }} # get the destination branch destination=${{ needs.qodana_initial_check.outputs.destination }} # client payload secondary_inputs=$(echo '{ "destination": "'"${destination}"'", "ref": "'"${{ github.ref }}"'", "repo": "'"${{ github.repository }}"'", "repo_name": "'"${{ github.event.repository.name }}"'", "run_id": "'"${{ github.run_id }}"'", "reports_markdown": "'"${{ needs.qodana_initial_check.outputs.reports_markdown }}"'", "status": "'"${{ needs.qodana.outputs.qodana_status }}"'" }' | jq -r .) #escape json control characters secondary_inputs=$(jq -n --arg secondary_inputs "$secondary_inputs" '$secondary_inputs' \ | sed -e 's/\\/\\\\/g' -e 's/"/\\"/g') echo $secondary_inputs primary_inputs=$(echo '{ "dispatch_repository": "'"${{ github.repository_owner }}/qodana-reports"'", "dispatch_workflow": "'"dispatch-qodana.yml"'", "dispatch_ref": "'"master"'", "dispatch_inputs": "'"$secondary_inputs"'" }' | jq -c .) echo $primary_inputs echo $primary_inputs | jq . echo "primary_inputs=$primary_inputs" >> $GITHUB_OUTPUT - name: Workflow Dispatch uses: benc-uk/workflow-dispatch@v1.2.2 continue-on-error: true # this might error if the workflow is not found, but we don't want to fail the workflow with: ref: ${{ github.base_ref || github.ref_name }} # base ref for PR and branch name for push workflow: dispatcher.yml inputs: ${{ steps.inputs.outputs.primary_inputs }} token: ${{ github.token }}