Release Strategy for Openship Packages: Automated Semantic Versioning and Distribution
Openship employs a single-source-of-truth versioning model where scripts/release.ts synchronizes semantic versions across all monorepo packages, commits changes, creates Git tags, and triggers a GitHub Actions workflow that builds cross-platform installers, publishes the CLI to npm via OIDC, and creates annotated GitHub Releases with SHA-256 checksums.
The oblien/openship repository maintains a unified release pipeline for its CLI, desktop application, web dashboard, and email service. Understanding the release strategy for openship packages ensures that contributors can ship consistent, reproducible updates across all distribution channels while maintaining strict version alignment between components.
Single-Source-of-Truth Versioning
Openship centralizes version authority in apps/api/package.json. The release script reads the current version from this file, detects drift against the root package.json, and computes the next semantic version based on the specified bump type. This approach guarantees that the API package—which serves as the operative source—dictates the version for the entire ecosystem.
The SYNCED_PKGS array in scripts/release.ts defines which manifests receive version updates: the root package.json, apps/api/package.json, apps/desktop/package.json, apps/web/package.json, apps/email/package.json, and apps/cli/package.json. When the script executes, it writes the new version to all listed manifests atomically.
The Release Automation Script (scripts/release.ts)
Located at scripts/release.ts, the central release orchestrator handles version computation, manifest synchronization, advisory generation, and Git operations.
Computing and Synchronizing Versions
The script accepts bump arguments (patch, minor, major, rc) or explicit semver strings (e.g., 1.2.0-beta.3). It validates the current state by comparing apps/api/package.json against the root manifest, then calculates the next version. Lines 46-53 of the script iterate through SYNCED_PKGS to update each package.json with the computed version, ensuring lock-step consistency across the monorepo.
Advisory Integration and User Notifications
When the publish flag is provided, the script writes an entry to release-advisories.json at lines 62-71. This JSON file drives the in-app upgrade banner, supporting severity levels of critical, recommended, or info. Only stable releases (tags without a hyphen) trigger user-facing announcements; prerelease tags (-rc.N, -beta.N) bypass the advisory system to prevent notification fatigue.
Git Tagging and Commit Operations
After staging modified files, the script creates a commit with the message Bump to vX.Y.Z (or Announce vX.Y.Z when publishing an advisory) and pushes the branch. It then generates an annotated Git tag matching the version (e.g., v2.1.0) and pushes the tag to origin. This tag push serves as the definitive trigger for the CI/CD pipeline.
CI/CD Pipeline Execution (.github/workflows/release.yml)
The file .github/workflows/release.yml defines the Release workflow, which triggers on push.tags: 'v*.*.*'.
Build Matrix and Artifact Generation
The workflow executes a multi-stage build process:
- Native installers: Compiles distributables for macOS, Windows, and Linux
- Server packages: Creates tarballs for the API and email service
- Dashboard bundle: Builds the Next.js web dashboard for static deployment
Each artifact receives a SHA-256 checksum for integrity verification.
NPM Publishing with OIDC Trusted Publishing
Lines 45-50 of the workflow configure npm publishing using OIDC trusted publishing, eliminating the need for long-lived authentication tokens. The openship CLI package uploads to the npm registry automatically upon successful build completion.
GitHub Release Creation
The final stage assembles a GitHub Release containing all built assets, including desktop installers, API tarballs, and checksum files. The workflow automatically classifies the release as stable or prerelease based on the tag format—tags containing a hyphen (e.g., v2.0.0-rc.1) are marked as prereleases, while standard semver tags generate full releases.
Running a Release: Practical Commands
Execute releases locally using bun scripts/release.ts with the following patterns:
Basic patch release without announcement:
bun scripts/release.ts patch
Announced minor release with advisory:
bun scripts/release.ts minor publish
Critical security release with custom messaging:
bun scripts/release.ts major publish --critical --message="⚡️ Critical security update – upgrade now!"
Dry-run to preview changes:
bun scripts/release.ts rc --dry-run
Explicit prerelease version:
bun scripts/release.ts 1.2.0-beta.3
Key Configuration Files
The release strategy relies on several critical files:
scripts/release.ts— Central automation script handling version computation, manifest syncing, and Git operations.github/workflows/release.yml— CI workflow triggered by version tags; manages builds, publishing, and release creationrelease-advisories.json— Database of upgrade advisories controlling in-app notification bannersapps/api/package.json— Canonical version source used to determine the next release numberapps/cli/package.json— Manifest for the npm-published CLI toolapps/desktop/package.json,apps/web/package.json,apps/email/package.json— Synchronized manifests for platform-specific builds
Summary
- Openship uses
apps/api/package.jsonas the single source of truth for version numbers across all packages. - The
scripts/release.tsCLI tool automates version bumping, manifest synchronization, advisory creation, and Git tagging. - Pushing a
v*.*.*tag triggers.github/workflows/release.ymlto build cross-platform installers and publish the CLI to npm via OIDC. - Stable releases support in-app upgrade notifications through
release-advisories.json, while prereleases (-rc,-beta) bypass user announcements. - The workflow generates SHA-256 checksums for all artifacts and creates fully annotated GitHub Releases automatically.
Frequently Asked Questions
How does Openship ensure all packages stay synchronized?
The SYNCED_PKGS array in scripts/release.ts explicitly lists every package manifest that must share the same version. When the script runs, it writes the computed version to the root package.json, apps/api/package.json, apps/desktop/package.json, apps/web/package.json, apps/email/package.json, and apps/cli/package.json in a single operation, preventing version drift between components.
What distinguishes stable releases from prereleases in the Openship workflow?
The .github/workflows/release.yml workflow parses the Git tag format to classify releases. Tags matching v*.*.* without hyphens (e.g., v2.1.0) trigger stable release processes, including eligibility for release-advisories.json entries. Tags containing hyphens (e.g., v2.1.0-rc.1 or v2.1.0-beta.3) are automatically marked as prereleases in GitHub and do not generate in-app upgrade banners.
How is the openship CLI published to npm without storing authentication tokens?
The release workflow implements OIDC trusted publishing as configured in lines 45-50 of .github/workflows/release.yml. This mechanism allows the GitHub Actions runner to exchange a short-lived OIDC token for temporary npm publish permissions, eliminating the need to store long-lived npm authentication tokens in repository secrets.
Can I test the release process without creating an actual tag or commit?
Yes. Append the --dry-run flag to any release command (e.g., bun scripts/release.ts minor --dry-run). This executes the version computation and file modification logic without committing changes, creating tags, or pushing to the remote repository, allowing maintainers to preview the exact files and versions that would be affected.
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 →