Skip to content

refactor(guides): outline steps and wide figures (batch 3) #672

refactor(guides): outline steps and wide figures (batch 3)

refactor(guides): outline steps and wide figures (batch 3) #672

Workflow file for this run

name: CI
on:
pull_request:
push:
branches: [main]
concurrency:
group: ci-${{ github.ref }}
cancel-in-progress: true
permissions:
contents: read
packages: write
jobs:
test-and-build:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: actions/setup-node@v4
with:
node-version: "24"
cache: "npm"
- name: Install dependencies
run: npm ci
- name: Lint
run: npm run lint
- name: Typecheck
run: npm run typecheck
- name: Unit tests
run: npm run test:unit
- name: Build
env:
AUTH_SECRET: ci-build-secret-not-for-production
NEXT_PUBLIC_OFFICER_HUB_PUBLIC: "true"
NEXT_PUBLIC_DEMO_SITE: "true"
# Optional — readable Sentry stack traces when the org secret is set.
SENTRY_AUTH_TOKEN: ${{ secrets.SENTRY_AUTH_TOKEN }}
SENTRY_ORG: union-ops
SENTRY_PROJECT: javascript-nextjs
run: npm run build
- name: Install Playwright browsers
run: |
# ubuntu-latest ships Microsoft apt feeds that can break `apt update` (NOSPLIT / unsigned).
sudo rm -f /etc/apt/sources.list.d/microsoft*.list \
/etc/apt/sources.list.d/microsoft*.sources \
/etc/apt/sources.list.d/azure-cli* 2>/dev/null || true
npx playwright install chromium --with-deps
- name: E2E smoke
env:
CI: "true"
AUTH_SECRET: ci-build-secret-not-for-production
# Production `next start` disables the demo roster unless opted in
# (isDemoAuthEnabled). Without this, hub/portal @smoke spins on
# CredentialsSignin until the job is cancelled.
AUTH_ALLOW_DEMO_USERS: "true"
NEXT_PUBLIC_DEMO_SITE: "true"
NEXT_PUBLIC_OFFICER_HUB_PUBLIC: "true"
run: npm run test:smoke
- name: Dependency audit
run: npm audit --audit-level=high
continue-on-error: true
# Docker build + GHCR publish run independently of E2E so CapRover can pull a
# pre-built image instead of rebuilding on a small droplet (BuildKit export failures).
docker-image:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: Docker build smoke
env:
SENTRY_AUTH_TOKEN: ${{ secrets.SENTRY_AUTH_TOKEN }}
NEXT_PUBLIC_SENTRY_DSN: ${{ secrets.NEXT_PUBLIC_SENTRY_DSN }}
run: |
EXTRA_ARGS=""
if [ -n "$SENTRY_AUTH_TOKEN" ]; then
EXTRA_ARGS="$EXTRA_ARGS --build-arg SENTRY_AUTH_TOKEN=$SENTRY_AUTH_TOKEN --build-arg SENTRY_ORG=union-ops --build-arg SENTRY_PROJECT=javascript-nextjs"
fi
if [ -n "$NEXT_PUBLIC_SENTRY_DSN" ]; then
EXTRA_ARGS="$EXTRA_ARGS --build-arg NEXT_PUBLIC_SENTRY_DSN=$NEXT_PUBLIC_SENTRY_DSN"
fi
# shellcheck disable=SC2086
docker build -f docker/Dockerfile -t union-communications:ci \
--build-arg AUTH_SECRET=build-time-placeholder-not-used-at-runtime \
--build-arg CAPROVER_GIT_COMMIT_SHA=${{ github.sha }} \
--build-arg NEXT_PUBLIC_OFFICER_HUB_PUBLIC=true \
--build-arg NEXT_PUBLIC_DEMO_SITE=true \
$EXTRA_ARGS \
.
- name: Docker migrate smoke
run: bash scripts/docker-migrate-smoke.sh union-communications:ci
- name: Log in to GHCR
if: github.event_name == 'push' && github.ref == 'refs/heads/main'
uses: docker/login-action@v3
with:
registry: ghcr.io
username: ${{ github.actor }}
password: ${{ secrets.GITHUB_TOKEN }}
- name: Push demo / workshop image
if: github.event_name == 'push' && github.ref == 'refs/heads/main'
run: |
IMAGE="ghcr.io/${{ github.repository }}"
docker tag union-communications:ci "${IMAGE}:main"
docker tag union-communications:ci "${IMAGE}:sha-${GITHUB_SHA::7}"
docker push "${IMAGE}:main"
docker push "${IMAGE}:sha-${GITHUB_SHA::7}"
- name: Build and push production hardened image
if: github.event_name == 'push' && github.ref == 'refs/heads/main'
uses: docker/build-push-action@v6
with:
context: .
file: docker/Dockerfile
push: true
tags: ghcr.io/${{ github.repository }}:production
build-args: |
AUTH_SECRET=build-time-placeholder-not-used-at-runtime
CAPROVER_GIT_COMMIT_SHA=${{ github.sha }}
NEXT_PUBLIC_OFFICER_HUB_PUBLIC=true
NEXT_PUBLIC_DEMO_SITE=false
SENTRY_AUTH_TOKEN=${{ secrets.SENTRY_AUTH_TOKEN }}
SENTRY_ORG=union-ops
SENTRY_PROJECT=javascript-nextjs
NEXT_PUBLIC_SENTRY_DSN=${{ secrets.NEXT_PUBLIC_SENTRY_DSN }}
deploy:
needs: docker-image
if: github.event_name == 'push' && github.ref == 'refs/heads/main'
runs-on: ubuntu-latest
steps:
- name: Deploy pre-built GHCR image to CapRover
env:
CAPROVER_SERVER: ${{ secrets.CAPROVER_SERVER }}
CAPROVER_PASSWORD: ${{ secrets.CAPROVER_PASSWORD }}
CAPROVER_APP: ${{ secrets.CAPROVER_APP }}
CAPROVER_WEBHOOK_URL: ${{ secrets.CAPROVER_WEBHOOK_URL }}
IMAGE: ghcr.io/${{ github.repository }}:main
run: |
if [ -n "$CAPROVER_SERVER" ] && [ -n "$CAPROVER_PASSWORD" ] && [ -n "$CAPROVER_APP" ]; then
echo "Deploying ${IMAGE} to CapRover app ${CAPROVER_APP} (pull only — no on-host build)."
docker run --rm caprover/caprover-cli:2.2.3 caprover deploy \
--caproverUrl "$CAPROVER_SERVER" \
--caproverPassword "$CAPROVER_PASSWORD" \
--caproverApp "$CAPROVER_APP" \
--imageName "$IMAGE"
echo "CapRover image deploy triggered."
exit 0
fi
if [ -n "$CAPROVER_WEBHOOK_URL" ]; then
echo "::warning::CAPROVER_SERVER/PASSWORD/APP not set — falling back to git webhook (rebuilds on CapRover; may fail on small hosts)."
curl -fsS -X POST "$CAPROVER_WEBHOOK_URL"
echo "CapRover git build webhook triggered."
exit 0
fi
echo "::warning::No CapRover deploy secrets — skipping deploy. Set CAPROVER_SERVER, CAPROVER_PASSWORD, CAPROVER_APP for image deploy."