diff --git a/.gitea/workflows/deploy.yml b/.gitea/workflows/deploy.yml index a52dfd8..db285b7 100644 --- a/.gitea/workflows/deploy.yml +++ b/.gitea/workflows/deploy.yml @@ -1,21 +1,9 @@ -# 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`. +# Rebuild + roll aibook.fun forward on any push to main. +# Runner: repo-registered act_runner on the aibook.fun droplet itself +# (co-located → local docker commands, no cross-host SSH needed). # # 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. +# (none — runner is on the droplet, has local root) name: deploy @@ -28,78 +16,23 @@ on: - '.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 + deploy: + runs-on: aibook-fun-droplet steps: - - uses: actions/checkout@v4 - - - name: Build image + - name: Pull latest + rebuild + roll 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 + set -euo pipefail + cd /opt/aibook_fun/repo + git fetch --prune origin + git reset --hard origin/main + docker build -t aibook-fun-marketing:v1 \ + -f /opt/aibook_fun/repo/deploy/docker/Dockerfile \ + /opt/aibook_fun/repo/marketing-site/ + cd /opt/aibook_fun + docker compose up -d --remove-orphans + docker image prune -f --filter "dangling=true"