Skip to content

Commit da47bd8

Browse files
Switch registry at CI builds explicitly (#2075)
Dataform uses trusted registry for CI builds. It does that by relying on nodejs's npm install interaction with yarn.lock. This interaction is known to be error-prone (for ex. npm/cli#5126), yarn recommends to only use yarn CLI when working with it's ecosystem. In particular, it blocks update of the Node, forcing us to use the version that is long out of EOL support (v16). Newer version breaks yarn.lock on npm install. Apart from that we don't verify that yarn.lock updates only registry. Addressing that by reimplementing registry substitution explicitly and switching to yarn install --freeze-lockfile instead of npm install. This will ensure that: We only change the registry, all other parts of the lock file like versions or hashsums remain the same. We don't change resolved versions by accident if there is a conflict between package.json spec and lockfile. Long-term solution would be migration to a supported NodeJS rules (most likely Aspect's), where we would be able to leverage PNPM, whose lockfile doesn't fix registry URL at all - only versions and hashsums.
1 parent e64b7b0 commit da47bd8

4 files changed

Lines changed: 49 additions & 2 deletions

File tree

scripts/publish

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,8 @@ fi
1616

1717
# Run all the tests.
1818
bazel run @nodejs//:yarn config set registry https://us-npm.pkg.dev/artifact-foundry-prod/ah-3p-staging-npm/
19-
bazel run @nodejs//:npm install
19+
bazel run //tools/registry-tools:switch_registry -- $(pwd)/yarn.lock https://us-npm.pkg.dev/artifact-foundry-prod/npm-3p-trusted/
20+
bazel run @nodejs//:yarn install -- --frozen-lockfile
2021
bazel test //... --build_tests_only
2122

2223
# After the code is build with Airlock dependencies, we change the registry to public npmjs

scripts/run_tests_on_cloudbuild

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,9 @@
22
set -e
33

44
bazel run @nodejs//:yarn config set registry https://us-npm.pkg.dev/artifact-foundry-prod/npm-3p-trusted/
5-
bazel run @nodejs//:npm install
5+
bazel run //tools/registry-tools:switch_registry -- $(pwd)/yarn.lock https://us-npm.pkg.dev/artifact-foundry-prod/npm-3p-trusted/
6+
# Install from trusted registry, prohibit lockfile changes.
7+
bazel run @nodejs//:yarn install -- --frozen-lockfile
68

79
# Run unit tests
810
./scripts/run_tests

tools/registry-tools/BUILD

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
load("@build_bazel_rules_nodejs//:index.bzl", "nodejs_binary")
2+
3+
nodejs_binary(
4+
name = "switch_registry",
5+
entry_point = "switch_registry.js",
6+
)
Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,38 @@
1+
// Replace Registry in yarn.lock with the specified one.
2+
// This script is executed before any node packages are fetched,
3+
// keep depencency free.
4+
5+
const fs = require('fs');
6+
7+
const args = process.argv.slice(2);
8+
const lockfilePath = args[0];
9+
let newRegistry = args[1];
10+
11+
if (!newRegistry) {
12+
console.error('Usage: node switch_registry.js /path/to/yarn.lock https://new.registry.com');
13+
process.exit(1);
14+
}
15+
16+
if (!newRegistry.match('https://.*')) {
17+
console.error(`Not a valid registry URL: ${newRegistry}`);
18+
process.exit(1);
19+
}
20+
21+
if (newRegistry.endsWith('/')) {
22+
newRegistry = newRegistry.slice(0, -1);
23+
}
24+
25+
try {
26+
const content = fs.readFileSync(lockfilePath, 'utf8');
27+
const registryRegex = /^(\s+resolved ")(https?:\/\/[^\/]+)(.*)"$/gm;
28+
29+
const updatedContent = content.replace(registryRegex, (match, prefix, oldOrigin, path) => {
30+
return `${prefix}${newRegistry}${path}"`;
31+
});
32+
33+
fs.writeFileSync(lockfilePath, updatedContent, 'utf8');
34+
35+
console.log(`yarn lockfile ${lockfilePath} updated successfully to: ${newRegistry}`);
36+
} catch (error) {
37+
console.error('Error processing yarn.lock:', error.message);
38+
}

0 commit comments

Comments
 (0)