refactor(docs-infra): decouple deploying from other operations in `deploy-to-firebase.js` (#39853)

Previously, the `deploy()` function in `deploy-to-firebase.js` would
also perform other operations (beyond deploying), such as building the
app, checking the generated payload size, testing the PWA score of the
deployed app.

This commit decouples these operations, so that deploying can be
performed independently.

NOTE:
In a subsequent commit, this will be leveraged fix an issue with
`rc.angular.io` redirects in the presence of a ServiceWorker by
deploying the same artifacts to multiple Firebase projects/sites.
See #39760 for more details.

PR Close #39853
This commit is contained in:
George Kalpakas 2020-11-30 13:59:10 +02:00 committed by Misko Hevery
parent c923aaf64b
commit 6e6eee6d5b
2 changed files with 119 additions and 63 deletions

View File

@ -30,13 +30,15 @@ if (require.main === module) {
console.log(deploymentInfo.reason);
} else {
console.log(
`Git branch : ${inputVars.currentBranch}\n` +
`Git commit : ${inputVars.currentCommit}\n` +
`Build/deploy mode : ${deploymentInfo.deployEnv}\n` +
`Firebase project : ${deploymentInfo.projectId}\n` +
`Firebase site : ${deploymentInfo.siteId}\n` +
`Deployment URLs : ${deploymentInfo.deployedUrl}\n` +
` https://${deploymentInfo.siteId}.web.app/`);
`Git branch : ${inputVars.currentBranch}\n` +
`Git commit : ${inputVars.currentCommit}\n` +
`Build/deploy mode : ${deploymentInfo.deployEnv}\n` +
`Firebase project : ${deploymentInfo.projectId}\n` +
`Firebase site : ${deploymentInfo.siteId}\n` +
`Pre-deploy actions : ${serializeActions(deploymentInfo.preDeployActions)}\n` +
`Post-deploy actions : ${serializeActions(deploymentInfo.postDeployActions)}\n` +
`Deployment URLs : ${deploymentInfo.deployedUrl}\n` +
` https://${deploymentInfo.siteId}.web.app/`);
if (!isDryRun) {
deploy({...inputVars, ...deploymentInfo});
@ -45,6 +47,22 @@ if (require.main === module) {
}
// Helpers
function build({deployedUrl, deployEnv}) {
console.log('\n\n\n==== Build the AIO app. ====\n');
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/');
console.log('\n\n\n==== Update opensearch descriptor for AIO with `deployedUrl`. ====\n');
yarn(`set-opensearch-url ${deployedUrl.replace(/[^/]$/, '$&/')}`); // The URL must end with `/`.
}
function checkPayloadSize() {
console.log('\n\n\n==== Check payload size and upload the numbers to Firebase DB. ====\n');
yarn('payload-size');
}
function computeDeploymentInfo(
{currentBranch, currentCommit, isPullRequest, repoName, repoOwner, stableBranch}) {
// Do not deploy if we are running in a fork.
@ -72,24 +90,32 @@ function computeDeploymentInfo(
projectId: 'angular-io',
siteId: 'next-angular-io-site',
deployedUrl: 'https://next.angular.io/',
preDeployActions: [build, checkPayloadSize],
postDeployActions: [testPwaScore],
},
rc: {
deployEnv: 'rc',
projectId: 'angular-io',
siteId: 'rc-angular-io-site',
deployedUrl: 'https://rc.angular.io/',
preDeployActions: [build, checkPayloadSize],
postDeployActions: [testPwaScore],
},
stable: {
deployEnv: 'stable',
projectId: 'angular-io',
siteId: `v${currentBranchMajorVersion}-angular-io-site`,
deployedUrl: 'https://angular.io/',
preDeployActions: [build, checkPayloadSize],
postDeployActions: [testPwaScore],
},
archive: {
deployEnv: 'archive',
projectId: 'angular-io',
siteId: `v${currentBranchMajorVersion}-angular-io-site`,
deployedUrl: `https://v${currentBranchMajorVersion}.angular.io/`,
preDeployActions: [build, checkPayloadSize],
postDeployActions: [testPwaScore],
},
};
@ -160,21 +186,20 @@ function computeMajorVersion(branchName) {
return +branchName.split('.', 1)[0];
}
function deploy(
{currentCommit, deployedUrl, deployEnv, firebaseToken, minPwaScore, projectId, siteId}) {
function deploy(data) {
const {
currentCommit,
firebaseToken,
postDeployActions,
preDeployActions,
projectId,
siteId,
} = data;
cd(`${__dirname}/..`);
console.log('\n\n\n==== Build the AIO app. ====\n');
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/');
console.log('\n\n\n==== Update opensearch descriptor for AIO with `deployedUrl`. ====\n');
yarn(`set-opensearch-url ${deployedUrl.replace(/[^/]$/, '$&/')}`); // The URL must end with `/`.
console.log('\n\n\n==== Check payload size and upload the numbers to Firebase DB. ====\n');
yarn('payload-size');
console.log('\n\n\n==== Run pre-deploy actions. ====\n');
preDeployActions.forEach(fn => fn(data));
console.log('\n\n\n==== Deploy AIO to Firebase hosting. ====\n');
yarn(`firebase use "${projectId}" --token "${firebaseToken}"`);
@ -183,8 +208,8 @@ function deploy(
`firebase deploy --only hosting:aio --message "Commit: ${currentCommit}" --non-interactive ` +
`--token "${firebaseToken}"`);
console.log('\n\n\n==== Run PWA-score tests. ====\n');
yarn(`test-pwa-score "${deployedUrl}" "${minPwaScore}"`);
console.log('\n\n\n==== Run post-deploy actions. ====\n');
postDeployActions.forEach(fn => fn(data));
}
function getRemoteRefs(refOrPattern, remote = NG_REMOTE_URL) {
@ -195,10 +220,19 @@ function getLatestCommit(branchName, remote = undefined) {
return getRemoteRefs(branchName, remote)[0].slice(0, 40);
}
function serializeActions(actions) {
return actions.map(fn => fn.name).join(', ');
}
function skipDeployment(reason) {
return {reason, skipped: true};
}
function testPwaScore({deployedUrl, minPwaScore}) {
console.log('\n\n\n==== Run PWA-score tests. ====\n');
yarn(`test-pwa-score "${deployedUrl}" "${minPwaScore}"`);
}
function yarn(cmd) {
// Using `--silent` to ensure no secret env variables are printed.
//

View File

@ -6,60 +6,70 @@ const {computeDeploymentInfo, computeInputVars, getLatestCommit} = require('./de
describe('deploy-to-firebase:', () => {
// Helpers
const jsonFunctionReplacer = (_key, val) =>
(typeof val === 'function') ? `function:${val.name}` : val;
const getDeploymentInfoFor = env => {
const deploymentInfo = computeDeploymentInfo(computeInputVars(env));
return JSON.parse(JSON.stringify(deploymentInfo, jsonFunctionReplacer));
};
it('master - skip deploy - not angular', () => {
expect(computeDeploymentInfo(computeInputVars({
expect(getDeploymentInfoFor({
CI_REPO_OWNER: 'angular',
CI_REPO_NAME: 'notangular',
}))).toEqual({
})).toEqual({
skipped: true,
reason: 'Skipping deploy because this is not angular/angular.',
});
});
it('master - skip deploy - angular fork', () => {
expect(computeDeploymentInfo(computeInputVars({
expect(getDeploymentInfoFor({
CI_REPO_OWNER: 'notangular',
CI_REPO_NAME: 'angular',
}))).toEqual({
})).toEqual({
skipped: true,
reason: 'Skipping deploy because this is not angular/angular.',
});
});
it('master - skip deploy - pull request', () => {
expect(computeDeploymentInfo(computeInputVars({
expect(getDeploymentInfoFor({
CI_REPO_OWNER: 'angular',
CI_REPO_NAME: 'angular',
CI_PULL_REQUEST: 'true',
}))).toEqual({
})).toEqual({
skipped: true,
reason: 'Skipping deploy because this is a PR build.',
});
});
it('master - deploy success', () => {
expect(computeDeploymentInfo(computeInputVars({
expect(getDeploymentInfoFor({
CI_REPO_OWNER: 'angular',
CI_REPO_NAME: 'angular',
CI_PULL_REQUEST: 'false',
CI_BRANCH: 'master',
CI_COMMIT: getLatestCommit('master'),
}))).toEqual({
})).toEqual({
deployEnv: 'next',
projectId: 'angular-io',
siteId: 'next-angular-io-site',
deployedUrl: 'https://next.angular.io/',
preDeployActions: ['function:build', 'function:checkPayloadSize'],
postDeployActions: ['function:testPwaScore'],
});
});
it('master - skip deploy - commit not HEAD', () => {
expect(computeDeploymentInfo(computeInputVars({
expect(getDeploymentInfoFor({
CI_REPO_OWNER: 'angular',
CI_REPO_NAME: 'angular',
CI_PULL_REQUEST: 'false',
CI_BRANCH: 'master',
CI_COMMIT: 'DUMMY_TEST_COMMIT',
}))).toEqual({
})).toEqual({
skipped: true,
reason:
'Skipping deploy because DUMMY_TEST_COMMIT is not the latest commit ' +
@ -68,30 +78,32 @@ describe('deploy-to-firebase:', () => {
});
it('stable - deploy success', () => {
expect(computeDeploymentInfo(computeInputVars({
expect(getDeploymentInfoFor({
CI_REPO_OWNER: 'angular',
CI_REPO_NAME: 'angular',
CI_PULL_REQUEST: 'false',
CI_BRANCH: '4.3.x',
CI_STABLE_BRANCH: '4.3.x',
CI_COMMIT: getLatestCommit('4.3.x'),
}))).toEqual({
})).toEqual({
deployEnv: 'stable',
projectId: 'angular-io',
siteId: 'v4-angular-io-site',
deployedUrl: 'https://angular.io/',
preDeployActions: ['function:build', 'function:checkPayloadSize'],
postDeployActions: ['function:testPwaScore'],
});
});
it('stable - skip deploy - commit not HEAD', () => {
expect(computeDeploymentInfo(computeInputVars({
expect(getDeploymentInfoFor({
CI_REPO_OWNER: 'angular',
CI_REPO_NAME: 'angular',
CI_PULL_REQUEST: 'false',
CI_BRANCH: '4.3.x',
CI_STABLE_BRANCH: '4.3.x',
CI_COMMIT: 'DUMMY_TEST_COMMIT',
}))).toEqual({
})).toEqual({
skipped: true,
reason:
'Skipping deploy because DUMMY_TEST_COMMIT is not the latest commit ' +
@ -100,48 +112,52 @@ describe('deploy-to-firebase:', () => {
});
it('archive - deploy success', () => {
expect(computeDeploymentInfo(computeInputVars({
expect(getDeploymentInfoFor({
CI_REPO_OWNER: 'angular',
CI_REPO_NAME: 'angular',
CI_PULL_REQUEST: 'false',
CI_BRANCH: '2.4.x',
CI_STABLE_BRANCH: '4.3.x',
CI_COMMIT: getLatestCommit('2.4.x'),
}))).toEqual({
})).toEqual({
deployEnv: 'archive',
projectId: 'angular-io',
siteId: 'v2-angular-io-site',
deployedUrl: 'https://v2.angular.io/',
preDeployActions: ['function:build', 'function:checkPayloadSize'],
postDeployActions: ['function:testPwaScore'],
});
});
// v9 used to be special-cased, because it was piloting the Firebase hosting "multisites" setup.
// See https://angular-team.atlassian.net/browse/DEV-125 for more info.
it('archive - deploy success (no special case for v9)', () => {
expect(computeDeploymentInfo(computeInputVars({
expect(getDeploymentInfoFor({
CI_REPO_OWNER: 'angular',
CI_REPO_NAME: 'angular',
CI_PULL_REQUEST: 'false',
CI_BRANCH: '9.1.x',
CI_STABLE_BRANCH: '10.0.x',
CI_COMMIT: getLatestCommit('9.1.x'),
}))).toEqual({
})).toEqual({
deployEnv: 'archive',
projectId: 'angular-io',
siteId: 'v9-angular-io-site',
deployedUrl: 'https://v9.angular.io/',
preDeployActions: ['function:build', 'function:checkPayloadSize'],
postDeployActions: ['function:testPwaScore'],
});
});
it('archive - skip deploy - commit not HEAD', () => {
expect(computeDeploymentInfo(computeInputVars({
expect(getDeploymentInfoFor({
CI_REPO_OWNER: 'angular',
CI_REPO_NAME: 'angular',
CI_PULL_REQUEST: 'false',
CI_BRANCH: '2.4.x',
CI_STABLE_BRANCH: '4.3.x',
CI_COMMIT: 'DUMMY_TEST_COMMIT',
}))).toEqual({
})).toEqual({
skipped: true,
reason:
'Skipping deploy because DUMMY_TEST_COMMIT is not the latest commit ' +
@ -150,14 +166,14 @@ describe('deploy-to-firebase:', () => {
});
it('archive - skip deploy - major same as stable, minor less than stable', () => {
expect(computeDeploymentInfo(computeInputVars({
expect(getDeploymentInfoFor({
CI_REPO_OWNER: 'angular',
CI_REPO_NAME: 'angular',
CI_PULL_REQUEST: 'false',
CI_BRANCH: '2.1.x',
CI_STABLE_BRANCH: '2.2.x',
CI_COMMIT: getLatestCommit('2.1.x'),
}))).toEqual({
})).toEqual({
skipped: true,
reason:
'Skipping deploy of branch "2.1.x" to Firebase.\n' +
@ -166,14 +182,14 @@ describe('deploy-to-firebase:', () => {
});
it('archive - skip deploy - major lower than stable, minor not latest', () => {
expect(computeDeploymentInfo(computeInputVars({
expect(getDeploymentInfoFor({
CI_REPO_OWNER: 'angular',
CI_REPO_NAME: 'angular',
CI_PULL_REQUEST: 'false',
CI_BRANCH: '2.1.x',
CI_STABLE_BRANCH: '4.3.x',
CI_COMMIT: getLatestCommit('2.1.x'),
}))).toEqual({
})).toEqual({
skipped: true,
reason:
'Skipping deploy of branch "2.1.x" to Firebase.\n' +
@ -182,46 +198,50 @@ describe('deploy-to-firebase:', () => {
});
it('rc - deploy success - major higher than stable', () => {
expect(computeDeploymentInfo(computeInputVars({
expect(getDeploymentInfoFor({
CI_REPO_OWNER: 'angular',
CI_REPO_NAME: 'angular',
CI_PULL_REQUEST: 'false',
CI_BRANCH: '4.4.x',
CI_STABLE_BRANCH: '2.2.x',
CI_COMMIT: getLatestCommit('4.4.x'),
}))).toEqual({
})).toEqual({
deployEnv: 'rc',
projectId: 'angular-io',
siteId: 'rc-angular-io-site',
deployedUrl: 'https://rc.angular.io/',
preDeployActions: ['function:build', 'function:checkPayloadSize'],
postDeployActions: ['function:testPwaScore'],
});
});
it('rc - deploy success - major same as stable, minor higher', () => {
expect(computeDeploymentInfo(computeInputVars({
expect(getDeploymentInfoFor({
CI_REPO_OWNER: 'angular',
CI_REPO_NAME: 'angular',
CI_PULL_REQUEST: 'false',
CI_BRANCH: '2.4.x',
CI_STABLE_BRANCH: '2.2.x',
CI_COMMIT: getLatestCommit('2.4.x'),
}))).toEqual({
})).toEqual({
deployEnv: 'rc',
projectId: 'angular-io',
siteId: 'rc-angular-io-site',
deployedUrl: 'https://rc.angular.io/',
preDeployActions: ['function:build', 'function:checkPayloadSize'],
postDeployActions: ['function:testPwaScore'],
});
});
it('rc - skip deploy - commit not HEAD', () => {
expect(computeDeploymentInfo(computeInputVars({
expect(getDeploymentInfoFor({
CI_REPO_OWNER: 'angular',
CI_REPO_NAME: 'angular',
CI_PULL_REQUEST: 'false',
CI_BRANCH: '2.4.x',
CI_STABLE_BRANCH: '2.2.x',
CI_COMMIT: 'DUMMY_TEST_COMMIT',
}))).toEqual({
})).toEqual({
skipped: true,
reason:
'Skipping deploy because DUMMY_TEST_COMMIT is not the latest commit ' +
@ -230,14 +250,14 @@ describe('deploy-to-firebase:', () => {
});
it('rc - skip deploy - major same as stable, minor not latest', () => {
expect(computeDeploymentInfo(computeInputVars({
expect(getDeploymentInfoFor({
CI_REPO_OWNER: 'angular',
CI_REPO_NAME: 'angular',
CI_PULL_REQUEST: 'false',
CI_BRANCH: '2.1.x',
CI_STABLE_BRANCH: '2.0.x',
CI_COMMIT: getLatestCommit('2.1.x'),
}))).toEqual({
})).toEqual({
skipped: true,
reason:
'Skipping deploy of branch "2.1.x" to Firebase.\n' +
@ -246,14 +266,14 @@ describe('deploy-to-firebase:', () => {
});
it('rc - skip deploy - major higher than stable, minor not latest', () => {
expect(computeDeploymentInfo(computeInputVars({
expect(getDeploymentInfoFor({
CI_REPO_OWNER: 'angular',
CI_REPO_NAME: 'angular',
CI_PULL_REQUEST: 'false',
CI_BRANCH: '4.3.x',
CI_STABLE_BRANCH: '2.4.x',
CI_COMMIT: getLatestCommit('4.3.x'),
}))).toEqual({
})).toEqual({
skipped: true,
reason:
'Skipping deploy of branch "4.3.x" to Firebase.\n' +
@ -273,12 +293,14 @@ describe('deploy-to-firebase:', () => {
};
const result = execSync(cmd, {encoding: 'utf8', env}).trim();
expect(result).toBe(
'Git branch : master\n' +
`Git commit : ${commit}\n` +
'Build/deploy mode : next\n' +
'Firebase project : angular-io\n' +
'Firebase site : next-angular-io-site\n' +
'Deployment URLs : https://next.angular.io/\n' +
' https://next-angular-io-site.web.app/');
'Git branch : master\n' +
`Git commit : ${commit}\n` +
'Build/deploy mode : next\n' +
'Firebase project : angular-io\n' +
'Firebase site : next-angular-io-site\n' +
'Pre-deploy actions : build, checkPayloadSize\n' +
'Post-deploy actions : testPwaScore\n' +
'Deployment URLs : https://next.angular.io/\n' +
' https://next-angular-io-site.web.app/');
});
});