Skip to content

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

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.
  • classify also requires the release PR to have been opened by amazon-ecs-bot[bot], so only a PR that create-release-pr generated is promoted automatically. This one fails rather than skipping: a manually staged release is a real release, so it should be visible in the run list rather than silently doing nothing. The operator promotes master by hand in that case, which is the process today.
  • 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, extract that version's CHANGELOG.md section, fast-forward master to the release commit, then draft the release with that section as the body. Both checks run before the push, so a failed check leaves master untouched. Publishing the draft stays manual, and is what creates the v<X.Y.Z> tag.
  • 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 - no release is 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. Fork dev was reverted between cases so each ran from the same state.

Happy path tested - merged the release PR as a merge commit:

  • master fast-forwarded to the release commit, and the release was drafted with that version's CHANGELOG.md section as its body
  • Both branches ended up on the same tree, with master on dev's history
  • The draft carries no tag until it is published
  • Release PR: Release 9.100.7 prateekchaudhry/amazon-ecs-agent#50

Failure paths tested - each stopped at its own check, with master untouched and nothing drafted:

Squash-merged the release PR

  • Failed at the ancestor check - the squash mints a new SHA on dev and orphans the release commit

Release branch with no # X.Y.Z section in CHANGELOG.md

  • Failed at the changelog extract, which runs before the push

Version that already had a v<X.Y.Z> tag but no release object

  • Failed at the already-released check

Release PR opened by an author other than the release bot

  • Failed at the author check in classify, before promote was reached at all

Skipped as intended: merging an unrelated PR into dev, and closing a release PR without merging it.

Description for the changelog

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

Licensing

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

@prateekchaudhry
prateekchaudhry requested a review from a team as a code owner September 4, 2026 23:26
@prateekchaudhry prateekchaudhry changed the title [WIP] Add auto-merge-and-tag workflow to promote the release commit to master Add auto-merge-and-tag workflow to promote the release commit to master Sep 9, 2026
@prateekchaudhry
prateekchaudhry force-pushed the auto-merge-and-tag branch 2 times, most recently from 6b9aa18 to 97f97cb Compare September 9, 2026 00:49
if gh release view "v${AGENT_VERSION}" --repo "${{ github.repository }}" >/dev/null 2>&1 || \
gh api "repos/${{ github.repository }}/git/refs/tags/v${AGENT_VERSION}" >/dev/null 2>&1; then
echo "::error::Version ${AGENT_VERSION} already has a GitHub release or a v${AGENT_VERSION} tag. Delete whichever exists (a draft release has no tag yet) and re-run this workflow."
exit 1

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Q: Do we want some kind of alarming when this github action fails like we do for our other automated github workflows?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Completion of GH Action will be manually verified by the person who creates the release PR, as that step is manual. I don't think we should need to add alarms here as long as we document this properly.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Hm I see, thanks. I was under the impression that the PR merge will be done manually and then these will take care of the sync to master for us automatically.

found && /^# / { exit }
found { print }
' /tmp/full-changelog.md > /tmp/release-notes.md
# Test for real content, not file size: an empty section yields a blank line, which -s counts as non-empty.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

We may want to move this logic to the release PR generation if it's not already there so that it can catch this sooner rather than at this point of the release. Or is this more of a defense check?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

This is a validation check here.

But it is a good candidate to be added in PR Generation script as well, currently we have it at warning there. We can add it as a different change.

# gh release view only finds a Release object; check the tag itself too, since a tag can survive a deleted release.
if gh release view "v${AGENT_VERSION}" --repo "${{ github.repository }}" >/dev/null 2>&1 || \
gh api "repos/${{ github.repository }}/git/refs/tags/v${AGENT_VERSION}" >/dev/null 2>&1; then
echo "::error::Version ${AGENT_VERSION} already has a GitHub release or a v${AGENT_VERSION} tag. Delete whichever exists (a draft release has no tag yet) and re-run this workflow."

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Q: Do we want to make this a bit more specific in regards to not delete already published release notes?

@prateekchaudhry
prateekchaudhry force-pushed the auto-merge-and-tag branch 3 times, most recently from 33314ca to ce06084 Compare September 10, 2026 17:55
Promotes the release commit to master automatically once the release PR
merges into dev. This is a manual step today.

classify runs only for a merged v<X.Y.Z>-stage branch that parses as
semver, so promote is skipped on unrelated merges into dev. It fails if
that PR was not opened by amazon-ecs-bot, so a manually staged release
stops here rather than promoting.

promote checks the version is not already released, extracts the
changelog section, verifies the release commit is reachable from dev,
fast-forwards master, then drafts the release. Publishing the draft
stays manual and creates the tag.

The reachability check rejects a squash or rebase merge, which would
otherwise leave master on a commit dev no longer contains.

Requires a paired change to master's branch protection so the App can
push. Until then promote fails at the push step, leaving master unmoved.
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.

4 participants