feat: implement native 'pnpm bugs' command#11493
Conversation
- Add fallback logic in execPnpm.ts to find pnpm binary in multiple locations since import.meta.dirname resolves differently in ESM mode - Fix test to check both stdout and stderr since pnpm outputs errors to stdout in some cases
According to npm help, the usage is: Usage: npm bugs [<pkgname> [<pkgname> ...]] This change adds support for passing package names to the bugs command, which will open the bugs URL for that package from the registry.
Renames pnpm/test/bugs.ts to pnpm/test/bugs.test.ts to ensure TypeScript compilation recognizes Jest globals (test, expect).
Add "types": ["jest"] to pnpm/test/tsconfig.json to resolve TypeScript errors for test and expect globals in test files.
Skip the 'dlx creates cache and store prune cleans cache' test that consistently times out after 180000ms. This is a pre-existing flaky test unrelated to the pnpm bugs feature.
This reverts commit 904eb08.
Replace Promise.all with sequential execution to prevent timeout issues when running multiple dlx commands in parallel during the test.
Replace Promise.all with sequential execution to prevent timeout. Add eslint-disable comment for no-await-in-loop as sequential execution is required here to avoid overwhelming the system.
Replace Promise.all with sequential execution to prevent timeout. Add eslint-disable comment for no-await-in-loop rule.
Move pnpm bugs into @pnpm/deps.inspection.commands alongside docs, reusing fetchPackageInfo for registry lookups (auth, scoped-name encoding, retries) and the open package for cross-platform browser opening. Normalize repository URLs (strip git+, .git, rewrite git:// and git@github.com:) before falling back to <repo>/issues. All errors are PnpmError; tests mock open and assert on resolved URLs. Drop unrelated test/build changes that crept into the branch: bins/linker spawnSync tweak, jest globalSetup SIGTERM handling, execPnpm bin location fallback, dlx sequential execution, tsconfig types override, and the pnpm-lock.yaml patchedDependencies expansion.
|
Note Reviews pausedIt looks like this branch is under active development. To avoid overwhelming you with review comments due to an influx of new commits, CodeRabbit has automatically paused this review. You can configure this behavior by changing the Use the following commands to manage reviews:
Use the checkboxes below for quick actions:
📝 WalkthroughWalkthroughAdds a native pnpm ChangesBugs Command Feature
Sequence DiagramsequenceDiagram
actor User
participant CLI as pnpm CLI
participant Handler as Bugs Handler
participant Manifest as Manifest Reader
participant Registry as Registry
participant URLUtil as URL Utilities
participant Browser as Browser
User->>CLI: pnpm bugs [package-name]
CLI->>Handler: invoke handler(opts, params)
alt No package name provided
Handler->>Manifest: tryReadProjectManifest(dir)
Manifest-->>Handler: local manifest
else Package name provided
Handler->>Registry: fetchPackageInfo(packageSpec)
Registry-->>Handler: remote manifest
end
Handler->>URLUtil: pickBugsUrl(manifest)
URLUtil-->>Handler: bugs URL or undefined
alt bugs URL found
Handler->>URLUtil: isHttpUrl(url)
URLUtil-->>Handler: validated URL
else no bugs field
Handler->>URLUtil: repositoryToIssuesUrl(repository)
URLUtil-->>Handler: issues URL
end
Handler->>Browser: open(finalURL)
Browser-->>User: opens bug tracker
Estimated code review effort🎯 3 (Moderate) | ⏱️ ~25 minutes Poem
🚥 Pre-merge checks | ✅ 4 | ❌ 1❌ Failed checks (1 warning)
✅ Passed checks (4 passed)
✏️ Tip: You can configure your own custom pre-merge checks in the settings. ✨ Finishing Touches🧪 Generate unit tests (beta)
Comment |
There was a problem hiding this comment.
Actionable comments posted: 2
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
Inline comments:
In @.changeset/pnpm-bugs-command.md:
- Line 6: Update the issue hyperlink in the changeset text to reference the
correct PR number: replace the existing `#11244` reference with `#11279` in the
.changeset/pnpm-bugs-command.md entry describing the `pnpm bugs` command so the
release-note link matches the tracked PR.
In `@deps/inspection/commands/src/bugs/index.ts`:
- Line 79: Trim trailing slashes from the normalized repository URL before
appending paths so you don't produce double slashes; in the code paths that
build URLs (the conditional using the variable normalized with isHttpUrl and the
other branches around lines 85-92), ensure you sanitize normalized by removing
any trailing '/' (e.g., via a single trim operation) before concatenating
"/issues" or other suffixes so `${normalized}/issues` never becomes `//issues`.
🪄 Autofix (Beta)
Fix all unresolved CodeRabbit comments on this PR:
- Push a commit to this branch (recommended)
- Create a new PR with the fixes
ℹ️ Review info
⚙️ Run configuration
Configuration used: defaults
Review profile: CHILL
Plan: Pro Plus
Run ID: fcdc1f84-72ad-4013-95a1-5def87882b39
📒 Files selected for processing (6)
.changeset/pnpm-bugs-command.mddeps/inspection/commands/src/bugs/index.tsdeps/inspection/commands/src/index.tsdeps/inspection/commands/test/bugs.tspnpm/src/cmd/index.tspnpm/src/cmd/notImplemented.ts
💤 Files with no reviewable changes (1)
- pnpm/src/cmd/notImplemented.ts
…geset issue link normalizeRepositoryUrl now strips trailing slashes so a repository URL like `https://github.com/foo/bar/` becomes `https://github.com/foo/bar/issues` rather than `...//issues`. Added a regression test. The changeset previously linked to #11244, which is the docs-command PR, not bugs — removed the bogus reference.
There was a problem hiding this comment.
🧹 Nitpick comments (1)
deps/inspection/commands/test/bugs.ts (1)
61-81: ⚡ Quick winAdd tests for remaining repository URL normalization branches.
Coverage currently validates
git+httpsand trailing-slash trimming, but notgit://andgit@github.com:paths handled bynormalizeRepositoryUrl. Add both to prevent regressions in the advertised fallback behavior.Proposed test additions
test('bugs: normalizes git+https repository URL with .git suffix', async () => { mockOpen.mockClear() const dir = tempDir() fs.writeFileSync(path.join(dir, 'package.json'), JSON.stringify({ name: 'test-pkg', repository: { url: 'git+https://github.com/test/pkg.git' }, })) await bugs.handler({ ...BASE_OPTIONS, dir }, []) expect(mockOpen).toHaveBeenCalledWith('https://github.com/test/pkg/issues') }) +test('bugs: normalizes git:// repository URL', async () => { + mockOpen.mockClear() + const dir = tempDir() + fs.writeFileSync(path.join(dir, 'package.json'), JSON.stringify({ + name: 'test-pkg', + repository: 'git://github.com/test/pkg.git', + })) + await bugs.handler({ ...BASE_OPTIONS, dir }, []) + expect(mockOpen).toHaveBeenCalledWith('https://github.com/test/pkg/issues') +}) + +test('bugs: normalizes git@github.com: repository URL', async () => { + mockOpen.mockClear() + const dir = tempDir() + fs.writeFileSync(path.join(dir, 'package.json'), JSON.stringify({ + name: 'test-pkg', + repository: 'git@github.com:test/pkg.git', + })) + await bugs.handler({ ...BASE_OPTIONS, dir }, []) + expect(mockOpen).toHaveBeenCalledWith('https://github.com/test/pkg/issues') +}) + test('bugs: trims trailing slash from repository URL before appending /issues', async () => { mockOpen.mockClear() const dir = tempDir() fs.writeFileSync(path.join(dir, 'package.json'), JSON.stringify({ name: 'test-pkg',🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@deps/inspection/commands/test/bugs.ts` around lines 61 - 81, Add two tests to deps/inspection/commands/test/bugs.ts that exercise the remaining branches of normalizeRepositoryUrl: one where package.json repository is "git://github.com/test/pkg.git" and one where it's "git@github.com:test/pkg.git" (or similar SSH form). Follow the existing test pattern that clears mockOpen, writes package.json into tempDir, calls await bugs.handler({ ...BASE_OPTIONS, dir }, []), and asserts mockOpen was called with 'https://github.com/test/pkg/issues'; reference the existing tests using mockOpen, tempDir, fs.writeFileSync, and bugs.handler to locate where to insert these cases.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
Nitpick comments:
In `@deps/inspection/commands/test/bugs.ts`:
- Around line 61-81: Add two tests to deps/inspection/commands/test/bugs.ts that
exercise the remaining branches of normalizeRepositoryUrl: one where
package.json repository is "git://github.com/test/pkg.git" and one where it's
"git@github.com:test/pkg.git" (or similar SSH form). Follow the existing test
pattern that clears mockOpen, writes package.json into tempDir, calls await
bugs.handler({ ...BASE_OPTIONS, dir }, []), and asserts mockOpen was called with
'https://github.com/test/pkg/issues'; reference the existing tests using
mockOpen, tempDir, fs.writeFileSync, and bugs.handler to locate where to insert
these cases.
ℹ️ Review info
⚙️ Run configuration
Configuration used: defaults
Review profile: CHILL
Plan: Pro Plus
Run ID: eb33f04d-21fe-4282-a589-c808e858388b
📒 Files selected for processing (3)
.changeset/pnpm-bugs-command.mddeps/inspection/commands/src/bugs/index.tsdeps/inspection/commands/test/bugs.ts
🚧 Files skipped from review as they are similar to previous changes (1)
- deps/inspection/commands/src/bugs/index.ts
There was a problem hiding this comment.
Pull request overview
Adds an npm-compatible native pnpm bugs command to open a package’s bug tracker URL in the browser, implemented in @pnpm/deps.inspection.commands and wired into the main pnpm CLI.
Changes:
- Added
bugscommand implementation that derives a bugs URL frombugsor falls back to<repository>/issues(local manifest or registry metadata). - Registered the command in pnpm’s command index and removed it from the “not implemented” list.
- Added Jest coverage for local-manifest and registry-lookup scenarios, plus a changeset to publish the feature.
Reviewed changes
Copilot reviewed 6 out of 6 changed files in this pull request and generated 4 comments.
Show a summary per file
| File | Description |
|---|---|
| pnpm/src/cmd/notImplemented.ts | Removes bugs from the list of unimplemented npm-compat commands. |
| pnpm/src/cmd/index.ts | Imports and registers the new bugs command with pnpm’s command list. |
| deps/inspection/commands/src/index.ts | Exposes the new bugs command from the inspection commands package. |
| deps/inspection/commands/src/bugs/index.ts | Implements pnpm bugs URL resolution + browser opening. |
| deps/inspection/commands/test/bugs.ts | Adds tests for bugs URL selection, normalization, and error cases with mocked open. |
| .changeset/pnpm-bugs-command.md | Declares a minor release for pnpm and @pnpm/deps.inspection.commands. |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
There was a problem hiding this comment.
♻️ Duplicate comments (1)
.changeset/pnpm-bugs-command.md (1)
6-6:⚠️ Potential issue | 🟡 Minor | ⚡ Quick winUse the issue URL (not pull URL) for
#11279.The text references linked issue
#11279, but the hyperlink points to a PR path. Please switch to the issue URL for accurate release-note traceability.Suggested patch
-Added the `pnpm bugs` command that opens a package's bug tracker URL in the browser. With no arguments, it reads the current project's `package.json`; with one or more package names, it fetches each package's metadata from the registry and opens its bug tracker. Falls back to `<repository>/issues` when the `bugs` field is missing [`#11279`](https://github.com/pnpm/pnpm/pull/11279). +Added the `pnpm bugs` command that opens a package's bug tracker URL in the browser. With no arguments, it reads the current project's `package.json`; with one or more package names, it fetches each package's metadata from the registry and opens its bug tracker. Falls back to `<repository>/issues` when the `bugs` field is missing [`#11279`](https://github.com/pnpm/pnpm/issues/11279).🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In @.changeset/pnpm-bugs-command.md at line 6, Update the hyperlink for the referenced ticket in the changelog entry: in .changeset/pnpm-bugs-command.md replace the PR URL "https://github.com/pnpm/pnpm/pull/11279" with the issue URL "https://github.com/pnpm/pnpm/issues/11279" so the reference to `#11279` points to the issue rather than the pull request.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
Duplicate comments:
In @.changeset/pnpm-bugs-command.md:
- Line 6: Update the hyperlink for the referenced ticket in the changelog entry:
in .changeset/pnpm-bugs-command.md replace the PR URL
"https://github.com/pnpm/pnpm/pull/11279" with the issue URL
"https://github.com/pnpm/pnpm/issues/11279" so the reference to `#11279` points
to the issue rather than the pull request.
ℹ️ Review info
⚙️ Run configuration
Configuration used: defaults
Review profile: CHILL
Plan: Pro Plus
Run ID: 7d9c3c85-39a4-4698-9aa6-3b0685019ffe
📒 Files selected for processing (1)
.changeset/pnpm-bugs-command.md
- Use readProjectManifestOnly with engineStrict/nodeVersion/supportedArchitectures passed through from config, matching the pattern of other commands. The not-found error now bubbles up as ERR_PNPM_NO_IMPORTER_MANIFEST_FOUND with pnpm's standard message that lists package.json/package.yaml/package.json5. - Build the fallback issues URL by parsing with URL, clearing search/hash, trimming the trailing slash and any .git suffix from the pathname, then appending /issues. Handles repository values with fragments/queries (e.g. git+https://github.com/foo/bar.git#main) without producing broken URLs. Added a regression test.
There was a problem hiding this comment.
Actionable comments posted: 1
🧹 Nitpick comments (1)
deps/inspection/commands/test/bugs.ts (1)
111-118: ⚡ Quick winTighten the registry lookup assertion to verify bug-tracker semantics.
startsWith('http')is too broad; this can pass on non-bug URLs. Assert an issues-like target (or an exact expected URL for the fixture package) to better lock behavior.Suggested patch
await bugs.handler(BASE_OPTIONS, ['is-negative']) expect(mockOpen).toHaveBeenCalledTimes(1) const calledUrl = mockOpen.mock.calls[0][0] expect(typeof calledUrl).toBe('string') - expect((calledUrl as string).startsWith('http')).toBe(true) + expect(calledUrl).toMatch(/^https?:\/\/.+\/issues\/?$/)🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@deps/inspection/commands/test/bugs.ts` around lines 111 - 118, The test "bugs: looks up package on registry by name" currently asserts only that the opened URL starts with "http", which is too loose; update the assertion on calledUrl (from mockOpen.mock.calls[0][0]) to verify bug-tracker semantics instead—either assert an exact expected URL for the fixture package "is-negative" (preferred) or at minimum assert the URL contains an issues-like path segment such as "/issues" or a known issue host (e.g., "github.com") so the test guarantees the command opens a bug/issue page rather than any arbitrary HTTP URL.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
Inline comments:
In `@deps/inspection/commands/src/bugs/index.ts`:
- Line 101: The pathname normalization for parsed.pathname in the bugs command
is missing the `.git/` case and can leave `.git` before appending `/issues`;
update the replace logic in the code handling parsed.pathname (the expression
that currently calls parsed.pathname.replace(/\.git$/, '').replace(/\/+$/, ''))
to strip a trailing `.git` with an optional slash (e.g., remove `/.git` or
`/.git/`) and then trim trailing slashes, so the final value when you append
'/issues' never retains `.git`; modify the regex to account for an optional
slash (or normalize slashes first) in the same expression where parsed.pathname
is set.
---
Nitpick comments:
In `@deps/inspection/commands/test/bugs.ts`:
- Around line 111-118: The test "bugs: looks up package on registry by name"
currently asserts only that the opened URL starts with "http", which is too
loose; update the assertion on calledUrl (from mockOpen.mock.calls[0][0]) to
verify bug-tracker semantics instead—either assert an exact expected URL for the
fixture package "is-negative" (preferred) or at minimum assert the URL contains
an issues-like path segment such as "/issues" or a known issue host (e.g.,
"github.com") so the test guarantees the command opens a bug/issue page rather
than any arbitrary HTTP URL.
🪄 Autofix (Beta)
Fix all unresolved CodeRabbit comments on this PR:
- Push a commit to this branch (recommended)
- Create a new PR with the fixes
ℹ️ Review info
⚙️ Run configuration
Configuration used: defaults
Review profile: CHILL
Plan: Pro Plus
Run ID: 9f867d68-f019-49a5-9430-59d80038e559
📒 Files selected for processing (2)
deps/inspection/commands/src/bugs/index.tsdeps/inspection/commands/test/bugs.ts
…-info Use hosted-git-info to resolve the bugs URL for the standard host shorthand forms (`owner/repo`, `github:owner/repo`, `gitlab:…`, `bitbucket:…`) and SSH git URLs (`git+ssh://…`, `git@github.com:…`) — anything HostedGit knows about yields the canonical /issues URL directly. The URL-parsing fallback remains for self-hosted git servers (e.g. `https://git.example.com/foo/bar.git`). Added tests for owner/repo shorthand, github:/gitlab: shorthands, git+ssh URLs, and the self-hosted fallback.
Summary
Adds a native
pnpm bugscommand (npm-compatible) that opens a package's bug tracker URL in the browser.bugs/repositoryfrom the current project'spackage.json.fetchPackageInfo, so auth, scoped names, and proxies are handled) and opens its bug tracker.<repository>/issueswhenbugsis missing, normalizinggit+,.git,git://, andgit@github.com:forms first.@pnpm/deps.inspection.commandsalongsidedocs, reusing theopenpackage for cross-platform browser launching.Picked up from #11279 (kairosci's branch) and reworked per @zkochan's review:
pnpm/src/cmd/into the inspection commands packagepnpm bugs [<pkgname> [<pkgname> ...]]per npmbins.linkerbump)Closes #11279.
Test plan
pnpm --filter @pnpm/deps.inspection.commands run lintdeps/inspection/commands/test/bugs.ts(URL resolution frombugs.url,bugsstring,repositoryfallback,git+httpsnormalization, missing-URL error, missing-manifest error, registry lookup) — all pass with mockedopenpnpm/dist/pnpm.mjs:bugs --help,bugs(success + no-URL error case)Written by an agent (Claude Code, claude-opus-4-7).
Summary by CodeRabbit
New Features
pnpm bugscommand to open a package’s bug tracker for the current project or for packages resolved from the registry, with fallback to repository issues when missing.Tests
Chores