action/image-build

Composite Gitea Action that builds a container image with buildx and optionally runs a smoke test. Does not push — pair with action/image-push to publish.

Splitting build from push lets a PR workflow run image-build without push or deploy side effects while main runs the full build → push → deploy chain. A PR build that pulls a private base image still needs a registry token limited to the read:package capability; public-base builds need no token. The action logs in as ci-bot, so the token must be issued to that account.

Private Go module builds

tools/private-modules/ owns the stdlib-only offline generator and verifier for native Go file-proxy bundles. Consumers export exact committed source bytes so their first check needs no Git, network, module dependency, or credential. Changes belong here; consumers must not edit their generated copies.

From this checkout, export a reviewed full commit ID into a service checkout:

python3 tools/export-private-modules.py /path/to/service --revision FULL_COMMIT_ID
python3 tools/export-private-modules.py /path/to/service --revision FULL_COMMIT_ID --check

The export includes source revision/path/digest metadata and a SHA256 lock. Service Make and Docker builds run sha256sum -c tools/private-modules.sha256 before GO111MODULE=off GOTOOLCHAIN=local GOFLAGS= go run tools/private-modules.go. Reviewers can reproduce --check from that pinned source commit. The local hash check detects accidental drift; Git review establishes the trusted source pin.

Populate selected private versions through the configured authenticated Go client once, then run the generated command with -write to copy unchanged .info, .mod, and .zip cache artifacts into third_party/go-proxy. The generator itself enforces offline resolution and a local toolchain. It preserves the complete original archives, including any licenses and notices. Normal Go downloads still validate their content against the consumer's go.sum.

Consumer resolution uses GONOPROXY=none, GONOSUMDB=code.fritzlab.net, GOFLAGS=-mod=readonly, GOTOOLCHAIN=local, and GOPROXY=file:///absolute/service/third_party/go-proxy,https://proxy.golang.org. Run the checker before and after downloads; its exact go.mod/go.sum fingerprint rejects stale dependency closures. Public modules stay on the public proxy. Registry publication remains a separate authenticated operation.

Usage

- uses: actions/checkout@v4
- uses: https://code.fritzlab.net/action/image-build@v1
  with:
    image: code.fritzlab.net/fritzlab/chrony
    smoke-test: docker run --rm --entrypoint /usr/sbin/chronyd $IMAGE -v

The image is built and tagged as <image>:<github.run_number> in the runner's local Docker daemon. Subsequent steps (e.g. action/image-push) can reference the same tag.

Private bases in PRs

Pass token only when the PR head is trusted, and limit ci-bot package access to the private base images that the build requires. Never expose an organization-wide package reader to a contributor-controlled Dockerfile: it can pull and disclose any package that the account can read.

with:
  token: ${{ secrets.PACKAGE_READ_TOKEN }} # caller-chosen secret name

The token must be issued to ci-bot with read:package capability. Tokens from other accounts fail because the action's registry username is fixed. Omit the input for public bases.

Inputs

Name Required Default Description
image yes — Full image name without tag (e.g. code.fritzlab.net/fritzlab/chrony).
context no . Docker build context.
dockerfile no Dockerfile (in context) Path to the Dockerfile, relative to the context (or absolute under $GITHUB_WORKSPACE). Use for monorepos where the build context is the repo root but the Dockerfile lives in a subdir, e.g. dockerfile: api/Dockerfile.
build-args no — Multiline KEY=VALUE build args. Visible in docker history — never put secrets here.
secrets no — Multiline id=VALUE BuildKit secrets (--secret). For tokens the build needs (e.g. a ci-bot token to go mod download a private module) that must not leak into layers. Reference with RUN --mount=type=secret,id=<id>.
smoke-test no — Shell command run after build. $IMAGE is set to <image>:<run_number>. Non-zero exit fails the action.
token no — ci-bot access token with read:package capability. Required to pull a private base image; omit for public bases.

Outputs

Name Description
tag Numeric tag assigned (= github.run_number).

Smoke test patterns

Override entrypoint for a binary that expects no args:

smoke-test: docker run --rm --entrypoint /usr/sbin/chronyd $IMAGE -v

Run a help command that returns non-zero:

smoke-test: docker run --rm $IMAGE --help || true

Multiple checks chained:

smoke-test: |
  docker run --rm $IMAGE --version
  docker run --rm --entrypoint /bin/sh $IMAGE -c 'test -x /usr/local/bin/myapp'
S
Description
fritzlab composite action: image-build
Readme
85 KiB
0 Stars 9 Watchers 0 Forks
Languages
Go 67.3%
Python 31.1%
Dockerfile 1.6%