Skip to content

test: port hook tests from pnpm install/hooks.ts#419

Merged
jdx merged 2 commits intomainfrom
claude/pnpm-import-hooks
Apr 30, 2026
Merged

test: port hook tests from pnpm install/hooks.ts#419
jdx merged 2 commits intomainfrom
claude/pnpm-import-hooks

Conversation

@jdx
Copy link
Copy Markdown
Contributor

@jdx jdx commented Apr 30, 2026

Summary

Ports 5 active hook tests + 2 skipped divergences from pnpm/test/install/hooks.ts into the new test/pnpm_install_hooks.bats, following the pattern established by #416 (tracked in test/PNPM_TEST_IMPORT.md).

Active tests (all passing):

  • async readPackage mutates a transitive's deps — pnpm hooks.ts:43
  • async afterAllResolved runs and is awaited — hooks.ts:498
  • syntax error in .pnpmfile.cjs fails the install — hooks.ts:292
  • require() of a missing module fails the install — hooks.ts:303
  • readPackage setting optional/peer/dev fields on a transitive — hooks.ts:528

Skipped — surfaced aube divergences (worth filing as Discussions before un-skipping):

  • readPackage returning undefined should fail the install (hooks.ts:68); aube continues with the original manifest
  • readPackage mutating the root project's .dependencies should install those deps (hooks.ts:551); aube does not run the hook on the root manifest

