mirror of
https://github.com/pnpm/pnpm.git
synced 2026-05-12 01:54:53 -04:00
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:
5
.changeset/chatty-dolphins-destroy.md
Normal file
5
.changeset/chatty-dolphins-destroy.md
Normal 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`.
|
||||
@@ -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 (
|
||||
|
||||
@@ -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 })
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -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",
|
||||
},
|
||||
],
|
||||
}
|
||||
`;
|
||||
@@ -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: [],
|
||||
})
|
||||
}
|
||||
})
|
||||
|
||||
Reference in New Issue
Block a user