lerna-lite / lerna-lite

Subset of Lerna in a smaller & more modular project. Helps manage and publish multiple packages in a monorepo/workspace structure
MIT License
460 stars 32 forks source link

--sync-workspace-lock issue #877

Closed achille1789 closed 2 weeks ago

achille1789 commented 3 weeks ago

Describe the bug

A short overview first: I have a"postinstall" script that runs "husky install" (Husky is npm package). Using Husky, I run a script on the git "pre-commit" hook that checks the name of the branch and fails the commit in case the branch name is not formatted as expected (branch "main" fails the script). When I merge a branch on "main", the pipeline:

  1. sets this env vars: HUSKY=0
  2. installs the dependencies but because of the above env var, Husky is not initialised
  3. runs "lerna version"
  4. lerna bumps the version, updates the package-lock.json, commits and pushes the tag

Everything works as expected as long as I don't set syncWorkspaceLock: true in lerna.json (I use npm). Setting the flag to true, Lerna fails to commit because the "pre-commit" hook is triggered and the script throws an error because the branch name is "main".

Expectation

As suggested by the docs, I should use syncWorkspaceLock: true and Lerna should be able to commit.

Reproduction

Should be possible to reproduce the issue following my bug description.

Lerna config and logs

lerna.json

```json { "$schema": "node_modules/@lerna-lite/cli/schemas/lerna-schema.json", "version": "independent", "command": { "version": { "allowBranch": [ "main" ], "message": "chore(release): [ci skip] version bump", "conventionalCommits": true, "private": false } }, "yes": true, "changelogPreset": "./changelog-preset.config.js", "ignoreChanges": [ "**/Tests/**" ], "useWorkspaces": true } ```

lerna-debug.log

```txt ```

Environment Info

System: OS: macOS 14.5 CPU: (10) arm64 Apple M1 Pro Memory: 258.52 MB / 32.00 GB Shell: 5.9 - /bin/zsh Binaries: Node: 20.12.2 - ~/.nvm/versions/node/v20.12.2/bin/node npm: 10.5.0 - ~/.nvm/versions/node/v20.12.2/bin/npm Browsers: Chrome: 125.0.6422.176 Safari: 17.5 npmPackages: @lerna-lite/cli: ^3.5.1 => 3.5.1 @lerna-lite/run: ^3.5.1 => 3.5.1 @lerna-lite/version: ^3.5.2 => 3.5.2

Used Package Manager

npm

Validations

ghiscoding commented 3 weeks ago

I don't use Husky and don't have much knowledge about it, all I know is that below is what the npm lock file update runs. This flag was created to sync the lock file and that's all it should do. I added this flag to replace the previous and often failing implementation that tried to modify the lock file directly, the new sync flag is simply calling whichever package manager is installed to do the synching of the lock file (we should always rely on the package manager instead of trying to modify the lock file ourselves which is a bad idea). It does accept extra npm arguments if that helps.

https://github.com/lerna-lite/lerna-lite/blob/3204e062cb42578fddd5e8314b0c73d230d2fac8/packages/version/src/lib/update-lockfile-version.ts#L161-L181

Looking at the Version command, the sync seems to happen before the version and postversion lifecycles.

https://github.com/lerna-lite/lerna-lite/blob/3204e062cb42578fddd5e8314b0c73d230d2fac8/packages/version/src/version-command.ts#L782-L793

Then the version lifecycle is called later at line 838 and the postversion lifecycle is at line 860. The order of the lifecycle for the lock file is exactly the same as the original Lerna when it tried to update the lock file directly. From what I can remember, the lock file must be updated before being added to the list of git changes and so before the version lifecycle

https://github.com/lerna-lite/lerna-lite/blob/3204e062cb42578fddd5e8314b0c73d230d2fac8/packages/version/src/version-command.ts#L836-L862

So I don't know what your problem is since I don't use that kind of scripts on my side and I can't provide much more info. The only suggestion I could give is to look at the available version Lifecycle Scripts and maybe use a different one if that helps, otherwise I have no idea. Another suggestion might be to change the logs to verbose and see what commands it runs, and also maybe try it via the --dry-run mode which might help to see what runs.

