Skip to content

Commit ad0d235

Browse files
committed
inline download artifact code
1 parent fb03978 commit ad0d235

File tree

3 files changed

+187
-48
lines changed

3 files changed

+187
-48
lines changed

dev-packages/size-limit-gh-action/index.mjs

Lines changed: 182 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
/* eslint-disable max-lines */
12
import { promises as fs } from 'node:fs';
23
import path from 'node:path';
34
import { fileURLToPath } from 'node:url';
@@ -7,11 +8,10 @@ import * as core from '@actions/core';
78
import { exec } from '@actions/exec';
89
import { context, getOctokit } from '@actions/github';
910
import * as glob from '@actions/glob';
11+
import * as io from '@actions/io';
1012
import bytes from 'bytes';
1113
import { markdownTable } from 'markdown-table';
1214

13-
import download from 'github-fetch-workflow-artifact';
14-
1515
const SIZE_LIMIT_HEADING = '## size-limit report 📦 ';
1616
const ARTIFACT_NAME = 'size-limit-action';
1717
const RESULTS_FILE = 'size-limit-results.json';
@@ -229,29 +229,27 @@ async function run() {
229229
let current;
230230

231231
try {
232-
core.startGroup('Downloading base results');
233-
core.warning(ARTIFACT_NAME);
234-
core.warning(comparisonBranch);
235-
core.warning(__dirname);
236-
core.warning(`${process.env.GITHUB_WORKFLOW || ''}`);
237-
core.endGroup();
232+
core.info('Downloading base results...');
233+
const artifacts = await getArtifactsForBranchAndWorkflow(octokit, {
234+
...repo,
235+
artifactName: ARTIFACT_NAME,
236+
branch: comparisonBranch,
237+
workflowName: `${process.env.GITHUB_WORKFLOW || ''}`,
238+
});
239+
core.info('Fetched artifacts for base results');
238240

239-
core.warning(download);
240-
core.warning(download.default);
241-
core.warning(Object.keys(download))
241+
if (!artifacts) {
242+
throw new Error('No artifacts found');
243+
}
242244

243-
// Ignore failures here as it is likely that this only happens when introducing size-limit
244-
// and this has not been run on the main branch yet
245-
const res = await download(octokit, {
245+
await downloadOtherWorkflowArtifact(octokit, {
246246
...repo,
247247
artifactName: ARTIFACT_NAME,
248-
branch: comparisonBranch,
248+
artifactId: artifacts.artifact.id,
249249
downloadPath: __dirname,
250-
workflowEvent: 'push',
251-
workflowName: `${process.env.GITHUB_WORKFLOW || ''}`,
252250
});
253-
core.warning('Downloaded base results');
254-
core.warning(res);
251+
252+
core.info('Downloaded base results');
255253
base = JSON.parse(await fs.readFile(resultsFilePath, { encoding: 'utf8' }));
256254
} catch (error) {
257255
core.startGroup('Warning, unable to find base results');
@@ -308,4 +306,169 @@ async function run() {
308306
}
309307
}
310308

309+
// max pages of workflows to pagination through
310+
const DEFAULT_MAX_PAGES = 50;
311+
// max results per page
312+
const DEFAULT_PAGE_LIMIT = 10;
313+
314+
/**
315+
* Fetch artifacts from a workflow run from a branch
316+
*
317+
* This is a bit hacky since GitHub Actions currently does not directly
318+
* support downloading artifacts from other workflows
319+
*/
320+
/**
321+
* Fetch artifacts from a workflow run from a branch
322+
*
323+
* This is a bit hacky since GitHub Actions currently does not directly
324+
* support downloading artifacts from other workflows
325+
*/
326+
export async function getArtifactsForBranchAndWorkflow(octokit, { owner, repo, workflowName, branch, artifactName }) {
327+
core.startGroup(`getArtifactsForBranchAndWorkflow - workflow:"${workflowName}", branch:"${branch}"`);
328+
329+
let repositoryWorkflow = null;
330+
331+
// For debugging
332+
const allWorkflows = [];
333+
334+
//
335+
// Find workflow id from `workflowName`
336+
//
337+
for await (const response of octokit.paginate.iterator(octokit.rest.actions.listRepoWorkflows, {
338+
owner,
339+
repo,
340+
})) {
341+
const targetWorkflow = response.data.find(({ name }) => name === workflowName);
342+
343+
allWorkflows.push(...response.data.map(({ name }) => name));
344+
345+
// If not found in responses, continue to search on next page
346+
if (!targetWorkflow) {
347+
continue;
348+
}
349+
350+
repositoryWorkflow = targetWorkflow;
351+
break;
352+
}
353+
354+
if (!repositoryWorkflow) {
355+
core.debug(
356+
`Unable to find workflow with name "${workflowName}" in the repository. Found workflows: ${allWorkflows.join(
357+
', ',
358+
)}`,
359+
);
360+
core.endGroup();
361+
return null;
362+
}
363+
364+
const workflow_id = repositoryWorkflow.id;
365+
366+
let currentPage = 0;
367+
const completedWorkflowRuns = [];
368+
369+
for await (const response of octokit.paginate.iterator(octokit.rest.actions.listWorkflowRuns, {
370+
owner,
371+
repo,
372+
workflow_id,
373+
branch,
374+
status: 'success',
375+
per_page: DEFAULT_PAGE_LIMIT,
376+
event: 'push',
377+
})) {
378+
if (!response.data.length) {
379+
core.warning(`Workflow ${workflow_id} not found in branch ${branch}`);
380+
core.endGroup();
381+
return null;
382+
}
383+
384+
// Do not allow downloading artifacts from a fork.
385+
completedWorkflowRuns.push(
386+
...response.data.filter(workflowRun => workflowRun.head_repository.full_name === `${owner}/${repo}`),
387+
);
388+
389+
if (!completedWorkflowRuns.length) {
390+
continue;
391+
}
392+
393+
if (currentPage > DEFAULT_MAX_PAGES) {
394+
core.warning(`Workflow ${workflow_id} not found in branch: ${branch}`);
395+
core.endGroup();
396+
return null;
397+
}
398+
399+
currentPage++;
400+
}
401+
402+
// Search through workflow artifacts until we find a workflow run w/ artifact name that we are looking for
403+
for (const workflowRun of completedWorkflowRuns) {
404+
core.debug(`Checking artifacts for workflow run: ${workflowRun.html_url}`);
405+
406+
const {
407+
data: { artifacts },
408+
} = await octokit.rest.actions.listWorkflowRunArtifacts({
409+
owner,
410+
repo,
411+
run_id: workflowRun.id,
412+
});
413+
414+
if (!artifacts) {
415+
core.debug(
416+
`Unable to fetch artifacts for branch: ${branch}, workflow: ${workflow_id}, workflowRunId: ${workflowRun.id}`,
417+
);
418+
} else {
419+
const foundArtifact = artifacts.find(({ name }) => name === artifactName);
420+
if (foundArtifact) {
421+
core.debug(`Found suitable artifact: ${foundArtifact.url}`);
422+
return {
423+
artifact: foundArtifact,
424+
workflowRun,
425+
};
426+
}
427+
}
428+
}
429+
430+
core.warning(`Artifact not found: ${artifactName}`);
431+
core.endGroup();
432+
return null;
433+
}
434+
311435
run();
436+
437+
/**
438+
* Use GitHub API to fetch artifact download url, then
439+
* download and extract artifact to `downloadPath`
440+
*/
441+
async function downloadOtherWorkflowArtifact(octokit, { owner, repo, artifactId, artifactName, downloadPath }) {
442+
const artifact = await octokit.rest.actions.downloadArtifact({
443+
owner,
444+
repo,
445+
artifact_id: artifactId,
446+
archive_format: 'zip',
447+
});
448+
449+
// Make sure output path exists
450+
try {
451+
await io.mkdirP(downloadPath);
452+
} catch {
453+
// ignore errors
454+
}
455+
456+
const downloadFile = path.resolve(downloadPath, `${artifactName}.zip`);
457+
458+
await exec('wget', [
459+
'-nv',
460+
'--retry-connrefused',
461+
'--waitretry=1',
462+
'--read-timeout=20',
463+
'--timeout=15',
464+
'-t',
465+
'0',
466+
'-O',
467+
downloadFile,
468+
artifact.url,
469+
]);
470+
471+
await exec('unzip', ['-q', '-d', downloadPath, downloadFile], {
472+
silent: true,
473+
});
474+
}

dev-packages/size-limit-gh-action/package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,10 +17,10 @@
1717
"@actions/artifact": "1.1.2",
1818
"@actions/core": "1.10.1",
1919
"@actions/exec": "1.1.1",
20+
"@actions/io": "1.1.3",
2021
"@actions/github": "^5.0.0",
2122
"@actions/glob": "0.4.0",
2223
"bytes": "3.1.2",
23-
"github-fetch-workflow-artifact": "2.0.0",
2424
"markdown-table": "3.0.3"
2525
},
2626
"volta": {

yarn.lock

Lines changed: 4 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -12,15 +12,15 @@
1212
tmp "^0.2.1"
1313
tmp-promise "^3.0.2"
1414

15-
"@actions/[email protected]", "@actions/core@^1.6.0", "@actions/core@^1.9.1":
15+
"@actions/[email protected]", "@actions/core@^1.9.1":
1616
version "1.10.1"
1717
resolved "https://registry.yarnpkg.com/@actions/core/-/core-1.10.1.tgz#61108e7ac40acae95ee36da074fa5850ca4ced8a"
1818
integrity sha512-3lBR9EDAY+iYIpTnTIXmWcNbX3T2kCkAEQGIQx4NVQ0575nk2k3GRZDTPQG+vVtS2izSLmINlxXf0uLtnrTP+g==
1919
dependencies:
2020
"@actions/http-client" "^2.0.1"
2121
uuid "^8.3.2"
2222

23-
"@actions/[email protected]", "@actions/exec@^1.1.0":
23+
"@actions/[email protected]":
2424
version "1.1.1"
2525
resolved "https://registry.yarnpkg.com/@actions/exec/-/exec-1.1.1.tgz#2e43f28c54022537172819a7cf886c844221a611"
2626
integrity sha512-+sCcHHbVdk93a0XT19ECtO/gIXoxvdsgQLzb2fE2/5sIZmWQuluYyjPQtrtTHdU1YzTZ7bAPN4sITq2xi1679w==
@@ -53,7 +53,7 @@
5353
tunnel "^0.0.6"
5454
undici "^5.25.4"
5555

56-
"@actions/io@^1.0.1", "@actions/io@^1.1.1":
56+
"@actions/io@1.1.3", "@actions/io@^1.0.1":
5757
version "1.1.3"
5858
resolved "https://registry.yarnpkg.com/@actions/io/-/io-1.1.3.tgz#4cdb6254da7962b07473ff5c335f3da485d94d71"
5959
integrity sha512-wi9JjgKLYS7U/z8PPbco+PvTb/nRWjeoFlJ1Qer83k/3C5PHQi28hiVdeE2kHXmIL99mQFawx8qt/JPjZilJ8Q==
@@ -6077,13 +6077,6 @@
60776077
resolved "https://registry.yarnpkg.com/@types/array.prototype.flat/-/array.prototype.flat-1.2.1.tgz#5433a141730f8e1d7a8e7486458ceb8144ee5edc"
60786078
integrity sha512-JOvNJUU/zjfJWcA1aHDnCKHwQjZ7VQ3UNfbcMKXrkQKKyMkJHrQ9vpSVMhgsztrtsbIRJKazMDvg2QggFVwJqw==
60796079

6080-
"@types/async-retry@^1.4.3":
6081-
version "1.4.8"
6082-
resolved "https://registry.yarnpkg.com/@types/async-retry/-/async-retry-1.4.8.tgz#eb32df13aceb9ba1a8a80e7fe518ff4e3fe46bb3"
6083-
integrity sha512-Qup/B5PWLe86yI5I3av6ePGaeQrIHNKCwbsQotD6aHQ6YkHsMUxVZkZsmx/Ry3VZQ6uysHwTjQ7666+k6UjVJA==
6084-
dependencies:
6085-
"@types/retry" "*"
6086-
60876080
"@types/aws-lambda@^8.10.62":
60886081
version "8.10.73"
60896082
resolved "https://registry.yarnpkg.com/@types/aws-lambda/-/aws-lambda-8.10.73.tgz#77773c9accb2cec26fcb7c6b510a555805604a53"
@@ -7054,11 +7047,6 @@
70547047
resolved "https://registry.yarnpkg.com/@types/resolve/-/resolve-1.20.3.tgz#066742d69a0bbba8c5d7d517f82e1140ddeb3c3c"
70557048
integrity sha512-NH5oErHOtHZYcjCtg69t26aXEk4BN2zLWqf7wnDZ+dpe0iR7Rds1SPGEItl3fca21oOe0n3OCnZ4W7jBxu7FOw==
70567049

7057-
"@types/retry@*":
7058-
version "0.12.5"
7059-
resolved "https://registry.yarnpkg.com/@types/retry/-/retry-0.12.5.tgz#f090ff4bd8d2e5b940ff270ab39fd5ca1834a07e"
7060-
integrity sha512-3xSjTp3v03X/lSQLkczaN9UIEwJMoMCA1+Nb5HfbJEQWogdeQIyVtTvxPXDQjZ5zws8rFQfVfRdz03ARihPJgw==
7061-
70627050
70637051
version "0.12.0"
70647052
resolved "https://registry.yarnpkg.com/@types/retry/-/retry-0.12.0.tgz#2b35eccfcee7d38cd72ad99232fbd58bffb3c84d"
@@ -8991,7 +8979,7 @@ async-promise-queue@^1.0.3, async-promise-queue@^1.0.5:
89918979
async "^2.4.1"
89928980
debug "^2.6.8"
89938981

8994-
async-retry@^1.2.1, async-retry@^1.3.3:
8982+
async-retry@^1.2.1:
89958983
version "1.3.3"
89968984
resolved "https://registry.yarnpkg.com/async-retry/-/async-retry-1.3.3.tgz#0e7f36c04d8478e7a58bdbed80cedf977785f280"
89978985
integrity sha512-wfr/jstw9xNi/0teMHrRW7dsz3Lt5ARhYNZ2ewpadnhaIp5mbALhOAP+EAdsC7t4Z6wqsDVv9+W6gm1Dk9mEyw==
@@ -16330,18 +16318,6 @@ gitconfiglocal@^1.0.0:
1633016318
dependencies:
1633116319
ini "^1.3.2"
1633216320

16333-
16334-
version "2.0.0"
16335-
resolved "https://registry.yarnpkg.com/github-fetch-workflow-artifact/-/github-fetch-workflow-artifact-2.0.0.tgz#0d763aec2fb3c6d81a165695892c4cda5892f2ac"
16336-
integrity sha512-FexZF1gRVKvbzVzOiHXDPFOkGkuqw7XqFoPc084WRBAj7juQqqMi4tCokaBof5I7N49kHYzsHpOVtIkvd/N5cQ==
16337-
dependencies:
16338-
"@actions/core" "^1.6.0"
16339-
"@actions/exec" "^1.1.0"
16340-
"@actions/github" "^5.0.0"
16341-
"@actions/io" "^1.1.1"
16342-
"@types/async-retry" "^1.4.3"
16343-
async-retry "^1.3.3"
16344-
1634516321
1634616322
version "0.0.0"
1634716323
resolved "https://registry.yarnpkg.com/github-from-package/-/github-from-package-0.0.0.tgz#97fb5d96bfde8973313f20e8288ef9a167fa64ce"

0 commit comments

Comments
 (0)