Template
The deploy step put ${{ secrets.DEPLOY_SSH_KEY }} straight into the run script. The runner prints that script, and Gitea does not mask a multi-line secret once it is split across script lines, so the key body appeared in every deploy log. The key now arrives through the step's env block.
137 lines
4.8 KiB
YAML
137 lines
4.8 KiB
YAML
name: Build and Deploy Next App
|
|
|
|
on:
|
|
push:
|
|
branches:
|
|
- main
|
|
paths:
|
|
- 'apps/next/**'
|
|
- 'packages/**'
|
|
- 'tools/**'
|
|
- 'scripts/**'
|
|
- 'docker/**'
|
|
- '.gitea/workflows/build-next.yml'
|
|
- 'package.json'
|
|
- 'bun.lock'
|
|
- 'turbo.json'
|
|
|
|
# One production deploy at a time; a newer push waits rather than racing.
|
|
concurrency:
|
|
group: build-next-production
|
|
cancel-in-progress: false
|
|
|
|
# Production env comes from the Infisical `staging` environment. Each job logs
|
|
# in as the read-only `convexmonorepo-ci` machine identity and writes the env to a
|
|
# temp file (scripts/ci-export-env.mjs), so no prod values live in Gitea.
|
|
jobs:
|
|
# Quality gate: workspace lint (sherif), eslint, typecheck and the unit,
|
|
# integration and component suites must pass before anything touches
|
|
# production. The local-stack e2e smoke check is skipped in CI.
|
|
quality:
|
|
runs-on: ubuntu-latest
|
|
|
|
steps:
|
|
- name: Checkout repository
|
|
uses: actions/checkout@v4
|
|
|
|
- name: Set up Bun
|
|
uses: oven-sh/setup-bun@v2
|
|
with:
|
|
bun-version: 1.3.14
|
|
|
|
- name: Install dependencies
|
|
run: ./scripts/ci-install
|
|
|
|
- name: Lint and typecheck
|
|
env:
|
|
INFISICAL_CLIENT_ID: ${{ secrets.INFISICAL_CLIENT_ID }}
|
|
INFISICAL_CLIENT_SECRET: ${{ secrets.INFISICAL_CLIENT_SECRET }}
|
|
run: |
|
|
env_file="$(mktemp)"
|
|
trap 'rm -f "$env_file"' EXIT
|
|
node scripts/ci-export-env.mjs staging > "$env_file"
|
|
bunx dotenv -e "$env_file" -- env NODE_ENV=test SKIP_E2E=1 bun run ci:check
|
|
|
|
# Pushes Convex functions and schema to prod before the image that depends on
|
|
# them is built. The env file must carry CONVEX_SELF_HOSTED_URL and
|
|
# CONVEX_SELF_HOSTED_ADMIN_KEY. Codegen is disabled: _generated is committed.
|
|
convex-deploy:
|
|
needs: [quality]
|
|
runs-on: ubuntu-latest
|
|
|
|
steps:
|
|
- name: Checkout repository
|
|
uses: actions/checkout@v4
|
|
|
|
- name: Set up Bun
|
|
uses: oven-sh/setup-bun@v2
|
|
with:
|
|
bun-version: 1.3.14
|
|
|
|
- name: Install dependencies
|
|
run: ./scripts/ci-install
|
|
|
|
- name: Deploy Convex functions
|
|
env:
|
|
INFISICAL_CLIENT_ID: ${{ secrets.INFISICAL_CLIENT_ID }}
|
|
INFISICAL_CLIENT_SECRET: ${{ secrets.INFISICAL_CLIENT_SECRET }}
|
|
run: |
|
|
env_file="$(mktemp)"
|
|
trap 'rm -f "$env_file"' EXIT
|
|
node scripts/ci-export-env.mjs staging > "$env_file"
|
|
cd packages/backend
|
|
bunx convex deploy --env-file "$env_file" --codegen disable --typecheck disable
|
|
|
|
build-next:
|
|
needs: [convex-deploy]
|
|
runs-on: ubuntu-latest
|
|
|
|
steps:
|
|
- name: Checkout repository
|
|
uses: actions/checkout@v4
|
|
|
|
- name: Log in to container registry
|
|
run: |
|
|
echo "${{ secrets.REGISTRY_PASSWORD }}" | docker login git.gbrown.org -u "${{ secrets.REGISTRY_USER }}" --password-stdin
|
|
|
|
- name: Build app using project script
|
|
env:
|
|
INFISICAL_CLIENT_ID: ${{ secrets.INFISICAL_CLIENT_ID }}
|
|
INFISICAL_CLIENT_SECRET: ${{ secrets.INFISICAL_CLIENT_SECRET }}
|
|
run: |
|
|
env_file="$(mktemp)"
|
|
trap 'rm -f "$env_file"' EXIT
|
|
node scripts/ci-export-env.mjs staging > "$env_file"
|
|
CI_ENV_FILE="$env_file" ./scripts/build-next-app staging
|
|
|
|
- name: Tag built image
|
|
run: |
|
|
docker tag convexmonorepo-next:latest git.gbrown.org/gib/convexmonorepo-next:${{ gitea.sha }}
|
|
docker tag convexmonorepo-next:latest git.gbrown.org/gib/convexmonorepo-next:latest
|
|
|
|
- name: Push image tags
|
|
run: |
|
|
docker push git.gbrown.org/gib/convexmonorepo-next:${{ gitea.sha }}
|
|
docker push git.gbrown.org/gib/convexmonorepo-next:latest
|
|
|
|
# Asks the VPS to pull the new image and restart podman-convexmonorepo.service
|
|
# through the forced-command deploy key (~/Server/AGENTS.md §15). A
|
|
# failure only warns: the image is pushed and the midnight
|
|
# podman-update.timer deploys it anyway.
|
|
- name: Trigger immediate deploy
|
|
# The key comes in through env, not ${{ secrets.* }} in the script:
|
|
# the runner prints the script, and Gitea does not mask a multi-line
|
|
# secret once it is split across script lines.
|
|
env:
|
|
DEPLOY_SSH_KEY: ${{ secrets.DEPLOY_SSH_KEY }}
|
|
run: |
|
|
install -m600 /dev/null "$HOME/.deploy_key"
|
|
printf '%s\n' "$DEPLOY_SSH_KEY" > "$HOME/.deploy_key"
|
|
ssh -i "$HOME/.deploy_key" \
|
|
-o BatchMode=yes \
|
|
-o StrictHostKeyChecking=accept-new \
|
|
-o ConnectTimeout=15 \
|
|
[email protected] convexmonorepo \
|
|
|| echo "::warning::deploy trigger failed; nightly sweep will deploy instead"
|
|
rm -f "$HOME/.deploy_key"
|