Skip to content

Developer Release Process

Jason Rhubottom edited this page May 31, 2026 · 2 revisions

Developer Release Process

The release process is fully automated with the ./scripts/release tool.

Quick Start

# Create beta release (interactive, opens editor for notes)
./scripts/release beta --editor

# Create production release from main
git checkout main
./scripts/release patch --editor

Release Script Overview

The release script automates:

  1. βœ… Version management in manifest.json
  2. βœ… Git commit and annotated tag creation
  3. βœ… Pushing to GitHub (triggers automated workflow)
  4. βœ… Editing GitHub release with notes and prerelease flag
  5. βœ… Verifying ZIP asset creation

Command Syntax

./scripts/release [VERSION_SPEC] [OPTIONS]

VERSION_SPEC:

  • patch - Increment patch version (X.Y.Z+1)
  • minor - Increment minor version (X.Y+1.0)
  • major - Increment major version (X+1.0.0)
  • beta - Auto-increment beta version
  • X.Y.Z - Explicit version number
  • X.Y.Z-beta.N - Explicit beta version
  • (omit for interactive mode)

OPTIONS:

  • --dry-run - Preview operations without executing
  • --yes, -y - Skip confirmation prompts
  • --editor, -e - Open editor for release notes
  • --notes FILE - Read release notes from file
  • --auto-notes - Use auto-generated notes only
  • --force-branch - Skip branch validation
  • --help, -h - Show help text

Release Types

Beta Releases

When to use: Testing new features on feature branches

Characteristics:

  • Created from feature branches
  • Version format: X.Y.Z-beta.N
  • Marked as "prerelease" on GitHub
  • Includes testing instructions
  • Not recommended for production use

Example workflow:

# On feature branch
git checkout feature/new-feature

# Create beta release (auto-increment)
./scripts/release beta --editor

# Or with explicit version
./scripts/release 2.5.1-beta.1 --editor

Release notes template:

# Beta Release vX.Y.Z-beta.N

**⚠️ BETA RELEASE** - This is a beta version for testing purposes.

## Changes
- Feature: [description]
- Bug fix: [description]

## Testing Instructions
1. Install vX.Y.Z-beta.N
2. Test: [specific test cases]
3. Report issues at: https://github.com/jrhubott/adaptive-cover/issues

## Installation
Download `adaptive_cover_pro.zip` from assets below.

Production Releases

When to use: Stable releases from main branch

Characteristics:

  • Created from main branch only
  • Version format: X.Y.Z
  • Not marked as prerelease
  • Production-ready
  • Full release notes

Example workflow:

# Merge feature branch to main
git checkout main
git merge feature/new-feature
git push origin main

# Create production release
./scripts/release patch --editor
# or
./scripts/release 2.5.0 --editor

Release notes template:

# Adaptive Cover Pro vX.Y.Z

## What's New
- [Feature highlights]

## Bug Fixes
- [Bug fixes]

## Breaking Changes
None

## Installation
### HACS: Update through HACS
### Manual: Download adaptive_cover_pro.zip

Nightly Releases (Automated)

When to use: never by hand β€” .github/workflows/nightly.yml runs it on a schedule. There is no ./scripts/release nightly mode.

Characteristics:

  • Built from the tip of develop daily at ~07:00 UTC (also runnable via workflow_dispatch)
  • Version format: X.Y.Z-nightly.<UTCtimestamp>, where X.Y.Z is one patch above the current manifest version with any pre-release suffix stripped β€” this guarantees the nightly sorts above the installed stable so HACS offers it as an update
  • Marked as "prerelease" on GitHub
  • Only the newest 3 nightly releases are kept; older ones are deleted automatically (tag and release)

How it differs from a beta: a beta is a deliberate, human-authored cut with real release notes. A nightly is a snapshot of whatever is on develop, gated only by the test suite. It carries no curated notes and no "Should I install this?" guidance.

What the workflow does:

  1. Compute & gate β€” checks out develop, computes the -nightly version, and counts commits since the last v*-nightly.* tag. If develop is unchanged, it sets should_run=false and stops β€” no empty nightly.
  2. Test gate β€” reuses tests.yml. The nightly is only published if the full suite passes.
  3. Tag & publish β€” writes the nightly version into manifest.json, makes an ephemeral chore: nightly build commit, tags it, and pushes only the tag (never the commit) so develop history stays clean. publish-release.yml then builds and publishes the pre-release. The tag is pushed with RELEASE_PAT, not GITHUB_TOKEN β€” a tag pushed with the default token would not trigger publish-release.yml.
  4. Prune β€” deletes all but the three most recent nightly releases.

Why the workflow lives on main: GitHub fires on: schedule only from the repository's default branch. Every job inside it operates on develop regardless (it checks out develop to compute the version and build the tagged commit).

Release Script Workflow

Here's what happens when you run the release script:

1. Validate Environment
   β”œβ”€ Check required tools (git, gh, jq)
   β”œβ”€ Verify gh authentication
   β”œβ”€ Ensure working directory is clean
   └─ Validate manifest.json exists

2. Calculate Version
   β”œβ”€ Read current version from manifest.json
   β”œβ”€ Calculate new version based on VERSION_SPEC
   └─ Validate version format

