This document describes how staging Docker images are published from the alpha branch for
the Metaboost monorepo. Pre-release tags use X.Y.Z-staging.N and a floating :staging
tag so the same build can be pinned from multiple non-prod clusters (e.g. alpha and beta) via
GitOps.
| Name | Meaning |
|---|---|
Git branch alpha |
Triggers the publish workflow; release-candidate line from develop. |
X.Y.Z-staging.N / :staging |
Image tags (SemVer prerelease + floating tag). Not a cluster or namespace name. |
GitOps metaboost-alpha (example) |
Environment folder/namespace (alpha, beta, prod, …). Independent of the word “staging” in image tags. |
Same X.Y.Z-staging.N stream can pin alpha and beta overlays with different GitOps commits.
The alpha branch is the release-candidate line. Default branch remains develop.
When you merge from develop into alpha (or push directly to alpha), the Publish staging
(alpha branch) GitHub Action runs: it validates the repo (audit, build, lint, type-check), builds
and pushes Docker images to GitHub Container Registry (GHCR), verifies tags, and creates a matching
Git tag on the workflow commit.
No Kubernetes manifests are applied from this repo. Clusters consume images and overlays from your
GitOps repository (e.g. Argo CD Application targetRevision, Kustomize newTag). After each
publish, update those pins in the GitOps repo (PR, automation in that repo, or manual commit)—this
Metaboost workflow does not push to other repositories.
Step-by-step GitOps file list: METABOOST-PUBLISH-GITOPS-BUMP-CHECKLIST.md.
-
Sync develop to alpha – Keep
alphaas a mirror ofdevelop:./scripts/publish/sync-develop-to-alpha.sh
If your branch protection does not allow direct push to
alpha, open a PR fromdeveloptoalphainstead. -
Merge to alpha – Open a PR from
developintoalpha(or push toalpha). The workflow .github/workflows/publish-alpha.yml runs on push toalpha. -
Manual run – In GitHub: Actions → Publish staging (alpha branch) → Run workflow. Choose the
alphabranch. You can set Version override (e.g.0.1.2-staging.99); when set, that value is used and GHCR auto-increment is skipped.
When bumping version via scripts/publish/bump-version.sh, the script regenerates the lockfile
under Linux (Docker) before committing so CI gets the correct optional deps. If you add or change
dependencies by hand, run ./scripts/development/update-lockfile-linux.sh and commit the updated
package-lock.json. See Lockfile (Linux).
Six images are built from the Dockerfiles under infra/docker/local/:
- api – Metaboost API
- management-api – Metaboost management API
- web – Next.js web app
- web-sidecar – Runtime-config sidecar for the web app
- management-web – Next.js management web app
- management-web-sidecar – Runtime-config sidecar for the management web app
Each image is tagged with :staging (latest staging build from this pipeline) and an immutable
version tag X.Y.Z-staging.N derived from root package.json base version (prerelease stripped)
plus an auto-incremented N from existing GHCR tags for that base. Pin clusters with the version
tag; use :staging only when you intentionally want “latest staging.”
On first publish where GHCR has no package yet, tag discovery 404 bootstraps at X.Y.Z-staging.0.
The pipeline publishes -staging.N and :staging as described above. GHCR may also list other tags (e.g. from earlier workflows); use the immutable version tag when you need a reproducible pin.
Replace OWNER and REPO with your GitHub org/user and repo name (e.g. myorg/metaboost).
# Pull by staging tag (latest staging build from alpha branch pipeline)
docker pull ghcr.io/OWNER/REPO/api:staging
docker pull ghcr.io/OWNER/REPO/management-api:staging
docker pull ghcr.io/OWNER/REPO/web:staging
docker pull ghcr.io/OWNER/REPO/web-sidecar:staging
docker pull ghcr.io/OWNER/REPO/management-web:staging
docker pull ghcr.io/OWNER/REPO/management-web-sidecar:staging
# Or by version tag (immutable)
docker pull ghcr.io/OWNER/REPO/api:0.1.2-staging.2
docker pull ghcr.io/OWNER/REPO/management-api:0.1.2-staging.2
docker pull ghcr.io/OWNER/REPO/web:0.1.2-staging.2
docker pull ghcr.io/OWNER/REPO/web-sidecar:0.1.2-staging.2
docker pull ghcr.io/OWNER/REPO/management-web:0.1.2-staging.2
docker pull ghcr.io/OWNER/REPO/management-web-sidecar:0.1.2-staging.2For private repos, authenticate to GHCR first (e.g.
echo $GITHUB_TOKEN | docker login ghcr.io -u USERNAME --password-stdin).
- Workflow: .github/workflows/publish-alpha.yml — runs
on push to
alphaorworkflow_dispatch. Display name: Publish staging (alpha branch).
The workflow supports two tokens for GHCR tag discovery:
GHCR_REGISTRY_TOKEN(recommended): repository secret withpackages:readGITHUB_TOKEN(fallback): built-in token ifGHCR_REGISTRY_TOKENis not set
If GHCR tag listing fails, the workflow exits with guidance or use Version override on manual dispatch.
Image push uses GITHUB_TOKEN with packages:write in the publish job.
The workflow behavior for GHCR tag discovery is:
200: normal tag discovery and increment behavior404: first-run bootstrap, starts atX.Y.Z-staging.0401/403: auth or package permission issue (fails with guidance)- Other status codes: unexpected, fail fast
- This pipeline is publish-first; it does not apply Kubernetes manifests in-cluster or modify a GitOps repo.
infra/k8s/alpha/is scaffold-only; remote overlays live in your GitOps repo.- Prefer immutable
X.Y.Z-staging.N(and matching Git tag on this repo) in overlays;:stagingonly when you want rolling “latest staging.”
- Tag discovery returns
404: Expected on first publish; bootstraps atX.Y.Z-staging.0. - Tag discovery returns
401or403: CheckGHCR_REGISTRY_TOKENand org package policy. - Emergency republish: Manual dispatch with
version_override.