Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
117 changes: 0 additions & 117 deletions .github/workflows/prerelease-cua-cli.yml

This file was deleted.

161 changes: 138 additions & 23 deletions .github/workflows/release-cua-cli.yml
Original file line number Diff line number Diff line change
Expand Up @@ -4,13 +4,20 @@ on:
push:
tags:
- "cua-cli/v*"
workflow_dispatch:
inputs:
dist_tag:
description: "npm dist-tag to publish under (never 'latest'); also used as the prerelease id"
required: true
default: "ext"
type: string

permissions:
contents: read
id-token: write

concurrency:
group: release-cua-cli-${{ github.ref_name }}
group: release-cua-cli-${{ github.event_name }}-${{ github.ref_name }}
cancel-in-progress: false

jobs:
Expand All @@ -24,23 +31,12 @@ jobs:
with:
fetch-depth: 0

- name: Verify tag is on main
- name: Verify production release
if: github.event_name == 'push'
run: |
git fetch origin main:refs/remotes/origin/main
git merge-base --is-ancestor "$GITHUB_SHA" origin/main

- uses: actions/setup-node@v5
with:
node-version: 24
registry-url: https://registry.npmjs.org

- name: Ensure npm supports trusted publishing
run: npm install -g npm@^11.5.1

- run: npm ci

- name: Verify package version matches tag
run: |
node --input-type=module <<'EOF'
import { readFileSync } from "node:fs";

Expand All @@ -59,13 +55,46 @@ jobs:
console.log(`${pkg.name}@${pkg.version}`);
EOF

- uses: actions/setup-node@v5
with:
node-version: 24
registry-url: https://registry.npmjs.org

- name: Ensure npm supports trusted publishing
run: npm install -g npm@^11.5.1

- run: npm ci

- name: Compute prerelease version
if: github.event_name == 'workflow_dispatch'
id: prerelease
env:
DIST_TAG: ${{ inputs.dist_tag }}
run: |
if [[ ! "$DIST_TAG" =~ ^[a-z0-9][a-z0-9-]*$ ]]; then
echo "dist_tag must be lowercase alphanumeric/hyphen, e.g. ext, next, pr-41 (got '$DIST_TAG')" >&2
exit 1
fi
if [[ "$DIST_TAG" == "latest" ]]; then
echo "refusing to publish a prerelease to the 'latest' dist-tag" >&2
exit 1
fi

BASE=$(node -p "require('./packages/cli/package.json').version")
VERSION="${BASE}-${DIST_TAG}.${GITHUB_RUN_NUMBER}"
npm pkg set version="$VERSION" --workspace @onkernel/cua-cli
echo "version=$VERSION" >> "$GITHUB_OUTPUT"
echo "cua-cli prerelease version: $VERSION"

- name: Cache Zig toolchain
if: github.event_name == 'push'
uses: actions/cache@v4
with:
path: .dev/tools/zig-x86_64-linux-${{ env.PTYWRIGHT_ZIG_VERSION }}
key: zig-${{ runner.os }}-${{ env.PTYWRIGHT_ZIG_VERSION }}

- name: Install Zig ${{ env.PTYWRIGHT_ZIG_VERSION }}
if: github.event_name == 'push'
run: |
set -euo pipefail
ZIG_DIR=".dev/tools/zig-x86_64-linux-${PTYWRIGHT_ZIG_VERSION}"
Expand All @@ -78,6 +107,7 @@ jobs:
echo "${GITHUB_WORKSPACE}/${ZIG_DIR}" >> "${GITHUB_PATH}"

- name: Cache ptywright native artifacts
if: github.event_name == 'push'
uses: actions/cache@v4
with:
path: |
Expand All @@ -88,37 +118,122 @@ jobs:
- run: npm run build --workspace @onkernel/cua-ai
- run: npm run build --workspace @onkernel/cua-agent

- name: Build ptywright (native binding)
run: npm run build --workspace @onkernel/ptywright

- name: Build cua-cli
run: npm run build --workspace @onkernel/cua-cli

- name: Verify runtime dependencies are published
- name: Verify published production dependencies
if: github.event_name == 'push'
run: |
node -p 'require("./packages/cli/package.json").dependencies["@onkernel/cua-ai"]' \
| xargs -I{} npm view @onkernel/cua-ai@{} version
node -p 'require("./packages/cli/package.json").dependencies["@onkernel/cua-agent"]' \
| xargs -I{} npm view @onkernel/cua-agent@{} version

- name: Build ptywright (native binding)
if: github.event_name == 'push'
run: npm run build --workspace @onkernel/ptywright

- name: Build cua-cli
run: npm run build --workspace @onkernel/cua-cli

