106 lines
4.4 KiB
YAML
106 lines
4.4 KiB
YAML
# aibook-fun — CI/CD: build the Next.js marketing site, push to reg.mini.dev,
|
|
# pin the image ref in Infisical, then trigger a pull + bounce on the droplet.
|
|
#
|
|
# Runs on Gitea Actions (GitHub-compatible syntax). This repo has Actions
|
|
# enabled; the runner must be labeled `ubuntu-latest`.
|
|
#
|
|
# Repository secrets required (Settings → Actions → Secrets):
|
|
# MINIMUS_TOKEN reg.mini.dev registry token (u: minimus)
|
|
# INFISICAL_CLIENT_ID Infisical Machine Identity Client ID
|
|
# INFISICAL_CLIENT_SECRET Infisical Machine Identity Client Secret
|
|
# INFISICAL_PROJECT_ID the /AIBook-Fun project ID
|
|
# DROPLET_IP droplet reserved IP (or resolve via DNS)
|
|
# DROPLET_SSH_KEY private SSH key for root@ on the droplet
|
|
#
|
|
# NOTE: first provision is NOT done here — it's terraform + ansible converge
|
|
# (deploy/docker-compose/terraform + ansible/deploy.yml). This workflow handles
|
|
# everything after the site exists: every main-branch push to app/deploy code
|
|
# rebuilds and rolls forward idempotently.
|
|
|
|
name: deploy
|
|
|
|
on:
|
|
push:
|
|
branches: [main]
|
|
paths:
|
|
- 'marketing-site/**'
|
|
- 'deploy/**'
|
|
- '.gitea/workflows/**'
|
|
workflow_dispatch:
|
|
|
|
permissions:
|
|
contents: read
|
|
|
|
concurrency:
|
|
group: aibook-fun-deploy
|
|
cancel-in-progress: false
|
|
|
|
env:
|
|
REGISTRY: reg.mini.dev
|
|
IMAGE_REPO: weownai/aibook-fun-marketing
|
|
INFISICAL_ENV: prod
|
|
INFISICAL_PATH: /AIBook-Fun
|
|
|
|
jobs:
|
|
build-and-deploy:
|
|
runs-on: ubuntu-latest
|
|
steps:
|
|
- uses: actions/checkout@v4
|
|
|
|
- name: Build image
|
|
run: |
|
|
docker build \
|
|
--pull \
|
|
-f deploy/docker-compose/docker/Dockerfile \
|
|
-t "${{ env.REGISTRY }}/${{ env.IMAGE_REPO }}:${{ github.sha }}" \
|
|
-t "${{ env.REGISTRY }}/${{ env.IMAGE_REPO }}:latest" \
|
|
marketing-site/
|
|
|
|
- name: Login to reg.mini.dev
|
|
run: echo "${{ secrets.MINIMUS_TOKEN }}" | docker login "${{ env.REGISTRY }}" -u minimus --password-stdin
|
|
|
|
- name: Push image
|
|
run: |
|
|
docker push "${{ env.REGISTRY }}/${{ env.IMAGE_REPO }}:${{ github.sha }}"
|
|
docker push "${{ env.REGISTRY }}/${{ env.IMAGE_REPO }}:latest"
|
|
|
|
- name: Pin AIBOOK_IMAGE in Infisical
|
|
env:
|
|
INFISICAL_UNIVERSAL_AUTH_CLIENT_ID: ${{ secrets.INFISICAL_CLIENT_ID }}
|
|
INFISICAL_UNIVERSAL_AUTH_CLIENT_SECRET: ${{ secrets.INFISICAL_CLIENT_SECRET }}
|
|
run: |
|
|
sudo curl -1sLf 'https://artifacts-cli.infisical.com/setup.deb.sh' | sudo -E bash
|
|
sudo DEBIAN_FRONTEND=noninteractive apt-get install -y -qq infisical >/dev/null
|
|
export INFISICAL_TOKEN="$(infisical login --method=universal-auth --plain --silent)"
|
|
infisical secrets set \
|
|
AIBOOK_IMAGE="${{ env.REGISTRY }}/${{ env.IMAGE_REPO }}:${{ github.sha }}" \
|
|
--projectId="${{ secrets.INFISICAL_PROJECT_ID }}" \
|
|
--env="${{ env.INFISICAL_ENV }}" \
|
|
--path="${{ env.INFISICAL_PATH }}"
|
|
|
|
- name: Deploy to droplet (pull + up)
|
|
uses: appleboy/ssh-action@v1
|
|
with:
|
|
host: ${{ secrets.DROPLET_IP }}
|
|
username: root
|
|
key: ${{ secrets.DROPLET_SSH_KEY }}
|
|
command_timeout: "15m"
|
|
script: |
|
|
set -euo pipefail
|
|
cd /opt/aibook_fun
|
|
# Droplet-side Infisical auth (auth file written by cloud-init).
|
|
source .infisical-auth.env
|
|
export INFISICAL_UNIVERSAL_AUTH_CLIENT_ID="$INFISICAL_CLIENT_ID"
|
|
export INFISICAL_UNIVERSAL_AUTH_CLIENT_SECRET="$INFISICAL_CLIENT_SECRET"
|
|
export INFISICAL_TOKEN="$(infisical login --method=universal-auth --plain --silent)"
|
|
# Re-auth reg.mini.dev if the docker login from ansible has lapsed.
|
|
MINIMUS_TOKEN="$(infisical secrets get MINIMUS_TOKEN --projectId="$INFISICAL_PROJECT_ID" --env=prod --path=/AIBook-Fun --plain || true)"
|
|
if [ -n "${MINIMUS_TOKEN:-}" ]; then
|
|
printf '%s' "$MINIMUS_TOKEN" | docker login reg.mini.dev -u minimus --password-stdin
|
|
fi
|
|
# AIBOOK_IMAGE is injected by `infisical run`; also export it so the
|
|
# ${AIBOOK_IMAGE:?} compose ref resolves even without run-injection.
|
|
export AIBOOK_IMAGE="$(infisical secrets get AIBOOK_IMAGE --projectId="$INFISICAL_PROJECT_ID" --env=prod --path=/AIBook-Fun --plain)"
|
|
infisical run --projectId="$INFISICAL_PROJECT_ID" --env=prod --path=/AIBook-Fun \
|
|
-- docker compose up -d --remove-orphans
|