name: Build & Deploy played game (reusable) # Invoked by each game's `.gitea/workflows/deploy.yml`: # # jobs: # deploy: # uses: played/workflows/.gitea/workflows/build-deploy-game.yml@main # with: # game-id: relayer # secrets: inherit # # The caller repo must expose these Gitea Actions secrets (via # `secrets: inherit` or per-secret pass-through): # - BUILD_ENV — the prod .env, written to /tmp/.env.prod for # Docker build secret mount AND to # ~/-secrets/.env on the deploy VM # - NPMRC — ~/.npmrc with @played registry auth token # - REGISTRY_USER / REGISTRY_TOKEN — Gitea container registry creds # - PLAYED_HOST / PLAYED_USER / PLAYED_PORT / PLAYED_SSH_KEY — deploy target # - STEP_CA_PROVISIONER_PASSWORD — for the cert-init container # # Notes on reliability: # - All remote actions are pinned to immutable patch tags so the act-runner # action cache hash is stable run-to-run. The cluster of "Cannot find # module .../dist/index.js" failures on home-runner-1 was act re-using a # partial cache dir for a moving tag (`@v3`); pinning kills that mode. # - Registry login is an inline shell step instead of docker/login-action. # One fewer remote-action download = one fewer failure point per job. on: workflow_call: inputs: game-id: description: Game slug (must match @played/games-registry's GAMES, e.g. relayer) type: string required: true jobs: build-api-core: runs-on: ubuntu-24.04 steps: - uses: actions/checkout@v4.2.2 - name: Set up Docker Buildx uses: docker/setup-buildx-action@v3.10.0 with: config-inline: | [registry."docker.io"] mirrors = ["192.168.1.52:5000"] [registry."192.168.1.52:5000"] http = true insecure = true - name: Log in to Gitea registry env: REGISTRY_USER: ${{ secrets.REGISTRY_USER }} REGISTRY_TOKEN: ${{ secrets.REGISTRY_TOKEN }} run: | printf '%s' "$REGISTRY_TOKEN" | docker login git.unom.io -u "$REGISTRY_USER" --password-stdin - name: Write secrets to files env: BUILD_ENV: ${{ secrets.BUILD_ENV }} NPMRC: ${{ secrets.NPMRC }} run: | printenv BUILD_ENV > /tmp/.env.prod printenv NPMRC > /tmp/.npmrc - name: Build & push api-core uses: docker/build-push-action@v6.16.0 with: context: . file: ./api/core/Dockerfile push: true tags: | git.unom.io/${{ gitea.repository }}/api-core:latest git.unom.io/${{ gitea.repository }}/api-core:${{ gitea.sha }} secret-files: | env=/tmp/.env.prod npmrc=/tmp/.npmrc cache-from: | type=registry,ref=git.unom.io/${{ gitea.repository }}/api-core:cache cache-to: | type=registry,ref=git.unom.io/${{ gitea.repository }}/api-core:cache,mode=max deploy-api-core: runs-on: ubuntu-24.04 needs: build-api-core steps: - name: Write secrets to server uses: appleboy/ssh-action@v1.2.5 with: host: ${{ secrets.PLAYED_HOST }} username: ${{ secrets.PLAYED_USER }} port: ${{ secrets.PLAYED_PORT }} key: ${{ secrets.PLAYED_SSH_KEY }} envs: BUILD_ENV,STEP_CA_PROVISIONER_PASSWORD,GAME_ID script: | mkdir -p ~/${GAME_ID}-secrets printf '%s' "$BUILD_ENV" > ~/${GAME_ID}-secrets/.env printf '%s' "$STEP_CA_PROVISIONER_PASSWORD" > ~/${GAME_ID}-secrets/step-provisioner-password.txt chmod 644 ~/${GAME_ID}-secrets/.env chmod 600 ~/${GAME_ID}-secrets/step-provisioner-password.txt env: BUILD_ENV: ${{ secrets.BUILD_ENV }} STEP_CA_PROVISIONER_PASSWORD: ${{ secrets.STEP_CA_PROVISIONER_PASSWORD }} GAME_ID: ${{ inputs.game-id }} - name: Pull and start api-core uses: appleboy/ssh-action@v1.2.5 with: host: ${{ secrets.PLAYED_HOST }} username: ${{ secrets.PLAYED_USER }} port: ${{ secrets.PLAYED_PORT }} key: ${{ secrets.PLAYED_SSH_KEY }} envs: GAME_ID script: | docker login git.unom.io -u ${{ secrets.REGISTRY_USER }} -p ${{ secrets.REGISTRY_TOKEN }} cd ~/${GAME_ID} git fetch origin main git reset --hard origin/main docker compose -f compose.production.yml --env-file ~/${GAME_ID}-secrets/.env pull api-core docker compose -f compose.production.yml --env-file ~/${GAME_ID}-secrets/.env up -d --no-build api-core env: GAME_ID: ${{ inputs.game-id }} - name: Wait for api-core to be healthy uses: appleboy/ssh-action@v1.2.5 with: host: ${{ secrets.PLAYED_HOST }} username: ${{ secrets.PLAYED_USER }} port: ${{ secrets.PLAYED_PORT }} key: ${{ secrets.PLAYED_SSH_KEY }} envs: GAME_ID script: | cd ~/${GAME_ID} echo "Waiting for api-core to be ready..." for i in $(seq 1 30); do if docker compose -f compose.production.yml --env-file ~/${GAME_ID}-secrets/.env ps api-core | grep -q "(healthy)"; then echo "api-core is healthy" exit 0 fi echo "Attempt $i/30..." sleep 5 done echo "api-core did not become healthy in time" exit 1 env: GAME_ID: ${{ inputs.game-id }} build-web: runs-on: ubuntu-24.04 # No `needs:` — web build is independent of the api-core build/deploy. # If the runner can run jobs concurrently, this lets it run in parallel # with build-api-core + deploy-api-core. deploy-web below still gates on # deploy-api-core so the runtime sequence is preserved. steps: - uses: actions/checkout@v4.2.2 - name: Set up Docker Buildx uses: docker/setup-buildx-action@v3.10.0 with: config-inline: | [registry."docker.io"] mirrors = ["192.168.1.52:5000"] [registry."192.168.1.52:5000"] http = true insecure = true - name: Log in to Gitea registry env: REGISTRY_USER: ${{ secrets.REGISTRY_USER }} REGISTRY_TOKEN: ${{ secrets.REGISTRY_TOKEN }} run: | printf '%s' "$REGISTRY_TOKEN" | docker login git.unom.io -u "$REGISTRY_USER" --password-stdin - name: Write secrets to files env: BUILD_ENV: ${{ secrets.BUILD_ENV }} NPMRC: ${{ secrets.NPMRC }} run: | printenv BUILD_ENV > /tmp/.env.prod printenv NPMRC > /tmp/.npmrc - name: Build & push web uses: docker/build-push-action@v6.16.0 with: context: . file: ./apps/web/Dockerfile push: true tags: | git.unom.io/${{ gitea.repository }}/web:latest git.unom.io/${{ gitea.repository }}/web:${{ gitea.sha }} secret-files: | env=/tmp/.env.prod npmrc=/tmp/.npmrc cache-from: | type=registry,ref=git.unom.io/${{ gitea.repository }}/web:cache cache-to: | type=registry,ref=git.unom.io/${{ gitea.repository }}/web:cache,mode=max deploy-web: runs-on: ubuntu-24.04 # Both gates: image must be built AND api-core must be live before web flips. needs: [build-web, deploy-api-core] steps: - name: Pull and start web uses: appleboy/ssh-action@v1.2.5 with: host: ${{ secrets.PLAYED_HOST }} username: ${{ secrets.PLAYED_USER }} port: ${{ secrets.PLAYED_PORT }} key: ${{ secrets.PLAYED_SSH_KEY }} envs: GAME_ID script: | docker login git.unom.io -u ${{ secrets.REGISTRY_USER }} -p ${{ secrets.REGISTRY_TOKEN }} cd ~/${GAME_ID} docker compose -f compose.production.yml --env-file ~/${GAME_ID}-secrets/.env pull web docker compose -f compose.production.yml --env-file ~/${GAME_ID}-secrets/.env up -d --no-build web env: GAME_ID: ${{ inputs.game-id }}