Skip to content

feat(ci): promote Trigger.dev tasks in lockstep with the ECS traffic cutover#5725

Open
TheodoreSpeaks wants to merge 3 commits into
stagingfrom
trigger-deploy
Open

feat(ci): promote Trigger.dev tasks in lockstep with the ECS traffic cutover#5725
TheodoreSpeaks wants to merge 3 commits into
stagingfrom
trigger-deploy

Conversation

@TheodoreSpeaks

Copy link
Copy Markdown
Collaborator

Summary

  • Move Trigger.dev staging + production deploys into CI (off the git-integration auto-deploy), deploying with --skip-promotion so new task runs keep executing the old version until we promote.
  • Promote the deployed version at the exact ECS traffic cutover: a new promote-trigger-* job polls CodeDeploy (AllowTraffic) and then runs trigger promote, so tasks and app cut over in lockstep instead of tasks flipping ~4–50 min early (the prod bake queue).
  • Correlate this push to its ECS deploy via the app image digest (build-amd64 publishes it as an artifact) → CodePipeline execution → CodeDeploy deployment id → AllowTraffic. ECR deploy tags are floating, so the digest is the only durable key.
  • Gate promotion on promote-images.promoted: when the stale-run guard skips the image retag, tasks correctly stay on the old version. If the app deploy fails or never cuts over, promote never fires and the job fails visibly.
  • New .github/scripts/wait-for-ecs-cutover.sh does the poll; verified end-to-end against real staging deploys (digest → d-…AllowTraffic).

Prerequisites before this runs on staging/prod

  • Add CodePipeline + CodeDeploy read perms to the OIDC deploy roles (STAGING_AWS_ROLE_TO_ASSUME, AWS_ROLE_TO_ASSUME), which are managed outside the repo: codepipeline:ListPipelineExecutions/GetPipelineExecution/ListActionExecutions, codedeploy:GetDeployment/ListDeploymentTargets/GetDeploymentTarget.
  • Set the TRIGGER_ACCESS_TOKEN repo secret (a Trigger.dev PAT; spans all environments). Then disable the Trigger.dev git integration for staging/prod.

Type of Change

  • New feature (CI/CD)

Testing

  • Ran wait-for-ecs-cutover.sh against real completed staging deployments: correctly resolved digest → pipeline execution → CodeDeploy deployment → AllowTraffic (exit 0), and timed out cleanly on an unmatched digest (exit 1).
  • actionlint clean (only pre-existing custom-runner-label warnings); bun run lint and bun run check:api-validation:strict pass; YAML validated.

Checklist

  • Code follows project style guidelines
  • Self-reviewed my changes
  • Tests added/updated and passing
  • No new warnings introduced
  • I confirm that I have read and agree to the terms outlined in the Contributor License Agreement (CLA)

@vercel

vercel Bot commented Jul 17, 2026

Copy link
Copy Markdown

The latest updates on your projects. Learn more about Vercel for GitHub.

Project Deployment Actions Updated (UTC)
docs Ready Ready Preview, Comment Jul 19, 2026 9:00pm

Request Review

@cursor

cursor Bot commented Jul 17, 2026

Copy link
Copy Markdown

PR Summary

Medium Risk
Changes production deploy sequencing for app and background tasks; mis-correlation or missing AWS read IAM could block promotion or delay cutover, but app deploy path is unchanged and stale-run guards limit accidental early promote.

Overview
Moves main/staging Trigger.dev deploys into CI and delays task promotion until the ECS app has finished its blue/green traffic shift, so background tasks and the app cut over together instead of tasks flipping minutes earlier.

A new deploy-trigger job uploads task versions with --skip-promotion (parallel to image build, not blocking app deploy). build-amd64 publishes the app image digest as an artifact; promote-images now exports promoted and retag_epoch when deploy tags move. promote-trigger runs only when promotion actually happened, polls via .github/scripts/wait-for-ecs-cutover.sh (digest + retag time → CodePipeline → CodeDeploy AllowTraffic on all targets), then runs trigger promote for the version from deploy-trigger. If ECS never cuts over or the stale-run guard skips retagging, promotion is skipped or the job fails visibly.

Reviewed by Cursor Bugbot for commit f7135b0. Bugbot is set up for automated code reviews on this repo. Configure here.

