Skip to content

Commit

Permalink
feat(publish): add workspace support
Browse files Browse the repository at this point in the history
Errors will make things stop altogether, dunno if we want to bikeshed
that here or not
  • Loading branch information
wraithgar committed May 11, 2021
1 parent 659751f commit 95f2014
Show file tree
Hide file tree
Showing 5 changed files with 263 additions and 29 deletions.
7 changes: 7 additions & 0 deletions docs/content/commands/npm-publish.md
Expand Up @@ -47,6 +47,13 @@ by specifying a different default registry or using a
actually publishing to the registry. Reports the details of what would
have been published.
* `[--workspaces]`: Enables workspace context while publishing. All
workspace packages will be published.
* `[--workspace]`: Enables workspaces context and limits results to only
those specified by this config item. Only the packages in the
workspaces given will be published.
The publish will fail if the package name and version combination already
exists in the specified registry.
Expand Down
48 changes: 39 additions & 9 deletions lib/publish.js
Expand Up @@ -11,6 +11,7 @@ const npmFetch = require('npm-registry-fetch')
const flatten = require('./utils/config/flatten.js')
const otplease = require('./utils/otplease.js')
const { getContents, logTar } = require('./utils/tar.js')
const getWorkspaces = require('./workspaces/get-workspaces.js')

// this is the only case in the CLI where we use the old full slow
// 'read-package-json' module, because we want to pull in all the
Expand All @@ -30,7 +31,7 @@ class Publish extends BaseCommand {

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

/* istanbul ignore next - see test/lib/load-all-commands.js */
Expand All @@ -44,6 +45,10 @@ class Publish extends BaseCommand {
this.publish(args).then(() => cb()).catch(cb)
}

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

async publish (args) {
if (args.length === 0)
args = ['.']
Expand All @@ -56,6 +61,7 @@ class Publish extends BaseCommand {
const dryRun = this.npm.config.get('dry-run')
const json = this.npm.config.get('json')
const defaultTag = this.npm.config.get('tag')
const silent = log.level === 'silent'

if (semver.validRange(defaultTag))
throw new Error('Tag name must not be a valid SemVer range: ' + defaultTag.trim())
Expand All @@ -77,7 +83,7 @@ class Publish extends BaseCommand {
path: spec.fetchSpec,
stdio: 'inherit',
pkg: manifest,
banner: log.level !== 'silent',
banner: !silent,
})
}

Expand Down Expand Up @@ -114,27 +120,51 @@ class Publish extends BaseCommand {
path: spec.fetchSpec,
stdio: 'inherit',
pkg: manifest,
banner: log.level !== 'silent',
banner: !silent,
})

await runScript({
event: 'postpublish',
path: spec.fetchSpec,
stdio: 'inherit',
pkg: manifest,
banner: log.level !== 'silent',
banner: !silent,
})
}

const silent = log.level === 'silent'
if (!silent && json)
this.npm.output(JSON.stringify(pkgContents, null, 2))
else if (!silent)
this.npm.output(`+ ${pkgContents.id}`)
if (!this.workspaces) {
if (!silent && json)
this.npm.output(JSON.stringify(pkgContents, null, 2))
else if (!silent)
this.npm.output(`+ ${pkgContents.id}`)
}

return pkgContents
}

async publishWorkspaces (args, filters) {
// Suppresses JSON output in publish() so we can handle it here
this.workspaces = true

const results = {}
const json = this.npm.config.get('json')
const silent = log.level === 'silent'
const workspaces =
await getWorkspaces(filters, { path: this.npm.localPrefix })
for (const [name, workspace] of workspaces.entries()) {
const pkgContents = await this.publish([workspace])
// This needs to be in-line w/ the rest of the output that non-JSON
// publish generates
if (!silent && !json)
this.npm.output(`+ ${pkgContents.id}`)
else
results[name] = pkgContents
}

if (!silent && json)
this.npm.output(JSON.stringify(results, null, 2))
}

// if it's a directory, read it from the file system
// otherwise, get the full metadata from whatever it is
getManifest (spec, opts) {
Expand Down
103 changes: 103 additions & 0 deletions tap-snapshots/test/lib/publish.js.test.cjs
Expand Up @@ -15,6 +15,109 @@ npm publish [<folder>]
Options:
[--tag <tag>] [--access <restricted|public>] [--dry-run]
[-w|--workspace <workspace-name> [-w|--workspace <workspace-name> ...]]
[-ws|--workspaces]
Run "npm help publish" for more info
`

exports[`test/lib/publish.js TAP workspaces all workspaces > should output all publishes 1`] = `
Array [
"+ workspace-a@1.2.3-a",
"+ workspace-b@1.2.3-n",
]
`

exports[`test/lib/publish.js TAP workspaces all workspaces > should publish all workspaces 1`] = `
Array [
Object {
"_id": "workspace-a@1.2.3-a",
"name": "workspace-a",
"readme": "ERROR: No README data found!",
"repository": Object {
"type": "git",
"url": "http://repo.workspace-a/",
},
"version": "1.2.3-a",
},
Object {
"_id": "workspace-b@1.2.3-n",
"bugs": Object {
"url": "https://github.com/npm/workspace-b/issues",
},
"homepage": "https://github.com/npm/workspace-b#readme",
"name": "workspace-b",
"readme": "ERROR: No README data found!",
"repository": Object {
"type": "git",
"url": "git+https://github.com/npm/workspace-b.git",
},
"version": "1.2.3-n",
},
]
`

exports[`test/lib/publish.js TAP workspaces json > should output all publishes as json 1`] = `
Array [
String(
{
"workspace-a": {
"id": "workspace-a@1.2.3-a"
},
"workspace-b": {
"id": "workspace-b@1.2.3-n"
}
}
),
]
`

exports[`test/lib/publish.js TAP workspaces json > should publish all workspaces 1`] = `
Array [
Object {
"_id": "workspace-a@1.2.3-a",
"name": "workspace-a",
"readme": "ERROR: No README data found!",
"repository": Object {
"type": "git",
"url": "http://repo.workspace-a/",
},
"version": "1.2.3-a",
},
Object {
"_id": "workspace-b@1.2.3-n",
"bugs": Object {
"url": "https://github.com/npm/workspace-b/issues",
},
"homepage": "https://github.com/npm/workspace-b#readme",
"name": "workspace-b",
"readme": "ERROR: No README data found!",
"repository": Object {
"type": "git",
"url": "git+https://github.com/npm/workspace-b.git",
},
"version": "1.2.3-n",
},
]
`

exports[`test/lib/publish.js TAP workspaces one workspace > should output one publish 1`] = `
Array [
"+ workspace-a@1.2.3-a",
]
`

exports[`test/lib/publish.js TAP workspaces one workspace > should publish given workspace 1`] = `
Array [
Object {
"_id": "workspace-a@1.2.3-a",
"name": "workspace-a",
"readme": "ERROR: No README data found!",
"repository": Object {
"type": "git",
"url": "http://repo.workspace-a/",
},
"version": "1.2.3-a",
},
]
`
2 changes: 2 additions & 0 deletions tap-snapshots/test/lib/utils/npm-usage.js.test.cjs
Expand Up @@ -697,6 +697,8 @@ All commands:
Options:
[--tag <tag>] [--access <restricted|public>] [--dry-run]
[-w|--workspace <workspace-name> [-w|--workspace <workspace-name> ...]]
[-ws|--workspaces]
Run "npm help publish" for more info
Expand Down

0 comments on commit 95f2014

Please sign in to comment.