Skip to content

chore(release): wire release-please + tag-triggered npm publish (Track 3)#19

Merged
IgorShevchik merged 2 commits into
mainfrom
chore/release-flow
May 26, 2026
Merged

chore(release): wire release-please + tag-triggered npm publish (Track 3)#19
IgorShevchik merged 2 commits into
mainfrom
chore/release-flow

Conversation

@IgorShevchik

Copy link
Copy Markdown
Collaborator

Track 3 — release flow. Last gate before tagging v0.1. No src/ changes.

After this lands, the release-please workflow opens a release PR on the next push to main. Merging that release PR creates the v0.1.0 tag and a GitHub Release, which triggers npm-publish.yml. No more workflow_dispatch releases needed for the happy path.

The flow

push to main
   │
   ▼
release-please.yml ──▶  maintains a "release-please" PR
                              with bumped package.json + CHANGELOG additions
                              (computed from Conventional Commits since last tag)
                              │
                              ▼ (manual review + squash-merge)
                       creates tag vX.Y.Z + GitHub Release
                              │
                              ▼ (release: types: [published])
                       npm-publish.yml ──▶  re-runs every gate + publishes
                                            with --provenance

What's added

release-please plumbing

  • .github/release-please-config.jsonrelease-type: node, include-v-in-tag: true, bump-minor-pre-major: true (so a feat: bumps 0.x.y to 0.(x+1).0 while we're still pre-1.0). Explicit changelog-sections mapping Conventional Commit types to the existing CHANGELOG.md headers (feat → Added, fix → Bug Fixes, refactor/perf → Changed, docs → Documentation; chore/test/ci/build hidden).
  • .release-please-manifest.json — pins current 0.0.4.
  • .github/workflows/release-please.yml — runs on push: branches: [main] + workflow_dispatch. Uses googleapis/release-please-action@v4. Permissions: contents:write, pull-requests:write. Concurrency group + 5-minute timeout.

npm-publish.yml changes

  • Trigger: workflow_dispatch-only → release: types: [published] + workflow_dispatch (kept as manual fallback).
  • New tag-vs-package.json sanity check — fails publish if the git tag and package.json version disagree (only on release-triggered runs; workflow_dispatch skips).
  • New docs:build step — mirrors the PR-time gate from ci.yml; a release path must not ship JSDoc with broken {@link}.
  • pnpm/action-setup@v4 pinned to version: 10 (matches packageManager in package.json).
  • timeout-minutes: 10 + concurrency group npm-publish.
  • --provenance was already wired in PR chore: refresh toolchain, trim deps, apply multi-angle review #4 — unchanged.

Documentation

  • CONTRIBUTING.md — new "Release flow" section explaining the four-step automated path and a "One-time maintainer setup" checklist (admin-only, can't be done in this PR):
    1. NPM_AUTH_TOKEN secret with npm Publish scope.
    2. Branch protection on main — list of all 7 required CI checks (Lint, Typecheck, Unit tests node 20, Unit tests node 22, Build, Commit messages, Docs).
    3. Workflow permissions = Read and write + Allow GitHub Actions to create and approve pull requests (so release-please can manage its release PR).
  • PROJECT-BRIEF.md — Track 3 "Gated release flow" ticked; branch-protection item annotated as documented-but-pending-admin. Critical-path summary updated.
  • CHANGELOG.md — Unreleased / Added entry.

Acceptance (from PROJECT-BRIEF.md Track 3)

  • Gated release flow. A wrong-tag publish attempt fails CI (tag-vs-package.json check). CHANGELOG.md is generated by release-please, not hand-edited going forward.
  • Branch protection on main — admin-only setting; documented in CONTRIBUTING.md but cannot be applied via this PR.

Behavioural change

  • For maintainers: no more manual workflow_dispatch to ship a release. Merge the release-please PR; everything else is automatic.
  • For consumers (npm users): nothing changes. Same package, same --provenance-signed tarball.

Gates

Gate Result
pnpm lint green
pnpm typecheck green
pnpm test 66/66
pnpm test:coverage 100/100/100/100
pnpm build green (17 kB ESM, unchanged)
pnpm docs:build green

Downstream consumer check

bitrix24/app-template-automation-rules — unaffected; no public API change.

What's next

After this PR merges:

  1. The release-please workflow runs on main and opens a release PR (probably 0.1.0 — there's been at least one feat: since 0.0.4).
  2. Review that release PR, merge it. The tag v0.1.0 + GitHub Release are created automatically.
  3. npm-publish.yml ships 0.1.0 to npm with provenance.

That's v0.1.


Generated by Claude Code

claude added 2 commits May 26, 2026 15:58
…k 3)

Last v0.1 gate. After this lands, the release-please PR that opens
on next push to main contains the v0.1 version bump (computed from
the Conventional Commits since 0.0.4 — at least one feat (logger
DI, PR #15) so it should propose 0.1.0).

Added:
- .github/release-please-config.json: release-type node,
  include-v-in-tag, bump-minor-pre-major (so feat triggers a minor
  bump while we're still 0.x), explicit changelog-sections mapping
  Conventional Commit types to the existing CHANGELOG.md headers
  (Added / Bug Fixes / Changed / Documentation / hidden chores).
- .release-please-manifest.json: pins current version 0.0.4.
- .github/workflows/release-please.yml: runs on push to main +
  workflow_dispatch. Maintains the release PR via
  googleapis/release-please-action@v4. permissions: contents:write,
  pull-requests:write. Single-job, 5min timeout.

Changed:
- .github/workflows/npm-publish.yml: trigger switched from
  workflow_dispatch-only to release: types: [published]. workflow_
  dispatch retained as a manual fallback. New sanity check verifies
  the git tag (vX.Y.Z) matches package.json version — fails publish
  if they disagree (only runs on release-triggered runs;
  workflow_dispatch skips). pnpm/action-setup pinned to version 10
  to match packageManager. Job gains timeout-minutes: 10 and a
  docs:build step (mirrors PR-time CI gate). --provenance unchanged.

Documentation:
- CONTRIBUTING.md gains a "Release flow" section explaining the
  four-step automated flow and a "One-time maintainer setup"
  checklist: NPM_AUTH_TOKEN secret, branch protection on main with
  the seven required CI checks, workflow read+write permissions
  (so release-please can push to its release PR).
- PROJECT-BRIEF.md Track 3 entries: Gated release flow flipped to
  [x] with PR ref; branch-protection item kept [ ] but annotated
  as documented-but-pending-admin. Critical-path summary updated:
  Track 3 done, next step is merging the release-please PR that
  opens after this lands -> tag v0.1.
- CHANGELOG.md Unreleased / Added entry.

Gates: lint, typecheck, test (66/66), coverage 100/100/100/100,
build, docs:build all green. No src/ changes. Public exports
unchanged. Bundle 17 kB ESM (unchanged).
…rst-run/PAT docs

Five parallel review angles (docs / senior-dev / QA / security /
CTO) — one Approve clean, four Approve-with-nits, zero blockers.
In-scope nits folded; one Docs nit refuted.

Refuted:
- Docs reviewer claimed `npm-publish.yml` runs `pnpm test` (not
  `test:coverage`) on line ~62. The file actually runs `pnpm
  test:coverage` on line 66 — verified via grep, and QA reviewer
  independently confirmed the same. CONTRIBUTING.md already says
  `test:coverage`. No change.

Senior-dev + CTO (the meaningful pair):
- CONTRIBUTING.md gains a "CHANGELOG reconciliation on the first
  auto-release" section. The hand-written `## Unreleased` block
  listing PRs #10-#19 is rich; release-please will insert
  `## [0.1.0]` above it with shorter auto-generated entries. The
  doc tells the maintainer to keep release-please's heading + date
  but replace its body with the hand-written content, then delete
  the empty `## Unreleased`. One-shot reconciliation; subsequent
  releases are clean.
- CONTRIBUTING.md "Known limitations of the default GITHUB_TOKEN
  for release-please" — explains that PRs opened by GITHUB_TOKEN
  don't auto-trigger downstream workflows (GitHub loop-prevention),
  so the release-please PR will sit pending the required CI checks.
  Three unblock options documented: empty commit, close+reopen, or
  wire a PAT/GitHub-App token. Defense-in-depth note that
  npm-publish.yml re-runs every gate before shipping.

QA:
- npm-publish.yml tag-check gap closed. Previously gated on
  `if: github.event_name == 'release'`; workflow_dispatch skipped
  the check entirely. Now ALWAYS runs:
  - On release event: derive tag from GITHUB_REF
    (`refs/tags/vX.Y.Z` -> `X.Y.Z`).
  - On workflow_dispatch: derive tag from `git describe --tags
    --exact-match HEAD` — fails loudly if HEAD is not on a tag,
    so a manual dispatch can't ship an unidentified build.
  - Either way, fail with `::error::` annotation if the derived
    tag != package.json version.
- Checkout step gains `fetch-depth: 0` so `git describe --tags`
  on the dispatch path can see tag history.
- Senior-dev tag-prefix hardening folded into the same change —
  two-step strip (`refs/tags/` then `v`) handles tags pushed
  without `v` prefix.
- CONTRIBUTING.md "One-time maintainer setup" failure modes now
  list the exact error string a missing step produces, so a future
  maintainer can grep for it: `ENEEDAUTH`, the workflow-permissions
  error, and the no-error-surface case for missing branch
  protection.
- CONTRIBUTING.md gains "First-run recovery — release-please
  bootstrap" section: how to close the first PR and add
  `bootstrap-sha` if the auto-generated CHANGELOG is busier than
  expected. Note that npm-publish is gated on release-published,
  so there's no risk of accidental publish during recovery.

Skipped (out of scope for this PR):
- Security suggestion to SHA-pin all third-party actions —
  org-wide policy, deferred (matches ci.yml convention currently).
- Security suggestion to add an environment-protected publish
  with required reviewers — admin-only setup; workflow_dispatch
  with the new always-on tag-check is now safer.
- CTO follow-ups (examples/package.json, dlq-drain PII log, README
  integrator update) — separate PRs after v0.1 tag.

Gates: lint, typecheck, test (66/66), coverage 100/100/100/100,
build, docs:build all green. Tag-check shell logic dry-tested
locally for both match and mismatch.
@IgorShevchik IgorShevchik merged commit 6a2e9f6 into main May 26, 2026
7 checks passed
IgorShevchik added a commit that referenced this pull request May 28, 2026
Per repo owner's request: switch npm publish auth from a static
NPM_AUTH_TOKEN secret to OIDC trusted publishing (npm 11.5.1+).
No long-lived secret stored in this repo; the workflow's
id-token: write permission lets the npm CLI exchange a short-
lived GitHub OIDC token for a one-shot publish credential.

Changes to .github/workflows/npm-publish.yml:
- New "Upgrade npm CLI for OIDC trusted publishing" step: runs
  `npm install -g 'npm@^11.5.1'` (pinned floor — not @latest —
  so a hypothetical npm 12 major can't roll in unnoticed with
  id-token: write in scope). `npm --version` after install as a
  one-line postmortem aid. pnpm 10 stays in charge of install +
  lint + typecheck + test + build; only the final publish step
  switches to npm for first-class OIDC integration.
- Publish step: `pnpm publish --access public --provenance
  --no-git-checks` -> `npm publish --access public --provenance
  --ignore-scripts`.
  - --ignore-scripts: explicit Build step already produced
    dist/; skip the prepack hook (which would re-invoke
    `pnpm run build`).
  - --no-git-checks was pnpm-specific; npm has no equivalent.
- Removed `env: NODE_AUTH_TOKEN: ${{ secrets.NPM_AUTH_TOKEN }}`.
  No token needed under OIDC.

Why OIDC > static token:
- No secret to rotate / leak / accidentally commit.
- Short-lived credentials (minutes, not forever).
- npm checks the OIDC claim chain (repo + workflow + ref) on
  every publish — stolen credentials from one run can't be
  reused elsewhere.
- --provenance attestation (already wired in PR #4) is signed
  by the same OIDC chain — provenance and publish identity now
  share one cryptographic anchor.

CONTRIBUTING.md "One-time maintainer setup" step #1 rewritten
as a sub-bulleted list under OIDC trusted publisher binding:
the npmjs.com Trusted Publishers URL, the three fields to set
(Repository: bitrix24/b24rabbitmq, Workflow filename:
npm-publish.yml, Environment: empty), the failure-mode 401
error string, and an explicit "after the first successful
OIDC publish, delete any stale NPM_AUTH_TOKEN secret" bullet
so a future workflow edit can't fall back to the long-lived
token.

CHANGELOG.md Unreleased entry for the release-flow work
amended in-place to reflect the OIDC switch (PR #19 hadn't
shipped a release yet, so the pre-release amendment is safe).

Reviewed by 3 parallel agents (security / senior-dev /
docs+CTO): three Approve-with-nits, zero blockers. The
unanimous nit — pinning npm to ^11.5.1 instead of @latest —
was folded along with the CONTRIBUTING sub-bullet restructure
and the explicit delete-stale-secret instruction.

Gates: lint, typecheck, test (66/66), coverage 100/100/100/100,
build, docs:build all green. No src/ changes. Public exports
unchanged. Bundle 17 kB ESM (unchanged).

Operationally next: owner configures the OIDC trusted-
publisher binding on npmjs.com, then merges the release-please
PR (which will open on the next push to main) to cut v0.1.0.
@IgorShevchik IgorShevchik deleted the chore/release-flow branch May 29, 2026 04:24
IgorShevchik pushed a commit that referenced this pull request May 29, 2026
Manual reconciliation between release-please's auto-generated
[0.1.0] block (short subject lines from commits, plus 4 stale
uuidv7/type-msg leftovers from pre-0.0.4 history) and the
hand-written Unreleased block we maintained through PRs #10-#21
(rich per-entry descriptions with behavioural-change callouts).

This is the one-shot reconciliation flagged in CONTRIBUTING.md
"Release flow -> CHANGELOG reconciliation on the first auto-
release" — subsequent releases will land cleanly because the
hand-written approach ends with v0.1.

Kept from release-please:
- [0.1.0] heading with compare link and 2026-05-28 date.

Replaced with hand-written content:
- Added (3): release-please+OIDC #19/#21, TypeDoc #18,
  Logger DI #15.
- Changed (3): types any->unknown #16, consumer reconnect #14,
  producer prefetch #13.
- Removed (1): RabbitRPC dropped #12.
- Bug Fixes (2): ack/nack idempotency #17,
  base/registerQueue merge #10.

Dropped:
- 4 stale `fix(uuidv7): improve` entries from pre-0.0.4 history
  (already covered in [0.0.3] / [0.0.2] sections below).
- 1 stale `fix(type/Message): improve` (already in [0.0.4]).
- 7 noise `docs: improve` / `docs(en): fix nav` entries from
  pre-reanimation that release-please surfaced without
  bootstrap-sha.

Also captures PR #16 (chore(types)) + PR #19 / #21 (chore(release))
which release-please hides under the chore: hidden setting.
The hand-written entries describe what actually shipped.

Gates: lint, typecheck, test (66/66), build, docs:build all green.

Note: this commit is pushed to the release-please branch (not
main) — it amends release-please PR #20 in-place. The push from
a non-GITHUB_TOKEN identity also triggers PR-time CI, which the
original release-please-bot push could not because of GitHub's
loop-prevention rule.
IgorShevchik pushed a commit that referenced this pull request May 29, 2026
First trustworthy release of @bitrix24/b24rabbitmq after the
full reanimation cycle. All three roadmap tracks closed:

- Track 1 (Correctness): every Phase 1 defect fixed test-first
  with characterisation locks (PRs #10, #12, #13, #14, #15,
  #16, #17).
- Track 2 (Onboarding & positioning): runnable examples,
  README integrator section, TypeDoc API reference + PR-time
  JSDoc gate (PRs #5, #18).
- Track 3 (Process & infrastructure): release-please-driven
  release flow, tag-triggered npm publish with OIDC trusted
  publishing + provenance, ci aggregator job for branch
  protection (PRs #19, #21, #22).

See the reconciled `[0.1.0]` block in CHANGELOG.md for the
rich per-PR descriptions and behavioural-change callouts.

Merging this PR creates the v0.1.0 git tag + GitHub Release,
which triggers .github/workflows/npm-publish.yml to publish
@bitrix24/b24rabbitmq@0.1.0 to npm via OIDC trusted
publishing with --provenance attestation.

Gates: lint, typecheck, unit tests (node 20 + 22), build,
docs:build, commit messages, ci aggregator — all green on
PR #20.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants