OpenWork Release Process: Complete Workflow Guide
OpenWork’s release workflow follows a three-phase process—review, prepare, and ship—controlled by pnpm scripts in scripts/release/ that validate workspace consistency, bump versions, create lightweight Git tags, and trigger GitHub Actions builds for cross-platform desktop app distribution.
The different-ai/openwork repository manages its deployment pipeline through a sophisticated CLI-driven workflow designed for reliability and team coordination. Understanding the release process for OpenWork requires examining the three root scripts located under scripts/release/ that orchestrate everything from version validation to GitHub release publication.
The Three-Phase Release Workflow
The entire release process for OpenWork is driven by three distinct phases executed through pnpm commands. Each phase is implemented as a Node.js script in the scripts/release/ directory.
Phase 1: Review (pnpm release:review)
The review phase validates that the workspace is ready for a version bump. Running pnpm release:review executes the scripts/release/review.mjs script to perform two critical checks:
- Verifies that version numbers across the workspace are consistent
- Confirms that the
opencodepin is present in the repository
This step must succeed before proceeding to the prepare phase. It acts as a gatekeeper to prevent releasing from an inconsistent state.
Phase 2: Prepare (pnpm release:prepare)
The prepare phase handles version bumping, commit creation, and tag generation. Implemented in scripts/release/prepare.mjs, this script performs several validation and mutation steps:
- Tool-chain validation – Ensures the pinned pnpm version matches
package.json’spackageManagerfield - Git state checks – Verifies you are on the
devbranch with a clean working tree - Synchronization – Executes a pull-rebase against
origin/devto ensure the latest changes are present - Version bump – Runs
pnpm bump:<patch|minor|major>to increment version numbers and regenerate the lockfile - Commit and tag – Creates a commit with the message
chore: bump version to …and generates a lightweight tagvX.Y.Z
The script temporarily disables global tag.gpgsign settings to avoid annotation problems during tag creation. Importantly, this phase is idempotent—if a bump commit already exists but the tag is missing, rerunning pnpm release:prepare resumes directly at the tagging step without duplicating work.
For testing changes without mutation, use the dry-run variant:
pnpm release:prepare:dry
All actions in this phase occur locally; no pushes occur to the remote repository at this stage.
Phase 3: Ship (pnpm release:ship)
The ship phase pushes artifacts to the remote and triggers the CI/CD pipeline. The scripts/release/ship.mjs script executes:
- Pushes the newly created tag to
origin - Attempts to synchronize the
devbranch (which is protected) - If direct push is rejected due to branch protection, creates a temporary branch
release/<tag>-dev-syncand opens a back-fill PR for team approval - Prints the URL to the "Release App" GitHub Actions workflow and the GitHub release page
To monitor the workflow execution in real-time:
pnpm release:ship:watch
GitHub Actions Automation
Once the ship phase pushes a tag, the .github/workflows/release-macos-aarch64.yml workflow automatically triggers. This workflow:
- Builds the Electron desktop application for macOS, Windows, and Linux
- Publishes the build assets to GitHub
- Executes the "Publish GitHub Release" step to transition the release from draft to public
The release is considered complete only when this workflow succeeds and the GitHub release is no longer in draft state. The full documentation for this automation resides in docs/RELEASING.md.
Branch Protection and Release Strategies
The release process for OpenWork accommodates two distinct strategies based on team permissions and urgency.
Tag-First (Admin Shortcut)
Administrators can execute pnpm release:prepare followed immediately by pnpm release:ship to create and push a tag directly, bypassing the normal PR merge workflow. This works because tags matching v* are admin-bypassable in the repository settings.
PR-First (Standard Flow)
The standard approach merges a bump PR into dev before shipping. The dev branch enforces strict protection rules:
- Pull-request-only updates
- Required approvals from a different person than the pusher
- Signed commit requirements
- Linear history enforcement
These guarantees ensure only reviewed code reaches subsequent releases.
Idempotency and Recovery
The release scripts are designed for resilience. If pnpm release:prepare crashes after committing but before tagging, rerunning the command resumes at the tagging step without creating duplicate commits.
If a defective tag is created, recovery involves:
- Deleting the draft release on GitHub
- Removing the local tag:
git tag -d vX.Y.Z - Rerunning the prepare and ship commands
To manually retry a failed workflow without creating a new tag:
gh workflow run "Release App" --repo different-ai/openwork -f tag=v0.18.15
Summary
- OpenWork uses three pnpm commands (
release:review,release:prepare,release:ship) orchestrated by scripts inscripts/release/ - The prepare phase in
scripts/release/prepare.mjscreates lightweight tags and is idempotent, resuming at tagging if interrupted - The ship phase in
scripts/release/ship.mjshandles protected branch constraints by creating temporaryrelease/<tag>-dev-syncbranches and back-fill PRs when direct pushes fail - Releases trigger via the
.github/workflows/release-macos-aarch64.ymlworkflow only after tag push, building cross-platform Electron assets - Complete release documentation exists in
docs/RELEASING.md
Frequently Asked Questions
What is the release process for OpenWork?
The release process for OpenWork consists of three phases: review (validation), prepare (bump and tag), and ship (push and sync). These are executed via pnpm release:review, pnpm release:prepare, and pnpm release:ship commands that validate workspace state, create lightweight Git tags, and trigger GitHub Actions builds.
How does OpenWork handle version bumping and tagging?
Version bumping occurs in scripts/release/prepare.mjs, which validates the toolchain, checks git state, performs the bump, regenerates lockfiles, commits changes, and creates a lightweight tag named vX.Y.Z. The script disables tag.gpgsign temporarily to ensure lightweight tags are created correctly and is idempotent to allow recovery from interruptions.
What happens if the dev branch is protected during release?
If pnpm release:ship cannot push directly to the protected dev branch, it automatically creates a temporary branch named release/<tag>-dev-sync and opens a back-fill pull request. This allows a teammate to approve the synchronization, ensuring compliance with branch protection rules requiring reviews and signed commits.
How can I retry a failed release without creating a new version?
You can manually trigger the release workflow for an existing tag using the GitHub CLI: gh workflow run "Release App" --repo different-ai/openwork -f tag=vX.Y.Z. This avoids unnecessary version bumps when the issue was with the CI/CD pipeline rather than the code itself.
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 →