mirror of
https://github.com/angular/angular
synced 2026-05-24 09:28:37 +00:00
build: add script to diff packages and ensure no unexpected changes (#61275)
Adds a script to diff snapshot packages to allow for easy verification that no unexpected changes were made. PR Close #61275
This commit is contained in:
parent
925b923e85
commit
8e78b4e438
4 changed files with 152 additions and 11 deletions
|
|
@ -2,10 +2,10 @@
|
|||
# Input hashes for repository rule npm_translate_lock(name = "npm2", pnpm_lock = "@//:pnpm-lock.yaml").
|
||||
# This file should be checked into version control along with the pnpm-lock.yaml file.
|
||||
.npmrc=-1406867100
|
||||
package.json=-686175807
|
||||
package.json=1344581013
|
||||
packages/compiler-cli/package.json=-1767555217
|
||||
packages/compiler/package.json=-426903429
|
||||
pnpm-lock.yaml=-445193031
|
||||
pnpm-lock.yaml=953012603
|
||||
pnpm-workspace.yaml=353334404
|
||||
tools/bazel/rules_angular_store/package.json=-239561259
|
||||
yarn.lock=1067917288
|
||||
|
|
|
|||
|
|
@ -44,7 +44,8 @@
|
|||
"devtools:test": "bazelisk test --//devtools/projects/shell-browser/src:flag_browser=chrome -- //devtools/...",
|
||||
"docs": "[[ -n $CI ]] && echo 'Cannot run this yarn script on CI' && exit 1 || yarn ibazel run //adev:serve",
|
||||
"docs:build": "[[ -n $CI ]] && echo 'Cannot run this yarn script on CI' && exit 1 || yarn bazel build //adev:build",
|
||||
"benchmarks": "tsx --tsconfig=scripts/tsconfig.json scripts/benchmarks/index.mts"
|
||||
"benchmarks": "tsx --tsconfig=scripts/tsconfig.json scripts/benchmarks/index.mts",
|
||||
"diff-release-package": "tsx --tsconfig=scripts/tsconfig.json scripts/diff-release-package.mts"
|
||||
},
|
||||
"// 1": "dependencies are used locally and by bazel",
|
||||
"dependencies": {
|
||||
|
|
|
|||
|
|
@ -6515,13 +6515,8 @@ packages:
|
|||
dependencies:
|
||||
ajv: 8.13.0
|
||||
|
||||
/ajv-formats@2.1.1(ajv@8.17.1):
|
||||
/ajv-formats@2.1.1:
|
||||
resolution: {integrity: sha512-Wx0Kx52hxE7C18hkMEggYlEifqWZtYaRgouJor+WMdPnQyEK13vgEWyVNup7SoeeoLMsr4kf5h6dOW11I15MUA==}
|
||||
peerDependencies:
|
||||
ajv: ^8.0.0
|
||||
peerDependenciesMeta:
|
||||
ajv:
|
||||
optional: true
|
||||
dependencies:
|
||||
ajv: 8.17.1
|
||||
|
||||
|
|
@ -9816,7 +9811,7 @@ packages:
|
|||
dependencies:
|
||||
'@apidevtools/json-schema-ref-parser': 9.1.2
|
||||
ajv: 8.17.1
|
||||
ajv-formats: 2.1.1(ajv@8.17.1)
|
||||
ajv-formats: 2.1.1
|
||||
body-parser: 1.20.3
|
||||
content-type: 1.0.5
|
||||
deep-freeze: 0.0.1
|
||||
|
|
@ -15947,7 +15942,7 @@ packages:
|
|||
dependencies:
|
||||
'@types/json-schema': 7.0.15
|
||||
ajv: 8.17.1
|
||||
ajv-formats: 2.1.1(ajv@8.17.1)
|
||||
ajv-formats: 2.1.1
|
||||
ajv-keywords: 5.1.0(ajv@8.17.1)
|
||||
dev: false
|
||||
|
||||
|
|
|
|||
145
scripts/diff-release-package.mts
Normal file
145
scripts/diff-release-package.mts
Normal file
|
|
@ -0,0 +1,145 @@
|
|||
/**
|
||||
* @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.dev/license
|
||||
*/
|
||||
|
||||
/**
|
||||
* Script that can be used to compare the local `npm_package` snapshot artifact
|
||||
* with the snapshot artifact from GitHub at upstream `HEAD`.
|
||||
*
|
||||
* This is useful during the `rules_js` migration to verify the npm artifact
|
||||
* doesn't differ unexpectedly.
|
||||
*
|
||||
* Example command: pnpm diff-release-package @angular/cli
|
||||
*/
|
||||
|
||||
import {GitClient} from '@angular/ng-dev';
|
||||
import childProcess from 'node:child_process';
|
||||
import fs from 'node:fs';
|
||||
import os from 'node:os';
|
||||
import path from 'node:path';
|
||||
import sh from 'shelljs';
|
||||
import {glob} from 'tinyglobby';
|
||||
|
||||
// Do not remove `.git` as we use Git for comparisons later.
|
||||
// Also preserve `uniqueId` as it's irrelevant for the diff and not included via Bazel.
|
||||
// The `README.md` is also put together outside of Bazel, so ignore it too.
|
||||
const SKIP_FILES = [/^README\.md$/, /^uniqueId$/, /\.map$/];
|
||||
|
||||
const packageName = process.argv[2];
|
||||
if (!packageName) {
|
||||
console.error('Expected package name to be specified.');
|
||||
process.exit(1);
|
||||
}
|
||||
|
||||
try {
|
||||
await main(packageName);
|
||||
} catch (e) {
|
||||
console.error(e);
|
||||
process.exitCode = 1;
|
||||
}
|
||||
|
||||
async function main(packageName: string) {
|
||||
const bazel = process.env.BAZEL ?? 'bazel';
|
||||
const git = await GitClient.get();
|
||||
const targetDir = packageName.replace(/^@/g, '').replace(/-/g, '_');
|
||||
|
||||
const snapshotRepoName = `angular/${packageName}-builds`;
|
||||
|
||||
const tmpDir = await fs.promises.mkdtemp(
|
||||
path.join(os.tmpdir(), `diff-release-package-${snapshotRepoName.replace(/\//g, '_')}`),
|
||||
);
|
||||
|
||||
console.info(`Cloning snapshot repo (${snapshotRepoName}) into ${tmpDir}..`);
|
||||
git.run(['clone', '--depth=1', `https://github.com/${snapshotRepoName}.git`, tmpDir]);
|
||||
console.info(`--> Cloned snapshot repo.`);
|
||||
|
||||
const bazelBinDir = childProcess
|
||||
.spawnSync(bazel, ['info', 'bazel-bin'], {
|
||||
shell: true,
|
||||
encoding: 'utf8',
|
||||
stdio: ['pipe', 'pipe', 'inherit'],
|
||||
})
|
||||
.stdout.trim();
|
||||
if (bazelBinDir === '') {
|
||||
throw new Error('Could not determine bazel-bin directory.');
|
||||
}
|
||||
|
||||
const outputPath = path.join(bazelBinDir, 'packages/', targetDir, 'npm_package');
|
||||
|
||||
// Delete old directory to avoid surprises, or stamping being outdated.
|
||||
await deleteDir(outputPath);
|
||||
|
||||
childProcess.spawnSync(
|
||||
bazel,
|
||||
['build', `//packages/${targetDir}:npm_package`, '--config=snapshot-build'],
|
||||
{
|
||||
shell: true,
|
||||
stdio: 'inherit',
|
||||
encoding: 'utf8',
|
||||
},
|
||||
);
|
||||
|
||||
console.info('--> Built npm package with --config=snapshot-build');
|
||||
console.error(`--> Output: ${outputPath}`);
|
||||
|
||||
const removeTasks: Promise<void>[] = [];
|
||||
for (const subentry of await glob('**/*', {
|
||||
dot: true,
|
||||
cwd: tmpDir,
|
||||
onlyFiles: true,
|
||||
ignore: ['.git'],
|
||||
})) {
|
||||
if (!SKIP_FILES.some((s) => s.test(subentry))) {
|
||||
continue;
|
||||
}
|
||||
|
||||
removeTasks.push(fs.promises.rm(path.join(tmpDir, subentry), {maxRetries: 3}));
|
||||
}
|
||||
await Promise.all(removeTasks);
|
||||
|
||||
// Stage all removed files that were skipped; to exclude them from the diff.
|
||||
git.run(['add', '-A'], {cwd: tmpDir});
|
||||
git.run(['commit', '-m', 'Delete skipped files for diff'], {cwd: tmpDir});
|
||||
|
||||
const copyTasks: Promise<void>[] = [];
|
||||
for (const subentry of await glob('**/*', {
|
||||
dot: true,
|
||||
cwd: outputPath,
|
||||
onlyFiles: true,
|
||||
ignore: ['.git'],
|
||||
})) {
|
||||
if (SKIP_FILES.some((s) => s.test(subentry))) {
|
||||
continue;
|
||||
}
|
||||
|
||||
copyTasks.push(
|
||||
fs.promises.cp(path.join(outputPath, subentry), path.join(tmpDir, subentry), {
|
||||
recursive: true,
|
||||
}),
|
||||
);
|
||||
}
|
||||
await Promise.all(copyTasks);
|
||||
|
||||
git.run(['config', 'core.filemode', 'false'], {cwd: tmpDir});
|
||||
|
||||
const diff = git.run(['diff', '--color'], {cwd: tmpDir}).stdout;
|
||||
|
||||
console.info('\n\n----- Diff ------');
|
||||
console.info(diff);
|
||||
|
||||
await deleteDir(tmpDir);
|
||||
}
|
||||
|
||||
async function deleteDir(dirPath: string) {
|
||||
if (!fs.existsSync(dirPath)) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Needed as Bazel artifacts are readonly and cannot be deleted otherwise.
|
||||
sh.chmod('-R', 'u+w', dirPath);
|
||||
await fs.promises.rm(dirPath, {recursive: true, force: true, maxRetries: 3});
|
||||
}
|
||||
Loading…
Reference in a new issue