Skip to content

[release process update] add force_republish option & release/<version> branches#80

Merged
Erik Weathers (erikdw) merged 5 commits intomainfrom
erikdw/branch-based-releases-with-republish-support
Apr 22, 2026
Merged

[release process update] add force_republish option & release/<version> branches#80
Erik Weathers (erikdw) merged 5 commits intomainfrom
erikdw/branch-based-releases-with-republish-support

Conversation

@erikdw
Copy link
Copy Markdown
Contributor

@erikdw Erik Weathers (erikdw) commented Apr 22, 2026

Summary

Adds a force_republish workflow input to recover from incomplete releases, and introduces release/<version> branches so every release has a clean, reproducible artifact branch with the correct Chart.yaml.

Issue that inspired this PR

If the release workflow fails or is never run for a given version, there's no way to re-publish that version's chart without either bumping to a new dot release or manually running helm push locally — the tag existence check blocks re-runs.

Specific recent releases that didn't have their chart published to ECR:

  • 5.1.0
  • 6.0.0
  • 6.1.0

Solution

Add support for republishing releases. This led to using release branches as well, because the original release process only operated on the main branch, and that wouldn't work for republishing older releases. We need to rewind the repo to the state at the point of the incomplete release and publish from that. The solution is to stop operating only on main, and instead publish from release branches.

New: force_republish input

