fix: Build the vantagectl image on its release tag, not on every push to main
vantagectl is a released tool, not a running service. An operator restoring a database should be able to name the version they ran, and ":latest, rebuilt whenever main moved" cannot be named after the fact. The image now builds in vantagectl-release.yml on a vantagectl/v* tag, tagged with that version as well as latest, with VERSION passed through so the binary inside reports the tag rather than "dev". server-deploy.yml no longer builds it and is back to seven images. The cost is that a shared/ fix reaches the image only at the next release rather than the next push to main. That is the intended trade and is written down in CLAUDE.md next to the trigger table.
This commit is contained in:
@@ -71,16 +71,22 @@ jobs:
|
||||
fi
|
||||
}
|
||||
|
||||
# The four Go images build from the repo root and COPY
|
||||
# shared/ plus their own directory, so shared/ rebuilds all
|
||||
# four. proto/ is in server's list as insurance: the
|
||||
# The three Go images here build from the repo root and
|
||||
# COPY shared/ plus their own directory, so shared/ rebuilds
|
||||
# all three. vantagectl also depends on shared/ but is NOT
|
||||
# built here: it is a released tool, so its image is built and
|
||||
# version-tagged by vantagectl-release.yml on a vantagectl/v*
|
||||
# tag. A shared/ change therefore reaches it at the next
|
||||
# release rather than on the next push to main, which is the
|
||||
# point — an operator restoring a database should be running a
|
||||
# version they can name, not whatever main built last night.
|
||||
# proto/ is in server's list as insurance: the
|
||||
# generated pb is committed under server/, but a proto change
|
||||
# that someone regenerates in the same push should not depend
|
||||
# on that ordering.
|
||||
flag server '^(server/|shared/|proto/|default_steps/|go\.work)'
|
||||
flag sitesvc '^(sitesvc/|shared/|go\.work)'
|
||||
flag admin '^(admin/|shared/|go\.work)'
|
||||
flag vantagectl '^(vantagectl/|shared/|go\.work)'
|
||||
|
||||
# The three Next images and the docs site use their own
|
||||
# directory as the build context, so nothing outside it can
|
||||
@@ -160,14 +166,6 @@ jobs:
|
||||
docker build -t "$IMAGE" -f admin/Dockerfile .
|
||||
docker push "$IMAGE"
|
||||
|
||||
- name: Build and push vantagectl image
|
||||
if: steps.changed.outputs.vantagectl == 'true'
|
||||
run: |
|
||||
IMAGE="${{ vars.DOCKER_HOST }}/${{ github.repository_owner }}/vantage/vantagectl:latest"
|
||||
# Root context: vantagectl depends on the shared module.
|
||||
docker build -t "$IMAGE" -f vantagectl/Dockerfile .
|
||||
docker push "$IMAGE"
|
||||
|
||||
- name: Build and push adminsite image
|
||||
if: steps.changed.outputs.adminsite == 'true'
|
||||
run: |
|
||||
|
||||
@@ -58,3 +58,54 @@ jobs:
|
||||
vantagectl/dist/vantagectl-darwin-arm64
|
||||
vantagectl/dist/vantagectl-windows-amd64.exe
|
||||
vantagectl/dist/checksums.txt
|
||||
|
||||
# The image is built here rather than in server-deploy.yml on every push to
|
||||
# main, because vantagectl is a released tool rather than a running service.
|
||||
# An operator restoring a database should be able to name the version they
|
||||
# ran; ":latest, rebuilt whenever main moved" cannot be named after the
|
||||
# fact. It is a separate job from the binaries because it needs a
|
||||
# docker-capable runner rather than a Go one, and it does not need the
|
||||
# binaries — the image builds from source in its own stage.
|
||||
image:
|
||||
runs-on: ubuntu-docker
|
||||
container: docker:dind
|
||||
steps:
|
||||
- name: Setup
|
||||
run: apk add --update nodejs npm git
|
||||
|
||||
- name: Checkout
|
||||
uses: actions/checkout@v4
|
||||
|
||||
- name: Extract version
|
||||
id: version
|
||||
run: |
|
||||
# v0.1.0 for the binary stamp, 0.1.0 for the image tag: a
|
||||
# leading v is conventional on a git tag and unconventional on
|
||||
# a container tag.
|
||||
VERSION="${GITHUB_REF_NAME#vantagectl/}"
|
||||
echo "VERSION=${VERSION}" >> $GITHUB_OUTPUT
|
||||
echo "IMAGE_TAG=${VERSION#v}" >> $GITHUB_OUTPUT
|
||||
|
||||
- name: Log in to registry
|
||||
run: |
|
||||
echo "${{ secrets.RELEASE_TOKEN }}" | \
|
||||
docker login ${{ vars.DOCKER_HOST }} \
|
||||
-u "${{ secrets.REGISTRY_USER }}" --password-stdin
|
||||
|
||||
- name: Build and push image
|
||||
env:
|
||||
VERSION: ${{ steps.version.outputs.VERSION }}
|
||||
IMAGE_TAG: ${{ steps.version.outputs.IMAGE_TAG }}
|
||||
run: |
|
||||
REPO="${{ vars.DOCKER_HOST }}/${{ github.repository_owner }}/vantage/vantagectl"
|
||||
# Root context: vantagectl depends on the shared module through
|
||||
# a replace directive, so the build needs shared/ alongside it.
|
||||
# VERSION is passed through so `vantagectl --version` inside the
|
||||
# image reports the tag it was built from rather than "dev".
|
||||
docker build \
|
||||
--build-arg VERSION="${VERSION}" \
|
||||
-t "${REPO}:${IMAGE_TAG}" \
|
||||
-t "${REPO}:latest" \
|
||||
-f vantagectl/Dockerfile .
|
||||
docker push "${REPO}:${IMAGE_TAG}"
|
||||
docker push "${REPO}:latest"
|
||||
|
||||
@@ -657,8 +657,11 @@ temporary directory before verifying its checksums, and a scratch image has no
|
||||
`server`, but here it would break every restore rather than only vulnerability
|
||||
scanning.
|
||||
|
||||
**`shared/` now fans out to four Go images** in `server-deploy.yml`:
|
||||
`server`, `sitesvc`, `admin` and `vantagectl` — see the CI section below.
|
||||
**`shared/` reaches four Go images, but only three of them from
|
||||
`server-deploy.yml`** (`server`, `sitesvc`, `admin`). The `vantagectl` image is
|
||||
built by `vantagectl-release.yml` on a `vantagectl/v*` tag instead, so a
|
||||
`shared/` change reaches it at the next release rather than the next push to
|
||||
main — see the CI section below.
|
||||
|
||||
### API tokens and OpenAPI
|
||||
|
||||
@@ -1318,7 +1321,7 @@ GOOS=linux GOARCH=amd64 go build \
|
||||
|
||||
### `server-deploy.yml` — triggered on every push to `main`
|
||||
|
||||
Builds and pushes eight images to the Gitea container registry: `server`, `web`, `site`, `sitesvc`, `admin`, `adminsite`, `docsite` and `vantagectl`.
|
||||
Builds and pushes seven images to the Gitea container registry: `server`, `web`, `site`, `sitesvc`, `admin`, `adminsite` and `docsite`. **`vantagectl` is deliberately not among them** — it is a released tool rather than a running service, and its image is version-tagged by `vantagectl-release.yml`.
|
||||
|
||||
Note that despite the name, **this workflow does not deploy** — it only builds and pushes. There is no SSH step. Rolling images out is a separate manual step on the host:
|
||||
|
||||
@@ -1334,13 +1337,16 @@ cd /opt/vantage && docker compose -f docker-compose.yml -f docker-compose.site.y
|
||||
| `server` | `server/`, `shared/`, `proto/`, `go.work` |
|
||||
| `admin` | `admin/`, `shared/`, `go.work` |
|
||||
| `sitesvc` | `sitesvc/`, `shared/`, `go.work` |
|
||||
| `vantagectl` | `vantagectl/`, `shared/`, `go.work` |
|
||||
| `web` · `site` · `adminsite` · `docsite` | their own directory only |
|
||||
|
||||
`shared/` fans out to **four** Go images (`server`, `sitesvc`, `admin`,
|
||||
`vantagectl`) because each of their Dockerfiles copies `shared/` from a root
|
||||
context — **if a fifth service ever imports `shared/`, add it to that list or
|
||||
it will ship stale**. A change to the workflow file rebuilds everything, since
|
||||
`shared/` fans out to **three** images here (`server`, `sitesvc`, `admin`)
|
||||
because each of their Dockerfiles copies `shared/` from a root context — **if a
|
||||
fourth service ever imports `shared/`, add it to that list or it will ship
|
||||
stale**. `vantagectl` also imports `shared/` and is the exception: it is built
|
||||
by `vantagectl-release.yml`, so a `shared/` fix reaches it only when someone
|
||||
cuts a `vantagectl/v*` tag. That is deliberate — an operator restoring a
|
||||
database should be running a version they can name — but it does mean a
|
||||
`shared/backup` fix is not live until it is released. A change to the workflow file rebuilds everything, since
|
||||
a build arg is baked into the image. So does anything that leaves no
|
||||
trustworthy base commit: a manual `workflow_dispatch`, a new branch, or a
|
||||
force-push whose old head is gone.
|
||||
|
||||
@@ -40,6 +40,13 @@ nobody can read.
|
||||
reconnect on their own, because `servers.agent_token_hash` — the thing an
|
||||
agent authenticates with — is itself in the backup.
|
||||
|
||||
:::note Pin the version
|
||||
The image is published on each `vantagectl/v*` release and tagged with that
|
||||
version; `:latest` also moves. Pin a version in anything scheduled. A restore
|
||||
is easier to reason about when you can say which build produced the archive and
|
||||
which one read it back.
|
||||
:::
|
||||
|
||||
## Taking a backup
|
||||
|
||||
The loose binary:
|
||||
@@ -59,7 +66,7 @@ docker run --rm \
|
||||
-e MONGO_DB=vantage \
|
||||
-e KEY_ENCRYPTION_KEY=<your 64-char hex key> \
|
||||
-v /backups:/backups \
|
||||
gitea.hostxtra.co.uk/mrhid6/vantage/vantagectl:latest backup --out /backups
|
||||
gitea.hostxtra.co.uk/mrhid6/vantage/vantagectl:0.1.0 backup --out /backups
|
||||
```
|
||||
|
||||
Kubernetes, as a scheduled `CronJob` the Helm chart can render for you:
|
||||
@@ -68,7 +75,7 @@ Kubernetes, as a scheduled `CronJob` the Helm chart can render for you:
|
||||
backup:
|
||||
enabled: true
|
||||
schedule: "0 2 * * *"
|
||||
image: "gitea.hostxtra.co.uk/mrhid6/vantage/vantagectl:latest"
|
||||
image: "gitea.hostxtra.co.uk/mrhid6/vantage/vantagectl:0.1.0"
|
||||
pvcName: "vantage-backups"
|
||||
```
|
||||
|
||||
|
||||
Reference in New Issue
Block a user