The workflow now verifies that all three DinD TLS certificates are readable before attempting registry login or Buildx operations. The check fails early with instructions to apply runner-compose.yaml if the runner has not mounted /certs/client into job containers. Buildx now creates a named Docker context from the TLS environment variables, as Buildx cannot use TLS endpoints without an explicit context. Each CI run uses a uniquely named builder (based
6.2 KiB
Gitea CI/CD
The workflow in .gitea/workflows/build.yml runs on branch pushes, v* tag
pushes, pull requests, and manual dispatches. Each platform runs formatting,
vet, and unit checks before building static AMD64 and ARM64 binaries. Linux
also runs the mock Ombi integration suite. No live Ombi credentials are needed.
Download the ombi-mcp-darwin, ombi-mcp-linux, or ombi-mcp-windows artifacts
from the workflow run. Each contains two .tar.gz archives, one per architecture,
with the executable and README. Tar preserves Unix executable permissions.
Runner setup
Enable Actions in the repository settings and register these runner labels:
| Label | Host / requirements |
|---|---|
macos |
macOS host runner, Git, Bash, tar, Node.js 20 |
windows |
Windows host runner, Git for Windows (Bash on PATH), tar, Node.js 20; public-repository access |
ubuntu-latest |
Linux runner with Git, Bash, tar, Node.js 20, Docker Engine, curl, and Docker daemon access |
The Linux jobs use the ubuntu-latest runner label. The Windows job uses Git
directly because the self-hosted Windows runner cannot start the Node-based
checkout action; it therefore requires access to the public repository URL.
setup-go installs the version specified in go.mod.
Runners need network access to GitHub actions, Go downloads/modules, Docker Hub,
GitHub release downloads, and git.i3omb.com. For a Docker-in-Docker runner,
the Docker job expects the sibling service at docker:2376 with TLS enabled and
the client certificates mounted at /certs/client inside the job container.
The workflow sets DOCKER_HOST, DOCKER_TLS_VERIFY, and DOCKER_CERT_PATH
explicitly because act_runner service environment variables are not inherited
by job containers. If Buildx is absent, the workflow installs its pinned CLI
plugin before building. Artifact uploads use upload-artifact@v3 for
compatibility with Gitea's older artifact API.
The workflow requests a bind mount of /certs/client and maps docker to
host-gateway. The bind source is resolved inside the DinD daemon's filesystem,
where its client certificates exist. Job containers run inside that daemon;
they do not share the outer Compose service network.
The runner must also permit that bind source in its active configuration:
container:
valid_volumes:
- /certs/client
Run 41655's job 43221 confirmed the runner discarded the requested mount:
[/certs/client] is not a valid volume, will be ignored. Adding workflow
options does not override this runner allowlist. This occurs before registry
authentication or Buildx can run.
For the existing TrueNAS deployment, runner-compose.yaml
is a complete replacement Compose definition. Apply it to the existing
Compose project, preserving its volume names and data directories. It embeds
the allowlist using Compose configs.content (requires Compose 2.23.1+) and
sets CONFIG_FILE=/etc/act_runner/config.yaml, which the official entrypoint
passes to the daemon.
It reuses the existing /data/.runner registration, so no registration token
is needed. The old /data/config.yaml remains on disk but is no longer used.
Before applying, verify the registered runner and DinD certificates exist:
docker exec gitea-runner test -s /data/.runner
docker exec gitea-dind test -s /certs/client/ca.pem
After saving the replacement YAML as the existing project's Compose file:
docker compose config --quiet
docker compose up -d --no-deps --force-recreate act-runner
docker exec gitea-runner cat /etc/act_runner/config.yaml
The printed config must contain /certs/client under container.valid_volumes.
Then rerun CI. Its first Docker step verifies that all three TLS files are
readable and that docker version can reach the daemon before attempting
registry login. This repository change cannot update the running TrueNAS
container itself.
References: Gitea runner volume configuration, Docker bind mount source paths, and Compose inline configs.
Container publishing
After all binary jobs succeed, Buildx builds a non-root, scratch-based image for
linux/amd64 and linux/arm64. Cross-compilation runs on the builder's native
architecture, so no QEMU installation is needed. The image includes public CA
certificates for HTTPS connections to Ombi. Authentication and the Ombi URL are
supplied at runtime.
The image job creates a named Docker context containing the DinD TLS endpoint and certificate paths; Buildx cannot create a builder from TLS environment variables alone. Each CI attempt uses its own builder and removes it on exit.
Set these repository Actions secrets before publishing:
| Secret | Value |
|---|---|
REGISTRY_USERNAME |
Gitea username with permission to publish packages under the repository owner |
REGISTRY_TOKEN |
That user's personal access token with write:package scope |
The destination is git.i3omb.com/<repository-owner>/<repository-name> (lowercase),
which is git.i3omb.com/gronod/ombi-mcp for this repository.
- Default-branch pushes publish
latestandsha-<full-commit-sha>. - Version-tag pushes publish the exact tag (for example
v1.2.3) and the SHA tag. They do not replacelatest, including prerelease tags. - Pull requests, other branches, and manual runs build without logging in or pushing.
Gitea's job token is not used for registry login; see the documented package authorization limitation and container registry instructions. Publishing uploads the image; it does not restart any running deployment.
Running the image
For stdio, keep stdin open and do not allocate a TTY:
docker run --rm -i --env-file .env git.i3omb.com/gronod/ombi-mcp:latest
For HTTP/SSE:
docker run --rm --env-file .env -e MCP_TRANSPORT=sse \
-p 8080:8080 git.i3omb.com/gronod/ombi-mcp:latest
Build locally with docker build -t ombi-mcp .. CI passes the Go version from
go.mod as a build argument; when upgrading Go, also update the Dockerfile's
default GO_VERSION for local builds.