diff --git a/.github/workflows/public-codeql.yml b/.github/workflows/public-codeql.yml index ad34b11..0fa40fb 100644 --- a/.github/workflows/public-codeql.yml +++ b/.github/workflows/public-codeql.yml @@ -27,6 +27,14 @@ on: description: 'Run github/codeql-action/autobuild before analyze.' type: boolean default: false + build_command: + description: 'Custom build command (bash) instead of autobuild. Empty = use autobuild setting. E.g. "cargo build --workspace --locked".' + type: string + default: '' + post_analyze_command: + description: 'Optional command (bash) to run AFTER analyze, e.g. extraction-diagnostics collection. Runs with always() so it captures failures too.' + type: string + default: '' output_directory: description: 'Optional CodeQL analyze output directory for SARIF artifacts.' type: string @@ -91,9 +99,15 @@ jobs: config-file: ${{ inputs.config_file }} - name: Autobuild - if: ${{ inputs.autobuild }} + if: ${{ inputs.autobuild && inputs.build_command == '' }} uses: github/codeql-action/autobuild@e4fba868fa4b1b91e1fdab776edc8cfbe6e9fb81 # v4.37.3 + - name: Custom build + if: ${{ inputs.build_command != '' }} + env: + BUILD_COMMAND: ${{ inputs.build_command }} + run: bash -c "$BUILD_COMMAND" + - name: Analyze if: ${{ inputs.output_directory == '' }} uses: github/codeql-action/analyze@e4fba868fa4b1b91e1fdab776edc8cfbe6e9fb81 # v4.37.3 @@ -115,3 +129,9 @@ jobs: path: ${{ inputs.output_directory }} if-no-files-found: error retention-days: ${{ inputs.retention_days }} + + - name: Post-analyze command + if: ${{ always() && inputs.post_analyze_command != '' }} + env: + POST_ANALYZE_COMMAND: ${{ inputs.post_analyze_command }} + run: bash -c "$POST_ANALYZE_COMMAND" diff --git a/.github/workflows/public-scorecard.yml b/.github/workflows/public-scorecard.yml index e066fd8..aba469b 100644 --- a/.github/workflows/public-scorecard.yml +++ b/.github/workflows/public-scorecard.yml @@ -14,6 +14,18 @@ on: description: 'Publish results to the OpenSSF Scorecard API (public repos).' type: boolean default: true + filter_rule_ids: + description: 'Comma-separated Scorecard rule IDs to DROP from results (e.g. "MaintainedID,CodeReviewID,CIIBestPracticesID"). Empty = keep all.' + type: string + default: '' + normalize_placeholder_uris: + description: 'Replace "no file associated with this alert" artifact URIs with a URI-safe placeholder (avoids upload errors).' + type: boolean + default: false + upload_sarif_on_forks: + description: 'Upload SARIF to code scanning even on fork PRs. Default false (skip forks).' + type: boolean + default: false permissions: {} @@ -45,6 +57,41 @@ jobs: results_format: sarif publish_results: ${{ inputs.publish_results }} + - name: Normalize placeholder URIs + if: ${{ inputs.normalize_placeholder_uris }} + shell: bash + run: | + set -euo pipefail + # Replace the non-URI-safe placeholder that Scorecard emits for + # alerts not tied to a specific file, which causes upload errors. + jq '(.runs[].results[].artifactLocation.uri // empty) |= + (if . == "no file associated with this alert" + then "no-file-associated-with-this-alert" else . end)' \ + results.sarif > results.filtered.sarif + mv results.filtered.sarif results.sarif + + - name: Filter rule IDs + if: ${{ inputs.filter_rule_ids != '' }} + shell: bash + env: + FILTER_RULE_IDS: ${{ inputs.filter_rule_ids }} + run: | + set -euo pipefail + # Build a jq "select" condition to drop results/rules by ruleId. + IFS=',' read -ra IDS <<< "$FILTER_RULE_IDS" + cond="" + for id in "${IDS[@]}"; do + id=$(echo "$id" | xargs) # trim whitespace + cond+="select(.ruleId != \"$id\") and " + done + cond="${cond% and }" + # Filter results and drop orphaned rule definitions + jq --argjson cond "$cond" ' + .runs[].results |= map(. | select($cond)) | + .runs[].tool.driver.rules |= map(. | select(.id as $id | $cond)) + ' results.sarif > results.filtered.sarif + mv results.filtered.sarif results.sarif + - name: Upload artifact uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1 with: @@ -53,6 +100,7 @@ jobs: retention-days: 5 - name: Upload SARIF to code scanning + if: ${{ github.event_name != 'pull_request' || inputs.upload_sarif_on_forks || github.event.pull_request.head.repo.full_name == github.repository }} uses: github/codeql-action/upload-sarif@e4fba868fa4b1b91e1fdab776edc8cfbe6e9fb81 # v4.37.3 with: sarif_file: results.sarif diff --git a/CHANGELOG.md b/CHANGELOG.md index dde1a9b..a50b6b0 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -4,6 +4,16 @@ ### Changed +- **`public-codeql.yml` gained `build_command` and `post_analyze_command` inputs.** + `build_command` runs a custom build (e.g. `cargo build --workspace --locked`) + instead of autobuild. `post_analyze_command` runs a hook after analysis with + `if: always()`, enabling repo-local extraction-diagnostics collection. +- **`public-scorecard.yml` gained `filter_rule_ids`, + `normalize_placeholder_uris`, and `upload_sarif_on_forks` inputs.** + `filter_rule_ids` drops non-actionable checks (MaintainedID, CodeReviewID, + CIIBestPracticesID). `normalize_placeholder_uris` fixes non-URI-safe + artifact locations. `upload_sarif_on_forks` gates fork-PR uploads. + - **`rust-ci.yml` gained 5 new inputs for full Rust CI coverage.** `test_matrix_os` (JSON array for OS matrix testing), `fmt_command` (dedicated rustfmt job), `clippy_command` (dedicated clippy lint job), `msrv_toolchain` diff --git a/catalog/runtime-coverage.yml b/catalog/runtime-coverage.yml index 937928b..6e5da10 100644 --- a/catalog/runtime-coverage.yml +++ b/catalog/runtime-coverage.yml @@ -19,13 +19,13 @@ entries: proven_digest: f946862cfe522cb62920aa104716b331b9f35210a9181ce5954879ccb48ce1df waiver: null - workflow: .github/workflows/benchmark-compare.yml - status: static-only + status: unverified validator: scripts/check_benchmark_contract.py evidence: 'Executable contract validator exercises the embedded program(s); no live workflow_call run.' last_run: null waiver: null - workflow: .github/workflows/benchmark.yml - status: static-only + status: unverified validator: scripts/check_benchmark_contract.py evidence: 'Executable contract validator exercises the embedded program(s); no live workflow_call run.' last_run: null @@ -106,7 +106,7 @@ entries: last_run: null waiver: null - workflow: .github/workflows/monorepo-changed-paths.yml - status: static-only + status: unverified validator: scripts/check_monorepo_routing.py evidence: 'Executable contract validator exercises the embedded program(s); no live workflow_call run.' last_run: null @@ -137,10 +137,10 @@ entries: last_run: null waiver: null - workflow: .github/workflows/public-codeql.yml - status: runtime-proven - evidence: "Called by this repository's own codeql.yml through a relative ref; language matrix executed live on main." - last_run: https://github.com/NDDev-it-com/ci-workflows/actions/runs/30702998427 - proven_digest: d7de98164001dad988a6c4ccc059a012f92c5e90c82de1198604f8f85c23d125 + status: unverified + evidence: 'Workflow inputs changed; awaiting re-validation via a live workflow_call run.' + last_run: null + proven_digest: b43ec65a54f8430885c589c4c296920c946c3880b2088a8cd60e4ddf536cb8f8 waiver: null - workflow: .github/workflows/public-dependency-review.yml status: runtime-proven @@ -175,13 +175,13 @@ entries: last_run: null waiver: null - workflow: .github/workflows/release-supply-chain-free.yml - status: static-only + status: unverified validator: scripts/check_release_supply_chain.py evidence: 'Executable contract validator exercises the embedded program(s); no live workflow_call run.' last_run: null waiver: null - workflow: .github/workflows/release-supply-chain.yml - status: static-only + status: unverified validator: scripts/check_release_supply_chain.py evidence: 'Executable contract validator exercises the embedded program(s). The runtime proof lapsed when actions/attest and actions/checkout were bumped: this