Skip to content

Commit 9237f29

Browse files
committed
build: ensure postinstall patches are applied properly
Ensures the postinstall fails if some replacements could not be made. This ensures that we don't update Angular and invalidate some of the workarounds. This would result in broken release output then.
1 parent 66c8708 commit 9237f29

File tree

1 file changed

+61
-34
lines changed

1 file changed

+61
-34
lines changed

tools/bazel/postinstall-patches.js

Lines changed: 61 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -6,9 +6,13 @@
66

77
const shelljs = require('shelljs');
88
const path = require('path');
9+
const fs = require('fs');
10+
11+
/** Path to the project directory. */
12+
const projectDir = path.join(__dirname, '../..');
913

1014
shelljs.set('-e');
11-
shelljs.cd(path.join(__dirname, '../..'));
15+
shelljs.cd(projectDir);
1216

1317
// Do not apply postinstall patches when running "postinstall" outside. The
1418
// "generate_build_file.js" file indicates that we run in Bazel managed node modules.
@@ -22,68 +26,91 @@ shelljs.exec('ngc -p angular-tsconfig.json');
2226
// Workaround for https://github.com/angular/angular/issues/30586. It's not possible to
2327
// enable tsickle decorator processing without enabling import rewriting to closure.
2428
// This replacement allows us to enable decorator processing without rewriting imports.
25-
shelljs.sed(
26-
'-i', /(this\.transformTypesToClosure) = bazelOpts\.tsickle;/, '$1 = false;',
29+
searchAndReplace(
30+
/(this\.transformTypesToClosure) = bazelOpts\.tsickle;/, '$1 = false;',
2731
'node_modules/@bazel/typescript/internal/tsc_wrapped/compiler_host.js');
28-
shelljs.sed(
29-
'-i', 'bazelOpts\.tsickleExternsPath', 'null',
32+
searchAndReplace(
33+
'bazelOpts\.tsickleExternsPath', 'null',
3034
'node_modules/@bazel/typescript/internal/tsc_wrapped/tsc_wrapped.js');
3135

3236
// Workaround for https://github.com/angular/angular/issues/32389. We need to ensure
3337
// that tsickle is available for esm5 output re-compilations.
34-
shelljs.sed(
35-
'-i', '@npm//@bazel/typescript/bin:tsc_wrapped',
38+
searchAndReplace(
39+
'@npm//@bazel/typescript/bin:tsc_wrapped',
3640
'@angular_material//tools/bazel:tsc_wrapped_with_tsickle',
3741
'node_modules/@angular/bazel/src/esm5.bzl');
3842

3943
// Workaround for: https://github.com/angular/angular/issues/32651. We just do not
4044
// generate re-exports for secondary entry-points. Similar to what "ng-packagr" does.
41-
shelljs.sed('-i', /(?!function\s+)createMetadataReexportFile\([^)]+\);/,
42-
'', 'node_modules/@angular/bazel/src/ng_package/packager.js');
43-
shelljs.sed('-i', /(?!function\s+)createTypingsReexportFile\([^)]+\);/,
44-
'', 'node_modules/@angular/bazel/src/ng_package/packager.js');
45+
searchAndReplace(
46+
/(?!function\s+)createMetadataReexportFile\([^)]+\);/, '',
47+
'node_modules/@angular/bazel/src/ng_package/packager.js');
48+
searchAndReplace(
49+
/(?!function\s+)createTypingsReexportFile\([^)]+\);/, '',
50+
'node_modules/@angular/bazel/src/ng_package/packager.js');
4551

4652
// Workaround for: https://github.com/angular/angular/pull/32650
47-
shelljs.sed('-i', 'var indexFile;', `
53+
searchAndReplace(
54+
'var indexFile;', `
4855
var publicApiFile = files.find(f => f.endsWith('/public-api.ts'));
4956
var moduleFile = files.find(f => f.endsWith('/module.ts'));
5057
var indexFile = publicApiFile || moduleFile;
51-
`, 'node_modules/@angular/compiler-cli/src/metadata/bundle_index_host.js');
52-
shelljs.sed('-i', 'var resolvedEntryPoint = null;', `
58+
`,
59+
'node_modules/@angular/compiler-cli/src/metadata/bundle_index_host.js');
60+
searchAndReplace(
61+
'var resolvedEntryPoint = null;', `
5362
var publicApiFile = tsFiles.find(f => f.endsWith('/public-api.ts'));
5463
var moduleFile = tsFiles.find(f => f.endsWith('/module.ts'));
5564
var resolvedEntryPoint = publicApiFile || moduleFile || null;
56-
`, 'node_modules/@angular/compiler-cli/src/ngtsc/entry_point/src/logic.js');
65+
`,
66+
'node_modules/@angular/compiler-cli/src/ngtsc/entry_point/src/logic.js');
5767

