mirror of
https://git.mirrors.martin98.com/https://github.com/actions/toolkit
synced 2026-04-21 07:08:04 +08:00
add download apis to stream zip from blob storage
This commit is contained in:
@@ -1,10 +1,10 @@
|
||||
import {ArtifactClient, Client} from './internal/client'
|
||||
import {UploadOptions, UploadResponse} from './internal/shared/interfaces'
|
||||
|
||||
/**
|
||||
* Exported functionality that we want to expose for any users of @actions/artifact
|
||||
*/
|
||||
export {ArtifactClient, UploadOptions, UploadResponse}
|
||||
export * from './internal/shared/interfaces'
|
||||
export {ArtifactClient}
|
||||
|
||||
export function create(): ArtifactClient {
|
||||
return Client.create()
|
||||
|
||||
@@ -1,7 +1,52 @@
|
||||
import path from 'path'
|
||||
import fs from 'fs/promises'
|
||||
import {PathLike} from 'fs'
|
||||
import github from '@actions/github'
|
||||
import core from '@actions/core'
|
||||
import httpClient from '@actions/http-client'
|
||||
import unzipper from 'unzipper'
|
||||
import {
|
||||
DownloadArtifactOptions,
|
||||
DownloadArtifactResponse
|
||||
} from '../shared/interfaces'
|
||||
import {getUserAgentString} from '../shared/user-agent'
|
||||
|
||||
const scrubQueryParameters = (url: string): string => {
|
||||
const parsed = new URL(url)
|
||||
parsed.search = ''
|
||||
return parsed.toString()
|
||||
}
|
||||
|
||||
async function exists(path: string): Promise<boolean> {
|
||||
try {
|
||||
await fs.access(path)
|
||||
return true
|
||||
} catch (error) {
|
||||
if (error.code === 'ENOENT') {
|
||||
return false
|
||||
} else {
|
||||
throw error
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
async function streamExtract(url: string, directory: PathLike): Promise<void> {
|
||||
const client = new httpClient.HttpClient(getUserAgentString())
|
||||
const response = await client.get(url)
|
||||
|
||||
if (response.message.statusCode !== 200) {
|
||||
throw new Error(
|
||||
`Unexpected HTTP response from blob storage: ${response.message.statusCode} ${response.message.statusMessage}`
|
||||
)
|
||||
}
|
||||
|
||||
return new Promise((resolve, reject) => {
|
||||
response.message
|
||||
.pipe(unzipper.Extract({path: directory}))
|
||||
.on('finish', resolve)
|
||||
.on('error', reject)
|
||||
})
|
||||
}
|
||||
|
||||
export async function downloadArtifact(
|
||||
artifactId: number,
|
||||
@@ -10,5 +55,54 @@ export async function downloadArtifact(
|
||||
token: string,
|
||||
options?: DownloadArtifactOptions
|
||||
): Promise<DownloadArtifactResponse> {
|
||||
throw new Error('Not implemented')
|
||||
let downloadPath = options?.path || process.cwd() // TODO: make this align with GITHUB_WORKSPACE
|
||||
if (options?.createArtifactFolder) {
|
||||
downloadPath = path.join(downloadPath, 'my-artifact') // TODO: need to pass artifact name
|
||||
}
|
||||
|
||||
if (!(await exists(downloadPath))) {
|
||||
core.debug(`Creating artifact folder: ${downloadPath}`)
|
||||
await fs.mkdir(downloadPath, {recursive: true})
|
||||
} else {
|
||||
core.warning(`Artifact folder already exists: ${downloadPath}`)
|
||||
}
|
||||
|
||||
const api = github.getOctokit(token)
|
||||
|
||||
core.info(
|
||||
`Downloading artifact ${artifactId} from ${repositoryOwner}/${repositoryName}`
|
||||
)
|
||||
|
||||
const {headers, status} = await api.rest.actions.downloadArtifact({
|
||||
owner: repositoryOwner,
|
||||
repo: repositoryName,
|
||||
artifact_id: artifactId,
|
||||
archive_format: 'zip',
|
||||
request: {
|
||||
redirect: 'manual'
|
||||
}
|
||||
})
|
||||
|
||||
if (status !== 302) {
|
||||
throw new Error(`Unable to download artifact. Unexpected status: ${status}`)
|
||||
}
|
||||
|
||||
const {location} = headers
|
||||
if (!location) {
|
||||
throw new Error(`Unable to redirect to artifact download url`)
|
||||
}
|
||||
|
||||
core.info(
|
||||
`Redirecting to blob download url: ${scrubQueryParameters(location)}`
|
||||
)
|
||||
|
||||
try {
|
||||
core.info(`Starting download of artifact to: ${downloadPath}`)
|
||||
await streamExtract(location, downloadPath)
|
||||
core.info(`Artifact download completed successfully.`)
|
||||
} catch (error) {
|
||||
throw new Error(`Unable to download and extract artifact: ${error.message}`)
|
||||
}
|
||||
|
||||
return {success: true}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user