Files
openprose__prose/.github/workflows/cli-release-check.yml
dan f9c84b834e Fix CLI workflows for the pnpm-workspace consolidation (#89)
* Fix CLI workflows for the pnpm-workspace consolidation

The Reactor consolidation moved the CLI into the pnpm workspace, but the
npm-to-pnpm workflow conversion was incomplete and broke CI on main.

- Add the missing pnpm/action-setup step before every setup-node that
  sets cache: pnpm (cli-real-harness-smoke, cli-release-check, release).
  Without pnpm on PATH, setup-node fails: "Unable to locate executable
  file: pnpm".
- Rework the npm-package-smoke job to pack with pnpm. npm pack does not
  rewrite the workspace: protocol dependency on @openprose/reactor;
  pnpm pack does. The install smoke now resolves that dependency from a
  locally packed reactor tarball so it does not depend on the registry.

* Build the Reactor dependency before the CLI compiles in CI

After the workspace consolidation the CLI typechecks and builds against
@openprose/reactor, which must be built first.

- Add a "Build workspace" step before every CLI typecheck/build step
  (node-checks, release-tarball-smoke, cli-real-harness-smoke, and the
  release workflow's verify-cli and release-assets jobs).
- Drop the deleted tools/cli/package-lock.json entries from
  .version-bump.json so bump-version.sh --check no longer fails.

* Drop Node 18 from the CLI check matrix

The CLI now requires Node 20+ (engines.node >=20.0.0, enforced by
install.sh). The Node 18 matrix leg fails install.sh's version gate.
2026-05-20 23:03:27 -07:00

309 lines
9.1 KiB
YAML

name: CLI Release Check
on:
pull_request:
paths:
- "tools/cli/**"
- ".github/workflows/cli-release-check.yml"
- ".github/workflows/cli-real-harness-smoke.yml"
- ".github/workflows/cli-skills-smoke.yml"
- ".github/workflows/openprose-smoke.yml"
- ".github/workflows/release.yml"
- ".github/scripts/openprose-smoke/**"
- "scripts/release-preflight.sh"
- "scripts/bump-version.sh"
- ".version-bump.json"
push:
branches:
- main
paths:
- "tools/cli/**"
- ".github/workflows/cli-release-check.yml"
- ".github/workflows/cli-real-harness-smoke.yml"
- ".github/workflows/cli-skills-smoke.yml"
- ".github/workflows/openprose-smoke.yml"
- ".github/workflows/release.yml"
- ".github/scripts/openprose-smoke/**"
- "scripts/release-preflight.sh"
- "scripts/bump-version.sh"
- ".version-bump.json"
workflow_dispatch:
permissions:
contents: read
concurrency:
group: cli-release-check-${{ github.ref }}
cancel-in-progress: true
jobs:
lint-shell-and-actions:
name: Lint shell and workflow files
runs-on: ubuntu-latest
timeout-minutes: 10
steps:
- name: Checkout
uses: actions/checkout@v4
- name: Setup Go for actionlint
uses: actions/setup-go@v5
with:
go-version: stable
cache: false
- name: Install actionlint
run: go install github.com/rhysd/actionlint/cmd/actionlint@v1.7.7
- name: Lint GitHub Actions workflows
run: actionlint .github/workflows/cli-*.yml .github/workflows/plugin-manifest.yml .github/workflows/openprose-smoke.yml .github/workflows/release.yml
- name: Check installer shell syntax
run: bash -n tools/cli/install.sh
- name: Check release helper syntax
run: node --check tools/cli/scripts/build-release-tarball.mjs
- name: Check harness smoke helper syntax
run: node --check tools/cli/scripts/smoke-harness.mjs
- name: Check release shell syntax
run: |
bash -n scripts/bump-version.sh
bash -n scripts/release-preflight.sh
- name: OpenProse versions in sync
run: ./scripts/bump-version.sh --check
node-checks:
name: Node ${{ matrix.node-version }} checks
runs-on: ubuntu-latest
timeout-minutes: 20
strategy:
fail-fast: false
matrix:
node-version:
- 20
- 22
defaults:
run:
working-directory: tools/cli
steps:
- name: Checkout
uses: actions/checkout@v4
- name: Setup pnpm
uses: pnpm/action-setup@v4
- name: Setup Node
uses: actions/setup-node@v4
with:
node-version: ${{ matrix.node-version }}
cache: pnpm
cache-dependency-path: pnpm-lock.yaml
- name: Install dependencies
run: corepack enable && pnpm install --frozen-lockfile --dir ../..
- name: Build workspace
run: pnpm --dir ../.. run build
- name: Typecheck
run: npm run typecheck
- name: Test
run: npm test
- name: Build
run: npm run build
- name: Smoke built CLI
run: |
set -euo pipefail
node dist/index.js --help
node dist/index.js help
node dist/index.js run hello.prose.md --harness mock
PROSE_HARNESS=mock node dist/index.js status
npm-package-smoke:
name: npm package smoke
runs-on: ubuntu-latest
timeout-minutes: 20
defaults:
run:
working-directory: tools/cli
steps:
- name: Checkout
uses: actions/checkout@v4
- name: Setup pnpm
uses: pnpm/action-setup@v4
- name: Setup Node
uses: actions/setup-node@v4
with:
node-version: 22
cache: pnpm
cache-dependency-path: pnpm-lock.yaml
- name: Install dependencies
run: corepack enable && pnpm install --frozen-lockfile --dir ../..
- name: Build workspace
run: pnpm --dir ../.. run build
- name: Pack CLI and reactor artifacts
run: |
set -euo pipefail
pack_dir="$RUNNER_TEMP/npm-pack"
mkdir -p "$pack_dir"
# pnpm pack rewrites the workspace: protocol dependency on
# @openprose/reactor to a concrete version; npm pack does not.
pnpm pack --pack-destination "$pack_dir"
pnpm --dir ../../packages/reactor pack --pack-destination "$pack_dir"
ls -1 "$pack_dir"
- name: Validate npm package manifest
run: |
set -euo pipefail
cli_tarball="$(find "$RUNNER_TEMP/npm-pack" -maxdepth 1 -name 'openprose-prose-cli-*.tgz' -print -quit)"
tar -tzf "$cli_tarball" | sed 's#^package/##' | sed '/^$/d' | sort -u > "$RUNNER_TEMP/cli-pack-files.txt"
node --input-type=module <<'EOF'
import { readFileSync } from "node:fs";
const paths = new Set(
readFileSync(`${process.env.RUNNER_TEMP}/cli-pack-files.txt`, "utf8")
.split("\n")
.filter(Boolean),
);
const required = ["package.json", "README.md", "LICENSE", "dist/index.js", "dist/index.d.ts"];
const forbiddenPrefixes = ["src/", "tests/", "node_modules/"];
for (const path of required) {
if (!paths.has(path)) {
throw new Error(`npm package is missing ${path}`);
}
}
for (const path of paths) {
if (forbiddenPrefixes.some((prefix) => path.startsWith(prefix))) {
throw new Error(`npm package includes ${path}`);
}
if (path.endsWith(".map")) {
throw new Error(`npm package includes sourcemap ${path}`);
}
}
console.log("ok: npm package manifest");
EOF
- name: Smoke npm package artifact
run: |
set -euo pipefail
pack_dir="$RUNNER_TEMP/npm-pack"
cli_tarball="$(find "$pack_dir" -maxdepth 1 -name 'openprose-prose-cli-*.tgz' -print -quit)"
reactor_tarball="$(find "$pack_dir" -maxdepth 1 -name 'openprose-reactor-*.tgz' -print -quit)"
prefix="$RUNNER_TEMP/npm-prefix"
# The packed CLI depends on @openprose/reactor by exact version;
# install the locally packed reactor tarball alongside it so the
# smoke does not depend on the registry.
npm install --global --prefix "$prefix" "$reactor_tarball" "$cli_tarball"
"$prefix/bin/prose" --version
"$prefix/bin/prose" run hello.prose.md --harness mock
import_dir="$RUNNER_TEMP/npm-import-smoke"
mkdir -p "$import_dir"
cd "$import_dir"
npm init -y
npm install "$reactor_tarball" "$cli_tarball"
node --input-type=module -e "await import('@openprose/prose-cli')"
release-tarball-smoke:
name: Release tarball smoke on ${{ matrix.os }}
runs-on: ${{ matrix.os }}
timeout-minutes: 25
strategy:
fail-fast: false
matrix:
os:
- ubuntu-latest
- macos-latest
defaults:
run:
working-directory: tools/cli
steps:
- name: Checkout
uses: actions/checkout@v4
- name: Setup pnpm
uses: pnpm/action-setup@v4
- name: Setup Node
uses: actions/setup-node@v4
with:
node-version: 22
cache: pnpm
cache-dependency-path: pnpm-lock.yaml
- name: Install dependencies
run: corepack enable && pnpm install --frozen-lockfile --dir ../..
- name: Build workspace
run: pnpm --dir ../.. run build
- name: Build
run: npm run build
- name: Build and smoke release tarball
run: |
set -euo pipefail
release_dir="$RUNNER_TEMP/prose-release"
install_dir="$RUNNER_TEMP/prose-install"
bin_dir="$RUNNER_TEMP/prose-bin"
npm run release:tarball -- --out-dir "$release_dir" --skip-build
env \
PROSE_VERSION="$(node -p 'require("./package.json").version')" \
PROSE_BASE_URL="file://$release_dir" \
PROSE_INSTALL_DIR="$install_dir" \
PROSE_BIN_DIR="$bin_dir" \
sh install.sh
"$bin_dir/prose" --version
"$bin_dir/prose" run hello.prose.md --harness mock
- name: Upload release tarball
uses: actions/upload-artifact@v4
with:
name: cli-release-${{ runner.os }}-${{ runner.arch }}
path: ${{ runner.temp }}/prose-release/*
if-no-files-found: error
production-audit:
name: Production dependency audit
runs-on: ubuntu-latest
timeout-minutes: 15
defaults:
run:
working-directory: tools/cli
steps:
- name: Checkout
uses: actions/checkout@v4
- name: Setup pnpm
uses: pnpm/action-setup@v4
- name: Setup Node
uses: actions/setup-node@v4
with:
node-version: 22
cache: pnpm
cache-dependency-path: pnpm-lock.yaml
- name: Install dependencies
run: corepack enable && pnpm install --frozen-lockfile --dir ../..
- name: Audit production dependencies
run: npm run audit:policy