Skip to content

Create release tags directly, and GitHub Releases for production only - #4812

Open
allister-beamable wants to merge 3 commits into
mainfrom
excise-github-releases
Open

Create release tags directly, and GitHub Releases for production only#4812
allister-beamable wants to merge 3 commits into
mainfrom
excise-github-releases

Conversation

@allister-beamable

@allister-beamable allister-beamable commented Aug 26, 2026

Copy link
Copy Markdown
Contributor

Heads-up for anyone who runs releases (@mhijaziB, @Leinnan) - this changes how the release tag gets made in all three release workflows, and changes what GitHub Releases are for.

This PR reversed course mid-review. It started out removing GitHub Releases entirely. @Leinnan pushed back in review: rather than delete them because they are empty, populate them with changelogs. He was right, and two findings during the follow-up made the case stronger than the one he made.

Why

gh release create was being used purely to mint the tag. Surveying what those Releases actually contained:

Total releases 1088
With binary assets 0
With notes beyond the stub "<X> Release <version>" 0
Code reading the Releases API none found
What downstream actually reads git tags - LightBeam's versioned alias, the docs SDK/CLI version table

That reads as a case for deleting Releases. It is actually a case for fixing them, because of how the 1088 break down:

Channel Releases
nightly 707
RC / experimental 292
production 89

The noise was the preview builds, not the Release object. A Release per nightly is indefensible under any theory. 89 production Releases carrying real changelogs are a reasonable version history for the Releases tab, which is where a developer evaluating an SDK looks first.

The second finding is the decisive one. release-mcpb.yml needs the Release to exist. It runs gh release upload "cli-<version>" to attach the .mcpb Claude Desktop extension bundles, and cli/cli/Docs/AGENTS.md already tells users to download them from GitHub Releases. That workflow has never run, so the "0 with binary assets" row above is true today and false by design. Removing Releases would have broken the .mcpb distribution path before it ever shipped.

Separately, the Release object was actively harmful as a tag-minter: it created the tag under GITHUB_TOKEN, and events raised by GITHUB_TOKEN never start a workflow run. That is why notify-docs-sdk-release.yml never fired for an automated release - it has run exactly once in its life, for a hand-pushed tag.

What changes

Tag creation is decoupled from the Release. release-unity.yml, release-nuget.yml, release-web.yml: gh release create -> gh api .../git/refs, creating the tag at exactly github.sha, for every release type. Used the API rather than git tag + git push so the tag does not depend on what the checkout fetched (release-unity.yml checks out inputs.commit, which need not be github.sha) and so tags stay lightweight, matching all 1088 existing tags.

A GitHub Release is created on top of that tag, for production only. Nightly, RC, and experimental builds get a bare tag and nothing else. Guarded with --verify-tag, because gh release create silently creates a tag from the default branch when none exists; the flag makes it abort instead, asserting the preceding tag step ran.

New build/bin/release-notes.sh generates the notes: a verbatim slice of the ## [VERSION] section of each CHANGELOG.md in the lanes that release touches, keyed on the same COPY_UNITY_SDK / COPY_CLI / COPY_WEB_SDK flags upload-changelogs.sh already takes, so each workflow declares its lanes identically for both scripts.

Workflow Lanes in the notes
release-unity.yml com.beamable, com.beamable.server
release-nuget.yml Beamable.Tools, Beamable.Server
release-web.yml Beamable Web SDK

Two details worth review attention:

  • A missing changelog section warns, it does not fail. The step runs after the packages have published, so failing it would red-X a release that already shipped. This is not hypothetical: com.beamable.server/CHANGELOG.md has been stale since [3.0.0], so the warning fires on the next Unity production release. Worth fixing, but separately.
  • Paths resolve from $GITHUB_WORKSPACE, not the working directory, because release-web.yml sets defaults.run.working-directory: web. That is the same trap that gives upload-changelogs.sh its ../../ special case.

notify-docs-sdk-release.yml is deleted. release-unity.yml already dispatches beamable/docs explicitly, and that path is proven working end to end (docs run 33002167833). One code path, one consumer of DOCS_DISPATCH_PAT.

The --prerelease flag disappears: nothing prerelease gets a Release object any more.

What is deliberately NOT changed

  • Tags themselves - same names, same targets, same lightweight type, still created for every release type.
  • The 1088 existing Releases - left in place by this PR. See follow-ups.

Testing

The changelog slicing is tested against real data for all three lanes, including the boundary case that [6.1.0] must not match a [16.1.0] heading (the match is anchored at column 4). All three workflows parse.

The release path itself cannot be verified without cutting a real release - there is no dry-run path that exercises tag or Release creation (if: inputs.dryRun == false). Step ordering is otherwise unchanged. The first production release after merge is the real test; if either step fails, it fails loudly rather than silently.

