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. @v1 can 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-grype and install-syft against keyless Cosign signatures (with checksum-pinned Cosign bootstraps), and install-mise against mise's minisign signature (with a checksum-pinned minisign bootstrap). They fetch only from github.com/sigstore/cosign, github.com/anchore/{grype,syft}, github.com/jedisct1/minisign and github.com/jdx/mise.
  • Report suspected issues privately to the maintainer (see CODEOWNERS) rather than opening a public issue.

Notes

  • The scan-image action writes the raw report to the workspace; the caller's notification step can keep using the same grype.json it already expects.
  • Nothing here reads or writes secrets. Tokens stay in the calling workflow.
S
Description
No description provided
Readme
54 KiB
0 Stars 1 Watchers 0 Forks
Languages
CODEOWNERS 100%