Skip to content

wildmason/gha-container-proof

gha-container-proof

gha-container-proof is the GitHub Actions job container and Docker action compatibility oracle for offline CI. It turns jobs.<job_id>.container definitions, steps[*].uses: docker://... references, and local action manifests with runs.using: docker into deterministic receipts with stable check IDs.

It is part of Wildmason's offline GitHub Actions proof-tool lane:

  • gha-workflow-proof checks workflow structure.
  • gha-eventsmith creates event/context fixtures.
  • gha-expression-proof evaluates Actions expressions.
  • gha-cache-proof models actions/cache.
  • gha-artifact-proof models artifact upload/download.
  • gha-service-proof models service containers (jobs.<id>.services) and readiness.
  • gha-container-proof models the primary job container and Docker action containers.
  • gha-github-service-proof models the GitHub API/service surface.
  • gha-runner-image-proof validates runner-image manifests and the toolcache.
  • gha-command-proof checks runtime command and environment-file side effects.

gha-container-proof does not duplicate gha-service-proof. If a workflow has both job containers and services, check-workflow classifies the job-container side and emits container.services.delegated pointing at the sibling tool.

Install

cargo install gha-container-proof --locked

Commands

check-workflow

Scan workflow YAML for job containers and Docker action surfaces.

gha-container-proof check-workflow `
  --repo . `
  --workspace . `
  --workflow .github/workflows/ci.yml `
  --format json `
  --output target/container-proof.json

When --workflow is omitted, the command scans .github/workflows/*.yml and .github/workflows/*.yaml. The scan detects:

  • jobs.<job_id>.container as a bare image string or full object (image, credentials, env, ports, volumes, options).
  • steps[*].uses: docker://image.
  • steps[*].uses: ./local-action whose action.yml declares runs.using: docker with image: Dockerfile, image: docker://..., or a relative Dockerfile path.
  • Remote action refs (owner/repo@ref) are classified as simulated — external action manifest unavailable unless mirrored or provided.

plan-job

Classify a concrete rendered job-container request.

gha-container-proof plan-job \
  --job-id build \
  --runner-os linux \
  --runs-on ubuntu-22.04 \
  --container node:22-bookworm \
  --env NODE_ENV=test \
  --port 3000 \
  --volume /host/cache:/cache \
  --options "--cpus 2" \
  --format json \
  --output receipt.json

plan-action

Classify a concrete Docker action request.

gha-container-proof plan-action \
  --action-ref ./actions/build-image \
  --action-path ./actions/build-image \
  --using docker \
  --image Dockerfile \
  --entrypoint /entrypoint.sh \
  --pre-entrypoint /pre.sh \
  --post-entrypoint /post.sh \
  --args "build" \
  --env INPUT_TARGET=release \
  --format json \
  --output receipt.json

Also supports docker:// action references without a local path:

gha-container-proof plan-action --action-ref docker://alpine:3.20 --image docker://alpine:3.20 --format json

probe

Optionally use the Docker CLI to verify runtime availability and image behavior. Offline by default — does not pull images unless --allow-pull is set.

gha-container-proof probe \
  --image node:22-bookworm \
  --runner-os linux \
  --tool node --tool bash \
  --command "node --version" \
  --format json \
  --output probe.json
  • docker image inspect <image> records local image availability.
  • docker run --rm <image> <tool> --version and docker run --rm <image> sh -c "<command>" record probe evidence.
  • Captures command kind, image, exit code, stdout/stderr excerpts, and elapsed time.
  • Skips cleanly when the Docker CLI is not on PATH (probe.docker_cli_not_found) and fails clearly when the daemon is unreachable (probe.docker_daemon_unreachable).
  • Override the Docker binary with --docker-bin <PATH> or the GHA_CONTAINER_PROOF_DOCKER environment variable (used by tests to run against a fake docker).

What It Models

Job containers

  • Container jobs require a Linux Docker runner; Windows and macOS hosted runners are unsupported.
  • When a job runs in a container, shell steps execute inside the job container; networking is Docker-internal.
  • container.credentials is recognized and classified as requiring secret-safe handling; credential values are redacted in receipts.
  • container.options are parsed enough to flag known unsupported or dangerous options.
  • --network / --net are unsupported under ci-forge-managed networking and emit a failure.
  • --privileged, --pid=host, --ipc=host, --security-opt, and Docker socket mounts are flagged as risky.
  • Absolute Windows host paths (C:\..., D:\...) mounted into Linux containers warn.
  • --user, --workdir/-w, --entrypoint, --env/-e, --volume/-v, --cpus, --memory/-m are classified explicitly.
  • Unknown Docker options are classified as simulated/unknown rather than silently accepted.

Docker actions

  • runs.using: docker actions run in a new container for the action.
  • runs.image: Dockerfile (or a relative *.Dockerfile path) requires build support.
  • runs.image: docker://... requires image availability.
  • runs.pre-entrypoint, runs.entrypoint, and runs.post-entrypoint are recognized.
  • runs.args is preserved.
  • Action INPUT_* env can be passed through for receipts; the executor (ci-forge) owns post-state (STATE_*) handoff.
  • Dockerfile-backed actions detect missing Dockerfile, unsupported context, and build requirement.

Unsupported and warning surfaces

  • Job container on non-Linux runner → fail.
  • Docker unavailable on probe → skip (probe.docker_cli_not_found) or fail (probe.docker_daemon_unreachable).
  • Image missing locally while offline → fail unless --allow-pull is set.
  • --network / --net in options when ci-forge owns networks → fail.
  • --privilegedwarn (or fail under --strict).
  • Host Docker socket mount → warn (high-risk; explicit compatibility).
  • Absolute Windows host mount into Linux container → warn.
  • container.credentials values → redacted; absence checked.
  • Unknown Docker options → warn (container.options.unknown).
  • Remote Docker action manifest unavailable → simulated (action.manifest.unavailable).

Receipt shape

Every command emits the same top-level receipt:

{
  "schema_version": 1,
  "tool": { "name": "gha-container-proof", "version": "1.0.0" },
  "checked_at": "2026-...",
  "mode": "check-workflow",
  "compatibility": "compatible",
  "summary": { "passed": 0, "warnings": 0, "failed": 0, "skipped": 0 },
  "subjects": [ ... ],
  "checks": [ ... ]
}

Each subject describes one job container, Docker action, or Docker probe:

{
  "kind": "job-container",
  "job_id": "build",
  "image": "node:22-bookworm",
  "runner_os": "linux",
  "classification": "compatible",
  "network_model": "ci-forge-managed",
  "requires_docker": true,
  "requires_build": false,
  "requires_pull": false,
  "checks": [
    { "id": "container.image.declared", "status": "pass", "message": "...", "details": {} }
  ]
}

See docs/spec.md for the protocol surface and docs/RULES.md for stable check IDs.

GitHub Action

- uses: wildmason/gha-container-proof@v1
  with:
    command: check-workflow
    repo: .
    workflow: .github/workflows/ci.yml
    format: json
    output: target/container-proof.json

The action installs the crate with Cargo unless gha-container-proof is already on PATH.

Exit behavior

The CLI exits 0 when there are no failed checks. With --strict, warnings also fail the run.

Limits

gha-container-proof is a compatibility oracle, not a runner. It does not start long-lived job containers as the source of truth for execution — ci-forge owns the Docker lifecycle and attaches these receipts beside gha-service-proof, gha-cache-proof, gha-artifact-proof, gha-github-service-proof, and the rest.

License

Licensed under either of:

at your option.

About

GitHub Actions job-container and Docker-action compatibility checker with Docker CLI probe receipts for offline CI.

Resources

License

MIT and 2 other licenses found

Licenses found

MIT
LICENSE
Unknown
LICENSE-APACHE
MIT
LICENSE-MIT

Contributing

Security policy

Stars

Watchers

Forks

Packages

 
 
 

Contributors

Languages