How to Set Up CI/CD for OpenWork Development: A Complete Guide

To set up CI/CD for OpenWork development, configure the GitHub Actions workflows under .github/workflows/, install the exact toolchain—Node 24, pnpm 11.4, Bun, and the OpenCode CLI—and run the same test, build, and publish commands defined in ci-tests.yml and the specialized package pipelines.

This guide explains how to set up CI/CD for OpenWork development using the existing automation in the different-ai/openwork repository. The project defines its entire delivery cycle under .github/workflows/, ensuring every push or pull request to the dev branch is linted, tested, and built before it reaches production.

How OpenWork CI/CD Is Structured

All workflow definitions live in the .github/workflows/ directory on the dev branch. The primary entry point for continuous integration is .github/workflows/ci-tests.yml, which triggers on every push and pull request.

Several focused workflows complement the main pipeline:

Together these files provide a complete CI/CD cycle for OpenWork development.

The Core Test Pipeline in ci-tests.yml

The primary workflow triggers on every push or pull request to the dev branch. It begins by installing the required toolchain, including the OpenCode CLI whose version is read from constants.json. The job then caches the pnpm store using keys derived from pnpm-lock.yaml and evals/pnpm-lock.yaml before executing tests.

Build, Test, and Packaging Stages

The CI run follows a strict five-stage sequence:

  1. Build and lint — Verify syntax and run static analysis.
  2. Unit tests — Run package-level suites for @openwork/app, openwork-server, @openwork/desktop, and the eval runner.
  3. Integration and end-to-end tests — Execute pnpm --filter @openwork/app test:e2e.
  4. Packaging — Build server plugins exactly as the production bundle does via pnpm --filter openwork-server build.
  5. Publish readiness — When a Git tag matching openwork-ui-mcp-v* is pushed, the corresponding workflow publishes to npm using the NPM_TOKEN secret.

This sequence ensures that code merged into dev is linted, tested, and buildable before it reaches users.

Specialized and Release Workflows

Beyond the main pipeline, dedicated workflows enforce quality gates and manage releases.

Lint and Publish Checks for openwork-ui-mcp

The .github/workflows/ci-openwork-ui-mcp.yml file targets the openwork-ui-mcp package specifically. It runs node --check, performs a type-check, and executes npm publish --dry-run on every relevant change. If the commit is tagged with a version string like openwork-ui-mcp-v*, the workflow performs a real publish to the npm registry.

Guardrails and i18n Validation

The .github/workflows/ci-i18n.yml workflow extracts translation keys and fails if i18n rules are violated. Meanwhile, .github/workflows/ci-no-new-eval-flows.yml acts as a guardrail by ensuring no eval flow files are added unintentionally, keeping the repository’s evaluation surface stable.

Production Release Automation

Release workflows such as .github/workflows/release-macos-aarch64.yml handle signing and packaging for macOS on Apple Silicon, while .github/workflows/release-daytona-snapshot.yml produces Docker snapshots. These jobs run outside the standard dev branch PR flow and are triggered by release tags or manual dispatch.

Mirror the OpenWork CI Environment Locally

To reproduce the exact environment used by the GitHub Actions runners, run the same installation and verification steps locally. This is the fastest way to debug a failing job before pushing to the dev branch.


# 1. Clone the repository and checkout the dev branch

git clone https://github.com/different-ai/openwork.git
cd openwork
git checkout dev

# 2. Install the exact Node version (24) – you can use nvm or asdf

nvm install 24 && nvm use 24

# 3. Install pnpm (matches the CI version)

npm i -g pnpm@11.4.0

# 4. Install the OpenCode CLI (the same binary the CI downloads)

#    The version is read from constants.json; the script below mirrors the CI logic.

OPENCODE_GITHUB_REPO=${OPENCODE_GITHUB_REPO:-anomalyco/opencode}
VERSION=$(node -p "require('./constants.json').opencodeVersion.replace(/^v/, '')")
ARCH=$(uname -m)
case "$(uname -s)" in
  Linux)  [[ $ARCH == aarch64 || $ARCH == arm64 ]] && ASSET=opencode-linux-arm64.tar.gz || ASSET=opencode-linux-x64-baseline.tar.gz ;;
  Darwin) [[ $ARCH == arm64 ]] && ASSET=opencode-darwin-arm64.zip || ASSET=opencode-darwin-x64-baseline.zip ;;
  *) echo "Unsupported OS"; exit 1 ;;
