Skip to content

fix: don't assume commands end with .cmd on Windows #9026

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

Open
wants to merge 3 commits into
base: master
Choose a base branch
from

Conversation

Almighty-Alpaca
Copy link

@Almighty-Alpaca Almighty-Alpaca commented Apr 11, 2025

Fixed first two issues of #9020. If an executable cannot be found it now looks like this:

  • electron-builder  version=26.0.12 os=10.0.26100
  • loaded configuration  file=<project_path>\electron-builder.yml
  • writing effective config  file=dist\builder-effective-config.yaml
  • skipped dependencies rebuild  reason=npmRebuild is set to false
  • packaging       platform=win32 arch=x64 electron=35.1.5 appOutDir=dist\win-unpacked

<project_path>\node_modules\builder-util\src\util.ts:94
  throw new Error(`Cannot find executable for ${options.name}, tried: ${executables.join(", ")}`)
        ^
Error: Cannot find executable for npm, tried: npm, npm.cmd
    at findExecutable (<project_path>\node_modules\builder-util\src\util.ts:94:9)
    at processTicksAndRejections (node:internal/process/task_queues:105:5)

I was a bit surprised that the logic to find the package manager executables was duplicated (util/yarn.ts and node-modules-collector). But since I'm not familiar with how electron-builder works internally I didn't try to refactor anything regarding this

Copy link

changeset-bot bot commented Apr 11, 2025

🦋 Changeset detected

Latest commit: 883a9f3

The changes in this PR will be included in the next version bump.

This PR includes changesets to release 10 packages
Name Type
app-builder-lib Patch
builder-util Patch
dmg-builder Patch
electron-builder-squirrel-windows Patch
electron-builder Patch
electron-forge-maker-appimage Patch
electron-forge-maker-nsis-web Patch
electron-forge-maker-nsis Patch
electron-forge-maker-snap Patch
electron-publish Patch

Not sure what this means? Click here to learn what changesets are.

Click here if you're a maintainer who wants to add another changeset to this PR

@Almighty-Alpaca
Copy link
Author

It seems like some tests are currently failing, I'll take a look

@Almighty-Alpaca
Copy link
Author

Almighty-Alpaca commented Apr 11, 2025

Unfortunately locally on my machine 1/4 of all tests fail (even without these changes), so it's a bit hard right now to debug this. The failures on my machine are totally unrelated to the ones here though. Is there any way to get a Windows environment where these tests run consistently that isn't CI? Normally I'd use a container for this but since we are talking about Windows...

@mmaietta
Copy link
Collaborator

@Almighty-Alpaca does TEST_FILES=BuildTest,oneClickInstallerTest pnpm ci:test work for you? Some tests are scoped specifically to certain OS's, but those two files should allow you to test your implementation on Windows

@Almighty-Alpaca Almighty-Alpaca force-pushed the fix/windows-executables branch from 4e2974f to 785305b Compare April 13, 2025 14:18
@Almighty-Alpaca Almighty-Alpaca force-pushed the fix/windows-executables branch from 785305b to 541b2d8 Compare April 13, 2025 14:32
@Almighty-Alpaca
Copy link
Author

Almighty-Alpaca commented Apr 13, 2025

@mmaietta thanks that really helped.

I learned a few intricacies of exec() vs execFile() debugging this. Turns out that on Windows (and only on Windows) you need to use either exec() or execFile(..., ..., {shell: true}) to execute .bat/.cmd script, which the npm/Yarn/PnPm wrappers from e.g. corepack are. The extension in the PATHEXT environment variable will also only be respected when executing through a shell.

I've fixed the implementation to use {shell: true} like most places already do and rebased everything onto the current master.

The downside to this is that now when findExecutable() succeeds because of PATHEXT being used in the shell, the returned command will also only ever work with {shell: true}. I've therefore changed the implementation to favor the operating specific executables first, which will make sure that e.g. npm.cmd is tried before the more generic npm.

@Almighty-Alpaca
Copy link
Author

Almighty-Alpaca commented Apr 13, 2025

Upon further inspection this doesn't work correctly in all cases yet, I'll try to investigate further

As a side note un- and then reinstalling the whole node/npm/yarn/pnpm in different ways for testing slightly different implementations kinda sucks, I don't know of a better way to test this though...

@mmaietta
Copy link
Collaborator

As a side note un- and then reinstalling the whole node/npm/yarn/pnpm in different ways for testing slightly different implementations kinda sucks, I don't know of a better way to test this though...

Yeah, I don't know of another way without committing the node_modules for each test directly to the repo. It was only recently that I added lockfile snapshots to prevent transient dependencies getting version bumped and causing test cases to randomly break.

For linux docker tests, you could point mount -v your yarn/npm/pnpm cache directly into the container though to potentially speed things up. Haven't tested it myself yet, but could be worthwhile adding to the test-linux cmd

@mmaietta
Copy link
Collaborator

@Almighty-Alpaca do you have a sample repro repo for this that I can take a look at? I can try and help by picking up this PR to work with your setup

@Almighty-Alpaca
Copy link
Author

Almighty-Alpaca commented Apr 25, 2025

@Almighty-Alpaca do you have a sample repro repo for this that I can take a look at? I can try and help by picking up this PR to work with your setup

Thanks, that would be awesome. Unfortunately I've been a bit busy with other deadlines and reverted to v26.0.3 for now.

Due to this being an environment issue more that a project setup issue I don't have a repro repository, but on Windows you can recreate the problem using one of the examples from the docs, e.g. by running these commands (I tested this in a fresh VM just now, but any Windows machine that doesn't already have any other NodeJS environment installed that could interfere should work):

# Install proto https://moonrepo.dev/docs/proto/install#windows
irm https://moonrepo.dev/install/proto.ps1 | iex
& "$HOME\.proto\bin\proto.exe" setup

# If on a fresh machine install Git
winget install git.git

### Reopen terminal here to reload environment variables

# Install Node and Yarn using proto
proto install node latest
proto install yarn latest

# Clone example repo and update electron-builder to problematic version
git clone https://github.com/electron-vite/electron-vite-react
cd electron-vite-react
Add-Content -Value 'nodeLinker: node-modules' -Path .yarnrc.yml # Add Yarn workaround
yarn add --dev electron-builder@26.0.13

# Runs into issue 1 from #9020 as there is no npm installed
yarn build

# Install npm and reinstall packages with npm
proto install npm 10.9.2
Remove-Item -Recurse .\node_modules\
npm i

# Runs into issue 2 from #9020 as npm is installed as npm.exe not npm.cmd
npm run build

# See that the npm shim is named npm.exe
where.exe npm
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment