2026-05-06 08:07:13 -05:00
# 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.
2026-08-26 13:22:07 +00:00
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
2026-08-26 13:39:16 +00:00
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.
2026-05-06 08:07:13 -05:00
2026-09-07 14:52:03 +00:00
## 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:
```sh
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` .
2026-09-07 15:08:18 +00:00
The generated proxy directory has an exact build-only nested `go.mod` marker.
Native Go module packaging excludes that directory from provider releases, so
downstream consumers never recursively bundle another provider's build inputs.
The checker requires the marker, and a native local-Git archive test proves the
exclusion without permitting Git network protocols.
2026-09-07 14:52:03 +00:00
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.
2026-05-06 08:07:13 -05:00
## Usage
```yaml
- 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
2026-08-26 13:39:16 +00:00
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.
```yaml
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.
2026-05-06 08:07:13 -05:00
## Inputs
| Name | Required | Default | Description |
|---|---|---|---|
| `image` | yes | — | Full image name without tag (e.g. `code.fritzlab.net/fritzlab/chrony` ). |
| `context` | no | `.` | Docker build context. |
2026-05-27 13:07:11 -05:00
| `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` . |
2026-07-08 19:32:41 -05:00
| `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>` . |
2026-05-06 08:07:13 -05:00
| `smoke-test` | no | — | Shell command run after build. `$IMAGE` is set to `<image>:<run_number>` . Non-zero exit fails the action. |
2026-08-26 13:39:16 +00:00
| `token` | no | — | `ci-bot` access token with `read:package` capability. Required to pull a private base image; omit for public bases. |
2026-05-06 08:07:13 -05:00
## Outputs
| Name | Description |
|---|---|
| `tag` | Numeric tag assigned (= `github.run_number` ). |
## Smoke test patterns
Override entrypoint for a binary that expects no args:
```yaml
smoke-test : docker run --rm --entrypoint /usr/sbin/chronyd $IMAGE -v
```
Run a help command that returns non-zero:
```yaml
smoke-test : docker run --rm $IMAGE --help || true
```
Multiple checks chained:
```yaml
smoke-test : |
docker run --rm $IMAGE --version
docker run --rm --entrypoint /bin/sh $IMAGE -c 'test -x /usr/local/bin/myapp'
```