The remaining 15 tests in hooks.ts depend on @pnpm.e2e/* fixtures (Phase 0) or addDistTag helper (Phase 2) and are tracked in the TODO doc.

Test plan

  • mise run test:bats test/pnpm_install_hooks.bats — 5 ok, 2 skip, 0 fail.

🤖 Generated with Claude Code


Note

Low Risk
Low risk: changes are limited to test suite additions and a tracking doc update, with no production code impact. Main risk is potential test flakiness due to lockfile/path assertions and pnpmfile error-message matching.

Overview
Ports a first batch of pnpm/test/install/hooks.ts coverage into aube’s bats suite by adding test/pnpm_install_hooks.bats.

The new tests exercise .pnpmfile.cjs hook behavior (async readPackage mutation of transitives, async afterAllResolved being awaited) and failure paths when the pnpmfile has a syntax error or require()s a missing module; two additional cases are added but marked skip to document current aube divergences.

Updates test/PNPM_TEST_IMPORT.md to track the hooks port progress, list completed/skipped cases, and note divergences/fixture-dependent tests still pending.

Reviewed by Cursor Bugbot for commit 10406fa. Bugbot is set up for automated code reviews on this repo. Configure here.

Adds test/pnpm_install_hooks.bats covering async readPackage on a
transitive, async afterAllResolved, .pnpmfile.cjs syntax-error and
require-error paths, and readPackage setting optional/peer/dev fields
on a transitive. Two more tests are present but skipped — they expose
real aube divergences from pnpm (readPackage returning undefined
should fail; readPackage on the root manifest should apply) that
warrant separate Discussions before un-skipping.

Updates test/PNPM_TEST_IMPORT.md to mark hooks.ts 5/22 done with the
remaining-test breakdown, mirroring the pattern from misc.ts.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
@greptile-apps
Copy link
Copy Markdown

greptile-apps Bot commented Apr 30, 2026

Greptile Summary

Ports 5 hook tests from pnpm/test/install/hooks.ts into a new test/pnpm_install_hooks.bats, covering async readPackage, async afterAllResolved, and pnpmfile error paths, with 2 tests explicitly skipped and documented as aube divergences. The previously noted missing negative assertions for is-number and kind-of are already present in this PR (lines 54–57).

Confidence Score: 5/5

Test-only PR with no production code changes; safe to merge.

All active tests include appropriate assertions (including the negative transitive-dep checks), skipped tests have clear divergence documentation, and the tracking doc is accurate. No logic or security concerns.

No files require special attention.

Important Files Changed

Filename Overview
test/pnpm_install_hooks.bats New Bats test file porting 5 active + 2 skipped hook tests from pnpm; negative assertions for stripped transitive deps are present; skipped tests are clearly documented with divergence rationale.
test/PNPM_TEST_IMPORT.md Tracking doc updated to reflect new hooks test file, progress counts, deferred tests, and documented aube divergences.

Reviews (2): Last reviewed commit: "test: add negative assertions to async r..." | Re-trigger Greptile

Comment thread test/pnpm_install_hooks.bats
Greptile flagged that asserting is-odd's snapshot is empty doesn't
prove the transitive chain was actually short-circuited. Add explicit
checks that is-number and kind-of (is-odd → is-number → kind-of)
never appear in the lockfile.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
@jdx jdx merged commit b5cb3cd into main Apr 30, 2026
18 checks passed
@jdx jdx deleted the claude/pnpm-import-hooks branch April 30, 2026 21:15
@github-actions
Copy link
Copy Markdown

Benchmark changes

Versions:

  • aube: 1.5.1 -> 1.5.2
  • pnpm: 11.0.1 -> 11.0.3

Public ratios: warm installs vs Bun 3x -> 4x; warm installs vs pnpm 9x -> 9x.

Benchmark aube bun pnpm
Fresh install (warm cache) 237ms -> 256ms (+8%) 728ms -> 1078ms (+48%) 2104ms -> 2405ms (+14%)
CI install (warm cache, GVS disabled) 564ms -> 736ms (+30%) 742ms -> 1330ms (+79%) 2094ms -> 2690ms (+28%)
CI install (cold cache, GVS disabled) 2282ms -> 4648ms (+104%) 1895ms -> 4676ms (+147%) 5439ms -> 4699ms (-14%)

10406fa vs 113eb8b | aube/bun/pnpm | 3 scenarios | 3 runs | 500mbit/50ms | generated by Codex.

jdx added a commit that referenced this pull request Apr 30, 2026
## Summary

Ports 5 active hook tests + 2 skipped divergences from
[`pnpm/test/install/hooks.ts`](https://github.com/pnpm/pnpm/blob/main/pnpm/test/install/hooks.ts)
into the new
[test/pnpm_install_hooks.bats](https://github.com/endevco/aube/blob/claude/pnpm-import-hooks/test/pnpm_install_hooks.bats),
following the pattern established by
[#416](#416) (tracked in
`test/PNPM_TEST_IMPORT.md`).

**Active tests (all passing):**
- async `readPackage` mutates a transitive's deps — pnpm hooks.ts:43
- async `afterAllResolved` runs and is awaited — hooks.ts:498
- syntax error in `.pnpmfile.cjs` fails the install — hooks.ts:292
- `require()` of a missing module fails the install — hooks.ts:303
- `readPackage` setting optional/peer/dev fields on a transitive —
hooks.ts:528

**Skipped — surfaced aube divergences (worth filing as Discussions
before un-skipping):**
- `readPackage` returning `undefined` should fail the install
(hooks.ts:68); aube continues with the original manifest
- `readPackage` mutating the root project's `.dependencies` should
install those deps (hooks.ts:551); aube does not run the hook on the
root manifest

The remaining 15 tests in hooks.ts depend on `@pnpm.e2e/*` fixtures
(Phase 0) or `addDistTag` helper (Phase 2) and are tracked in the TODO
doc.

## Test plan

- [x] `mise run test:bats test/pnpm_install_hooks.bats` — 5 ok, 2 skip,
0 fail.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

<!-- CURSOR_SUMMARY -->
---

> [!NOTE]
> **Low Risk**
> Low risk: changes are limited to test suite additions and a tracking
doc update, with no production code impact. Main risk is potential test
flakiness due to lockfile/path assertions and pnpmfile error-message
matching.
> 
> **Overview**
> Ports a first batch of `pnpm/test/install/hooks.ts` coverage into
aube’s bats suite by adding `test/pnpm_install_hooks.bats`.
> 
> The new tests exercise `.pnpmfile.cjs` hook behavior (async
`readPackage` mutation of transitives, async `afterAllResolved` being
awaited) and failure paths when the pnpmfile has a syntax error or
`require()`s a missing module; two additional cases are added but marked
`skip` to document current aube divergences.
> 
> Updates `test/PNPM_TEST_IMPORT.md` to track the hooks port progress,
list completed/skipped cases, and note divergences/fixture-dependent
tests still pending.
> 
> <sup>Reviewed by [Cursor Bugbot](https://cursor.com/bugbot) for commit
10406fa. Bugbot is set up for automated
code reviews on this repo. Configure
[here](https://www.cursor.com/dashboard/bugbot).</sup>
<!-- /CURSOR_SUMMARY -->

---------

Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
jdx added a commit that referenced this pull request Apr 30, 2026
Closes three pnpmfile gaps surfaced while porting more cases from
pnpm/test/install/hooks.ts (follow-up to #419):

- `aube update` now runs the full pnpmfile cycle (preResolution +
  readPackage + afterAllResolved). Previously it built its resolver
  via `commands::build_resolver` without attaching the readPackage
  host, then handed off to `install::run` in frozen-prefer mode —
  which consumes the lockfile as-is, so the hook never fired on
  update.
- `aube update --ignore-pnpmfile` is now accepted and honored,
  matching the install-side flag (and pnpm).
- The `preResolution` hook is now supported. The hook receives a
  context object with `lockfileDir`, `storeDir`, `currentLockfile`,
  `wantedLockfile`, `existsCurrentLockfile`,
  `existsNonEmptyWantedLockfile`, and a `registries` map (default
  + scoped), matching pnpm's shape on the wire (camelCase). It
  fires before resolve in install (lockfile-only and streaming
  paths) and update; the spawn is skipped when the pnpmfile
  doesn't reference `preResolution`, so hook-less files don't pay
  the per-install node-startup cost.

Implementation factors out a `run_one_shot_hook` helper in
pnpmfile.rs so afterAllResolved and preResolution share the same
node-spawn / pipe / wait scaffolding, and a
`commands::run_pnpmfile_pre_resolution` helper so install and
update build the context from the same sources.

Also un-skips the three previously-skipped tests in
test/pnpm_install_hooks.bats now that the underlying gaps are
closed; they were the originals that surfaced these divergences
during the port.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
jdx added a commit that referenced this pull request Apr 30, 2026
Closes three pnpmfile gaps surfaced while porting more cases from
pnpm/test/install/hooks.ts (follow-up to #419):

- `aube update` now runs the full pnpmfile cycle (preResolution +
  readPackage + afterAllResolved). Previously it built its resolver
  via `commands::build_resolver` without attaching the readPackage
  host, then handed off to `install::run` in frozen-prefer mode —
  which consumes the lockfile as-is, so the hook never fired on
  update.
- `aube update --ignore-pnpmfile` is now accepted and honored,
  matching the install-side flag (and pnpm).
- The `preResolution` hook is now supported. The hook receives a
  context object with `lockfileDir`, `storeDir`, `currentLockfile`,
  `wantedLockfile`, `existsCurrentLockfile`,
  `existsNonEmptyWantedLockfile`, and a `registries` map (default
  + scoped), matching pnpm's shape on the wire (camelCase). It
  fires before resolve in install (lockfile-only and streaming
  paths) and update; the spawn is skipped when the pnpmfile
  doesn't reference `preResolution`, so hook-less files don't pay
  the per-install node-startup cost.

Implementation factors out a `run_one_shot_hook` helper in
pnpmfile.rs so afterAllResolved and preResolution share the same
node-spawn / pipe / wait scaffolding, and a
`commands::run_pnpmfile_pre_resolution` helper so install and
update build the context from the same sources.

Also un-skips the three previously-skipped tests in
test/pnpm_install_hooks.bats now that the underlying gaps are
closed; they were the originals that surfaced these divergences
during the port.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
jdx added a commit that referenced this pull request Apr 30, 2026
Closes three pnpmfile gaps surfaced while porting more cases from
pnpm/test/install/hooks.ts (follow-up to #419):

- `aube update` now runs the full pnpmfile cycle (preResolution +
  readPackage + afterAllResolved). Previously it built its resolver
  via `commands::build_resolver` without attaching the readPackage
  host, then handed off to `install::run` in frozen-prefer mode —
  which consumes the lockfile as-is, so the hook never fired on
  update.
- `aube update --ignore-pnpmfile` is now accepted and honored,
  matching the install-side flag (and pnpm).
- The `preResolution` hook is now supported. The hook receives a
  context object with `lockfileDir`, `storeDir`, `currentLockfile`,
  `wantedLockfile`, `existsCurrentLockfile`,
  `existsNonEmptyWantedLockfile`, and a `registries` map (default
  + scoped), matching pnpm's shape on the wire (camelCase). It
  fires before resolve in install (lockfile-only and streaming
  paths) and update; the spawn is skipped when the pnpmfile
  doesn't reference `preResolution`, so hook-less files don't pay
  the per-install node-startup cost.

Implementation factors out a `run_one_shot_hook` helper in
pnpmfile.rs so afterAllResolved and preResolution share the same
node-spawn / pipe / wait scaffolding, and a
`commands::run_pnpmfile_pre_resolution` helper so install and
update build the context from the same sources.

Also un-skips the three previously-skipped tests in
test/pnpm_install_hooks.bats now that the underlying gaps are
closed; they were the originals that surfaced these divergences
during the port.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
jdx added a commit that referenced this pull request Apr 30, 2026
Closes three pnpmfile gaps surfaced while porting more cases from
pnpm/test/install/hooks.ts (follow-up to #419):

- `aube update` now runs the full pnpmfile cycle (preResolution +
  readPackage + afterAllResolved). Previously it built its resolver
  via `commands::build_resolver` without attaching the readPackage
  host, then handed off to `install::run` in frozen-prefer mode —
  which consumes the lockfile as-is, so the hook never fired on
  update.
- `aube update --ignore-pnpmfile` is now accepted and honored,
  matching the install-side flag (and pnpm).
- The `preResolution` hook is now supported. The hook receives a
  context object with `lockfileDir`, `storeDir`, `currentLockfile`,
  `wantedLockfile`, `existsCurrentLockfile`,
  `existsNonEmptyWantedLockfile`, and a `registries` map (default
  + scoped), matching pnpm's shape on the wire (camelCase). It
  fires before resolve in install (lockfile-only and streaming
  paths) and update; the spawn is skipped when the pnpmfile
  doesn't reference `preResolution`, so hook-less files don't pay
  the per-install node-startup cost.

Implementation factors out a `run_one_shot_hook` helper in
pnpmfile.rs so afterAllResolved and preResolution share the same
node-spawn / pipe / wait scaffolding, and a
`commands::run_pnpmfile_pre_resolution` helper so install and
update build the context from the same sources.

Also un-skips the three previously-skipped tests in
test/pnpm_install_hooks.bats now that the underlying gaps are
closed; they were the originals that surfaced these divergences
during the port.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
jdx added a commit that referenced this pull request Apr 30, 2026
Closes three pnpmfile gaps surfaced while porting more cases from
pnpm/test/install/hooks.ts (follow-up to #419):

- `aube update` now runs the full pnpmfile cycle (preResolution +
  readPackage + afterAllResolved). Previously it built its resolver
  via `commands::build_resolver` without attaching the readPackage
  host, then handed off to `install::run` in frozen-prefer mode —
  which consumes the lockfile as-is, so the hook never fired on
  update.
- `aube update --ignore-pnpmfile` is now accepted and honored,
  matching the install-side flag (and pnpm).
- The `preResolution` hook is now supported. The hook receives a
  context object with `lockfileDir`, `storeDir`, `currentLockfile`,
  `wantedLockfile`, `existsCurrentLockfile`,
  `existsNonEmptyWantedLockfile`, and a `registries` map (default
  + scoped), matching pnpm's shape on the wire (camelCase). It
  fires before resolve in install (lockfile-only and streaming
  paths) and update; the spawn is skipped when the pnpmfile
  doesn't reference `preResolution`, so hook-less files don't pay
  the per-install node-startup cost.

Implementation factors out a `run_one_shot_hook` helper in
pnpmfile.rs so afterAllResolved and preResolution share the same
node-spawn / pipe / wait scaffolding, and a
`commands::run_pnpmfile_pre_resolution` helper so install and
update build the context from the same sources.

Also un-skips the three previously-skipped tests in
test/pnpm_install_hooks.bats now that the underlying gaps are
closed; they were the originals that surfaced these divergences
during the port.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
jdx added a commit that referenced this pull request Apr 30, 2026
Closes three pnpmfile gaps surfaced while porting more cases from
pnpm/test/install/hooks.ts (follow-up to #419):

- `aube update` now runs the full pnpmfile cycle (preResolution +
  readPackage + afterAllResolved). Previously it built its resolver
  via `commands::build_resolver` without attaching the readPackage
  host, then handed off to `install::run` in frozen-prefer mode —
  which consumes the lockfile as-is, so the hook never fired on
  update.
- `aube update --ignore-pnpmfile` is now accepted and honored,
  matching the install-side flag (and pnpm).
- The `preResolution` hook is now supported. The hook receives a
  context object with `lockfileDir`, `storeDir`, `currentLockfile`,
  `wantedLockfile`, `existsCurrentLockfile`,
  `existsNonEmptyWantedLockfile`, and a `registries` map (default
  + scoped), matching pnpm's shape on the wire (camelCase). It
  fires before resolve in install (lockfile-only and streaming
  paths) and update; the spawn is skipped when the pnpmfile
  doesn't reference `preResolution`, so hook-less files don't pay
  the per-install node-startup cost.

Implementation factors out a `run_one_shot_hook` helper in
pnpmfile.rs so afterAllResolved and preResolution share the same
node-spawn / pipe / wait scaffolding, and a
`commands::run_pnpmfile_pre_resolution` helper so install and
update build the context from the same sources.

Also un-skips the three previously-skipped tests in
test/pnpm_install_hooks.bats now that the underlying gaps are
closed; they were the originals that surfaced these divergences
during the port.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
jdx added a commit that referenced this pull request Apr 30, 2026
Closes three pnpmfile gaps surfaced while porting more cases from
pnpm/test/install/hooks.ts (follow-up to #419):

- `aube update` now runs the full pnpmfile cycle (preResolution +
  readPackage + afterAllResolved). Previously it built its resolver
  via `commands::build_resolver` without attaching the readPackage
  host, then handed off to `install::run` in frozen-prefer mode —
  which consumes the lockfile as-is, so the hook never fired on
  update.
- `aube update --ignore-pnpmfile` is now accepted and honored,
  matching the install-side flag (and pnpm).
- The `preResolution` hook is now supported. The hook receives a
  context object with `lockfileDir`, `storeDir`, `currentLockfile`,
  `wantedLockfile`, `existsCurrentLockfile`,
  `existsNonEmptyWantedLockfile`, and a `registries` map (default
  + scoped), matching pnpm's shape on the wire (camelCase). It
  fires before resolve in install (lockfile-only and streaming
  paths) and update; the spawn is skipped when the pnpmfile
  doesn't reference `preResolution`, so hook-less files don't pay
  the per-install node-startup cost.

Implementation factors out a `run_one_shot_hook` helper in
pnpmfile.rs so afterAllResolved and preResolution share the same
node-spawn / pipe / wait scaffolding, and a
`commands::run_pnpmfile_pre_resolution` helper so install and
update build the context from the same sources.

Also un-skips the three previously-skipped tests in
test/pnpm_install_hooks.bats now that the underlying gaps are
closed; they were the originals that surfaced these divergences
during the port.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
jdx added a commit that referenced this pull request Apr 30, 2026
Closes three pnpmfile gaps surfaced while porting more cases from
pnpm/test/install/hooks.ts (follow-up to #419):

- `aube update` now runs the full pnpmfile cycle (preResolution +
  readPackage + afterAllResolved). Previously it built its resolver
  via `commands::build_resolver` without attaching the readPackage
  host, then handed off to `install::run` in frozen-prefer mode —
  which consumes the lockfile as-is, so the hook never fired on
  update.
- `aube update --ignore-pnpmfile` is now accepted and honored,
  matching the install-side flag (and pnpm).
- The `preResolution` hook is now supported. The hook receives a
  context object with `lockfileDir`, `storeDir`, `currentLockfile`,
  `wantedLockfile`, `existsCurrentLockfile`,
  `existsNonEmptyWantedLockfile`, and a `registries` map (default
  + scoped), matching pnpm's shape on the wire (camelCase). It
  fires before resolve in install (lockfile-only and streaming
  paths) and update; the spawn is skipped when the pnpmfile
  doesn't reference `preResolution`, so hook-less files don't pay
  the per-install node-startup cost.

Implementation factors out a `run_one_shot_hook` helper in
pnpmfile.rs so afterAllResolved and preResolution share the same
node-spawn / pipe / wait scaffolding, and a
`commands::run_pnpmfile_pre_resolution` helper so install and
update build the context from the same sources.

Also un-skips the three previously-skipped tests in
test/pnpm_install_hooks.bats now that the underlying gaps are
closed; they were the originals that surfaced these divergences
during the port.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
jdx added a commit that referenced this pull request Apr 30, 2026
Closes three pnpmfile gaps surfaced while porting more cases from
pnpm/test/install/hooks.ts (follow-up to #419):

- `aube update` now runs the full pnpmfile cycle (preResolution +
  readPackage + afterAllResolved). Previously it built its resolver
  via `commands::build_resolver` without attaching the readPackage
  host, then handed off to `install::run` in frozen-prefer mode —
  which consumes the lockfile as-is, so the hook never fired on
  update.
- `aube update --ignore-pnpmfile` is now accepted and honored,
  matching the install-side flag (and pnpm).
- The `preResolution` hook is now supported. The hook receives a
  context object with `lockfileDir`, `storeDir`, `currentLockfile`,
  `wantedLockfile`, `existsCurrentLockfile`,
  `existsNonEmptyWantedLockfile`, and a `registries` map (default
  + scoped), matching pnpm's shape on the wire (camelCase). It
  fires before resolve in install (lockfile-only and streaming
  paths) and update; the spawn is skipped when the pnpmfile
  doesn't reference `preResolution`, so hook-less files don't pay
  the per-install node-startup cost.

Implementation factors out a `run_one_shot_hook` helper in
pnpmfile.rs so afterAllResolved and preResolution share the same
node-spawn / pipe / wait scaffolding, and a
`commands::run_pnpmfile_pre_resolution` helper so install and
update build the context from the same sources.

Also un-skips the three previously-skipped tests in
test/pnpm_install_hooks.bats now that the underlying gaps are
closed; they were the originals that surfaced these divergences
during the port.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
jdx added a commit that referenced this pull request Apr 30, 2026
Closes three pnpmfile gaps surfaced while porting more cases from
pnpm/test/install/hooks.ts (follow-up to #419):

- `aube update` now runs the full pnpmfile cycle (preResolution +
  readPackage + afterAllResolved). Previously it built its resolver
  via `commands::build_resolver` without attaching the readPackage
  host, then handed off to `install::run` in frozen-prefer mode —
  which consumes the lockfile as-is, so the hook never fired on
  update.
- `aube update --ignore-pnpmfile` is now accepted and honored,
  matching the install-side flag (and pnpm).
- The `preResolution` hook is now supported. The hook receives a
  context object with `lockfileDir`, `storeDir`, `currentLockfile`,
  `wantedLockfile`, `existsCurrentLockfile`,
  `existsNonEmptyWantedLockfile`, and a `registries` map (default
  + scoped), matching pnpm's shape on the wire (camelCase). It
  fires before resolve in install (lockfile-only and streaming
  paths) and update; the spawn is skipped when the pnpmfile
  doesn't reference `preResolution`, so hook-less files don't pay
  the per-install node-startup cost.

Implementation factors out a `run_one_shot_hook` helper in
pnpmfile.rs so afterAllResolved and preResolution share the same
node-spawn / pipe / wait scaffolding, and a
`commands::run_pnpmfile_pre_resolution` helper so install and
update build the context from the same sources.

Also un-skips the three previously-skipped tests in
test/pnpm_install_hooks.bats now that the underlying gaps are
closed; they were the originals that surfaced these divergences
during the port.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
jdx added a commit that referenced this pull request Apr 30, 2026
## Summary

Closes three pnpmfile gaps surfaced while porting more cases from
[`pnpm/test/install/hooks.ts`](https://github.com/pnpm/pnpm/blob/main/pnpm/test/install/hooks.ts)
(follow-up to [#419](#419)):

- **`aube update` now runs the full pnpmfile cycle.** Previously update
built its resolver via `commands::build_resolver` without attaching the
readPackage host, then handed off to `install::run` in frozen-prefer
mode — which consumes the lockfile as-is, so the hook never fired on
update. Now update wires `preResolution` + `readPackage` +
`afterAllResolved` the same way install does.
- **`aube update --ignore-pnpmfile`** is now accepted and honored,
matching the install-side flag and pnpm.
- **`preResolution` hook** is now supported. The hook receives a context
object with `lockfileDir`, `storeDir`, `currentLockfile`,
`wantedLockfile`, `existsCurrentLockfile`,
`existsNonEmptyWantedLockfile`, and a `registries` map (default +
scoped), matching pnpm's wire shape (camelCase). It fires before resolve
in install (lockfile-only and streaming paths) and update; the spawn is
skipped when the pnpmfile doesn't reference `preResolution`, so
hook-less files don't pay the per-install node-startup cost.

Implementation factors out a `run_one_shot_hook` helper in
[`crates/aube/src/pnpmfile.rs`](https://github.com/endevco/aube/blob/claude/pnpm-import-hooks-followup/crates/aube/src/pnpmfile.rs)
so `afterAllResolved` and `preResolution` share the same node-spawn /
pipe / wait scaffolding, and a `commands::run_pnpmfile_pre_resolution`
helper in
[`crates/aube/src/commands/mod.rs`](https://github.com/endevco/aube/blob/claude/pnpm-import-hooks-followup/crates/aube/src/commands/mod.rs)
so install and update build the context from the same sources.

Also adds three more ports from `hooks.ts`
([`test/pnpm_install_hooks.bats`](https://github.com/endevco/aube/blob/claude/pnpm-import-hooks-followup/test/pnpm_install_hooks.bats))
— these are the originals that surfaced the divergences during the port
and pass once the gaps above are closed:

- `readPackage` during `aube update` (hooks.ts:263)
- `--ignore-pnpmfile` on `aube update` (hooks.ts:338)
- `preResolution` hook fires before resolve (hooks.ts:624)

## Test plan

- [x] `mise run test:bats test/pnpm_install_hooks.bats` — 8 ok, 2 skip
(the two pre-existing divergences from #419), 0 fail.
- [x] `mise run test:bats test/pnpmfile.bats` — 9 ok.
- [x] `mise run test:bats test/update.bats` — 10 ok.
- [x] `mise run test:bats test/install.bats` — 61 ok.
- [x] `cargo test -p aube` — 330 unit tests + 4 e2e, 0 failures.
- [x] `cargo clippy --all-targets -- -D warnings` clean.
- [x] `cargo fmt --check` clean.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

<!-- CURSOR_SUMMARY -->
---

> [!NOTE]
> **Medium Risk**
> Changes when and how `.pnpmfile.*` hooks execute (including spawning
`node`) during `update` and early install resolution, which can affect
dependency graphs and lockfile output.
> 
> **Overview**
> `aube update` now runs the pnpmfile hook lifecycle (runs
`preResolution`, attaches `readPackage`, then runs `afterAllResolved`)
so hook-driven dependency mutations are reflected in the updated
lockfile.
> 
> Adds support for the pnpmfile `preResolution` hook with a pnpm-shaped
context snapshot, and factors one-shot hook execution into a shared
`run_one_shot_hook` helper. Introduces `update --ignore-pnpmfile` and
propagates it through the chained frozen-prefer install.
> 
> Updates CLI usage/docs and adds new Bats coverage for `readPackage`
during update, `--ignore-pnpmfile` on update, and `preResolution` firing
before resolve.
> 
> <sup>Reviewed by [Cursor Bugbot](https://cursor.com/bugbot) for commit
1ad36a5. Bugbot is set up for automated
code reviews on this repo. Configure
[here](https://www.cursor.com/dashboard/bugbot).</sup>
<!-- /CURSOR_SUMMARY -->

Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
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