fix(ngcc): only back up the original `prepublishOnly` script and not the overwritten one (#32427)

In order to prevent `ngcc`'d packages (e.g. libraries) from getting
accidentally published, `ngcc` overwrites the `prepublishOnly` npm
script to log a warning and exit with an error. In case we want to
restore the original script (e.g. "undo" `ngcc` processing), we keep a
backup of the original `prepublishOnly` script.

Previously, running `ngcc` a second time (e.g. for a different format)
would create a backup of the overwritten `prepublishOnly` script (if
there was originally no `prepublishOnly` script). As a result, if we
ever tried to "undo" `ngcc` processing and restore the original
`prepublishOnly` script, the error-throwing script would be restored
instead.

This commit fixes it by ensuring that we only back up a `prepublishOnly`
script, iff it is not the one we created ourselves (i.e. the
error-throwing one).

PR Close #32427
This commit is contained in:
George Kalpakas 2019-08-12 16:38:42 +03:00 committed by Matias Niemelä
parent bd1de32b33
commit 38359b166e
2 changed files with 28 additions and 4 deletions

View File

@ -59,16 +59,20 @@ export function markAsProcessed(
}
const scripts = packageJson.scripts || (packageJson.scripts = {});
scripts.prepublishOnly__ivy_ngcc_bak =
scripts.prepublishOnly__ivy_ngcc_bak || scripts.prepublishOnly;
scripts.prepublishOnly = 'node --eval \"console.error(\'' +
const oldPrepublishOnly = scripts.prepublishOnly;
const newPrepublishOnly = 'node --eval \"console.error(\'' +
'ERROR: Trying to publish a package that has been compiled by NGCC. This is not allowed.\\n' +
'Please delete and rebuild the package, without compiling with NGCC, before attempting to publish.\\n' +
'Note that NGCC may have been run by importing this package into another project that is being built with Ivy enabled.\\n' +
'\')\" ' +
'&& exit 1';
if (oldPrepublishOnly && (oldPrepublishOnly !== newPrepublishOnly)) {
scripts.prepublishOnly__ivy_ngcc_bak = oldPrepublishOnly;
}
scripts.prepublishOnly = newPrepublishOnly;
// Just in case this package.json was synthesized due to a custom configuration
// we will ensure that the path to the containing folder exists before we write the file.
fs.ensureDir(dirname(packageJsonPath));

View File

@ -147,6 +147,26 @@ runInEachFileSystem(() => {
expect(pkg.scripts.prepublishOnly).toContain('This is not allowed');
expect(pkg.scripts.prepublishOnly__ivy_ngcc_bak).toBe(prepublishOnly);
});
it(`should not keep backup of overwritten 'prepublishOnly' script`, () => {
const COMMON_PACKAGE_PATH = _('/node_modules/@angular/common/package.json');
const fs = getFileSystem();
let pkg = JSON.parse(fs.readFile(COMMON_PACKAGE_PATH));
markAsProcessed(fs, pkg, COMMON_PACKAGE_PATH, ['fesm2015']);
pkg = JSON.parse(fs.readFile(COMMON_PACKAGE_PATH));
expect(pkg.scripts.prepublishOnly).toContain('This is not allowed');
expect(pkg.scripts.prepublishOnly__ivy_ngcc_bak).toBeUndefined();
// Running again, now that there is `prepublishOnly` script (created by `ngcc`), it should
// still not back it up as `prepublishOnly__ivy_ngcc_bak`.
markAsProcessed(fs, pkg, COMMON_PACKAGE_PATH, ['fesm2015']);
pkg = JSON.parse(fs.readFile(COMMON_PACKAGE_PATH));
expect(pkg.scripts.prepublishOnly).toContain('This is not allowed');
expect(pkg.scripts.prepublishOnly__ivy_ngcc_bak).toBeUndefined();
});
});
describe('hasBeenProcessed', () => {