Skip to content

Commit

Permalink
fix(deps): upgrading pacote & npm-packlist to v7 requires arborist tr…
Browse files Browse the repository at this point in the history
…ee (#367)

* fix(deps): upgrading pacote & npm-packlist to v7 requires arborist tree
- `npm-packlist` has a breaking change, it now requires `tree` has the first parameter (see their [changelog](https://github.com/npm/npm-packlist/blob/main/CHANGELOG.md)
- the arborist tree must now be provided in the options and will not be generated for you. the npm-packlist bin has also been removed.
- also update Pacote to v14 which has a peerDep on npm-packlist v7 (see their [changelog](https://github.com/npm/pacote/blob/main/CHANGELOG.md))

* chore: upgrade Pacote to latest v15

* chore: upgrade `npm-registry-fetch` to v14
  • Loading branch information
ghiscoding committed Oct 14, 2022
1 parent 6f373fd commit 8c34a3b
Show file tree
Hide file tree
Showing 14 changed files with 275 additions and 108 deletions.
3 changes: 3 additions & 0 deletions __fixtures__/normal-workspace-name-prefixed/lerna.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
{
"version": "1.0.0"
}
3 changes: 3 additions & 0 deletions __fixtures__/normal-workspace-name-prefixed/package.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
{
"name": "my-workspace"
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
{
"name": "@my-workspace/package-1",
"version": "1.0.0"
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
{
"name": "@my-workspace/package-2",
"version": "1.0.0",
"dependencies": {
"@my-workspace/package-1": "^1.0.0"
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
{
"name": "@my-workspace/package-3",
"version": "1.0.0",
"peerDependencies": {
"@my-workspace/package-2": "^1.0.0"
},
"devDependencies": {
"@my-workspace/package-2": "^1.0.0"
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
{
"name": "@my-workspace/package-4",
"version": "1.0.0",
"dependencies": {
"@my-workspace/package-1": "^0.0.0"
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
{
"name": "@my-workspace/package-5",
"dependencies": {
"@my-workspace/package-1": "^1.0.0"
},
"optionalDependencies": {
"@my-workspace/package-3": "^1.0.0"
},
"private": true,
"version": "1.0.0"
}
2 changes: 1 addition & 1 deletion packages/core/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -95,7 +95,7 @@
"@types/write-file-atomic": "^4.0.0",
"@types/write-json-file": "^3.2.1",
"@types/write-pkg": "^4.0.0",
"npm-registry-fetch": "^13.3.1",
"npm-registry-fetch": "^14.0.0",
"yargs": "^17.6.0",
"yargs-parser": "^21.1.1"
},
Expand Down
4 changes: 2 additions & 2 deletions packages/core/src/utils/pulse-till-done.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ import log from 'npmlog';
let pulsers = 0;
let pulse: any;

function pulseStart(prefix: string | Promise<string>) {
function pulseStart(prefix: string | Promise<unknown>) {
pulsers += 1;

if (pulsers > 1) {
Expand All @@ -23,7 +23,7 @@ function pulseStop() {
clearInterval(pulse);
}

export function pulseTillDone(prefix: string | Promise<string>, promise?: Promise<any> | string) {
export function pulseTillDone(prefix: string | Promise<unknown>, promise?: Promise<any> | string) {
if (!promise) {
/* eslint-disable no-param-reassign */
promise = prefix;
Expand Down
7 changes: 4 additions & 3 deletions packages/publish/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,7 @@
"dependencies": {
"@lerna-lite/core": "workspace:*",
"@lerna-lite/version": "workspace:*",
"@npmcli/arborist": "^5.6.2",
"byte-size": "^7.0.1",
"chalk": "^4.1.2",
"columnify": "^1.6.0",
Expand All @@ -41,12 +42,12 @@
"libnpmaccess": "^6.0.4",
"libnpmpublish": "^6.0.5",
"npm-package-arg": "^9.1.2",
"npm-packlist": "^6.0.1",
"npm-registry-fetch": "^13.3.1",
"npm-packlist": "^7.0.0",
"npm-registry-fetch": "^14.0.0",
"npmlog": "^6.0.2",
"p-map": "^4.0.0",
"p-pipe": "^3.1.0",
"pacote": "^13.6.2",
"pacote": "^15.0.0",
"path": "^0.12.7",
"pify": "^5.0.0",
"read-package-json": "^5.0.2",
Expand Down
56 changes: 50 additions & 6 deletions packages/publish/src/__tests__/publish-command.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -190,6 +190,51 @@ describe('PublishCommand', () => {
);
});

it('publishes changed packages including workspace name prefix', async () => {
const testDir = await initFixture('normal-workspace-name-prefixed');

await new PublishCommand(createArgv(testDir));
// await lernaPublish(testDir)();

expect(promptConfirmation).toHaveBeenLastCalledWith('Are you sure you want to publish these packages?');
expect((packDirectory as any).registry).toMatchInlineSnapshot(`
Set {
"@my-workspace/package-1",
"@my-workspace/package-4",
"@my-workspace/package-2",
"@my-workspace/package-3",
}
`);
expect((npmPublish as typeof npmPublishMock).registry).toMatchInlineSnapshot(`
Map {
"@my-workspace/package-1" => "latest",
"@my-workspace/package-4" => "latest",
"@my-workspace/package-2" => "latest",
"@my-workspace/package-3" => "latest",
}
`);
expect((npmPublish as typeof npmPublishMock).order()).toEqual([
'@my-workspace/package-1',
'@my-workspace/package-4',
'@my-workspace/package-2',
'@my-workspace/package-3',
// @my-workspace/package-5 is private
]);
expect(npmDistTag.remove).not.toHaveBeenCalled();
expect(npmDistTag.add).not.toHaveBeenCalled();

expect(getNpmUsername).not.toHaveBeenCalled();
expect(verifyNpmPackageAccess).not.toHaveBeenCalled();

expect(gitCheckout).toHaveBeenCalledWith(
// the list of changed files has been asserted many times already
expect.any(Array),
{ granularPathspec: true },
{ cwd: testDir },
undefined
);
});

it('publishes changed independent packages', async () => {
const testDir = await initFixture('independent');

Expand Down Expand Up @@ -396,16 +441,15 @@ describe('PublishCommand', () => {
});

describe('--registry', () => {
it('passes registry to npm commands', async () => {
const testDir = await initFixture('normal');
it('passes registry to npm commands that also includes workspace in the name prefix', async () => {
const testDir = await initFixture('normal-workspace-name-prefixed');
const registry = 'https://my-private-registry';

// await lernaPublish(testDir)("--registry", registry);
await new PublishCommand(createArgv(testDir, '--registry', registry));
await lernaPublish(testDir)('--registry', registry);

expect(npmPublish).toHaveBeenCalledWith(
expect.objectContaining({ name: 'package-1' }),
'/TEMP_DIR/package-1-MOCKED.tgz',
expect.objectContaining({ name: '@my-workspace/package-1' }),
'/TEMP_DIR/@my-workspace/package-1-MOCKED.tgz',
expect.objectContaining({ registry }),
expect.objectContaining({ otp: undefined })
);
Expand Down
28 changes: 28 additions & 0 deletions packages/publish/src/__tests__/publish-from-git.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -81,6 +81,34 @@ describe('publish from-git', () => {
]);
});

it('publishes tagged packages that includes workspace in the name prefix', async () => {
const cwd = await initFixture('normal-workspace-name-prefixed');

await gitTag(cwd, 'v1.0.0');
await new PublishCommand(createArgv(cwd, '--bump', 'from-git'));

// called from chained describeRef()
expect(throwIfUncommitted).toHaveBeenCalled();

expect(promptConfirmation).toHaveBeenLastCalledWith('Are you sure you want to publish these packages?');
expect((logOutput as any).logged()).toMatch('Found 4 packages to publish:');
expect((npmPublish as typeof npmPublishMock).order()).toEqual([
'@my-workspace/package-1',
'@my-workspace/package-4',
'@my-workspace/package-2',
'@my-workspace/package-3',
// @my-workspace/package-5 is private
]);

// check that @my-workspace/package-1 is properly escaped in the tarball tgz name
expect(npmPublish).toHaveBeenCalledWith(
expect.objectContaining({ name: '@my-workspace/package-1', version: '1.0.0' }),
expect.stringContaining('my-workspace-package-1-1.0.0.tgz'),
expect.any(Object),
expect.any(Object)
);
});

it('publishes tagged packages in dry-run mode', async () => {
const cwd = await initFixture('normal');

Expand Down
70 changes: 34 additions & 36 deletions packages/publish/src/lib/pack-directory.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
import Arborist from '@npmcli/arborist';
import path from 'path';
import packlist from 'npm-packlist';
import log from 'npmlog';
Expand All @@ -14,7 +15,7 @@ import { Tarball } from '../models';
* @param {string} dir to pack
* @param {PackConfig} options
*/
export function packDirectory(_pkg: Package, dir: string, options: PackConfig) {
export async function packDirectory(_pkg: Package, dir: string, options: PackConfig) {
const pkg = Package.lazy(_pkg, dir);
const opts: LifecycleConfig = {
// @ts-ignore
Expand All @@ -24,51 +25,48 @@ export function packDirectory(_pkg: Package, dir: string, options: PackConfig) {

opts.log.verbose('pack-directory', path.relative('.', pkg.contents));

let chain: Promise<any> = Promise.resolve();

if (opts.ignorePrepublish !== true) {
chain = chain.then(() => runLifecycle(pkg, 'prepublish', opts));
await runLifecycle(pkg, 'prepublish', opts);
}

chain = chain.then(() => runLifecycle(pkg, 'prepare', opts));
await runLifecycle(pkg, 'prepare', opts);

if (opts.lernaCommand === 'publish') {
opts.stdio = 'inherit';
chain = chain.then(() => pkg.refresh());
chain = chain.then(() => runLifecycle(pkg, 'prepublishOnly', opts));
chain = chain.then(() => pkg.refresh());
await pkg.refresh();
await runLifecycle(pkg, 'prepublishOnly', opts);
await pkg.refresh();
}

chain = chain.then(() => runLifecycle(pkg, 'prepack', opts));
chain = chain.then(() => pkg.refresh());
chain = chain.then(() => packlist({ path: pkg.contents }));
chain = chain.then((files: string[]) =>
tar.create(
{
cwd: pkg.contents,
prefix: 'package/',
portable: true,
// Provide a specific date in the 1980s for the benefit of zip,
// which is confounded by files dated at the Unix epoch 0.
mtime: new Date('1985-10-26T08:15:00.000Z'),
gzip: true,
},
// NOTE: node-tar does some Magic Stuff depending on prefixes for files
// specifically with @ signs, so we just neutralize that one
// and any such future 'features' by prepending `./`
files.map((f) => `./${f}`)
)
);
chain = chain.then((stream: DataView & Readable) => tempWrite(stream, getTarballName(pkg)));
chain = chain.then((tarFilePath) =>
getPacked(pkg, tarFilePath).then((packed: Tarball) =>
Promise.resolve()
.then(() => runLifecycle(pkg, 'postpack', opts))
.then(() => packed)
)
await runLifecycle(pkg, 'prepack', opts);
await pkg.refresh();

const arborist = new Arborist({ path: pkg.contents });
const tree = await arborist.loadActual();
const files: string[] = await packlist(tree);
const stream: DataView & Readable = tar.create(
{
cwd: pkg.contents,
prefix: 'package/',
portable: true,
// Provide a specific date in the 1980s for the benefit of zip,
// which is confounded by files dated at the Unix epoch 0.
mtime: new Date('1985-10-26T08:15:00.000Z'),
gzip: true,
},
// NOTE: node-tar does some Magic Stuff depending on prefixes for files
// specifically with @ signs, so we just neutralize that one
// and any such future 'features' by prepending `./`
files.map((f) => `./${f}`)
);

return chain;
const tarFilePath = await tempWrite(stream, getTarballName(pkg));

return getPacked(pkg, tarFilePath).then((packed: Tarball) =>
Promise.resolve()
.then(() => runLifecycle(pkg, 'postpack', opts))
.then(() => packed)
);
}

function getTarballName(pkg: Package) {
Expand Down

0 comments on commit 8c34a3b

Please sign in to comment.