diff --git a/.github/workflows/docker-build.yml b/.github/workflows/docker-build.yml index 6e0df06..29cb0c6 100644 --- a/.github/workflows/docker-build.yml +++ b/.github/workflows/docker-build.yml @@ -70,6 +70,16 @@ on: trivy-ignore-unfixed: type: boolean default: true + upload-sarif: + description: >- + Upload the Trivy SARIF report to code scanning. Requires GitHub + Advanced Security, so private repos on the Free plan must pass false — + otherwise the upload step fails with "Advanced Security must be + enabled for this repository to use code scanning" while the scan + itself passes. Mirrors the input of the same name on trivy-repo.yml. + Defaults true to preserve existing behaviour. + type: boolean + default: true sign-image: description: "Sign the pushed image with cosign keyless OIDC. Requires push: true." type: boolean @@ -115,7 +125,17 @@ jobs: steps: - uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1 + # QEMU only exists to emulate a foreign architecture. The runners are all + # X64 and `platforms` defaults to linux/amd64, so for most consumers this + # step installs binfmt handlers that nothing then uses — while costing real + # wall-clock on a contended pool: 16m18s observed on one extractor-llm + # run, ahead of a build that never needed it. + # + # Skipped when the requested platforms are exactly the native arch. The + # two consumers that do cross-build (scraper-proxy-router always, store-s3 + # on main) pass a platforms list containing linux/arm64 and still get it. - uses: docker/setup-qemu-action@96fe6ef7f33517b61c61be40b68a1882f3264fb8 # v4.2.0 + if: inputs.platforms != 'linux/amd64' - uses: docker/setup-buildx-action@37fe631027851001ddb9b187196cc803df7f5f0e # v4.3.0 # Mint a scoped App token for private modules pulled during the build. @@ -226,8 +246,14 @@ jobs: severity: ${{ inputs.trivy-severity }} ignore-unfixed: ${{ inputs.trivy-ignore-unfixed }} + # Guarded by `upload-sarif` for the same reason trivy-repo.yml is: uploading + # to code scanning needs GitHub Advanced Security, which private repos on + # the Free plan do not have. Without the guard the step fails with + # "Advanced Security must be enabled for this repository to use code + # scanning" on every push to main, while the scan above passes — a + # permanently red check reporting an entitlement rather than a finding. - name: Trivy scan (SARIF) - if: inputs.run-trivy-scan && inputs.push && github.event_name != 'pull_request' + if: inputs.run-trivy-scan && inputs.push && inputs.upload-sarif && github.event_name != 'pull_request' uses: aquasecurity/trivy-action@ed142fd0673e97e23eac54620cfb913e5ce36c25 # v0.36.0 with: image-ref: ${{ steps.imageref.outputs.repo }}@${{ steps.build.outputs.digest }} @@ -237,7 +263,7 @@ jobs: ignore-unfixed: ${{ inputs.trivy-ignore-unfixed }} - name: Upload SARIF - if: inputs.run-trivy-scan && inputs.push && github.event_name != 'pull_request' + if: inputs.run-trivy-scan && inputs.push && inputs.upload-sarif && github.event_name != 'pull_request' uses: github/codeql-action/upload-sarif@cdf488f595d80d6e07e03d4674febd5ab45fa938 # v4.37.9 with: sarif_file: trivy.sarif diff --git a/CHANGELOG.md b/CHANGELOG.md index fceb802..e8ccd5f 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -6,6 +6,33 @@ project uses [SemVer](https://semver.org/) for the `vMAJOR.MINOR.PATCH` tags. ## [Unreleased] +### Added + +- **`docker-build.yml` gained an `upload-sarif` input** (boolean, default + `true`, mirroring the input of the same name on `trivy-repo.yml`). Uploading + a SARIF report to code scanning requires GitHub Advanced Security, which + private repos on the Free plan do not have, so the `Upload SARIF` step failed + with `Advanced Security must be enabled for this repository to use code + scanning` on every push to `main` while the Trivy scan immediately above it + passed. That is a permanently red check reporting an entitlement rather than + a security finding. Consumers on the Free plan pass `upload-sarif: false`; + the SARIF generation step is gated on the same input, so nothing is produced + that cannot be uploaded. Default is `true`, so existing behaviour is + unchanged for anyone who has Advanced Security. + +### Fixed + +- **`docker-build.yml` no longer runs `docker/setup-qemu-action` for + single-architecture builds.** QEMU exists only to emulate a foreign + architecture; the runners are all X64 and `platforms` defaults to + `linux/amd64`, so for most consumers the step installed binfmt handlers that + nothing subsequently used. It is not free: **16m18s** on one observed + `extractor-llm` run, ahead of a build that never needed it, on a three-runner + pool where queueing is the dominant cost. The step is now skipped when + `platforms` is exactly `linux/amd64`. The two consumers that genuinely + cross-build — `scraper-proxy-router` (always) and `store-s3` (on `main`) — + request `linux/arm64` and still get QEMU. + ### Changed - **`claude-code-review.yml` now defaults to a GitHub-hosted runner**