refactor(docs-infra): convert deploy-to-firebase script to ESM (#43963)

Convert the `deploy-to-firebase` script (and corresponding tests) from
CommonJS format to ESM.

PR Close #43963
This commit is contained in:
George Kalpakas
2021-10-29 14:17:13 +03:00
committed by Alex Rickabaugh
parent 80d8eb87bb
commit 4f4b2b5ac9
6 changed files with 38 additions and 25 deletions
@@ -6,4 +6,4 @@ TODO (gkalpak): Add docs. Mention:
Relevant files: `aio/aio-builds-setup/scripts/test.sh`
- Deploying from CI.
Relevant files: `.circleci/config.yml`, `scripts/ci/deploy.sh`, `aio/scripts/build-artifacts.sh`,
`aio/scripts/deploy-to-firebase/index.js`
`aio/scripts/deploy-to-firebase/index.mjs`
+3 -3
View File
@@ -44,7 +44,7 @@
"example-use-local": "node tools/ng-packages-installer overwrite ./tools/examples/shared --debug --force",
"example-use-npm": "node tools/ng-packages-installer restore ./tools/examples/shared",
"example-check-local": "node tools/ng-packages-installer check ./tools/examples/shared",
"deploy-production": "node scripts/deploy-to-firebase",
"deploy-production": "node scripts/deploy-to-firebase/index.mjs",
"check-env": "yarn ~~check-env",
"postcheck-env": "yarn aio-check-local",
"payload-size": "scripts/payload.sh",
@@ -56,8 +56,8 @@
"docs-test": "node tools/transforms/test.js",
"redirects-test": "node tests/deployment/unit/test",
"firebase-utils-test": "node tools/firebase-test-utils/test",
"tools-lint": "eslint scripts/deploy-to-firebase && eslint tools/firebase-test-utils && eslint tools/ng-packages-installer",
"tools-test": "yarn docs-test && yarn boilerplate:test && jasmine tools/ng-packages-installer/index.spec.js && jasmine scripts/deploy-to-firebase/**/*.spec.js && yarn firebase-utils-test",
"tools-lint": "eslint --ext=.mjs scripts/deploy-to-firebase && eslint tools/firebase-test-utils && eslint tools/ng-packages-installer",
"tools-test": "yarn docs-test && yarn boilerplate:test && jasmine tools/ng-packages-installer/index.spec.js && jasmine scripts/deploy-to-firebase/**/*.spec.mjs && yarn firebase-utils-test",
"preserve-and-sync": "yarn docs",
"serve-and-sync": "run-p \"docs-watch --watch-only\" \"start {@}\" --",
"boilerplate:add": "node ./tools/examples/example-boilerplate add",
@@ -8,6 +8,9 @@ module.exports = {
jasmine: true,
node: true,
},
parserOptions: {
sourceType: 'module',
},
plugins: [
'jasmine',
],
@@ -2,11 +2,12 @@
//
// WARNING: `CI_SECRET_AIO_DEPLOY_FIREBASE_TOKEN` should NOT be printed.
//
'use strict';
const {cd, cp, exec, mv, sed, set} = require('shelljs');
import {dirname} from 'path';
import sh from 'shelljs';
import {fileURLToPath} from 'url';
set('-e');
sh.set('-e');
// Constants
@@ -15,10 +16,11 @@ const NG_REMOTE_URL = `https://github.com/${REPO_SLUG}.git`;
const GIT_REMOTE_REFS_CACHE = new Map();
// Exports
module.exports = {
export {
computeDeploymentsInfo,
computeInputVars,
computeMajorVersion,
getDirname,
getLatestCommit,
getMostRecentMinorBranch,
skipDeployment,
@@ -26,7 +28,11 @@ module.exports = {
};
// Run
if (require.main === module) {
// ESM alternative for CommonJS' `require.main === module`. For simplicity, we assume command
// references the full file path (including the file extension).
// See https://stackoverflow.com/questions/45136831/node-js-require-main-module#answer-60309682 for
// more details.
if (fileURLToPath(import.meta.url) === process.argv[1]) {
const isDryRun = process.argv[2] === '--dry-run';
const inputVars = computeInputVars(process.env);
const deploymentsInfo = computeDeploymentsInfo(inputVars);
@@ -67,7 +73,7 @@ function build({deployedUrl, deployEnv}) {
yarn(`build --configuration=${deployEnv} --progress=false`);
console.log('\n\n\n==== Add any mode-specific files into the AIO distribution. ====\n');
cp('-rf', `src/extra-files/${deployEnv}/.`, 'dist/');
sh.cp('-rf', `src/extra-files/${deployEnv}/.`, 'dist/');
console.log('\n\n\n==== Update opensearch descriptor for AIO with `deployedUrl`. ====\n');
yarn(`set-opensearch-url ${deployedUrl.replace(/[^/]$/, '$&/')}`); // The URL must end with `/`.
@@ -270,7 +276,7 @@ function deploy(data) {
siteId,
} = data;
cd(`${__dirname}/../..`);
sh.cd(`${getDirname(import.meta.url)}/../..`);
console.log('\n\n\n==== Run pre-deploy actions. ====\n');
preDeployActions.forEach(fn => fn(data));
@@ -286,6 +292,10 @@ function deploy(data) {
postDeployActions.forEach(fn => fn(data));
}
function getDirname(fileUrl) {
return dirname(fileURLToPath(fileUrl));
}
function getRemoteRefs(refOrPattern, {remote = NG_REMOTE_URL, retrieveFromCache = true} = {}) {
// If remote refs for the same `refOrPattern` and `remote` have been requested before, return the
// cached results. This improves the performance and ensures a more stable behavior.
@@ -298,7 +308,7 @@ function getRemoteRefs(refOrPattern, {remote = NG_REMOTE_URL, retrieveFromCache
const cmd = `git ls-remote ${remote} ${refOrPattern}`;
const result = (retrieveFromCache && GIT_REMOTE_REFS_CACHE.has(cmd)) ?
GIT_REMOTE_REFS_CACHE.get(cmd) :
exec(cmd, {silent: true}).trim().split('\n');
sh.exec(cmd, {silent: true}).trim().split('\n');
// Cache the result for future use (regardless of the value of `retrieveFromCache`).
GIT_REMOTE_REFS_CACHE.set(cmd, result);
@@ -337,13 +347,13 @@ function redirectToAngularIo() {
// See https://firebase.google.com/docs/hosting/full-config#redirects.
const redirectRule =
'{"type": 302, "regex": "^(.*/[^./]*)$", "destination": "https://angular.io:1"}';
sed('-i', /(\s*)"redirects": \[/, `$&\n$1 ${redirectRule},\n`, 'firebase.json');
sh.sed('-i', /(\s*)"redirects": \[/, `$&\n$1 ${redirectRule},\n`, 'firebase.json');
}
function removeServiceWorker() {
// Rename the SW manifest (`ngsw.json`). This will cause the ServiceWorker to unregister itself.
// See https://angular.io/guide/service-worker-devops#fail-safe.
mv('dist/ngsw.json', 'dist/ngsw.json.bak');
sh.mv('dist/ngsw.json', 'dist/ngsw.json.bak');
}
function serializeActions(actions) {
@@ -360,7 +370,8 @@ function testNoActiveRcDeployment({deployedUrl}) {
// Ensure a request for `ngsw.json` returns 404.
const ngswJsonUrl = `${deployedOrigin}/ngsw.json`;
const ngswJsonScript = `https.get('${ngswJsonUrl}', res => console.log(res.statusCode))`;
const ngswJsonActualStatusCode = exec(`node --eval "${ngswJsonScript}"`, {silent: true}).trim();
const ngswJsonActualStatusCode =
sh.exec(`node --eval "${ngswJsonScript}"`, {silent: true}).trim();
const ngswJsonExpectedStatusCode = '404';
if (ngswJsonActualStatusCode !== ngswJsonExpectedStatusCode) {
@@ -374,7 +385,7 @@ function testNoActiveRcDeployment({deployedUrl}) {
const fooBarScript =
`https.get('${fooBarUrl}', res => console.log(res.statusCode, res.headers.location))`;
const [fooBarActualStatusCode, fooBarActualRedirectUrl] =
exec(`node --eval "${fooBarScript}"`, {silent: true}).trim().split(' ');
sh.exec(`node --eval "${fooBarScript}"`, {silent: true}).trim().split(' ');
const fooBarExpectedStatusCode = '302';
const fooBarExpectedRedirectUrl = 'https://angular.io/foo/bar?baz=qux';
@@ -480,5 +491,5 @@ function yarn(cmd) {
// This is not strictly necessary, since CircleCI will mask secret environment variables in the
// output (see https://circleci.com/docs/2.0/env-vars/#secrets-masking), but is an extra
// precaution.
return exec(`yarn --silent ${cmd}`);
return sh.exec(`yarn --silent ${cmd}`);
}
@@ -1,16 +1,14 @@
#!/usr/bin/env node
'use strict';
const {execSync} = require('child_process');
const {
import {execSync} from 'child_process';
import {
computeDeploymentsInfo,
computeInputVars,
computeMajorVersion,
getDirname,
getLatestCommit,
getMostRecentMinorBranch,
skipDeployment,
validateDeploymentsInfo,
} = require('./index');
} from './index.mjs';
describe('deploy-to-firebase:', () => {
@@ -424,7 +422,8 @@ describe('deploy-to-firebase:', () => {
// and thus does not share the `getRemoteRefs()` cache. To improve stability, we retrieve the
// latest commit from master ignoring any cached entries.
const latestCommitOnMaster = getLatestCommit('master', {retrieveFromCache: false});
const cmd = `"${process.execPath}" "${__dirname}" --dry-run`;
const scriptPath = `${getDirname(import.meta.url)}/index.mjs`;
const cmd = `"${process.execPath}" "${scriptPath}" --dry-run`;
const env = {
CI_REPO_OWNER: 'angular',
CI_REPO_NAME: 'angular',
+1 -1
View File
@@ -4,7 +4,7 @@ This folder is used for extra files that should be included in deployments to fi
After the AIO application had been built and before it is deployed all files and folders inside the folder with the same name as the current deployment mode (next, stable, archive) will be copied to the `dist` folder.
See the `scripts/deploy-to-firebase/index.js` script for more details.
See the `scripts/deploy-to-firebase/index.mjs` script for more details.
**Note:**
The script always expects there to be a folder for the current deployment mode (even if it is empty).