Revert "build: fix ts-api-guardian golden approval not working on windows (#36096)" (#36113)

This reverts commit f862536ec4.

Reverted due to test failures that have shown up in the Windows CI Jobs
that don't run on pull requests. A follow-up will be sent that re-adds
the changes w/ fixes for the windows test job.

PR Close #36113
This commit is contained in:
Paul Gschwendtner 2020-03-17 19:11:16 +01:00 committed by Andrew Kushnir
parent f862536ec4
commit 34a17f3699
2 changed files with 31 additions and 53 deletions

View File

@ -16,23 +16,8 @@ import * as path from 'path';
import {SerializationOptions, generateGoldenFile, verifyAgainstGoldenFile, discoverAllEntrypoints} from './main';
/** Name of the CLI */
const CMD = 'ts-api-guardian';
/** Name of the Bazel workspace that runs the CLI. */
const bazelWorkspaceName = process.env.BAZEL_WORKSPACE;
/**
* Path to the Bazel workspace directory. Only set if the CLI is run with `bazel run`.
* https://docs.bazel.build/versions/master/user-manual.html#run.
*/
const bazelWorkspaceDirectory = process.env.BUILD_WORKSPACE_DIRECTORY;
/**
* Regular expression that matches Bazel manifest paths that start with the
* current Bazel workspace, followed by a path delimiter.
*/
const bazelWorkspaceManifestPathRegex =
bazelWorkspaceName ? new RegExp(`^${bazelWorkspaceName}[/\\\\]`) : null;
export function startCli() {
const {argv, mode, errors} = parseArguments(process.argv.slice(2));
@ -225,48 +210,35 @@ Options:
}
/**
* Resolves a given path in the file system. If `ts-api-guardian` runs with Bazel, file paths
* are resolved through runfiles. Additionally in Bazel, this method handles the case where
* manifest file paths are not existing, but need to resolve to the Bazel workspace directory.
* This happens commonly when goldens are approved, but the golden file does not exist yet.
* Resolves a given path to the associated relative path if the current process runs within
* Bazel. We need to use the wrapped NodeJS resolve logic in order to properly handle the given
* runfiles files which are only part of the runfile manifest on Windows.
*/
function resolveFilePath(fileName: string): string {
// If an absolute path is specified, the path is already resolved.
if (path.isAbsolute(fileName)) {
return fileName;
function resolveBazelFilePath(fileName: string): string {
// If the CLI has been launched through the NodeJS Bazel rules, we need to resolve the
// actual file paths because otherwise this script won't work on Windows where runfiles
// are not available in the working directory. In order to resolve the real path for the
// runfile, we need to use `require.resolve` which handles runfiles properly on Windows.
if (process.env['BAZEL_TARGET']) {
// This try/catch block is necessary because if the path is to the source file directly
// rather than via symlinks in the bazel output directories, require is not able to
// resolve it.
try {
return path.relative(process.cwd(), require.resolve(fileName));
} catch (err) {
return path.relative(process.cwd(), fileName);
}
}
// Outside of Bazel, file paths are resolved based on the current working directory.
if (!bazelWorkspaceName) {
return path.resolve(fileName);
}
// In Bazel, we first try to resolve the file through the runfiles. We do this by calling
// the `require.resolve` function that is patched by the Bazel NodeJS rules. Note that we
// need to catch errors because files inside tree artifacts cannot be resolved through
// runfile manifests. Hence, we need to have alternative resolution logic when resolving
// file paths. Additionally, it could happen that manifest paths which aren't part of the
// runfiles are specified (i.e. golden is approved but does not exist in the workspace yet).
try {
return require.resolve(fileName);
} catch {
}
// This handles cases where file paths cannot be resolved through runfiles. This happens
// commonly when goldens are approved while the golden does not exist in the workspace yet.
// In those cases, we want to build up a relative path based on the manifest path, and join
// it with the absolute bazel workspace directory (which is only set in `bazel run`).
// e.g. `angular/goldens/<..>/common` should become `{workspace_dir}/goldens/<...>/common`.
if (bazelWorkspaceManifestPathRegex !== null && bazelWorkspaceDirectory &&
bazelWorkspaceManifestPathRegex.test(fileName)) {
return path.join(bazelWorkspaceDirectory, fileName.substr(bazelWorkspaceName.length + 1));
}
throw Error(`Could not resolve file path in runfiles: ${fileName}`);
return fileName;
}
function resolveFileNamePairs(argv: minimist.ParsedArgs, mode: string, entrypoints: string[]):
{entrypoint: string, goldenFile: string}[] {
if (argv[mode]) {
return [{
entrypoint: resolveFilePath(entrypoints[0]),
goldenFile: resolveFilePath(argv[mode]),
entrypoint: resolveBazelFilePath(entrypoints[0]),
goldenFile: resolveBazelFilePath(argv[mode]),
}];
} else { // argv[mode + 'Dir']
let rootDir = argv['rootDir'] || '.';
@ -274,8 +246,8 @@ function resolveFileNamePairs(argv: minimist.ParsedArgs, mode: string, entrypoin
return entrypoints.map((fileName: string) => {
return {
entrypoint: resolveFilePath(fileName),
goldenFile: resolveFilePath(path.join(goldenDir, path.relative(rootDir, fileName))),
entrypoint: resolveBazelFilePath(fileName),
goldenFile: resolveBazelFilePath(path.join(goldenDir, path.relative(rootDir, fileName))),
};
});
}

View File

@ -17,6 +17,13 @@ export function generateGoldenFile(
entrypoint: string, outFile: string, options: SerializationOptions = {}): void {
const output = publicApi(entrypoint, options);
// BUILD_WORKSPACE_DIRECTORY environment variable is only available during bazel
// run executions. This workspace directory allows us to generate golden files directly
// in the source file tree rather than via a symlink.
if (process.env['BUILD_WORKSPACE_DIRECTORY']) {
outFile = path.join(process.env['BUILD_WORKSPACE_DIRECTORY'], outFile);
}
ensureDirectory(path.dirname(outFile));
fs.writeFileSync(outFile, output);
}
@ -29,8 +36,7 @@ export function verifyAgainstGoldenFile(
if (actual === expected) {
return '';
} else {
const displayFileName = path.relative(process.cwd(), goldenFile);
const patch = createPatch(displayFileName, expected, actual, 'Golden file', 'Generated API');
const patch = createPatch(goldenFile, expected, actual, 'Golden file', 'Generated API');
// Remove the header of the patch
const start = patch.indexOf('\n', patch.indexOf('\n') + 1) + 1;