diff --git a/.github/workflows/shared-cloudrun-rollback.yml b/.github/workflows/shared-cloudrun-rollback.yml new file mode 100644 index 00000000..4029fa8d --- /dev/null +++ b/.github/workflows/shared-cloudrun-rollback.yml @@ -0,0 +1,76 @@ +--- +name: Cloud Run Deploy with Auto Rollback + +on: + workflow_call: + inputs: + gcp_registry_host: + required: true + type: string + IMAGE_NAME: + required: true + type: string + IMAGE_TAG: + required: true + type: string + GCP_REPOSITORY: + required: true + type: string + SERVICE_NAME: + required: true + type: string + REGION: + required: true + type: string + + secrets: + GCP_PROJECT_ID: + required: true + GCP_SA_KEY: + required: true + + outputs: + revision: + description: "Previous revision" + value: ${{ jobs.deploy.outputs.revision }} + service_name: + description: "Service name" + value: ${{ inputs.SERVICE_NAME }} + +jobs: + deploy: + runs-on: ubuntu-latest + outputs: + revision: ${{ steps.prev.outputs.revision }} + + steps: + - name: Authenticate to GCP + uses: google-github-actions/auth@v2 + with: + credentials_json: ${{ secrets.GCP_SA_KEY }} + + - name: Setup gcloud + uses: google-github-actions/setup-gcloud@v2 + + - name: Get current revision + id: prev + run: | + REVISION=$(gcloud run services describe ${{ inputs.SERVICE_NAME }} \ + --region ${{ inputs.REGION }} \ + --format="value(status.traffic[0].revisionName)") + echo "Current revision: $REVISION" + # Set for parent workflow (Environment file) + echo "revision=$REVISION" >> $GITHUB_OUTPUT + + # 2ī¸âƒŖ Deploy new image + - name: Deploy new image + id: deploy + run: | + IMAGE_URI="${{ inputs.gcp_registry_host }}/${{ secrets.GCP_PROJECT_ID }}/${{ inputs.GCP_REPOSITORY }}/${{ inputs.IMAGE_NAME }}:${{ inputs.IMAGE_TAG }}" + echo "🚀 Deploying $IMAGE_URI" + gcloud run deploy ${{ inputs.SERVICE_NAME }} \ + --image "$IMAGE_URI" \ + --region ${{ inputs.REGION }} \ + --platform managed \ + --quiet +... diff --git a/docs/30.tfdrift.md b/docs/31.tfdrift.md similarity index 100% rename from docs/30.tfdrift.md rename to docs/31.tfdrift.md diff --git a/docs/32.cloudrun-rollback.md b/docs/32.cloudrun-rollback.md new file mode 100644 index 00000000..ac6eb150 --- /dev/null +++ b/docs/32.cloudrun-rollback.md @@ -0,0 +1,98 @@ +## [Cloud Run Deploy with Auto Rollback reusable workflow](https://github.com/clouddrove/github-shared-workflows/blob/master/.github/workflows/shared-cloudrun-rollback.yml) + + + +### Overview + +The Cloud Run Deploy with Auto Rollback workflow: + +* Deploys a new Docker image to a Cloud Run service + +* Captures the currently active revision before deployment + +* Exposes the previous revision as an output for rollback + +* Enables parent workflows to trigger rollback automatically on failure + +This workflow helps ensure safer production deployments and faster recovery in case of issues. + +### Workflow Location +``` +.github/workflows/shared-cloudrun-rollback.yml +``` +#### Example +```yaml + +name: Deploy to Cloud Run + +on: + workflow_dispatch: + +jobs: + deploy-backend: + uses: clouddrove/github-shared-workflows/.github/workflows/shared-cloudrun-rollback.yml@master + with: + gcp_registry_host: # GCP Artifact Registry host + IMAGE_NAME: # Docker image name + IMAGE_TAG: # Image tag to deploy + SERVICE_NAME: # Cloud Run service name + REGION: # GCP region + GCP_REPOSITORY: # Artifact Registry repository + secrets: + GCP_PROJECT_ID: # GCP Project ID + GCP_SA_KEY: # GCP Service Account key (JSON) + + rollback-all: + needs: + - deploy-backend + if: ${{ failure() }} + runs-on: ubuntu-latest + + steps: + - name: Authenticate to GCP + uses: google-github-actions/auth@v2 + with: + credentials_json: # GCP Service Account key (JSON) + + - name: Setup gcloud + uses: google-github-actions/setup-gcloud@v2 + with: + project_id: # GCP Project ID + + - name: Rollback Cloud Run services (if needed) + run: | + echo "🚨 Rollback triggered because a deployment failed" + + REGION= # GCP region + PROJECT= # GCP Project ID + + rollback_if_needed () { + SERVICE_NAME=$1 + PREV_REV=$2 + + if [ -z "$PREV_REV" ]; then + echo "â„šī¸ $SERVICE_NAME was not deployed, skipping rollback" + return + fi + + CURRENT_REV=$(gcloud run services describe "$SERVICE_NAME" \ + --region "$REGION" \ + --project "$PROJECT" \ + --format="value(status.traffic[0].revisionName)") + + if [ "$CURRENT_REV" = "$PREV_REV" ]; then + echo "✅ $SERVICE_NAME rollback not required — traffic already on previous revision ($PREV_REV)" + else + echo "🔄 Rolling back $SERVICE_NAME to revision: $PREV_REV" + gcloud run services update-traffic "$SERVICE_NAME" \ + --to-revisions="$PREV_REV=100" \ + --region "$REGION" \ + --project "$PROJECT" \ + && echo "✅ $SERVICE_NAME rollback successful" \ + || echo "âš ī¸ $SERVICE_NAME rollback failed — traffic may already be correct" + fi + } + + rollback_if_needed "# Cloud Run service name" "${{ needs.deploy-backend.outputs.revision }}" + +``` \ No newline at end of file