From 6c76681915e88ef029384b0acd95a211eb11f8f3 Mon Sep 17 00:00:00 2001 From: Maxim Stykow Date: Sat, 11 Jul 2026 18:20:02 +0200 Subject: [PATCH 1/2] feat: add license-policy, fail-on, and sarif-file inputs for CI gating Surface the Provenant compliance gate as first-class inputs: `license-policy` (YAML policy file), `fail-on` (error|warning; fails the job when a matching license is found), and `sarif-file` (SARIF 2.1.0 for code-scanning upload). The entrypoint maps each to the corresponding `provenant scan` flag when set. Adds a README example that gates the build and uploads findings via upload-sarif. Co-Authored-By: Claude Opus 4.8 (1M context) Signed-off-by: Maxim Stykow --- README.md | 39 +++++++++++++++++++++++++++++++++++---- action.yml | 24 ++++++++++++++++++++++++ entrypoint.sh | 17 +++++++++++++++++ 3 files changed, 76 insertions(+), 4 deletions(-) diff --git a/README.md b/README.md index 7b839a1..6cf309d 100644 --- a/README.md +++ b/README.md @@ -69,12 +69,39 @@ jobs: args: --license --package --copyright ``` +### Fail the build on a disallowed license + +Provide a [license-policy file](https://github.com/getprovenant/provenant/blob/main/docs/CLI_GUIDE.md#the-license-policy-file) +that marks licenses with a `compliance_alert`, then gate on it. The job fails +when a matching license is found, and the SARIF file surfaces the violations as +pull-request and code-scanning alerts: + +```yaml +permissions: + contents: read + security-events: write # to upload SARIF + +jobs: + license-gate: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v7 + - uses: getprovenant/provenant-action@v1 + with: + license-policy: .github/license-policy.yml + fail-on: error + sarif-file: provenant.sarif + - uses: github/codeql-action/upload-sarif@v3 + if: always() # upload findings even when the gate fails the job + with: + sarif_file: provenant.sarif +``` + ### Other scan options Any `provenant scan` flag can be passed through `args` — for example -`--ignore "node_modules/*"` to skip noise, `--incremental` with a cached -`--cache-dir` to reuse work across runs, or `--license-policy policy.yml` for -policy-aware review. See the [CLI Guide](https://github.com/getprovenant/provenant/blob/main/docs/CLI_GUIDE.md) +`--ignore "node_modules/*"` to skip noise or `--incremental` with a cached +`--cache-dir` to reuse work across runs. See the [CLI Guide](https://github.com/getprovenant/provenant/blob/main/docs/CLI_GUIDE.md) for the full set of workflows and flags. ## Inputs @@ -86,11 +113,15 @@ for the full set of workflows and flags. | `output-file` | `-` | Where to write the report. `-` streams to stdout (the workflow log); any other value is a path written inside the workspace. | | `args` | `--license --package` | Extra raw arguments appended verbatim to `provenant scan`. Detections are opt-in — this is where you enable them (`--license`, `--package`, `--copyright`, `--info`, `--email`, `--url`, …). | | `paths-file` | _(empty)_ | Optional file listing exact files/directories to scan (one per line), relative to a single scan root in `paths`. Ideal for pull-request CI via `git diff --name-only`. When set, `paths` must stay a single root (the default `.`). | +| `license-policy` | _(empty)_ | Optional path to a YAML license-policy file. Enables policy evaluation; required by `fail-on` and by SARIF output. | +| `fail-on` | _(empty)_ | Fail the job (exit 3) when a file matches a policy whose `compliance_alert` is at or above this level: `error` or `warning`. Requires `license-policy`. | +| `sarif-file` | _(empty)_ | Also write SARIF 2.1.0 of policy violations to this path, for `github/codeql-action/upload-sarif`. Meaningful only with `license-policy`. | Under the hood the action runs: ```sh -provenant scan [--paths-file ] -- +provenant scan [--paths-file ] [--license-policy ] \ + [--fail-on ] [--sarif ] -- ``` ## Outputs diff --git a/action.yml b/action.yml index b72880e..830e976 100644 --- a/action.yml +++ b/action.yml @@ -48,6 +48,27 @@ inputs: to scan `paths` directly. required: false default: "" + license-policy: + description: >- + Optional path to a YAML license-policy file (see the Provenant CLI guide for + the format). Enables policy evaluation; required by `fail-on` and by SARIF + output. + required: false + default: "" + fail-on: + description: >- + Fail the job (exit code 3) when a scanned file matches a policy whose + compliance_alert is at or above this level: "error" or "warning". Requires + `license-policy`. Leave empty to report without gating. + required: false + default: "" + sarif-file: + description: >- + Optional path to also write SARIF 2.1.0 of policy violations, for uploading + with github/codeql-action/upload-sarif so findings appear as pull-request and + code-scanning alerts. Meaningful only with `license-policy`. + required: false + default: "" # The upstream image (gcr.io/distroless/static-debian12) ships no shell and its # ENTRYPOINT is the provenant binary itself, so optional/variadic inputs cannot @@ -66,3 +87,6 @@ runs: - ${{ inputs.output-file }} - ${{ inputs.args }} - ${{ inputs.paths-file }} + - ${{ inputs.license-policy }} + - ${{ inputs.fail-on }} + - ${{ inputs.sarif-file }} diff --git a/entrypoint.sh b/entrypoint.sh index 7527c65..96d3735 100755 --- a/entrypoint.sh +++ b/entrypoint.sh @@ -9,6 +9,9 @@ # $3 = output-file ("-" for stdout, or a path) # $4 = extra args (raw flags, word-split intentionally) # $5 = paths-file (optional; a --paths-file list, empty to skip) +# $6 = license-policy (optional; a --license-policy file, empty to skip) +# $7 = fail-on (optional; error|warning, empty to skip) +# $8 = sarif-file (optional; a --sarif output path, empty to skip) set -eu paths="${1:-.}" @@ -16,6 +19,9 @@ fmt="${2:-json-pp}" outfile="${3:--}" extra="${4:-}" pathsfile="${5:-}" +policy="${6:-}" +failon="${7:-}" +sariffile="${8:-}" case "$fmt" in json | json-pp | json-lines | yaml | cyclonedx | cyclonedx-xml | spdx-tv | spdx-rdf | debian | html) @@ -37,6 +43,17 @@ set -- scan $paths if [ -n "$pathsfile" ]; then set -- "$@" --paths-file "$pathsfile" fi +# License policy, the CI gate, and SARIF output. `--fail-on` and SARIF both need a +# policy to be meaningful; the CLI validates the `--fail-on` requirement. +if [ -n "$policy" ]; then + set -- "$@" --license-policy "$policy" +fi +if [ -n "$failon" ]; then + set -- "$@" --fail-on "$failon" +fi +if [ -n "$sariffile" ]; then + set -- "$@" --sarif "$sariffile" +fi # shellcheck disable=SC2086 set -- "$@" "$fmt_flag" "$outfile" $extra From bf767ac39975b97c1da4968d7f8d974c63fff59c Mon Sep 17 00:00:00 2001 From: Maxim Stykow Date: Sat, 11 Jul 2026 18:50:58 +0200 Subject: [PATCH 2/2] docs: clarify the action auto-tracks latest Provenant (no per-release commits) Signed-off-by: Maxim Stykow --- AGENTS.md | 13 +++++++++---- README.md | 19 ++++++++++--------- 2 files changed, 19 insertions(+), 13 deletions(-) diff --git a/AGENTS.md b/AGENTS.md index f9c6e37..1ec9f07 100644 --- a/AGENTS.md +++ b/AGENTS.md @@ -31,7 +31,12 @@ contain the scanner, only a thin Docker container action that runs the published ## Versioning and releases -- The wrapped Provenant version is selected by the `FROM` tag in the `Dockerfile`, **not** by a - call-time input (GitHub Actions forbids expressions in a container action's image reference). -- Cutting an action release: bump the `Dockerfile` `FROM` tag to a concrete, working Provenant - version, tag `vX.Y.Z`, and move the floating `vX` tag. Consumers pin `@vN` or a full SHA. +- The `Dockerfile` is `FROM ghcr.io/getprovenant/provenant:latest`, so the action **auto-tracks the + newest Provenant release** — GitHub rebuilds the image on each run and pulls `:latest`. There is + **no per-Provenant-release commit or re-release of this action**; publish it once and it follows + Provenant forward. +- Cut an action release only for changes to the **action itself** (inputs, entrypoint, docs): tag + `vX.Y.Z` and move the floating `vX` tag. Consumers pin `@vN` or a full SHA. +- Trade-off: `@vN` is not pinned to a fixed scanner version. If reproducible version pinning is ever + needed without per-release commits, convert to a composite action running + `docker run …:${{ inputs.version }}` (default `latest`). diff --git a/README.md b/README.md index 6cf309d..468322c 100644 --- a/README.md +++ b/README.md @@ -132,17 +132,18 @@ reading the report streamed to the workflow log when `output-file` is `-`. ## Versioning -The action is a Docker container action. The wrapped Provenant version is baked -into the action's [`Dockerfile`](Dockerfile) per release, so the version you run -is determined by the git ref you pin: +The action always runs the **latest** published Provenant release: its +[`Dockerfile`](Dockerfile) is `FROM ghcr.io/getprovenant/provenant:latest`, rebuilt on each run. +So the wrapped scanner advances automatically with every Provenant release — there is no per-release +update to this action. -- A **major version tag** (such as `@v1`) tracks the latest release within that - major series — the best default for most workflows. -- A **full commit SHA** is an exact, immutable pin. +You pin the **action's own** behavior by git ref: -Because GitHub Actions does not allow expressions in a container action's image -reference, the wrapped Provenant version cannot be selected at call time via an -input; it is selected by the action release you pin to. +- A **major version tag** (such as `@v1`) — the best default; picks up action fixes within that major. +- A **full commit SHA** — an exact, immutable pin of the action. + +Because the action tracks `:latest`, `@vN` does not pin a fixed scanner version. If you need a +reproducible scanner version, pin the container directly instead (`docker run ghcr.io/getprovenant/provenant: scan …`). ## How it works