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

feat: workspaces support for dist-tag #3032

Merged
merged 1 commit into from Apr 8, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
12 changes: 12 additions & 0 deletions docs/content/commands/npm-dist-tag.md
Expand Up @@ -88,6 +88,18 @@ semver as `>=1.4.0 <1.5.0`. See <https://github.com/npm/npm/issues/6082>.
The simplest way to avoid semver problems with tags is to use tags that do
not begin with a number or the letter `v`.

### Configuration

#### workspaces

Only supported by `ls`. Enables listing dist-tags of all workspace
contexts defined in the current `package.json`.

#### workspace

Only supported by `ls`. Enables listing dist-tags of workspace contexts
limiting results to only those specified by this config item.

### See Also

* [npm publish](/commands/npm-publish)
Expand Down
56 changes: 52 additions & 4 deletions lib/dist-tag.js
Expand Up @@ -5,13 +5,19 @@ const semver = require('semver')

const otplease = require('./utils/otplease.js')
const readLocalPkgName = require('./utils/read-local-package.js')
const getWorkspaces = require('./workspaces/get-workspaces.js')
const BaseCommand = require('./base-command.js')

class DistTag extends BaseCommand {
static get description () {
return 'Modify package distribution tags'
}

/* istanbul ignore next - see test/lib/load-all-commands.js */
static get params () {
return ['workspace', 'workspaces']
}

/* istanbul ignore next - see test/lib/load-all-commands.js */
static get name () {
return 'dist-tag'
Expand Down Expand Up @@ -43,15 +49,14 @@ class DistTag extends BaseCommand {

async distTag ([cmdName, pkg, tag]) {
const opts = this.npm.flatOptions
const has = (items) => new Set(items).has(cmdName)

if (has(['add', 'a', 'set', 's']))
if (['add', 'a', 'set', 's'].includes(cmdName))
return this.add(pkg, tag, opts)

if (has(['rm', 'r', 'del', 'd', 'remove']))
if (['rm', 'r', 'del', 'd', 'remove'].includes(cmdName))
return this.remove(pkg, tag, opts)

if (has(['ls', 'l', 'sl', 'list']))
if (['ls', 'l', 'sl', 'list'].includes(cmdName))
return this.list(pkg, opts)

if (!pkg) {
Expand All @@ -62,6 +67,33 @@ class DistTag extends BaseCommand {
throw this.usage
}

execWorkspaces (args, filters, cb) {
this.distTagWorkspaces(args, filters).then(() => cb()).catch(cb)
}

async distTagWorkspaces ([cmdName, pkg, tag], filters) {
// cmdName is some form of list
// pkg is one of:
// - unset
// - .
// - .@version
if (['ls', 'l', 'sl', 'list'].includes(cmdName) && (!pkg || pkg === '.' || /^\.@/.test(pkg)))
return this.listWorkspaces(filters)

// pkg is unset
// cmdName is one of:
// - unset
// - .
// - .@version
if (!pkg && (!cmdName || cmdName === '.' || /^\.@/.test(cmdName)))
return this.listWorkspaces(filters)

// anything else is just a regular dist-tag command
// so we fallback to the non-workspaces implementation
log.warn('Ignoring workspaces for specified package')
return this.distTag([cmdName, pkg, tag])
}

async add (spec, tag, opts) {
spec = npa(spec || '')
const version = spec.rawSpec
Expand Down Expand Up @@ -145,6 +177,22 @@ class DistTag extends BaseCommand {
}
}

async listWorkspaces (filters) {
const workspaces =
await getWorkspaces(filters, { path: this.npm.localPrefix })

for (const [name] of workspaces) {
try {
this.npm.output(`${name}:`)
await this.list(npa(name), this.npm.flatOptions)
} catch (err) {
// set the exitCode directly, but ignore the error
// since it will have already been logged by this.list()
process.exitCode = 1
}
}
}

async fetchTags (spec, opts) {
const data = await regFetch.json(
`/-/package/${spec.escapedName}/dist-tags`,
Expand Down
112 changes: 112 additions & 0 deletions tap-snapshots/test-lib-dist-tag.js-TAP.test.js
Expand Up @@ -15,6 +15,9 @@ npm dist-tag add <pkg>@<version> [<tag>]
npm dist-tag rm <pkg> <tag>
npm dist-tag ls [<pkg>]

Options:
[-w|--workspace <workspace-name> [-w|--workspace <workspace-name> ...]] [-ws|--workspaces]

alias: dist-tags

Run "npm help dist-tag" for more info
Expand All @@ -30,6 +33,9 @@ npm dist-tag add <pkg>@<version> [<tag>]
npm dist-tag rm <pkg> <tag>
npm dist-tag ls [<pkg>]

Options:
[-w|--workspace <workspace-name> [-w|--workspace <workspace-name> ...]] [-ws|--workspaces]

alias: dist-tags

Run "npm help dist-tag" for more info
Expand All @@ -54,6 +60,9 @@ npm dist-tag add <pkg>@<version> [<tag>]
npm dist-tag rm <pkg> <tag>
npm dist-tag ls [<pkg>]

Options:
[-w|--workspace <workspace-name> [-w|--workspace <workspace-name> ...]] [-ws|--workspaces]

alias: dist-tags

Run "npm help dist-tag" for more info
Expand All @@ -75,6 +84,9 @@ npm dist-tag add <pkg>@<version> [<tag>]
npm dist-tag rm <pkg> <tag>
npm dist-tag ls [<pkg>]

Options:
[-w|--workspace <workspace-name> [-w|--workspace <workspace-name> ...]] [-ws|--workspaces]

alias: dist-tags

Run "npm help dist-tag" for more info
Expand Down Expand Up @@ -126,6 +138,9 @@ npm dist-tag add <pkg>@<version> [<tag>]
npm dist-tag rm <pkg> <tag>
npm dist-tag ls [<pkg>]

Options:
[-w|--workspace <workspace-name> [-w|--workspace <workspace-name> ...]] [-ws|--workspaces]

alias: dist-tags

Run "npm help dist-tag" for more info
Expand All @@ -142,3 +157,100 @@ dist-tag add b to @scoped/another@0.6.0
dist-tag add b is already set to version 0.6.0

`

exports[`test/lib/dist-tag.js TAP workspaces no args > printed the expected output 1`] = `
workspace-a:
latest-a: 1.0.0
latest: 1.0.0
workspace-b:
latest-b: 2.0.0
latest: 2.0.0
workspace-c:
latest-c: 3.0.0
latest: 3.0.0
`

exports[`test/lib/dist-tag.js TAP workspaces no args, one failing workspace sets exitCode to 1 > printed the expected output 1`] = `
workspace-a:
latest-a: 1.0.0
latest: 1.0.0
workspace-b:
latest-b: 2.0.0
latest: 2.0.0
workspace-c:
latest-c: 3.0.0
latest: 3.0.0
workspace-d:
`

exports[`test/lib/dist-tag.js TAP workspaces no args, one workspace > printed the expected output 1`] = `
workspace-a:
latest-a: 1.0.0
latest: 1.0.0
`

exports[`test/lib/dist-tag.js TAP workspaces one arg -- . > printed the expected output 1`] = `
workspace-a:
latest-a: 1.0.0
latest: 1.0.0
workspace-b:
latest-b: 2.0.0
latest: 2.0.0
workspace-c:
latest-c: 3.0.0
latest: 3.0.0
`

exports[`test/lib/dist-tag.js TAP workspaces one arg -- .@1, ignores version spec > printed the expected output 1`] = `
workspace-a:
latest-a: 1.0.0
latest: 1.0.0
workspace-b:
latest-b: 2.0.0
latest: 2.0.0
workspace-c:
latest-c: 3.0.0
latest: 3.0.0
`

exports[`test/lib/dist-tag.js TAP workspaces one arg -- list > printed the expected output 1`] = `
workspace-a:
latest-a: 1.0.0
latest: 1.0.0
workspace-b:
latest-b: 2.0.0
latest: 2.0.0
workspace-c:
latest-c: 3.0.0
latest: 3.0.0
`

exports[`test/lib/dist-tag.js TAP workspaces two args -- list, . > printed the expected output 1`] = `
workspace-a:
latest-a: 1.0.0
latest: 1.0.0
workspace-b:
latest-b: 2.0.0
latest: 2.0.0
workspace-c:
latest-c: 3.0.0
latest: 3.0.0
`

exports[`test/lib/dist-tag.js TAP workspaces two args -- list, .@1, ignores version spec > printed the expected output 1`] = `
workspace-a:
latest-a: 1.0.0
latest: 1.0.0
workspace-b:
latest-b: 2.0.0
latest: 2.0.0
workspace-c:
latest-c: 3.0.0
latest: 3.0.0
`

exports[`test/lib/dist-tag.js TAP workspaces two args -- list, @scoped/pkg, logs a warning and ignores workspaces > printed the expected output 1`] = `
a: 0.0.1
b: 0.5.0
latest: 1.0.0
`
3 changes: 3 additions & 0 deletions tap-snapshots/test-lib-utils-npm-usage.js-TAP.test.js
Expand Up @@ -323,6 +323,9 @@ All commands:
npm dist-tag rm <pkg> <tag>
npm dist-tag ls [<pkg>]

Options:
[-w|--workspace <workspace-name> [-w|--workspace <workspace-name> ...]] [-ws|--workspaces]

alias: dist-tags

Run "npm help dist-tag" for more info
Expand Down