|
1 | 1 | /* eslint-disable no-console */
|
| 2 | +import type { components } from '@octokit/openapi-types'; |
| 3 | + |
2 | 4 | import { exists, getOctokit, run, setVerbose, toAbsolutePath } from '../../common';
|
3 | 5 | import { getClientsConfigField, getLanguageFolder } from '../../config';
|
4 | 6 | import { getTargetBranch } from '../../release/common';
|
5 | 7 | import type { Language } from '../../types';
|
6 | 8 |
|
7 | 9 | import { commitStartRelease } from './text';
|
8 | 10 |
|
9 |
| -function getAllRuns(languages: Language[], workflowIDs: Array<number | undefined>): Promise<any[]> { |
10 |
| - const octokit = getOctokit(); |
11 |
| - |
12 |
| - return Promise.all( |
13 |
| - languages.map(async (lang, index) => { |
14 |
| - // wait for the CI to start |
15 |
| - const workflowID = workflowIDs[index]; |
16 |
| - if (!workflowID) { |
17 |
| - return undefined; |
18 |
| - } |
| 11 | +type Run = { |
| 12 | + language: Language; |
| 13 | + run?: components['schemas']['workflow-run']; |
| 14 | + finished: boolean; |
| 15 | +}; |
19 | 16 |
|
20 |
| - const ciRun = await octokit.actions.listWorkflowRuns({ |
21 |
| - owner: 'algolia', |
22 |
| - repo: getClientsConfigField(lang, 'gitRepoId'), |
23 |
| - workflow_id: workflowID, |
24 |
| - per_page: 1, |
25 |
| - branch: getTargetBranch(lang), |
26 |
| - }); |
| 17 | +async function fetchAllRuns(runs: Run[]): Promise<void> { |
| 18 | + const octokit = getOctokit(); |
27 | 19 |
|
28 |
| - if (ciRun.data.workflow_runs.length === 0) { |
29 |
| - return null; |
30 |
| - } |
| 20 | + await Promise.allSettled( |
| 21 | + runs |
| 22 | + .filter((ciRun) => !ciRun.finished) |
| 23 | + .map(async (ciRun) => { |
| 24 | + // wait for the CI to start |
| 25 | + const workflowRun = await octokit.actions.listWorkflowRuns({ |
| 26 | + owner: 'algolia', |
| 27 | + repo: getClientsConfigField(ciRun.language, 'gitRepoId'), |
| 28 | + workflow_id: 'release.yml', |
| 29 | + per_page: 1, |
| 30 | + branch: ciRun.language === 'dart' ? undefined : getTargetBranch(ciRun.language), |
| 31 | + }); |
| 32 | + |
| 33 | + if (workflowRun.data.workflow_runs.length === 0) { |
| 34 | + return; |
| 35 | + } |
31 | 36 |
|
32 |
| - // check that the run was created less than 10 minutes ago |
33 |
| - if (Date.now() - Date.parse(ciRun.data.workflow_runs[0].created_at) > 15 * 60 * 1000) { |
34 |
| - return null; |
35 |
| - } |
| 37 | + // check that the run was created less than 10 minutes ago |
| 38 | + if ( |
| 39 | + Date.now() - Date.parse(workflowRun.data.workflow_runs[0].created_at) > |
| 40 | + 15 * 60 * 1000 |
| 41 | + ) { |
| 42 | + return; |
| 43 | + } |
36 | 44 |
|
37 |
| - return ciRun.data.workflow_runs[0]; |
38 |
| - }), |
| 45 | + ciRun.run = workflowRun.data.workflow_runs[0]; |
| 46 | + }), |
39 | 47 | );
|
40 | 48 | }
|
41 | 49 |
|
42 |
| -async function waitForAllReleases(languages: Language[]): Promise<void> { |
43 |
| - const octokit = getOctokit(); |
44 |
| - |
| 50 | +async function waitForAllReleases(languagesReleased: Language[]): Promise<void> { |
45 | 51 | const lastCommitMessage = await run('git log -1 --format="%s"');
|
46 | 52 |
|
47 | 53 | if (!lastCommitMessage.startsWith(commitStartRelease)) {
|
48 | 54 | return;
|
49 | 55 | }
|
50 | 56 |
|
51 |
| - console.log( |
52 |
| - `Waiting for all releases CI to finish for the following languages: ${languages.join(', ')}`, |
53 |
| - ); |
54 |
| - |
55 |
| - const workflowIDs = await Promise.all( |
56 |
| - languages.map(async (lang) => { |
57 |
| - if ( |
58 |
| - !(await exists(toAbsolutePath(`${getLanguageFolder(lang)}/.github/workflows/release.yml`))) |
59 |
| - ) { |
60 |
| - return undefined; |
61 |
| - } |
62 |
| - |
63 |
| - const workflows = await octokit.actions.listRepoWorkflows({ |
64 |
| - owner: 'algolia', |
65 |
| - repo: getClientsConfigField(lang, 'gitRepoId'), |
66 |
| - }); |
67 |
| - |
68 |
| - return workflows.data.workflows.find( |
69 |
| - (workflow) => |
70 |
| - workflow.path === '.github/workflows/release.yml' && workflow.state === 'active', |
71 |
| - )?.id; |
72 |
| - }), |
73 |
| - ); |
| 57 | + const runs: Run[] = ( |
| 58 | + await Promise.all( |
| 59 | + languagesReleased.map(async (lang) => { |
| 60 | + return { |
| 61 | + lang, |
| 62 | + available: await exists( |
| 63 | + toAbsolutePath(`${getLanguageFolder(lang)}/.github/workflows/release.yml`), |
| 64 | + ), |
| 65 | + }; |
| 66 | + }), |
| 67 | + ) |
| 68 | + ) |
| 69 | + .filter((lang) => lang.available) |
| 70 | + .map((lang) => ({ language: lang.lang, run: undefined, finished: false })); |
74 | 71 |
|
75 | 72 | console.log(
|
76 |
| - `Found the following workflows: ${languages.map((l, i) => `${l} => ${workflowIDs[i]}`).join(', ')}`, |
| 73 | + `Waiting for all releases CI to finish for the following languages: ${runs.map((l) => l.language).join(', ')}`, |
77 | 74 | );
|
78 | 75 |
|
79 | 76 | const failures: Language[] = [];
|
80 | 77 |
|
81 | 78 | const start = Date.now();
|
82 | 79 | // kotlin release can take a long time
|
83 | 80 | while (Date.now() - start < 1000 * 60 * 12) {
|
84 |
| - const runs = await getAllRuns(languages, workflowIDs); |
85 |
| - for (let i = 0; i < languages.length; i++) { |
86 |
| - if (runs[i] === null) { |
87 |
| - console.log(`⏳ ${languages[i]} CI not started yet`); |
| 81 | + await fetchAllRuns(runs); |
| 82 | + for (const ciRun of runs) { |
| 83 | + if (ciRun.finished) { |
| 84 | + continue; |
| 85 | + } |
| 86 | + |
| 87 | + if (!ciRun.run) { |
| 88 | + console.log(`⏳ ${ciRun.language} CI not started yet`); |
88 | 89 | continue;
|
89 | 90 | }
|
90 | 91 |
|
91 |
| - if (runs[i]?.status === 'completed') { |
92 |
| - const success = runs[i]?.conclusion === 'success'; |
| 92 | + if (ciRun.run.status === 'completed') { |
| 93 | + const success = ciRun.run.conclusion === 'success'; |
93 | 94 | console.log(
|
94 |
| - `${success ? '✅' : '❌'} ${languages[i]} CI finished with conclusion: ${runs[i]?.conclusion}`, |
| 95 | + `${success ? '✅' : '❌'} ${ciRun.language} CI finished with conclusion: ${ciRun.run.conclusion}`, |
95 | 96 | );
|
96 | 97 | if (!success) {
|
97 |
| - failures.push(languages[i]); |
| 98 | + failures.push(ciRun.language); |
98 | 99 | }
|
99 | 100 | // stop fetching this run.
|
100 |
| - workflowIDs[i] = undefined; |
| 101 | + ciRun.finished = true; |
101 | 102 | }
|
102 | 103 | }
|
103 | 104 |
|
104 |
| - if (workflowIDs.every((id) => id === undefined)) { |
| 105 | + if (runs.every((ciRun) => ciRun.finished)) { |
105 | 106 | break;
|
106 | 107 | }
|
107 | 108 |
|
|
0 commit comments