4.1 KiB
id, title, sidebar_label
| id | title | sidebar_label |
|---|---|---|
| ci-cd | CI/CD | CI/CD |
Two Gitea Actions workflows: one releases agents, one builds images.
Agent releases
Triggered by an agent/v* tag.
git tag agent/v1.0.0 && git push origin agent/v1.0.0
Builds linux/amd64, linux/arm64 and windows/amd64, writes checksums.txt
and creates a Gitea release. A second job on Windows packages the WiX MSI.
The install and update scripts read the newest agent/v* release from the Gitea
API, so tagging is what makes a new agent available to every install.
Image builds
Triggered on every push to main. Builds and pushes seven images: server,
web, site, sitesvc, admin, adminsite and docsite.
:::warning Despite the name, this workflow does not deploy There is no SSH step. Rolling images out is a manual step on the host:
cd /opt/vantage && \
docker compose -f docker-compose.yml -f docker-compose.site.yml pull && \
docker compose -f docker-compose.yml -f docker-compose.site.yml up -d --remove-orphans
:::
Each image rebuilds only when its own inputs change
A git diff against the previous head decides. That is why the checkout uses
fetch-depth: 0 — a shallow clone has one commit and nothing to diff against.
| Image | Rebuilds when |
|---|---|
server |
server/, shared/, proto/, go.work |
admin |
admin/, shared/, go.work |
sitesvc |
sitesvc/, shared/, go.work |
web · site · adminsite · docsite |
their own directory only |
shared/ fans out to all three Go images because each of their Dockerfiles
copies it from a root context. If a fourth service ever imports shared/, it
must be added to that list or it will ship stale.
Everything rebuilds when there is no trustworthy base commit to diff against: a
manual workflow_dispatch, a new branch, or a force-push whose old head is
gone. Changing the workflow file itself also rebuilds everything, since a build
argument is baked into each image.
The gap: repository variables
:::danger Editing a repository variable pushes no commit, so nothing rebuilds
Values like ADMIN_API_URL, HQ_URL, ADMIN_ENV, PADDLE_ENV,
PADDLE_CLIENT_TOKEN, DOCS_URL and DOCS_BASE_URL are baked into images at
build time. After editing one, run the workflow manually — that is what
workflow_dispatch is for.
The symptom is a frontend that keeps using the old value with no error anywhere, which is a long afternoon if you do not know about this. :::
The same applies to base images: a service nobody touches stops being rebuilt on newer base layers. A periodic manual run covers it.
Secrets and variables
| Name | Type | Purpose |
|---|---|---|
RELEASE_TOKEN |
Secret | Gitea API token, write:release |
REGISTRY_USER / REGISTRY_PASSWORD |
Secret | Registry push credentials |
PADDLE_API_KEY |
Secret | Read by admin at runtime |
PADDLE_WEBHOOK_SECRET |
Secret | Webhook signature verification |
GITEA_HOST / DOCKER_HOST |
Variable | Hosts used in tags and URLs |
HQ_URL |
Variable | Baked into web; empty on self-hosted |
SITE_API_URL / SITE_CONTACT_EMAIL |
Variable | Baked into site |
ADMIN_API_URL |
Variable | Baked into adminsite and site |
ADMIN_ENV |
Variable | Environment badge in the portal |
PADDLE_ENV |
Variable | Baked into adminsite, read by admin. Must match on both sides |
PADDLE_CLIENT_TOKEN |
Variable | Browser Paddle token for checkout |
DOCS_URL / DOCS_BASE_URL |
Variable | Baked into docsite |
Anything marked "browser-reachable" must be an origin a browser can actually resolve — not an internal service name. Get it wrong and every request fails at runtime with a not-connected panel rather than at build time.
The documentation site
docsite/ builds to static files and is served by nginx under /docs on the
marketing host, routed by its own proxy location.
DOCS_BASE_URL has to agree with three things at once: that proxy location, the
directory the runtime image serves from, and the value baked into the build. When
they disagree the page loads and every stylesheet and script 404s.