Skip to content

ci: publish-artifact smoke — install the release candidate like a user would - #3100

Merged
os-zhuang merged 1 commit into
mainfrom
claude/intelligent-moore-584e50
Jul 17, 2026
Merged

ci: publish-artifact smoke — install the release candidate like a user would#3100
os-zhuang merged 1 commit into
mainfrom
claude/intelligent-moore-584e50

Conversation

@os-zhuang

Copy link
Copy Markdown
Contributor

Problem — the 15.1.0 blind spot (#3091)

Workspace pnpm-workspace.yaml overrides kept every in-repo CI job on better-auth 1.7.0-rc.1, but overrides don't ship with published packages — every fresh npx create-objectstack project resolved plugin-auth's own declared ranges to an untested mix that 500'd all auth endpoints. Nothing in CI ever installed the combination users actually get.

#3085 added the static gate (check-override-consistency.mjs: override targets must be reflected in published manifests). This PR adds the dynamic gate: really install the about-to-publish artifacts into a clean project and drive the first-run flow.

What's in the box

scripts/publish-smoke.sh — one driver, two modes, same probe set (locally reproducible: pnpm build && bash scripts/publish-smoke.sh):

  • pack (default): pnpm pack all 67 publishable packages (pack applies the same manifest rewrites as publish, incl. workspace:* → concrete versions), scaffold a fresh project outside the workspace with the repo-built create-objectstack, and pin every @objectstack/* to the tarballs via the project's ownpnpm-workspace.yaml overrides — the project inherits nothing from the repo's workspace file, so better-auth & friends resolve exactly as they would for a downstream user. A lockfile assertion fails the run if any @objectstack/* leaked to the registry (i.e. the override map ever grows a hole).
  • registry: npx create-objectstack@latest + npm install against the real registry — catches ^-range ecosystem drift breaking already-published versions after the fact.

Probes (both modes): anonymous get-session 200 → sign-up/email 200 → sign-in/email 200 → session carries the user → REST CRUD round on the scaffolded object (POST/GET/PATCH/DELETE/api/v1/data/<obj>, 201/200/200/200) as the --fresh-seeded dev admin → zero error/fatal log lines (ANSI-stripped; three logger formats covered, incl. the #3091 signature Failed to register OIDC discovery routes).

.github/workflows/publish-smoke.yml

  • pack-smoke runs on workflow_run after each Release run. Why not on: pull_request/push: the changesets release PR is pushed with GITHUB_TOKEN, and GITHUB_TOKEN events never trigger other workflows — the release PR literally has no Actions checks today (see chore: version packages #3086: only Vercel). So the smoke fires when Release completes (the moment changesets refreshes the branch), checks out the release-branch head SHA iff an open release PR exists, and reports the verdict back as a commit status on that SHA — visible on the release PR like any check. Skips cleanly when no release PR is open. Deliberately not on normal PR CI: full build + pack + clean install is inner-loop-hostile (~25–35 min).
  • registry-canary weekly (Mon 04:47 UTC) + on dispatch; on scheduled failure it opens (or refreshes, deduped) an issue.
  • workflow_dispatch runs both modes on any ref for manual verification.

Verification

scenarioresult
pack mode, current tree✅ green — all 12 probes, 0 error lines, 108 tarball-resolved lockfile entries, 0 registry leaks
pack mode, negative: plugin-auth declarations reverted to the exact 15.1.0 mix (^1.6.23 + scim 1.7.0-rc.1)✅ red — clean project resolves core@1.6.23 + scim@1.7.0-rc.1, OIDC provider init throws the incident's modelName TypeError, log scan fails the run. (Core sign-in stays 200 thanks to the #3087 isolation — the gate still catches the broken init via the error-line scan. Pre-#3087 this would also have red-failed the sign-up/sign-in probes directly.)
registry mode against published 15.1.1✅ green

The negative run also flushed out two real gate-hardening fixes during development: a 403 INVALID_ORIGIN on 127.0.0.1 (probes now use localhost, matching the default trustedOrigins wildcard) and a colorizedERROR line slipping past the scan (now NO_COLOR=1 + ANSI-strip before grep).

Notes

  • better-sqlite3 stays an optionalDependency of driver-sql: if the runner can't build the native addon, install still succeeds and the runtime falls back to WASM sqlite (better-sqlite3 → wasm auto-fallback doesn't cover the persistent-file / --artifact dev path (only the zero-config :memory: branch) #2229) — the smoke never blocks on node-gyp.
  • workflow_run only fires for workflow files on the default branch, so the release-PR path can't be exercised from this PR; after merge it can be validated via workflow_dispatch and the next real release PR.
  • Relationship to scaffold-e2e.yml: that gate exercises the scaffolder against the registry and only probes /health; this one exercises the unpublished release candidate and probes the auth + CRUD surface where 15.1.0 actually broke.

Refs: #3091 · #3085 · #3087

🤖 Generated with Claude Code

…r would
The 15.1.0 incident (#3091): workspace pnpm overrides kept every in-repo CI
job on better-auth 1.7.0-rc.1, but overrides do not ship with published
packages, so every fresh `npx create-objectstack` project resolved an
untested dependency mix that 500'd all auth endpoints. #3085 added the static
gate (override ↔ declaration consistency); this adds the dynamic gate —
install the exact bits a user would get and drive the first-run flow.
scripts/publish-smoke.sh, two modes sharing one probe set:
- pack (default): pnpm-pack all 67 publishable packages (pack applies the
same manifest rewrites as publish), scaffold a fresh project outside the
workspace with the repo-built create-objectstack, pin @objectstack/* to
the tarballs via the project's OWN pnpm-workspace.yaml overrides (nothing
inherited from the repo), install, and smoke. A lockfile assertion proves
no @objectstack/* leaked to the registry.
- registry: npx create-objectstack@latest + npm install against the real
registry — catches ^-range ecosystem drift breaking published versions.
Probes: anonymous get-session 200 → sign-up 200 → sign-in 200 → session
carries the user → REST CRUD round (201/200/200/200) on the scaffolded
object as the seeded dev admin → zero error/fatal log lines (ANSI-stripped;
catches the #3091 'Failed to register OIDC discovery routes' signature).
.github/workflows/publish-smoke.yml:
- workflow_run after each Release run — the changesets release PR is pushed
with GITHUB_TOKEN, whose events never trigger on:push/pull_request (the
release PR has no Actions checks today), so the smoke runs after Release
completes, checks out the release-branch head SHA iff an open release PR
exists, and reports the verdict back as a commit status on that SHA so it
is visible on the release PR. Deliberately not in normal PR CI (too slow).
- weekly registry canary (Mon 04:47 UTC) that opens/refreshes an issue on
failure.
Verified locally: pack mode green on the current tree; a negative run with
plugin-auth's declarations reverted to the 15.1.0 mix (^1.6.23 + scim rc.1)
goes red via the log scan — core sign-in stays up thanks to the #3087
isolation, and the smoke still catches the broken optional-plugin init.
Registry mode green against published 15.1.1. better-sqlite3 stays an
optionalDependency, so a failed native build falls back to WASM sqlite
(#2229) instead of blocking the smoke.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
@os-zhuangos-zhuang added the skip-changeset PR has no user-facing published change; bypasses the changeset gate label Jul 17, 2026
@vercel

vercelBot commented Jul 17, 2026

Copy link
Copy Markdown

The latest updates on your projects. Learn more about Vercel for GitHub.

ProjectDeploymentActionsUpdated (UTC)
specReadyReadyPreview, CommentJul 17, 2026 7:38am

Request Review

@os-zhuang
os-zhuang merged commit 89467f5 into mainJul 17, 2026
18 checks passed
@os-zhuang
os-zhuang deleted the claude/intelligent-moore-584e50 branch July 17, 2026 07:39
os-zhuang added a commit that referenced this pull request Jul 17, 2026
…all works on pnpm 11 (#3119)
`npx create-objectstack && pnpm install` exited 1 on pnpm 11 (ERR_PNPM_IGNORED_BUILDS:
better-sqlite3, esbuild). pnpm 11 turned an unapproved dependency build script from a
warning into a hard error, and the blank template declared no approvals — verified against
published 15.1.1, so the first command a new user ran failed.
The scaffold now ships a pnpm-workspace.yaml approving the two packages it depends on
building. Both keys are required: pnpm 11 honors only `allowBuilds` (understood back to
10.31), while pnpm 10.0–10.30 understand only `onlyBuiltDependencies`. npm and yarn ignore
the file.
This is why Publish Smoke had been red since #3100 introduced it. The gate was never
broken — it correctly reported a real, shipping product bug on its first run. Pinning the
smoke's pnpm to the repo's packageManager would have turned it green by testing a pnpm no
user runs: the same "in-repo settings hide the user's real resolution" mistake as #3091,
the exact failure class this gate exists to catch. The pnpm version stays unpinned and the
reasoning is recorded in the script header.
publish-smoke.sh now appends its tarball overrides to the file the template ships instead
of hand-writing the whole thing. It previously declared the approvals itself, so it proved
nothing about what users get — that is how this bug stayed invisible to a gate designed to
find it. It now fails loudly if the scaffold declares no approvals.
Verified: Publish Smoke dispatched on the fix branch went green (all 3 jobs) — the first
pass in its history. Locally reproduced under CI-identical resolution via a corepack shim
(10.31.0 in-repo, 11.13.1 in the app dir); stripping allowBuilds reproduces the exact CI
failure and restoring it passes.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Sign up for freeto join this conversation on GitHub. Already have an account? Sign in to comment

Labels

ci/cdsize/lskip-changesetPR has no user-facing published change; bypasses the changeset gate

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant

@os-zhuang