Skip to content

Commit

Permalink
feat(version): reify on workspace version change (#4588)
Browse files Browse the repository at this point in the history
Adds a minimalistic reify step that updates the installed tree after a
version change within one of the configured workspaces when using any
of the workspaces config options.

It's also possible to use the `--save` config option in order to
auto update semver ranges of dependencies declarations accross dependent
`package.json` files.

Fixes: #3403
Relates to: npm/rfcs#556
Relates to: #3757
Relates to: #4193
  • Loading branch information
ruyadorno committed Mar 24, 2022
1 parent 362831c commit 723a091
Show file tree
Hide file tree
Showing 11 changed files with 297 additions and 9 deletions.
11 changes: 11 additions & 0 deletions docs/content/commands/npm-version.md
Original file line number Diff line number Diff line change
Expand Up @@ -144,6 +144,17 @@ This value is not exported to the environment for child processes.
<!-- automatically generated, do not edit manually -->
<!-- see lib/utils/config/definitions.js -->

#### `workspaces-update`

* Default: true
* Type: Boolean

If set to true, the npm cli will run an update after operations that may
possibly change the workspaces installed to the `node_modules` folder.

<!-- automatically generated, do not edit manually -->
<!-- see lib/utils/config/definitions.js -->

#### `include-workspace-root`

* Default: false
Expand Down
11 changes: 11 additions & 0 deletions docs/content/using-npm/config.md
Original file line number Diff line number Diff line change
Expand Up @@ -1823,6 +1823,17 @@ This value is not exported to the environment for child processes.
<!-- automatically generated, do not edit manually -->
<!-- see lib/utils/config/definitions.js -->

#### `workspaces-update`

* Default: true
* Type: Boolean

If set to true, the npm cli will run an update after operations that may
possibly change the workspaces installed to the `node_modules` folder.

<!-- automatically generated, do not edit manually -->
<!-- see lib/utils/config/definitions.js -->

#### `yes`

* Default: null
Expand Down
35 changes: 35 additions & 0 deletions lib/commands/version.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,9 @@ const { resolve } = require('path')
const { promisify } = require('util')
const readFile = promisify(require('fs').readFile)

const Arborist = require('@npmcli/arborist')
const reifyFinish = require('../utils/reify-finish.js')

const BaseCommand = require('../base-command.js')

class Version extends BaseCommand {
Expand All @@ -17,6 +20,7 @@ class Version extends BaseCommand {
'sign-git-tag',
'workspace',
'workspaces',
'workspaces-update',
'include-workspace-root',
]

Expand Down Expand Up @@ -81,15 +85,18 @@ class Version extends BaseCommand {
async changeWorkspaces (args, filters) {
const prefix = this.npm.config.get('tag-version-prefix')
await this.setWorkspaces(filters)
const updatedWorkspaces = []
for (const [name, path] of this.workspaces) {
this.npm.output(name)
const version = await libnpmversion(args[0], {
...this.npm.flatOptions,
'git-tag-version': false,
path,
})
updatedWorkspaces.push(name)
this.npm.output(`${prefix}${version}`)
}
return this.update(updatedWorkspaces)
}

async list (results = {}) {
Expand Down Expand Up @@ -129,6 +136,34 @@ class Version extends BaseCommand {
}
return this.list(results)
}

async update (args) {
if (!this.npm.flatOptions.workspacesUpdate || !args.length) {
return
}

// default behavior is to not save by default in order to avoid
// race condition problems when publishing multiple workspaces
// that have dependencies on one another, it might still be useful
// in some cases, which then need to set --save
const save = this.npm.config.isDefault('save')
? false
: this.npm.config.get('save')

// runs a minimalistic reify update, targetting only the workspaces
// that had version updates and skipping fund/audit/save
const opts = {
...this.npm.flatOptions,
audit: false,
fund: false,
path: this.npm.localPrefix,
save,
}
const arb = new Arborist(opts)

await arb.reify({ ...opts, update: args })
await reifyFinish(this.npm, arb)
}
}

module.exports = Version
10 changes: 10 additions & 0 deletions lib/utils/config/definitions.js
Original file line number Diff line number Diff line change
Expand Up @@ -2270,6 +2270,16 @@ define('workspaces', {
},
})

define('workspaces-update', {
default: true,
type: Boolean,
description: `
If set to true, the npm cli will run an update after operations that may
possibly change the workspaces installed to the \`node_modules\` folder.
`,
flatten,
})

define('yes', {
default: null,
type: [null, Boolean],
Expand Down
2 changes: 2 additions & 0 deletions tap-snapshots/test/lib/commands/config.js.test.cjs
Original file line number Diff line number Diff line change
Expand Up @@ -155,6 +155,7 @@ exports[`test/lib/commands/config.js TAP config list --json > output matches sna
"which": null,
"workspace": [],
"workspaces": null,
"workspaces-update": true,
"yes": null,
"metrics-registry": "https://registry.npmjs.org/"
}
Expand Down Expand Up @@ -308,6 +309,7 @@ viewer = "{VIEWER}"
which = null
workspace = []
workspaces = null
workspaces-update = true
yes = null
; "global" config from {GLOBALPREFIX}/npmrc
Expand Down
94 changes: 94 additions & 0 deletions tap-snapshots/test/lib/commands/version.js.test.cjs
Original file line number Diff line number Diff line change
@@ -0,0 +1,94 @@
/* IMPORTANT
* This snapshot file is auto-generated, but designed for humans.
* It should be checked into source control and tracked carefully.
* Re-generate by setting TAP_SNAPSHOT=1 and running tests.
* Make sure to inspect the output below. Do not ignore changes!
*/
'use strict'
exports[`test/lib/commands/version.js TAP empty versions workspaces with one arg, all workspaces > must match snapshot 1`] = `
{
"name": "workspaces-test",
"version": "1.0.0",
"lockfileVersion": 2,
"requires": true,
"packages": {
"": {
"name": "workspaces-test",
"version": "1.0.0",
"workspaces": [
"workspace-a",
"workspace-b"
]
},
"node_modules/workspace-a": {
"resolved": "workspace-a",
"link": true
},
"node_modules/workspace-b": {
"resolved": "workspace-b",
"link": true
},
"workspace-a": {
"version": "2.0.0"
},
"workspace-b": {
"version": "2.0.0"
}
},
"dependencies": {
"workspace-a": {
"version": "file:workspace-a"
},
"workspace-b": {
"version": "file:workspace-b"
}
}
}
`

exports[`test/lib/commands/version.js TAP empty versions workspaces with one arg, all workspaces, saves package.json > must match snapshot 1`] = `
{
"name": "workspaces-test",
"version": "1.0.0",
"lockfileVersion": 2,
"requires": true,
"packages": {
"": {
"name": "workspaces-test",
"version": "1.0.0",
"workspaces": [
"workspace-a",
"workspace-b"
],
"dependencies": {
"workspace-a": "^2.0.0",
"workspace-b": "^2.0.0"
}
},
"node_modules/workspace-a": {
"resolved": "workspace-a",
"link": true
},
"node_modules/workspace-b": {
"resolved": "workspace-b",
"link": true
},
"workspace-a": {
"version": "2.0.0"
},
"workspace-b": {
"version": "2.0.0"
}
},
"dependencies": {
"workspace-a": {
"version": "file:workspace-a"
},
"workspace-b": {
"version": "file:workspace-b"
}
}
}
`
2 changes: 1 addition & 1 deletion tap-snapshots/test/lib/load-all-commands.js.test.cjs
Original file line number Diff line number Diff line change
Expand Up @@ -1092,7 +1092,7 @@ Options:
[--allow-same-version] [--no-commit-hooks] [--no-git-tag-version] [--json]
[--preid prerelease-id] [--sign-git-tag]
[-w|--workspace <workspace-name> [-w|--workspace <workspace-name> ...]]
[-ws|--workspaces] [--include-workspace-root]
[-ws|--workspaces] [--no-workspaces-update] [--include-workspace-root]
alias: verison
Expand Down
11 changes: 11 additions & 0 deletions tap-snapshots/test/lib/utils/config/definitions.js.test.cjs
Original file line number Diff line number Diff line change
Expand Up @@ -151,6 +151,7 @@ Array [
"which",
"workspace",
"workspaces",
"workspaces-update",
"yes",
]
`
Expand Down Expand Up @@ -1915,6 +1916,16 @@ _unless_ one or more workspaces are specified in the \`workspace\` config.
This value is not exported to the environment for child processes.
`

exports[`test/lib/utils/config/definitions.js TAP > config description for workspaces-update 1`] = `
#### \`workspaces-update\`
* Default: true
* Type: Boolean
If set to true, the npm cli will run an update after operations that may
possibly change the workspaces installed to the \`node_modules\` folder.
`

exports[`test/lib/utils/config/definitions.js TAP > config description for yes 1`] = `
#### \`yes\`
Expand Down
11 changes: 11 additions & 0 deletions tap-snapshots/test/lib/utils/config/describe-all.js.test.cjs
Original file line number Diff line number Diff line change
Expand Up @@ -1697,6 +1697,17 @@ This value is not exported to the environment for child processes.
<!-- automatically generated, do not edit manually -->
<!-- see lib/utils/config/definitions.js -->
#### \`workspaces-update\`
* Default: true
* Type: Boolean
If set to true, the npm cli will run an update after operations that may
possibly change the workspaces installed to the \`node_modules\` folder.
<!-- automatically generated, do not edit manually -->
<!-- see lib/utils/config/definitions.js -->
#### \`yes\`
* Default: null
Expand Down
2 changes: 1 addition & 1 deletion tap-snapshots/test/lib/utils/npm-usage.js.test.cjs
Original file line number Diff line number Diff line change
Expand Up @@ -1125,7 +1125,7 @@ All commands:
[--allow-same-version] [--no-commit-hooks] [--no-git-tag-version] [--json]
[--preid prerelease-id] [--sign-git-tag]
[-w|--workspace <workspace-name> [-w|--workspace <workspace-name> ...]]
[-ws|--workspaces] [--include-workspace-root]
[-ws|--workspaces] [--no-workspaces-update] [--include-workspace-root]
alias: verison
Expand Down
Loading

0 comments on commit 723a091

Please sign in to comment.