Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
80 changes: 80 additions & 0 deletions .github/workflows/_build-codeforafrica.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,80 @@
name: Reusable Build | codeforAFRICA

on:
workflow_call:
inputs:
tag:
required: true
type: string
description: "Image tag to build or push"
push:
required: true
type: boolean
description: "Whether to push the built image to the registry"
base_tag:
required: true
type: string
description: "Published base image tag to build from"
app_url:
required: true
type: string
description: "NEXT_PUBLIC_APP_URL baked into the client bundle (public, not a secret)"
sentry_environment:
required: true
type: string
description: "Sentry environment baked into the app"
set:
required: false
type: string
default: ""
description: "Additional bake --set overrides"
secrets:
DOCKER_HUB_USERNAME:
required: false
DOCKER_HUB_ACCESS_TOKEN:
required: false
DATABASE_URL:
required: false
PAYLOAD_SECRET:
required: false
SENTRY_AUTH_TOKEN:
required: false
SENTRY_ORG:
required: false
SENTRY_PROJECT:
required: false
# Not genuine secrets (public app name/logo, inlined into the client
# bundle by design) but stored as GitHub Secrets today — plumbed
# through here rather than as bake Variables to avoid a GitHub
# Variable migration, matching NEXT_PUBLIC_SENTRY_DSN's precedent.
NEXT_PUBLIC_APP_NAME:
required: false
NEXT_PUBLIC_APP_LOGO_URL:
required: false

jobs:
build:
permissions:
actions: read
contents: read
uses: ./.github/workflows/_bake-and-push.yml
with:
target: codeforafrica
target_os: '["ubuntu-24.04-arm"]'
base_tag: ${{ inputs.base_tag }}
tag: ${{ inputs.tag }}
push: ${{ inputs.push }}
set: |
codeforafrica.args.NEXT_PUBLIC_APP_URL=${{ inputs.app_url }}
codeforafrica.args.SENTRY_ENVIRONMENT=${{ inputs.sentry_environment }}
codeforafrica.args.NEXT_PUBLIC_APP_NAME=${{ secrets.NEXT_PUBLIC_APP_NAME }}
codeforafrica.args.NEXT_PUBLIC_APP_LOGO_URL=${{ secrets.NEXT_PUBLIC_APP_LOGO_URL }}
${{ inputs.set }}
secrets:
DOCKER_HUB_USERNAME: ${{ secrets.DOCKER_HUB_USERNAME }}
DOCKER_HUB_ACCESS_TOKEN: ${{ secrets.DOCKER_HUB_ACCESS_TOKEN }}
DATABASE_URL: ${{ secrets.DATABASE_URL }}
PAYLOAD_SECRET: ${{ secrets.PAYLOAD_SECRET }}
SENTRY_AUTH_TOKEN: ${{ secrets.SENTRY_AUTH_TOKEN }}
SENTRY_ORG: ${{ secrets.SENTRY_ORG }}
SENTRY_PROJECT: ${{ secrets.SENTRY_PROJECT }}
138 changes: 138 additions & 0 deletions .github/workflows/codeforafrica.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,138 @@
name: codeforAFRICA

on:
push:
branches:
- main
paths:
- "apps/codeforafrica/**"
- "docker/apps/codeforafrica/**"
- "docker-bake.hcl"
- ".github/workflows/_bake-and-push.yml"
- ".github/workflows/_build-codeforafrica.yml"
- ".github/workflows/codeforafrica.yml"

permissions:
actions: read
contents: read

concurrency:
group: "${{ github.workflow }} @ ${{ github.ref }}"
cancel-in-progress: true

jobs:
# Checks whether apps/codeforafrica/package.json has a version bump.
# The prod deploy is gated on this: every push triggers a dev build+deploy,
# only a version bump triggers a prod build+deploy.
version-check:
runs-on: ${{ matrix.os }}
strategy:
matrix:
os: [ubuntu-24.04]
permissions:
contents: read
outputs:
changed: ${{ steps.check.outputs.changed }}
version: ${{ steps.check.outputs.version }}
steps:
- uses: actions/checkout@v6
with:
fetch-depth: 0

