diff --git a/test/Templates.Test/Helpers/Node/install-via-yarn-with-shrinkwrap.js b/test/Templates.Test/Helpers/Node/install-via-yarn-with-shrinkwrap.js deleted file mode 100644 index 280d7e2d96..0000000000 --- a/test/Templates.Test/Helpers/Node/install-via-yarn-with-shrinkwrap.js +++ /dev/null @@ -1,97 +0,0 @@ -/* -============================================================================================== -Implementation based on https://github.com/dabroek/shrinkwrap-to-lockfile/ by Matthijs Dabroek - -License for original package: -MIT License - -Copyright (c) 2017 Matthijs Dabroek - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in all -copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -SOFTWARE. -============================================================================================== - -Modified to support execution across multiple directories simultaneously, -to provide console output while executing, and to eliminate lodash dependency. -*/ - -const fs = require('fs'); -const path = require('path'); -const execSync = require('child_process').execSync; - -function parseJsonFile(filename) { - let obj = {}; - - try { - const file = fs.readFileSync(path.resolve(process.cwd(), filename), 'utf8'); - obj = JSON.parse(file); - } catch (error) { - throw new Error(`${filename} could not be parsed.`); - } - - return obj; -} - -function getDependencyVersions(dependencies) { - const result = {}; - for (const name in dependencies) { - if (dependencies.hasOwnProperty(name)) { - const pkg = dependencies[name]; - const version = pkg.version || pkg; - result[name] = version.match(/(\d+\.\d+\.\d+(?:-.+)?)/)[0]; - } - } - return result; -} - -function objectMergeLeft(a, b) { - return _.reduce(a, (result, value, key) => { - result[key] = value; - - if (!_.isEqual(value, b[key])) { - result[key] = b[key]; - } - - return result; - }, {}); -} - -function updatePackageJson(shrinkwrapFile, packageFile) { - const packageFilePath = path.resolve(process.cwd(), packageFile); - const origPackageFileContents = fs.readFileSync(packageFilePath); - const shrinkwrapJson = parseJsonFile(shrinkwrapFile); - const packageJson = parseJsonFile(packageFile); - - packageJson.dependencies = getDependencyVersions(shrinkwrapJson.dependencies); - delete packageJson.devDependencies; - - fs.writeFileSync(packageFilePath, JSON.stringify(packageJson, null, 2)); - return { - dispose: () => { - fs.writeFileSync(packageFilePath, origPackageFileContents); - } - }; -} - -const temporaryPackageJson = updatePackageJson('npm-shrinkwrap.json', 'package.json'); -try { - console.log('Generating yarn.lock from npm-shrinkwrap.json...'); - execSync('yarn install --mutex network', { stdio: 'inherit' }); -} finally { - temporaryPackageJson.dispose(); -} diff --git a/test/Templates.Test/Helpers/TemplateTestBase.cs b/test/Templates.Test/Helpers/TemplateTestBase.cs index 68c7a6cdc2..f85470db4a 100644 --- a/test/Templates.Test/Helpers/TemplateTestBase.cs +++ b/test/Templates.Test/Helpers/TemplateTestBase.cs @@ -16,6 +16,7 @@ namespace Templates.Test public class TemplateTestBase : IDisposable { private static object DotNetNewLock = new object(); + private static object NpmInstallLock = new object(); protected string ProjectName { get; set; } protected string TemplateOutputDir { get; private set; } @@ -75,27 +76,14 @@ namespace Templates.Test protected void InstallNpmPackages(string relativePath) { - var fullPath = Path.Combine(TemplateOutputDir, relativePath); - - if (!HasYarnInstalled()) + // It's not safe to run multiple NPM installs in parallel + // https://github.com/npm/npm/issues/2500 + lock (NpmInstallLock) { - Output.WriteLine($"Restoring NPM packages in '{relativePath}' using npm because yarn is not installed..."); + var fullPath = Path.Combine(TemplateOutputDir, relativePath); + Output.WriteLine($"Restoring NPM packages in '{relativePath}' using npm..."); RunViaShell(fullPath, "npm install"); } - else - { - // Current versions of NPM produce random errors when run on Windows - // (e.g., https://github.com/npm/npm/issues/19004). Plus, it's very slow to - // restore the SPA template packages. To make CI faster and more reliable, use - // Yarn to install the packages. To make Yarn respect the npm-shrinkwrap.json - // files, run a script that temporarily replaces the package.json content using - // dependency information from npm-shrinkwrap.json. - var installViaYarnWithShrinkwrapScriptPath = Path.Combine( - Path.GetDirectoryName(typeof(TemplateTestBase).Assembly.Location), - @"..\..\..\Helpers\Node\install-via-yarn-with-shrinkwrap.js"); - Output.WriteLine($"Restoring NPM packages in '{relativePath}' using yarn..."); - RunViaShell(fullPath, $"node {installViaYarnWithShrinkwrapScriptPath}"); - } } private void RunViaShell(string workingDirectory, string commandAndArgs) @@ -108,19 +96,6 @@ namespace Templates.Test .WaitForExit(assertSuccess: true); } - private bool HasYarnInstalled() - { - try - { - RunViaShell(TemplateOutputDir, "yarn --version"); - return true; - } - catch - { - return false; - } - } - protected void AssertDirectoryExists(string path, bool shouldExist) { var fullPath = Path.Combine(TemplateOutputDir, path);