Use checked-in package-lock.json file for npm install (#1078)

This avoids generating package-lock.json upon every build; given that npm install without a lock file is not necessarily deterministic, every build can in theory generate a new package-lock.json. Instead, when the lock file is explicitly provided, the behavior of npm install is fixed and deterministic.
This commit is contained in:
Aleksandar Milicevic 2019-10-21 15:29:05 -07:00 коммит произвёл GitHub
Родитель 7150734200
Коммит 0c65334b8f
Не найден ключ, соответствующий данной подписи
Идентификатор ключа GPG: 4AEE18F83AFDEB23
5 изменённых файлов: 24 добавлений и 18 удалений

Просмотреть файл

@ -105,7 +105,7 @@ namespace Node {
} }
@@public @@public
export function tscCompile(workingDirectory: Directory, dependencies: StaticDirectory[]) : OpaqueDirectory { export function tscCompile(workingDirectory: Directory, dependencies: Transformer.InputArtifact[]) : OpaqueDirectory {
const outPath = d`${workingDirectory}/out`; const outPath = d`${workingDirectory}/out`;
const arguments: Argument[] = [ const arguments: Argument[] = [
Cmd.argument(Artifact.none(f`${workingDirectory}/node_modules/typescript/lib/tsc.js`)), Cmd.argument(Artifact.none(f`${workingDirectory}/node_modules/typescript/lib/tsc.js`)),

Просмотреть файл

@ -41,8 +41,13 @@ namespace Npm {
}; };
} }
export interface NpmInstallResult {
installDir: OpaqueDirectory;
newPackageLock: DerivedFile;
}
@@public @@public
export function npmInstall(rootDir: StaticDirectory): OpaqueDirectory { export function npmInstall(rootDir: StaticDirectory, packageLock: DerivedFile): NpmInstallResult {
const wd = rootDir.root; const wd = rootDir.root;
const nodeModulesPath = d`${wd}/node_modules`; const nodeModulesPath = d`${wd}/node_modules`;
const npmCachePath = Context.getNewOutputDirectory('npm-install-cache'); const npmCachePath = Context.getNewOutputDirectory('npm-install-cache');
@ -50,6 +55,7 @@ namespace Npm {
const arguments: Argument[] = [ const arguments: Argument[] = [
Cmd.argument(Artifact.input(Node.npmCli)), Cmd.argument(Artifact.input(Node.npmCli)),
Cmd.argument("install"), Cmd.argument("install"),
Cmd.argument("--no-audit"),
Cmd.option("--cache ", Artifact.none(npmCachePath)), // Forces the npm cache to use this output folder for this object so that it doesn't write to user folder Cmd.option("--cache ", Artifact.none(npmCachePath)), // Forces the npm cache to use this output folder for this object so that it doesn't write to user folder
]; ];
@ -58,6 +64,7 @@ namespace Npm {
workingDirectory: wd, workingDirectory: wd,
dependencies: [ rootDir ], dependencies: [ rootDir ],
outputs: [ outputs: [
{ artifact: packageLock, existence: "required" }, // rewritten file in place
{ directory: wd, kind: "shared" }, { directory: wd, kind: "shared" },
npmCachePath, // Place the cache path as an output directory so it is cleaned each time. npmCachePath, // Place the cache path as an output directory so it is cleaned each time.
], ],
@ -68,7 +75,10 @@ namespace Npm {
], ],
}); });
return result.getOutputDirectory(wd); return {
installDir: result.getOutputDirectory(wd),
newPackageLock: result.getOutputFile(packageLock.path)
};
} }
@@public @@public

Просмотреть файл

@ -18,21 +18,17 @@ namespace VsCode.Client {
const clientCopy: OpaqueDirectory = Deployment.copyDirectory(clientSealDir.root, Context.getNewOutputDirectory("client-copy"), clientSealDir); const clientCopy: OpaqueDirectory = Deployment.copyDirectory(clientSealDir.root, Context.getNewOutputDirectory("client-copy"), clientSealDir);
const copiedPackageLock = Transformer.copyFile(
f`${Context.getMount("CgNpmRoot").path}/package-lock.json`,
p`${clientCopy}/package-lock.json`);
@public @public
export const installRootDir: OpaqueDirectory = Npm.npmInstall(clientCopy); export const npmInstallResult = Npm.npmInstall(clientCopy, copiedPackageLock);
@@public @@public
export const compileOutDir: OpaqueDirectory = Node.tscCompile(clientCopy.root, [clientCopy, installRootDir]); export const compileOutDir: OpaqueDirectory = Node.tscCompile(
clientCopy.root,
@@public [ clientCopy, npmInstallResult.installDir, npmInstallResult.newPackageLock ]);
export const deployedNpmPackageLockFile = Deployment.copyFileFromOpaqueDirectory(
// Here we want to copy a file from inside an opaque output directory.
// If done using Transformer.copyFile we would have no way of specifying a dependency
// of that copy pip to the pip producing this opaque directory, so we wouldn't be able to
// ensure that the copy operation runs after the opaque directory is produced.
p`${installRootDir}/package-lock.json`,
p`${Context.getMount("CgNpmRoot").path}/package-lock.json`,
installRootDir);
} }
namespace LanguageService.Server { namespace LanguageService.Server {
@ -115,7 +111,7 @@ namespace LanguageService.Server {
}, },
{ {
subfolder: a`node_modules`, subfolder: a`node_modules`,
contents: [ Deployment.createDeployableOpaqueSubDirectory(VsCode.Client.installRootDir, r`node_modules`) ] contents: [ Deployment.createDeployableOpaqueSubDirectory(VsCode.Client.npmInstallResult.installDir, r`node_modules`) ]
}, },
{ {
subfolder: a`out`, subfolder: a`out`,

Просмотреть файл

@ -560,7 +560,7 @@ if (!$skipFilter){
if ($Minimal) { if ($Minimal) {
# filtering by core deployment. # filtering by core deployment.
$AdditionalBuildXLArguments += "/f:(output='$($useDeployment.buildDir)\*'or(output='out\bin\$DeployConfig\Sdk\*')or($CacheOutputFilter))and~($CacheLongRunningFilter)ortag='protobufgenerator'oroutput='cg\*'" $AdditionalBuildXLArguments += "/f:(output='$($useDeployment.buildDir)\*'or(output='out\bin\$DeployConfig\Sdk\*')or($CacheOutputFilter))and~($CacheLongRunningFilter)ortag='protobufgenerator'"
} }
if ($Cache) { if ($Cache) {

Просмотреть файл

@ -643,7 +643,7 @@ config({
name: a`CgNpmRoot`, name: a`CgNpmRoot`,
path: p`cg/npm`, path: p`cg/npm`,
trackSourceFileChanges: true, trackSourceFileChanges: true,
isWritable: true, isWritable: false,
isReadable: true isReadable: true
}, },
{ {