- uses: actions/setup-node@v6
with:
node-version-file: "package.json"

- name: Check if version is bumped
id: check
uses: EndBug/version-check@v3
with:
diff-search: true
file-name: apps/codeforafrica/package.json

# Builds the DEV image and pushes it to DockerHub on every push. Matches
# the pre-bake workflow's DEV/PROD split: each is a separate build using
# its own canonical URL and its own Mongo secret.
#
# Required GitHub Secrets:
# CODEFORAFRICA_MONGO_URL, CODEFORAFRICA_PAYLOAD_SECRET,
# CODEFORAFRICA_SENTRY_PROJECT, NEXT_PUBLIC_CODEFORAFRICA_APP_NAME,
# NEXT_PUBLIC_CODEFORAFRICA_APP_LOGO_URL, SENTRY_AUTH_TOKEN, SENTRY_ORG,
# UI_BASE_TAG (var)
build-dev:
permissions:
actions: read
contents: read
uses: ./.github/workflows/_build-codeforafrica.yml
with:
base_tag: ${{ vars.UI_BASE_TAG }}
tag: ${{ github.sha }}
push: true
app_url: "https://codeforafrica-ui.dev.codeforafrica.org"
sentry_environment: development
secrets:
DOCKER_HUB_USERNAME: ${{ secrets.DOCKER_HUB_USERNAME }}
DOCKER_HUB_ACCESS_TOKEN: ${{ secrets.DOCKER_HUB_ACCESS_TOKEN }}
# The pre-bake DEV workflow appends the Dokku app name to this secret
# (a shared Mongo host, disambiguated by database name per app).
DATABASE_URL: "${{ secrets.CODEFORAFRICA_MONGO_URL }}/codeforafrica-ui"
PAYLOAD_SECRET: ${{ secrets.CODEFORAFRICA_PAYLOAD_SECRET }}
SENTRY_AUTH_TOKEN: ${{ secrets.SENTRY_AUTH_TOKEN }}
SENTRY_ORG: ${{ secrets.SENTRY_ORG }}
SENTRY_PROJECT: ${{ secrets.CODEFORAFRICA_SENTRY_PROJECT }}
NEXT_PUBLIC_APP_NAME: ${{ secrets.NEXT_PUBLIC_CODEFORAFRICA_APP_NAME }}
NEXT_PUBLIC_APP_LOGO_URL: ${{ secrets.NEXT_PUBLIC_CODEFORAFRICA_APP_LOGO_URL }}

deploy-dev:
needs: build-dev
permissions: {}
uses: ./.github/workflows/push-to-dokku.yml
with:
git_remote_url: "ssh://azureuser@ui-1.dev.codeforafrica.org/codeforafrica-ui"
deploy_docker_image: "codeforafrica/codeforafrica-ui:${{ github.sha }}"
secrets:
SSH_PRIVATE_KEY: ${{ secrets.SSH_PRIVATE_KEY }}

# Builds the PROD image only when the package.json version is bumped, using
# the PROD canonical URL and the semver tag.
build-prod:
needs: version-check
if: needs.version-check.outputs.changed == 'true'
permissions:
actions: read
contents: read
uses: ./.github/workflows/_build-codeforafrica.yml
with:
base_tag: ${{ vars.UI_BASE_TAG }}
tag: ${{ needs.version-check.outputs.version }}
push: true
# Matches the pre-bake PROD workflow's existing (if unusual) value —
# not changed here since that's a pre-existing app config question,
# not something this build-tooling migration should alter.
app_url: "https://cfa.dev.codeforafrica.org"
sentry_environment: production
set: |
codeforafrica.tags+=codeforafrica/codeforafrica-ui:latest
secrets:
DOCKER_HUB_USERNAME: ${{ secrets.DOCKER_HUB_USERNAME }}
DOCKER_HUB_ACCESS_TOKEN: ${{ secrets.DOCKER_HUB_ACCESS_TOKEN }}
# PROD uses a distinct secret from DEV — a dedicated, full connection
# string (no app-name path appended), matching the pre-bake workflow.
DATABASE_URL: ${{ secrets.CODEFORAFRICA_MONGODB_URL }}
PAYLOAD_SECRET: ${{ secrets.CODEFORAFRICA_PAYLOAD_SECRET }}
SENTRY_AUTH_TOKEN: ${{ secrets.SENTRY_AUTH_TOKEN }}
SENTRY_ORG: ${{ secrets.SENTRY_ORG }}
SENTRY_PROJECT: ${{ secrets.CODEFORAFRICA_SENTRY_PROJECT }}
NEXT_PUBLIC_APP_NAME: ${{ secrets.NEXT_PUBLIC_CODEFORAFRICA_APP_NAME }}
NEXT_PUBLIC_APP_LOGO_URL: ${{ secrets.NEXT_PUBLIC_CODEFORAFRICA_APP_LOGO_URL }}

