gha-container-proof 1.0.0

GitHub Actions job-container and Docker-action compatibility checker with Docker CLI probe receipts for offline CI
Documentation
name: "GHA Container Proof"
description: "Classify GitHub Actions job containers and Docker actions with Docker CLI probe receipts — offline by default."
author: "Wildmason"
branding:
  icon: "box"
  color: "gray-dark"
inputs:
  version:
    description: "Crate version to install, or latest."
    required: false
    default: "latest"
  command:
    description: "Command to run. Use check-workflow, plan-job, plan-action, or probe."
    required: false
    default: "check-workflow"
  repo:
    description: "Repository root for check-workflow (defaults to the current directory)."
    required: false
  workspace:
    description: "Workspace root for check-workflow."
    required: false
  workflow:
    description: "Newline-separated workflow paths for check-workflow."
    required: false
  job-id:
    description: "Job id for plan-job."
    required: false
  runner-os:
    description: "Runner OS: linux, windows, or macos."
    required: false
    default: "linux"
  runs-on:
    description: "Newline-separated runs-on labels for plan-job."
    required: false
  container:
    description: "Image for plan-job's job container."
    required: false
  env:
    description: "Newline-separated KEY=VALUE entries (plan-job, plan-action, probe)."
    required: false
  port:
    description: "Newline-separated port mappings for plan-job."
    required: false
  volume:
    description: "Newline-separated volume mappings for plan-job."
    required: false
  options:
    description: "Raw Docker options string for plan-job."
    required: false
  action-ref:
    description: "Action reference for plan-action (e.g. ./actions/build or docker://alpine:3)."
    required: false
  action-path:
    description: "Local action directory for plan-action."
    required: false
  using:
    description: "runs.using value for plan-action (docker, node20, composite)."
    required: false
  image:
    description: "Image or Dockerfile descriptor for plan-action or probe."
    required: false
  entrypoint:
    description: "Entrypoint override for plan-action."
    required: false
  pre-entrypoint:
    description: "Pre-entrypoint script for plan-action."
    required: false
  post-entrypoint:
    description: "Post-entrypoint script for plan-action."
    required: false
  args:
    description: "Args string for plan-action."
    required: false
  tool:
    description: "Newline-separated tool names for probe (each run as `<tool> --version`)."
    required: false
  probe-command:
    description: "Newline-separated raw commands for probe (each run inside the container)."
    required: false
  allow-pull:
    description: "Allow probe to pull images (set to 'true' for opt-in)."
    required: false
    default: "false"
  docker-bin:
    description: "Override the Docker CLI binary path (default: discovered on PATH)."
    required: false
  format:
    description: "Receipt format: text, json, or markdown."
    required: false
    default: "text"
  output:
    description: "Optional receipt output path."
    required: false
  strict:
    description: "Treat warnings as failures."
    required: false
    default: "false"