Comment thread .github/workflows/ci.yml
Comment thread .github/scripts/wait-for-ecs-cutover.sh
@greptile-apps

greptile-apps Bot commented Jul 17, 2026

Copy link
Copy Markdown
Contributor

Greptile Summary

This PR coordinates Trigger.dev task promotion with the ECS traffic cutover. The main changes are:

  • Deploy Trigger.dev versions from CI without immediately promoting them.
  • Publish the app image digest and correlate it with the matching CodePipeline execution.
  • Wait for successful AllowTraffic events across all ECS deployment targets.
  • Promote the Trigger.dev version only after the app traffic shift.

Confidence Score: 5/5

The latest fixes look safe to merge.

  • The timestamp filter prevents old same-digest deployments from satisfying the normal cutover gate.
  • The cutover loop now requires successful AllowTraffic status for every returned ECS target.
  • No additional blocking issue met the scope for this follow-up review.

Important Files Changed

Filename Overview
.github/scripts/wait-for-ecs-cutover.sh Adds polling that resolves the matching CodeDeploy deployment and waits for every ECS target to complete its traffic shift.
.github/workflows/ci.yml Adds staged Trigger.dev deployment and promotion jobs tied to the ECS image promotion workflow.

Reviews (3): Last reviewed commit: "fix(ci): widen promote-trigger job timeo..." | Re-trigger Greptile

Comment thread .github/scripts/wait-for-ecs-cutover.sh Outdated
Comment thread .github/scripts/wait-for-ecs-cutover.sh Outdated
@TheodoreSpeaks

Copy link
Copy Markdown
Collaborator Author

@greptile review

@TheodoreSpeaks

Copy link
Copy Markdown
Collaborator Author

@cursor review

Comment thread .github/workflows/ci.yml
Comment thread .github/workflows/ci.yml Outdated
Comment thread .github/workflows/ci.yml
uses: aws-actions/configure-aws-credentials@e7f100cf4c008499ea8adda475de1042d6975c7b # v6
with:
role-to-assume: ${{ github.ref == 'refs/heads/main' && secrets.AWS_ROLE_TO_ASSUME || secrets.STAGING_AWS_ROLE_TO_ASSUME }}
aws-region: ${{ github.ref == 'refs/heads/main' && secrets.AWS_REGION || secrets.STAGING_AWS_REGION }}

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

AWS creds expire before poll

High Severity

promote-trigger assumes the deploy role with the default ~60-minute session and never sets role-duration-seconds, while wait-for-ecs-cutover.sh is built to poll for up to 70 minutes (the prod bake-queue case). After the session expires, AWS calls fail; those errors are swallowed, so the script keeps retrying until timeout and never promotes. The long-wait path this change was written for leaves the app cut over while Trigger.dev stays on the old version.

Additional Locations (1)
Fix in Cursor Fix in Web

Reviewed by Cursor Bugbot for commit f7135b0. Configure here.

@TheodoreSpeaks

Copy link
Copy Markdown
Collaborator Author

@greptile review

@TheodoreSpeaks

Copy link
Copy Markdown
Collaborator Author

@cursor review

@cursor cursor Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Cursor Bugbot has reviewed your changes using default effort and found 1 potential issue.

There are 2 total unresolved issues (including 1 from previous review).

Fix All in Cursor

❌ Bugbot Autofix is OFF. To automatically fix reported issues with cloud agents, enable autofix in the Cursor dashboard.

Reviewed by Cursor Bugbot for commit f7135b0. Configure here.

log "No matching post-retag pipeline execution yet; retry in ${POLL_INTERVAL}s (remaining $(remaining)s)"
sleep "$POLL_INTERVAL"
fi
done

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Same digest blocks task promotion

Medium Severity

Phase A requires a CodePipeline execution for the app digest with startTime at/after retag_epoch. That rejects the historical same-digest run this filter was added for, but retagging latest/staging to a digest it already points at is often a no-op for ECR (no new EventBridge/pipeline). The poll then never finds a post-retag execution and times out, so the skip-promoted Trigger.dev version from deploy-trigger is never promoted—especially on re-runs after promote-images already moved the tag, or any push that reuses the app image digest (Trigger tasks live in background/ and are not in the final app image).

Additional Locations (1)
Fix in Cursor Fix in Web

Reviewed by Cursor Bugbot for commit f7135b0. Configure here.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant