release #13
Workflow file for this run
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| name: release | |
| # Tag-driven publishing for @leadbay/mcp (npm) and @leadbay/leadclaw (npm + ClawHub). | |
| # | |
| # Tag scheme: | |
| # - mcp-v<ver> → publishes @leadbay/mcp only | |
| # - leadclaw-v<ver> → publishes @leadbay/leadclaw to npm, then ClawHub | |
| # - v<ver> → legacy alias for mcp-v<ver> (from the original release-mcp workflow) | |
| # | |
| # One-time setup (done in repo settings): | |
| # - NPM_TOKEN → npm automation token, scope-owner on @leadbay | |
| # - CLAWHUB_TOKEN → ClawHub publish token with rights to @leadbay/leadclaw | |
| # | |
| # No auto-version-bump, no auto-changelog. Bump `package.json` (and | |
| # `openclaw.plugin.json` for leadclaw) in a normal PR. Tagging is automatic: | |
| # `auto-tag.yml` watches main, sees the bumped version, and pushes the | |
| # corresponding tag, which triggers this workflow. Manual `git tag` is only | |
| # needed for emergency re-publish of a version already on main. | |
| on: | |
| push: | |
| tags: | |
| - "mcp-v*.*.*" | |
| - "leadclaw-v*.*.*" | |
| - "v*.*.*" | |
| workflow_dispatch: | |
| inputs: | |
| package: | |
| description: "Which package to publish (mcp | leadclaw)" | |
| required: true | |
| default: "mcp" | |
| type: choice | |
| options: [mcp, leadclaw] | |
| dry_run: | |
| description: "If true, npm half uses --dry-run (ClawHub has no dry-run; skipped on dry runs)" | |
| required: false | |
| default: "false" | |
| jobs: | |
| preflight-npm: | |
| name: Preflight — verify npm auth + @leadbay scope | |
| runs-on: ubuntu-latest | |
| steps: | |
| - uses: actions/setup-node@v4 | |
| with: | |
| node-version: 22 | |
| registry-url: "https://registry.npmjs.org" | |
| always-auth: true | |
| - name: whoami + scope probe | |
| env: | |
| NODE_AUTH_TOKEN: ${{ secrets.NPM_TOKEN }} | |
| run: | | |
| set -euo pipefail | |
| echo "Logged in as: $(npm whoami --registry=https://registry.npmjs.org)" | |
| # Scope-empty on first publish is OK; fall through. Fatal errors (401/403) | |
| # come from npm whoami above. | |
| npm access list packages @leadbay 2>&1 || echo "scope empty or no packages yet — first publish will create" | |
| publish-mcp: | |
| name: Publish @leadbay/mcp to npm | |
| needs: preflight-npm | |
| if: | | |
| startsWith(github.ref, 'refs/tags/mcp-v') || | |
| startsWith(github.ref, 'refs/tags/v') || | |
| (github.event_name == 'workflow_dispatch' && github.event.inputs.package == 'mcp') | |
| runs-on: ubuntu-latest | |
| permissions: | |
| contents: write # gh release create/upload for the .dxt bundle | |
| id-token: write # npm provenance | |
| steps: | |
| - uses: actions/checkout@v4 | |
| - uses: pnpm/action-setup@v4 | |
| with: | |
| version: 10 | |
| - uses: actions/setup-node@v4 | |
| with: | |
| node-version: 22 | |
| registry-url: "https://registry.npmjs.org" | |
| always-auth: true | |
| - name: Install | |
| run: pnpm install --frozen-lockfile | |
| - name: Build | |
| run: pnpm -r build | |
| - name: Test | |
| run: pnpm -r test | |
| - name: Verify tag matches packages/mcp/package.json version | |
| # Runs whenever the workflow is keyed off a tag ref — both real | |
| # tag-push events and auto-tag's workflow_dispatch on a tag ref. | |
| if: startsWith(github.ref, 'refs/tags/') | |
| run: | | |
| set -euo pipefail | |
| REF="${GITHUB_REF#refs/tags/}" | |
| # Strip either "mcp-v" or plain "v" prefix. | |
| TAG="${REF#mcp-v}" | |
| TAG="${TAG#v}" | |
| PKG_VERSION=$(node -p "require('./packages/mcp/package.json').version") | |
| if [ "$TAG" != "$PKG_VERSION" ]; then | |
| echo "Tag $REF → version $TAG does not match packages/mcp/package.json $PKG_VERSION" | |
| exit 1 | |
| fi | |
| echo "Aligned: $REF = $PKG_VERSION" | |
| - name: Publish | |
| working-directory: packages/mcp | |
| run: | | |
| set -euo pipefail | |
| VERSION=$(node -p "require('./package.json').version") | |
| # Idempotent: if @leadbay/mcp@$VERSION is already on npm, skip. | |
| if npm view "@leadbay/mcp@$VERSION" version --silent 2>/dev/null; then | |
| echo "@leadbay/mcp@$VERSION already on npm — skipping" | |
| exit 0 | |
| fi | |
| if [ "${{ github.event.inputs.dry_run }}" = "true" ]; then | |
| npm publish --access public --provenance --dry-run | |
| else | |
| npm publish --access public --provenance | |
| fi | |
| env: | |
| NODE_AUTH_TOKEN: ${{ secrets.NPM_TOKEN }} | |
| - name: Build .dxt bundle | |
| # Same gate as the tag-verify step: runs on any tag ref, including | |
| # auto-tag's workflow_dispatch. Skipped when running off main. | |
| if: startsWith(github.ref, 'refs/tags/') && github.event.inputs.dry_run != 'true' | |
| run: pnpm --filter @leadbay/dxt build | |
| - name: Upload .dxt to GitHub Release | |
| if: startsWith(github.ref, 'refs/tags/') && github.event.inputs.dry_run != 'true' | |
| env: | |
| GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} | |
| run: | | |
| set -euo pipefail | |
| TAG="${GITHUB_REF#refs/tags/}" | |
| # gh release upload needs a release to exist. Create it if the tag | |
| # wasn't already promoted to a release (auto-tag.yml only pushes tags). | |
| if ! gh release view "$TAG" >/dev/null 2>&1; then | |
| gh release create "$TAG" \ | |
| --title "$TAG" \ | |
| --notes "Automated release for $TAG — see CHANGELOG.md" | |
| fi | |
| gh release upload "$TAG" packages/dxt/dist/*.dxt --clobber | |
| echo "Uploaded .dxt to release $TAG" | |
| publish-leadclaw: | |
| name: Publish @leadbay/leadclaw to npm + ClawHub | |
| needs: preflight-npm | |
| if: | | |
| startsWith(github.ref, 'refs/tags/leadclaw-v') || | |
| (github.event_name == 'workflow_dispatch' && github.event.inputs.package == 'leadclaw') | |
| runs-on: ubuntu-latest | |
| permissions: | |
| contents: read | |
| id-token: write | |
| steps: | |
| - uses: actions/checkout@v4 | |
| - uses: pnpm/action-setup@v4 | |
| with: | |
| version: 10 | |
| - uses: actions/setup-node@v4 | |
| with: | |
| node-version: 22 | |
| registry-url: "https://registry.npmjs.org" | |
| always-auth: true | |
| - name: Install | |
| run: pnpm install --frozen-lockfile | |
| - name: Build | |
| run: pnpm -r build | |
| - name: Test | |
| run: pnpm -r test | |
| - name: Verify tag ↔ package.json ↔ openclaw.plugin.json version agreement | |
| if: startsWith(github.ref, 'refs/tags/') | |
| run: | | |
| set -euo pipefail | |
| TAG="${GITHUB_REF#refs/tags/leadclaw-v}" | |
| PKG=$(node -p "require('./packages/leadclaw/package.json').version") | |
| MAN=$(node -p "require('./packages/leadclaw/openclaw.plugin.json').version") | |
| if [ "$TAG" != "$PKG" ] || [ "$PKG" != "$MAN" ]; then | |
| echo "Version drift: tag=$TAG pkg=$PKG manifest=$MAN — bump all three to match" | |
| exit 1 | |
| fi | |
| echo "Aligned: $TAG = $PKG = $MAN" | |
| - name: Publish to npm | |
| working-directory: packages/leadclaw | |
| run: | | |
| set -euo pipefail | |
| VERSION=$(node -p "require('./package.json').version") | |
| # Idempotent: if @leadbay/leadclaw@$VERSION is already on npm, skip. | |
| # Handles the retry-after-ClawHub-failure case without manual intervention. | |
| if npm view "@leadbay/leadclaw@$VERSION" version --silent 2>/dev/null; then | |
| echo "@leadbay/leadclaw@$VERSION already on npm — skipping npm publish" | |
| exit 0 | |
| fi | |
| if [ "${{ github.event.inputs.dry_run }}" = "true" ]; then | |
| npm publish --access public --provenance --dry-run | |
| else | |
| npm publish --access public --provenance | |
| fi | |
| env: | |
| NODE_AUTH_TOKEN: ${{ secrets.NPM_TOKEN }} | |
| - name: Install ClawHub CLI | |
| if: github.event.inputs.dry_run != 'true' | |
| run: npm i -g clawhub@^0.9 | |
| - name: Authenticate ClawHub | |
| if: github.event.inputs.dry_run != 'true' | |
| env: | |
| CLAWHUB_TOKEN: ${{ secrets.CLAWHUB_TOKEN }} | |
| run: clawhub login --token "$CLAWHUB_TOKEN" --no-browser | |
| - name: Publish to ClawHub | |
| if: github.event.inputs.dry_run != 'true' | |
| run: | | |
| set -euo pipefail | |
| VERSION=$(node -p "require('./packages/leadclaw/package.json').version") | |
| clawhub package publish packages/leadclaw \ | |
| --version "$VERSION" \ | |
| --source-repo "$GITHUB_REPOSITORY" \ | |
| --source-commit "$GITHUB_SHA" \ | |
| --source-ref "${GITHUB_REF_NAME}" \ | |
| --source-path packages/leadclaw \ | |
| --tags latest |