Skip to content

Migrate codeforafrica builds to Docker Bake - #1512

Merged
kelvinkipruto merged 2 commits into
mainfrom
feat/codeforafrica-docker-bake
Aug 25, 2026
Merged

Migrate codeforafrica builds to Docker Bake#1512
kelvinkipruto merged 2 commits into
mainfrom
feat/codeforafrica-docker-bake

Conversation

@kelvinkipruto

Copy link
Copy Markdown
Contributor

Description

Migrate codeforafrica from the legacy shared root Dockerfile to the repository's per-app Dockerfile and Docker Bake build architecture, following the same pattern already established for charterafrica/climatemappedafrica/pesayetu/roboshield/techlabblog/trustlab.

Why

Docker builds against the legacy shared Dockerfile are slow and have repeatedly broken in ways unrelated to the app itself (see #1507, #1509). Moving codeforafrica onto the turbo-prune-based Bake architecture keeps its build isolated, cacheable, and consistent with the other migrated apps.

codeforafrica uses a custom Express + Payload server (server.ts, compiled to dist/server.js) that connects to MongoDB via payload.init() before next build runs, so — like climatemappedafrica/charterafrica — this build genuinely needs a reachable database, not just a well-formed connection string.

Unlike charterafrica, codeforafrica deploys to real DEV and PROD Dokku apps today, so this migration is deliberately conservative about preserving exact existing behavior rather than cleaning anything up:

  1. DockerHub repository name. The bake target tags images as codeforafrica/codeforafrica-ui (not codeforafrica/codeforafrica, the naming every other migrated app uses) because the live Dokku apps already pull images by that exact name.
  2. DEV/PROD each get their own build, matching roboshield's precedent — codeforafrica bakes an environment-specific NEXT_PUBLIC_APP_URL into the client bundle, so a single build-once-promote wouldn't work.
  3. The pre-existing DEV/PROD secret split is preserved exactly. DEV uses CODEFORAFRICA_MONGO_URL with the Dokku app name appended (/codeforafrica-ui), matching the pre-bake DEV workflow's own string concatenation. PROD uses a different secret, CODEFORAFRICA_MONGODB_URL, already a full connection string with no appending. These are two distinct GitHub Secrets in the pre-bake workflows today — this PR does not merge or rename them, just moves the same two references into the new pipeline.
  4. PROD's NEXT_PUBLIC_APP_URL is left as https://cfa.dev.codeforafrica.org — yes, a .dev. domain for the production build — because that's what the pre-bake PROD workflow already bakes in. Whether that's a bug is a separate, pre-existing question outside this migration's scope.

What changed

codeforafrica Docker Bake migration

  • Add a pruned, multi-stage Dockerfile at docker/apps/codeforafrica/Dockerfile. Like climatemappedafrica/charterafrica, this app doesn't use Next.js output: "standalone", so the runner stage copies the full node_modules/.next folder rather than a pruned standalone bundle, plus migrations/.
  • Add the codeforafrica target to docker-bake.hcl and the shared apps group, inheriting _payload-app-runner directly — its secret names (PAYLOAD_SECRET, and now DATABASE_URL) already match the shared convention, so no app-specific secret list is needed (unlike charterafrica).
  • NEXT_PUBLIC_APP_NAME and NEXT_PUBLIC_APP_LOGO_URL are public config values that happen to already be stored as GitHub Secrets; they're passed through as bake --set overrides from _build-codeforafrica.yml rather than touching the shared _bake-and-push.yml.
  • Standardize on DATABASE_URL for the Payload DB connection instead of MONGODB_URL, matching the other migrated apps, in payload.config.ts.
  • Reuse the published ui-builder-base/ui-runner-base images in CI.
  • Switch local make codeforafrica and Compose usage to the Bake-built image.
  • Mark codeforafrica migrated in docker/README.md.
  • Leave the legacy root Dockerfile stage and codeforafrica-deploy-*.yml workflows untouched for now, matching the rollback-safety precedent from the other migrations — to be disabled once this pipeline is validated in production.

CI/CD

  • Add a reusable Bake workflow (_build-codeforafrica.yml) and a new orchestration workflow (codeforafrica.yml): DEV builds and deploys on every push (real Dokku app at ui-1.dev.codeforafrica.org), PROD builds and deploys only on a package.json version bump (real Dokku app at ui-2.prod.codeforafrica.org) — mirroring roboshield's two-build DEV/PROD split.
  • Add codeforafrica to the pr-build.yml image-validation workflow and scripts/pr-build-targets.mjs's target detection. PR builds use the real CODEFORAFRICA_MONGO_URL secret (mapped to DATABASE_URL, same DEV-style app-name suffix) rather than a dummy value, since the build needs a reachable database to succeed.
  • No new GitHub secrets required — existing CODEFORAFRICA_MONGO_URL/CODEFORAFRICA_MONGODB_URL/CODEFORAFRICA_PAYLOAD_SECRET/CODEFORAFRICA_SENTRY_PROJECT/NEXT_PUBLIC_CODEFORAFRICA_APP_NAME/NEXT_PUBLIC_CODEFORAFRICA_APP_LOGO_URL carry over, just remapped to the Bake secret names.

Validation

  • docker buildx bake codeforafrica against a real local MongoDB instance — full turbo prune → install → next build (compile, lint, static export) → payload build all pass.
  • docker run smoke test — the built image boots, Payload connects, Next.js starts, and both / and /admin return HTTP 200.
  • pnpm test:scripts — all pr-build-targets detection tests pass, including the updated codeforafrica cases.
  • ESLint passes on all changed files.

Type of change

  • New feature (non-breaking change which adds functionality)

Screenshots

N/A

Checklist

  • My code follows the style guidelines of this project
  • I have performed a self-review of my own code
  • I have commented my code, particularly in hard-to-understand areas
  • I have made corresponding changes to the documentation

Matches the naming already used by roboshield/trustlab/climatemappedafrica/
charterafrica.
Adds docker/apps/codeforafrica/Dockerfile and a bake target following the
climatemappedafrica/charterafrica/roboshield/trustlab pattern: turbo-prune
based multi-stage build, secrets mounted via BuildKit instead of build args,
and CI wired through the shared _bake-and-push.yml reusable workflow.

Unlike charterafrica, codeforafrica deploys to real DEV and PROD Dokku apps
today, so this preserves the pre-bake pipeline's DEV/PROD split exactly:
each environment gets its own build (matching roboshield's precedent, since
codeforafrica bakes an environment-specific NEXT_PUBLIC_APP_URL into the
client bundle) and its own Mongo secret (CODEFORAFRICA_MONGO_URL for DEV,
with the Dokku app name appended per the pre-bake workflow's convention;
CODEFORAFRICA_MONGODB_URL for PROD, already a full connection string). The
DockerHub repository name (codeforafrica/codeforafrica-ui) is preserved as
well, since the live Dokku apps already pull images by that exact name.

NEXT_PUBLIC_APP_NAME and NEXT_PUBLIC_APP_LOGO_URL are public config values
that happen to be stored as GitHub Secrets already; they're passed through
as bake --set overrides from _build-codeforafrica.yml rather than modifying
the shared _bake-and-push.yml, keeping this app-specific quirk contained.

PROD's NEXT_PUBLIC_APP_URL is left pointing at the same (unusual, .dev.)
domain the pre-bake PROD workflow already used — not a regression, and not
this migration's job to fix.
@kelvinkipruto
kelvinkipruto force-pushed the feat/codeforafrica-docker-bake branch from 7dd2443 to 014bd1e Compare August 25, 2026 17:39
@kelvinkipruto
kelvinkipruto added this pull request to the merge queue Aug 25, 2026
Merged via the queue into main with commit e1c789b Aug 25, 2026
6 checks passed
@kelvinkipruto
kelvinkipruto deleted the feat/codeforafrica-docker-bake branch August 25, 2026 17:45
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants