allow "suffix" be optional in product queries for Python algorithms (… #1705
This file contains hidden or 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
| # yaml-language-server: $schema=https://json.schemastore.org/github-workflow.json | |
| name: "CodeQL Analysis" | |
| "on": | |
| push: | |
| branches: [main, develop] | |
| pull_request: | |
| schedule: | |
| - cron: "0 3 * * 0" # weekly (UTC) — adjust as needed | |
| workflow_dispatch: | |
| inputs: | |
| ref: | |
| description: "The branch, ref, or SHA to checkout. Defaults to the repository's default branch." | |
| required: false | |
| type: string | |
| workflow_call: | |
| inputs: | |
| checkout-path: | |
| description: "Path to check out code to" | |
| required: false | |
| type: string | |
| build-path: | |
| description: "Path for build artifacts" | |
| required: false | |
| type: string | |
| language-matrix: | |
| description: "JSON array of languages to analyze" | |
| required: false | |
| type: string | |
| pr-number: | |
| description: "PR number if run in PR context" | |
| required: false | |
| type: string | |
| pr-head-repo: | |
| description: "The full name of the PR head repository" | |
| required: false | |
| type: string | |
| pr-base-repo: | |
| description: "The full name of the PR base repository" | |
| required: false | |
| type: string | |
| pr-base-sha: | |
| description: "Base SHA of the PR for relevance check" | |
| required: false | |
| type: string | |
| pr-head-sha: | |
| description: "Head SHA of the PR for relevance check" | |
| required: false | |
| type: string | |
| ref: | |
| description: "The branch, ref, or SHA to checkout" | |
| required: false | |
| type: string | |
| repo: | |
| description: "The repository to checkout from" | |
| required: false | |
| type: string | |
| permissions: | |
| actions: read | |
| contents: read | |
| security-events: write | |
| env: | |
| BUILD_TYPE: RelWithDebInfo | |
| CPP_COMPILER: g++ | |
| jobs: | |
| setup: | |
| runs-on: ubuntu-latest | |
| outputs: | |
| is_act: ${{ steps.setup.outputs.is_act }} | |
| ref: ${{ steps.setup.outputs.ref }} | |
| repo: ${{ steps.setup.outputs.repo }} | |
| base_sha: ${{ steps.setup.outputs.base_sha }} | |
| pr_number: ${{ steps.setup.outputs.pr_number }} | |
| checkout_path: ${{ steps.setup.outputs.checkout_path }} | |
| build_path: ${{ steps.setup.outputs.build_path }} | |
| skip_detection: ${{ steps.should_skip.outputs.skip }} | |
| has_changes_cpp: ${{ steps.detect_cpp.outputs.has_changes }} | |
| has_changes_python: ${{ steps.detect_python.outputs.has_changes }} | |
| has_changes_actions: ${{ steps.detect_actions.outputs.has_changes }} | |
| steps: | |
| - name: Workflow setup | |
| id: setup | |
| uses: Framework-R-D/phlex/.github/actions/workflow-setup@main | |
| with: | |
| ref: ${{ inputs.ref }} | |
| repo: ${{ inputs.repo }} | |
| pr-base-sha: ${{ inputs.pr-base-sha }} | |
| checkout-path: ${{ inputs.checkout-path }} | |
| build-path: ${{ inputs.build-path }} | |
| - name: Determine if detection should be skipped | |
| id: should_skip | |
| env: | |
| IS_ACT: ${{ steps.setup.outputs.is_act }} | |
| LANGUAGE_MATRIX: ${{ inputs.language-matrix }} | |
| run: | | |
| if [ "${GITHUB_EVENT_NAME}" = "schedule" ] || \ | |
| [ "${GITHUB_EVENT_NAME}" = "workflow_dispatch" ] || \ | |
| [ "${GITHUB_EVENT_NAME}" = "push" ] || \ | |
| { [ "${GITHUB_EVENT_NAME}" = "workflow_call" ] && [ -n "${LANGUAGE_MATRIX}" ]; } || \ | |
| [ "${IS_ACT}" = "true" ]; then | |
| echo "skip=true" >> "$GITHUB_OUTPUT" | |
| else | |
| echo "skip=false" >> "$GITHUB_OUTPUT" | |
| fi | |
| - name: Detect C++ changes | |
| id: detect_cpp | |
| if: steps.should_skip.outputs.skip != 'true' | |
| uses: Framework-R-D/phlex/.github/actions/run-change-detection@main | |
| with: | |
| checkout-path: ${{ steps.setup.outputs.checkout_path }} | |
| ref: ${{ steps.setup.outputs.ref }} | |
| repo: ${{ steps.setup.outputs.repo }} | |
| base-ref: ${{ steps.setup.outputs.base_sha }} | |
| head-ref: ${{ inputs.pr-head-sha || steps.setup.outputs.ref }} | |
| file-type: | | |
| cpp | |
| cmake | |
| - name: Detect Python changes | |
| id: detect_python | |
| if: steps.should_skip.outputs.skip != 'true' | |
| uses: Framework-R-D/phlex/.github/actions/run-change-detection@main | |
| with: | |
| checkout-path: ${{ steps.setup.outputs.checkout_path }} | |
| ref: ${{ steps.setup.outputs.ref }} | |
| repo: ${{ steps.setup.outputs.repo }} | |
| base-ref: ${{ steps.setup.outputs.base_sha }} | |
| head-ref: ${{ inputs.pr-head-sha || steps.setup.outputs.ref }} | |
| file-type: python | |
| - name: Detect Actions changes | |
| id: detect_actions | |
| if: steps.should_skip.outputs.skip != 'true' | |
| uses: Framework-R-D/phlex/.github/actions/run-change-detection@main | |
| with: | |
| checkout-path: ${{ steps.setup.outputs.checkout_path }} | |
| ref: ${{ steps.setup.outputs.ref }} | |
| repo: ${{ steps.setup.outputs.repo }} | |
| base-ref: ${{ steps.setup.outputs.base_sha }} | |
| head-ref: ${{ inputs.pr-head-sha || steps.setup.outputs.ref }} | |
| include-globs: | | |
| .github/workflows/*.yaml | |
| .github/workflows/*.yml | |
| .github/actions/**/action.yaml | |
| .github/actions/**/action.yml | |
| determine-languages: | |
| needs: setup | |
| if: always() && needs.setup.result == 'success' | |
| runs-on: ubuntu-latest | |
| outputs: | |
| languages: ${{ steps.build_matrix.outputs.languages }} | |
| steps: | |
| - name: Build language matrix | |
| id: build_matrix | |
| env: | |
| LANGUAGE_MATRIX: ${{ inputs.language-matrix }} | |
| SKIP_DETECTION: ${{ needs.setup.outputs.skip_detection }} | |
| HAS_CHANGES_CPP: ${{ needs.setup.outputs.has_changes_cpp }} | |
| HAS_CHANGES_PYTHON: ${{ needs.setup.outputs.has_changes_python }} | |
| HAS_CHANGES_ACTIONS: ${{ needs.setup.outputs.has_changes_actions }} | |
| run: | | |
| # If detection was skipped, use all languages or the provided language-matrix | |
| if [ "${SKIP_DETECTION}" = "true" ]; then | |
| if [ "${GITHUB_EVENT_NAME}" = "workflow_call" ] && [ -n "${LANGUAGE_MATRIX}" ]; then | |
| # Validate that language-matrix is valid JSON | |
| if ! echo "${LANGUAGE_MATRIX}" | python3 -c "import sys, json; json.load(sys.stdin)" 2>/dev/null; then | |
| echo "::error::Invalid language-matrix input: must be valid JSON array" | |
| exit 1 | |
| fi | |
| echo "languages=${LANGUAGE_MATRIX}" >> "$GITHUB_OUTPUT" | |
| else | |
| echo 'languages=["cpp", "python", "actions"]' >> "$GITHUB_OUTPUT" | |
| fi | |
| exit 0 | |
| fi | |
| # Build array based on detection results | |
| langs=() | |
| if [ "${HAS_CHANGES_CPP}" = "true" ]; then | |
| langs+=("cpp") | |
| fi | |
| if [ "${HAS_CHANGES_PYTHON}" = "true" ]; then | |
| langs+=("python") | |
| fi | |
| if [ "${HAS_CHANGES_ACTIONS}" = "true" ]; then | |
| langs+=("actions") | |
| fi | |
| # Convert bash array to JSON array | |
| if [ "${#langs[@]}" -eq 0 ]; then | |
| echo 'languages=[]' >> "$GITHUB_OUTPUT" | |
| else | |
| json_array="[" | |
| for i in "${!langs[@]}"; do | |
| if [ "$i" -gt 0 ]; then | |
| json_array+="," | |
| fi | |
| json_array+="\"${langs[$i]}\"" | |
| done | |
| json_array+="]" | |
| echo "languages=$json_array" >> "$GITHUB_OUTPUT" | |
| fi | |
| codeql: | |
| needs: [setup, determine-languages] | |
| if: > | |
| needs.determine-languages.result == 'success' && needs.determine-languages.outputs.languages != '[]' | |
| name: Analyze ${{ matrix.language }} with CodeQL | |
| runs-on: ubuntu-24.04 | |
| container: | |
| image: ghcr.io/framework-r-d/phlex-ci:latest | |
| env: | |
| local_checkout_path: ${{ needs.setup.outputs.checkout_path }} | |
| local_build_path: ${{ needs.setup.outputs.build_path }} | |
| CODEQL_EXTRACTOR_CPP_COMPILATION_DATABASE: | |
| ${{ github.workspace }}/${{ needs.setup.outputs.build_path }}/compile_commands.json | |
| strategy: | |
| fail-fast: false | |
| matrix: | |
| language: ${{ fromJson(needs.determine-languages.outputs.languages) }} | |
| timeout-minutes: 120 | |
| steps: | |
| - name: Checkout repository | |
| uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 | |
| with: | |
| ref: ${{ needs.setup.outputs.ref }} | |
| path: ${{ env.local_checkout_path }} | |
| fetch-depth: 0 | |
| - name: Setup build environment | |
| uses: Framework-R-D/phlex/.github/actions/setup-build-env@main | |
| with: | |
| build-path: ${{ env.local_build_path }} | |
| - name: Initialize CodeQL | |
| uses: github/codeql-action/init@b1bff81932f5cdfc8695c7752dcee935dcd061c8 # v4.33.0 | |
| with: | |
| languages: ${{ matrix.language }} | |
| config-file: ${{ env.local_checkout_path }}/.github/codeql/codeql-config.yml | |
| source-root: ${{ env.local_checkout_path }} | |
| build-mode: none | |
| - name: Produce compile_commands.json (C++ only) | |
| if: matrix.language == 'cpp' | |
| uses: Framework-R-D/phlex/.github/actions/configure-cmake@main | |
| with: | |
| build-type: ${{ env.BUILD_TYPE }} | |
| source-path: ${{ env.local_checkout_path }} | |
| build-path: ${{ env.local_build_path }} | |
| - name: Verify compile_commands.json (C++ only) | |
| if: matrix.language == 'cpp' | |
| run: | | |
| set -eu | |
| if [ ! -f "$CODEQL_EXTRACTOR_CPP_COMPILATION_DATABASE" ]; then | |
| echo "Expected compile_commands.json at $CODEQL_EXTRACTOR_CPP_COMPILATION_DATABASE" >&2 | |
| exit 1 | |
| fi | |
| # Run CodeQL analysis (uploads results to code scanning) | |
| - name: Perform CodeQL Analysis | |
| uses: github/codeql-action/analyze@b1bff81932f5cdfc8695c7752dcee935dcd061c8 # v4.33.0 | |
| with: | |
| checkout_path: ${{ env.local_checkout_path }} | |
| output: results | |
| category: ${{ matrix.language }} | |
| - name: Upload SARIF results | |
| uses: actions/upload-artifact@bbbca2ddaa5d8feaa63e36b76fdaad77386f024f # v7.0.0 | |
| with: | |
| name: codeql-sarif-${{ matrix.language }} | |
| path: results | |
| retention-days: 7 | |
| codeql-report: | |
| name: Aggregate CodeQL alerts | |
| needs: codeql | |
| runs-on: ubuntu-24.04 | |
| if: needs.codeql.result == 'success' | |
| permissions: | |
| contents: read | |
| issues: write | |
| pull-requests: write | |
| security-events: read | |
| env: | |
| CODEQL_MIN_LEVEL: warning | |
| GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} | |
| steps: | |
| - name: Set log file path | |
| id: set_log_path | |
| run: echo "path=$RUNNER_TEMP/codeql-alerts.log" >> "$GITHUB_OUTPUT" | |
| - name: Checkout repository | |
| uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 | |
| with: | |
| fetch-depth: 0 | |
| - name: Checkout Phlex for scripts | |
| if: github.event_name == 'workflow_call' | |
| uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 | |
| with: | |
| repository: Framework-R-D/phlex | |
| path: phlex | |
| fetch-depth: 0 | |
| - name: Download CodeQL SARIF artifacts | |
| uses: actions/download-artifact@3e5f45b2cfb9172054b4087a40e8e0b5a5461e7c # v8.0.1 | |
| with: | |
| pattern: codeql-sarif-* | |
| path: sarif | |
| merge-multiple: true | |
| - name: Check CodeQL SARIF for new or resolved alerts | |
| id: check_codeql | |
| env: | |
| LOG_PATH: ${{ steps.set_log_path.outputs.path }} | |
| INPUT_PR_NUMBER: ${{ inputs.pr-number }} | |
| run: | | |
| set -eu | |
| ARGS=( | |
| --sarif "$GITHUB_WORKSPACE/sarif" | |
| --min-level "${CODEQL_MIN_LEVEL}" | |
| --log-path "${LOG_PATH}" | |
| ) | |
| PR_NUMBER="" | |
| if [ "${GITHUB_EVENT_NAME}" = "pull_request" ]; then | |
| PR_NUMBER="$(jq -r '.pull_request.number // empty' "${GITHUB_EVENT_PATH}")" | |
| elif [ "${GITHUB_EVENT_NAME}" = "workflow_call" ]; then | |
| PR_NUMBER="${INPUT_PR_NUMBER}" | |
| fi | |
| if [ -n "$PR_NUMBER" ]; then | |
| ARGS+=(--ref "refs/pull/${PR_NUMBER}/merge") | |
| fi | |
| script_path="scripts/check_codeql_alerts.py" | |
| if [ "${GITHUB_EVENT_NAME}" = "workflow_call" ]; then | |
| script_path="phlex/$script_path" | |
| fi | |
| python3 "$script_path" "${ARGS[@]}" | |
| - name: Upload CodeQL alerts debug log | |
| if: always() | |
| uses: actions/upload-artifact@bbbca2ddaa5d8feaa63e36b76fdaad77386f024f # v7.0.0 | |
| with: | |
| name: codeql-alerts-debug-log | |
| path: ${{ steps.set_log_path.outputs.path }} | |
| retention-days: 3 | |
| - name: Prepare PR comment data | |
| if: >- | |
| github.event_name == 'pull_request' && steps.check_codeql.outputs.comment_path != '' | |
| env: | |
| COMMENT_PATH: ${{ steps.check_codeql.outputs.comment_path }} | |
| run: | | |
| mkdir -p pr_comment_data | |
| jq -r '.pull_request.number // empty' "${GITHUB_EVENT_PATH}" > pr_comment_data/pr_number.txt | |
| cp "${COMMENT_PATH}" pr_comment_data/comment_body.md | |
| - name: Upload PR comment data | |
| if: >- | |
| github.event_name == 'pull_request' && steps.check_codeql.outputs.comment_path != '' | |
| uses: actions/upload-artifact@bbbca2ddaa5d8feaa63e36b76fdaad77386f024f # v7.0.0 | |
| with: | |
| name: codeql-pr-data | |
| path: pr_comment_data/ | |
| retention-days: 1 | |
| - name: Fail workflow due to new CodeQL alerts | |
| # Fails the check on the PR so the user sees red X | |
| if: >- | |
| github.event_name == 'pull_request' && steps.check_codeql.outputs.new_alerts == 'true' | |
| run: | | |
| echo "New CodeQL alerts detected; failing job." | |
| exit 1 |