Files
gronod 6d47ec4e48
Build and publish / Test and build (darwin) (push) Successful in 1m25s
Build and publish / Test and build (windows) (push) Successful in 3m6s
Build and publish / Test and build (linux) (push) Successful in 3m59s
Build and publish / Build and publish Docker image (push) Successful in 2m41s
Validate Docker daemon access before CI steps
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
2026-09-18 23:20:51 +01:00

138 lines
6.2 KiB
Markdown

# 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:
```yaml
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](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:
```sh
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:
```sh
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](https://docs.gitea.com/runner/2/configuration/#container),
[Docker bind mount source paths](https://docs.docker.com/engine/storage/bind-mounts/),
and [Compose inline configs](https://docs.docker.com/reference/compose-file/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 `latest` and `sha-<full-commit-sha>`.
- Version-tag pushes publish the exact tag (for example `v1.2.3`) and the SHA tag.
They do not replace `latest`, 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](https://docs.gitea.com/usage/actions/comparison/#package-repository-authorization)
and [container registry instructions](https://docs.gitea.com/usage/packages/container/).
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:
```sh
docker run --rm -i --env-file .env git.i3omb.com/gronod/ombi-mcp:latest
```
For HTTP/SSE:
```sh
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.