runs:
  using: "composite"
  steps:
    - name: "Install gha-container-proof"
      shell: "bash"
      run: |
        if command -v gha-container-proof >/dev/null 2>&1; then
          exit 0
        fi

        if [ "${PROOF_VERSION}" = "latest" ]; then
          cargo install gha-container-proof --locked
        else
          cargo install gha-container-proof --version "${PROOF_VERSION}" --locked
        fi
      env:
        PROOF_VERSION: ${{ inputs.version }}
    - name: "Run gha-container-proof"
      shell: "bash"
      run: |
        set -euo pipefail

        args=("$PROOF_COMMAND")

        append_if_set() {
          local flag="$1"
          local value="$2"
          if [ -n "$value" ]; then
            args+=("$flag" "$value")
          fi
        }

        append_lines() {
          local flag="$1"
          local value="$2"
          while IFS= read -r line; do
            if [ -n "$line" ]; then
              args+=("$flag" "$line")
            fi
          done <<< "$value"
        }

        case "$PROOF_COMMAND" in
          check-workflow)
            append_if_set --repo "$PROOF_REPO"
            append_if_set --workspace "$PROOF_WORKSPACE"
            append_lines --workflow "$PROOF_WORKFLOW"
            append_if_set --runner-os "$PROOF_RUNNER_OS"
            ;;
          plan-job)
            append_if_set --job-id "$PROOF_JOB_ID"
            append_if_set --runner-os "$PROOF_RUNNER_OS"
            append_lines --runs-on "$PROOF_RUNS_ON"
            append_if_set --container "$PROOF_CONTAINER"
            append_lines --env "$PROOF_ENV"
            append_lines --port "$PROOF_PORT"
            append_lines --volume "$PROOF_VOLUME"
            append_if_set --options "$PROOF_OPTIONS"
            ;;
          plan-action)
            append_if_set --action-ref "$PROOF_ACTION_REF"
            append_if_set --action-path "$PROOF_ACTION_PATH"
            append_if_set --using "$PROOF_USING"
            append_if_set --image "$PROOF_IMAGE"
            append_if_set --entrypoint "$PROOF_ENTRYPOINT"
            append_if_set --pre-entrypoint "$PROOF_PRE_ENTRYPOINT"
            append_if_set --post-entrypoint "$PROOF_POST_ENTRYPOINT"
            append_if_set --args "$PROOF_ARGS"
            append_lines --env "$PROOF_ENV"
            ;;
          probe)
            append_if_set --image "$PROOF_IMAGE"
            append_if_set --runner-os "$PROOF_RUNNER_OS"
            append_lines --tool "$PROOF_TOOL"
            append_lines --command "$PROOF_PROBE_COMMAND"
            append_lines --env "$PROOF_ENV"
            if [ "$PROOF_ALLOW_PULL" = "true" ]; then
              args+=(--allow-pull)
            fi
            append_if_set --docker-bin "$PROOF_DOCKER_BIN"
            ;;
          *)
            echo "command must be one of: check-workflow, plan-job, plan-action, probe" >&2
            exit 2
            ;;
        esac

        args+=(--format "$PROOF_FORMAT")
        append_if_set --output "$PROOF_OUTPUT"
        if [ "$PROOF_STRICT" = "true" ]; then
          args+=(--strict)
        fi

        gha-container-proof "${args[@]}"
      env:
        PROOF_COMMAND: ${{ inputs.command }}
        PROOF_REPO: ${{ inputs.repo }}
        PROOF_WORKSPACE: ${{ inputs.workspace }}
        PROOF_WORKFLOW: ${{ inputs.workflow }}
        PROOF_RUNNER_OS: ${{ inputs.runner-os }}
        PROOF_JOB_ID: ${{ inputs.job-id }}
        PROOF_RUNS_ON: ${{ inputs.runs-on }}
        PROOF_CONTAINER: ${{ inputs.container }}
        PROOF_ENV: ${{ inputs.env }}
        PROOF_PORT: ${{ inputs.port }}
        PROOF_VOLUME: ${{ inputs.volume }}
        PROOF_OPTIONS: ${{ inputs.options }}
        PROOF_ACTION_REF: ${{ inputs.action-ref }}
        PROOF_ACTION_PATH: ${{ inputs.action-path }}
        PROOF_USING: ${{ inputs.using }}
        PROOF_IMAGE: ${{ inputs.image }}
        PROOF_ENTRYPOINT: ${{ inputs.entrypoint }}
        PROOF_PRE_ENTRYPOINT: ${{ inputs.pre-entrypoint }}
        PROOF_POST_ENTRYPOINT: ${{ inputs.post-entrypoint }}
        PROOF_ARGS: ${{ inputs.args }}
        PROOF_TOOL: ${{ inputs.tool }}
        PROOF_PROBE_COMMAND: ${{ inputs.probe-command }}
        PROOF_ALLOW_PULL: ${{ inputs.allow-pull }}
        PROOF_DOCKER_BIN: ${{ inputs.docker-bin }}
        PROOF_FORMAT: ${{ inputs.format }}
        PROOF_OUTPUT: ${{ inputs.output }}
        PROOF_STRICT: ${{ inputs.strict }}