rmcguireandClaude Opus 5 7a81afec65
Build Images / ${{ fromJSON(needs.select.outputs.images) }} (push) Successful in 3m33s
Build Images / Select images (push) Successful in 41s
Lint / lint (push) Successful in 44s
Lint by piping files to the linters instead of bind-mounting
`make lint` passed locally but failed in Gitea Actions with every Dockerfile
reported as missing:

    hadolint: images/node-agent/Dockerfile: withBinaryFile: does not exist

The job itself runs in a container, and the checkout lives in a docker volume
rather than on the host filesystem. Starting hadolint as a sibling container
through the host's docker socket meant `-v "$(CURDIR)":/repo` was resolved
against the HOST, where /workspace/... does not exist — so Docker created an
empty directory and mounted that.

Stream each file in on stdin instead. No shared filesystem is involved, so the
same command works locally and in CI. The linters then only ever see "-" as the
filename, so hack/lint.sh prints the real path itself, and only on failure.

Reproduced the original error and verified the fix against a faithful local
simulation: the repo in a docker volume at a path absent from the host, with
the socket mounted, running the real runner image.

Co-Authored-By: Claude Opus 5 (1M context) <[email protected]>
2026-08-09 11:48:50 -04:00

images

Custom container images, published to the public rmcguire registry on Gitea.

Each image is self-contained in its own directory under images/: a Dockerfile, a README.md, and an optional test.sh.

Images

Image Base Purpose
node-agent node:22-alpine Node 22 plus a GNU shell, network and Kubernetes toolchain — a general-purpose command execution environment for AI agents

Pulling

docker pull gitea.libretechconsulting.com/rmcguire/node-agent:latest

The registry is public, so no pull secret is required.

Tags

Tag Points at
vX.Y.Z / vX.Y / vX a released build
latest the most recent release
edge the current tip of main
main-<sha> one specific commit on main

Releases are cut per image by pushing a tag named <image>/vX.Y.Z, which builds and publishes that image alone:

git tag node-agent/v1.0.0 && git push origin node-agent/v1.0.0

Base images and package versions are deliberately not pinned — rebuilding is how upstream updates land, and the published tag is what pins things for whoever pulls it.

Adding an image

cp -r template images/my-image
  1. Edit images/my-image/Dockerfile, or base it on an image already published here (FROM gitea.libretechconsulting.com/rmcguire/node-agent:latest).
  2. Fill in images/my-image/README.md.
  3. Extend images/my-image/test.sh to assert whatever the image promises.
  4. make build test IMAGE=my-image

CI needs no changes — it discovers every directory under images/ that contains a Dockerfile.

Local development

make help                        # list targets
make all                         # everything CI does
make build test IMAGE=node-agent # one image

CI

Two Gitea workflows, both of which just call the make targets above:

  • lint.yaml — repository layout, hadolint, shellcheck.
  • build.yaml — builds only the images whose files changed, smoke-tests each one before anything is published, then pushes on main or a release tag.
S
Description
Public container images
Readme
76 KiB
Languages
Shell 69.3%
Dockerfile 20.5%
Makefile 10.2%