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:

Summary

  • Openship uses apps/api/package.json as the single source of truth for version numbers across all packages.
  • The scripts/release.ts CLI tool automates version bumping, manifest synchronization, advisory creation, and Git tagging.
  • Pushing a v*.*.* tag triggers .github/workflows/release.yml to 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:

Share the following with your agent to get started:
curl -s "https://instagit.com/install.md"

Works with
Claude Codex Cursor VS Code OpenClaw Any MCP Client

Maintain an open-source project? Get it listed too →