esac
curl -L -o opencode.$ASSET "https://github.com/${OPENCODE_GITHUB_REPO}/releases/download/v${VERSION}/${ASSET}"

# Extract and put the binary on PATH (same as CI)

mkdir -p $HOME/.opencode/bin
if [[ $ASSET == *.tar.gz ]]; then tar -xzf opencode.$ASSET -C $HOME/.opencode/bin; else unzip -q opencode.$ASSET -d $HOME/.opencode/bin; fi
export PATH=$HOME/.opencode/bin:$PATH

# 5. Verify the CLI

opencode --version

# 6. Install Bun (used by some scripts)

curl -fsSL https://bun.sh/install | bash
export PATH=$HOME/.bun/bin:$PATH
bun --version

# 7. Install project dependencies (cached in CI)

pnpm install --frozen-lockfile --prefer-offline

# 8. Install the eval workspace (same as CI)

pnpm --dir evals install --frozen-lockfile --prefer-offline

# 9. Run the same test lanes as CI

pnpm --dir evals run spec                    # eval specs

pnpm --filter @openwork/app test             # app unit tests

pnpm --filter openwork-server test           # server unit tests

pnpm --filter @openwork/desktop test         # desktop unit tests

pnpm test:eval-runner                        # eval-runner unit tests

pnpm check:outbound-access                    # outbound-access manifest check

pnpm --filter openwork-server build           # build server plugins (type-check)

pnpm --filter @openwork/desktop typecheck:electron
pnpm --filter @openwork/app test:e2e        # e2e tests

Running these commands reproduces the same environment and verification steps executed on GitHub Actions. If a test fails locally, it will fail in CI, allowing you to fix issues before opening a pull request.

Customize and Extend Your OpenWork CI/CD

You can tune the pipeline to match evolving project needs without breaking the existing flow.

Summary

  • OpenWork CI/CD is orchestrated through GitHub Actions under .github/workflows/, with .github/workflows/ci-tests.yml serving as the main pipeline for the dev branch.
  • The CI toolchain requires Node 24, pnpm 11.4, Bun, and the OpenCode CLI, whose version is pinned in constants.json.
  • The pipeline covers build, unit tests, integration tests, end-to-end tests (pnpm --filter @openwork/app test:e2e), server plugin builds (pnpm --filter openwork-server build), and npm publishing.
  • Specialized workflows enforce i18n compliance, prevent new eval flows, and handle macOS and snapshot releases.
  • You can replicate the entire CI environment locally by running the installation and test commands exactly as defined in the workflows.

Frequently Asked Questions

What versions of Node, pnpm, and Bun does the OpenWork CI use?

The OpenWork CI runners currently use Node 24, pnpm 11.4, and the latest Bun release installed via the official install script. These versions are hard-coded in .github/workflows/ci-tests.yml and .github/workflows/ci-openwork-ui-mcp.yml, so local development should match them exactly to avoid lock file or runtime discrepancies.

How can I reproduce a failing OpenWork CI job on my machine?

Clone the dev branch, install the toolchain using the same commands found in .github/workflows/ci-tests.yml, and run the test lane that failed. The bash script above downloads the identical OpenCode CLI binary and executes pnpm install --frozen-lockfile --prefer-offline followed by the relevant pnpm --filter test and build commands.

Which Git tag format triggers npm publishing in OpenWork?

Pushing a tag that matches the pattern openwork-ui-mcp-v* triggers the publish job inside .github/workflows/ci-openwork-ui-mcp.yml. The workflow first runs npm publish --dry-run on every commit, but only performs the live publish to npm when it detects a matching tag and the NPM_TOKEN secret is available.

Where does OpenWork CI store its cache keys?

The pnpm store is cached using keys derived from the contents of pnpm-lock.yaml and evals/pnpm-lock.yaml. If either lock file changes, the cache is invalidated and dependencies are reinstalled. Adjust the actions/cache step in the workflow files if you add additional lock files to the repository.

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 →