-
Notifications
You must be signed in to change notification settings - Fork 12k
test: run e2e tests on pre-compiled packages #23753
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
This file was deleted.
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,26 +1,30 @@ | ||
import { getGlobalVariable } from '../utils/env'; | ||
import { PkgInfo } from '../utils/packages'; | ||
import { globalNpm, extractNpmEnv } from '../utils/process'; | ||
import { isPrereleaseCli } from '../utils/project'; | ||
|
||
export default async function () { | ||
const testRegistry: string = getGlobalVariable('package-registry'); | ||
await globalNpm( | ||
[ | ||
'run', | ||
'admin', | ||
'--', | ||
'publish', | ||
'--no-versionCheck', | ||
'--no-branchCheck', | ||
`--registry=${testRegistry}`, | ||
'--tag', | ||
isPrereleaseCli() ? 'next' : 'latest', | ||
], | ||
{ | ||
...extractNpmEnv(), | ||
// Also set an auth token value for the local test registry which is required by npm 7+ | ||
// even though it is never actually used. | ||
'NPM_CONFIG__AUTH': 'e2e-testing', | ||
}, | ||
const packageTars: PkgInfo[] = Object.values(getGlobalVariable('package-tars')); | ||
|
||
// Publish packages specified with --package | ||
await Promise.all( | ||
packageTars.map(({ path: p }) => | ||
globalNpm( | ||
[ | ||
'publish', | ||
`--registry=${testRegistry}`, | ||
'--tag', | ||
isPrereleaseCli() ? 'next' : 'latest', | ||
p, | ||
], | ||
{ | ||
...extractNpmEnv(), | ||
// Also set an auth token value for the local test registry which is required by npm 7+ | ||
// even though it is never actually used. | ||
'NPM_CONFIG__AUTH': 'e2e-testing', | ||
}, | ||
), | ||
), | ||
); | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,39 @@ | ||
/** | ||
* @license | ||
* Copyright Google LLC All Rights Reserved. | ||
* | ||
* Use of this source code is governed by an MIT-style license that can be | ||
* found in the LICENSE file at https://angular.io/license | ||
*/ | ||
|
||
import fs from 'fs'; | ||
import { normalize } from 'path'; | ||
import { Parse } from 'tar'; | ||
|
||
/** | ||
* Extract and return the contents of a single file out of a tar file. | ||
* | ||
* @param tarball the tar file to extract from | ||
* @param filePath the path of the file to extract | ||
* @returns the Buffer of file or an error on fs/tar error or file not found | ||
*/ | ||
export async function extractFile(tarball: string, filePath: string): Promise<Buffer> { | ||
return new Promise((resolve, reject) => { | ||
fs.createReadStream(tarball) | ||
.pipe( | ||
new Parse({ | ||
strict: true, | ||
filter: (p) => normalize(p) === normalize(filePath), | ||
// TODO: @types/tar 'entry' does not have ReadEntry.on | ||
onentry: (entry: any) => { | ||
const chunks: Buffer[] = []; | ||
|
||
entry.on('data', (chunk: any) => chunks!.push(chunk)); | ||
entry.on('error', reject); | ||
entry.on('finish', () => resolve(Buffer.concat(chunks!))); | ||
}, | ||
}), | ||
) | ||
.on('close', () => reject(`${tarball} does not contain ${filePath}`)); | ||
}); | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -10,6 +10,9 @@ import { createNpmRegistry } from './e2e/utils/registry'; | |
import { launchTestProcess } from './e2e/utils/process'; | ||
import { join } from 'path'; | ||
import { findFreePort } from './e2e/utils/network'; | ||
import { extractFile } from './e2e/utils/tar'; | ||
import { realpathSync } from 'fs'; | ||
import { PkgInfo } from './e2e/utils/packages'; | ||
|
||
Error.stackTraceLimit = Infinity; | ||
|
||
|
@@ -34,6 +37,8 @@ Error.stackTraceLimit = Infinity; | |
* --shard Index of this processes' shard. | ||
* --tmpdir=path Override temporary directory to use for new projects. | ||
* --yarn Use yarn as package manager. | ||
* --package=path An npm package to be published before running tests | ||
* | ||
* If unnamed flags are passed in, the list of tests will be filtered to include only those passed. | ||
*/ | ||
const argv = yargsParser(process.argv.slice(2), { | ||
|
@@ -49,10 +54,14 @@ const argv = yargsParser(process.argv.slice(2), { | |
], | ||
string: ['devkit', 'glob', 'ignore', 'reuse', 'ng-tag', 'tmpdir', 'ng-version'], | ||
number: ['nb-shards', 'shard'], | ||
array: ['package'], | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. For the time being can we default this to For context here's an example of the command now.
|
||
configuration: { | ||
'dot-notation': false, | ||
'camel-case-expansion': false, | ||
}, | ||
default: { | ||
'package': ['./dist/_*.tgz'], | ||
}, | ||
}); | ||
|
||
/** | ||
|
@@ -162,10 +171,11 @@ console.log(['Tests:', ...testsToRun].join('\n ')); | |
setGlobalVariable('argv', argv); | ||
setGlobalVariable('package-manager', argv.yarn ? 'yarn' : 'npm'); | ||
|
||
Promise.all([findFreePort(), findFreePort()]) | ||
.then(async ([httpPort, httpsPort]) => { | ||
Promise.all([findFreePort(), findFreePort(), findPackageTars()]) | ||
.then(async ([httpPort, httpsPort, packageTars]) => { | ||
setGlobalVariable('package-registry', 'http://localhost:' + httpPort); | ||
setGlobalVariable('package-secure-registry', 'http://localhost:' + httpsPort); | ||
setGlobalVariable('package-tars', packageTars); | ||
|
||
// NPM registries for the lifetime of the test execution | ||
const registryProcess = await createNpmRegistry(httpPort, httpPort); | ||
|
@@ -306,3 +316,23 @@ function printFooter(testName: string, type: 'setup' | 'initializer' | 'test', s | |
); | ||
console.log(''); | ||
} | ||
|
||
// Collect the packages passed as arguments and return as {package-name => pkg-path} | ||
async function findPackageTars(): Promise<{ [pkg: string]: PkgInfo }> { | ||
const pkgs: string[] = (getGlobalVariable('argv').package as string[]).flatMap((p) => | ||
glob.sync(p, { realpath: true }), | ||
); | ||
|
||
const pkgJsons = await Promise.all(pkgs.map((pkg) => extractFile(pkg, './package/package.json'))); | ||
|
||
return pkgs.reduce((all, pkg, i) => { | ||
const json = pkgJsons[i].toString('utf8'); | ||
const { name, version } = JSON.parse(json); | ||
if (!name) { | ||
throw new Error(`Package ${pkg} - package.json name/version not found`); | ||
} | ||
|
||
all[name] = { path: realpathSync(pkg), name, version }; | ||
return all; | ||
}, {} as { [pkg: string]: PkgInfo }); | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Since
packages
is now computed from the package tars passed on the CLI there's no guarantee that it has been put into the "global variable"s when this file is first loading, so I've moved it into a method.Previously in this PR I had this doing
require(../../../....../package.json).version
instead of reading it from the loaded packages. However a) that is not the same as before this PR and b) the git repo version might not be the same as the packages being tested.