From 284451864389fbd6dd57c0699d738ba90467bbce Mon Sep 17 00:00:00 2001 From: Claude Date: Tue, 7 Jul 2026 19:39:33 +0000 Subject: [PATCH] ci: automate npm publish of the portable skill MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Add .github/workflows/publish-skill.yml to publish skill/infographic-agent to npm automatically. On a push to main that changes the skill, it reads the version from package.json and publishes only if that version is not already on npm — so a version bump releases, while doc/script edits are safe no-ops. Includes npm provenance (OIDC), package sanity checks, and a skill-v git tag on release. Also runnable manually via workflow_dispatch. Document the flow and the required NPM_TOKEN secret in docs/releasing.md. Co-Authored-By: Claude Opus 4.8 Claude-Session: https://claude.ai/code/session_018VA5q9TqsQjnmj6myJeB1g --- .github/workflows/publish-skill.yml | 80 +++++++++++++++++++++++++++++ docs/releasing.md | 54 +++++++++++++++++++ 2 files changed, 134 insertions(+) create mode 100644 .github/workflows/publish-skill.yml create mode 100644 docs/releasing.md diff --git a/.github/workflows/publish-skill.yml b/.github/workflows/publish-skill.yml new file mode 100644 index 0000000..c5b6978 --- /dev/null +++ b/.github/workflows/publish-skill.yml @@ -0,0 +1,80 @@ +name: Publish skill to npm + +# Automatically publishes the portable skill (skill/infographic-agent) to npm. +# +# How it works — "automagic" releases: +# 1. Bump `version` in skill/infographic-agent/package.json (and update CHANGELOG.md). +# 2. Merge to main. +# 3. This workflow runs, sees the new version is not yet on npm, and publishes it. +# +# It is safe and idempotent: unrelated edits to the skill (docs, script tweaks) +# re-run the workflow but publish nothing, because the version already exists on +# npm. Only a version bump triggers an actual publish. You can also run it +# manually from the Actions tab (workflow_dispatch) — handy for the very first +# release once the package lands on main. +# +# Required secret: NPM_TOKEN — an npm "Automation" access token with publish +# rights for the `infographic-agent` package (Settings → Secrets and variables +# → Actions). Publishes include npm provenance for supply-chain attestation. + +on: + push: + branches: [main] + paths: + - 'skill/infographic-agent/**' + workflow_dispatch: + +concurrency: + group: publish-skill + cancel-in-progress: false + +permissions: + contents: write # push the release tag + id-token: write # npm provenance (OIDC attestation) + +jobs: + publish: + runs-on: ubuntu-latest + defaults: + run: + working-directory: skill/infographic-agent + steps: + - uses: actions/checkout@v4 + + - uses: actions/setup-node@v4 + with: + node-version: "20" + registry-url: "https://registry.npmjs.org" + + - name: Sanity-check the package + run: | + node --check bin/infographic-agent.js + python3 -m py_compile portable_infographic.py + npm pack --dry-run + + - name: Resolve version & publish state + id: v + run: | + VERSION="$(node -p "require('./package.json').version")" + echo "version=$VERSION" >> "$GITHUB_OUTPUT" + if npm view "infographic-agent@$VERSION" version >/dev/null 2>&1; then + echo "exists=true" >> "$GITHUB_OUTPUT" + echo "::notice::infographic-agent@$VERSION is already on npm — nothing to publish." + else + echo "exists=false" >> "$GITHUB_OUTPUT" + echo "::notice::infographic-agent@$VERSION is new — publishing." + fi + + - name: Publish to npm + if: steps.v.outputs.exists == 'false' + run: npm publish --provenance --access public + env: + NODE_AUTH_TOKEN: ${{ secrets.NPM_TOKEN }} + + - name: Tag the release + if: steps.v.outputs.exists == 'false' + working-directory: . + run: | + TAG="skill-v${{ steps.v.outputs.version }}" + git tag "$TAG" + git push origin "$TAG" diff --git a/docs/releasing.md b/docs/releasing.md new file mode 100644 index 0000000..03f8059 --- /dev/null +++ b/docs/releasing.md @@ -0,0 +1,54 @@ +# Releasing the portable skill to npm + +The portable skill in [`skill/infographic-agent/`](../skill/infographic-agent/) is +published to npm as [`infographic-agent`](https://www.npmjs.com/package/infographic-agent) +so anyone can run it with `npx infographic-agent "..."`. + +Releases are **automated** by +[`.github/workflows/publish-skill.yml`](../.github/workflows/publish-skill.yml). + +## Cutting a release (the automagic path) + +1. Make your changes under `skill/infographic-agent/`. +2. Bump `version` in `skill/infographic-agent/package.json` following + [SemVer](https://semver.org/) (patch for fixes, minor for features, major for + breaking changes). +3. Add a matching entry to [`CHANGELOG.md`](../CHANGELOG.md). +4. Open a PR and merge it to `main`. + +On merge, the workflow: + +- sanity-checks the package (`node --check`, `py_compile`, `npm pack --dry-run`), +- checks whether that version is already on npm, +- if it's new, runs `npm publish --provenance --access public`, and +- pushes a `skill-v` git tag. + +If the version is unchanged, the workflow still runs but publishes nothing — so +doc-only or script-only edits are safe no-ops. To publish the very first version +after this workflow lands, trigger it once manually from the **Actions** tab +(**Publish skill to npm → Run workflow**). + +## One-time setup: the `NPM_TOKEN` secret + +The workflow authenticates to npm with a repository secret named `NPM_TOKEN`. + +1. On [npmjs.com](https://www.npmjs.com/), go to **Access Tokens → Generate New + Token → Granular Access Token** (or a classic **Automation** token). Grant it + **read + write** for the `infographic-agent` package. Automation/granular + tokens bypass 2FA, which CI requires. +2. In GitHub: **Settings → Secrets and variables → Actions → New repository + secret**, name it `NPM_TOKEN`, and paste the token. + +Publishes include [npm provenance](https://docs.npmjs.com/generating-provenance-statements) +via GitHub OIDC (`id-token: write`), which cryptographically links each published +version back to the exact commit and workflow that built it. + +## Manual publish (fallback) + +If you ever need to publish by hand: + +```bash +cd skill/infographic-agent +npm publish --dry-run # verify contents first +npm publish --access public +```