A new boolean dispatch input (default false) allows re-running the release workflow for a version that previously failed partway through.

  • Validation requires the tag to already exist (errors if it doesn't — nothing to republish from)
  • The existing GitHub release and tag are deleted, then fully recreated from scratch
  • The existing release/<version> branch is also deleted and recreated
  • Main is not updated — only the release branch is touched

New: release/<version> branches

Every release now creates a dedicated release/$CHART_VERSION branch:

  • Normal flow: version bumps (services + chart) are committed and pushed to main as before, then release/$CHART_VERSION is branched off main's new HEAD and pushed.
  • force_republish flow: a fresh release/$CHART_VERSION is created from the SHA the broken tag pointed to, the Chart.yaml bump is re-applied (idempotent), and the branch is pushed.

gh release create now uses --target release/$CHART_VERSION in both paths, so the git tag is always created from a commit guaranteed to have the correct Chart.yaml version.

Other fixes

  • fetch-tags: true added to the checkout step so the tag existence check and git rev-parse in force_republish mode work correctly
  • GH_TOKEN added to the "Prepare release branch" step (needed for gh release delete / gh release view)

Testing

Tested against erikdw/branch-based-releases-with-republish-support via gh workflow run.

Normal flow (0.0.2-test)

Triggered with version=0.0.2-test, no force_republish. Verified:

  • release/0.0.2-test branch created and pushed
  • Chart.yaml bumped and pushed to main
  • Draft release created via gh release create --target release/0.0.2-test
  • Helm chart packaged successfully (braintrust-0.0.2-test.tgz)
  • Release published with correct notes

force_republish flow (0.0.3-test)

Set up broken state by manually creating tag 0.0.3-test and a draft GitHub release, then triggered with version=0.0.3-test, force_republish=true. Verified:

  • Tag existence check passed, SHA captured (8f0e5e2)
  • Existing release and tag deleted via gh release delete --cleanup-tag
  • Fresh release/0.0.3-test branch created from the captured SHA
  • Chart.yaml bumped on the release branch (main not touched)
  • Release recreated, packaged, and published successfully

Note

Disabled the helm push to ECR for these 2 tests, since I lack permission to clean up the test artifacts there. Earlier test left some detritus that can be cleaned up: public.ecr.aws/braintrust/helm/braintrust:0.0.1-test

Warning

Tests as listed above weren't great because we still push to the main branch in the "normal" path, if we test again with this strategy we should disable any modifications to main.

…sion>` branches

## Summary

Adds a `force_republish` workflow input to recover from incomplete releases, and
introduces `release/<version>` branches so every release has a clean, reproducible
artifact branch with the correct `Chart.yaml`.

### New: `force_republish` input

A new boolean dispatch input (default `false`) allows re-running the release
workflow for a version that previously failed partway through.

- Validation requires the tag to already exist (errors if it doesn't — nothing to
  republish from)
- The existing GitHub release and tag are deleted, then fully recreated from scratch
- The existing `release/<version>` branch is also deleted and recreated
- Main is **not** updated — only the release branch is touched

### New: `release/<version>` branches

Every release now creates a dedicated `release/$CHART_VERSION` branch:

- **Normal flow**: version bumps (services + chart) are committed and pushed to
  main as before, then `release/$CHART_VERSION` is branched off main's new HEAD
  and pushed.
- **`force_republish` flow**: a fresh `release/$CHART_VERSION` is created from the
  SHA the broken tag pointed to, the `Chart.yaml` bump is re-applied (idempotent),
  and the branch is pushed.

`gh release create` now uses `--target release/$CHART_VERSION` in both paths, so
the git tag is always created from a commit guaranteed to have the correct
`Chart.yaml` version.

### Other fixes

- `fetch-tags: true` added to the checkout step so the tag existence check and
  `git rev-parse` in `force_republish` mode work correctly
- `GH_TOKEN` added to the "Prepare release branch" step (needed for `gh release
  delete` / `gh release view`)

### Testing

Tested against `erikdw/branch-based-releases-with-republish-support` via `gh workflow run`.

**Normal flow (`0.0.2-test`)**

Triggered with `version=0.0.2-test`, no `force_republish`. Verified:
- `release/0.0.2-test` branch created and pushed
- Chart.yaml bumped and pushed to main
- Draft release created via `gh release create --target release/0.0.2-test`
- Helm chart packaged successfully (`braintrust-0.0.2-test.tgz`)
- Release published with correct notes

**`force_republish` flow (`0.0.3-test`)**

Set up broken state by manually creating tag `0.0.3-test` and a draft GitHub release,
then triggered with `version=0.0.3-test`, `force_republish=true`. Verified:
- Tag existence check passed, SHA captured (`8f0e5e2`)
- Existing release and tag deleted via `gh release delete --cleanup-tag`
- Fresh `release/0.0.3-test` branch created from the captured SHA
- Chart.yaml bumped on the release branch (main not touched)
- Release recreated, packaged, and published successfully
Copy link
Copy Markdown

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Choose a reason for hiding this comment

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

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 2368df1008

ℹ️ About Codex in GitHub

Codex has been enabled to automatically review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "Codex (@codex) review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

When you sign up for Codex through ChatGPT, Codex can also answer questions or update the PR, like "Codex (@codex) address that feedback".

Comment thread .github/workflows/release.yml Outdated
Comment thread .github/workflows/release.yml Outdated
… lock

- Apply `./lock_versions` on the release branch in `force_republish` mode when
  `services_version` is provided, matching the behavior of the normal flow
Comment thread .github/workflows/release.yml Outdated
Comment thread .github/workflows/release.yml Outdated
- Split release/tag deletion into independent checks in force_republish path;
  always delete the tag explicitly rather than only in the else branch
- Use --delete syntax for tag deletion for consistency with branch deletion
- Replace git tag | grep with git tag --list for exact tag matching (dots in
  semver are regex wildcards, not literals)
Comment thread .github/workflows/release.yml Outdated
The two paths previously each created the release branch, applied the
services-version lock, bumped Chart.yaml, and pushed — with only the
starting point and final push target differing. Collapse them:

- Both modes compute a START_POINT (tag SHA for force_republish,
  origin/main for normal) and share a single
  `git checkout -b release/$CHART_VERSION $START_POINT`.
- Services-version lock, Chart.yaml bump, and `git push origin
  release/$CHART_VERSION` are now shared.
- Normal mode fast-forwards main to the release branch tip at the end
  (`git push origin release/$CHART_VERSION:main`) instead of committing
  to main first and branching from it.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
@erikdw Erik Weathers (erikdw) merged commit 2f1d58e into main Apr 22, 2026
3 checks passed
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.

2 participants