Skip to content

Commit dc9872e

Browse files
committed
feat(ng-dev): add sync-module-bazel command to update pnpm and typescript versions and integrity in MODULE.bazel
This is helpful to ensure that these versions are always synced.
1 parent 2b0a301 commit dc9872e

File tree

6 files changed

+145
-6
lines changed

6 files changed

+145
-6
lines changed

MODULE.bazel

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -68,7 +68,8 @@ use_repo(rules_angular, rules_angular_configurable_deps = "dev_infra_rules_angul
6868
pnpm = use_extension("@aspect_rules_js//npm:extensions.bzl", "pnpm")
6969
pnpm.pnpm(
7070
name = "pnpm",
71-
pnpm_version = "10.16.1",
71+
pnpm_version = "10.26.0",
72+
pnpm_version_integrity = "sha512-Oz9scl6+cSUGwKsa1BM8+GsfS2h+/85iqbOLTXLjlUJC5kMZD8UfoWQpScc19APevUT1yw7dZXq+Y6i2p+HkAg==",
7273
)
7374
use_repo(pnpm, "pnpm")
7475

MODULE.bazel.lock

Lines changed: 4 additions & 4 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

ng-dev/misc/cli.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@
77
*/
88
import {Argv} from 'yargs';
99

10+
import {SyncModuleBazelModule} from './sync-module-bazel/cli.js';
1011
import {BuildAndLinkCommandModule} from './build-and-link/cli.js';
1112
import {GeneratedFilesModule} from './generated-files/cli.js';
1213
import {GeneratedNodeJsToolchainModule} from './generate-nodejs-toolchain/cli.js';
@@ -16,6 +17,7 @@ export function buildMiscParser(localYargs: Argv) {
1617
return localYargs
1718
.help()
1819
.strict()
20+
.command(SyncModuleBazelModule)
1921
.command(BuildAndLinkCommandModule)
2022
.command(GeneratedFilesModule)
2123
.command(GeneratedNodeJsToolchainModule);
Lines changed: 120 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,120 @@
1+
/**
2+
* @license
3+
* Copyright Google LLC
4+
*
5+
* Use of this source code is governed by an MIT-style license that can be
6+
* found in the LICENSE file at https://angular.io/license
7+
*/
8+
9+
import {Argv, CommandModule} from 'yargs';
10+
import {readFileSync, writeFileSync} from 'node:fs';
11+
import {execSync} from 'node:child_process';
12+
import {join} from 'node:path';
13+
import {Log} from '../../utils/logging';
14+
15+
async function builder(argv: Argv) {
16+
return argv;
17+
}
18+
19+
async function handler() {
20+
const rootDir = process.cwd();
21+
const packageJsonPath = join(rootDir, 'package.json');
22+
const moduleBazelPath = join(rootDir, 'MODULE.bazel');
23+
24+
interface PackageJson {
25+
engines?: {
26+
pnpm?: string;
27+
};
28+
dependencies?: {
29+
typescript?: string;
30+
};
31+
devDependencies?: {
32+
typescript?: string;
33+
};
34+
}
35+
36+
// Read package.json
37+
const packageJson = JSON.parse(readFileSync(packageJsonPath, 'utf8')) as PackageJson;
38+
const pnpmVersion = packageJson.engines?.pnpm;
39+
const tsVersion = packageJson.dependencies?.typescript || packageJson.devDependencies?.typescript;
40+
41+
if (!pnpmVersion) {
42+
throw new Error('Could not find engines.pnpm in package.json');
43+
}
44+
45+
if (!tsVersion) {
46+
throw new Error('Could not find typescript in dependencies or devDependencies in package.json');
47+
}
48+
49+
// Helper to get integrity
50+
async function getIntegrity(pkg: string, version: string): Promise<string> {
51+
const response = await fetch(`https://registry.npmjs.org/${pkg}/${version}`);
52+
if (!response.ok) {
53+
throw new Error(`Failed to request ${pkg}@${version}: ${response.statusText}`);
54+
}
55+
56+
const {dist} = (await response.json()) as {dist: {integrity: string}};
57+
58+
return dist.integrity;
59+
}
60+
61+
// Read MODULE.bazel
62+
let originalBazelContent = readFileSync(moduleBazelPath, 'utf8');
63+
let moduleBazelContent = originalBazelContent;
64+
65+
if (moduleBazelContent.includes('pnpm_version')) {
66+
console.log(`Resolving integrity for pnpm@${pnpmVersion}...`);
67+
const pnpmIntegrity = await getIntegrity('pnpm', pnpmVersion);
68+
69+
// Update pnpm version and integrity
70+
moduleBazelContent = moduleBazelContent.replace(
71+
/pnpm_version = ".*?"/,
72+
`pnpm_version = "${pnpmVersion}"`,
73+
);
74+
75+
if (moduleBazelContent.includes('pnpm_version_integrity =')) {
76+
moduleBazelContent = moduleBazelContent.replace(
77+
/pnpm_version_integrity = ".*?"/,
78+
`pnpm_version_integrity = "${pnpmIntegrity}"`,
79+
);
80+
} else {
81+
moduleBazelContent = moduleBazelContent.replace(
82+
/pnpm_version = ".*?"/,
83+
`$&,\n pnpm_version_integrity = "${pnpmIntegrity}"`,
84+
);
85+
}
86+
}
87+
88+
// Update typescript version and integrity
89+
if (moduleBazelContent.includes('ts_version')) {
90+
console.log(`Resolving integrity for typescript@${tsVersion}...`);
91+
const tsIntegrity = await getIntegrity('typescript', tsVersion);
92+
93+
moduleBazelContent = moduleBazelContent.replace(
94+
/ts_version = ".*?"/,
95+
`ts_version = "${tsVersion}"`,
96+
);
97+
moduleBazelContent = moduleBazelContent.replace(
98+
/ts_integrity = ".*?"/,
99+
`ts_integrity = "${tsIntegrity}"`,
100+
);
101+
102+
if (originalBazelContent !== moduleBazelContent) {
103+
writeFileSync(moduleBazelPath, moduleBazelContent);
104+
105+
try {
106+
execSync('pnpm bazel mod deps --lockfile_mode=update', {stdio: 'inherit'});
107+
} catch (e) {
108+
Log.debug(e);
109+
}
110+
}
111+
}
112+
}
113+
114+
/** CLI command module. */
115+
export const SyncModuleBazelModule: CommandModule = {
116+
builder,
117+
handler,
118+
command: 'sync-module-bazel',
119+
describe: 'Sync pnpm and typescript versions in MODULE.bazel with package.json.',
120+
};

renovate-presets/default.json5

Lines changed: 16 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -48,6 +48,7 @@
4848
// Workaround for https://github.com/renovatebot/renovate/issues/25557
4949
{
5050
postUpgradeTasks: {
51+
matchManagers: ['bazel', 'bazel-module', 'bazelisk'],
5152
commands: [
5253
'git restore .npmrc || true', // In case `.npmrc` avoid a hard error.
5354
'bazel mod deps --lockfile_mode=update',
@@ -56,7 +57,21 @@
5657
// run when in the same branch there are mixtures of update types by different managers.
5758
executionMode: 'update',
5859
},
59-
matchManagers: ['bazel', 'bazel-module', 'bazelisk'],
60+
},
61+
62+
// Enable 'postUpdateTasks' for changes that effect the typescript and pnpm versions.
63+
// This is to ensure that the `MODULE.bazel` is updated with the correct versions.
64+
{
65+
matchManagers: ['npm'],
66+
matchDepNames: ['pnpm', 'typescript'],
67+
postUpgradeTasks: {
68+
commands: [
69+
'git restore .npmrc || true', // In case `.npmrc` avoid a hard error.
70+
'pnpm install --frozen-lockfile',
71+
'pnpm ng-dev misc sync-module-bazel || true', // TODO(alanagius): Remove || true once all repos update to the latest ng-dev.
72+
],
73+
executionMode: 'branch',
74+
},
6075
},
6176

6277
// Rule to require manual approval for NPM updates on branches other than 'main'.

renovate.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@
1313
"commands": [
1414
"pnpm install --frozen-lockfile",
1515
"pnpm bazel mod deps --lockfile_mode=update",
16+
"pnpm ng-dev misc sync-module-bazel",
1617
"pnpm update-generated-files"
1718
],
1819
"executionMode": "branch"

0 commit comments

Comments
 (0)