From 114342553c22aaabb77ba390249fe659fd0c9e21 Mon Sep 17 00:00:00 2001 From: yya007 Date: Mon, 22 Jun 2026 22:28:40 -0700 Subject: [PATCH] ci: auto-publish npm when a fresh index lands on master MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Adds .github/workflows/npm-publish.yml: on a data/version.txt change pushed to master (a merged local index rebuild), it patch-bumps @yya007/skill-finder, publishes to npm (NPM_TOKEN secret — granular bypass-2FA token), tags v, and stamps the release log — entirely on GitHub runners, no local machine or OTP. Version is bumped from the *published* npm version, so a missed commit/push self-heals on the next run. workflow_dispatch supports dry_run (default true) to test without publishing. The index build stays manual/local (CI can't rebuild it, per PRD-005); only the npm release step is automated. Documents this in PRD-005. Co-Authored-By: Claude Opus 4.8 (1M context) --- .github/workflows/npm-publish.yml | 85 +++++++++++++++++++++++++++++++ docs/prd/PRD-005-ci-cd-release.md | 9 ++++ 2 files changed, 94 insertions(+) create mode 100644 .github/workflows/npm-publish.yml diff --git a/.github/workflows/npm-publish.yml b/.github/workflows/npm-publish.yml new file mode 100644 index 0000000..df39596 --- /dev/null +++ b/.github/workflows/npm-publish.yml @@ -0,0 +1,85 @@ +name: Publish npm package + +# Auto-publishes @yya007/skill-finder to npm when a fresh index lands on master +# (i.e. data/version.txt changes). The index itself is built LOCALLY and merged +# via PR — CI cannot rebuild it (see PRD-005). This job then bumps the patch +# version, publishes, tags v, and stamps the release log. +# +# Requires the NPM_TOKEN repo secret = a granular npm token with "Bypass 2FA" +# enabled (set via: gh secret set NPM_TOKEN). The version is bumped from the +# *published* npm version, so a missed commit/push self-heals on the next run. + +on: + push: + branches: [master] + paths: + - data/version.txt + workflow_dispatch: + inputs: + dry_run: + description: Dry run (pack + validate only — does NOT publish, commit, or tag) + type: boolean + default: true + +permissions: + contents: write # commit the version bump + push the tag + +concurrency: + group: npm-publish + cancel-in-progress: false + +jobs: + publish: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v4 + with: + fetch-depth: 0 + + - uses: actions/setup-node@v4 + with: + node-version: '20' + registry-url: https://registry.npmjs.org + + - uses: actions/setup-python@v5 + with: + python-version: '3.11' + + # On a push (fresh index merged) → real publish. On manual dispatch → + # honor the dry_run input (default true) so the flow can be tested safely. + - name: Resolve dry-run mode + run: echo "DRY_RUN=${{ github.event_name == 'workflow_dispatch' && inputs.dry_run }}" >> "$GITHUB_ENV" + + - name: Compute next version (patch bump from the published version) + run: | + PUB=$(npm view @yya007/skill-finder version 2>/dev/null || echo "0.0.0") + npm version "$PUB" --no-git-tag-version --allow-same-version >/dev/null + npm version patch --no-git-tag-version >/dev/null + NEW=$(node -p "require('./package.json').version") + echo "published=$PUB -> new=$NEW" + echo "NEW_VERSION=$NEW" >> "$GITHUB_ENV" + + - name: Publish to npm + env: + NODE_AUTH_TOKEN: ${{ secrets.NPM_TOKEN }} + run: | + if [ "$DRY_RUN" = "true" ]; then + echo "::notice::Dry run — npm publish --dry-run (nothing is published)" + npm publish --dry-run --access public + else + npm publish --access public + echo "::notice::Published @yya007/skill-finder@${NEW_VERSION}" + fi + + # Only on a real publish: record the npm version, commit the bump, tag, push. + - name: Stamp release log, commit bump, tag, push + if: env.DRY_RUN != 'true' + run: | + python pipeline/update_release_log.py --npm-version "${NEW_VERSION}" + git config user.name "github-actions[bot]" + git config user.email "github-actions[bot]@users.noreply.github.com" + git add package.json data/release_log.jsonl docs/release-log.md + git commit -m "chore: publish npm v${NEW_VERSION} [skip ci]" + git tag "v${NEW_VERSION}" + git push origin "HEAD:${{ github.event.repository.default_branch }}" + git push origin "v${NEW_VERSION}" diff --git a/docs/prd/PRD-005-ci-cd-release.md b/docs/prd/PRD-005-ci-cd-release.md index 95c33dc..3e6f848 100644 --- a/docs/prd/PRD-005-ci-cd-release.md +++ b/docs/prd/PRD-005-ci-cd-release.md @@ -29,6 +29,15 @@ run since launch was cancelled or failed; a manual run on 2026-06-22 produced on cannot accept incremental adds. Because the production corpus is > 30k, CI is effectively dormant until a local rebuild lowers the count or the index type changes; it exists to avoid weekly false-failures and to self-activate for smaller corpora. +- **npm publish is automated (`npm-publish.yml`).** When a fresh index lands on + `master` (a `data/version.txt` change from a merged local rebuild), this workflow + patch-bumps the package, publishes `@yya007/skill-finder` to npm, tags `v`, + and stamps the release log — all on GitHub runners, no local machine. It bumps from + the *published* npm version (self-healing across runs) and requires the `NPM_TOKEN` + secret (a granular npm token with "Bypass 2FA"). `workflow_dispatch` supports a + `dry_run` (default true) to test without publishing. The index build stays manual + (local); only the npm release step is hands-off. The `npm-release` skill remains for + ad-hoc/manual publishes. The functional requirements below describe the original full-rebuild-in-CI design and are retained for history; F5 (incremental strategy) is what CI now implements.