feat(publish): --report-summary (#3461)

* feat(publish): --report-summary

* fix: typo

* fix: write a report summary even if packages were not published
This commit is contained in:
Zoltan Kochan
2021-05-21 02:31:14 +03:00
committed by GitHub
parent f45b1af7d4
commit 819f678942
5 changed files with 150 additions and 31 deletions

View File

@@ -0,0 +1,5 @@
---
"@pnpm/plugin-commands-publishing": minor
---
New option: reportSummary. When it is set to `true`, recursive publish will save the summary of published packages to `pnpm-publish-summary.json`.

View File

@@ -39,6 +39,7 @@ export function cliOptionsTypes () {
force: Boolean,
json: Boolean,
recursive: Boolean,
'report-summary': Boolean,
}
}
@@ -80,6 +81,10 @@ export function help () {
description: 'Packages are proceeded to be published even if their current version is already in the registry. This is useful when a "prepublishOnly" script bumps the version of the package before it is published',
name: '--force',
},
{
description: 'Save the list of the newly published packages to "pnpm-publish-summary.json". Useful when some other tooling is used to report the list of published packages.',
name: '--report-summary',
},
],
},
],
@@ -195,6 +200,7 @@ Do you want to continue?`,
'postpublish',
], manifest)
}
return { manifest }
}
async function runScriptsIfPresent (

View File

@@ -1,3 +1,4 @@
import path from 'path'
import { createResolver } from '@pnpm/client'
import { Config } from '@pnpm/config'
import logger from '@pnpm/logger'
@@ -7,6 +8,8 @@ import sortPackages from '@pnpm/sort-packages'
import storePath from '@pnpm/store-path'
import { Registries } from '@pnpm/types'
import pFilter from 'p-filter'
import R from 'ramda'
import writeJsonFile from 'write-json-file'
import { handler as publish } from './publish'
export type PublishRecursiveOpts = Required<Pick<Config,
@@ -46,6 +49,7 @@ Partial<Pick<Config,
argv: {
original: string[]
}
reportSummary?: boolean
}
export default async function (
@@ -76,43 +80,50 @@ export default async function (
}, pkg.manifest.name, pkg.manifest.version))
})
const publishedPkgDirs = new Set(pkgsToPublish.map(({ dir }) => dir))
const publishedPackages = []
if (publishedPkgDirs.size === 0) {
logger.info({
message: 'There are no new packages that should be published',
prefix: opts.dir,
})
return
}
const appendedArgs = []
if (opts.cliOptions['access']) {
appendedArgs.push(`--access=${opts.cliOptions['access'] as string}`)
}
if (opts.dryRun) {
appendedArgs.push('--dry-run')
}
const chunks = sortPackages(opts.selectedProjectsGraph)
const tag = opts.tag ?? 'latest'
for (const chunk of chunks) {
for (const pkgDir of chunk) {
if (!publishedPkgDirs.has(pkgDir)) continue
const pkg = opts.selectedProjectsGraph[pkgDir].package
await publish({
...opts,
argv: {
original: [
'publish',
pkg.dir,
'--tag',
tag,
'--registry',
pickRegistryForPackage(opts.registries, pkg.manifest.name!),
...appendedArgs,
],
},
gitChecks: false,
recursive: false,
}, [pkg.dir])
} else {
const appendedArgs = []
if (opts.cliOptions['access']) {
appendedArgs.push(`--access=${opts.cliOptions['access'] as string}`)
}
if (opts.dryRun) {
appendedArgs.push('--dry-run')
}
const chunks = sortPackages(opts.selectedProjectsGraph)
const tag = opts.tag ?? 'latest'
for (const chunk of chunks) {
for (const pkgDir of chunk) {
if (!publishedPkgDirs.has(pkgDir)) continue
const pkg = opts.selectedProjectsGraph[pkgDir].package
const publishResult = await publish({
...opts,
argv: {
original: [
'publish',
pkg.dir,
'--tag',
tag,
'--registry',
pickRegistryForPackage(opts.registries, pkg.manifest.name!),
...appendedArgs,
],
},
gitChecks: false,
recursive: false,
}, [pkg.dir])
if (publishResult?.manifest != null) {
publishedPackages.push(R.pick(['name', 'version'], publishResult.manifest))
}
}
}
}
if (opts.reportSummary) {
await writeJsonFile(path.join(opts.lockfileDir ?? opts.dir, 'pnpm-publish-summary.json'), { publishedPackages })
}
}

View File

@@ -0,0 +1,16 @@
// Jest Snapshot v1, https://goo.gl/fbAQLP
exports[`recursive publish writes publish summary 1`] = `
Object {
"publishedPackages": Array [
Object {
"name": "@pnpmtest/test-recursive-publish-project-4",
"version": "1.0.0",
},
Object {
"name": "@pnpmtest/test-recursive-publish-project-3",
"version": "1.0.0",
},
],
}
`;

View File

@@ -200,3 +200,84 @@ test('packages are released even if their current version is published, when for
const manifest = await loadJsonFile<ProjectManifest>('is-positive/package.json')
expect(manifest.version).toBe('4.0.0')
})
test('recursive publish writes publish summary', async () => {
preparePackages([
{
name: '@pnpmtest/test-recursive-publish-project-3',
version: '1.0.0',
dependencies: {
'is-positive': '1.0.0',
},
},
{
name: '@pnpmtest/test-recursive-publish-project-4',
version: '1.0.0',
dependencies: {
'is-negative': '1.0.0',
},
},
// This will not be published because is-positive@1.0.0 is in the registry
{
name: 'is-positive',
version: '1.0.0',
scripts: {
prepublishOnly: 'exit 1',
},
},
// This will not be published because it is a private package
{
name: 'i-am-private',
version: '1.0.0',
private: true,
scripts: {
prepublishOnly: 'exit 1',
},
},
// Package with no name is skipped
{
location: 'no-name',
package: {
scripts: {
prepublishOnly: 'exit 1',
},
},
},
])
await fs.writeFile('.npmrc', CREDENTIALS, 'utf8')
process.env.npm_config_userconfig = path.join('.npmrc')
await publish.handler({
...DEFAULT_OPTS,
...await readProjects(process.cwd(), []),
dir: process.cwd(),
recursive: true,
reportSummary: true,
}, [])
{
const publishSummary = await loadJsonFile('pnpm-publish-summary.json')
expect(publishSummary).toMatchSnapshot()
await fs.unlink('pnpm-publish-summary.json')
}
await publish.handler({
...DEFAULT_OPTS,
...await readProjects(process.cwd(), []),
dir: process.cwd(),
recursive: true,
reportSummary: true,
}, [])
{
const publishSummary = await loadJsonFile('pnpm-publish-summary.json')
expect(publishSummary).toStrictEqual({
publishedPackages: [],
})
}
})