From 05a648b096526a3f3d709e4f55da6ade1f6a02ed Mon Sep 17 00:00:00 2001 From: Christian Gick Date: Fri, 3 Apr 2026 07:06:25 +0300 Subject: [PATCH] fix: promote :latest only after health+smoke checks pass Previously, :latest was pushed during build before any validation. If health checks failed, rollback restored locally but Watchtower re-pulled the broken :latest from registry, undoing the rollback. Now: build pushes only SHA tag, deploy uses SHA tag locally, new promote job pushes :latest only after smoke tests pass. Rollback also pushes restored image as :latest to registry. Co-Authored-By: Claude Opus 4.6 (1M context) --- .gitea/workflows/deploy.yml | 27 ++++++++++++++++++++++----- 1 file changed, 22 insertions(+), 5 deletions(-) diff --git a/.gitea/workflows/deploy.yml b/.gitea/workflows/deploy.yml index e368237..b7bd168 100644 --- a/.gitea/workflows/deploy.yml +++ b/.gitea/workflows/deploy.yml @@ -50,10 +50,8 @@ jobs: run: | DOCKER_BUILDKIT=1 docker build --pull \ -t ${{ env.IMAGE }}:${{ github.sha }} \ - -t ${{ env.IMAGE }}:latest \ . docker push ${{ env.IMAGE }}:${{ github.sha }} - docker push ${{ env.IMAGE }}:latest - name: Cleanup if: always() @@ -87,9 +85,10 @@ jobs: # Sync docker-compose.yml and deploy scp docker-compose.yml ${{ env.REMOTE_USER }}@${{ env.REMOTE_HOST }}:${{ env.DEPLOY_PATH }}/docker-compose.yml - ssh ${{ env.REMOTE_USER }}@${{ env.REMOTE_HOST }} << 'EOF' + ssh ${{ env.REMOTE_USER }}@${{ env.REMOTE_HOST }} << EOF cd /opt/apps/internetforkids - docker pull gitea.agiliton.internal:3000/christian/internetforkids:latest + docker pull ${{ env.IMAGE }}:${{ github.sha }} + docker tag ${{ env.IMAGE }}:${{ github.sha }} ${{ env.IMAGE }}:latest docker compose up -d --force-recreate --remove-orphans EOF @@ -164,6 +163,22 @@ jobs: fi echo "All smoke tests passed" + promote: + name: Promote to Latest + runs-on: ubuntu-latest + needs: [smoke-test] + steps: + - name: Login to registry + run: | + echo "${{ secrets.REGISTRY_TOKEN }}" | docker login ${{ env.REGISTRY }} -u christian --password-stdin + + - name: Tag and push latest + run: | + docker pull ${{ env.IMAGE }}:${{ github.sha }} + docker tag ${{ env.IMAGE }}:${{ github.sha }} ${{ env.IMAGE }}:latest + docker push ${{ env.IMAGE }}:latest + echo "Promoted ${{ github.sha }} to :latest" + rollback: name: Rollback runs-on: ubuntu-latest @@ -186,6 +201,8 @@ jobs: cd ${{ env.DEPLOY_PATH }} docker tag $PREVIOUS ${{ env.IMAGE }}:latest docker compose up -d --force-recreate + # Push rolled-back image as :latest so Watchtower doesn't re-pull broken + docker push ${{ env.IMAGE }}:latest EOF - name: Verify rollback @@ -201,7 +218,7 @@ jobs: audit: name: Audit runs-on: ubuntu-latest - needs: [deploy, health-check, smoke-test, rollback] + needs: [deploy, health-check, smoke-test, promote, rollback] if: always() steps: - name: Setup SSH