mirror of
https://github.com/angular/angular-cli.git
synced 2025-05-17 02:54:21 +08:00
test: use random ports for local verdaccio npm servers
This commit is contained in:
parent
ba93117e78
commit
aa30bb156d
@ -1,17 +1,24 @@
|
||||
import { ChildProcess, spawn } from 'child_process';
|
||||
import { copyFileSync, mkdtempSync, realpathSync } from 'fs';
|
||||
import { spawn } from 'child_process';
|
||||
import { mkdtempSync, realpathSync } from 'fs';
|
||||
import { tmpdir } from 'os';
|
||||
import { join } from 'path';
|
||||
import { writeFile } from './fs';
|
||||
import { getGlobalVariable } from './env';
|
||||
import { writeFile, readFile } from './fs';
|
||||
|
||||
export function createNpmRegistry(withAuthentication = false): ChildProcess {
|
||||
export async function createNpmRegistry(
|
||||
port: number,
|
||||
httpsPort: number,
|
||||
withAuthentication = false,
|
||||
) {
|
||||
// Setup local package registry
|
||||
const registryPath = mkdtempSync(join(realpathSync(tmpdir()), 'angular-cli-e2e-registry-'));
|
||||
|
||||
copyFileSync(
|
||||
let configContent = await readFile(
|
||||
join(__dirname, '../../', withAuthentication ? 'verdaccio_auth.yaml' : 'verdaccio.yaml'),
|
||||
join(registryPath, 'verdaccio.yaml'),
|
||||
);
|
||||
configContent = configContent.replace(/\$\{HTTP_PORT\}/g, String(port));
|
||||
configContent = configContent.replace(/\$\{HTTPS_PORT\}/g, String(httpsPort));
|
||||
await writeFile(join(registryPath, 'verdaccio.yaml'), configContent);
|
||||
|
||||
return spawn('node', [require.resolve('verdaccio/bin/verdaccio'), '-c', './verdaccio.yaml'], {
|
||||
cwd: registryPath,
|
||||
@ -21,7 +28,6 @@ export function createNpmRegistry(withAuthentication = false): ChildProcess {
|
||||
|
||||
// Token was generated using `echo -n 'testing:s3cret' | openssl base64`.
|
||||
const VALID_TOKEN = `dGVzdGluZzpzM2NyZXQ=`;
|
||||
const SECURE_REGISTRY = `//localhost:4876/`;
|
||||
|
||||
export function createNpmConfigForAuthentication(
|
||||
/**
|
||||
@ -42,7 +48,7 @@ export function createNpmConfigForAuthentication(
|
||||
invalidToken = false,
|
||||
): Promise<void> {
|
||||
const token = invalidToken ? `invalid=` : VALID_TOKEN;
|
||||
const registry = SECURE_REGISTRY;
|
||||
const registry = (getGlobalVariable('package-secure-registry') as string).replace(/^\w+:/, '');
|
||||
|
||||
return writeFile(
|
||||
'.npmrc',
|
||||
@ -68,7 +74,7 @@ export function setNpmEnvVarsForAuthentication(
|
||||
delete process.env['NPM_CONFIG_REGISTRY'];
|
||||
|
||||
const registryKey = useYarnEnvVariable ? 'YARN_REGISTRY' : 'NPM_CONFIG_REGISTRY';
|
||||
process.env[registryKey] = `http:${SECURE_REGISTRY}`;
|
||||
process.env[registryKey] = getGlobalVariable('package-secure-registry');
|
||||
|
||||
process.env['NPM_CONFIG__AUTH'] = invalidToken ? `invalid=` : VALID_TOKEN;
|
||||
|
||||
|
@ -9,6 +9,7 @@ import * as path from 'path';
|
||||
import { setGlobalVariable } from './e2e/utils/env';
|
||||
import { gitClean } from './e2e/utils/git';
|
||||
import { createNpmRegistry } from './e2e/utils/registry';
|
||||
import { AddressInfo, createServer, Server } from 'net';
|
||||
|
||||
Error.stackTraceLimit = Infinity;
|
||||
|
||||
@ -122,93 +123,99 @@ if (testsToRun.length == allTests.length) {
|
||||
setGlobalVariable('argv', argv);
|
||||
setGlobalVariable('ci', process.env['CI']?.toLowerCase() === 'true' || process.env['CI'] === '1');
|
||||
setGlobalVariable('package-manager', argv.yarn ? 'yarn' : 'npm');
|
||||
setGlobalVariable('package-registry', 'http://localhost:4873');
|
||||
|
||||
const registryProcess = createNpmRegistry();
|
||||
const secureRegistryProcess = createNpmRegistry(true);
|
||||
Promise.all([findFreePort(), findFreePort()])
|
||||
.then(async ([httpPort, httpsPort]) => {
|
||||
setGlobalVariable('package-registry', 'http://localhost:' + httpPort);
|
||||
setGlobalVariable('package-secure-registry', 'http://localhost:' + httpsPort);
|
||||
|
||||
testsToRun
|
||||
.reduce((previous, relativeName, testIndex) => {
|
||||
// Make sure this is a windows compatible path.
|
||||
let absoluteName = path.join(e2eRoot, relativeName);
|
||||
if (/^win/.test(process.platform)) {
|
||||
absoluteName = absoluteName.replace(/\\/g, path.posix.sep);
|
||||
}
|
||||
const registryProcess = await createNpmRegistry(httpPort, httpPort);
|
||||
const secureRegistryProcess = await createNpmRegistry(httpPort, httpsPort, true);
|
||||
|
||||
return previous.then(() => {
|
||||
currentFileName = relativeName.replace(/\.ts$/, '');
|
||||
const start = +new Date();
|
||||
return testsToRun
|
||||
.reduce((previous, relativeName, testIndex) => {
|
||||
// Make sure this is a windows compatible path.
|
||||
let absoluteName = path.join(e2eRoot, relativeName);
|
||||
if (/^win/.test(process.platform)) {
|
||||
absoluteName = absoluteName.replace(/\\/g, path.posix.sep);
|
||||
}
|
||||
|
||||
const module = require(absoluteName);
|
||||
const originalEnvVariables = {
|
||||
...process.env,
|
||||
};
|
||||
return previous.then(() => {
|
||||
currentFileName = relativeName.replace(/\.ts$/, '');
|
||||
const start = +new Date();
|
||||
|
||||
const fn: (skipClean?: () => void) => Promise<void> | void =
|
||||
typeof module == 'function'
|
||||
? module
|
||||
: typeof module.default == 'function'
|
||||
? module.default
|
||||
: () => {
|
||||
throw new Error('Invalid test module.');
|
||||
};
|
||||
const module = require(absoluteName);
|
||||
const originalEnvVariables = {
|
||||
...process.env,
|
||||
};
|
||||
|
||||
let clean = true;
|
||||
let previousDir = null;
|
||||
const fn: (skipClean?: () => void) => Promise<void> | void =
|
||||
typeof module == 'function'
|
||||
? module
|
||||
: typeof module.default == 'function'
|
||||
? module.default
|
||||
: () => {
|
||||
throw new Error('Invalid test module.');
|
||||
};
|
||||
|
||||
return Promise.resolve()
|
||||
.then(() => printHeader(currentFileName, testIndex))
|
||||
.then(() => (previousDir = process.cwd()))
|
||||
.then(() => logStack.push(lastLogger().createChild(currentFileName)))
|
||||
.then(() => fn(() => (clean = false)))
|
||||
.then(
|
||||
() => logStack.pop(),
|
||||
(err) => {
|
||||
logStack.pop();
|
||||
throw err;
|
||||
},
|
||||
)
|
||||
.then(() => console.log('----'))
|
||||
.then(() => {
|
||||
// If we're not in a setup, change the directory back to where it was before the test.
|
||||
// This allows tests to chdir without worrying about keeping the original directory.
|
||||
if (!allSetups.includes(relativeName) && previousDir) {
|
||||
process.chdir(previousDir);
|
||||
let clean = true;
|
||||
let previousDir = null;
|
||||
|
||||
// Restore env variables before each test.
|
||||
console.log(' Restoring original environment variables...');
|
||||
process.env = originalEnvVariables;
|
||||
}
|
||||
})
|
||||
.then(() => {
|
||||
// Only clean after a real test, not a setup step. Also skip cleaning if the test
|
||||
// requested an exception.
|
||||
if (!allSetups.includes(relativeName) && clean) {
|
||||
logStack.push(new logging.NullLogger());
|
||||
return gitClean().then(
|
||||
return Promise.resolve()
|
||||
.then(() => printHeader(currentFileName, testIndex))
|
||||
.then(() => (previousDir = process.cwd()))
|
||||
.then(() => logStack.push(lastLogger().createChild(currentFileName)))
|
||||
.then(() => fn(() => (clean = false)))
|
||||
.then(
|
||||
() => logStack.pop(),
|
||||
(err) => {
|
||||
logStack.pop();
|
||||
throw err;
|
||||
},
|
||||
)
|
||||
.then(() => console.log('----'))
|
||||
.then(() => {
|
||||
// If we're not in a setup, change the directory back to where it was before the test.
|
||||
// This allows tests to chdir without worrying about keeping the original directory.
|
||||
if (!allSetups.includes(relativeName) && previousDir) {
|
||||
process.chdir(previousDir);
|
||||
|
||||
// Restore env variables before each test.
|
||||
console.log(' Restoring original environment variables...');
|
||||
process.env = originalEnvVariables;
|
||||
}
|
||||
})
|
||||
.then(() => {
|
||||
// Only clean after a real test, not a setup step. Also skip cleaning if the test
|
||||
// requested an exception.
|
||||
if (!allSetups.includes(relativeName) && clean) {
|
||||
logStack.push(new logging.NullLogger());
|
||||
return gitClean().then(
|
||||
() => logStack.pop(),
|
||||
(err) => {
|
||||
logStack.pop();
|
||||
throw err;
|
||||
},
|
||||
);
|
||||
}
|
||||
})
|
||||
.then(
|
||||
() => printFooter(currentFileName, start),
|
||||
(err) => {
|
||||
printFooter(currentFileName, start);
|
||||
console.error(err);
|
||||
throw err;
|
||||
},
|
||||
);
|
||||
}
|
||||
})
|
||||
.then(
|
||||
() => printFooter(currentFileName, start),
|
||||
(err) => {
|
||||
printFooter(currentFileName, start);
|
||||
console.error(err);
|
||||
throw err;
|
||||
},
|
||||
);
|
||||
});
|
||||
}, Promise.resolve())
|
||||
});
|
||||
}, Promise.resolve())
|
||||
.finally(() => {
|
||||
registryProcess.kill();
|
||||
secureRegistryProcess.kill();
|
||||
});
|
||||
})
|
||||
.then(
|
||||
() => {
|
||||
registryProcess.kill();
|
||||
secureRegistryProcess.kill();
|
||||
|
||||
console.log(colors.green('Done.'));
|
||||
process.exit(0);
|
||||
},
|
||||
@ -218,9 +225,6 @@ testsToRun
|
||||
console.error(colors.red(err.message));
|
||||
console.error(colors.red(err.stack));
|
||||
|
||||
registryProcess.kill();
|
||||
secureRegistryProcess.kill();
|
||||
|
||||
if (argv.debug) {
|
||||
console.log(`Current Directory: ${process.cwd()}`);
|
||||
console.log('Will loop forever while you debug... CTRL-C to quit.');
|
||||
@ -257,3 +261,15 @@ function printFooter(testName: string, startTime: number) {
|
||||
console.log(colors.green('Last step took ') + colors.bold.blue('' + t) + colors.green('s...'));
|
||||
console.log('');
|
||||
}
|
||||
|
||||
function findFreePort() {
|
||||
return new Promise<number>((resolve, reject) => {
|
||||
const srv = createServer();
|
||||
srv.once('listening', () => {
|
||||
const port = (srv.address() as AddressInfo).port;
|
||||
srv.close((e) => (e ? reject(e) : resolve(port)));
|
||||
});
|
||||
srv.once('error', (e) => srv.close(() => reject(e)));
|
||||
srv.listen();
|
||||
});
|
||||
}
|
||||
|
@ -3,7 +3,7 @@ storage: ./storage
|
||||
auth:
|
||||
auth-memory:
|
||||
users: {}
|
||||
listen: localhost:4873
|
||||
listen: localhost:${HTTP_PORT}
|
||||
uplinks:
|
||||
npmjs:
|
||||
url: https://registry.npmjs.org/
|
||||
|
@ -5,10 +5,10 @@ auth:
|
||||
testing:
|
||||
name: testing
|
||||
password: s3cret
|
||||
listen: localhost:4876
|
||||
listen: localhost:${HTTPS_PORT}
|
||||
uplinks:
|
||||
local:
|
||||
url: http://localhost:4873
|
||||
url: http://localhost:${HTTP_PORT}
|
||||
cache: false
|
||||
maxage: 20m
|
||||
max_fails: 32
|
||||
|
Loading…
x
Reference in New Issue
Block a user