From c789ebdf67c8b2e61d899280a95af5cb1a50fa6a Mon Sep 17 00:00:00 2001 From: Adrien Langou Date: Fri, 11 Sep 2026 12:19:28 +0200 Subject: [PATCH] fix(ci): align Trivy change detection and scan baselines Signed-off-by: Adrien Langou --- .agents/skills/watch-github-actions/SKILL.md | 7 +++++++ .github/workflows/trivy-changes.yml | 18 +++++++++++++++++- CI.md | 13 ++++++++++--- architecture/build.md | 4 ++++ 4 files changed, 38 insertions(+), 4 deletions(-) diff --git a/.agents/skills/watch-github-actions/SKILL.md b/.agents/skills/watch-github-actions/SKILL.md index c9e2843311..5d926cc647 100644 --- a/.agents/skills/watch-github-actions/SKILL.md +++ b/.agents/skills/watch-github-actions/SKILL.md @@ -125,6 +125,13 @@ gh run list --json databaseId,status,headBranch,url --jq '.[] | {id: .databaseId ## View Job Logs +For `Trivy Changes`, inspect the `Resolve PR baseline` step for the base and head +SHAs. PR runs compare the tested merge commit with its +first parent; change detection and scans must use the same pair. On reruns, do +not substitute the current `main` tip or the event's older PR base SHA. Merge +groups and manual runs use their explicit baseline. Findings are reported by +`Reject new high or critical findings`; distinguish those from scanner failures. + View logs for a specific run: ```bash diff --git a/.github/workflows/trivy-changes.yml b/.github/workflows/trivy-changes.yml index 612ce891cc..15e9b7af33 100644 --- a/.github/workflows/trivy-changes.yml +++ b/.github/workflows/trivy-changes.yml @@ -34,6 +34,7 @@ jobs: pull-requests: read outputs: should_run: ${{ steps.default.outputs.should_run || steps.changed.outputs.any_modified }} + base_sha: ${{ steps.comparison.outputs.base_sha }} steps: - id: default if: github.event_name != 'pull_request' @@ -42,12 +43,27 @@ jobs: - uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1 if: github.event_name == 'pull_request' with: + ref: ${{ github.sha }} + # Include both parents of the exact PR merge commit, even on reruns. + fetch-depth: 2 persist-credentials: false + - name: Resolve PR baseline + id: comparison + if: github.event_name == 'pull_request' + run: | + git rev-parse --verify HEAD^2 >/dev/null + base_sha=$(git rev-parse --verify HEAD^1) + echo "base_sha=$base_sha" >> "$GITHUB_OUTPUT" + echo "Trivy comparison: $base_sha -> $(git rev-parse HEAD)" + - id: changed if: github.event_name == 'pull_request' uses: tj-actions/changed-files@aa08304bd477b800d468db44fe10f6c61f7f7b11 # v42.1.0 with: + base_sha: ${{ steps.comparison.outputs.base_sha }} + sha: ${{ github.sha }} + output_renamed_files_as_deleted_and_added: true # `any_modified` covers deletions, which `any_changed` omits, and a # failed diff has to fail the job: both otherwise report no relevant # change, and removing the scanner or a value fixture would skip the @@ -73,7 +89,7 @@ jobs: runs-on: ubuntu-latest timeout-minutes: 30 env: - BASE_REF: ${{ github.event.pull_request.base.sha || github.event.merge_group.base_sha || inputs.base_sha }} + BASE_REF: ${{ needs.changes.outputs.base_sha || github.event.merge_group.base_sha || inputs.base_sha }} HEAD_REF: ${{ inputs.head_sha || github.sha }} defaults: run: diff --git a/CI.md b/CI.md index 4838595cc5..a8c54fc726 100644 --- a/CI.md +++ b/CI.md @@ -135,9 +135,16 @@ Use a fresh `TRIVY_REPORT_DIR` for each scan session. `prepare-sarif` creates ### Pull-request change gate -`Trivy Changes` scans the base and candidate when a pull request or merge group -changes deployment configuration or scanner inputs. It fails only for new -`HIGH` or `CRITICAL` misconfigurations and retains both report sets. +`Trivy Changes` scans the base and candidate when a pull request changes +deployment configuration or scanner inputs; merge groups and manual runs always +scan. It fails only for new `HIGH` or `CRITICAL` misconfigurations and retains +both report sets. + +For pull requests, change detection compares the exact tested merge commit with +its first parent. Both detection and scanning use that same pair. This excludes +unrelated changes on `main` even when the event carries an older base SHA or a +job is rerun. Merge groups use the event's base SHA; manual runs use the supplied +base and head. A missing revision or invalid PR merge checkout fails the gate. The candidate ignore file is validated, but the baseline policy applies to both scans so a change cannot exempt its own finding. Existing profiles are compared diff --git a/architecture/build.md b/architecture/build.md index 5f3b913e1b..504bb49c82 100644 --- a/architecture/build.md +++ b/architecture/build.md @@ -494,6 +494,10 @@ references. Publication batches respect GitHub's limit of 20 SARIF runs. The PR/merge-group gate scans base and candidate with the same scanner and rejects new `HIGH` or `CRITICAL` configuration findings. Its stable `OpenShell / Trivy Changes` status succeeds when nothing relevant changed. +For PRs, the baseline is the first parent of the exact merge commit being tested, +not the event's potentially older base SHA or the current branch tip. Change +detection and both scans use that same immutable pair, including on reruns. +Merge groups and manual runs retain their explicit baseline and always scan. Image CVEs need the standalone scan. The reporting and gate invariants are: - A structurally invalid Trivy report is an error, not an empty finding set.