blob: 4eefb7454f36b617acf04e55bc729e223420ff72 [file] [log] [blame]
import {createWriteStream} from 'fs'
import * as core from '@actions/core'
import * as github from '@actions/github'
import {GitHub} from '@actions/github/lib/utils'
import {EventPayloads} from '@octokit/webhooks'
import * as stream from 'stream'
import {promisify} from 'util'
import got from 'got'
const asyncStream = promisify(stream.pipeline)
export function getCheckRunContext(): {sha: string; runId: number} {
if (github.context.eventName === 'workflow_run') {
core.info('Action was triggered by workflow_run: using SHA and RUN_ID from triggering workflow')
const event = github.context.payload as EventPayloads.WebhookPayloadWorkflowRun
if (!event.workflow_run) {
throw new Error("Event of type 'workflow_run' is missing 'workflow_run' field")
}
return {
sha: event.workflow_run.head_commit.id,
runId: event.workflow_run.id
}
}
const runId = github.context.runId
if (github.context.payload.pull_request) {
core.info(`Action was triggered by ${github.context.eventName}: using SHA from head of source branch`)
const pr = github.context.payload.pull_request as EventPayloads.WebhookPayloadPullRequestPullRequest
return {sha: pr.head.sha, runId}
}
return {sha: github.context.sha, runId}
}
export async function downloadArtifact(
octokit: InstanceType<typeof GitHub>,
artifactId: number,
fileName: string,
token: string
): Promise<void> {
core.startGroup(`Downloading artifact ${fileName}`)
try {
core.info(`Artifact ID: ${artifactId}`)
const req = octokit.actions.downloadArtifact.endpoint({
...github.context.repo,
artifact_id: artifactId,
archive_format: 'zip'
})
const headers = {
Authorization: `Bearer ${token}`
}
const resp = await got(req.url, {
headers,
followRedirect: false
})
core.info(`Fetch artifact URL: ${resp.statusCode} ${resp.statusMessage}`)
if (resp.statusCode !== 302) {
throw new Error('Fetch artifact URL failed: received unexpected status code')
}
const url = resp.headers.location
if (url === undefined) {
const receivedHeaders = Object.keys(resp.headers)
core.info(`Received headers: ${receivedHeaders.join(', ')}`)
throw new Error('Location header was not found in API response')
}
if (typeof url !== 'string') {
throw new Error(`Location header has unexpected value: ${url}`)
}
const downloadStream = got.stream(url, {headers})
const fileWriterStream = createWriteStream(fileName)
core.info(`Downloading ${url}`)
downloadStream.on('downloadProgress', ({transferred}) => {
core.info(`Progress: ${transferred} B`)
})
await asyncStream(downloadStream, fileWriterStream)
} finally {
core.endGroup()
}
}
export async function listFiles(octokit: InstanceType<typeof GitHub>, sha: string): Promise<string[]> {
core.startGroup('Fetching list of tracked files from GitHub')
try {
const commit = await octokit.git.getCommit({
commit_sha: sha,
...github.context.repo
})
const files = await listGitTree(octokit, commit.data.tree.sha, '')
return files
} finally {
core.endGroup()
}
}
async function listGitTree(octokit: InstanceType<typeof GitHub>, sha: string, path: string): Promise<string[]> {
const pathLog = path ? ` at ${path}` : ''
core.info(`Fetching tree ${sha}${pathLog}`)
let truncated = false
let tree = await octokit.git.getTree({
recursive: 'true',
tree_sha: sha,
...github.context.repo
})
if (tree.data.truncated) {
truncated = true
tree = await octokit.git.getTree({
tree_sha: sha,
...github.context.repo
})
}
const result: string[] = []
for (const tr of tree.data.tree) {
const file = `${path}${tr.path}`
if (tr.type === 'blob') {
result.push(file)
} else if (tr.type === 'tree' && truncated) {
const files = await listGitTree(octokit, tr.sha, `${file}/`)
result.push(...files)
}
}
return result
}