Skip to content

Artifact Registry

Two Docker repos, both in asia-east1, both managed by infrastructure/gcp/registry.tf. Argo CD Image Updater pulls metadata from these to detect new tags.

Repos

Repo Format Location Purpose
tomoda-dev-repo DOCKER asia-east1 Main-branch builds — dev environment
tomoda-prod-repo DOCKER asia-east1 Semver-tagged builds — prod environment

Full URIs:

asia-east1-docker.pkg.dev/development-485000/tomoda-dev-repo/<image>:<tag>
asia-east1-docker.pkg.dev/development-485000/tomoda-prod-repo/<image>:<tag>

The image names inside each repo (e.g. tomoda-backend, tomoda-frontend) are determined by the build YAMLs in the tomoda repo, not by Terraform.

Tag conventions

  • Dev repo: :latest is overwritten on every successful main-branch build (set via the TAG_NAME = "latest" substitution in cloudbuild.tf). The previous digest is still reachable by SHA, but there is no immutable name for it.
  • Prod repo: the build YAML reads ${TAG_NAME} from the substitution, which release triggers leave unset → the YAML falls back to the Git tag (e.g. v0.4.2). Each prod image is therefore tagged exactly once and never overwritten.

Retention & cleanup

Both repos have native Artifact Registry cleanup_policies configured in registry.tf. Cleanup runs asynchronously on GCP's schedule.

Dev repo (tomoda-dev-repo) — aggressive

Policy Action Condition
delete-untagged-7d DELETE Untagged images older than 7 days
delete-tagged-30d DELETE Tagged images older than 30 days
keep-recent-10 KEEP Last 10 tagged versions (any age)

KEEP is evaluated before DELETE, so the 10-version floor protects recent images that would otherwise hit the 30-day window.

Prod repo (tomoda-prod-repo) — conservative

Policy Action Condition
delete-untagged-14d DELETE Untagged images older than 14 days
delete-tagged-180d DELETE Tagged images older than 180 days
keep-recent-20 KEEP Last 20 tagged versions (any age)

Prod is sized to keep rollback targets viable for ~6 months while still bounding storage growth.

Manual cleanup

If you ever need to short-circuit a policy (e.g. delete a specific vulnerable image immediately), use the console or:

gcloud artifacts docker images delete \
  asia-east1-docker.pkg.dev/development-485000/tomoda-prod-repo/<image>@<digest>

Who can read & write

Authoritative bindings live in the IAM Terraform files; see IAM Overview for the full table.

Principal Role What it enables
cloudbuild-worker-sa@… roles/artifactregistry.writer (project-level, cloudbuild_iam.tf) Cloud Build can push image layers to both repos
GKE default compute SA (…-compute@developer.gserviceaccount.com) roles/artifactregistry.reader (project-level, gke_iam.tf) Cluster nodes can pull images
argocd-image-updater-sa@… roles/artifactregistry.reader (project-level, image_updater_iam.tf) Argo CD Image Updater can list tags

All three roles are granted at the project level rather than per-repo, so adding a third repo later does not require new bindings.

Argo CD Image Updater integration

Argo CD Image Updater runs in the argocd namespace as the KSA argocd-image-updater. It impersonates argocd-image-updater-sa@${project_id}.iam.gserviceaccount.com via Workload Identity (binding in image_updater_iam.tf) and uses that SA's artifactregistry.reader role to:

  1. List tags on a watched image (e.g. …/tomoda-dev-repo/tomoda-backend).
  2. Compare against the digest currently referenced in the Argo CD Application manifest.
  3. If newer, write a Git commit updating the manifest, which Argo CD then reconciles.

This is read-only metadata access — the updater never pushes images, only reads tags. The dev/prod split between which application watches which repo is configured per Argo CD Application via annotations, not via Terraform.

flowchart LR
    CB[Cloud Build] -->|push| AR[(Artifact Registry)]
    IU[Argo CD Image Updater<br/>KSA: argocd-image-updater]
    IU -. impersonates .-> SA[argocd-image-updater-sa@…]
    SA -->|artifactregistry.reader| AR
    IU -->|git commit| REPO[(GitOps repo)]
    REPO --> ARGO[Argo CD]
    ARGO --> GKE[GKE workloads]

See Argo CD for the install and Cloud Build for the producer side.