deploy-prod:
needs: [version-check, build-prod]
if: needs.version-check.outputs.changed == 'true'
permissions: {}
uses: ./.github/workflows/push-to-dokku.yml
with:
git_remote_url: "ssh://dokku@ui-2.prod.codeforafrica.org/codeforafrica-ui"
deploy_docker_image: "codeforafrica/codeforafrica-ui:${{ needs.version-check.outputs.version }}"
secrets:
SSH_PRIVATE_KEY: ${{ secrets.SSH_PRIVATE_KEY }}
31 changes: 31 additions & 0 deletions .github/workflows/pr-build.yml
Original file line number Diff line number Diff line change
Expand Up @@ -5,11 +5,13 @@ on:
types: [opened, synchronize, reopened, ready_for_review]
paths:
- "apps/climatemappedafrica/**"
- "apps/codeforafrica/**"
- "apps/pesayetu/**"
- "apps/roboshield/**"
- "apps/techlabblog/**"
- "apps/trustlab/**"
- "docker/apps/climatemappedafrica/**"
- "docker/apps/codeforafrica/**"
- "docker/apps/pesayetu/**"
- "docker/apps/roboshield/**"
- "docker/apps/techlabblog/**"
Expand All @@ -25,11 +27,13 @@ on:
- "scripts/pr-build-targets.test.mjs"
- ".github/workflows/_bake-and-push.yml"
- ".github/workflows/_build-climatemappedafrica.yml"
- ".github/workflows/_build-codeforafrica.yml"
- ".github/workflows/_build-pesayetu.yml"
- ".github/workflows/_build-roboshield.yml"
- ".github/workflows/_build-techlabblog.yml"
- ".github/workflows/_build-trustlab.yml"
- ".github/workflows/climatemappedafrica.yml"
- ".github/workflows/codeforafrica.yml"
- ".github/workflows/pesayetu.yml"
- ".github/workflows/pr-build.yml"
- ".github/workflows/roboshield.yml"
Expand Down Expand Up @@ -123,6 +127,33 @@ jobs:
DATABASE_URL: ${{ secrets.CLIMATEMAPPEDAFRICA_MONGO_URL }}
PAYLOAD_SECRET: pr-build-unused

build-codeforafrica:
name: Build codeforafrica image
needs: affected
if: ${{ contains(fromJSON(needs.affected.outputs.targets), 'codeforafrica') }}
permissions:
actions: read
contents: read
uses: ./.github/workflows/_build-codeforafrica.yml
with:
base_tag: ${{ vars.UI_BASE_TAG }}
tag: pr-${{ github.event.pull_request.number }}-${{ github.sha }}
push: false
app_url: "http://localhost:3000"
sentry_environment: ci
secrets:
# The custom server connects to MongoDB via payload.init() before
# spawning `next build`, so — like the other Payload-backed migrated
# apps — PR builds need a genuinely reachable database, not a dummy
# value.
DATABASE_URL: "${{ secrets.CODEFORAFRICA_MONGO_URL }}/codeforafrica-ui"
PAYLOAD_SECRET: pr-build-unused
SENTRY_AUTH_TOKEN: pr-build-unused
SENTRY_ORG: pr-build-unused
SENTRY_PROJECT: pr-build-unused
NEXT_PUBLIC_APP_NAME: pr-build-unused
NEXT_PUBLIC_APP_LOGO_URL: pr-build-unused

