2023-08-17 14:40:33 -04:00
import { info , warning , debug } from '@actions/core'
import { getOctokit } from '@actions/github'
import { ListArtifactsResponse , Artifact } from '../shared/interfaces'
import { getUserAgentString } from '../shared/user-agent'
2023-08-23 10:36:33 -07:00
import { getRetryOptions } from './retry-options'
2023-08-17 14:40:33 -04:00
import { defaults as defaultGitHubOptions } from '@actions/github/lib/utils'
import { requestLog } from '@octokit/plugin-request-log'
import { retry } from '@octokit/plugin-retry'
2023-08-23 10:36:33 -07:00
import { OctokitOptions } from '@octokit/core/dist-types/types'
2023-11-30 03:47:04 +00:00
import { internalArtifactTwirpClient } from '../shared/artifact-twirp-client'
import { getBackendIdsFromToken } from '../shared/util'
import { ListArtifactsRequest } from 'src/generated'
2023-08-17 14:40:33 -04:00
// Limiting to 1000 for perf reasons
const maximumArtifactCount = 1000
const paginationCount = 100
const maxNumberOfPages = maximumArtifactCount / paginationCount
2023-11-30 03:47:04 +00:00
export async function listArtifactsPublic (
2023-08-17 14:40:33 -04:00
workflowRunId : number ,
repositoryOwner : string ,
repositoryName : string ,
token : string
) : Promise < ListArtifactsResponse > {
2023-08-22 09:57:14 -07:00
info (
`Fetching artifact list for workflow run ${ workflowRunId } in repository ${ repositoryOwner } / ${ repositoryName } `
)
2023-08-17 14:40:33 -04:00
const artifacts : Artifact [] = []
2023-08-23 10:36:33 -07:00
const [ retryOpts , requestOpts ] = getRetryOptions ( defaultGitHubOptions )
2023-08-17 14:40:33 -04:00
2023-08-23 10:36:33 -07:00
const opts : OctokitOptions = {
2023-08-17 14:40:33 -04:00
log : undefined ,
userAgent : getUserAgentString (),
previews : undefined ,
retry : retryOpts ,
request : requestOpts
}
const github = getOctokit ( token , opts , retry , requestLog )
let currentPageNumber = 1
const { data : listArtifactResponse } =
await github . rest . actions . listWorkflowRunArtifacts ({
owner : repositoryOwner ,
repo : repositoryName ,
run_id : workflowRunId ,
per_page : paginationCount ,
page : currentPageNumber
})
let numberOfPages = Math . ceil (
listArtifactResponse . total_count / paginationCount
)
const totalArtifactCount = listArtifactResponse . total_count
if ( totalArtifactCount > maximumArtifactCount ) {
warning (
`Workflow run ${ workflowRunId } has more than 1000 artifacts. Results will be incomplete as only the first ${ maximumArtifactCount } artifacts will be returned`
)
numberOfPages = maxNumberOfPages
}
// Iterate over the first page
2023-08-22 10:06:40 -07:00
for ( const artifact of listArtifactResponse . artifacts ) {
2023-08-17 14:40:33 -04:00
artifacts . push ({
name : artifact.name ,
id : artifact.id ,
size : artifact.size_in_bytes
})
2023-08-22 10:06:40 -07:00
}
2023-08-17 14:40:33 -04:00
// Iterate over any remaining pages
for (
currentPageNumber ;
currentPageNumber < numberOfPages ;
currentPageNumber ++
) {
currentPageNumber ++
debug ( `Fetching page ${ currentPageNumber } of artifact list` )
const { data : listArtifactResponse } =
await github . rest . actions . listWorkflowRunArtifacts ({
owner : repositoryOwner ,
repo : repositoryName ,
run_id : workflowRunId ,
per_page : paginationCount ,
page : currentPageNumber
})
2023-08-22 10:06:40 -07:00
for ( const artifact of listArtifactResponse . artifacts ) {
2023-08-17 14:40:33 -04:00
artifacts . push ({
name : artifact.name ,
id : artifact.id ,
size : artifact.size_in_bytes
})
2023-08-22 10:06:40 -07:00
}
2023-08-17 14:40:33 -04:00
}
2023-11-30 03:47:04 +00:00
info ( `Found ${ artifacts . length } artifact(s)` )
return {
artifacts
}
}
export async function listArtifactsInternal () : Promise < ListArtifactsResponse > {
const artifactClient = internalArtifactTwirpClient ()
const { workflowRunBackendId , workflowJobRunBackendId } =
getBackendIdsFromToken ()
const req : ListArtifactsRequest = {
workflowRunBackendId ,
workflowJobRunBackendId ,
nameFilter : '' ,
idFilter : '0' // TODO(robherley): zero values are awkward, use pb wrappers
}
const res = await artifactClient . ListArtifacts ( req )
const artifacts = res . artifacts . map ( artifact => ({
name : artifact.name ,
id : Number ( artifact . databaseId ),
size : Number ( artifact . size )
}))
info ( `Found ${ artifacts . length } artifact(s)` )
2023-08-17 14:40:33 -04:00
return {
2023-08-22 10:06:40 -07:00
artifacts
2023-08-17 14:40:33 -04:00
}
}