Skip to content

ci: CI pipeline and changesets-driven release to npm - #13

Merged
AStaroverov merged 6 commits into
mainfrom
ci/release-flow
Jul 27, 2026
Merged

ci: CI pipeline and changesets-driven release to npm#13
AStaroverov merged 6 commits into
mainfrom
ci/release-flow

Conversation

@AStaroverov

@AStaroverov AStaroverov commented Jul 27, 2026

Copy link
Copy Markdown
Owner

Adds the missing GitHub flow: CI on every PR, and an automated release of webactor to npm.

CI — .github/workflows/ci.yml

Four parallel jobs on every PR and push to main:

Job What it runs
check pnpm lint, pnpm format:check, pnpm build (includes tsc --noEmit per package)
unit pnpm test:unit — 130 vitest tests
e2e pnpm test:e2e — 32 Playwright load tests
devtools pnpm test:devtools — 32 Playwright panel/extension tests

test-results/ is uploaded as an artifact when a Playwright job fails. Setup (pnpm → Node from .node-versionpnpm install --frozen-lockfile) is factored into a composite action so it isn't repeated four times.

Release — .github/workflows/release.yml

Driven by changesets:

  1. A PR lands with a .changeset/*.md describing the bump.
  2. On merge to main the workflow opens/updates a chore(release): version packages PR containing the version bump and generated CHANGELOG.md.
  3. Merging that PR runs pnpm release → build → changeset publish → npm + git tag + GitHub Release.

Auth is npm trusted publishing over OIDC — no NPM_TOKEN in the repo, and releases get a provenance attestation automatically.

Two defects the first CI run exposed

Both were real, both reproduce locally once you know how — neither was papered over.

Unit tests silently depended on a previous build. tests/worker/worker.mjs is a Node worker fixture, so it imports ../../dist/index.js rather than the TS source. On a machine that had never built the package the worker never came up and three tests failed on empty message arrays. rm -rf packages/webactor/dist && pnpm test:unit reproduces it. The package's test script now builds first, matching what webactor-devtools already did.

channel-storm raced with machine speed. It aborted its mid-flight opens on a setTimeout(..., 5), assuming the open request reaches the supporter within 5ms; on a 2-core runner a channel open averages 43ms, so every abort landed before the request was sent and supportsLostBeforeHandshake came back 0 instead of 100. Rather than relax the assertion, each mid-flight open now carries a unique marker and the supporter fires that abort the moment the request arrives — strictly before its own supportChannel call, on any machine.

Also in here

  • MIT LICENSE plus license fields — the README claimed MIT-style usage but no license text existed, so npm would have listed the package as unlicensed.
  • webactor-devtools marked private — it is never published; changesets skips it (privatePackages: { version: false }).
  • Manual release / release:beta scripts removed from packages/webactor, so publishing can only happen through CI.
  • prepack / postpack carry the root README and LICENSE into the package at pack time — with files: ["dist"] the tarball would otherwise ship without either.
  • Repository URLs updated from AStaroverov/actorr to AStaroverov/webactor; the repo was renamed and npm's OIDC check validates the real name.
  • .node-version (26.5.0), CI + npm badges, and CONTRIBUTING.md documenting the flow.

Before merging

  • Configure the trusted publisher on npmjs.com — package webactor → Settings → Trusted publisher → GitHub Actions, org AStaroverov, repo webactor, workflow release.yml, environment empty. Without it the publish step fails with a 404.
  • Merging publishes webactor@1.0.0 immediately. npm currently has 0.3.3 as latest, and there are no pending changesets, so the first run on main takes the publish path rather than opening a version PR.

Note for later: changeset publish shells out to pnpm publish, not npm publish. pnpm 10.x handles OIDC fine, but pnpm 11.0.8 has a regression (pnpm/pnpm#11513) — worth checking before bumping packageManager.

Verification

Every command CI runs was run locally on this branch: lint, format:check, build, unit (130 passed, verified from a cold dist/), e2e (32 passed), devtools (32 passed). changeset version was executed for real against a throwaway changeset — it produced a correct bump plus CHANGELOG.md — and reverted. pnpm pack confirmed README and LICENSE land in the tarball and the copies are cleaned up afterwards.

🤖 Generated with Claude Code

AStaroverov and others added 6 commits July 27, 2026 16:44
CI runs lint, format, build, unit, e2e and devtools tests on every PR and
push to main. Release is driven by changesets: a changeset in a PR produces
a "version packages" PR, merging it publishes webactor to npm over OIDC
trusted publishing (no NPM_TOKEN, provenance included).

webactor-devtools is marked private so it is never published, and the manual
release scripts in packages/webactor are replaced by a prepack step that
carries the root README into the published tarball.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
The repo was renamed from actorr to webactor; the changesets changelog
config and the npm package metadata need the real name, and the trusted
publisher must be registered against it or OIDC auth fails.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
The worker fixture imports the built dist, so `vitest run` on a machine that
had never built the package saw a dead worker and three failures; the test
script now builds first, matching what the devtools suite already does.

channel-storm aborted its mid-flight opens on a 5ms timer, assuming the open
request reaches the supporter faster than that. On CI a channel open averages
43ms, so every abort landed before the request was ever sent and nothing was
lost before a handshake. The supporter now fires the abort itself when the
request arrives, which orders the two events on any machine.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
The README claimed MIT-style usage but no license text existed, so npm would
have listed the package as unlicensed. prepack now carries LICENSE into the
tarball alongside the README, since npm only picks up a license file that
sits in the package directory.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
@AStaroverov
AStaroverov merged commit 8255fef into main Jul 27, 2026
4 checks passed
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.

1 participant