Skip to content

Commit 654bf73

Browse files
committed
Revert "Remove: Original GH workflows"
This reverts commit 66033ff.
1 parent 66033ff commit 654bf73

26 files changed

+31558
-0
lines changed
Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
load("//tools:defaults.bzl", "esbuild_checked_in")
2+
3+
exports_files([
4+
"tsconfig.json",
5+
])
6+
7+
esbuild_checked_in(
8+
name = "main",
9+
entry_point = "//.github/actions/deploy-docs-site/lib:main.ts",
10+
external = [
11+
"undici",
12+
],
13+
platform = "node",
14+
target = "node14",
15+
deps = [
16+
"//.github/actions/deploy-docs-site/lib",
17+
],
18+
)
Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
name: 'Deploy angular.dev site'
2+
description: 'Automatically deploy and set up redirects for angular.dev'
3+
author: 'Angular'
4+
inputs:
5+
serviceKey:
6+
description: 'The service key used for firebase deployments.'
7+
required: true
8+
githubReleaseTrainReadToken:
9+
description: 'GitHub access token for reading release trains without rate limits.'
10+
required: true
11+
configPath:
12+
description: 'The path to the firebase config file.'
13+
required: true
14+
distDir:
15+
description: 'The path to the firebase dist directory.'
16+
required: true
17+
runs:
18+
using: 'node20'
19+
main: 'main.js'
Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
load("//tools:defaults.bzl", "ts_library")
2+
3+
package(default_visibility = ["//.github/actions/deploy-docs-site:__subpackages__"])
4+
5+
exports_files([
6+
"main.ts",
7+
])
8+
9+
ts_library(
10+
name = "lib",
11+
srcs = glob(
12+
["*.ts"],
13+
),
14+
#tsconfig = "//.github/actions/deploy-docs-site:tsconfig.json",
15+
deps = [
16+
"@npm//@actions/core",
17+
"@npm//@actions/github",
18+
"@npm//@angular/ng-dev",
19+
"@npm//@types/node",
20+
"@npm//@types/tmp",
21+
"@npm//tmp",
22+
],
23+
)
Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
import {fileSync} from 'tmp';
2+
import {writeSync} from 'fs';
3+
import {getInput, setSecret} from '@actions/core';
4+
5+
let credentialFilePath: undefined | string;
6+
7+
export function getCredentialFilePath(): string {
8+
if (credentialFilePath === undefined) {
9+
const tmpFile = fileSync({postfix: '.json'});
10+
writeSync(tmpFile.fd, getInput('serviceKey', {required: true}));
11+
setSecret(tmpFile.name);
12+
credentialFilePath = tmpFile.name;
13+
}
14+
return credentialFilePath;
15+
}
16+
17+
/** Github access token. Used for querying the active release trains. */
18+
export const githubReleaseTrainReadToken: string = getInput('githubReleaseTrainReadToken', {
19+
required: true,
20+
});
Lines changed: 116 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,116 @@
1+
import {cp, mkdtemp, readFile, rm, writeFile} from 'fs/promises';
2+
import {Deployment} from './deployments';
3+
import {join} from 'path';
4+
5+
import {tmpdir} from 'os';
6+
import {spawnSync} from 'child_process';
7+
import {getCredentialFilePath} from './credential';
8+
9+
export async function deployToFirebase(
10+
deployment: Deployment,
11+
configPath: string,
12+
distDirPath: string,
13+
) {
14+
if (deployment.destination == undefined) {
15+
console.log(`No deployment necessary for docs created from: ${deployment.branch}`);
16+
return;
17+
}
18+
19+
console.log('Preparing for deployment to firebase...');
20+
21+
const tmpDeployDir = await mkdtemp(join(tmpdir(), 'deploy-directory'));
22+
const deployConfigPath = join(tmpDeployDir, 'firebase.json');
23+
24+
const config = JSON.parse(await readFile(configPath, {encoding: 'utf-8'})) as {
25+
hosting: {public: string};
26+
};
27+
config['hosting']['public'] = './dist';
28+
29+
await writeFile(deployConfigPath, JSON.stringify(config, null, 2));
30+
31+
await cp(distDirPath, join(tmpDeployDir, 'dist'), {recursive: true});
32+
spawnSync(`chmod 777 -R ${tmpDeployDir}`, {encoding: 'utf-8', shell: true});
33+
34+
firebase(
35+
`target:clear --config ${deployConfigPath} --project angular-dev-site hosting angular-docs`,
36+
tmpDeployDir,
37+
);
38+
firebase(
39+
`target:apply --config ${deployConfigPath} --project angular-dev-site hosting angular-docs ${deployment.destination}`,
40+
tmpDeployDir,
41+
);
42+
firebase(
43+
`deploy --config ${deployConfigPath} --project angular-dev-site --only hosting --non-interactive`,
44+
tmpDeployDir,
45+
);
46+
firebase(
47+
`target:clear --config ${deployConfigPath} --project angular-dev-site hosting angular-docs`,
48+
tmpDeployDir,
49+
);
50+
51+
await rm(tmpDeployDir, {recursive: true});
52+
}
53+
54+
export async function setupRedirect(deployment: Deployment) {
55+
if (deployment.redirect === undefined) {
56+
console.log(`No redirect necessary for docs created from: ${deployment.branch}`);
57+
return;
58+
}
59+
60+
console.log('Preparing to set up redirect on firebase...');
61+
62+
const redirectConfig = JSON.stringify(
63+
{
64+
hosting: {
65+
target: 'angular-docs',
66+
redirects: [
67+
{
68+
type: 302,
69+
regex: '^(.*)$',
70+
destination: `${deployment.redirect.to}:1`,
71+
},
72+
],
73+
},
74+
},
75+
null,
76+
2,
77+
);
78+
79+
const tmpRedirectDir = await mkdtemp(join(tmpdir(), 'redirect-directory'));
80+
const redirectConfigPath = join(tmpRedirectDir, 'firebase.json');
81+
82+
await writeFile(redirectConfigPath, redirectConfig);
83+
spawnSync(`chmod 777 -R ${tmpRedirectDir}`, {encoding: 'utf-8', shell: true});
84+
85+
firebase(
86+
`target:clear --config ${redirectConfigPath} --project angular-dev-site hosting angular-docs`,
87+
tmpRedirectDir,
88+
);
89+
firebase(
90+
`target:apply --config ${redirectConfigPath} --project angular-dev-site hosting angular-docs ${deployment.redirect.from}`,
91+
tmpRedirectDir,
92+
);
93+
firebase(
94+
`deploy --config ${redirectConfigPath} --project angular-dev-site --only hosting --non-interactive`,
95+
tmpRedirectDir,
96+
);
97+
firebase(
98+
`target:clear --config ${redirectConfigPath} --project angular-dev-site hosting angular-docs`,
99+
tmpRedirectDir,
100+
);
101+
102+
await rm(tmpRedirectDir, {recursive: true});
103+
}
104+
105+
function firebase(cmd: string, cwd?: string) {
106+
spawnSync('npx', `-y firebase-tools@13.15.1 ${cmd}`.split(' '), {
107+
cwd,
108+
encoding: 'utf-8',
109+
shell: true,
110+
stdio: 'inherit',
111+
env: {
112+
...process.env,
113+
GOOGLE_APPLICATION_CREDENTIALS: getCredentialFilePath(),
114+
},
115+
});
116+
}
Lines changed: 67 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,67 @@
1+
import {fetchLongTermSupportBranchesFromNpm, ActiveReleaseTrains} from '@angular/ng-dev';
2+
import {ReleaseConfig} from '@angular/ng-dev';
3+
import {AuthenticatedGitClient} from '@angular/ng-dev';
4+
5+
export interface Deployment {
6+
branch: string;
7+
redirect?: {
8+
from: string;
9+
to: string;
10+
};
11+
destination?: string;
12+
}
13+
14+
export type Deployments = Map<string, Deployment>;
15+
16+
export async function getDeployments(): Promise<Deployments> {
17+
const {github} = await AuthenticatedGitClient.get();
18+
const releaseTrains = await ActiveReleaseTrains.fetch({
19+
api: github,
20+
name: 'angular',
21+
owner: 'angular',
22+
nextBranchName: 'main',
23+
});
24+
const ltsBranches = await fetchLongTermSupportBranchesFromNpm({
25+
representativeNpmPackage: '@angular/core',
26+
} as ReleaseConfig);
27+
28+
const docSites = new Map<string, Deployment>();
29+
30+
[...ltsBranches.active, ...ltsBranches.inactive].forEach((branch) => {
31+
docSites.set(branch.name, {
32+
branch: branch.name,
33+
destination: `v${branch.version.major}-angular-dev`,
34+
});
35+
});
36+
37+
docSites.set(releaseTrains.latest.branchName, {
38+
branch: releaseTrains.latest.branchName,
39+
redirect: {
40+
from: `v${releaseTrains.latest.version.major}-angular-dev`,
41+
to: 'https://angular.dev',
42+
},
43+
destination: 'angular-dev-site',
44+
});
45+
46+
if (releaseTrains.releaseCandidate) {
47+
docSites.set(releaseTrains.next.branchName, {
48+
branch: releaseTrains.next.branchName,
49+
});
50+
51+
docSites.set(releaseTrains.releaseCandidate.branchName, {
52+
branch: releaseTrains.releaseCandidate.branchName,
53+
destination: 'next-angular-dev',
54+
redirect: {
55+
from: `v${releaseTrains.releaseCandidate.version.major}-angular-dev`,
56+
to: 'https://next.angular.dev',
57+
},
58+
});
59+
} else {
60+
docSites.set(releaseTrains.next.branchName, {
61+
branch: releaseTrains.next.branchName,
62+
destination: 'next-angular-dev',
63+
});
64+
}
65+
66+
return docSites;
67+
}
Lines changed: 75 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,75 @@
1+
import {getInput, setFailed} from '@actions/core';
2+
import {context} from '@actions/github';
3+
import {deployToFirebase, setupRedirect} from './deploy';
4+
import {getDeployments} from './deployments';
5+
import {AuthenticatedGitClient, GithubConfig, setConfig} from '@angular/ng-dev';
6+
import {githubReleaseTrainReadToken} from './credential';
7+
8+
const refMatcher = /refs\/heads\/(.*)/;
9+
10+
async function deployDocs() {
11+
setConfig({
12+
github: <GithubConfig>{
13+
mainBranchName: 'main',
14+
name: 'angular',
15+
owner: 'angular',
16+
},
17+
});
18+
19+
AuthenticatedGitClient.configure(githubReleaseTrainReadToken);
20+
21+
if (context.eventName !== 'push') {
22+
throw Error();
23+
}
24+
const matchedRef = context.ref.match(refMatcher);
25+
if (matchedRef === null) {
26+
throw Error();
27+
}
28+
29+
const currentBranch = matchedRef[1];
30+
const configPath = getInput('configPath');
31+
const distDir = getInput('distDir');
32+
33+
const deployment = (await getDeployments()).get(currentBranch);
34+
if (deployment === undefined) {
35+
console.log(`Current branch (${currentBranch}) does not deploy a documentation site.`);
36+
console.log(`Exiting...`);
37+
process.exit(0);
38+
}
39+
40+
console.log('Doc site deployment information');
41+
console.log('');
42+
console.log('Current Branch:');
43+
console.log(` ${deployment.branch}`);
44+
console.log('');
45+
console.log('Firebase Site:');
46+
if (deployment.destination === undefined) {
47+
console.log(' No deployment of a documenation site is necessary');
48+
} else {
49+
console.log(` Deploying to: ${deployment.destination}`);
50+
}
51+
console.log('');
52+
console.log('Redirect Configuration:');
53+
if (deployment.redirect === undefined) {
54+
console.log(' No redirects are necessary');
55+
} else {
56+
console.log(` From: ${deployment.redirect.from}`);
57+
console.log(` To: ${deployment.redirect.to}`);
58+
}
59+
60+
await deployToFirebase(deployment, configPath, distDir);
61+
await setupRedirect(deployment);
62+
}
63+
64+
// Only run if the action is executed in a repository with is in the Angular org. This is in place
65+
// to prevent the action from actually running in a fork of a repository with this action set up.
66+
if (context.repo.owner === 'angular') {
67+
deployDocs().catch((e: Error) => {
68+
setFailed(e.message);
69+
console.error(e);
70+
});
71+
} else {
72+
console.warn(
73+
'The action was skipped as this action is only meant to run in repos belonging to the Angular organization.',
74+
);
75+
}

0 commit comments

Comments
 (0)