From 3f1425b46f7bdbf459beb5455682e213f2ffa8d0 Mon Sep 17 00:00:00 2001 From: hongming-codex-laptop Date: Wed, 13 May 2026 15:57:11 -0700 Subject: [PATCH] fix(ci): harden production redeploy workflow --- .gitea/workflows/redeploy-tenants-on-main.yml | 45 ++++++++++++------- 1 file changed, 28 insertions(+), 17 deletions(-) diff --git a/.gitea/workflows/redeploy-tenants-on-main.yml b/.gitea/workflows/redeploy-tenants-on-main.yml index 2e216ff4..6fdd803b 100644 --- a/.gitea/workflows/redeploy-tenants-on-main.yml +++ b/.gitea/workflows/redeploy-tenants-on-main.yml @@ -77,13 +77,11 @@ env: GITHUB_SERVER_URL: https://git.moleculesai.app jobs: + # bp-exempt: production redeploy is a side-effect workflow, not a merge gate. redeploy: - # Skip the auto-trigger if publish-workspace-server-image didn't - # actually succeed. workflow_run fires on any completion state; we - # don't want to redeploy against a half-built image. - # NOTE (Gitea port): workflow_dispatch trigger dropped; only the - # workflow_run path remains. - if: ${{ github.event.workflow_run.conclusion == 'success' }} + # Gitea 1.22.6 does not support workflow_run. This workflow is now + # controlled by push/path triggers plus an explicit kill switch. + if: ${{ github.event_name == 'push' || github.event_name == 'workflow_dispatch' }} runs-on: ubuntu-latest # Phase 3 (RFC #219 §1): surface broken workflows without blocking. # mc#774: pre-existing continue-on-error mask; root-fix and remove, do not renew silently. @@ -120,15 +118,15 @@ jobs: # the only thing retagging `:latest` today is the manual # promote-latest.yml — last run 2026-04-28). Auto-trigger # from workflow_run uses workflow_run.head_sha; manual - # dispatch with no input falls through to github.sha. + # dispatch with no variable falls through to github.sha. env: - INPUT_TAG: ${{ inputs.target_tag }} - HEAD_SHA: ${{ github.event.workflow_run.head_sha || github.sha }} + PROD_MANUAL_REDEPLOY_TARGET_TAG: ${{ vars.PROD_MANUAL_REDEPLOY_TARGET_TAG || secrets.PROD_MANUAL_REDEPLOY_TARGET_TAG || '' }} + HEAD_SHA: ${{ github.sha }} run: | set -euo pipefail - if [ -n "${INPUT_TAG:-}" ]; then - echo "target_tag=$INPUT_TAG" >> "$GITHUB_OUTPUT" - echo "Using operator-pinned tag: $INPUT_TAG" + if [ -n "${PROD_MANUAL_REDEPLOY_TARGET_TAG:-}" ]; then + echo "target_tag=$PROD_MANUAL_REDEPLOY_TARGET_TAG" >> "$GITHUB_OUTPUT" + echo "Using operator-pinned tag from PROD_MANUAL_REDEPLOY_TARGET_TAG." else SHORT="${HEAD_SHA:0:7}" echo "target_tag=staging-$SHORT" >> "$GITHUB_OUTPUT" @@ -144,13 +142,26 @@ jobs: CP_URL: ${{ vars.CP_URL || 'https://api.moleculesai.app' }} CP_ADMIN_API_TOKEN: ${{ secrets.CP_ADMIN_API_TOKEN }} TARGET_TAG: ${{ steps.tag.outputs.target_tag }} - CANARY_SLUG: ${{ inputs.canary_slug || 'hongming' }} - SOAK_SECONDS: ${{ inputs.soak_seconds || '60' }} - BATCH_SIZE: ${{ inputs.batch_size || '3' }} - DRY_RUN: ${{ inputs.dry_run || false }} + CANARY_SLUG: ${{ vars.PROD_REDEPLOY_CANARY_SLUG || secrets.PROD_REDEPLOY_CANARY_SLUG || '' }} + SOAK_SECONDS: ${{ vars.PROD_REDEPLOY_SOAK_SECONDS || secrets.PROD_REDEPLOY_SOAK_SECONDS || '' }} + BATCH_SIZE: ${{ vars.PROD_REDEPLOY_BATCH_SIZE || secrets.PROD_REDEPLOY_BATCH_SIZE || '' }} + DRY_RUN: ${{ vars.PROD_REDEPLOY_DRY_RUN || secrets.PROD_REDEPLOY_DRY_RUN || '' }} + PROD_AUTO_DEPLOY_DISABLED: ${{ vars.PROD_AUTO_DEPLOY_DISABLED || secrets.PROD_AUTO_DEPLOY_DISABLED || '' }} run: | set -euo pipefail + case "${PROD_AUTO_DEPLOY_DISABLED,,}" in + 1|true|yes|on) + echo "::notice::PROD_AUTO_DEPLOY_DISABLED is set; skipping production redeploy." + exit 0 + ;; + esac + + CANARY_SLUG="${CANARY_SLUG:-hongming}" + SOAK_SECONDS="${SOAK_SECONDS:-60}" + BATCH_SIZE="${BATCH_SIZE:-3}" + DRY_RUN="${DRY_RUN:-false}" + if [ -z "${CP_ADMIN_API_TOKEN:-}" ]; then echo "::error::CP_ADMIN_API_TOKEN secret not set — skipping redeploy" echo "::notice::Set CP_ADMIN_API_TOKEN in repo secrets to enable auto-redeploy." @@ -172,7 +183,7 @@ jobs: }') echo "POST $CP_URL/cp/admin/tenants/redeploy-fleet" - echo " body: $BODY" + echo " target_tag=$TARGET_TAG canary=$CANARY_SLUG soak_seconds=$SOAK_SECONDS batch_size=$BATCH_SIZE dry_run=$DRY_RUN" HTTP_RESPONSE=$(mktemp) HTTP_CODE_FILE=$(mktemp)