Follow-ups (not in this PR)

  • Backfill the 89 existing production Releases with the same changelog slices, read from each CHANGELOG.md at its own tag. Tooling is written and dry-run (87 of 89 produce content; two predate their changelog). Not applied - it is 89 public-facing edits.
  • Delete the 999 preview Releases. Verified safe: gh release delete without --cleanup-tag leaves the tag, and /releases/tag/<tag>, /archive/refs/tags/<tag>.zip, and /tree/<tag> all return 200 for a tag with no Release (346 tags already have none, which is how this was tested directly). Needs throttling for GitHub's secondary rate limit.
  • docsTag.yml triggers on 1.** tags, a scheme no longer cut. Its run history is empty. Dead, flagged not touched.
  • com.beamable.server/CHANGELOG.md is stale since [3.0.0].
  • Backport to release/unity-6.1.x only if that line cuts another patch - releases execute from release branches, so main alone does not cover an in-flight line.
  • BeamableProduct#4734 can close once a production release confirms the docs dispatch.

The CS release runbooks and release policy in JurnalDeBord have been updated to match; they had documented the original "no GitHub Releases" plan.

The three release workflows created a GitHub Release solely as a way to
mint the tag. Those Releases carried no assets and no notes beyond a stub
string, nothing in the org read the Releases API, and every downstream
consumer keys off the git tag instead: LightBeam's versioned alias and the
docs SDK/CLI version table both read tags. Create the tag directly and skip
the empty wrapper.

Tags are created through the git/refs API rather than git tag + push so
they land on exactly github.sha without depending on what the checkout
fetched, and so they stay lightweight, matching all 1088 prior tags.

Existing Releases are deliberately left alone. This stops making new ones;
it does not remove history.

Also drops notify-docs-sdk-release.yml. It fired on tag pushes to dispatch
the docs table update, but the tag is created with GITHUB_TOKEN and events
raised by GITHUB_TOKEN never start a workflow run, so it worked only for
tags pushed by hand. release-unity.yml now dispatches beamable/docs
explicitly, which is the path proven working, leaving one code path and one
consumer of DOCS_DISPATCH_PAT.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
@Leinnan

Leinnan commented Aug 26, 2026

Copy link
Copy Markdown
Collaborator

I would go the other way around - instead of removing the creation of the GitHub Releases because they are empty could we consider populating the GitHub Releases with changelogs?

@allister-beamable

Copy link
Copy Markdown
Contributor Author

I would go the other way around - instead of removing the creation of the GitHub Releases because they are empty could we consider populating the GitHub Releases with changelogs?

The main reason I dislike GitHub Releases for us is that we never publish real artifacts there. That is, the thing we are providing, the Beamable Unity SDK and the Beamable.Tools packages have canonical hosting that is NOT GH Releases. Developers get the SDK via Nexus and Beam-CLI via NuGet, and never from GitHub.

I will have to think about this; releases automatically get a ZIP and a tarball of the source at the time of release, which is sort of, kind of like an artifact. Your point about releases becoming more valuable when they have changelogs on them is a solid one.

allister-beamable and others added 2 commits August 27, 2026 14:49
Per Peter's review comment: a Release is worth having when it carries the
changelog. Preview builds are what made the previous 1088 Releases noise -
999 of them were nightly, RC, or experimental.

- Tag creation stays unconditional and decoupled, so nightly/RC/exp builds
  still get their tags; only the Release object is production-gated.
- New build/bin/release-notes.sh slices the verbatim "## [VERSION]" section
  out of each CHANGELOG.md in the lanes the release actually touches, using
  the same COPY_* lane flags upload-changelogs.sh already takes. Warns rather
  than fails on a missing section, so a stale changelog cannot red-X a
  release whose packages have already published.
- Paths resolve from GITHUB_WORKSPACE because release-web.yml sets
  defaults.run.working-directory.

Also note release-mcpb.yml uploads .mcpb bundles to the cli-<version>
Release; production-gating keeps that path intact, where dropping Releases
entirely would have broken it.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
gh release create silently creates a tag from the default branch when none
exists. --verify-tag makes it abort instead, asserting that the preceding
tag step actually ran.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
@allister-beamable allister-beamable changed the title Create release tags directly instead of via GitHub Releases Create release tags directly, and GitHub Releases for production only Aug 27, 2026
@github-actions

Copy link
Copy Markdown
Contributor

Lightbeam link

@allister-beamable

Copy link
Copy Markdown
Contributor Author

Idea from @mhijaziB : include a link to the "Getting Started" installation instructions. That way anyone who arrives at Beamable by way of the Releases tab will be guided to the correct next steps.

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