diff --git a/.github/workflows/deploy-prod.yml b/.github/workflows/deploy-prod.yml index d4ad0bcd..13c9c794 100644 --- a/.github/workflows/deploy-prod.yml +++ b/.github/workflows/deploy-prod.yml @@ -30,6 +30,7 @@ on: permissions: id-token: write # assume the deploy role via OIDC (deploy job only) contents: read # checkout the released tag (validate + deploy) + packages: write # push the image to ghcr.io (deploy job) # checks: write is not used by THIS workflow — it's the ceiling for the # reusable ci.yml call: its `test` job requests checks: write (dorny # test-reporter), and a called job may never exceed the caller's grants. @@ -43,8 +44,10 @@ concurrency: env: AWS_REGION: us-east-2 - ECR_REGISTRY: 639595353568.dkr.ecr.us-east-2.amazonaws.com - ECR_REPOSITORY: checkin-prod + # The fleet standardized on ghcr.io (dev, arbor, s-read, bootstrap all push + # there; the prod task defs pull via the shared ghcr-pull-credentials + # secret). The ECR registry this workflow originally targeted is vestigial. + IMAGE_REPO: ghcr.io/innovationtreehouse/checkin-prod # Prod runs on the shared Managed-Instances cluster, not a dedicated # checkin-prod cluster (infra #104 destroyed that one). Names below come from # the infra repo — see the "prod infra" note in the PR description. @@ -158,19 +161,28 @@ jobs: role-to-assume: ${{ env.DEPLOY_ROLE }} aws-region: ${{ env.AWS_REGION }} - - name: Log in to Amazon ECR - uses: aws-actions/amazon-ecr-login@v2 + - name: Log in to ghcr.io + uses: docker/login-action@v4 + with: + registry: ghcr.io + username: ${{ github.actor }} + password: ${{ secrets.GITHUB_TOKEN }} - name: Build and push image id: build env: - IMAGE: ${{ env.ECR_REGISTRY }}/${{ env.ECR_REPOSITORY }}:${{ steps.vars.outputs.sha }} - IMAGE_TAGGED: ${{ env.ECR_REGISTRY }}/${{ env.ECR_REPOSITORY }}:${{ steps.vars.outputs.tag }} + IMAGE: ${{ env.IMAGE_REPO }}:${{ steps.vars.outputs.sha }} + IMAGE_TAGGED: ${{ env.IMAGE_REPO }}:${{ steps.vars.outputs.tag }} run: | set -euo pipefail # Native arm64 runner -> a plain build produces the arm64 image the # ECS task defs require (runtime_platform.cpu_architecture = ARM64). + # -f: there is no root Dockerfile — the app image builds from + # checkin-app/Dockerfile with the repo root as context, exactly like + # deploy-dev.yml (the release-scrub found this job would die here). docker build \ + --build-arg NEXT_PUBLIC_GIT_SHA="${{ steps.vars.outputs.sha }}" \ + -f checkin-app/Dockerfile \ -t "$IMAGE" -t "$IMAGE_TAGGED" . docker push "$IMAGE" docker push "$IMAGE_TAGGED" @@ -273,14 +285,37 @@ jobs: --query 'taskDefinition.taskDefinitionArn' --output text) echo "Registered app task def: $APP_ARN" + # --desired-count 1: the service is STAGED at 0 until the first + # release (infra sets desired_count = 0 with ignore_changes on it — + # "the deploy pipeline scales this up when it ships a real image"). + # Without this, update-service keeps 0, a 0/0 service is instantly + # "stable", and the run goes green while serving nothing. aws ecs update-service \ --cluster "$ECS_CLUSTER" --service "$ECS_SERVICE" \ - --task-definition "$APP_ARN" >/dev/null + --task-definition "$APP_ARN" \ + --desired-count 1 >/dev/null echo "Waiting for the service to reach steady state..." aws ecs wait services-stable --cluster "$ECS_CLUSTER" --services "$ECS_SERVICE" echo "Service is stable." + - name: Smoke test the live app + run: | + set -euo pipefail + # A real probe of the DEPLOYED service (CI's boot/smoke checks the + # image, not production). The app answers 200 or an auth redirect; + # retries cover target registration + first boot after scale-up. + for i in $(seq 1 12); do + CODE=$(curl -s -o /dev/null -w '%{http_code}' --max-time 10 "$APP_URL" || echo 000) + echo "attempt $i: $APP_URL -> HTTP $CODE" + case "$CODE" in + 200|301|302|307|308) echo "Smoke OK."; exit 0 ;; + esac + sleep 10 + done + echo "::error::Smoke test failed: $APP_URL never answered with 200/redirect" + exit 1 + - name: Report result if: always() env: @@ -295,7 +330,7 @@ jobs: { echo "### ✅ Released $TAG to prod" echo "Commit \`$SHORT_SHA\` is live on [$APP_URL]($APP_URL)." - echo "- Image: \`$ECR_REPOSITORY:$TAG\`" + echo "- Image: \`$IMAGE_REPO:$TAG\`" echo "- Migrations: applied · Service: stable" echo "- [Release]($RELEASE_URL) · [Deploy run]($RUN_URL)" } >> "$GITHUB_STEP_SUMMARY"