7.6 KiB
actions
Reusable composite actions shared across the git.sysmd.uk CI workflows.
These actions implement mechanism only (install a tool, scan an image). Each calling workflow keeps its own policy: what triggers a build, and whether a finding notifies, fails the run, blocks a push, or blocks a deploy.
Actions
| Action | Purpose |
|---|---|
install-grype |
Installs a pinned, signature-verified Grype (and the pinned Cosign used to verify it) into a job-local directory on PATH. |
install-syft |
Installs a pinned, signature-verified Syft the same way, for SBOM generation. |
install-mise |
Installs a pinned, signature-verified mise (and the pinned minisign used to verify it) into a job-local directory on PATH. |
scan-image |
Scans an image, directory, or SBOM with Grype and fails the step on fixable findings at the configured severities; writes the raw JSON report. |
Usage
Reference the actions from another repository with the full instance URL. An
unprefixed owner/repo@ref is fetched from github.com (unless
DEFAULT_ACTIONS_URL=self), and the self: prefix is not honoured by all
runner versions. The absolute form works regardless:
uses: https://git.sysmd.uk/mdaleo404/actions/install-grype@v1
Pin the ref (@v1, or a commit SHA for stronger supply-chain guarantees)
rather than floating @main. The path is any directory containing
action.yml — these live at the repo root, so the refs are short.
The repository must be reachable by the runner without credentials. If it is
private, either make it public or vendor the action into the consuming
repository and reference it locally as ./.gitea/actions/<name>.
jobs:
build-scan-push:
runs-on: running-man
env:
IMAGE: git.sysmd.uk/team/example:latest
steps:
- uses: actions/checkout@v4
- name: Login to registry
run: echo "$REGISTRY_TOKEN" | docker login git.sysmd.uk -u "$REGISTRY_USER" --password-stdin
env:
REGISTRY_USER: ${{ secrets.REGISTRY_USER }}
REGISTRY_TOKEN: ${{ secrets.REGISTRY_TOKEN }}
- name: Build image
run: docker build --no-cache -t "${IMAGE}" .
- uses: https://git.sysmd.uk/mdaleo404/actions/install-grype@v1
# continue-on-error lets the caller inspect the outcome and decide policy.
- name: Scan image
id: scan
continue-on-error: true
uses: https://git.sysmd.uk/mdaleo404/actions/scan-image@v1
with:
image: ${{ env.IMAGE }}
- name: Notify on vulnerabilities
if: steps.scan.outcome == 'failure'
run: |
# read grype.json (written by scan-image) and post wherever you like
jq '{repo: "owner/repo", image: env.IMAGE, count: (.matches | length)}' grype.json
- name: Fail if vulnerabilities found
if: steps.scan.outcome == 'failure'
run: exit 1
- name: Push image
if: steps.scan.outcome != 'failure'
run: docker push "${IMAGE}"
SBOM / directory scan
For a repository rather than an image, generate an SBOM with Syft and scan it
with the same action by passing target:
- uses: https://git.sysmd.uk/mdaleo404/actions/install-grype@v1
- uses: https://git.sysmd.uk/mdaleo404/actions/install-syft@v1
- name: Generate SBOM
run: syft dir:. -o json > sbom.json
- name: Scan SBOM
id: scan
continue-on-error: true
uses: https://git.sysmd.uk/mdaleo404/actions/scan-image@v1
with:
target: sbom:sbom.json
severities: Medium,High,Critical
Interface
install-grype
| Input | Default | Notes |
|---|---|---|
grype-version |
v0.110.0 |
Release tag including v. |
cosign-version |
v3.0.5 |
Cosign used only to verify Grype's checksums. |
install-dir |
job-local dir on PATH |
Override to choose the install location. |
Outputs: grype-path, version.
Supports amd64 and arm64. Cosign is checksum-pinned per architecture; Grype
is verified against its keyless-signed checksum file.
install-syft
| Input | Default | Notes |
|---|---|---|
syft-version |
v1.42.3 |
Release tag including v. |
cosign-version |
v3.0.5 |
Cosign used only to verify Syft's checksums. |
install-dir |
job-local dir on PATH |
Override to choose the install location. |
Outputs: syft-path, version.
Supports amd64 and arm64, verified the same way as Grype.
install-mise
| Input | Default | Notes |
|---|---|---|
mise-version |
v2026.10.9 |
Release tag including v. |
minisign-version |
0.12 |
minisign used only to verify mise's checksums. |
install-dir |
job-local dir on PATH |
Override to choose the install location. |
Outputs: mise-path, version.
Supports amd64 and arm64. This is the one action here that does not use
Cosign, because mise publishes no keyless-signed checksum file: it bootstraps
minisign (itself checksum-pinned, in a tarball carrying both architectures) and
verifies SHASUMS256.txt against mise's minisign public key, pinned in the
action, before checking the release archive against the verified file.
Only the mise binary is installed. A caller that then runs mise install
decides for itself where the toolchain lands (MISE_DATA_DIR), and what to do
with the result: mise has no audit command, so vulnerability coverage comes
from scanning the installed artifacts.
scan-image
| Input | Default | Notes |
|---|---|---|
image |
— | Image reference to scan. Required unless target is set. |
target |
— | Grype target, e.g. sbom:sbom.json or dir:.. Overrides image when set. |
report-path |
grype.json |
Raw JSON report location, relative to the workspace. |
fail-on-fixable |
true |
Set false to always pass and inspect outputs instead. |
severities |
High,Critical |
Comma-separated severities that count as findings. |
Outputs: fixable-count, total-count, report-path.
The step exits non-zero when fixable findings exist at the selected severities
and fail-on-fixable is true. Combine with continue-on-error: true and
steps.<id>.outcome to implement notify-then-fail, as above.
Versioning
install-grype, install-syft and install-mise centralise the Cosign, Grype,
Syft, mise, and minisign versions. Bump them here, deliberately, and tag a new
release (v1, v2, ...) so callers can pin. The mise action also carries a
minisign bootstrap checksum and mise's minisign public key; bump those together
with the versions they belong to.
Consuming safely
This repository is public, and every action here runs inside the caller's job — with the caller's secrets, on the caller's runner. Treat a merge here as a release to every consumer:
- Pin a commit SHA, not a moving ref.
@v1can be moved; a full SHA cannot. - Keep secrets in the calling workflow; nothing here reads or writes secrets.
- Installs verify their payloads before use:
install-grypeandinstall-syftagainst keyless Cosign signatures (with checksum-pinned Cosign bootstraps), andinstall-miseagainst mise's minisign signature (with a checksum-pinned minisign bootstrap). They fetch only fromgithub.com/sigstore/cosign,github.com/anchore/{grype,syft},github.com/jedisct1/minisignandgithub.com/jdx/mise. - Report suspected issues privately to the maintainer (see
CODEOWNERS) rather than opening a public issue.
Notes
- The
scan-imageaction writes the raw report to the workspace; the caller's notification step can keep using the samegrype.jsonit already expects. - Nothing here reads or writes secrets. Tokens stay in the calling workflow.