3. Validate Branch
   β”œβ”€ Check current branch
   β”œβ”€ Ensure branch matches release type
   β”‚  β”œβ”€ Beta: Any branch (usually feature/*)
   β”‚  └─ Production: main branch only
   └─ Skip with --force-branch if needed

4. Get Release Notes
   β”œβ”€ Option 1: Open editor (--editor)
   β”œβ”€ Option 2: Read from file (--notes FILE)
   └─ Option 3: Auto-generate (--auto-notes)

5. Update Version
   └─ Update manifest.json with jq (preserves formatting)

6. Create Git Commit
   β”œβ”€ Stage manifest.json
   └─ Commit: "chore: Bump version to vX.Y.Z"

7. Create Annotated Tag
   β”œβ”€ Tag name: vX.Y.Z
   └─ Tag message: Release notes (Co-Authored-By filtered)

8. Push to GitHub
   β”œβ”€ Push commit to current branch
   └─ Push tag (triggers GitHub Actions workflow)

9. Wait for Workflow
   β”œβ”€ Poll GitHub every 5s
   β”œβ”€ Timeout: 60s
   └─ Workflow creates initial release + ZIP asset

10. Edit Release
    β”œβ”€ Set title: "Adaptive Cover Pro β›… vX.Y.Z"
    β”œβ”€ Set detailed notes
    └─ Add --prerelease flag for beta releases

11. Verify ZIP Asset
    β”œβ”€ Check adaptive_cover_pro.zip exists
    β”œβ”€ Verify size is reasonable (100KB-500KB)
    └─ Display success message with release URL

Examples

Example 1: Beta Release (Interactive)

# On feature branch with new feature
git checkout feature/diagnostic-sensors

# Run release script in interactive mode
./scripts/release

# Select "1) Beta"
# Opens editor with template
# Edit release notes, save, and close
# Confirms and creates release

Example 2: Beta Release (Quick)

# Auto-increment beta, use auto-generated notes
./scripts/release beta --yes --auto-notes

Example 3: Production Release

# Ensure on main branch
git checkout main

# Create patch release with editor
./scripts/release patch --editor

# Edit release notes with full changelog
# Confirms and creates production release

Example 4: Explicit Version

# Create specific version
./scripts/release 2.6.0-beta.1 --editor

Example 5: Release Notes from File

# Prepare release notes
cat > /tmp/release-notes.md << 'EOF'
# Adaptive Cover Pro v2.5.0

## What's New
- New diagnostic sensors for troubleshooting
- Improved manual override detection
- Support for open/close-only covers

## Bug Fixes
- Fixed inverse state behavior for open/close-only covers
- Corrected unit display for Last Cover Action sensor
EOF

# Create release with notes from file
./scripts/release 2.5.0 --notes /tmp/release-notes.md --yes

Example 6: Dry Run (Safe Testing)

# Preview what would happen without making changes
./scripts/release beta --dry-run

# Output shows all operations that would be performed
# No actual changes to git or GitHub

Release Checklist

Before creating a release:

  • All changes committed and pushed to feature branch
  • Pre-commit hooks passing
  • Code linted: ./scripts/lint
  • Manual testing completed with ./scripts/develop
  • README.md updated with new features/entities
  • CLAUDE.md updated if development process changed
  • Working directory clean: git status

For beta releases:

  • On feature branch
  • Version will be X.Y.Z-beta.N

For production releases:

  • On main branch
  • Beta testing completed successfully
  • Version will be X.Y.Z (no beta suffix)

Troubleshooting Releases

Problem: Working directory not clean

βœ— Working directory is not clean
β„Ή Commit or stash changes before creating a release

Solution: Commit or stash your changes:

git add .
git commit -m "your message"
# or
git stash

Problem: Production release from feature branch

βœ— Production releases must be created from main branch
β„Ή Current branch: feature/my-feature
β„Ή Switch to main: git checkout main

Solution: Either:

  1. Switch to main: git checkout main
  2. Use beta version: ./scripts/release beta
  3. Override (not recommended): ./scripts/release --force-branch

Problem: Tag already exists

βœ— Tag already exists locally: v2.5.0

Solution: Use a different version:

# Delete local tag if it's a mistake
git tag -d v2.5.0

# Or use a different version
./scripts/release 2.5.1

Problem: GitHub CLI not authenticated

βœ— GitHub CLI not authenticated
β„Ή Run: gh auth login

Solution: Authenticate with GitHub:

gh auth login
# Follow the prompts to authenticate

Problem: ZIP asset not found

βœ— ZIP asset not found: adaptive_cover_pro.zip

Solution: Check GitHub Actions workflow:

# View recent workflow runs
gh run list --workflow=publish-release.yml

# View specific run details
gh run view <run-id>

The workflow might have failed. Check the logs and re-run if necessary.

Problem: Workflow timeout

βœ— Workflow did not complete within 60s

Solution: The workflow is probably still running:

# Check workflow status
gh run list --workflow=publish-release.yml

# Wait for it to complete, then manually edit the release
gh release edit v2.5.0 --title "Title" --notes "Notes"

Rollback on Failure

The release script automatically rolls back changes if an error occurs:

  1. Deletes the local tag (if created)
  2. Deletes the remote tag (if pushed)
  3. Resets the commit (if manifest.json was committed)

If you need to manually rollback:

# Delete local tag
git tag -d vX.Y.Z

# Delete remote tag
git push --delete origin vX.Y.Z

# Reset last commit (if needed)
git reset --hard HEAD^

# Force push to remote (if commit was already pushed)
git push --force origin feature/branch-name

CI/CD Mode

For automated releases in CI/CD pipelines:

# Non-interactive, no prompts, auto-generated notes
./scripts/release beta --yes --auto-notes

Environment variables needed:

  • GITHUB_TOKEN - For gh authentication
  • GitHub Actions automatically provides this

Clone this wiki locally