Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
# 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=-2023857461
package.json=-859706413
pnpm-lock.yaml=1168783332
package.json=2055569205
pnpm-lock.yaml=1847443622
pnpm-workspace.yaml=1711114604
yarn.lock=86020133
3 changes: 2 additions & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,8 @@
"ng-dev": "node --no-warnings=ExperimentalWarning --loader ts-node/esm/transpile-only node_modules/@angular/ng-dev/bundles/cli.mjs",
"public-api:update": "node goldens/public-api/manage.js accept",
"ts-circular-deps": "yarn ng-dev ts-circular-deps --config ./scripts/circular-deps-test.conf.mjs",
"check-tooling-setup": "tsc --project .ng-dev/tsconfig.json"
"check-tooling-setup": "tsc --project .ng-dev/tsconfig.json",
"diff-release-package": "node --no-warnings=ExperimentalWarning --loader ts-node/esm/transpile-only scripts/diff-release-package.mts"
},
"repository": {
"type": "git",
Expand Down
3 changes: 1 addition & 2 deletions pnpm-lock.yaml

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

139 changes: 139 additions & 0 deletions scripts/diff-release-package.mts
Original file line number Diff line number Diff line change
@@ -0,0 +1,139 @@
/**
* @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: yarn 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';

// 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', '.git'];

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 monorepoData = JSON.parse(fs.readFileSync('./.monorepo.json', 'utf-8'));
const targetDir = packageName.replace(/^@/g, '').replace(/-/g, '_');

// `help/` is only generated in snapshots outside of Bazel. Ignore it when
// diffing the Angular CLI package
// https://github.com/angular/angular-cli/blob/main/scripts/json-help.mts#L16-L17.
if (packageName === '@angular/cli') {
SKIP_FILES.push('help');
}

const snapshotRepoName = monorepoData.packages[packageName]?.snapshotRepo;
const tmpDir = await fs.promises.mkdtemp(
path.join(os.tmpdir(), `diff-release-package-${snapshotRepoName.replace(/\//g, '_')}`),
);

console.log(`Cloning snapshot repo (${snapshotRepoName}) into ${tmpDir}..`);
git.run(['clone', `https://github.com/${snapshotRepoName}.git`, tmpDir]);
console.log(`--> 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'],
{
shell: true,
stdio: 'inherit',
encoding: 'utf8',
},
);

console.log('--> Built npm package with --config=snapshot');
console.error(`--> Output: ${outputPath}`);

const removeTasks: Promise<void>[] = [];
for (const subentry of await fs.promises.readdir(tmpDir)) {
if (SKIP_FILES.includes(subentry)) {
continue;
}

removeTasks.push(
fs.promises.rm(path.join(tmpDir, subentry), { recursive: true, maxRetries: 3 }),
);
}
await Promise.all(removeTasks);

const copyTasks: Promise<void>[] = [];
for (const subentry of await fs.promises.readdir(outputPath)) {
if (SKIP_FILES.includes(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.log('\n\n----- Diff ------');
console.log(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