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

Run install and pack when fetching git dependencies with a prepare script #3553

Merged
merged 1 commit into from
Jun 20, 2017

Conversation

Volune
Copy link
Contributor

@Volune Volune commented Jun 1, 2017

Implement a new behaviour in GitFetcher to fix #2875 and match the new behaviour of npm 5 regarding git dependencies:

  • If the git repository's package.json does not contain a prepare script, no change of behaviour
  • If the git repository's package.json contains a prepare script:
    • clone the repository in a new temporary folder
    • run install command in that folder, excluding the prepublish script
    • run pack command and use the content of the generated tarball as result of GitFetcher
    • remove the temporary folder

(@zkat please let me know if you think it differs from npm)


At the moment, I open the PR mostly for review and comments. The PR still lacks documentation of the new behaviour.

Some implementation details:

  • There is a new boolean config.gitDependency to disable the prepublish script
  • The tarball generated if there is a prepare script uses the pack code. That means all the files are in a package/ folder. If generated from git archive, there are no package/ folder. To differentiate during the tarball extraction, when I generate a tarball from the pack command, I add a parameter in the header of the first file.
  • The tarballMirrorPath filename does not have extension. The tarballCachePath filename has extension tgz, but the content does not seem gzipped. I did not change these points.
  • The git archive may be run multiple times for one fetch. I replicated this behaviour, running the pack command multiple times. I did so to ensure a better error handling with minimal work. I think both cases can be optimised.

I added only one test. I'm thinking of improving it to ensure the prepublish script is not run.
I'm not sure what other tests are worth adding, while staying in the scope of this PR. (I don't want to fix all git-fetcher issues here).
By the way, if yarn supports a "git+file://" protocol, that would be useful for testing.

@zkat
Copy link
Contributor

zkat commented Jun 2, 2017

The algorithm specified seems to be right. Just make sure all the relevant lifecycle scripts are being run in the same order and such.

@Volune
Copy link
Contributor Author

Volune commented Jun 12, 2017

