Files
Mark b0e009d606
All checks were successful
CI / nightly-e2e (pull_request) Has been skipped
CI / deploy (pull_request) Has been skipped
CI / ci (pull_request) Successful in 3m2s
CI / pr-e2e (pull_request) Successful in 3m6s
Migrate deploy workflow to OpenBao SSH CA
2026-03-17 16:56:45 +00:00

249 lines
9.0 KiB
YAML

name: CI
on:
pull_request:
push:
branches:
- main
schedule:
- cron: "0 2 * * *"
concurrency:
group: ci-pr-${{ github.event.pull_request.number || github.ref }}
cancel-in-progress: true
jobs:
ci:
if: github.event_name == 'pull_request'
runs-on: ubuntu-latest
env:
CI_IMAGE: nohype-ci:${{ github.run_id }}
steps:
- uses: actions/checkout@v4
- name: Build
run: docker build -t "$CI_IMAGE" .
- name: Start PostgreSQL
run: |
docker run -d --name ci-postgres \
-e POSTGRES_DB=nohype \
-e POSTGRES_USER=nohype \
-e POSTGRES_PASSWORD=nohype \
postgres:16-alpine
for i in $(seq 1 30); do
if docker exec ci-postgres pg_isready -U nohype -d nohype >/dev/null; then
exit 0
fi
sleep 2
done
docker logs ci-postgres || true
exit 1
- name: Ruff
run: docker run --rm --network container:ci-postgres -e SECRET_KEY=ci-secret-key -e DATABASE_URL=postgres://nohype:nohype@127.0.0.1:5432/nohype "$CI_IMAGE" ruff check .
- name: Mypy
run: docker run --rm --network container:ci-postgres -e SECRET_KEY=ci-secret-key -e DATABASE_URL=postgres://nohype:nohype@127.0.0.1:5432/nohype "$CI_IMAGE" mypy apps config
- name: Pytest
run: docker run --rm --network container:ci-postgres -e SECRET_KEY=ci-secret-key -e DATABASE_URL=postgres://nohype:nohype@127.0.0.1:5432/nohype "$CI_IMAGE" pytest --ignore=e2e
- name: Tailwind build (assert generated diff is clean)
run: |
docker run --name ci-tailwind \
--network container:ci-postgres \
-e SECRET_KEY=ci-secret-key \
-e DATABASE_URL=postgres://nohype:nohype@127.0.0.1:5432/nohype \
"$CI_IMAGE" \
sh -lc "python manage.py tailwind install --no-input && python manage.py tailwind build"
docker cp ci-tailwind:/app/theme/static/css/styles.css /tmp/ci-styles.css
docker rm -f ci-tailwind
cmp -s theme/static/css/styles.css /tmp/ci-styles.css
- name: Remove PostgreSQL
if: always()
run: |
docker rm -f ci-postgres || true
- name: Remove CI image
if: always()
run: docker image rm -f "$CI_IMAGE" || true
pr-e2e:
if: github.event_name == 'pull_request'
runs-on: ubuntu-latest
env:
CI_IMAGE: nohype-ci-e2e:${{ github.run_id }}
PLAYWRIGHT_CACHE_VOLUME: nohype-playwright-browsers
steps:
- uses: actions/checkout@v4
- name: Build
run: docker build -t "$CI_IMAGE" .
- name: Ensure Playwright Chromium cache
run: |
docker volume create "$PLAYWRIGHT_CACHE_VOLUME" >/dev/null
docker run --rm \
-v "$PLAYWRIGHT_CACHE_VOLUME:/ms-playwright" \
-e PLAYWRIGHT_BROWSERS_PATH=/ms-playwright \
"$CI_IMAGE" \
python -m playwright install chromium
- name: Start PostgreSQL
run: |
docker run -d --name pr-e2e-postgres \
-e POSTGRES_DB=nohype \
-e POSTGRES_USER=nohype \
-e POSTGRES_PASSWORD=nohype \
postgres:16-alpine
for i in $(seq 1 30); do
if docker exec pr-e2e-postgres pg_isready -U nohype -d nohype >/dev/null; then
exit 0
fi
sleep 2
done
docker logs pr-e2e-postgres || true
exit 1
- name: Start app with seeded content
run: |
docker run -d --name pr-e2e-app --network container:pr-e2e-postgres \
-v "$PLAYWRIGHT_CACHE_VOLUME:/ms-playwright:ro" \
-e SECRET_KEY=ci-secret-key \
-e DATABASE_URL=postgres://nohype:nohype@127.0.0.1:5432/nohype \
-e CONSENT_POLICY_VERSION=1 \
-e EMAIL_BACKEND=django.core.mail.backends.console.EmailBackend \
-e DEFAULT_FROM_EMAIL=hello@nohypeai.com \
-e NEWSLETTER_PROVIDER=buttondown \
-e PLAYWRIGHT_BROWSERS_PATH=/ms-playwright \
-e E2E_MODE=1 \
"$CI_IMAGE" \
sh -lc "python manage.py migrate --noinput && python manage.py seed_e2e_content && python manage.py runserver 0.0.0.0:8000"
for i in $(seq 1 40); do
if docker exec pr-e2e-app curl -fsS http://127.0.0.1:8000/ >/dev/null; then
exit 0
fi
sleep 2
done
docker logs pr-e2e-app || true
exit 1
- name: Run E2E tests
run: |
docker exec -e E2E_BASE_URL=http://127.0.0.1:8000 pr-e2e-app \
pytest e2e/ -o addopts='' -q --tb=short
- name: Remove containers
if: always()
run: |
docker rm -f pr-e2e-app || true
docker rm -f pr-e2e-postgres || true
- name: Remove CI image
if: always()
run: docker image rm -f "$CI_IMAGE" || true
nightly-e2e:
if: github.event_name == 'schedule'
runs-on: ubuntu-latest
env:
CI_IMAGE: nohype-ci-nightly:${{ github.run_id }}
PLAYWRIGHT_CACHE_VOLUME: nohype-playwright-browsers
steps:
- uses: actions/checkout@v4
- name: Build
run: docker build -t "$CI_IMAGE" .
- name: Ensure Playwright Chromium cache
run: |
docker volume create "$PLAYWRIGHT_CACHE_VOLUME" >/dev/null
docker run --rm \
-v "$PLAYWRIGHT_CACHE_VOLUME:/ms-playwright" \
-e PLAYWRIGHT_BROWSERS_PATH=/ms-playwright \
"$CI_IMAGE" \
python -m playwright install chromium
- name: Start PostgreSQL
run: |
docker run -d --name nightly-postgres \
-e POSTGRES_DB=nohype \
-e POSTGRES_USER=nohype \
-e POSTGRES_PASSWORD=nohype \
postgres:16-alpine
for i in $(seq 1 30); do
if docker exec nightly-postgres pg_isready -U nohype -d nohype >/dev/null; then
exit 0
fi
sleep 2
done
docker logs nightly-postgres || true
exit 1
- name: Start dev server with seeded content
run: |
docker run -d --name nightly-e2e --network container:nightly-postgres \
-v "$PLAYWRIGHT_CACHE_VOLUME:/ms-playwright:ro" \
-e SECRET_KEY=ci-secret-key \
-e DATABASE_URL=postgres://nohype:nohype@127.0.0.1:5432/nohype \
-e CONSENT_POLICY_VERSION=1 \
-e EMAIL_BACKEND=django.core.mail.backends.console.EmailBackend \
-e DEFAULT_FROM_EMAIL=hello@nohypeai.com \
-e NEWSLETTER_PROVIDER=buttondown \
-e PLAYWRIGHT_BROWSERS_PATH=/ms-playwright \
-e E2E_MODE=1 \
"$CI_IMAGE" \
sh -lc "python manage.py migrate --noinput && python manage.py seed_e2e_content && python manage.py runserver 0.0.0.0:8000"
for i in $(seq 1 40); do
if docker exec nightly-e2e curl -fsS http://127.0.0.1:8000/ >/dev/null; then
exit 0
fi
sleep 2
done
docker logs nightly-e2e || true
exit 1
- name: Run Playwright E2E tests
run: |
docker exec -e E2E_BASE_URL=http://127.0.0.1:8000 nightly-e2e \
pytest e2e/ apps/core/tests/test_nightly_e2e_playwright.py -o addopts='' -q --tb=short
- name: Remove nightly container
if: always()
run: |
docker rm -f nightly-e2e || true
docker rm -f nightly-postgres || true
- name: Remove CI image
if: always()
run: docker image rm -f "$CI_IMAGE" || true
deploy:
if: github.event_name == 'push' && github.ref == 'refs/heads/main'
runs-on:
- ubuntu-latest
- agent-workspace
env:
BAO_TOKEN_FILE: /run/openbao-agent-ci_runner/token
steps:
- name: Configure SSH via OpenBao CA
shell: bash
run: |
set -euo pipefail
: "${OPENBAO_ADDR:?OPENBAO_ADDR must be set by the runner environment}"
mkdir -p ~/.ssh && chmod 700 ~/.ssh
ssh-keygen -t ed25519 -f ~/.ssh/id_ed25519 -N "" -q
BAO_TOKEN="$(<"$BAO_TOKEN_FILE")"
SIGNED_KEY=$(curl -fsS \
-H "X-Vault-Token: $BAO_TOKEN" \
-H "X-Vault-Request: true" \
-X POST \
-d "{\"public_key\": \"$(cat ~/.ssh/id_ed25519.pub)\", \"valid_principals\": \"${{ vars.DEPLOY_USER }}\"}" \
"${OPENBAO_ADDR}/v1/ssh/sign/${{ vars.DEPLOY_SSH_ROLE }}" \
| jq -r '.data.signed_key')
[ -n "$SIGNED_KEY" ] && [ "$SIGNED_KEY" != "null" ] \
|| { echo "ERROR: failed to sign SSH key via OpenBao CA" >&2; exit 1; }
printf '%s\n' "$SIGNED_KEY" > ~/.ssh/id_ed25519-cert.pub
unset BAO_TOKEN SIGNED_KEY
- name: Add deploy host to known_hosts
run: ssh-keyscan -H "${{ vars.DEPLOY_HOST }}" >> ~/.ssh/known_hosts 2>/dev/null
- name: Deploy to lintel-prod-01
run: ssh "${{ vars.DEPLOY_USER }}@${{ vars.DEPLOY_HOST }}" "bash /srv/sum/nohype/app/deploy/deploy.sh"