pulsar-edit / ppm

Pulsar Package Manager
MIT License
35 stars 14 forks source link

CI: Work around a weird bug in Yarn v1.x #101

Closed DeeDeeG closed 1 year ago

DeeDeeG commented 1 year ago

Install a global copy of node-gyp for Yarn to use. Works around a really weird bug.

Details of the bug (and explanation of the workaround) below:


Yarn install in Yarn v1.x has a really obscure bug that only happens for certain repos that "require node-gyp", and even then, only if the globally installed copy of npm is v9.7.2 or newer (or if there is no global copy of npm installed, which is quite rare.)

In these unusual (and complex to describe) circumstances, this repo's postinstall script will not run, due to the bug in Yarn v1.x.

Unfortunately for us, the versions of npm Yarn v1.x is incompatible with in this manner, npm v9.7.2 or newer, are bundled with NodeJS v18.18.0 and newer, as well as NodeJS v20.4.0 and newer. So, this is the new normal.

Working around this is easy IRL. Yarn globally installs a copy of node-gyp it can use the first time, so this is a one-time issue. The only problem is it not handing off to its own package lifecycle script handler afterwrd, thus skipping the postinstall.

So, to work around this problem IRL, simply run 'yarn install' a second time, or run 'yarn postinstall' once, in the ppm repo.

ppm repo still needs a workaround (like this commit) to keep testing in CI with newer versions of Node. Either we install older npm in CI (not a sustainable fix, since this will become incompatible with newer versions of Node eventually), or give Yarn a copy of node-gyp it can use, (anything to ensure the postinstall script actually runs), which is what this commit does.

(We could just manually run 'yarn postinstall' after the install, but this commit's approach is tidier, faster on machines where the workaround isn't needed, and clearer about what is going on.)

(We may also want to consider switching to the newer versions of Yarn, which are actively maintained. Yarn v1.x doesn't accept bug fixes anymore, only "maybe" critical security fixes. Something like this could happen again, and we'd be on our own, again.)

DeeDeeG commented 1 year ago

Repeating myself a fair bit, but doing this a bit more informally to get my thoughts across (feel free to skip or skim, I bolded key parts and context for the repo, and so on):

This fixes the weird CI failures in the most recent versions of NodeJS 18 for this repo. And yeah, this turned about to be a really weird one, even after I mostly understand what's happening here.

Looks like Yarn v1.x does some funky stuff[1],[2] that's meant to find node-gyp either on the PATH, or as bundled with the copy of npm bundled with NodeJS. (Unlike npm, Yarn does not bundle its own copy of node-gyp out of the box).

If Yarn v1.x can't find node-gyp in any of those places, and it believes it needs a copy, it will add a copy of node-gyp in its own special bins dir.

That's all well and good, and it works in and of itself, but what's not good is that this happens during Yarn's package lifecycle script handling, like just before the postinstall script would normally run, and it doesn't properly hand back off to the lifecycle script handling code. It just effectively exits that code early right after downloading its own copy of node-gyp to use.

So... this PR simply does the "grab a copy of node-gyp for Yarn to use" thing early, before the bug in Yarn's package lifecycle script code can be hit. The postinstall script runs as normal with this workaround. CI should finally be green again for us.

This only started happening as of npm 9.7.2,[3] which is included in NodeJS 18.18.0+,[4] and NodeJS 20.4.0+.[5] That's because the subdir of npm (bin/node-gyp-bin), which is where Yarn v1.x checks for npm's copy of node-gyp, was deleted in npm v9.7.2.

We'll probably want to look at migrating to newer Yarn at this point, IMO, since Yarn v1.x isn't accepting bug fixes anymore, only maybe (?) critical security fixes. Hopefully the transition path is decently smooth now? But I don't want to debug obscure things like this again in the future, knowing there's no real fix coming, only strange workarounds. (And boy was this a weird one to get to the bottom of. Took a while, too.)

By the way, this would have no merge conflicts with https://github.com/pulsar-edit/ppm/pull/95, so there should be no worries about merging this before that one if need be to get back to green/passing CI for this repo.

DeeDeeG commented 1 year ago

This is definitely one of those "really small changes I went overboard about writing the PR for and explaining it to death" things.

I do like to get my thoughts down while they're fresh once I've tracked down a weird and obscure problem, or done my research on something I usually don't have to think hard about.

But this is another real simple PR that I hope will be easy to review if looking at the diff alone.

Sorry about the walls of text. I hope they are informative to anyone who reads them, and inoffensive to anyone who skims or skips them! If anything, I get the satisfaction of being thorough.

DeeDeeG commented 1 year ago

I'd be seriously curious on how this discovery came about.

I have a log of stuff I tried: https://github.com/DeeDeeG/ppm/commits/oldddd-node-18-npm-fix

I never write blog posts, so this is about as close as I'm gonna get lol. Since you asked.

It was a journey, I might as well memorialize it here before I (as quick as I can) forget all this crazy stuff, lol. I mean, only half joking, this is pretty useless knowledge other than to know "it needs a workaround" and "here's the workaround". Heh.

And that's about as much as I should write about this, actually debatably I could have profitably stopped writing a lot earlier, LMAO. But I do like write-ups. I think that's pretty abundantly apparent by now, lol.

DeeDeeG commented 1 year ago

I believe #95 can be left alone, I can do a run on another branch maybe just to confirm it works well on NodeJS 18, but 2colours has been through a lot, another merge or rebase on that PR feels too much disruption to their PR (in what is merely my personal feeling about this rather subjective matter).

DeeDeeG commented 1 year ago

Thanks for the review-approve, I'm merging this!