Compare commits

..

3 Commits

Author SHA1 Message Date
Bassem Dghaidi
a9bc5e6ef2 Use Node24 2026-03-17 06:33:43 -07:00
Bassem Dghaidi
ad191675b4 Use Node20 2026-03-17 06:25:04 -07:00
Bassem Dghaidi
1163061bb1 Security update dependencies including transitive 2026-03-17 06:17:42 -07:00
6 changed files with 4175 additions and 117132 deletions

View File

@@ -8,22 +8,6 @@ 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: 'node24'
main: 'dist/index.js' main: 'dist/index.js'

119536
dist/index.js vendored

File diff suppressed because one or more lines are too long

1586
package-lock.json generated

File diff suppressed because it is too large Load Diff

View File

@@ -1,6 +1,6 @@
{ {
"name": "download-artifact", "name": "download-artifact",
"version": "3.0.0", "version": "3.1.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,9 +28,8 @@
}, },
"homepage": "https://github.com/actions/download-artifact#readme", "homepage": "https://github.com/actions/download-artifact#readme",
"dependencies": { "dependencies": {
"@actions/artifact": "^2.0.0", "@actions/artifact": "^1.1.3",
"@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",

View File

@@ -1,11 +1,7 @@
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'
} }

View File

@@ -1,105 +1,61 @@
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'
const PARALLEL_DOWNLOADS = 5
export const chunk = <T>(arr: T[], n: number): T[][] =>
arr.reduce((acc, cur, i) => {
const index = Math.floor(i / n)
acc[index] = [...(acc[index] || []), cur]
return acc
}, [] as T[][])
async function run(): Promise<void> { async function run(): Promise<void> {
const inputs = { try {
name: core.getInput(Inputs.Name, {required: false}), const name = core.getInput(Inputs.Name, {required: false})
path: core.getInput(Inputs.Path, {required: false}), const 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) { let resolvedPath
inputs.path = process.env['GITHUB_WORKSPACE'] || process.cwd() // resolve tilde expansions, path.replace only replaces the first occurrence of a pattern
if (path.startsWith(`~`)) {
resolvedPath = resolve(path.replace('~', os.homedir()))
} else {
resolvedPath = resolve(path)
} }
if (inputs.path.startsWith(`~`)) {
inputs.path = inputs.path.replace('~', os.homedir())
}
const isSingleArtifactDownload: boolean = !!inputs.name
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()
let artifacts: artifact.Artifact[] = [] if (!name) {
// download all artifacts
if (isSingleArtifactDownload) { core.info('No artifact name specified, downloading all artifacts')
core.info(`Downloading single artifact`) core.info(
'Creating an extra directory for each artifact that is being downloaded'
const {artifact: targetArtifact} = await artifactClient.getArtifact( )
inputs.name, const downloadResponse = await artifactClient.downloadAllArtifacts(
inputs.runID, resolvedPath
owner, )
repo, core.info(`There were ${downloadResponse.length} artifacts downloaded`)
inputs.token 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 {
core.info(`No input name specified, downloading all artifacts. Extra directory with the artifact name will be created for each download`) // download a single artifact
core.info(`Starting download for ${name}`)
const listArtifactResponse = await artifactClient.listArtifacts( const downloadOptions = {
inputs.runID, createArtifactFolder: false
owner, }
repo, const downloadResponse = await artifactClient.downloadArtifact(
inputs.token name,
resolvedPath,
downloadOptions
) )
core.info(
if (listArtifactResponse.artifacts.length === 0) { `Artifact ${downloadResponse.artifactName} was downloaded to ${downloadResponse.downloadPath}`
throw new Error(
`No artifacts found for run '${inputs.runID}' in '${inputs.repository}'`
) )
} }
// output the directory that the artifact(s) was/were downloaded to
core.debug(`Found ${listArtifactResponse.artifacts.length} artifacts`) // if no path is provided, an empty string resolves to the current working directory
artifacts = listArtifactResponse.artifacts
}
const downloadPromises = artifacts.map(artifact =>
artifactClient.downloadArtifact(artifact.id, owner, repo, inputs.token, {
path: isSingleArtifactDownload ? resolvedPath : 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('Download artifact has finished successfully') core.info('Artifact download has finished successfully')
} catch (err) {
core.setFailed(err.message)
}
} }
run().catch(err => run()
core.setFailed(`Unable to download artifact(s): ${err.message}`)
)