- name: CLI unit tests
if: github.event_name == 'push'
env:
PTYWRIGHT_REQUIRED: "1"
run: npm test --workspace @onkernel/cua-cli

- name: Pack tarball
- name: Pack production tarball
if: github.event_name == 'push'
run: npm pack --workspace @onkernel/cua-cli --pack-destination "$RUNNER_TEMP"

- name: Pack branch workspace dependencies
if: github.event_name == 'workflow_dispatch'
run: |
mkdir -p "$RUNNER_TEMP/workspace-packages"
npm pack --workspace @onkernel/cua-ai --pack-destination "$RUNNER_TEMP/workspace-packages"
npm pack --workspace @onkernel/cua-agent --pack-destination "$RUNNER_TEMP/workspace-packages"

- name: Pack bundled CLI prerelease
if: github.event_name == 'workflow_dispatch'
run: |
export STAGE_DIR="$RUNNER_TEMP/cua-cli-prerelease"
mkdir -p "$STAGE_DIR/node_modules/@onkernel"
cp packages/cli/package.json packages/cli/README.md "$STAGE_DIR/"
cp -R packages/cli/dist "$STAGE_DIR/"

for package in cua-ai cua-agent; do
tarball=$(find "$RUNNER_TEMP/workspace-packages" -name "onkernel-${package}-*.tgz" -print -quit)
mkdir -p "$STAGE_DIR/node_modules/@onkernel/$package"
tar -xzf "$tarball" --strip-components=1 -C "$STAGE_DIR/node_modules/@onkernel/$package"
done

node --input-type=module <<'EOF'
import { readFileSync, writeFileSync } from "node:fs";
import { join } from "node:path";

const packagePath = join(process.env.STAGE_DIR, "package.json");
const pkg = JSON.parse(readFileSync(packagePath, "utf8"));
const bundled = ["@onkernel/cua-ai", "@onkernel/cua-agent"];

for (const name of bundled) {
const dependency = JSON.parse(
readFileSync(join(process.env.STAGE_DIR, "node_modules", name, "package.json"), "utf8"),
);
pkg.dependencies[name] = dependency.version;
for (const [dependencyName, version] of Object.entries(dependency.dependencies ?? {})) {
if (bundled.includes(dependencyName)) continue;
const current = pkg.dependencies[dependencyName];
if (current && current !== version) {
throw new Error(`Conflicting ${dependencyName} versions: ${current} and ${version}`);
}
pkg.dependencies[dependencyName] = version;
}
}

pkg.bundledDependencies = bundled;
writeFileSync(packagePath, `${JSON.stringify(pkg, null, 2)}\n`);
EOF

npm pack "$STAGE_DIR" --pack-destination "$RUNNER_TEMP"

- name: CLI bin smoke test
run: |
SMOKE_DIR=$(mktemp -d)
cd "$SMOKE_DIR"
npm init -y > /dev/null
npm install "$RUNNER_TEMP"/onkernel-cua-cli-*.tgz
if [[ "$GITHUB_EVENT_NAME" == "workflow_dispatch" ]]; then
test -f node_modules/@onkernel/cua-cli/node_modules/@onkernel/cua-ai/dist/index.js
test -f node_modules/@onkernel/cua-cli/node_modules/@onkernel/cua-agent/dist/index.js
fi
OUTPUT=$(./node_modules/.bin/cua --help)
echo "$OUTPUT"
echo "$OUTPUT" | grep -q "Usage:"
echo "$OUTPUT" | grep -q "cua \[options\] \[prompt\.\.\.\]"

- name: Publish to npm
- name: Publish production release
if: github.event_name == 'push'
run: npm publish --workspace @onkernel/cua-cli --access public

- name: Publish prerelease
if: github.event_name == 'workflow_dispatch'
env:
DIST_TAG: ${{ inputs.dist_tag }}
run: npm publish "$RUNNER_TEMP"/onkernel-cua-cli-*.tgz --access public --tag "$DIST_TAG"

- name: Prerelease summary
if: github.event_name == 'workflow_dispatch'
env:
DIST_TAG: ${{ inputs.dist_tag }}
VERSION: ${{ steps.prerelease.outputs.version }}
run: |
{
echo "### Prerelease published"
echo ""
echo "- version: \`$VERSION\`"
echo "- dist-tag: \`$DIST_TAG\`"
echo "- branch: \`$GITHUB_REF_NAME\` (\`$GITHUB_SHA\`)"
echo ""
echo "Install:"
echo ""
echo '```'
echo "npm install -g @onkernel/cua-cli@$DIST_TAG"
echo '```'
} >> "$GITHUB_STEP_SUMMARY"
Loading