Skip to content

[node] support git sources #382

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 1 commit into
base: master
Choose a base branch
from
Open

Conversation

Ian2020
Copy link

@Ian2020 Ian2020 commented Nov 3, 2023

Fixes #381 and I hope will help #237 and #182.

I've added a new set of tests to cover more types of git references: https and ssh both with a commit hash and without. The tests cover all versions of the lockfile format v1,2,3.

In my testing I found that it doesn't appear to be necessary to patch package-lock.json (npm.py:444), so that has been removed. If there's another reason that is needed let me know but the tests all pass without it.

@refi64
Copy link
Collaborator

refi64 commented Nov 3, 2023

I think this has some overlap with #351 😅 see the discussion there.

@jwillikers
Copy link

Attempting to use this for the Stretchly flatpak, and I get the following error when building:

Downloading sources
Fetching git repo https://[email protected]/Jelmerro/dbus-final.git, ref refs/heads/master
remote: Total 0 (delta 0), reused 0 (delta 0), pack-reused 0
Fetching git repo https://github.com/hovancik/stretchly.git, ref refs/tags/v1.15.0
remote: Total 0 (delta 0), reused 0 (delta 0), pack-reused 0
Starting build of net.hovancik.Stretchly
Cache hit for dbus-glib, skipping build
Cache miss, checking out last cache hit
========================================================================
Building module stretchly in /home/jordan/Projects/net.hovancik.Stretchly/.flatpak-builder/build/stretchly-11
========================================================================
Note: switching to '3e43f60d80bbcdf0dfa0b59b838097d6af4d17ba'.

You are in 'detached HEAD' state. You can look around, make experimental
changes and commit them, and you can discard any commits you make in this
state without impacting any branches by switching back to a branch.

If you want to create a new branch to retain commits you create, you may
do so (now or later) by using -c with the switch command. Example:

  git switch -c <new-branch-name>

Or undo this operation with:

  git switch -

Turn off this advice by setting config variable advice.detachedHead to false

HEAD is now at 3e43f60 update deps
jq: error: Could not open file /var/home/jordan/Projects/net.hovancik.Stretchly/.flatpak-builder/build/stretchly-11/package.json: No such file or directory
/var/home/jordan/Projects/net.hovancik.Stretchly/.flatpak-builder/build/stretchly-11/flatpak-node/patch/app.sh: line 2: /var/home/jordan/Projects/net.hovancik.Stretchly/.flatpak-builder/build/stretchly-11/app/package.json.new: No such file or directory
mv: cannot stat '/var/home/jordan/Projects/net.hovancik.Stretchly/.flatpak-builder/build/stretchly-11/app/package.json.new': No such file or directory
Error: module stretchly: Child process exited with code 1

@Ian2020
Copy link
Author

Ian2020 commented Nov 12, 2023

There's something up with the paths here:

Building module stretchly in /home/jordan/Projects/net.hovancik.Stretchly/.flatpak-builder/build/stretchly-11

...but later the jq is looking in /var/home/... rather than /home/...

jq: error: Could not open file /var/home/jordan/Projects/net.hovancik.Stretchly/.flatpak-builder/build/stretchly-11/package.json: No such file or directory

Not sure where that /var prefix has come from.

@jwillikers
Copy link

jwillikers commented Nov 12, 2023

There's something up with the paths here:

Building module stretchly in /home/jordan/Projects/net.hovancik.Stretchly/.flatpak-builder/build/stretchly-11

...but later the jq is looking in /var/home/... rather than /home/...

jq: error: Could not open file /var/home/jordan/Projects/net.hovancik.Stretchly/.flatpak-builder/build/stretchly-11/package.json: No such file or directory

Not sure where that /var prefix has come from.

That's a thing on Fedora rpm-ostree systems. /home is a symlink to /var/home. This is documented here.

@jwillikers
Copy link

The manifest and everything can be found in this MR.

@Ian2020
Copy link
Author

Ian2020 commented Nov 12, 2023

Thanks, I'll take a look.

@Ian2020
Copy link
Author

Ian2020 commented Nov 13, 2023

