Release Process
This document describes how to create and publish releases of HelixScreen.
Table of Contents
Section titled “Table of Contents”- Version Scheme
- Automated Release Pipeline
- Creating a Release
- Release Checklist
- Hotfix Releases
- Pre-release Versions
Version Scheme
Section titled “Version Scheme”HelixScreen uses Semantic Versioning:
MAJOR.MINOR.PATCH[-PRERELEASE]| Component | When to Increment |
|---|---|
| MAJOR | Breaking changes (config format, API, incompatible UI changes) |
| MINOR | New features, backwards-compatible |
| PATCH | Bug fixes, documentation, minor improvements |
| PRERELEASE | Do not use. See below. |
Never ship a prerelease suffix
Section titled “Never ship a prerelease suffix”
helix::version::Versiondiscards the prerelease suffix when parsing (include/version.h).v1.0.0-rc.1,v1.0.0-betaandv1.0.0all parse to1.0.0and compare equal.So a user who installs
v1.0.0-rc.1has an app that believes it is already on1.0.0. When the real1.0.0publishes, the updater sees no newer version and never offers it. Your testers are stranded on the release candidate.Use a plain monotonic version instead, and pick the audience with the branch’s
RELEASE_CHANNELfile rather than with the tag string. That is exactly whyRELEASE_CHANNELexists - read its header comment. A release candidate that everyone should test is just the nextPATCHon the line they are already on (v0.99.114 was the 1.0 RC, shipped on the stable 0.99.x line).
Examples
Section titled “Examples”v1.0.0- First stable releasev1.1.0- New features addedv1.1.1- Bug fixv2.0.0- Breaking changesv0.99.114- a release candidate: a plain PATCH bump, audience chosen byRELEASE_CHANNEL, not by a-rcsuffix
Automated Release Pipeline
Section titled “Automated Release Pipeline”The release process is fully automated via GitHub Actions (.github/workflows/release.yml).
Trigger
Section titled “Trigger”Pushing a tag matching v* triggers the release workflow:
git tag v1.2.0git push origin v1.2.0Pipeline Stages
Section titled “Pipeline Stages”┌─────────────────────────────────────────────────────────────┐│ Tag Push (v1.2.0) │└──────────────────────────────┬──────────────────────────────┘ │ ▼┌─────────────────────────────────────────────────────────────┐│ Build Matrix │└──────────────────────────────┬──────────────────────────────┘ │ ▼ validate-shell gate → build-platforms matrix (9): pi · pi32 · ad5m · cc1 · k1 · ad5x · k2 · x86 · snapmaker-u1 plus build-android → publish-android `release` needs build-android too, not just build-platforms — otherwise it could publish before Android finished and ship with no APKs, silently. build-android FAILS the whole release if ANDROID_KEYSTORE_BASE64 is unset; it no longer falls back to the debug keystore. See ANDROID_PLAY_STORE.md.
Each platform job: Docker cross-toolchain → target arch → package .zip │ ▼ ┌──────────────────┐ │ release │ │ │ │ • Download all │ │ artifacts │ │ • Extract version│ │ • Generate notes │ │ • Create release │ └──────────────────┘Build Artifacts
Section titled “Build Artifacts”| Platform | Artifact Name | Contents |
|---|---|---|
| Raspberry Pi (64-bit) | helixscreen-pi.zip | aarch64 binary, assets, configs |
| Raspberry Pi (32-bit) | helixscreen-pi32.zip | armhf binary, assets, configs |
| AD5M | helixscreen-ad5m.zip | armv7l binary (static), assets, configs |
| CC1 | helixscreen-cc1.zip | ARM binary, assets, configs |
| K1 | helixscreen-k1.zip | MIPS32 binary (static, musl), assets, configs |
| AD5X | helixscreen-ad5x.zip | MIPS binary (ZMOD), assets, configs |
| K2 | helixscreen-k2.zip | ARM binary (static, musl), assets, configs |
| x86 | helixscreen-x86.zip | x86 binary, assets, configs |
| Snapmaker U1 | helixscreen-snapmaker-u1.zip | ARM binary, assets, configs |
| Android | Play Store bundle | via build-android / publish-android |
Bridge release note: Starting with v1.0.0 (the version you’re currently preparing), the primary release asset is
helixscreen-{platform}.zip(unversioned filename). The legacyhelixscreen-{platform}-v{version}.tar.gzis still published during this bridge release for backwards compatibility with older installed versions; it will be removed in the following release.
Creating a Release
Section titled “Creating a Release”Step 1: Prepare the Release
Section titled “Step 1: Prepare the Release”-
Ensure main branch is stable:
Terminal window git checkout maingit pull origin mainmake test-run # Run tests -
Bump
VERSION.txtand add the CHANGELOG entry, in onechore(release):commit.VERSION.txtis the source of truth for the built binary (Makefile:195,mk/cross.mk:2452) - the version does not come from the git tag. Tagging without bumping the file ships a binary that reports the previous version.echo "X.Y.Z" > VERSION.txt- Add the release section to
CHANGELOG.mdabove the previous one git commit -m "chore(release): vX.Y.Z" CHANGELOG.md VERSION.txt- Also check
CLAUDE.md/README.mdfor any hardcoded version strings
-
Test on actual hardware:
- MainsailOS / Raspberry Pi
- AD5M with ForgeX (if applicable)
- Run through verification checklist in
docs/user/TESTING_INSTALLATION.md
Step 2: Create the Tag
Section titled “Step 2: Create the Tag”With release notes (recommended):
# Create annotated tag with release notesgit tag -a v1.2.0 -m "$(cat <<'EOF'## What's New
### Features- Added input shaper visualization- Improved AMS panel responsiveness
### Bug Fixes- Fixed crash when Moonraker disconnects during print- Fixed touch calibration on rotated displays
### Other- Updated documentation- Performance improvementsEOF)"
# Push the taggit push origin v1.2.0Without release notes:
git tag v1.2.0git push origin v1.2.0The workflow auto-generates basic release notes if no annotation is provided.
Step 3: Monitor the Build
Section titled “Step 3: Monitor the Build”- Go to Actions tab on GitHub
- Watch the “Release” workflow
- Build takes ~15-20 minutes typically
Step 4: Verify the Release
Section titled “Step 4: Verify the Release”- Go to Releases on GitHub
- Check both platform archives are attached
- Verify checksums in release notes
- Test installation:
Terminal window curl -sSL https://raw.githubusercontent.com/prestonbrown/helixscreen/main/scripts/install.sh | sh
Release Checklist
Section titled “Release Checklist”Before Tagging
Section titled “Before Tagging”- All tests pass (
make test-run) - No critical bugs in issue tracker
- Documentation updated for new features
- ROADMAP.md updated if needed
- Tested on real hardware (Pi and/or AD5M)
After Release
Section titled “After Release”- Release workflow completed successfully
- Both platform artifacts attached
- Release notes accurate
- Installation tested via curl|sh
- Update any external references (Discord, documentation sites)
Hotfix Releases
Section titled “Hotfix Releases”For urgent bug fixes:
-
Create hotfix branch from the release tag:
Terminal window git checkout -b hotfix/v1.2.1 v1.2.0 -
Apply minimal fix - only the necessary changes
-
Test thoroughly - verify the fix, check for regressions
-
Merge to main (via PR if time permits):
Terminal window git checkout maingit merge hotfix/v1.2.1 -
Tag and release:
Terminal window git tag -a v1.2.1 -m "Fix: [description of fix]"git push origin v1.2.1
Pre-release Versions
Section titled “Pre-release Versions”For testing new features before stable release:
Creating a Pre-release
Section titled “Creating a Pre-release”# Beta versiongit tag -a v1.3.0-beta -m "Beta release for testing new AMS features"git push origin v1.3.0-beta
# Release candidategit tag -a v1.3.0-rc.1 -m "Release candidate 1"git push origin v1.3.0-rc.1Pre-release Behavior
Section titled “Pre-release Behavior”The GitHub prerelease flag and the R2 upload channels both come from the
RELEASE_CHANNEL file at the repo root, on the branch being tagged — not from
the tag string. See docs/devel/UPDATE_SYSTEM.md § “How CI Determines Upload
Channels” for the full table and the reason.
RELEASE_CHANNEL=stable-> full GitHub release, shown as “latest”RELEASE_CHANNEL=betaordev-> marked prerelease, not shown as “latest”- Users must explicitly choose to install a prerelease:
Terminal window curl -sSL .../install.sh | sh -s -- --version v1.3.0-beta
Do not use a -suffix to mean “devel build”. helix::version::Version
discards prerelease suffixes, so v1.1.0-dev1 and v1.1.0-dev2 compare equal and
the in-app updater stops offering builds. Devel-track releases use plain
incrementing versions and rely on RELEASE_CHANNEL for routing. A suffixed tag on
a stable branch is rejected by scripts/release-channel.sh.
Graduating Pre-releases
Section titled “Graduating Pre-releases”After testing:
# When beta is ready for stablegit tag -a v1.3.0 -m "Stable release"git push origin v1.3.0Manual Release (Emergency)
Section titled “Manual Release (Emergency)”If GitHub Actions fails, you can build and release manually:
Build Locally
Section titled “Build Locally”# Build for Pimake PLATFORM_TARGET=pi clean release-pi
# Build for AD5Mmake PLATFORM_TARGET=ad5m clean release-ad5mCreate Release Manually
Section titled “Create Release Manually”- Go to GitHub Releases → Draft a new release
- Choose the tag
- Write release notes
- Upload the
.zipfiles fromreleases/(plus the legacy.tar.gzfiles if the bridge release still ships them) - Publish
Changelog Generation
Section titled “Changelog Generation”Currently, changelogs are written manually in the tag annotation. Future options:
Option A: Manual Changelog File
Section titled “Option A: Manual Changelog File”Maintain CHANGELOG.md in the repository, update before each release.
Option B: Conventional Commits + Auto-generation
Section titled “Option B: Conventional Commits + Auto-generation”Use tools like git-cliff or semantic-release:
# Generate changelog from conventional commitsgit cliff -o CHANGELOG.mdThis requires commit messages follow Conventional Commits:
feat: add new featurefix: resolve bugdocs: update documentation
Current Approach
Section titled “Current Approach”We use annotated tags with manual release notes. This provides flexibility while keeping the process simple.
Troubleshooting
Section titled “Troubleshooting”Build Fails
Section titled “Build Fails”- Check Actions logs for the specific error
- Common issues:
- Submodule not checked out
- Docker cache issues (try re-running)
- Toolchain image problems
Wrong Version Released
Section titled “Wrong Version Released”- Delete the release on GitHub
- Delete the tag:
Terminal window git tag -d v1.2.0git push origin :refs/tags/v1.2.0 - Fix the issue
- Re-tag and push
Missing Artifact
Section titled “Missing Artifact”If one platform’s build fails:
- Fix the issue
- Delete the partial release
- Delete and re-push the tag to trigger fresh build
Related: CI/CD Guide | Testing Installation