OpenHuman Versioning Practices: A SemVer-Based Release Workflow
OpenHuman uses a centralized SemVer system where Cargo.toml serves as the single source of truth, automatically propagating version strings to the Rust core, Tauri desktop bundle, and npm frontend through CI workflows.
The OpenHuman repository maintains a strict release process that coordinates the Rust core (tinyhumansai/openhuman), the Tauri desktop application, and the web-based UI. This standardized approach ensures that every binary, installer, and API response carries a consistent, traceable version identifier derived from a single canonical location.
Centralized Version Control in Cargo.toml
Single Source of Truth
The versioning system anchors to Cargo.toml at the repository root. The version field defined here becomes CARGO_PKG_VERSION at compile time, serving as the canonical reference for the entire monorepo.
According to the source code, this value is baked into the Rust binary and exposed via multiple channels:
- Runtime access: Retrieved via
env!("CARGO_PKG_VERSION")in Rust source files - Health checks: Embedded in
src/openhuman/health/ops.rsfor system status reporting - UI injection: Passed from
app/src-tauri/src/lib.rsinto the Vite frontend bundle
When the CI cuts a release, it reads the version from Cargo.toml and synchronizes downstream:
# Cargo.toml
[package]
name = "openhuman"
version = "0.57.35" # Canonical version
edition = "2021"
Propagating to Frontend Components
The Tauri bridge in app/src-tauri/src/lib.rs reads the compiled version and injects it into the frontend environment:
// app/src-tauri/src/lib.rs
let version = env!("CARGO_PKG_VERSION");
println!("OpenHuman core version: {}", version);
This value flows into three locations that must remain synchronized:
Cargo.toml– Core Rust crate versionapp/package.json– Frontend npm/yarn workspace versionapp/src-tauri/tauri.conf.json– Tauri bundle version (displayed in installers)
The scripts/prepare-build.sh script handles this propagation automatically during the release process.
Automated Release Workflows
OpenHuman employs two distinct GitHub Actions workflows that handle version bumps and artifact generation without manual intervention.
Staging Releases
The release-staging.yml workflow runs on every push to main. It automatically bumps the patch version in Cargo.toml and creates a pre-release tag with the -staging suffix:
# scripts/prepare-build.sh (simplified)
VERSION=$(awk '/^version =/ {print $3}' Cargo.toml | tr -d '"')
npm version "$VERSION" --no-git-tag-version
jq ".tauri.bundle.version = \"$VERSION\"" app/src-tauri/tauri.conf.json -i
git commit -am "chore(release): bump to $VERSION"
git tag "v$VERSION-staging"
Staging tags follow the format v1.2.3-staging, which sorts lexicographically before the production tag v1.2.3. This allows the team to test installers and auto-updaters before final promotion.
Production Promotions
The release-production.yml workflow supports two paths:
- Promotion: Takes a validated staging tag and removes the
-stagingsuffix without generating a new version number - Main-head releases: On direct
mainbranch runs, can bumppatch,minor, ormajorversions (restricted to the main branch only)
If any matrix build fails during the process, a cleanup job removes the draft release and associated tag, leaving the preceding staging tag untouched for later promotion.
Version Enforcement and Gates
Minimum Supported App Version
The frontend enforces a minimum-supported-app-version gate for OAuth authentication flows. This prevents outdated clients from completing OAuth deep-links when critical security updates are required.
The gate is configured via the VITE_MINIMUM_SUPPORTED_APP_VERSION environment variable during CI builds and checked in app/src/utils/oauthAppVersionGate.ts:
// app/src/utils/oauthAppVersionGate.ts
import { MIN_SUPPORTED_VERSION } from '@/utils/config';
export function isVersionSupported(current: string): boolean {
// semver compare – returns true if current ≥ minimum
return semver.gte(current, MIN_SUPPORTED_VERSION);
}
Health Check and RPC Exposure
Every OpenHuman component reports the same version string through the health system. The openhuman.health_system_info.version field in RPC responses contains the CARGO_PKG_VERSION value, ensuring that agents, monitoring tools, and CLI utilities see consistent versioning:
// src/openhuman/health/ops.rs example pattern
let version = env!("CARGO_PKG_VERSION");
// Exposed via health RPC schema
Rollback and Cleanup Procedures
The CI workflows include defensive measures for failed releases. If any build matrix job fails (Windows, macOS, or Linux), a cleanup job automatically removes the draft GitHub release and deletes the associated tag. This leaves the repository in a clean state with the previous staging tag available for immediate promotion, eliminating the need for manual version rollback or tag deletion.
Summary
- Single source of truth:
Cargo.tomlholds the canonical version that becomesCARGO_PKG_VERSIONat compile time - Automated propagation: CI scripts update
app/package.jsonandtauri.conf.jsonto match the Rust crate version - Staging vs. production: Staging tags use the
-stagingsuffix; production promotes by removing the suffix without changing version numbers - Security gates: OAuth flows enforce minimum app versions via
VITE_MINIMUM_SUPPORTED_APP_VERSIONandapp/src/utils/oauthAppVersionGate.ts - Atomic rollbacks: Failed builds trigger automatic cleanup of draft releases and tags, leaving the previous staging tag intact
Frequently Asked Questions
How does OpenHuman ensure version consistency across Rust and TypeScript codebases?
OpenHuman treats Cargo.toml as the single source of truth. During the CI release process, scripts/prepare-build.sh reads the version from Cargo.toml and injects it into app/package.json and app/src-tauri/tauri.conf.json using npm version and jq. The Rust code exposes this value to the frontend via Tauri's env!("CARGO_PKG_VERSION") injection, ensuring the Vite bundle receives the exact same version string that is compiled into the binary.
What is the difference between staging and production tags in OpenHuman?
Staging tags append the -staging suffix (e.g., v1.2.3-staging) and are created automatically on every main branch push with a patch version bump. Production tags drop the suffix (e.g., v1.2.3) and are created either by promoting an existing staging tag or by running a main-head release with manual version bumping. The suffix ensures staging releases sort before production releases in semantic versioning comparisons while remaining distinct from final artifacts.
How does OpenHuman prevent outdated clients from authenticating via OAuth?
The repository implements a minimum supported app version gate through app/src/utils/oauthAppVersionGate.ts. During CI builds, the VITE_MINIMUM_SUPPORTED_APP_VERSION environment variable is baked into the frontend bundle. When processing OAuth deep-links, the application compares the running binary's version (exposed via Tauri) against this minimum threshold using semantic versioning comparison. If the current version is lower, the authentication flow is blocked until the user updates.
What happens if a release build fails in the CI pipeline?
If any matrix build (Windows, macOS, or Linux) fails during the release process, a cleanup job automatically removes the draft GitHub release and deletes the associated git tag. This atomic rollback leaves the previous staging tag untouched, allowing the team to either fix the issue and retry or promote the previous stable staging tag to production without manual version manipulation or repository cleanup.
Have a question about this repo?
These articles cover the highlights, but your codebase questions are specific. Give your agent direct access to the source. Share this with your agent to get started:
curl -s "https://instagit.com/install.md" Maintain an open-source project? Get it listed too →