1+ /* eslint-disable max-lines */
12import { promises as fs } from 'node:fs' ;
23import path from 'node:path' ;
34import { fileURLToPath } from 'node:url' ;
@@ -7,11 +8,10 @@ import * as core from '@actions/core';
78import { exec } from '@actions/exec' ;
89import { context , getOctokit } from '@actions/github' ;
910import * as glob from '@actions/glob' ;
11+ import * as io from '@actions/io' ;
1012import bytes from 'bytes' ;
1113import { markdownTable } from 'markdown-table' ;
1214
13- import download from 'github-fetch-workflow-artifact' ;
14-
1515const SIZE_LIMIT_HEADING = '## size-limit report 📦 ' ;
1616const ARTIFACT_NAME = 'size-limit-action' ;
1717const RESULTS_FILE = 'size-limit-results.json' ;
@@ -229,20 +229,28 @@ async function run() {
229229 let current ;
230230
231231 try {
232- // Ignore failures here as it is likely that this only happens when introducing size-limit
233- // and this has not been run on the main branch yet
234- await download ( octokit , {
232+ const artifacts = await getArtifactsForBranchAndWorkflow ( octokit , {
235233 ...repo ,
236234 artifactName : ARTIFACT_NAME ,
237235 branch : comparisonBranch ,
238- downloadPath : __dirname ,
239- workflowEvent : 'push' ,
240236 workflowName : `${ process . env . GITHUB_WORKFLOW || '' } ` ,
241237 } ) ;
238+
239+ if ( ! artifacts ) {
240+ throw new Error ( 'No artifacts found' ) ;
241+ }
242+
243+ await downloadOtherWorkflowArtifact ( octokit , {
244+ ...repo ,
245+ artifactName : ARTIFACT_NAME ,
246+ artifactId : artifacts . artifact . id ,
247+ downloadPath : __dirname ,
248+ } ) ;
249+
242250 base = JSON . parse ( await fs . readFile ( resultsFilePath , { encoding : 'utf8' } ) ) ;
243251 } catch ( error ) {
244252 core . startGroup ( 'Warning, unable to find base results' ) ;
245- core . debug ( error ) ;
253+ core . error ( error ) ;
246254 core . endGroup ( ) ;
247255 }
248256
@@ -295,4 +303,169 @@ async function run() {
295303 }
296304}
297305
306+ // max pages of workflows to pagination through
307+ const DEFAULT_MAX_PAGES = 50 ;
308+ // max results per page
309+ const DEFAULT_PAGE_LIMIT = 10 ;
310+
311+ /**
312+ * Fetch artifacts from a workflow run from a branch
313+ *
314+ * This is a bit hacky since GitHub Actions currently does not directly
315+ * support downloading artifacts from other workflows
316+ */
317+ /**
318+ * Fetch artifacts from a workflow run from a branch
319+ *
320+ * This is a bit hacky since GitHub Actions currently does not directly
321+ * support downloading artifacts from other workflows
322+ */
323+ export async function getArtifactsForBranchAndWorkflow ( octokit , { owner, repo, workflowName, branch, artifactName } ) {
324+ core . startGroup ( `getArtifactsForBranchAndWorkflow - workflow:"${ workflowName } ", branch:"${ branch } "` ) ;
325+
326+ let repositoryWorkflow = null ;
327+
328+ // For debugging
329+ const allWorkflows = [ ] ;
330+
331+ //
332+ // Find workflow id from `workflowName`
333+ //
334+ for await ( const response of octokit . paginate . iterator ( octokit . rest . actions . listRepoWorkflows , {
335+ owner,
336+ repo,
337+ } ) ) {
338+ const targetWorkflow = response . data . find ( ( { name } ) => name === workflowName ) ;
339+
340+ allWorkflows . push ( ...response . data . map ( ( { name } ) => name ) ) ;
341+
342+ // If not found in responses, continue to search on next page
343+ if ( ! targetWorkflow ) {
344+ continue ;
345+ }
346+
347+ repositoryWorkflow = targetWorkflow ;
348+ break ;
349+ }
350+
351+ if ( ! repositoryWorkflow ) {
352+ core . info (
353+ `Unable to find workflow with name "${ workflowName } " in the repository. Found workflows: ${ allWorkflows . join (
354+ ', ' ,
355+ ) } `,
356+ ) ;
357+ core . endGroup ( ) ;
358+ return null ;
359+ }
360+
361+ const workflow_id = repositoryWorkflow . id ;
362+
363+ let currentPage = 0 ;
364+ const completedWorkflowRuns = [ ] ;
365+
366+ for await ( const response of octokit . paginate . iterator ( octokit . rest . actions . listWorkflowRuns , {
367+ owner,
368+ repo,
369+ workflow_id,
370+ branch,
371+ status : 'completed' ,
372+ per_page : DEFAULT_PAGE_LIMIT ,
373+ event : 'push' ,
374+ } ) ) {
375+ if ( ! response . data . length ) {
376+ core . warning ( `Workflow ${ workflow_id } not found in branch ${ branch } ` ) ;
377+ core . endGroup ( ) ;
378+ return null ;
379+ }
380+
381+ // Do not allow downloading artifacts from a fork.
382+ completedWorkflowRuns . push (
383+ ...response . data . filter ( workflowRun => workflowRun . head_repository . full_name === `${ owner } /${ repo } ` ) ,
384+ ) ;
385+
386+ if ( completedWorkflowRuns . length ) {
387+ break ;
388+ }
389+
390+ if ( currentPage > DEFAULT_MAX_PAGES ) {
391+ core . warning ( `Workflow ${ workflow_id } not found in branch: ${ branch } ` ) ;
392+ core . endGroup ( ) ;
393+ return null ;
394+ }
395+
396+ currentPage ++ ;
397+ }
398+
399+ // Search through workflow artifacts until we find a workflow run w/ artifact name that we are looking for
400+ for ( const workflowRun of completedWorkflowRuns ) {
401+ core . info ( `Checking artifacts for workflow run: ${ workflowRun . html_url } ` ) ;
402+
403+ const {
404+ data : { artifacts } ,
405+ } = await octokit . rest . actions . listWorkflowRunArtifacts ( {
406+ owner,
407+ repo,
408+ run_id : workflowRun . id ,
409+ } ) ;
410+
411+ if ( ! artifacts ) {
412+ core . warning (
413+ `Unable to fetch artifacts for branch: ${ branch } , workflow: ${ workflow_id } , workflowRunId: ${ workflowRun . id } ` ,
414+ ) ;
415+ } else {
416+ const foundArtifact = artifacts . find ( ( { name } ) => name === artifactName ) ;
417+ if ( foundArtifact ) {
418+ core . info ( `Found suitable artifact: ${ foundArtifact . url } ` ) ;
419+ return {
420+ artifact : foundArtifact ,
421+ workflowRun,
422+ } ;
423+ }
424+ }
425+ }
426+
427+ core . warning ( `Artifact not found: ${ artifactName } ` ) ;
428+ core . endGroup ( ) ;
429+ return null ;
430+ }
431+
298432run ( ) ;
433+
434+ /**
435+ * Use GitHub API to fetch artifact download url, then
436+ * download and extract artifact to `downloadPath`
437+ */
438+ async function downloadOtherWorkflowArtifact ( octokit , { owner, repo, artifactId, artifactName, downloadPath } ) {
439+ const artifact = await octokit . rest . actions . downloadArtifact ( {
440+ owner,
441+ repo,
442+ artifact_id : artifactId ,
443+ archive_format : 'zip' ,
444+ } ) ;
445+
446+ // Make sure output path exists
447+ try {
448+ await io . mkdirP ( downloadPath ) ;
449+ } catch {
450+ // ignore errors
451+ }
452+
453+ const downloadFile = path . resolve ( downloadPath , `${ artifactName } .zip` ) ;
454+
455+ await exec ( 'wget' , [
456+ '-nv' ,
457+ '--retry-connrefused' ,
458+ '--waitretry=1' ,
459+ '--read-timeout=20' ,
460+ '--timeout=15' ,
461+ '-t' ,
462+ '0' ,
463+ '-O' ,
464+ downloadFile ,
465+ artifact . url ,
466+ ] ) ;
467+
468+ await exec ( 'unzip' , [ '-q' , '-d' , downloadPath , downloadFile ] , {
469+ silent : true ,
470+ } ) ;
471+ }
0 commit comments