in my case I don't need to use this sync flag because I use the workspace: protocol which technically speaking never changes the lock file neither git changes because workspace: are only replaced at publish time. However that is not true for npm and that is why this sync flag was created. I know the Jest project use this flag with Lerna-Lite but they also switched to workspace: not long after so they probably don't need the flag either.

EDIT

Actually someone did install Husky for conventional commits checks in one of my project and I also had to set HUSKY: 0 because it failed without it but that's all I did and it all worked correctly after. Note that I use dynamic Lerna version command because I have a checkbox in my release to sometime test it in dry-run mode and I build the Lerna query dynamically

(ref release.yml)

- name: Lerna Version 🏷️
        env:
          GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
          NODE_AUTH_TOKEN: ${{ secrets.NPM_TOKEN }}
          NPM_CONFIG_PROVENANCE: true
          HUSKY: 0
        run: |
          git config --global user.name "${{ github.actor }}"
          git config --global user.email "${{ github.actor }}@users.noreply.github.com"
          pnpm whoami
          pnpm exec ${{ env.LERNA_VERSION_QUERY }}
achille1789 commented 2 weeks ago

Hi @ghiscoding many thanks for your quick and detailed response!

I investigated a little bit and basically the problem is that npm install --package-lock-only runs all the npm hooks, so setting "syncWorkspaceLock: true" was causing husky to be initialised, because HUSKY env var was already out of scope when this command run. Leaving "syncWorkspaceLock: false" doesn't run npm install --package-lock-only so there is no problem.

I bypassed the issue moving HUSKY env var in the parent scope and now even setting "syncWorkspaceLock: true", when Lerna runs npm install --package-lock-only the HUSKY var is set and Husky is not initialised.

Anyway, looking at the original Lerna code: https://github.com/lerna/lerna/blob/7bd983510110d00d9c3db94fb99f74773ab75d40/libs/commands/version/src/index.ts?#L811-L827

it is running npm install --package-lock-only --ignore-scripts that prevents to run the NPM hooks. So I don't know if it worths to do the same, just to avoid any issue in future when people migrate from Lerna to Lerna-lite

ghiscoding commented 2 weeks ago

Anyway, looking at the original Lerna code: https://github.com/lerna/lerna/blob/7bd983510110d00d9c3db94fb99f74773ab75d40/libs/commands/version/src/index.ts?#L811-L827

it is running npm install --package-lock-only --ignore-scripts that prevents to run the NPM hooks. So I don't know if it worths to do the same, just to avoid any issue in future when people migrate from Lerna to Lerna-lite

hmm there is actually a CLI option runScriptsOnLockfileUpdate to pass for the command to ignore script, I guess we could add the same option in here too

ghiscoding commented 2 weeks ago

Side note and as mentioned above you could also add the ignore script yourself via the npmClientArgs in the Lerna version command, so I guess something like this should work (untested), you can refer to the docs --npm-client-args

{
  "command": {
    "version": {
      "npmClientArgs": ["--ignore-scripts"]
    }
}

that is until I have time to add the other skip script run option. or you could also contribute the missing option 😉

achille1789 commented 2 weeks ago

Side note and as mentioned above you could also add the ignore script yourself via the npmClientArgs in the Lerna version command, so I guess something like this should work (untested), you can refer to the docs --npm-client-args

{
  "command": {
    "version": {
      "npmClientArgs": ["--ignore-scripts"]
    }
}

that is until I have time to add the other skip script run option. or you could also contribute the missing option 😉

Hi @ghiscoding, as I said, I already solved my problem but I will keep in mind this as future reference! Thanks

ghiscoding commented 1 week ago

latest release v3.6.0 will no longer run scripts when npm install runs, the behavior is now the same as Lerna and if you want to run the scripts then the new option runScriptsOnLockfileUpdate will let you do that (which is also the same option as Lerna)