-
Notifications
You must be signed in to change notification settings - Fork 12
/
Copy pathpromote-cherry-picks.ts
112 lines (102 loc) · 3.38 KB
/
promote-cherry-picks.ts
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
/**
* Promotes cherry-picked release in related channels.
*/
import yargs from 'yargs/yargs';
import {Prefixes, Versions} from '../configs/schemas/versions';
import {
createVersionsUpdatePullRequest,
octokit,
runPromoteJob,
} from './promote-job';
import {getChannels} from './get-channels-utils';
interface Args {
amp_version: string;
}
const {amp_version: ampVersion}: Args = yargs(process.argv.slice(2))
.options({
amp_version: {type: 'string', demandOption: true},
})
.parseSync();
const jobName = 'promote-cherry-pick.ts';
const ampVersionWithoutCherryPicksCounter = ampVersion.slice(0, 10);
const cherryPicksCount = ampVersion.slice(-3);
function getAmpVersionToCherrypick(
ampVersion: string,
currentVersions: Versions
): string {
const ampVersionToCherrypick = Object.values(currentVersions).find(
(version) =>
version?.slice(2, 12) == ampVersionWithoutCherryPicksCounter &&
version?.slice(-3) < cherryPicksCount
);
if (!ampVersionToCherrypick) {
throw Error(
`Could not find a live AMP version to be cherry-picked with ${ampVersion}`
);
}
return ampVersionToCherrypick.slice(-13);
}
async function getCherryPickedPRs(
ampVersion: string,
numberOfCherryPickedCommits: number
): Promise<string[]> {
try {
const {data} = await octokit.rest.repos.listCommits({
owner: 'ampproject',
repo: 'amphtml',
sha: ampVersion,
per_page: numberOfCherryPickedCommits,
});
return data.map(({commit}) => {
const [firstLine] = commit.message.split('\n');
const pullNumber = firstLine?.match(/\(#(?<pullNumber>\d+)\)$/)?.groups
?.pullNumber;
if (pullNumber) {
return `* https://github.com/ampproject/amphtml/pull/${pullNumber}`;
}
return `* ${commit.url}`;
});
} catch (err) {
console.warn('Could not fetch the list of cherry picked PRs, skipping...');
console.warn('Exception thrown:', err);
return [];
}
}
function generateBody(
ampVersion: string,
channels: string,
cherryPickedPRs: string[]
): string {
let body = `Promoting release ${ampVersion} to channels: ${channels}`;
if (cherryPickedPRs.length) {
body += '\n\nPRs included in this cherry pick:\n';
body += cherryPickedPRs.join('\n');
}
body += `\n\nCommits on release branch: [amp-release-${ampVersion}](https://github.com/ampproject/amphtml/commits/amp-release-${ampVersion})`;
return body;
}
void runPromoteJob(jobName, async () => {
return createVersionsUpdatePullRequest(async (currentVersions) => {
const currentAmpVersion = getAmpVersionToCherrypick(
ampVersion,
currentVersions
);
const currentCherryPicksCount = currentAmpVersion.slice(-3);
const channels = getChannels(currentAmpVersion, currentVersions);
const versionsChanges: Record<string, string> = {};
for (const channel of channels) {
versionsChanges[channel] = `${Prefixes[channel]}${ampVersion}`;
}
const cherryPickedPRs = await getCherryPickedPRs(
ampVersion,
Number(cherryPicksCount) - Number(currentCherryPicksCount)
);
return {
ampVersion,
versionsChanges,
title: `🌸 Promoting all ${ampVersionWithoutCherryPicksCounter}[${currentCherryPicksCount}→${cherryPicksCount}] channels`,
body: generateBody(ampVersion, channels.join(', '), cherryPickedPRs),
branch: `cherry-pick-${currentAmpVersion}-to-${ampVersion}`,
};
});
});