58-
// Workaround for https://github.com/angular/angular/issues/32603. Note that we don't
59-
// want to apply the patch if it has been applied already.
60-
if (!shelljs.test('-f', 'node_modules/@angular/bazel/src/ng_package/rollup_bin.js')) {
61-
shelljs.cat(path.join(__dirname, './rollup_windows_arguments.patch')).exec('patch -p0');
62-
}
68+
// Workaround for https://github.com/angular/angular/issues/32603.
69+
shelljs.cat(path.join(__dirname, './rollup_windows_arguments.patch')).exec('patch -p0');
6370

6471
// Workaround for: https://hackmd.io/MlqFp-yrSx-0mw4rD7dnQQ?both. We only want to discard
6572
// the metadata of files in the bazel managed node modules. That way we keep the default
6673
// behavior of ngc-wrapped except for dependencies between sources of the library. This makes
6774
// the "generateCodeForLibraries" flag more accurate in the Bazel environment where previous
6875
// compilations should not be treated as external libraries. Read more about this in the document.
69-
shelljs.sed('-i', /if \((this\.options\.generateCodeForLibraries === false)/, `
76+
searchAndReplace(
77+
/if \((this\.options\.generateCodeForLibraries === false)/, `
7078
const fs = require('fs');
7179
const hasFlatModuleBundle = fs.existsSync(filePath.replace('.d.ts', '.metadata.json'));
7280
if ((filePath.includes('node_modules/') || !hasFlatModuleBundle) && $1`,
73-
'node_modules/@angular/compiler-cli/src/transformers/compiler_host.js');
81+
'node_modules/@angular/compiler-cli/src/transformers/compiler_host.js');
7482
shelljs.cat(path.join(__dirname, './flat_module_factory_resolution.patch')).exec('patch -p0');
7583
// The three replacements below ensure that metadata files can be read by NGC and
7684
// that metadata files are collected as Bazel action inputs.
77-
shelljs.sed('-i', /(const NGC_ASSETS = \/[^(]+\()([^)]*)(\).*\/;)/, '$1$2|metadata.json$3',
78-
'node_modules/@angular/bazel/src/ngc-wrapped/index.js');
79-
shelljs.sed('-i', /^((\s*)results = depset\(dep.angular.summaries, transitive = \[results]\))$/,
80-
`$1#\n$2results = depset(dep.angular.metadata, transitive = [results])`,
81-
'node_modules/@angular/bazel/src/ng_module.bzl');
82-
shelljs.sed('-i',
83-
/^((\s*)results = depset\(target.angular.summaries if hasattr\(target, "angular"\) else \[]\))$/,
84-
`$1#\n$2results = depset(target.angular.metadata if hasattr(target, "angular") else [], transitive = [results])`,
85-
'node_modules/@angular/bazel/src/ng_module.bzl');
85+
searchAndReplace(
86+
/(const NGC_ASSETS = \/[^(]+\()([^)]*)(\).*\/;)/, '$1$2|metadata.json$3',
87+
'node_modules/@angular/bazel/src/ngc-wrapped/index.js');
88+
searchAndReplace(
89+
/^((\s*)results = depset\(dep.angular.summaries, transitive = \[results]\))$/m,
90+
`$1#\n$2results = depset(dep.angular.metadata, transitive = [results])`,
91+
'node_modules/@angular/bazel/src/ng_module.bzl');
92+
searchAndReplace(
93+
/^((\s*)results = depset\(target.angular.summaries if hasattr\(target, "angular"\) else \[]\))$/m,
94+
`$1#\n$2results = depset(target.angular.metadata if hasattr(target, "angular") else [], transitive = [results])`,
95+
'node_modules/@angular/bazel/src/ng_module.bzl');
8696
// Ensure that "metadata" of transitive dependencies can be collected.
87-
shelljs.sed('-i', /("metadata": outs.metadata),/,
88-
`$1 + [m for dep in ctx.attr.deps if hasattr(dep, "angular") for m in dep.angular.metadata],`,
89-
'node_modules/@angular/bazel/src/ng_module.bzl');
97+
searchAndReplace(
98+
/("metadata": outs.metadata),/,
99+
`$1 + [m for dep in ctx.attr.deps if hasattr(dep, "angular") for m in dep.angular.metadata],`,
100+
'node_modules/@angular/bazel/src/ng_module.bzl');
101+
102+
/**
103+
* Reads the specified file and replaces matches of the search expression
104+
* with the given replacement. Throws if no changes were made.
105+
*/
106+
function searchAndReplace(search, replacement, relativeFilePath) {
107+
const filePath = path.join(projectDir, relativeFilePath);
108+
const originalContent = fs.readFileSync(filePath, 'utf8');
109+
const newFileContent = originalContent.replace(search, replacement);
110+
111+
if (originalContent === newFileContent) {
112+
throw Error(`Could not perform replacement in: ${filePath}.`);
113+
}
114+
115+
fs.writeFileSync(filePath, newFileContent, 'utf8');
116+
}

0 commit comments

Comments
 (0)