Ok a few things going on here:

  • The inclusion of generated-sources.json in net.hovancik.Stretchly.yaml needs to come AFTER the stretchly source code is checked out, that's why package.json can't be found to be patched by generated-sources. This should fix the error you've reported but you'll next hit a ENOTCACHED error because...
  • We don't patch refs that looks like "github:user/project" and in Stretchly you have exactly this: "github:Jelmerro/dbus-final". I can't find in the package.json spec where this is allowed but it seems to be common searching across Github. So I think I have to add support for that to this PR.
  • The Stretchly project has two package.json files: one in / one in /app. Both would have to be patched for its flatpak build to succeed with git refs. The electron-builder cmd in the postinstall script seems to use the /app one. @jwillikers do you know why there are two package.json files?

@jwillikers
Copy link

Ok a few things going on here:

* The inclusion of `generated-sources.json` in [net.hovancik.Stretchly.yaml](https://github.com/flathub/net.hovancik.Stretchly/blob/master/net.hovancik.Stretchly.yaml) needs to come AFTER the stretchly source code is checked out, that's why package.json can't be found to be patched by generated-sources. This should fix the error you've reported but you'll next hit a ENOTCACHED error because...

* We don't patch refs that looks like "github:user/project" and in Stretchly you have exactly this: "github:Jelmerro/dbus-final". I can't find in the [package.json spec](https://docs.npmjs.com/cli/v9/configuring-npm/package-json) where this is allowed but it seems to be common searching across Github. So I think I have to add support for that to this PR.

* The Stretchly project has two `package.json` files: one in `/` one in `/app`. Both would have to be patched for its flatpak build to succeed with git refs. The `electron-builder` cmd in the postinstall script seems to use the `/app` one. @jwillikers do you know why there are two `package.json` files?

I've changed that order.
As for why there are two package.json files, I'm not sure.
@hovancik Could you shed some light on why there is app/package.json in addition to package.json?

@hovancik
Copy link

@jwillikers that's the structure from electron-builder: https://www.electron.build/tutorials/two-package-structure.html

I've tried in the past to remove 2 package structure, as they say it's not needed anymore but it did not work for me.

@Ian2020 Ian2020 force-pushed the gitrefs branch 2 times, most recently from 3cd5b3e to f28defd Compare November 16, 2023 14:20
@Ian2020
Copy link
Author

Ian2020 commented Nov 16, 2023

  • We don't patch refs that looks like "github:user/project" and in Stretchly you have exactly this: "github:Jelmerro/dbus-final". I can't find in the package.json spec where this is allowed but it seems to be common searching across Github. So I think I have to add support for that to this PR.

Ok I've added support for these 'shortcut' git urls to the PR. But we still need to overcome the 2 package structure in stretchly somehow.

@hovancik
Copy link

@Ian2020 should I try to remove 2package structure? It's been some time since last time I tried so I can try again if that helps

@Ian2020
Copy link
Author

Ian2020 commented Nov 16, 2023

@hovancik yes I think that would be simplest if you can, thanks.

@hovancik
Copy link

@Ian2020 done, new version is out.

@hovancik
Copy link

@Ian2020 actually scratch that, it does not work, will need to look into this more.

@Ian2020
Copy link
Author

Ian2020 commented Nov 20, 2023

Ok, despite that I can now successfully build Stretchly v1.15.1 as a flatpak. I created generated-sources.yaml using this PR against v1.15.1 of stretchly. Then copied that file into branch update-71b455c of https://github.com/flathub/net.hovancik.Stretchly and updated the source tag in the yaml to v1.15.1 and it builds a flatpak that I could run @hovancik @jwillikers

So I think this PR is doing what it should do for Stretchly to build as a flatpak, I hope you can sort the other issues in Stretchly. Let me know if you think there's anything more needed here.

@jwillikers
Copy link

jwillikers commented Nov 20, 2023

@Ian2020 One thing, I noticed that running flatpak-node-generator from this PR doesn't work when attempting to run it from a relative directory. I usually run flatpak-node-generator npm stretchly/package-lock.json --electron-node-headers with Stretchly checked out in the stretchly subdirectory in the Flatpak repository. I had to change into the stretchly subdirectory, generate the sources, and then move the generated file up one directory to make things work.

@hovancik
Copy link

@Ian2020 can you possibly try with this PR? hovancik/stretchly#1401

Seems like it was local issue only but would be nice to confirm build is ok after this change

@jwillikers
Copy link

@Ian2020 can you possibly try with this PR? hovancik/stretchly#1401

Seems like it was local issue only but would be nice to confirm build is ok after this change

@hovancik I just tested it and that commit builds and runs fine.

@hovancik
Copy link

Thanks, we are all good then, I guess.

p2004a added a commit to p2004a/info.beyondallreason.bar that referenced this pull request Mar 3, 2024
As part of the update, I had to refactor quite a bit of how the build
process works.

flatpak-node-generator is quite bugged:
 - Output `generated-source.json` expects the package to be in the main
   directory, so I've split the build into modules but still had to add
   `flatpak-node` exclusion to build
 - I had to patch locally flatpak/flatpak-builder-tools#382
   and use that because flatpak/flatpak-builder-tools#381
 - I've also run into flatpak/flatpak-builder-tools#377

I've also:
 - Made copying of addr2line dependencies more reliable
 - Merged the startup scripts into one
 - Added permission and setup for discord so that rich presence works
p2004a added a commit to p2004a/info.beyondallreason.bar that referenced this pull request Mar 3, 2024
As part of the update, I had to refactor quite a bit of how the build
process works.

flatpak-node-generator is quite bugged:
 - Output `generated-source.json` expects the package to be in the main
   directory, so I've split the build into modules but still had to add
   `flatpak-node` exclusion to build
 - I had to patch locally flatpak/flatpak-builder-tools#382
   and use that because flatpak/flatpak-builder-tools#381
 - I've also run into flatpak/flatpak-builder-tools#377

I've also:
 - Made copying of addr2line dependencies more reliable
 - Merged the startup scripts into one
 - Added permission and setup for discord so that rich presence works
p2004a added a commit to flathub/info.beyondallreason.bar that referenced this pull request Mar 3, 2024
As part of the update, I had to refactor quite a bit of how the build
process works.

flatpak-node-generator is quite bugged:
 - Output `generated-source.json` expects the package to be in the main
   directory, so I've split the build into modules but still had to add
   `flatpak-node` exclusion to build
 - I had to patch locally flatpak/flatpak-builder-tools#382
   and use that because flatpak/flatpak-builder-tools#381
 - I've also run into flatpak/flatpak-builder-tools#377

I've also:
 - Made copying of addr2line dependencies more reliable
 - Merged the startup scripts into one
 - Added permission and setup for discord so that rich presence works
@proletarius101
Copy link
Contributor

Hi @hfiguiere. Since you mentioned that you prefer to build from source, could this PR be merged?

@hfiguiere
Copy link
Collaborator

I don't maintain that module and I don't have the knowledge space.

@Ian2020
Copy link
Author

Ian2020 commented Apr 18, 2025

Today's commit addresses all issues raised so far. I can build both Stretchly and Pocket-Casts flatpaks no problem. Please let me know of any new problems. About these latest changes:

  • Added new tests and fixed previous tests to be more realistic - the lockfiles were hand-edited before but I regenerated them all with the right version of npm and yarn. This surfaced that we do need to patch package.json and package-lock.json but only for lockfile v1/npm v7. If support can ever be dropped for this old format lots of code can go. As such that code is all protected by a guard if lockfile_v1 in npm.py so it's clear what can be dropped in future.
  • Due to above we only add patch commands to the generated-sources.json when needed now - most projects which are NPM-16+ do not need them.
  • @hadess discovered an issue with transitive git dependencies in their flatpak. New tests have been added to cover this. Another entry was needed in the npm cache essentially. We also found a separate issue with electron forge: [electron] EAI_AGAIN on SHASUMS256.txt - recent electron versions ignore cache #452
  • Support for git refs in lockfile v1 files has been completed here also. This should have eliminated all "Don't know how to handle package" and "KeyError: 'integrity'" exceptions I hope. I found a few open bugs for those in this repo and have commented that this PR should help.

@Ian2020 Ian2020 changed the title [node] support git sources in lockfile v2 format [node] support git sources Apr 18, 2025
ProjectSynchro added a commit to ProjectSynchro/tech.feliciano.pocket-casts that referenced this pull request Apr 19, 2025
ProjectSynchro added a commit to ProjectSynchro/tech.feliciano.pocket-casts that referenced this pull request Apr 19, 2025
hadess pushed a commit to flathub/tech.feliciano.pocket-casts that referenced this pull request Apr 22, 2025
@hadess
Copy link
Contributor

hadess commented May 6, 2025

This is blocking updating pocket-casts:
flathub/tech.feliciano.pocket-casts#21
as @Ian2020's repo is outside the allowed organisations:

        "external-gitmodule-url-found: Only flatpak, flathub, and flathub-infra gitmodules are allowed in manifest git repo: ['https://github.com/Ian2020/flatpak-builder-tools.git']"

And it fixes issues that otherwise cause dependency generation not to work. Using Ian2020's repo didn't cause problems 2 weeks ago (flathub/tech.feliciano.pocket-casts#8 (comment)), but it now does.

Let me know if I should file an issue about this (which I definitely will if this cannot not be fixed quickly).

(Note to self, the repo to file it against is https://github.com/flathub-infra/vorarbeiter/)

@salim-b
Copy link
Contributor

salim-b commented May 6, 2025

@hadess Instead of using Ian2020's fork, you could just reference this PR. To e.g. install it via pipx:

pipx install --force git+https://github.com/flatpak/flatpak-builder-tools.git@refs/pull/382/head#subdirectory=node

@bbhtt
Copy link
Collaborator

bbhtt commented May 7, 2025

External gitmodule check was added to linter several months ago and it doesn't have anything to do with vorarbeiter.

@bbhtt
Copy link
Collaborator

bbhtt commented May 7, 2025

Is the work here still ongoing? If not if you can fix the conflict, rebase and clear up the history it'd be nice.

I think this has some overlap with #351 😅 see the discussion there.

@refi64 Seems like this has progressed a lot more than the other PR. Any chance you can review it?

@bbhtt bbhtt added the Need Rebase The PR need rebase before merging label May 7, 2025
hadess added a commit to flathub/tech.feliciano.pocket-casts that referenced this pull request May 7, 2025
Submodules outside the sanctioned organisations are not allowed, so
install the fixed flatpak-node-generator through its fork directly.

See flatpak/flatpak-builder-tools#382 (comment)
hadess added a commit to flathub/tech.feliciano.pocket-casts that referenced this pull request May 7, 2025
Submodules outside the sanctioned organisations are not allowed, so
install the fixed flatpak-node-generator through its fork directly.

See flatpak/flatpak-builder-tools#382 (comment)
@hadess
Copy link
Contributor

hadess commented May 7, 2025

@hadess Instead of using Ian2020's fork, you could just reference this PR. To e.g. install it via pipx:

pipx install --force git+https://github.com/flatpak/flatpak-builder-tools.git@refs/pull/382/head#subdirectory=node

This worked (and I learnt something), thanks!

hadess added a commit to flathub/tech.feliciano.pocket-casts that referenced this pull request May 7, 2025
Submodules outside the sanctioned organisations are not allowed, so
install the fixed flatpak-node-generator through its fork directly.

See flatpak/flatpak-builder-tools#382 (comment)
@Ian2020
Copy link
Author

Ian2020 commented May 7, 2025

if you can fix the conflict, rebase and clear up the history it'd be nice.

@bbhtt can do, probably be next week now

@refi64 refi64 self-assigned this May 12, 2025
@refi64
Copy link
Collaborator

refi64 commented May 12, 2025

will take a look again sometime this week

@Ian2020 Ian2020 requested a review from a team as a code owner May 15, 2025 10:10
@github-actions github-actions bot removed the npm label May 15, 2025
@Ian2020
Copy link
Author

Ian2020 commented May 15, 2025

if you can fix the conflict, rebase and clear up the history it'd be nice.

Done.

self.gen.add_git_source(source.url, source.commit, path)

url = urllib.parse.urlparse(source.url)
Copy link
Collaborator

@bbhtt bbhtt May 15, 2025

Choose a reason for hiding this comment

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

is the git source here always going to github.com and gitlab.com? because only those two seems to be handled.

Copy link
Author

Choose a reason for hiding this comment

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

When I was working on this github and gitlab were the only two forges on which I could easily find packages to test, however npm seems to also support bitbucket and gists from their docs: https://docs.npmjs.com/cli/v11/commands/npm-install.

I agree the code should be fixed though as any other url will fail. Is it ok to throw an exception if it's not a url we can handle? My suspicion is that gitlab/github covers 80%+ of use cases. If anyone can provide a failing url it could be addressed in future as we need to determine where to get the tarball from and how npm wants it indexed.

Copy link
Collaborator

Choose a reason for hiding this comment

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

s it ok to throw an exception if it's not a url we can handle?

Ok let's do that for now.

Copy link
Collaborator

Choose a reason for hiding this comment

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

I believe the full list of stuff to handle would be in: https://github.com/npm/hosted-git-info

Co-authored-by: Danilo Bargen <[email protected]>
Co-authored-by: Jordan Williams <[email protected]>
# with https://[email protected]/ianstormtaylor/to-camel-case.git
# for git+ssh URLs
if ':' in new_url.netloc:
netloc_split = new_url.netloc.split(':')
Copy link
Collaborator

Choose a reason for hiding this comment

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

this will break if there are extra colons (I mean, there really shouldn't be, but alas)

Suggested change
netloc_split = new_url.netloc.split(':')
netloc_split = new_url.netloc.split(':', 1)

(note that the branch immediately above also handles this, but...it does so kinda poorly, by comparison)

source = ResolvedSource(
resolved=info['resolved'], integrity=integrity
)
if info['resolved'].startswith('git+'):
Copy link
Collaborator

Choose a reason for hiding this comment

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

info['resolved'] should probably be in an intermediate variable so the same string constant isn't copy-pasted in 3 places. (this is also something the rest of the code admittedly does poorly.)

self.gen.add_git_source(source.url, source.commit, path)

url = urllib.parse.urlparse(source.url)
Copy link
Collaborator

Choose a reason for hiding this comment

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

I believe the full list of stuff to handle would be in: https://github.com/npm/hosted-git-info

@@ -0,0 +1,94 @@
{
Copy link
Collaborator

Choose a reason for hiding this comment

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

very nice to see the tests for this!

),
commands=[
provider_factory_spec.install_command,
"""node -e 'require("array-range");require("is-empty-object");require("is-number");require("person-lib");require("to-camel-case");require("to-capital-case");require("to-no-case");require("to-space-case");require("@flatpak-node-generator-tests/subdir").sayHello()'""",
Copy link
Collaborator

Choose a reason for hiding this comment

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

this is...a bit horrifying, you could pull out the JS into a top-level multiline string constant, or just stick it in the shared datadir with the package.json (we don't really do that anywhere else, but the other lines are also much shorter!).

url = urllib.parse.urlparse(source.url)
if url.netloc == '[email protected]' or url.netloc == 'github.com':
url = url._replace(
netloc='codeload.github.com', path=re.sub('.git$', '', url.path)
Copy link
Collaborator

Choose a reason for hiding this comment

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

should the . in .git here and below be escaped? might be useful to extract this into a separate git_suffix = re.compile(r'\.git$') and then use that for the substitutions below.

netloc='codeload.github.com', path=re.sub('.git$', '', url.path)
)
tarball_url = url._replace(
path=re.sub('$', f'/tar.gz/{source.commit}', url.path)
Copy link
Collaborator

Choose a reason for hiding this comment

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

is this just...replacing the empty string? couldn't it just be a string concat then? ditto for gitlab.com below.

self.gen.add_git_source(source.url, source.commit, path)

url = urllib.parse.urlparse(source.url)
if url.netloc == '[email protected]' or url.netloc == 'github.com':
Copy link
Collaborator

Choose a reason for hiding this comment

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

could be url.hostname == 'github.com' (and maybe also check url.username in ('git', '') or similar? do you know if that's semantically important in any way? if not, then just checking the hostname is a bit cleaner.) ditto for the gitlab.com check below.

@@ -208,7 +206,7 @@ def __init__(
self.all_lockfiles: Set[Path] = set()
# Mapping of lockfiles to a dict of the Git source target paths and GitSource objects.
self.git_sources: DefaultDict[
Path, Dict[Path, GitSource]
Path, Dict[Path, Tuple[str, GitSource]]
Copy link
Collaborator

Choose a reason for hiding this comment

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

should update the comment above to indicate what this is, since it's no longer just a GitSource. or maybe the value a dataclass like NamedGitSource or something instead, to make it clearer what the str is (and then you can just use attributes to get the innards, instead of having to do unpacking assignments)

# Don't use with_extension to avoid problems if the package has a . in its name.
patch_dest = patch_dest.with_name(patch_dest.name + '.sh')
with open(lockfile) as fp:
lockfile_v1 = json.load(fp)['lockfileVersion'] == 1
Copy link
Collaborator

Choose a reason for hiding this comment

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

this could probably be saved inside self.git_sources' values, right? and then no need to re-open the lockfile here.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Need Rebase The PR need rebase before merging node
Projects
None yet
Development

Successfully merging this pull request may close these issues.

[node] NotImplementedError: Git sources in lockfile v2 format are not supported yet
10 participants