Skip to content

Commit bb927d0

Browse files
Sebastian McKenziebestander
authored andcommitted
Put build artifact tracking in integrity file (#3224)
* Put build artifact tracking in integrity file * fix lint
1 parent b8266f5 commit bb927d0

File tree

5 files changed

+57
-24
lines changed

5 files changed

+57
-24
lines changed

__tests__/commands/install/integration.js

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -52,9 +52,9 @@ test.concurrent('properly find and save build artifacts', async () => {
5252
await runInstall({}, 'artifacts-finds-and-saves', async (config): Promise<void> => {
5353
const cacheFolder = path.join(config.cacheFolder, 'npm-dummy-0.0.0');
5454

55-
expect(
56-
(await fs.readJson(path.join(cacheFolder, constants.METADATA_FILENAME))).artifacts,
57-
).toEqual(
55+
const integrity = await fs.readJson(path.join(config.cwd, 'node_modules', constants.INTEGRITY_FILENAME));
56+
57+
expect(integrity.artifacts['dummy@0.0.0']).toEqual(
5858
['dummy', path.join('dummy', 'dummy.txt'), 'dummy.txt'],
5959
);
6060

src/cli/commands/install.js

Lines changed: 13 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -329,6 +329,12 @@ export class Install {
329329
return true;
330330
}
331331

332+
const {artifacts} = match;
333+
if (artifacts) {
334+
this.linker.setArtifacts(artifacts);
335+
this.scripts.setArtifacts(artifacts);
336+
}
337+
332338
return false;
333339
}
334340

@@ -603,7 +609,13 @@ export class Install {
603609
}
604610

605611
// write integrity hash
606-
await this.integrityChecker.save(patterns, lockfileBasedOnResolver, this.flags, this.resolver.usedRegistries);
612+
await this.integrityChecker.save(
613+
patterns,
614+
lockfileBasedOnResolver,
615+
this.flags,
616+
this.resolver.usedRegistries,
617+
this.scripts.getArtifacts(),
618+
);
607619

608620
const lockFileHasAllPatterns = patterns.filter((p) => !this.lockfile.getLocked(p)).length === 0;
609621
const resolverPatternsAreSameAsInLockfile = Object.keys(lockfileBasedOnResolver)

src/integrity-checker.js

Lines changed: 9 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@ import * as constants from './constants.js';
88
import {registryNames} from './registries/index.js';
99
import * as fs from './util/fs.js';
1010
import {sortAlpha, compareSortedArrays} from './util/misc.js';
11-
11+
import type {InstallArtifacts} from './package-install-scripts.js';
1212

1313
const invariant = require('invariant');
1414
const path = require('path');
@@ -17,6 +17,7 @@ export type IntegrityCheckResult = {
1717
integrityFileMissing: boolean,
1818
integrityMatches?: boolean,
1919
missingPatterns: Array<string>,
20+
artifacts?: ?InstallArtifacts,
2021
};
2122

2223
type IntegrityHashLocation = {
@@ -33,6 +34,7 @@ type IntegrityFile = {
3334
[key: string]: string
3435
},
3536
files: Array<string>,
37+
artifacts: ?InstallArtifacts,
3638
}
3739

3840
type IntegrityFlags = {
@@ -125,6 +127,7 @@ export default class InstallationIntegrityChecker {
125127
patterns: Array<string>,
126128
flags: IntegrityFlags,
127129
modulesFolder: string,
130+
artifacts?: InstallArtifacts,
128131
): Promise<IntegrityFile> {
129132

130133
const result: IntegrityFile = {
@@ -133,6 +136,7 @@ export default class InstallationIntegrityChecker {
133136
topLevelPatters: [],
134137
lockfileEntries: {},
135138
files: [],
139+
artifacts,
136140
};
137141

138142
result.topLevelPatters = patterns.sort(sortAlpha);
@@ -247,6 +251,7 @@ export default class InstallationIntegrityChecker {
247251
integrityFileMissing: false,
248252
integrityMatches,
249253
missingPatterns,
254+
artifacts: expected ? expected.artifacts : null,
250255
};
251256
}
252257

@@ -257,11 +262,12 @@ export default class InstallationIntegrityChecker {
257262
patterns: Array<string>,
258263
lockfile: {[key: string]: LockManifest},
259264
flags: IntegrityFlags,
260-
usedRegistries?: Set<RegistryNames>): Promise<void> {
265+
usedRegistries?: Set<RegistryNames>,
266+
artifacts: InstallArtifacts): Promise<void> {
261267
const loc = await this._getIntegrityHashLocation(usedRegistries);
262268
invariant(loc.locationPath, 'expected integrity hash location');
263269
await fs.mkdirp(path.dirname(loc.locationPath));
264-
const integrityFile = await this._generateIntegrityFile(lockfile, patterns, flags, loc.locationFolder);
270+
const integrityFile = await this._generateIntegrityFile(lockfile, patterns, flags, loc.locationFolder, artifacts);
265271
await fs.writeFile(loc.locationPath, JSON.stringify(integrityFile, null, 2));
266272
}
267273

src/package-install-scripts.js

Lines changed: 17 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -14,13 +14,18 @@ const path = require('path');
1414

1515
const INSTALL_STAGES = ['preinstall', 'install', 'postinstall'];
1616

17+
export type InstallArtifacts = {
18+
[pattern: string]: Array<string>,
19+
};
20+
1721
export default class PackageInstallScripts {
1822
constructor(config: Config, resolver: PackageResolver, force: boolean) {
1923
this.installed = 0;
2024
this.resolver = resolver;
2125
this.reporter = config.reporter;
2226
this.config = config;
2327
this.force = force;
28+
this.artifacts = {};
2429
}
2530

2631
needsPermission: boolean;
@@ -29,7 +34,15 @@ export default class PackageInstallScripts {
2934
installed: number;
3035
config: Config;
3136
force: boolean;
37+
artifacts: InstallArtifacts;
38+
39+
setArtifacts(artifacts: InstallArtifacts) {
40+
this.artifacts = artifacts;
41+
}
3242

43+
getArtifacts(): InstallArtifacts {
44+
return this.artifacts;
45+
}
3346

3447
getInstallCommands(pkg: Manifest): Array<[string, string]> {
3548
const scripts = pkg.scripts;
@@ -77,21 +90,10 @@ export default class PackageInstallScripts {
7790
return;
7891
}
7992

80-
// if the process is killed while copying over build artifacts then we'll leave
81-
// the cache in a bad state. remove the metadata file and add it back once we've
82-
// done our copies to ensure cache integrity.
83-
const cachedLoc = this.config.generateHardModulePath(pkg._reference, true);
84-
const metadata = await this.config.readPackageMetadata(cachedLoc);
85-
metadata.artifacts = buildArtifacts;
86-
87-
const metadataLoc = path.join(cachedLoc, constants.METADATA_FILENAME);
88-
await fs.writeFile(metadataLoc, JSON.stringify({
89-
...metadata,
90-
91-
// config.readPackageMetadata also returns the package manifest but that's not in the original
92-
// metadata json
93-
package: undefined,
94-
}, null, ' '));
93+
// set build artifacts
94+
const ref = pkg._reference;
95+
invariant(ref, 'expected reference');
96+
this.artifacts[`${pkg.name}@${pkg.version}`] = buildArtifacts;
9597
}
9698

9799
async install(cmds: Array<[string, string]>, pkg: Manifest, spinner: ReporterSetSpinner): Promise<void> {

src/package-linker.js

Lines changed: 15 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ import type {Reporter} from './reporters/index.js';
66
import type Config from './config.js';
77
import type {HoistManifestTuples} from './package-hoister.js';
88
import type {CopyQueueItem} from './util/fs.js';
9+
import type {InstallArtifacts} from './package-install-scripts.js';
910
import PackageHoister from './package-hoister.js';
1011
import * as constants from './constants.js';
1112
import * as promise from './util/promise.js';
@@ -43,12 +44,18 @@ export default class PackageLinker {
4344
this.resolver = resolver;
4445
this.reporter = config.reporter;
4546
this.config = config;
47+
this.artifacts = {};
4648
}
4749

50+
artifacts: InstallArtifacts;
4851
reporter: Reporter;
4952
resolver: PackageResolver;
5053
config: Config;
5154

55+
setArtifacts(artifacts: InstallArtifacts) {
56+
this.artifacts = artifacts;
57+
}
58+
5259
async linkSelfDependencies(pkg: Manifest, pkgLoc: string, targetBinLoc: string): Promise<void> {
5360
targetBinLoc = await fs.realpath(targetBinLoc);
5461
pkgLoc = await fs.realpath(pkgLoc);
@@ -139,13 +146,19 @@ export default class PackageLinker {
139146
invariant(ref, 'expected package reference');
140147
ref.setLocation(dest);
141148

142-
// get a list of build artifacts contained in this module so we can prevent them from being marked as
143-
// extraneous
149+
// backwards compatibility: get build artifacts from metadata
144150
const metadata = await this.config.readPackageMetadata(src);
145151
for (const file of metadata.artifacts) {
146152
artifactFiles.push(path.join(dest, file));
147153
}
148154

155+
const integrityArtifacts = this.artifacts[`${pkg.name}@${pkg.version}`];
156+
if (integrityArtifacts) {
157+
for (const file of integrityArtifacts) {
158+
artifactFiles.push(path.join(dest, file));
159+
}
160+
}
161+
149162
const copiedDest = copiedSrcs.get(src);
150163
if (!copiedDest) {
151164
if (hardlinksEnabled) {

0 commit comments

Comments
 (0)