ci(root): serve packed packages from a registry instead of file: specs - #839
Conversation
Scaffold blog-visual has been red on main. plugin-form-builder/dist/admin cannot resolve @nextlyhq/plugin-sdk/admin, which reads as a missing export and is a missing install. Two things combine. The pin loop only repoints names the manifest ALREADY declares, so a packed package that is nothing but a peer of another packed package never enters the tree. And the override makes that worse rather than better: pnpm applies overrides to peer RANGES, so the range becomes a file: spec and no resolved semver version can satisfy one. Measured on a minimal fixture. Without a direct dependency pnpm reports missing peer and declines to link it; with one it reports unmet peer, a warning, and links it anyway. That is why only the pnpm leg fails - npm's hoisted layout leaves the package reachable either way. The peer set is derived from the tarballs already being opened for their names, rather than listed, which is the rule this file states about itself. optionalDependencies joins the pin loop as the third place a manifest can name a package; a spec left unpinned there resolves from the registry exactly as an unpinned dependency would.
|
Warning Review limit reached
Next review available in: 55 minutes You've used all free OSS reviews for now. Wait for the free limit to reset to keep reviewing this public repository. How can I continue?After more reviews become available, a review can be triggered using the To avoid repeated limits, reduce automatic review volume by pausing incremental auto-reviews earlier, using label-based review opt-in, excluding WIP or generated PR titles, or requesting reviews manually when the PR is ready. If your team needs uninterrupted high-volume reviews, an organization admin can enable usage-based reviews. How do review limits work?CodeRabbit enforces per-developer PR review limits for each organization. Most developers receive the normal plan review availability. For paid Pro and Pro+ PR reviews, CodeRabbit uses adaptive limits for sustained high-volume activity. When a developer's recent PR review activity reaches the 95th percentile or higher among CodeRabbit users, additional reviews become available more gradually as earlier reviews age out of the rolling window. Please refer docs for additional details. Review details⚙️ Run configurationConfiguration used: Path: .coderabbit.yaml Review profile: CHILL Plan: Pro Plus Run ID: 📒 Files selected for processing (2)
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 03a4f7de10
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
@nextlyhq/adapter-drizzle
@nextlyhq/adapter-mysql
@nextlyhq/adapter-postgres
@nextlyhq/adapter-sqlite
@nextlyhq/admin
@nextlyhq/admin-css
@nextlyhq/blocks-engine
@nextlyhq/blocks-react
@nextlyhq/builder
create-nextly-app
nextly
@nextlyhq/plugin-form-builder
@nextlyhq/plugin-page-builder
@nextlyhq/plugin-sdk
@nextlyhq/plugin-seo
@nextlyhq/storage-s3
@nextlyhq/storage-uploadthing
@nextlyhq/storage-vercel-blob
@nextlyhq/ui
commit: |
nextly declares all three database adapters as optional peers, and a scaffolded app installs exactly the one it was generated for. Adding the other two would not merely bloat the install: it would let an accidental import of an adapter the app never declared COMPILE, so the leg would pass on code a real user's install cannot run - the check weakened by the change meant to repair it. peerDependenciesMeta is read from the same tarball manifest already being opened, so the optional flag is derived rather than assumed. Measured with all three adapter tarballs packed and a manifest declaring only sqlite: sqlite is added, mysql and postgres are not.
|
@codex please review this PR |
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 6822138168
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
A union over all packed tarballs adds a peer because SOME packed package wants it. Reproduced: a blank-like manifest gained @nextlyhq/plugin-sdk purely because plugin-form-builder declares it, and that scaffold installs no plugin. That is the same failure as adding an optional adapter - it lets an accidental import compile in a project whose real install would reject it, so the leg passes on code a user cannot run. The change meant to repair the check weakens it, twice over, in the same derivation. The set is now the reachability closure from the packages the manifest actually declares, followed through required peers only. Transitive, because a peer that gets added brings its own required peers and stopping at one level leaves the second unresolvable for the reason the first was. Paired controls: a blank-like manifest does NOT gain plugin-sdk, a manifest that installs plugin-form-builder DOES, and both keep ui, which admin requires.
|
@codex please review this PR |
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 2106e55003
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
|
My own change has now demonstrated the defect its reviewer predicted, empirically rather than by argument. I recommend closing this unmerged. Latest run ( The failure: Mechanism, measured. On a code-first blog manifest, this change adds exactly one package: So the objection in the open thread is no longer hypothetical. Adding a root dependency to satisfy a peer cannot avoid changing the dependency boundary, and the scaffold legs exist to test that boundary. Four rounds, and rounds 2, 3 and 4 were all the same defect in different clothes:
I measured the cheap alternative before concluding this: What I believe is correct. Stop using Leaving this open for the founder to decide rather than closing it myself. |
|
Correcting my own diagnosis. The mechanism I posted earlier was wrong, and I stated it as measured. I claimed this PR adds
So the story I told — widened graph unlocks the font loader — is not supported. I am withdrawing it. What I actually know:
Leading hypothesis, explicitly NOT yet verified: the assertion greps Next diagnostic, and I will not post another mechanism before running it: reproduce the code-first scaffold locally with and without Two lanes have now relayed my unverified mechanism onward. That is on me: I presented an inference in the same register as a measurement, and it travelled. The measurements above are re-runnable; the earlier story was not. |
The pin rewrote the generated manifest to `file:` specifiers, and pnpm applies that rewrite to peer RANGES as well as to dependency specs. No resolved semver version satisfies a `file:` range, so pnpm reported an unmet peer with a correct copy installed, never linked it, and the build failed on `Can't resolve '@nextlyhq/plugin-sdk/admin'`. npm's hoisted layout hid it. Publishing the tarballs to a registry inside the job and installing them by version removes that: peer ranges stay semver and the manifest is not modified, so the legs still test the dependency boundary the generator writes rather than one CI invented. A new assertion requires the manifest to carry no `file:` spec and no `pnpm.overrides`. Publishing needs both `--registry` and an `@nextlyhq:registry` config entry, and neither is sufficient alone: the flag overrides each package's own `publishConfig.registry`, and the config entry wins for a scoped name where the flag does not. A guard refuses to publish unless both resolve to localhost, because these packages name the real registry in `publishConfig`.
|
Mechanism REPLACED rather than narrowed a fifth time. The pin script is deleted. Why the previous approach could not work
Every repair so far satisfied the peer by ADDING a root dependency, which necessarily widens the app's dependency graph - the exact boundary these legs exist to test. What replaces itThe packed tarballs are published to a registry running inside the job and installed BY VERSION. The generator already writes A new assertion makes the old regression unrepresentable rather than merely absent: the manifest must carry no Measured locally, both legs, before pushing
Under pnpm, Two findings worth carryingPublishing needs BOTH Every package carries WithdrawnI posted a Staying in DRAFT until both blog legs are green at one commit in CI. |
|
@codex please review this PR |
|
Codex Review: Didn't find any major issues. Can't wait for the next one! Reviewed commit: ℹ️ About Codex in GitHubYour team has set up Codex to review pull requests in this repo. Reviews are triggered when you
If Codex has suggestions, it will comment; otherwise it will react with 👍. Codex can also answer questions or update the PR. Try commenting "@codex address that feedback". |
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: d4dbe4e5b9
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
|
CI verification at 24 Both blog legs are green AT ONE COMMIT, which is the bar this PR was held to:
Two notes for whoever updates the claims board:
Still outstanding: no reviewer has looked at this head. Codex last reviewed @codex please review this PR |
|
Codex Review: Didn't find any major issues. Hooray! Reviewed commit: ℹ️ About Codex in GitHubYour team has set up Codex to review pull requests in this repo. Reviews are triggered when you
If Codex has suggestions, it will comment; otherwise it will react with 👍. Codex can also answer questions or update the PR. Try commenting "@codex address that feedback". |
…version alpha Two defects that a green run does not reveal. The registry redirect was written to `$HOME/.npmrc` BEFORE `npx` fetched verdaccio, so that fetch was aimed at a port nothing was listening on. It survived only because the step runs from the repository root, whose own `.npmrc` names npmjs and outranks the user-level file — a working directory away from hanging. Reproduced by moving the redirect ahead of the start locally: verdaccio never came up. Starting it first removes the dependency on config precedence. Every published version now also carries the `alpha` tag. The generator resolves a version by asking npmjs for dist-tags, and a package whose only published artifact is its `0.0.0` name-claiming placeholder has no `alpha` tag to find, so it writes the literal string `alpha` as the spec rather than a range. A registry carrying only `latest` cannot satisfy that, and the leg would fail on an unavailable tag instead of testing the new package.
|
@codex please review this PR |
|
Codex Review: Didn't find any major issues. What shall we delve into next? Reviewed commit: ℹ️ About Codex in GitHubYour team has set up Codex to review pull requests in this repo. Reviews are triggered when you
If Codex has suggestions, it will comment; otherwise it will react with 👍. Codex can also answer questions or update the PR. Try commenting "@codex address that feedback". |
|
Failure: This PR changes exactly two paths: Neither is reachable from the e2e canvas suite. That suite boots the playground and exercises page-builder drag behaviour; a scaffold-build workflow and a deleted CI script cannot participate in it. Unreachability is what exonerates a PR here, not a green re-run — and that argument holds whether or not a second run passes, which is why I am not simply re-running it. The failing assertion is a positive control on press liveness, which belongs to the canvas/page-builder lane's settle-allowance and drag-threshold work (#825, and #854 recovering the settle-guard commit stranded by it). Flagging it there rather than adopting it here. Everything this PR is responsible for is green at |
Scaffold blog-visualis red onmain— the last remaining scaffold failure after #835 cleared the other one.It reads as a missing export. It is a missing install.
Two things combine
The pin loop only repoints names the manifest already declares. A packed package that is nothing but a peer of another packed package is named by neither the manifest nor the loop, so it never enters the tree.
The override makes that worse rather than better. pnpm applies
overridesto peer ranges, not only to dependency specs. The range becomesfile:/tmp/….tgz, and no resolved semver version can satisfy afile:specifier:That line is the proof, and it is the one reasoning cannot produce: the package is present at the exact version and the peer is still unmet. My first diagnosis was that the override failed to reach peers. It is the inverse — reaching them is the defect.
Measured, on a minimal fixture rather than through CI
✕ missing peer✕ unmet peer(warning)And the failing specifier resolves from the exact file that failed:
This also explains why only ONE blog leg failed, which the mechanism alone does not:
blog-code-firstis npm, whose hoisted layout leaves the package reachable regardless of the peer range;blog-visualis pnpm, whose isolated layout declines to link it.The fix
The peer set is derived from the tarballs already being opened for their names, not listed — the rule this file states about itself: "a list in this file would be a second answer to a question the manifests already answer".
optionalDependenciesjoins the pin loop as the third place a manifest can name a package; a spec left unpinned there resolves from the registry exactly as an unpinned dependency would. Flagged by a reviewer of #835, whose own first fix removed a hardcoded list and left a hardcoded expectation one level down.Separating property
A green
blankleg proves nothing here. Only the two blog legs declarecore: workspace, so they are the only ones that mix registry and workspace packages and the only ones that can catch this. Judge this onScaffold blog-visual.No changeset: CI tooling, ships nothing.
A green run that the mechanism did not produce
Worth recording, because it is the reason the second fix here is ORDERING rather than
configuration.
The registry redirect was originally written to
$HOME/.npmrcbeforenpxfetchedverdaccio, so that fetch was aimed at a port nothing was listening on. Every run was green
anyway. The reason is that this step runs from the repository root, whose own
.npmrcnamesnpmjs and project config outranks user config, while every other command in the step runs
cd /tmpand correctly resolved localhost. The ordering was wrong and the result was green,because something other than the mechanism under test was supplying the answer.
It was found by accident: while verifying the unrelated dist-tag fix locally, the redirected
HOMEwas exported before starting verdaccio - the same ordering, without a repository.npmrcto rescue it - and verdaccio never came up. With the start moved first it came up in 4 seconds.
AGENTS.mdstates the general form of this ("ask what ELSE would produce the same green"). Thefix is to start the registry first, so the fetch cannot depend on config precedence at all,
rather than to add configuration that makes the existing order work.