Skip to content

Commit 9f1418b

Browse files
committed
fix(release): exclude generated npm bin links
1 parent e1b9786 commit 9f1418b

2 files changed

Lines changed: 53 additions & 7 deletions

File tree

‎scripts/prepare-bundled-npm.mjs‎

Lines changed: 29 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
import { createHash } from 'node:crypto';
22
import { createReadStream } from 'node:fs';
33
import { cp, lstat, mkdir, readFile, readdir, rm, writeFile } from 'node:fs/promises';
4-
import { dirname, join, relative } from 'node:path';
4+
import { basename, dirname, join, relative } from 'node:path';
55
import { fileURLToPath, pathToFileURL } from 'node:url';
66

77
const repoRoot = dirname(dirname(fileURLToPath(import.meta.url)));
@@ -76,7 +76,7 @@ export async function prepareBundledNpm({
7676
);
7777
}
7878

79-
await inventoryFiles(sourceNpmRoot);
79+
await inventoryFiles(sourceNpmRoot, { ignoreGeneratedBinDirectories: true });
8080
for (const patch of BUNDLED_NPM_SECURITY_PATCHES) {
8181
await inventoryFiles(join(patchedPackagesRoot, patch.packageName));
8282
}
@@ -98,6 +98,7 @@ export async function prepareBundledNpm({
9898
verbatimSymlinks: true,
9999
});
100100
}
101+
await removeGeneratedBinDirectories(runtimeOutputRoot);
101102
await requireRegularFile(join(runtimeOutputRoot, 'LICENSE'), 'npm license');
102103
await requireRegularFile(join(runtimeOutputRoot, 'bin', 'npm-cli.js'), 'npm CLI');
103104
const files = await inventoryFiles(runtimeOutputRoot);
@@ -172,20 +173,27 @@ async function requirePackageVersion(path, name, version, label) {
172173
}
173174
}
174175

175-
async function inventoryFiles(root) {
176+
async function inventoryFiles(root, { ignoreGeneratedBinDirectories = false } = {}) {
176177
const files = [];
177-
await walk(root, root, files);
178+
await walk(root, root, files, { ignoreGeneratedBinDirectories });
178179
files.sort((left, right) => Buffer.from(left.path).compare(Buffer.from(right.path)));
179180
return files;
180181
}
181182

182-
async function walk(root, directory, files) {
183+
async function walk(root, directory, files, options) {
183184
const entries = await readdir(directory, { withFileTypes: true });
184185
for (const entry of entries) {
185186
const absolutePath = join(directory, entry.name);
187+
if (
188+
options.ignoreGeneratedBinDirectories &&
189+
entry.name === '.bin' &&
190+
basename(directory) === 'node_modules'
191+
) {
192+
continue;
193+
}
186194
const info = await lstat(absolutePath);
187195
if (entry.isDirectory() && !info.isSymbolicLink()) {
188-
await walk(root, absolutePath, files);
196+
await walk(root, absolutePath, files, options);
189197
continue;
190198
}
191199
if (!entry.isFile() || info.isSymbolicLink()) {
@@ -199,6 +207,21 @@ async function walk(root, directory, files) {
199207
}
200208
}
201209

210+
async function removeGeneratedBinDirectories(directory) {
211+
const entries = await readdir(directory, { withFileTypes: true });
212+
for (const entry of entries) {
213+
const absolutePath = join(directory, entry.name);
214+
if (entry.name === '.bin' && basename(directory) === 'node_modules') {
215+
await rm(absolutePath, { recursive: true, force: true });
216+
continue;
217+
}
218+
const info = await lstat(absolutePath);
219+
if (entry.isDirectory() && !info.isSymbolicLink()) {
220+
await removeGeneratedBinDirectories(absolutePath);
221+
}
222+
}
223+
}
224+
202225
async function requireRegularFile(path, label) {
203226
const info = await lstat(path);
204227
if (!info.isFile() || info.isSymbolicLink()) {

‎scripts/prepare-bundled-npm.test.mjs‎

Lines changed: 24 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
import assert from 'node:assert/strict';
2-
import { mkdtemp, mkdir, readFile, rm, symlink, writeFile } from 'node:fs/promises';
2+
import { access, mkdtemp, mkdir, readFile, rm, symlink, writeFile } from 'node:fs/promises';
33
import { tmpdir } from 'node:os';
44
import { join } from 'node:path';
55
import test from 'node:test';
@@ -72,6 +72,29 @@ test('rejects symlink or junction input before publication', async (t) => {
7272
);
7373
});
7474

75+
test('excludes install-generated internal bin links from the published runtime', {
76+
skip: process.platform === 'win32',
77+
}, async (t) => {
78+
const fixture = await createFixture();
79+
t.after(fixture.remove);
80+
const generatedBinRoot = join(fixture.inputs.sourceNpmRoot, 'node_modules', '.bin');
81+
await mkdir(generatedBinRoot, { recursive: true });
82+
await symlink(
83+
join('..', '..', 'bin', 'npm-cli.js'),
84+
join(generatedBinRoot, 'npm-internal'),
85+
'file',
86+
);
87+
const runtimeOutputRoot = join(fixture.root, 'runtime', 'npm');
88+
89+
await prepareBundledNpm({
90+
...fixture.inputs,
91+
runtimeOutputRoot,
92+
outputPath: join(fixture.root, 'runtime', 'bundled-npm.json'),
93+
});
94+
95+
await assert.rejects(access(join(runtimeOutputRoot, 'node_modules', '.bin')));
96+
});
97+
7598
async function createFixture() {
7699
const root = await mkdtemp(join(tmpdir(), 'maka-prepare-bundled-npm-'));
77100
const sourceNpmRoot = join(root, 'npm');

0 commit comments

Comments
 (0)