Tests updated, and I think they pass. (The master branch builds are failing, so I don't know how confident I should be about the tests)
Can someone point me to the documentation I need to update?

package.json Outdated
@@ -37,6 +37,7 @@
"strip-bom": "^3.0.0",
"tar-fs": "^1.15.1",
"tar-stream": "^1.5.2",
"test-js-git-repo": "https://github.com/Volune/test-js-git-repo",
Copy link
Member

Choose a reason for hiding this comment

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

not on npm?

Copy link
Member

Choose a reason for hiding this comment

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

Is this dependency needed?

@@ -842,7 +846,9 @@ export async function wrapLifecycle(config: Config, flags: Object, factory: () =
await config.executeLifecycleScript('postinstall');

if (!config.production) {
await config.executeLifecycleScript('prepublish');
if (!config.gitDependency) {
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 better to name it more generic disablePrepublish

@bestander
Copy link
Member

Thanks, @Volune, this looks legit and well thought through.

@Volune
Copy link
Contributor Author

Volune commented Jun 20, 2017

I cleaned the code according to comments, and rebased, so tests are passing now. Let me know if anything is missing.

@bestander bestander merged commit 5839c36 into yarnpkg:master Jun 20, 2017
@bestander
Copy link
Member

Great work, @Volune.
I think this feature is under documented now and many people might want to use it.
Do you think it will be possible for you to write a short blog post here https://github.com/yarnpkg/website/tree/master/_posts?

@Volune
Copy link
Contributor Author

Volune commented Jun 22, 2017

I'll look into it. It will take some time, I'm not used to writing.

@sammarks
Copy link

@bestander @Volune just checked out the new feature, and I'm wondering what your recommendation is for the following setup given the new functionality:

  • I have package-a that depends on package-b (through a git URL as package-b is not published to a registry).
  • package-a and package-b both use Babel (listed in devDependencies in both).
  • package-b's prepare script is: babel --optional runtime src -d dist

When installing the dependencies of package-a, I get an error message: babel: command not found

When I change to the temporary directory where the build is supposed to be happening before packing, it appears the node_modules/.bin directory is not created (but the dependencies are installed), which causes the reference to babel to be not found (since we can't expect babel to be installed globally).

Here's the output just for reference:

[1/4] Resolving packages...
[2/4] Fetching packages...
[1/4] Resolving packages...
[2/4] Fetching packages...
[3/4] Linking dependencies...
[4/4] Building fresh packages...
[1/2] ⠄ ngrok
[2/2] ⠄ fsevents
[-/2] ⠄ waiting...
[-/2] ⠄ waiting...
warning Error running install script for optional dependency: "/Users/sammarks/Library/Caches/Yarn/v1/.tmp/a339a22b5c259ad43ee07022e7413f6b.9abc356b9eaa1ddf2c84e3bec8f94758bb49eaf4.prepare/node_modules/fsevents: Command failed.\nExit code: 1\nCommand: sh\nArguments: -c node install\nDirectory: /Users/sammarks/Library/Caches/Yarn/v1/.tmp/a339a22b5c259ad43ee07022e7413f6b.9abc356b9eaa1ddf2c84e3bec8f94758bb49eaf4.prepare/node_modules/fsevents\nOutput:\nevents.js:160\n      throw er; // Unhandled 'error' event\n      ^\n\nError: spawn node-pre-gyp ENOENT\n    at exports._errnoException (util.js:1022:11)\n    at Process.ChildProcess._handle.onexit (internal/child_process.js:193:32)\n    $ babel --optional runtime src -d dist
sh: babel: command not found
error Command failed with exit code 127.
info Visit https://yarnpkg.com/en/docs/cli/upgrade for documentation about this command.

Could this be related to #2053?

I thought best to continue the discussion on this PR since it's recent and relevant, but I can create a new issue to house the discussion if you'd like.

@Volune
Copy link
Contributor Author

Volune commented Jun 26, 2017

@sammarks I can reproduce.
An option binLinks: true is missing when installing dependencies

I will prepare a PR with a fix and improved tests.

@bestander Do you or another contributor with good knowledge of the binLinks option know if it can have undesired side effects?

@ramasilveyra
Copy link
Contributor

ramasilveyra commented Jun 26, 2017

Hello! I just published a tool to create git tags for packages with build steps and monorepos packages https://github.com/ramasilveyra/gitpkg, my intention is to create very lightweight git tags that don't delay the install command and also be able to publish the gitpkg packages to the same repo.

Please if you want let me know what do you think about this approach.

Thanks!

@sammarks
Copy link

This is pretty cool @ramasilveyra! Looks like a nice alternative until we can nail down this issue.

@bestander
Copy link
Member

@ramasilveyra that looks exciting.
What can we do to make it work better with Yarn and Lerna?

@ramasilveyra
Copy link
Contributor

ramasilveyra commented Jun 26, 2017

@sammarks Sadly they are not the same 🙁 the approach choose by npm and yarn is to run the build scripts when you install the git dep, this could increase a lot the installation time. And it doesn't work with lerna git tags.

gitpkg publish at this moment does:

  1. Read and validate package.json.
  2. Run prepublish scripts.
  3. Prepare package: npm pack and untar tarball to temp dir.
  4. Upload package: create git tag from temp dir and push to resolved gitpkg registry.
  5. Run postpublish scripts.

The end result is a git tag with only the files needed, look at this https://github.com/ramasilveyra/public-registry/tree/gitpkg%401.0.0-beta.0-gitpkg


@bestander I believe that there is a lot of wins if the functionality of gitpkg gets integrated in yarn, npm and lerna/workspaces.

  • On the yarn and npm side:

    • publishConfig.registry: "publishConfig":{"registry":"http://my-internal-registry.local"} maybe it would be cool to check if that entry is a git url and if it is the publish command will create the git tag and push it to that repo.
    • semver ranges support: for example that the dep ramasilveyra/public-registry#gitpkg:^1.0.0-beta.0 (note the :^ chars) resolves to the git tag gitpkg@1.0.0-beta.0-gitpkg on git@github.com:ramasilveyra/public-registry.git.
  • On the lerna and workspaces:

    • That the bootstrap command creates the symlinks for the git tags deps too.

Is this something for a RFC? Is there a common place to discuss this ideas to get implemented on npm and yarn?

@bestander
Copy link
Member

@ramasilveyra, yes an RFC would be the right way to go.
Please consider a multistep approach, there are a lot of things that are not the best in publish experience and we are going to work on revamping it a lot, so big changes may be hard to consider against multiple other changes.

@masaeedu
Copy link

masaeedu commented Oct 6, 2017

@Volune Doing yarn add masaeedu/ava doesn't seem to result in the prepare script being executed with yarn 1.1.0. Is this feature perhaps part of a later milestone?

@rwjblue
Copy link
Contributor

rwjblue commented Oct 31, 2017

@masaeedu - I was just looking into a similar issue, in my case it turned out that the logic added in this PR only applies to git: references and not github: references. Once I changed my package.json to reference it via git: the prepare was properly being invoked.

@Volune
Copy link
Contributor Author

Volune commented Nov 10, 2017

@masaeedu @rwjblue
Yarn has a different behavior for "hosted git repositories"
I started a discussion a while ago regarding this issue on yarnpkg/rfcs#79, but it then happened that I didn't have time to take care of it. The idea is to use the same algorithm to install "hosted git repositories" and "git repositories"
I can't promise I'll have time to work on it soon.

vith added a commit to vith/uppy that referenced this pull request May 22, 2018
When a prepare script is defined, npm and yarn will build uppy
automatically if it's being depended on through a git URL.
This is useful when downstream projects don't want to wait for
the next release to be tagged.

See npm/npm#3055 (comment)
See also yarnpkg/yarn#3553
lovelypuppy0607 added a commit to lovelypuppy0607/yarn that referenced this pull request May 11, 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.

Installing package from github URL doesn't trigger prepublish script
7 participants