From 21e6d4b742150df56864b05bccef8da7a115905a Mon Sep 17 00:00:00 2001 From: Talisson Costa Date: Thu, 27 Aug 2026 17:24:34 -0300 Subject: [PATCH] ci(frontend-deploy): announce a deploy when it starts The channel went quiet for the eleven minutes between a push and its outcome, so there was no way to tell a deploy was in flight, which is exactly when that matters: it is the window in which pushing again supersedes someone. Adds a card at the start, carrying the commit and who pushed it, like the outcome card. It has no needs, so it lands within seconds rather than after the tests. The action's conclusion input becomes state, since in_progress is not a conclusion. Distinct emoji and no Open Production button, because the two cards otherwise look alike while scanning and production has not changed yet. Co-Authored-By: Claude Opus 5 (1M context) --- .../actions/notify-slack-deploy/action.yml | 11 ++++--- .../actions/notify-slack-deploy/payload.jq | 15 ++++++--- .../workflows/frontend-deploy-production.yml | 31 ++++++++++++++++++- 3 files changed, 47 insertions(+), 10 deletions(-) diff --git a/.github/actions/notify-slack-deploy/action.yml b/.github/actions/notify-slack-deploy/action.yml index 261849312fcd..0074de2e4ff4 100644 --- a/.github/actions/notify-slack-deploy/action.yml +++ b/.github/actions/notify-slack-deploy/action.yml @@ -15,10 +15,11 @@ inputs: description: The environment that was deployed to. required: false default: production - conclusion: + state: description: > - The deploy run's conclusion, straight from workflow_run. Only success and - cancelled get their own copy; anything else reads as a failure. + in_progress before the deploy runs, otherwise the production job's + result. Only in_progress, success and cancelled get their own copy; + anything else reads as a failure. required: true commit_sha: description: The commit that was deployed. @@ -47,7 +48,7 @@ runs: SERVICE: ${{ inputs.service }} APP_URL: ${{ inputs.app_url }} ENVIRONMENT: ${{ inputs.environment }} - CONCLUSION: ${{ inputs.conclusion }} + STATE: ${{ inputs.state }} COMMIT_SHA: ${{ inputs.commit_sha }} ACTOR: ${{ inputs.actor }} RUN_URL: ${{ inputs.run_url }} @@ -77,7 +78,7 @@ runs: jq -n \ --arg service "$SERVICE" \ --arg environment "$ENVIRONMENT" \ - --arg conclusion "$CONCLUSION" \ + --arg state "$STATE" \ --arg short_sha "${COMMIT_SHA:0:7}" \ --arg actor "$ACTOR" \ --arg app_url "$APP_URL" \ diff --git a/.github/actions/notify-slack-deploy/payload.jq b/.github/actions/notify-slack-deploy/payload.jq index 1481a9f637fb..4cb7ae91fb34 100644 --- a/.github/actions/notify-slack-deploy/payload.jq +++ b/.github/actions/notify-slack-deploy/payload.jq @@ -3,16 +3,23 @@ ($environment | (.[0:1] | ascii_upcase) + .[1:]) as $env_name | -# Only success and cancelled need their own words. Everything else GitHub -# reports, timed_out and skipped included, means the deploy did not happen. -(if $conclusion == "success" then +# Only in_progress, success and cancelled need their own words. Everything +# else, timed_out and skipped included, means the deploy did not happen. +(if $state == "in_progress" then + { + headline: "⏳ \($service) deploying to \($environment)", + body: "Tests and deploy are running. \($env_name) is still on the previous release.", + actor_label: "Pushed by", + link_app: false + } +elif $state == "success" then { headline: "🚀 \($service) deployed to \($environment)", body: "🧪 *\($env_name) smoke test required*\n\nPlease verify the application directly in \($environment).", actor_label: "Deployed by", link_app: true } -elif $conclusion == "cancelled" then +elif $state == "cancelled" then { headline: "⏭️ \($service) deploy to \($environment) stopped", # run-tests cancels itself in progress when the next commit lands on main, diff --git a/.github/workflows/frontend-deploy-production.yml b/.github/workflows/frontend-deploy-production.yml index 0f822539f5b2..b40ddb235f63 100644 --- a/.github/workflows/frontend-deploy-production.yml +++ b/.github/workflows/frontend-deploy-production.yml @@ -9,6 +9,35 @@ on: - .github/** jobs: + notify-production-deploy-started: + name: Notify Production Deploy Started + # No needs, so this lands within seconds of the push. Knowing a deploy is + # in flight is only useful while it still is. + runs-on: ubuntu-latest + permissions: + # Enough to resolve the local action below. + contents: read + + steps: + - name: Cloning repo + uses: actions/checkout@fbc6f3992d24b796d5a048ff273f7fcc4a7b6c09 # v5.1.0 + with: + # Nothing runs git after this, so the token need not persist. + persist-credentials: false + + - name: Notify Slack + # A Slack outage must not hold up a deploy. + continue-on-error: true + uses: ./.github/actions/notify-slack-deploy + with: + webhook_url: ${{ secrets.SLACK_FRONTEND_DEPLOY_WEBHOOK }} + service: Frontend + app_url: https://app.flagsmith.com + state: in_progress + commit_sha: ${{ github.sha }} + actor: ${{ github.actor }} + run_url: ${{ github.server_url }}/${{ github.repository }}/actions/runs/${{ github.run_id }} + run-unit-tests: runs-on: ubuntu-latest name: Run Unit Tests @@ -136,7 +165,7 @@ jobs: webhook_url: ${{ secrets.SLACK_FRONTEND_DEPLOY_WEBHOOK }} service: Frontend app_url: https://app.flagsmith.com - conclusion: ${{ steps.outcome.outputs.conclusion }} + state: ${{ steps.outcome.outputs.conclusion }} commit_sha: ${{ github.sha }} actor: ${{ github.actor }} run_url: ${{ github.server_url }}/${{ github.repository }}/actions/runs/${{ github.run_id }}