Skip to content

Verify Publish

Verify Publish #16

name: Verify Publish
# Manually triggered smoke test against the npm registry — run after a Publish
# Package workflow completes. Installs the just-published package into a clean
# environment and exercises it enough to catch "published but broken" failures
# (bin missing +x, workspace:* deps not rewritten, missing exports, etc.).
on:
workflow_dispatch:
inputs:
package:
description: 'Package to verify'
required: true
default: '@agentworkforce/cli'
type: choice
options:
- '@agentworkforce/events'
- '@agentworkforce/persona-kit'
- '@agentworkforce/runtime'
- '@agentworkforce/compose'
- '@agentworkforce/delivery'
- '@agentworkforce/workload-router'
- '@agentworkforce/deploy'
- '@agentworkforce/review-kit'
- '@agentworkforce/mcp-workforce'
- '@agentworkforce/daytona-runner'
- '@agentworkforce/local-surface'
- '@agentworkforce/cli'
- 'agentworkforce'
version:
description: 'Version to verify (defaults to the "latest" dist-tag)'
required: false
default: latest
tag:
description: 'Alternate dist-tag to pull from if `version` is left as default'
required: false
default: latest
permissions:
contents: read
jobs:
verify:
name: Install + smoke test
runs-on: ubuntu-latest
steps:
- name: Setup Node
uses: actions/setup-node@v4
with:
node-version: '26.5.0'
registry-url: 'https://registry.npmjs.org'
- name: Resolve version
id: resolve
run: |
INPUT='${{ github.event.inputs.version }}'
TAG='${{ github.event.inputs.tag }}'
if [ -z "$INPUT" ] || [ "$INPUT" = "latest" ]; then
RESOLVED=$(npm view "${{ github.event.inputs.package }}@$TAG" version)
else
RESOLVED="$INPUT"
fi
echo "version=$RESOLVED" >> "$GITHUB_OUTPUT"
echo "Verifying ${{ github.event.inputs.package }}@$RESOLVED"
- name: CLI smoke test
if: ${{ github.event.inputs.package == 'agentworkforce' }}
run: |
set -euo pipefail
# The top-level `agentworkforce` package is the user-facing global
# CLI package. The scoped @agentworkforce/cli package is an
# implementation dependency and intentionally does not declare a bin.
BIN="agentworkforce"
npm install -g "${{ github.event.inputs.package }}@${{ steps.resolve.outputs.version }}"
# --help should exit 0 and print the usage block.
output=$("$BIN" --help)
echo "$output"
echo "$output" | grep -q "Usage: $BIN " || {
echo "::error::--help output did not include expected usage block (looking for 'Usage: $BIN ')" >&2
exit 1
}
# Bare invocation should exit non-zero with the usage text.
if "$BIN" > /dev/null 2>&1; then
echo "::error::bare $BIN should exit non-zero (missing subcommand)" >&2
exit 1
fi
# Unknown persona should exit non-zero and list the catalog.
if "$BIN" agent __definitely_not_a_persona__ > /dev/null 2>&1; then
echo "::error::unknown persona should exit non-zero" >&2
exit 1
fi
echo "CLI smoke test passed."
- name: Scoped CLI package smoke test
if: ${{ github.event.inputs.package == '@agentworkforce/cli' }}
run: |
set -euo pipefail
WORKDIR=$(mktemp -d)
cd "$WORKDIR"
npm init -y > /dev/null
npm install "${{ github.event.inputs.package }}@${{ steps.resolve.outputs.version }}"
node --input-type=module <<'EOF'
import { readFileSync } from 'node:fs';
import assert from 'node:assert/strict';
const pkg = JSON.parse(readFileSync('node_modules/@agentworkforce/cli/package.json', 'utf8'));
assert.equal(pkg.name, '@agentworkforce/cli');
assert.equal(pkg.version, '${{ steps.resolve.outputs.version }}');
assert.equal(pkg.bin, undefined);
const mod = await import('./node_modules/@agentworkforce/cli/dist/cli.js');
assert.equal(typeof mod.main, 'function');
console.log(`scoped CLI package smoke passed for ${pkg.name}@${pkg.version}`);
EOF
- name: Library smoke test (ESM import + exports surface)
if: ${{ github.event.inputs.package != '@agentworkforce/cli' && github.event.inputs.package != 'agentworkforce' }}
run: |
set -euo pipefail
WORKDIR=$(mktemp -d)
cd "$WORKDIR"
npm init -y > /dev/null
node -e "require('fs').writeFileSync('package.json', JSON.stringify({...require('./package.json'), type:'module'}, null, 2))"
npm install "${{ github.event.inputs.package }}@${{ steps.resolve.outputs.version }}"
cat > check.mjs <<'EOF'
const mod = await import(process.argv[2]);
const exports = Object.keys(mod).sort();
if (exports.length === 0) {
console.error('no exports from package');
process.exit(1);
}
console.log('exports:', exports.join(', '));
EOF
node check.mjs "${{ github.event.inputs.package }}"
echo "Library smoke test passed."
- name: Summary
if: always()
run: |
{
echo "### Verify Publish"
echo ""
echo "- **package**: \`${{ github.event.inputs.package }}\`"
echo "- **version**: \`${{ steps.resolve.outputs.version }}\`"
echo "- **result**: ${{ job.status }}"
} >> "$GITHUB_STEP_SUMMARY"