Ship v3.2.1 with hardened release pipeline#35
Merged
chenliuyun merged 27 commits intomainfrom Apr 26, 2026
Merged
Conversation
…exhaustive coverage guard tests
…ace inline catalog with pointer note
…ate, status-sync, upgrade-check coverage
…tus-sync start/run, test count - Add afterEach vi.useRealTimers() to daemon stop/reload describe blocks to prevent fake timer leak - Fix bundle-size test to skip size assertion when tsc output is present (detects esbuild bundle by absence of relative imports) - Add status-sync start (--json + human) and run (exit 0 and exit 1) test coverage - Update README test count to 1959
…log-unify feat: P0 fixes, policy schema, agent-bootstrap --sections, esbuild bundler, capabilities/catalog unification, and comprehensive test coverage (1959 tests)
…js banner both added it
…d output
- Remove shebang from src/index.ts; bundle.mjs banner is the sole source
- Add createRequire-based require shim in banner so bundled CJS packages
(yaml, commander) can call bare require('process') on Node 20/22
- Add scripts/cjs-shim.mjs as esbuild inject target for require polyfill
- Fix agent-bootstrap and upgrade-check to import version from src/version.ts
instead of require('../../package.json') which breaks when bundled to
a non-root dist/ location
- Rewrite bundle-size test: build to dist/bundle-test.js (same level as
dist/index.js so ../package.json resolves correctly), add shebang-count,
node --check, --version semver, and size < 15 MB assertions
…elease pipeline Add a parallel pack-install-smoke-tsc CI job that runs `npm run build` (tsc) + smoke:pack-install, mirroring exactly what publish.yml does before npm publish. Previously only the esbuild bundle was smoke-tested on PRs while publish shipped the tsc output, so a tsc-specific packaging regression would only surface after the release tag was already pushed. Add docs/release-pipeline.md with the tsc vs esbuild split, the full gate sequence, and the invariants that must hold for future pipeline changes. Link it from README and the CHANGELOG 3.2.1 entry.
…sh source publish.yml was running `npm run build` (tsc) + smoke:pack-install, but `npm publish` triggers prepublishOnly, which does `clean && build:prod` unconditionally. So the tarball that smoke validated was thrown away and replaced with the esbuild bundle right before upload — smoke was verifying a different artifact than what shipped. Fix by making esbuild the single publish source: - publish.yml step 2: `npm run build` -> `npm run build:prod`, so the artifact validated by smoke:pack-install is byte-identical to what prepublishOnly produces and what npm publish uploads. - ci.yml: remove the `pack-install-smoke-tsc` job added in the previous commit — it was validating the tsc output that never ships. - docs/release-pipeline.md: rewrite to reflect the single-publish-source model; add explicit invariant that publish.yml and prepublishOnly must use the same builder. - CHANGELOG: update the 3.2.1 release-pipeline entry.
Collaborator
Author
Follow-up: align publish.yml with prepublishOnly (
|
Now that the esbuild bundle is the single publish source, bundle-smoke must catch bundle regressions on every supported Node version before a PR can merge. Previously it was advisory (continue-on-error: true) and single-node (20.x). Changes: - Remove continue-on-error. The stale "Node 22 CJS interop issues" comment dates from before 7bbbc44 fixed the CJS require shim; the bundle now runs cleanly on Node 18/20/22 (verified locally on 22.21). - Add strategy.matrix.node-version = [18.x, 20.x, 22.x] with fail-fast: false, so any Node version that cannot run the bundle is surfaced independently. - Update docs/release-pipeline.md: remove the "Known gaps" section, add invariant #5 making the matrix + blocking status explicit. - CHANGELOG entry added.
3 tasks
added 3 commits
April 26, 2026 09:40
On some Linux CI runners, vi.spyOn(process, 'kill') failed to reliably intercept process.kill(pid, 0), so isProcessRunning hit the real kill syscall against a PID that happened to exist in the container, got back EPERM, and reported the stale process as still running. Replace the spy with a direct property assignment and restore the original kill in afterAll so the interception is deterministic across Node 18/20/22.
…pipeline npm run build is now the only path that produces the published artifact. It drives a 5-stage orchestrator in scripts/build.mjs: 1. clean remove dist/ 2. typecheck tsc --noEmit 3. bundle scripts/bundle.mjs (esbuild) 4. copy-assets scripts/copy-assets.mjs (policy assets only) 5. ensure-binary scripts/ensure-binary.mjs (shebang + chmod 0755 guard) prepublishOnly, verify:pre-commit, verify:pre-push, publish.yml, and the bundle-smoke / pack-install-smoke CI jobs all call npm run build by name; no job re-implements any step. scripts/copy-assets.mjs no longer injects the shebang or chmods the entry. The new scripts/ensure-binary.mjs is a regression guard: it asserts the shebang is present and fails loudly (pointing at scripts/bundle.mjs) if the esbuild banner ever drops it, rather than silently repairing the output the way copy-assets used to. Dropped scripts: build:prod, clean (folded into build.mjs). Added script: typecheck (tsc --noEmit).
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
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Re-lands the full v3.2.1 work (previously rolled back from
mainafter a post-release regression) together with a hardened release pipeline so this class of breakage can't reach the npm registry again.P0 / P1 fixes included
capabilitiesregression (P0) — exportCOMMAND_META, add missingrules explainentry, add exhaustive coverage guard tests (88667cc)a947cfc)746f2ac)agent-bootstrap --sections(P1) — project top-level payload keys (55a4875)dist/index.js(76d4384)schema export --capabilities— replace the inline catalog incapabilitieswith a pointer note (68b8fe8)Release pipeline hardening (
b92948a,12dae35)The v3.2.0 / v3.2.1 failures both shipped because the broken artifact was only exercised after
npm publish. This PR moves all critical smoke checks BEFORE publish and adds defense-in-depth after:Pre-publish gates (new/extended):
scripts/copy-assets.mjs— force-injects#!/usr/bin/env nodeintodist/index.jsand chmods0o755on every buildtests/version.test.ts— asserts shebang presence as a regression guardscripts/smoke-pack-install.mjs—npm pack→ install into throwaway project → executenode_modules/.bin/switchbot --versionpre-commithook (verify:pre-commit: build:prod + version test) andpre-pushhook (verify:pre-push: + smoke:pack-install), wired viacore.hooksPath = .githooksonnpm installpack-install-smoke(esbuild) — runs the same smoke on every PRpack-install-smoke-tsc(tsc, matchespublish.yml) — closes the gap where the PR gate validated esbuild while publish shipped tscpublish.ymlstep 5 now runssmoke:pack-installBEFOREnpm publish --tag next; if it fails, nothing reaches the registryPost-publish defense-in-depth:
npm-published-smoke.ymlworkflow: waits for@nextto appear, installs in a clean temp project, runs offline smoke (--version,--help,schema export,capabilities) + live smoke (doctor,devices listwith real credentials)@next → @latestinstall_packageoroffline_smokefails — never onlive_smokefailures, since transient SwitchBot API outages must not deprecate a working packageDocumentation:
docs/release-pipeline.mdexplains the tsc vs esbuild split, the full gate sequence, and four invariants that future pipeline changes must preserve (linked from README)Test plan
npm run verify:pre-commitgreen locally (build:prod + version test, 2/2 passed, shebang + parity)npm run verify:pre-pushgreen locally (adds smoke:pack-install —switchbot --version -> 3.2.1from packed tarball)npm run lint:md:changeloggreenbundle-smoke— advisory (Node 22 CJS interop tracking issue still open)offline-smoke(size budgets) greenpack-install-smoke(esbuild) greenpack-install-smoke-tsc(tsc, matches publish) greenpolicy-schema-syncgreen or SKIPAfter merge: cut release v3.2.1 →
publish.ymlruns →npm-published-smoke.ymlauto-promotesnext → latest.