mirror of
https://github.com/actions/download-artifact.git
synced 2026-03-21 15:36:10 +08:00
Compare commits
8 Commits
v3/v3.1.0-
...
robherley/
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
9140050fd5 | ||
|
|
896d1bb258 | ||
|
|
57685c7c71 | ||
|
|
8c323b340c | ||
|
|
727cfbe442 | ||
|
|
24b1443a07 | ||
|
|
e9ef242655 | ||
|
|
adf9559c4f |
18
action.yml
18
action.yml
@@ -8,6 +8,22 @@ inputs:
|
|||||||
path:
|
path:
|
||||||
description: 'Destination path'
|
description: 'Destination path'
|
||||||
required: false
|
required: false
|
||||||
|
github-token:
|
||||||
|
description: The GitHub token used to download the artifact
|
||||||
|
default: ${{ github.token }}
|
||||||
|
required: false
|
||||||
|
repository:
|
||||||
|
description: 'The repository owner and the repository name joined together by "/".
|
||||||
|
This specifies the repository that artifacts will be downloaded from. If downloading artifacts from external workflow runs or repositories then the above download-token must be permissions to this repository.'
|
||||||
|
required: false
|
||||||
|
default: ${{ github.repository }}
|
||||||
|
run-id:
|
||||||
|
description: 'The id of the workflow run where the desired download artifact was uploaded from. If downloading artifacts from anything other than the current workflow run then this needs to be overwritten.'
|
||||||
|
required: false
|
||||||
|
default: ${{ github.run_id }}
|
||||||
|
outputs:
|
||||||
|
download-path:
|
||||||
|
description: 'Path of artifact download'
|
||||||
runs:
|
runs:
|
||||||
using: 'node20'
|
using: 'node16'
|
||||||
main: 'dist/index.js'
|
main: 'dist/index.js'
|
||||||
|
|||||||
119554
dist/index.js
vendored
119554
dist/index.js
vendored
File diff suppressed because one or more lines are too long
1578
package-lock.json
generated
1578
package-lock.json
generated
File diff suppressed because it is too large
Load Diff
@@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "download-artifact",
|
"name": "download-artifact",
|
||||||
"version": "3.1.0",
|
"version": "3.0.0",
|
||||||
"description": "Download a build artifact that was previously uploaded in the workflow by the upload-artifact action",
|
"description": "Download a build artifact that was previously uploaded in the workflow by the upload-artifact action",
|
||||||
"main": "dist/index.js",
|
"main": "dist/index.js",
|
||||||
"scripts": {
|
"scripts": {
|
||||||
@@ -28,8 +28,9 @@
|
|||||||
},
|
},
|
||||||
"homepage": "https://github.com/actions/download-artifact#readme",
|
"homepage": "https://github.com/actions/download-artifact#readme",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@actions/artifact": "^1.1.3",
|
"@actions/artifact": "^2.0.0",
|
||||||
"@actions/core": "^1.10.0"
|
"@actions/core": "^1.10.0",
|
||||||
|
"@actions/github": "^5.1.1"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@types/node": "^12.12.6",
|
"@types/node": "^12.12.6",
|
||||||
|
|||||||
@@ -1,7 +1,11 @@
|
|||||||
export enum Inputs {
|
export enum Inputs {
|
||||||
Name = 'name',
|
Name = 'name',
|
||||||
Path = 'path'
|
Path = 'path',
|
||||||
|
GitHubToken = 'github-token',
|
||||||
|
Repository = 'repository',
|
||||||
|
RunID = 'run-id'
|
||||||
}
|
}
|
||||||
|
|
||||||
export enum Outputs {
|
export enum Outputs {
|
||||||
DownloadPath = 'download-path'
|
DownloadPath = 'download-path'
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,61 +1,100 @@
|
|||||||
|
import * as os from 'os'
|
||||||
|
import * as path from 'path'
|
||||||
import * as core from '@actions/core'
|
import * as core from '@actions/core'
|
||||||
import * as artifact from '@actions/artifact'
|
import * as artifact from '@actions/artifact'
|
||||||
import * as os from 'os'
|
|
||||||
import {resolve} from 'path'
|
|
||||||
import {Inputs, Outputs} from './constants'
|
import {Inputs, Outputs} from './constants'
|
||||||
|
|
||||||
async function run(): Promise<void> {
|
const PARALLEL_DOWNLOADS = 5
|
||||||
try {
|
|
||||||
const name = core.getInput(Inputs.Name, {required: false})
|
|
||||||
const path = core.getInput(Inputs.Path, {required: false})
|
|
||||||
|
|
||||||
let resolvedPath
|
export const chunk = <T>(arr: T[], n: number): T[][] =>
|
||||||
// resolve tilde expansions, path.replace only replaces the first occurrence of a pattern
|
arr.reduce((acc, cur, i) => {
|
||||||
if (path.startsWith(`~`)) {
|
const index = Math.floor(i / n)
|
||||||
resolvedPath = resolve(path.replace('~', os.homedir()))
|
acc[index] = [...(acc[index] || []), cur]
|
||||||
} else {
|
return acc
|
||||||
resolvedPath = resolve(path)
|
}, [] as T[][])
|
||||||
|
|
||||||
|
async function run(): Promise<void> {
|
||||||
|
const inputs = {
|
||||||
|
name: core.getInput(Inputs.Name, {required: false}),
|
||||||
|
path: core.getInput(Inputs.Path, {required: false}),
|
||||||
|
token: core.getInput(Inputs.GitHubToken, {required: true}),
|
||||||
|
repository: core.getInput(Inputs.Repository, {required: true}),
|
||||||
|
runID: parseInt(core.getInput(Inputs.RunID, {required: true}))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (!inputs.path) {
|
||||||
|
inputs.path = process.env['GITHUB_WORKSPACE'] || process.cwd()
|
||||||
|
}
|
||||||
|
|
||||||
|
if (inputs.path.startsWith(`~`)) {
|
||||||
|
inputs.path = inputs.path.replace('~', os.homedir())
|
||||||
|
}
|
||||||
|
|
||||||
|
const resolvedPath = path.resolve(inputs.path)
|
||||||
core.debug(`Resolved path is ${resolvedPath}`)
|
core.debug(`Resolved path is ${resolvedPath}`)
|
||||||
|
|
||||||
|
const [owner, repo] = inputs.repository.split('/')
|
||||||
|
if (!owner || !repo) {
|
||||||
|
throw new Error(
|
||||||
|
`Invalid repository: '${inputs.repository}'. Must be in format owner/repo`
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
const artifactClient = artifact.create()
|
const artifactClient = artifact.create()
|
||||||
if (!name) {
|
let artifacts: artifact.Artifact[] = []
|
||||||
// download all artifacts
|
|
||||||
core.info('No artifact name specified, downloading all artifacts')
|
if (inputs.name) {
|
||||||
core.info(
|
const {artifact: targetArtifact} = await artifactClient.getArtifact(
|
||||||
'Creating an extra directory for each artifact that is being downloaded'
|
inputs.name,
|
||||||
)
|
inputs.runID,
|
||||||
const downloadResponse = await artifactClient.downloadAllArtifacts(
|
owner,
|
||||||
resolvedPath
|
repo,
|
||||||
)
|
inputs.token
|
||||||
core.info(`There were ${downloadResponse.length} artifacts downloaded`)
|
|
||||||
for (const artifact of downloadResponse) {
|
|
||||||
core.info(
|
|
||||||
`Artifact ${artifact.artifactName} was downloaded to ${artifact.downloadPath}`
|
|
||||||
)
|
)
|
||||||
|
|
||||||
|
if (!targetArtifact) {
|
||||||
|
throw new Error(`Artifact '${inputs.name}' not found`)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
core.debug(
|
||||||
|
`Found named artifact '${inputs.name}' (ID: ${targetArtifact.id}, Size: ${targetArtifact.size})`
|
||||||
|
)
|
||||||
|
|
||||||
|
artifacts = [targetArtifact]
|
||||||
} else {
|
} else {
|
||||||
// download a single artifact
|
const listArtifactResponse = await artifactClient.listArtifacts(
|
||||||
core.info(`Starting download for ${name}`)
|
inputs.runID,
|
||||||
const downloadOptions = {
|
owner,
|
||||||
createArtifactFolder: false
|
repo,
|
||||||
}
|
inputs.token
|
||||||
const downloadResponse = await artifactClient.downloadArtifact(
|
|
||||||
name,
|
|
||||||
resolvedPath,
|
|
||||||
downloadOptions
|
|
||||||
)
|
)
|
||||||
core.info(
|
|
||||||
`Artifact ${downloadResponse.artifactName} was downloaded to ${downloadResponse.downloadPath}`
|
if (listArtifactResponse.artifacts.length === 0) {
|
||||||
|
throw new Error(
|
||||||
|
`No artifacts found for run '${inputs.runID}' in '${inputs.repository}'`
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
// output the directory that the artifact(s) was/were downloaded to
|
|
||||||
// if no path is provided, an empty string resolves to the current working directory
|
core.debug(`Found ${listArtifactResponse.artifacts.length} artifacts`)
|
||||||
|
artifacts = listArtifactResponse.artifacts
|
||||||
|
}
|
||||||
|
|
||||||
|
const downloadPromises = artifacts.map(artifact =>
|
||||||
|
artifactClient.downloadArtifact(artifact.id, owner, repo, inputs.token, {
|
||||||
|
path: path.join(resolvedPath, artifact.name)
|
||||||
|
})
|
||||||
|
)
|
||||||
|
|
||||||
|
const chunkedPromises = chunk(downloadPromises, PARALLEL_DOWNLOADS)
|
||||||
|
for (const chunk of chunkedPromises) {
|
||||||
|
await Promise.all(chunk)
|
||||||
|
}
|
||||||
|
|
||||||
|
core.info(`Total of ${artifacts.length} artifact(s) downloaded`)
|
||||||
core.setOutput(Outputs.DownloadPath, resolvedPath)
|
core.setOutput(Outputs.DownloadPath, resolvedPath)
|
||||||
core.info('Artifact download has finished successfully')
|
core.info('Download artifact has finished successfully')
|
||||||
} catch (err) {
|
|
||||||
core.setFailed(err.message)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
run()
|
run().catch(err =>
|
||||||
|
core.setFailed(`Unable to download artifact(s): ${err.message}`)
|
||||||
|
)
|
||||||
|
|||||||
Reference in New Issue
Block a user