The three release trains
| Train | Source path | Distribution | Tag format |
|---|---|---|---|
| iOS app | ios/HealthPush/ | App Store, TestFlight | ios-v1.2.3 |
| HA integration | integrations/homeassistant/custom_components/healthpush/ | HACS + GitHub Release | ha-v0.4.1 |
| Storage core | packages/HealthPushStorageCore/ | Swift Package Manager consumers | storage-core-v0.1.0 |
docs/ deploy continuously and have no version number.
Semver per component
Every release train follows Semantic Versioning 2.0.0:- MAJOR — breaking change that requires user action.
- MINOR — new feature, additive only.
- PATCH — bug fix or internal change with no API surface impact.
Pre-1.0 policy
While a component is pre-1.0 (0.x.y):
- Breaking changes are allowed in minor bumps.
- We try to flag them in the changelog as “breaking” but don’t promise stability.
- Users should expect rough edges and rapid change.
Post-1.0 policy
Once a component has released1.0.0:
- Breaking changes require a MAJOR bump.
- Deprecations live for at least two minor releases before removal.
release-pleaseautomatically opens a release PR when the commit history warrants a new version.
Schema version is orthogonal to product version
HealthPush has a data schema contract (seedocs/schema.md once published) that is versioned independently of any product component. The schema lives at v1 today.
- A product minor release (e.g.
ios-v1.3.0) does not imply a schema bump. - A schema MAJOR bump (e.g.
v2) is signaled by a new folder prefix on S3, a new JSONschemaVersionvalue, and a new MQTT topic namespace — and coincides with a coordinated product release across all components that read or write the schema. - Within a schema MAJOR, changes are strictly additive. New optional fields may appear; existing fields never change type or meaning.
- HealthPush commits to reading any
v1.xdata it has ever written, for the life ofv1.
Conventional Commits drive releases
Version bumps are computed from commit history, not hand-edited. The workflow is:- Contributors open PRs with Conventional Commit titles — see
CONTRIBUTING.md. - PR titles are squash-merged to
mainand become commits. release-please(see.github/workflows/release-please.yml) reads the commit history for each package and opens a per-component release PR with:- Computed new version.
- Generated changelog entry.
- Updated version marker in the relevant file (
project.yml,manifest.json, etc.).
- A maintainer merges the release PR.
- The merge creates a tag in the relevant format, which triggers the matching release workflow (TestFlight for iOS, GitHub Release for HA, SPM tag for storage-core).
iOS build number
The iOS build number (CURRENT_PROJECT_VERSION in project.yml) is set from GITHUB_RUN_NUMBER at release time — it is monotonically increasing and does not need to be managed by hand.
MARKETING_VERSION is owned by release-please via the extra-files config in release-please-config.json.
Rollback
- iOS: Phased Release is enabled for every App Store submission. If a regression is detected in the 72-hour watchdog window, the release can be paused directly from App Store Connect.
- HA: mark the bad release as a pre-release on GitHub, and tag a fixed
ha-v*.*.x+1immediately. - Storage core: never force-delete a published tag; cut a patch release instead.
workflow_dispatch on the relevant release workflow, but the fix must still land on main via a normal PR first.