This repository uses branch-based version maintenance so active development can continue while shipped versions still receive hotfixes.
stablealways represents the next planned release line.- Every shipped version gets an immutable branch named
releases/x.y.zthat points to the same commit as its tag. - A release branch may be pushed before publication as the pull-request branch for that version, but it becomes immutable once
vX.Y.Zis tagged. - Breaking changes, refactors, and new feature work stay on
stableunless they are intentionally backported. - Each public release is identified by a git tag.
- Stable package publication is triggered by the exact
vX.Y.Ztag, not by a branch push.
stable is the forward-looking integration branch.
- Use it for the next feature release or major/minor line.
- Example: while
releases/2.9.9is maintained for hotfixes,stablecan hold the work for3.0.0. - Fixes that apply to both the next release and the current shipped version should usually land on
stableand then be cherry-picked to the matching release branch when safe.
Each release branch preserves the source for exactly one shipped version.
- Prepare
releases/X.Y.Zfrom the intended stable base and use it as the PR head for that release. - Merge the release PR into
stable, then fast-forwardreleases/X.Y.Zto the resulting stable merge commit. - Tag that exact shared commit as
vX.Y.Z; from that point onward, do not add commits to the release branch. - Prepare the next patch on a new branch such as
releases/X.Y.(Z+1)instead of changing the previous version branch. - Do not merge unrelated future
stablework into a patch release candidate.
beta is the optional public-prerelease lane.
- Synchronize it from the intended stable release base before starting a new prerelease series.
- Use versions such as
X.Y.Z-beta.Nand tags such asvX.Y.Z-beta.N. - Beta builds use the beta game-assembly branches and publish only as GitHub prereleases.
- A stable patch does not need to pass through
betaunless public beta validation is intentionally part of that release.
Use standard semantic version tags.
- Initial release:
v2.9.9 - First follow-up hotfix release for that line:
v2.9.10 - Second follow-up hotfix release for that line:
v2.9.11
Experimental builds use SemVer prerelease tags such as v3.1.0-beta.1. These tags:
- are created from the
betabranch; - build against the
betabranches of both private game-assembly repositories; - publish as GitHub prereleases and do not become the latest stable release;
- do not publish to Nexus Mods, Thunderstore, or NuGet.
Increment the trailing prerelease number for each experimental refresh. Create the stable
vX.Y.Z tag from the eventual release branch only after public-beta validation is complete.
Patch numbers are ordinary integers, not single digits. That means 2.9.10 is the next patch after 2.9.9, not 3.0.0.
- Prepare the release changes and version bump on
releases/X.Y.Z, based on the intendedstablecommit. - Open a PR from
releases/X.Y.Zintostableand complete validation. - Merge the PR into
stablewith a merge commit. - Fast-forward
releases/X.Y.Zto that exact stable merge commit. - Tag the shared commit as
vX.Y.Zto publish the stable release. - Treat both the tag and release branch as immutable release records.
- Continue forward development on
stabletoward the next version.
- Create
releases/X.Y.(Z+1)from the current stable tree when it still matches the shipped version, or from thevX.Y.Ztag when stable has unrelated future work. - Apply only the hotfix and the
X.Y.(Z+1)version bump to that new release branch. - Open a PR from
releases/X.Y.(Z+1)intostableand merge it after validation. - Fast-forward
releases/X.Y.(Z+1)to the resulting stable merge commit. - Tag that exact commit as
vX.Y.(Z+1)to publish the new patch. - Leave
releases/X.Y.Zand its tag unchanged as the immutable record of the previous release.
Using the new version's branch as the PR head keeps review history attached to the release while ensuring every version branch continues to identify the assembly it shipped.
- Prefer the new
releases/X.Y.Zbranch and a narrowly scoped PR for each release candidate. - Keep hotfix PRs narrowly scoped so release notes stay easy to read.
- Merge release PRs into
stablebefore tagging. - Fast-forward the release branch to the stable merge commit before creating the tag.
- Never put a new version bump on a branch named for an already shipped version.
The NuGet package publish workflow uses the stable release tag as its authority.
- Automatic publication runs for stable
vX.Y.Ztag pushes. - Prerelease tags such as
vX.Y.Z-beta.Ndo not publish to NuGet. - The workflow checks out the tag and requires
S1API/S1API.csproj<Version>to exactly match it. workflow_dispatchcan republish an existing stable tag when explicitly supplied.- Branch creation, release-PR merges, and ordinary version bumps do not publish packages by themselves.
Before expecting a NuGet package to publish:
- Confirm
stable,releases/x.y.z, andvX.Y.Zidentify the same release commit. - Confirm the project and Melon versions match
X.Y.Z. - Confirm the branch name uses
releases/, notrelease/. - Confirm the publish workflow secrets are configured in GitHub.
The GitHub release workflow packages public mod archives and can publish the same release to mod distribution platforms.
publish-github-release.ymlruns from release tags and can also be rerun withworkflow_dispatch.- The GitHub/Nexus archive is
S1API-Forked-x.y.z.zipand containsMods/andPlugins/at the archive root. - GitHub Releases should only publish
S1API-Forked-x.y.z.zipas a release asset. - The Thunderstore archive is
S1API-TS-x.y.z.zipand containsicon.png,README.md,manifest.json,Mods/, andPlugins/at the archive root, but it is only used for Thunderstore publishing. - The uppercase
Mods/andPlugins/paths are intentional so case-sensitive filesystems do not create parallel lowercase install folders. - The GitHub release asset is always uploaded by the workflow.
- Nexus Mods upload runs when
NEXUSMODS_API_KEY,NEXUSMODS_FILE_GROUP_ID, andNEXUSMODS_MOD_IDare configured. - Generated release notes are published on GitHub. The Nexus Mods upload intentionally omits the optional changelog input because Nexus handles file versions and changelogs through separate endpoints, and a rejected changelog request would otherwise fail the workflow after a successful file upload.
- Thunderstore upload runs when
THUNDERSTORE_TOKENis configured. workflow_dispatchexposespublish_nexusandpublish_thunderstoretoggles for refreshing GitHub assets without re-publishing external platforms.
- When
stablecontains unrelated future work, create the next release branch from the previous stable tag and cherry-pick only the relevant fixes. - Preserve original commit messages when possible so history stays easy to trace.
- Merge the completed release branch back into
stable; resolve divergence without pulling unrelated stable work into the release candidate. - If a cherry-pick needs adaptation, keep the behavior equivalent and mention the branch-specific adjustment in the commit body or PR notes.
For a 3.1.3 hotfix after 3.1.2 has shipped:
- Leave
releases/3.1.2andv3.1.2unchanged. - Prepare the fix and version bump on
releases/3.1.3. - Merge
releases/3.1.3intostableafter validation. - Fast-forward
releases/3.1.3to the stable merge commit. - Tag that shared commit
v3.1.3to publish it.
This keeps maintenance work isolated without allowing a version branch to drift away from the artifact named by that branch.