This document describes the automated release process for Crankshaft, covering version management, release workflows, and distribution through GitHub and APT repositories.
The Crankshaft release process is fully automated through GitHub Actions, enabling consistent, reproducible releases from development to production. The process handles:
- Semantic versioning validation
- Automated builds or reuse of existing builds
- Release notes generation with changelog and SBOM
- GitHub release creation with assets
- APT repository publishing for stable versions
Crankshaft follows Semantic Versioning 2.0.0:
- MAJOR.MINOR.PATCH (e.g.,
1.2.0) - Pre-release versions (e.g.,
1.2.0-alpha.1,1.2.0-rc.1) - Build metadata not used in versioning
Valid versions must match the pattern: ^[0-9]+\.[0-9]+\.[0-9]+(-[a-zA-Z0-9.]+)?$
Examples:
- ✅
1.0.0(stable release) - ✅
1.2.3(stable release) - ✅
1.2.0-alpha(pre-release) - ✅
1.2.0-rc.1(release candidate) - ❌
1.2(missing patch version) - ❌
1.2.0.(trailing dot) - ❌
v1.2.0(version tags are stored without 'v', added automatically)
Trigger: Push a semantic version tag
# Create and push a version tag
git tag v1.2.0
git push origin v1.2.0Process:
- ✅ Validate version format
- ✅ Automatically trigger build workflow
- ✅ Poll for build completion (45-minute timeout)
- ✅ Generate release notes and SBOM
- ✅ Create GitHub release
- ✅ Publish to stable APT channel (non-prerelease only)
Duration: ~5-10 minutes (depending on build time)
Trigger: GitHub Actions workflow_dispatch
Actions tab → Release → Run workflow
version: v1.2.0
build-run-id: (leave empty)
create-draft: false
Process: Same as automatic release but triggered manually
Scenario: Reuse packages from previous build
Actions tab → Release → Run workflow
version: v1.2.0
build-run-id: 1234567890
create-draft: false
Process:
- ✅ Validate version format
- ⏭️ Skip build (use provided run ID)
- ✅ Generate release notes and SBOM
- ✅ Create GitHub release
- ✅ Publish to stable APT channel (non-prerelease only)
Duration: ~2-3 minutes
Create a release for review before publishing:
Actions tab → Release → Run workflow
version: v1.2.0
build-run-id: (optional)
create-draft: true
Draft releases are marked as such on GitHub and are not automatically published to APT.
- Trigger: Automatic on every merge to
mainanddevelopbranches - Distribution:
/apt/nightly/ - Retention: Latest build only
- Packages: All architectures (amd64, arm64, armhf)
- Stability: Development/testing versions
Installation:
echo "deb [arch=amd64,arm64,armhf] https://apt.opencardev.com/nightly jammy main" | sudo tee /etc/apt/sources.list.d/crankshaft-nightly.sources
sudo apt update
sudo apt install crankshaft- Trigger: Manual release workflow with non-prerelease version
- Distribution:
/apt/stable/ - Retention: All released versions
- Packages: All architectures (amd64, arm64, armhf)
- Stability: Production-ready versions
Installation:
echo "deb [arch=amd64,arm64,armhf] https://apt.opencardev.com/stable jammy main" | sudo tee /etc/apt/sources.list.d/crankshaft.sources
sudo apt update
sudo apt install crankshaftPre-release versions (alpha, beta, rc) are:
- Published to GitHub releases
- NOT published to stable APT channel
- Must be manually installed from GitHub releases
Manual installation:
wget https://github.com/opencardev/crankshaft-mvp/releases/download/v1.2.0-rc.1/crankshaft-amd64_1.2.0-rc.1_amd64.deb
sudo dpkg -i crankshaft-amd64_1.2.0-rc.1_amd64.debValidates the release version and determines pre-release status.
Outputs:
version: Semantic version (without 'v' prefix)is-prerelease: true if version contains dash, false otherwise
Triggered when no build-run-id provided. Automatically:
- Triggers CI workflow
- Polls for workflow completion
- Returns the build run ID
Condition: github.event.inputs.build-run-id == '' && github.event_name == 'workflow_dispatch'
Timeout: 45 minutes
Outputs:
build-run-id: The workflow run ID of the completed build
Generates comprehensive release documentation:
- Downloads build artifacts from CI workflow
- Generates changelog from git history
- Generates SBOM (Software Bill of Materials) in SPDX format
- Calculates SHA256 checksums for all packages
- Assembles comprehensive release notes markdown
Outputs:
release-notes: Markdown with installation, changelog, verification, and SBOM info
Artifacts Uploaded:
RELEASE_NOTES.md- Complete release documentationCHANGELOG.md- Changes onlySBOM.spdx- Software Bill of MaterialsSHA256SUMS- Package checksums
Creates a GitHub release with:
- Tag:
v{version} - Name:
Crankshaft {version} - Body: Release notes from previous job
- Draft: Conditional based on input
- Pre-release: true if version contains dash
- Assets: All .deb packages and SHA256SUMS
Publishes packages to stable APT channel for non-prerelease versions.
Condition: needs.validate.outputs.is-prerelease == 'false'
Uses: apt-publish.yml reusable workflow
Inputs:
build-run-id: Build run IDchannel: stablearchitectures: amd64 arm64 armhf
Final job that always runs to report success/failure.
Outputs: Summary message with release details and next steps
If the automatic build fails:
- Check the build workflow logs for errors
- Fix the issue in source code
- Push fixes to main branch
- Re-trigger release with same version tag (force push if needed):
git tag -d v1.2.0 git push --delete origin v1.2.0 git tag v1.2.0 git push origin v1.2.0
If release was created but packages are invalid:
- Delete the GitHub release
- Delete the git tag:
git tag -d v1.2.0 git push --delete origin v1.2.0
- Verify build artifacts
- Re-trigger release with new attempt
If GitHub release succeeded but APT publishing failed:
- Check
publish-stablejob logs for specific error - Manual APT sync can be triggered via workflow_dispatch
- Version remains available on GitHub until fixed
Release notes are automatically generated from git history using conventional commits:
<type>(<scope>): <subject>
Types (included in changelog):
feat:- Featuresfix:- Bug fixesperf:- Performance improvementsrefactor:- Code refactoringdocs:- Documentation (not in changelog)test:- Tests (not in changelog)chore:- Build/CI (not in changelog)
Breaking Changes:
- Any commit with
BREAKING CHANGE:in footer is listed separately - Pre-release versions with major changes recommended
## 1.2.0 - 2025-01-15
### Features
- feat(ui): Add dark mode support
- feat(api): New event system for extensions
- feat(media): Support for multiple audio outputs
### Bug Fixes
- fix(bluetooth): Reconnection after device loss
- fix(ui): Theme switching persistence
### Improvements
- perf(core): Reduce memory footprint by 30%
- refactor(extension): Simplified manifest loading
### Breaking Changes
- BREAKING CHANGE: Extension manifest format v2 required
- BREAKING CHANGE: Removed deprecated WebSocket APIEach release includes a comprehensive SBOM in SPDX 2.3 format documenting:
- All dependencies and exact versions
- License information for each component
- Component relationships and dependency tree
- Known vulnerabilities (when available)
File: crankshaft-sbom-{version}.spdx
Format: SPDX tag-value format
- Human-readable text
- Machine-parseable for vulnerability tracking
- Compatible with SBOM tools and security scanners
Contents:
SPDXVersion: SPDX-2.3
DataLicense: CC0-1.0
SPDXID: SPDXRef-DOCUMENT
DocumentName: Crankshaft SBOM
PackageName: Qt6Core
SPDXID: SPDXRef-Qt6Core
PackageVersion: 6.x.x
PackageDownloadLocation: https://qt.io
FilesAnalyzed: false
PackageLicenseConcluded: LGPL-2.0-or-later
PackageName: openssl
SPDXID: SPDXRef-openssl
PackageVersion: 3.x.x
PackageDownloadLocation: https://www.openssl.org
FilesAnalyzed: false
PackageLicenseConcluded: Apache-2.0
/apt/
├── stable/
│ ├── dists/
│ │ └── jammy/
│ │ ├── InRelease (GPG signed)
│ │ ├── Release
│ │ ├── Release.gpg
│ │ └── {main,universe}/
│ │ └── binary-{amd64,arm64,armhf}/
│ │ ├── Packages
│ │ ├── Packages.gz
│ │ └── Release
│ └── pool/
│ └── c/
│ └── crankshaft/
│ └── crankshaft_*.deb
│
├── nightly/
│ └── (same structure as stable)
└── current → ./stable (symlink)
Verify downloaded packages:
# Download checksums and signature
wget https://apt.opencardev.com/stable/dists/jammy/Release
wget https://apt.opencardev.com/stable/dists/jammy/Release.gpg
# Verify signature
gpg --verify Release.gpg Release
# Verify package checksums
sha256sum -c SHA256SUMSFor critical fixes to released versions:
-
Checkout release tag:
git checkout v1.2.0 git checkout -b hotfix/1.2.1
-
Apply fixes as commits
-
Update version in code (if needed)
-
Create new tag:
git tag v1.2.1 git push origin v1.2.1
-
Release workflow automatically triggers
For alpha/beta/rc releases:
-
Create branch from main:
git checkout -b release/1.2.0-rc.1
-
Perform final testing and fixes
-
Tag version:
git tag v1.2.0-rc.1 git push origin v1.2.0-rc.1
-
Release workflow:
- Creates GitHub release marked as pre-release
- Publishes packages to GitHub releases only
- Does NOT publish to stable APT (requires explicit decision)
- Users can opt-in to test via manual installation
-
Gather feedback and repeat for rc.2, rc.3, etc.
-
When ready, release as v1.2.0 stable
After release, update:
- README.md: Update installation instructions, version numbers
- CHANGELOG.md: Add version section with release date
- RELEASE.txt: Update latest version info
- Documentation: Reflect new features, API changes
If a released version has critical issues:
- GitHub Release: Mark as deprecated in release description
- APT Stable: Previous version remains available (all versions kept)
- Users: Manually downgrade:
sudo apt install crankshaft=1.1.0
- Release New Fix: Create hotfix release with version bump
Track release success via:
- GitHub Actions dashboard
- Release workflow job logs
- APT repository metrics
- Package download analytics
- Build took >45 minutes
- Manually trigger release with
build-run-idfrom slower build - Or increase timeout in
release.yml
- Check version matches semver pattern
- Remove 'v' prefix if present
- No trailing dots or extra characters
- Check SSH connectivity to APT server
- Verify GPG signing key configured
- Check APT server disk space
- Manual re-trigger via workflow_dispatch
- Verify build run completed successfully
- Check artifact retention (90-day limit)
- Download from GitHub release instead
- Rebuild if artifacts expired
- All release artifacts are cryptographically signed
- GitHub releases are signed with commit signing keys
- APT packages are signed with GPG key
- Repository metadata (Release files) are GPG signed
- SBOM enables vulnerability tracking
- All operations logged and auditable