Private module tooling / contract (pull_request) Successful in 32s
Authored-By: Codex (GPT-6) <noreply@openai.com>
134 lines
6.0 KiB
Markdown
134 lines
6.0 KiB
Markdown
# 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:
|
|
|
|
```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`.
|
|
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.
|
|
|
|
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
|
|
|
|
```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
|
|
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.
|
|
|
|
## 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`). |
|
|
|
|
## Private module contract validation
|
|
|
|
The private-module contract workflow runs its Go race tests in the digest-pinned
|
|
standard Go compiler image in `tests/private-modules.Dockerfile`. The Fritzlab
|
|
runner doesn't provide GCC. Only `tools/private-modules` enters that build context;
|
|
the test runs with networking and module downloads disabled. The public compiler
|
|
image must already be cached or obtainable through the existing image pull path.
|
|
This check doesn't publish an image or change runner configuration.
|
|
|
|
```sh
|
|
python3 -m unittest discover -s tests
|
|
docker build --network none --file tests/private-modules.Dockerfile tools/private-modules
|
|
```
|
|
|
|
## 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'
|
|
```
|