build-pesayetu:
name: Build pesayetu image
needs: affected
Expand Down
2 changes: 1 addition & 1 deletion Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ climatemappedafrica:
./scripts/bake-up.sh climatemappedafrica

codeforafrica:
./scripts/dc.sh codeforafrica
./scripts/bake-up.sh codeforafrica

down:
$(COMPOSE_BUILD_ENV) $(COMPOSE) down --volumes
Expand Down
2 changes: 1 addition & 1 deletion apps/codeforafrica/payload.config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -60,7 +60,7 @@ export default buildConfig({
serverURL: appURL,
editor: slateEditor({}),
db: mongooseAdapter({
url: process.env.MONGODB_URL,
url: process.env.DATABASE_URL,
migrationDir: process.env.MIGRATIONS_DIR,
}),
collections: [
Expand Down
21 changes: 20 additions & 1 deletion docker-bake.hcl
Original file line number Diff line number Diff line change
Expand Up @@ -71,7 +71,7 @@ group "base" {
}

group "apps" {
targets = ["climatemappedafrica", "pesayetu", "roboshield", "techlabblog", "trustlab"]
targets = ["climatemappedafrica", "codeforafrica", "pesayetu", "roboshield", "techlabblog", "trustlab"]
}

# Prefer explicit targets/groups for predictability.
Expand Down Expand Up @@ -175,6 +175,25 @@ target "climatemappedafrica" {
# mounts, matching pesayetu's approach.
}

target "codeforafrica" {
inherits = ["_payload-app-runner"]
dockerfile = "docker/apps/codeforafrica/Dockerfile"
# "-ui" suffix matches the pre-bake DockerHub repository name
# (codeforafrica/codeforafrica-ui) that the live Dokku apps already pull by.
tags = ["${REGISTRY}codeforafrica-ui:${TAG}"]
args = {
NEXT_PUBLIC_APP_URL = "${NEXT_PUBLIC_APP_URL}"
SENTRY_ENVIRONMENT = "${SENTRY_ENVIRONMENT}"
}
# database_url/payload_secret/sentry_auth_token/org/project are all
# inherited from _payload-app-runner/_app. NEXT_PUBLIC_APP_NAME and
# NEXT_PUBLIC_APP_LOGO_URL are set via --set overrides at the workflow
# level (see _build-codeforafrica.yml), since they're sourced from
# GitHub Secrets rather than Variables — matching the legacy pipeline,
# which never wired NEXT_PUBLIC_IMAGE_DOMAINS/NEXT_PUBLIC_IMAGE_UNOPTIMIZED
# as build args either, despite next.config.js reading them.
}

# pesayetu fetches content from WordPress (WPGraphQL) during static generation,
# so these are real build args, not just runtime config. They default to empty
# so the image still builds without them; pages that depend on WordPress data
Expand Down
12 changes: 1 addition & 11 deletions docker-compose.yml
Original file line number Diff line number Diff line change
Expand Up @@ -48,17 +48,7 @@ services:
- 3000:3000

codeforafrica:
build:
secrets:
- mongodb_url
- payload_secret
- sentry_auth_token
- sentry_org
- sentry_project
context: .
target: codeforafrica-runner
args:
- SENTRY_ENVIRONMENT=${SENTRY_ENVIRONMENT}
image: codeforafrica/codeforafrica-ui:${TAG:-local}
env_file:
- path: ./apps/codeforafrica/.env
- path: ./apps/codeforafrica/.env.local
Expand Down
2 changes: 1 addition & 1 deletion docker/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ Apps checked below have migrated to the per-app Dockerfile pattern under
- [ ] `charterafrica`
- [ ] `civicsignalblog`
- [x] `climatemappedafrica`
- [ ] `codeforafrica`
- [x] `codeforafrica`
- [x] `pesayetu`
- [x] `roboshield`
- [x] `techlabblog`
Expand Down
Loading