Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: friendlier error message when command not found #6887

Merged
merged 19 commits into from Aug 4, 2023

Conversation

KSXGitHub
Copy link
Contributor

@KSXGitHub KSXGitHub commented Aug 1, 2023

Related comment: scaffold-eth/scaffold-eth-2#444 (comment)

Initially, I have hoped that I can create a hint for pnpm $script in general, but since I don't know how to distinguish between pnpm $script and pnpm exec $script, I have to settle for pnpm exec $script only.

@KSXGitHub KSXGitHub requested a review from zkochan as a code owner August 1, 2023 10:03
Comment on lines 217 to 219
const nearestCommand = getNearestCommand(params[0], (await readProjectManifestOnly(opts.dir)).scripts)
if (nearestCommand) {
err.hint = `Did you mean "pnpm exec ${nearestCommand}"?`
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This doesn't make sense. The pnpm exec command is not for running scripts. pnpm exec is for running binaries from node_modules/.bin or just running any commands. For running scripts there is the pnpm run command.

@KSXGitHub KSXGitHub requested a review from zkochan August 1, 2023 11:25
@KSXGitHub
Copy link
Contributor Author

@zkochan Ideally, if there is a way to distinguish between pnpm $command and pnpm exec $command, I can create 2 hints that work for each case.

@zkochan
Copy link
Member

zkochan commented Aug 1, 2023

You should be able to distinguish if you pass some option to exec handler from the run handler.

@KSXGitHub
Copy link
Contributor Author

The CI always fail, but the logs doesn't tell me where.

@KSXGitHub
Copy link
Contributor Author

pnpm _test:  ERR_PNPM_META_FETCH_FAIL  GET http://localhost:7776/typescript: request to http://localhost:7776/typescript failed, reason: Socket timeout

I guess there's nothing we can do about it.

@zkochan
Copy link
Member

zkochan commented Aug 2, 2023

This test fails: "pnpm exec command not found"

Locally fails too.

@KSXGitHub
Copy link
Contributor Author

Oh. I think I know why I didn't found failed tests last time.

I searched for "Failed", but jest only outputs FAIL (without "ed").

@KSXGitHub
Copy link
Contributor Author

@zkochan Almost all tests have passed. The ones that failed are because of timeout.

This make me think: Currently, CI tests run in a matrix of 3 node versions ✕ 2 OSes ✕ 2 events = 12 parallel jobs. I think we can skip some of them to reduce timeouts. For example: On Windows, only node 20 runs, the rest is skipped. Another alternative is serialize the node versions: node 20 is tested first, then switch to 18, then 16.

@zkochan
Copy link
Member

zkochan commented Aug 3, 2023

We can serialize but it will probably make the wait longer.


export async function getNearestProgram (programName: string) {
try {
const binDir = path.join(process.cwd(), 'node_modules', '.bin')
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is not enough. You should check the list of commands in the current project's node_modules and in the node_modules of the workspace root.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

How to get the workspace root?

This is for a hint. If the code for getting workspace root turns out to be too complicated, I think we should not implement it. After all, an incomplete but correct hint is better than an incorrect hint and a greater possibility for bugs.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

workspaceDir or lockfileDir should be already passed through options.

err.hint = buildCommandNotFoundHint(params[0], (await readProjectManifestOnly(opts.dir)).scripts)
err.message = `Command "${params[0]}" not found`
if (opts.implicitlyFellbackFromRun) {
try {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

why is this try needed? There is already a try/catch in getNearestProgram

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Because I think readProjectManifestOnly interacts with the filesystem and therefore can fail.

@KSXGitHub KSXGitHub requested a review from zkochan August 3, 2023 10:35
let programList!: string[]
if (workspaceDir && workspaceDir !== dir) {
const workspaceBinDir = path.join(workspaceDir, 'node_modules', '.bin')
const programListExtension = await readdir(workspaceBinDir)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think it is OK if you just use readdir synchronously here and make the function synchronous. We don't care about the performance here so much.

performance is not critical here
const programList = readdirSync(binDir)
if (workspaceDir && workspaceDir !== dir) {
const workspaceBinDir = path.join(workspaceDir, 'node_modules', '.bin')
programList.push(...readdirSync(workspaceBinDir))
Copy link
Member

@zkochan zkochan Aug 3, 2023

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

it is not as easy as reading all files from the .bin directory. On Windows the same command will be duplicated a few times with different extensions: .exe, .cmd, maybe even .ps1. So we need to remove the extensions.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can the didYouMean function handle duplication, especially when we only need 1 result (the top result)?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't know if it can handle duplication. I would deduplicated before passing it the array

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It handles duplication just fine
Screenshot from 2023-08-03 20-14-59

@zkochan
Copy link
Member

zkochan commented Aug 3, 2023

There are linting errors.

@zkochan zkochan merged commit c5fbdb5 into main Aug 4, 2023
13 of 14 checks passed
@zkochan zkochan deleted the friendlier-err-msg-for-cmd-not-found branch August 4, 2023 00:18
@zkochan
Copy link
Member

zkochan commented Aug 4, 2023

This make me think: Currently, CI tests run in a matrix of 3 node versions ✕ 2 OSes ✕ 2 events = 12 parallel jobs. I think we can skip some of them to reduce timeouts. For example: On Windows, only node 20 runs, the rest is skipped. Another alternative is serialize the node versions: node 20 is tested first, then switch to 18, then 16.

The tests were mostly stable in the past but for the last 2-3 days the audit tests are failing very frequently. Maybe the npm registry is rate limiting requests to the audit endpoint.

@technophile-04
Copy link

Tysm @KSXGitHub and @zkochan 🙌 Really appreciate this !!

KSXGitHub added a commit that referenced this pull request Aug 7, 2023
@KSXGitHub KSXGitHub mentioned this pull request Aug 7, 2023
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.

None yet

3 participants