excalidraw: migrate image build to GHA -> private ghcr (ADR-0002)

The image was still built by hand and pushed to DockerHub (v1..v4),
predating the all-builds-off-infra doctrine; Viktor chose to move it
onto the standard pipeline while shipping the export/rename feature
rather than keep the manual flow.

Mirrors the k8s-portal pattern: .github/workflows/build-excalidraw.yml
(go test + buildx linux/amd64, pushes ghcr latest+sha), excalidraw ns
added to the Kyverno ghcr-credentials allowlist (package is PRIVATE),
deployment now pins ghcr :latest with pullPolicy Always + pull secret,
Keel force/match-tag/5m annotations seed the metadata (live values win
via ignore_changes). DockerHub viktorbarzin/excalidraw-library:v4 stays
frozen as the rollback image. Docs: ci-cd.md + .claude/CLAUDE.md image
lists updated (also backfilled the missing k8s-portal rows in ci-cd.md).

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
Viktor Barzin 2026-07-02 14:29:23 +00:00
parent 1cbc1e962b
commit 8fc657f431
5 changed files with 77 additions and 7 deletions

View file

@ -10,7 +10,7 @@ resource "kubernetes_namespace" "excalidraw" {
name = "excalidraw"
labels = {
"istio-injection" : "disabled"
tier = local.tiers.aux
tier = local.tiers.aux
"keel.sh/enrolled" = "true"
}
}
@ -45,6 +45,15 @@ resource "kubernetes_deployment" "excalidraw" {
app = "excalidraw"
tier = local.tiers.aux
}
# Keel rolls new ghcr:latest digests (k8s-portal pattern). Values here are
# recreate-correct seeds only the keys are in ignore_changes below, so
# the live annotations win on an existing deployment.
annotations = {
"keel.sh/policy" = "force"
"keel.sh/trigger" = "poll"
"keel.sh/match-tag" = "true"
"keel.sh/pollSchedule" = "@every 5m"
}
}
spec {
replicas = 1
@ -67,9 +76,19 @@ resource "kubernetes_deployment" "excalidraw" {
}
}
spec {
# GHCR pull secret: the ghcr-credentials Secret in this namespace is
# cloned in by the kyverno stack's sync-ghcr-credentials ClusterPolicy
# (allowlisted private-ghcr namespaces only ADR-0002). Source of
# truth: stacks/kyverno/modules/kyverno/ghcr-credentials.tf.
image_pull_secrets {
name = "ghcr-credentials"
}
container {
image = "viktorbarzin/excalidraw-library:v4"
image_pull_policy = "IfNotPresent"
# ADR-0002: GHA-built (.github/workflows/build-excalidraw.yml),
# PRIVATE ghcr; Keel rolls new :latest digests. DockerHub
# viktorbarzin/excalidraw-library:v4 is the frozen rollback image.
image = "ghcr.io/viktorbarzin/excalidraw-library:latest"
image_pull_policy = "Always"
name = "excalidraw"
port {
container_port = 8080
@ -107,7 +126,7 @@ resource "kubernetes_deployment" "excalidraw" {
}
lifecycle {
ignore_changes = [
spec[0].template[0].spec[0].dns_config, # KYVERNO_LIFECYCLE_V1
spec[0].template[0].spec[0].dns_config, # KYVERNO_LIFECYCLE_V1
spec[0].template[0].spec[0].container[0].image, # KEEL_IGNORE_IMAGE Keel manages tag updates
metadata[0].annotations["keel.sh/policy"],
metadata[0].annotations["keel.sh/trigger"],