Skip to content

[WIP] Add auto-merge-and-tag workflow to promote the release commit to master - #5127

Open
prateekchaudhry wants to merge 1 commit into
aws:devfrom
prateekchaudhry:auto-merge-and-tag
Open

[WIP] Add auto-merge-and-tag workflow to promote the release commit to master#5127
prateekchaudhry wants to merge 1 commit into
aws:devfrom
prateekchaudhry:auto-merge-and-tag

Conversation

@prateekchaudhry

@prateekchaudhry prateekchaudhry commented Sep 4, 2026

Copy link
Copy Markdown
Contributor

Summary

Previously we have added an automation to create release PRs - #4892

This PR continues the release automation effort to "auto merge" release PRs once we have human approvals. The requirement of a release push is to have dev and master in sync.

This has so far been done by merging the release PR -

  1. to dev by merge commit
  2. to master by a push

The result of this is that we have same Git SHAs in both branches. However this process has been manual so far.

This PR automates it using GitHub Actions.

Implementation details

  • Workflow triggers on any PR closed against dev, and is split into two jobs.
  • classify decides whether the merge is a release promotion - the branch must be merged, named v<X.Y.Z>-stage, and parse as semver. It outputs is_release and the version.
  • The split into two jobs is what gives a genuine SKIPPED promote for every unrelated PR merged into dev, instead of a red X on every merge, or a green that looks the same as a real release.
  • promote does what a human does today, in order: check the version isn't already released, fast-forward master to the release commit, extract that version's CHANGELOG.md section, then create the v<X.Y.Z> tag and draft the release with that section as the body. Publishing the draft stays manual.
  • Everything is pinned to the release commit from the PR event (head.sha), so the promotion targets exactly the commit that was reviewed.
  • promote also verifies the release commit is reachable from dev before pushing. Fast-forward-only looks sufficient here but isn't - a squash or rebase merge creates a new SHA and orphans the release commit, and master is still an ancestor of that orphan, so the push would succeed and leave master on a line dev abandoned. Without this check we would only find out at the next release.
  • Uses the GitHub App token (existing APP_ID / APP_PRIVATE_KEY secrets), minted before checkout so the push to master carries the App's credentials rather than the default GITHUB_TOKEN.

Please note: this needs a paired update to master's branch protection so the App is allowed to push. Until that is applied, promote will fail at the push step - nothing is tagged or drafted and master is not moved, so the manual process still works as it does today, and the job can be re-run once the protection update is in place.

Testing

Tested on my fork with protected dev and master, running the real two-workflow chain - create-release-pr to open the release PR, then merging it to trigger this one.

  • Happy path: merging the release PR as a merge commit fast-forwarded master to the release commit, created the tag and drafted the release with the changelog section as its body. dev and master ended up with the same SHA. Release PR: Release 9.99.10 prateekchaudhry/amazon-ecs-agent#43
  • Merging an unrelated PR into dev left both jobs skipped

Not verifiable on a fork: app-level push restrictions can't be configured on a personal repo, so the "only the App can push master" part is only exercisable here.

New tests cover the changes:
No - workflow change

Description for the changelog

Housekeeping: add an action to automate merging release PRs to master.

Additional Information

Does this PR include breaking model changes? If so, Have you added transformation functions? N/A

Does this PR include the addition of new environment variables in the README? N/A

Licensing

By submitting this pull request, I confirm that my contribution is made under the terms of the Apache 2.0 license.

Today the release commit reaches master by hand: an operator disables
master's branch protection, pushes the stage branch, then re-enables it.
This adds a workflow that performs the same promotion automatically once
the release PR merges into dev, so the protection rule is never disabled
and instead carries a single named exception for the App.

Two jobs:

  classify  Runs only for a merged v<X.Y.Z>-stage branch whose name
            parses as semver. Splitting this out is what produces a
            genuine SKIPPED promote for every unrelated PR merged into
            dev, rather than a red X or an indistinguishable green.

  promote   Refuses if the version already has a release or tag, checks
            the release commit is reachable from dev, fast-forwards
            master to it, extracts that version's CHANGELOG.md section,
            then creates the v<X.Y.Z> tag and drafts the GitHub release.
            Publishing the draft stays a separate manual step.

The reachability check is the load-bearing one. A squash or rebase merge
mints a new SHA and orphans the release commit from dev, yet master is
still an ancestor of that orphan, so the fast-forward push SUCCEEDS and
master silently diverges from dev. Detection would otherwise be deferred
to the next release's push rejection, after the bad release had shipped.

The App token is minted before actions/checkout and passed via its
token: input, because master will restrict pushes to the App and the
default GITHUB_TOKEN is attributed to github-actions[bot], which is not
on that allowlist. permission-contents: write narrows the token from the
App's full installation scope to the only scope promote needs.

Attacker-influenced event fields (head.ref, head.sha) are passed through
step-level env: rather than interpolated into run: blocks, since ${{ }}
is substituted before bash parses the script.

Requires a paired change to master's branch protection: lock_branch off,
and restrictions set to apps: ["amazon-ecs-bot"]. Until that lands
master is locked to everyone including the App, and promote fails at the
push step.
@prateekchaudhry
prateekchaudhry requested a review from a team as a code owner September 4, 2026 23:26
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