mirror of
https://github.com/actions/download-artifact.git
synced 2025-12-27 01:53:57 -05:00
Compare commits
1 Commits
patch-zip-
...
releases/v
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
cbed621e49 |
@@ -1,6 +0,0 @@
|
||||
// For format details, see https://aka.ms/devcontainer.json. For config options, see the
|
||||
// README at: https://github.com/devcontainers/templates/tree/main/src/typescript-node
|
||||
{
|
||||
"name": "@actions/download-artifact",
|
||||
"image": "mcr.microsoft.com/devcontainers/typescript-node:0-16"
|
||||
}
|
||||
11
.github/workflows/check-dist.yml
vendored
11
.github/workflows/check-dist.yml
vendored
@@ -22,13 +22,12 @@ jobs:
|
||||
runs-on: ubuntu-latest
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@v3
|
||||
- uses: actions/checkout@v2
|
||||
|
||||
- name: Setup Node 16
|
||||
uses: actions/setup-node@v3
|
||||
- name: Set Node.js 12.x
|
||||
uses: actions/setup-node@v1
|
||||
with:
|
||||
node-version: 16.x
|
||||
cache: 'npm'
|
||||
node-version: 12.x
|
||||
|
||||
- name: Install dependencies
|
||||
run: npm ci
|
||||
@@ -46,7 +45,7 @@ jobs:
|
||||
id: diff
|
||||
|
||||
# If index.js was different than expected, upload the expected version as an artifact
|
||||
- uses: actions/upload-artifact@v3
|
||||
- uses: actions/upload-artifact@v2
|
||||
if: ${{ failure() && steps.diff.conclusion == 'failure' }}
|
||||
with:
|
||||
name: dist
|
||||
|
||||
8
.github/workflows/codeql-analysis.yml
vendored
8
.github/workflows/codeql-analysis.yml
vendored
@@ -20,11 +20,11 @@ jobs:
|
||||
|
||||
steps:
|
||||
- name: Checkout repository
|
||||
uses: actions/checkout@v3
|
||||
uses: actions/checkout@v2
|
||||
|
||||
# Initializes the CodeQL tools for scanning.
|
||||
- name: Initialize CodeQL
|
||||
uses: github/codeql-action/init@v2
|
||||
uses: github/codeql-action/init@v1
|
||||
# Override language selection by uncommenting this and choosing your languages
|
||||
# with:
|
||||
# languages: go, javascript, csharp, python, cpp, java
|
||||
@@ -32,7 +32,7 @@ jobs:
|
||||
# Autobuild attempts to build any compiled languages (C/C++, C#, or Java).
|
||||
# If this step fails, then you should remove it and run the build manually (see below)
|
||||
- name: Autobuild
|
||||
uses: github/codeql-action/autobuild@v2
|
||||
uses: github/codeql-action/autobuild@v1
|
||||
|
||||
# ℹ️ Command-line programs to run using the OS shell.
|
||||
# 📚 https://git.io/JvXDl
|
||||
@@ -46,4 +46,4 @@ jobs:
|
||||
# make release
|
||||
|
||||
- name: Perform CodeQL Analysis
|
||||
uses: github/codeql-action/analyze@v2
|
||||
uses: github/codeql-action/analyze@v1
|
||||
|
||||
2
.github/workflows/licensed.yml
vendored
2
.github/workflows/licensed.yml
vendored
@@ -13,7 +13,7 @@ jobs:
|
||||
runs-on: ubuntu-latest
|
||||
name: Check licenses
|
||||
steps:
|
||||
- uses: actions/checkout@v3
|
||||
- uses: actions/checkout@v2
|
||||
- run: npm ci
|
||||
- name: Install licensed
|
||||
run: |
|
||||
|
||||
@@ -21,7 +21,7 @@ jobs:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: Update the ${{ env.TAG_NAME }} tag
|
||||
uses: actions/publish-action@v0.2.1
|
||||
uses: actions/publish-action@v0.1.0
|
||||
with:
|
||||
source-tag: ${{ env.TAG_NAME }}
|
||||
slack-webhook: ${{ secrets.SLACK_WEBHOOK }}
|
||||
|
||||
10
.github/workflows/test.yml
vendored
10
.github/workflows/test.yml
vendored
@@ -21,14 +21,12 @@ jobs:
|
||||
|
||||
steps:
|
||||
- name: Checkout
|
||||
uses: actions/checkout@v3
|
||||
uses: actions/checkout@v2
|
||||
|
||||
# using node 16 since that is what the latest version of the runner ships with
|
||||
- name: Setup Node 16
|
||||
uses: actions/setup-node@v3
|
||||
- name: Set Node.js 12.x
|
||||
uses: actions/setup-node@v1
|
||||
with:
|
||||
node-version: 16.x
|
||||
cache: 'npm'
|
||||
node-version: 12.x
|
||||
|
||||
- name: npm install
|
||||
run: npm install
|
||||
|
||||
BIN
.licenses/npm/@actions/artifact.dep.yml
generated
BIN
.licenses/npm/@actions/artifact.dep.yml
generated
Binary file not shown.
BIN
.licenses/npm/@actions/core.dep.yml
generated
BIN
.licenses/npm/@actions/core.dep.yml
generated
Binary file not shown.
BIN
.licenses/npm/@actions/http-client-2.0.1.dep.yml
generated
BIN
.licenses/npm/@actions/http-client-2.0.1.dep.yml
generated
Binary file not shown.
BIN
.licenses/npm/@types/tmp.dep.yml
generated
Normal file
BIN
.licenses/npm/@types/tmp.dep.yml
generated
Normal file
Binary file not shown.
BIN
.licenses/npm/minimatch.dep.yml
generated
BIN
.licenses/npm/minimatch.dep.yml
generated
Binary file not shown.
BIN
.licenses/npm/rimraf.dep.yml
generated
BIN
.licenses/npm/rimraf.dep.yml
generated
Binary file not shown.
BIN
.licenses/npm/tmp-promise.dep.yml
generated
BIN
.licenses/npm/tmp-promise.dep.yml
generated
Binary file not shown.
BIN
.licenses/npm/tmp.dep.yml
generated
BIN
.licenses/npm/tmp.dep.yml
generated
Binary file not shown.
BIN
.licenses/npm/uuid.dep.yml
generated
BIN
.licenses/npm/uuid.dep.yml
generated
Binary file not shown.
32
README.md
32
README.md
@@ -1,4 +1,4 @@
|
||||
# Download-Artifact v3
|
||||
# Download-Artifact v2
|
||||
|
||||
This downloads artifacts from your build
|
||||
|
||||
@@ -10,7 +10,7 @@ See also [upload-artifact](https://github.com/actions/upload-artifact).
|
||||
- Output parameter for the download path
|
||||
- Port entire action to typescript from a runner plugin so it is easier to collaborate and accept contributions
|
||||
|
||||
Refer [here](https://github.com/actions/download-artifact/tree/v2) for the previous version
|
||||
Refer [here](https://github.com/actions/download-artifact/tree/v1) for the previous version
|
||||
|
||||
# Usage
|
||||
|
||||
@@ -21,9 +21,9 @@ See [action.yml](action.yml)
|
||||
Basic (download to the current working directory):
|
||||
```yaml
|
||||
steps:
|
||||
- uses: actions/checkout@v3
|
||||
- uses: actions/checkout@v2
|
||||
|
||||
- uses: actions/download-artifact@v3
|
||||
- uses: actions/download-artifact@v2
|
||||
with:
|
||||
name: my-artifact
|
||||
|
||||
@@ -34,9 +34,9 @@ steps:
|
||||
Download to a specific directory:
|
||||
```yaml
|
||||
steps:
|
||||
- uses: actions/checkout@v3
|
||||
- uses: actions/checkout@v2
|
||||
|
||||
- uses: actions/download-artifact@v3
|
||||
- uses: actions/download-artifact@v2
|
||||
with:
|
||||
name: my-artifact
|
||||
path: path/to/artifact
|
||||
@@ -48,13 +48,13 @@ steps:
|
||||
|
||||
Basic tilde expansion is supported for the `path` input:
|
||||
```yaml
|
||||
- uses: actions/download-artifact@v3
|
||||
- uses: actions/download-artifact@v2
|
||||
with:
|
||||
name: my-artifact
|
||||
path: ~/download/path
|
||||
```
|
||||
|
||||
## Compatibility between `v1` and `v2`/`v3`
|
||||
## Compatibility between `v1` and `v2`
|
||||
|
||||
When using `download-artifact@v1`, a directory denoted by the name of the artifact would be created if the `path` input was not provided. All of the contents would be downloaded to this directory.
|
||||
```
|
||||
@@ -63,13 +63,13 @@ When using `download-artifact@v1`, a directory denoted by the name of the artifa
|
||||
... contents of my-artifact
|
||||
```
|
||||
|
||||
With `v2` and `v3`, when an artifact is specified by the `name` input, there is no longer an extra directory that is created if the `path` input is not provided. All the contents are downloaded to the current working directory.
|
||||
With `v2`, when an artifact is specified by the `name` input, there is no longer an extra directory that is created if the `path` input is not provided. All the contents are downloaded to the current working directory.
|
||||
```
|
||||
current/working/directory/
|
||||
... contents of my-artifact
|
||||
```
|
||||
|
||||
To maintain the same behavior for `v2` and `v3`, you can set the `path` to the name of the artifact so an extra directory gets created.
|
||||
To maintain the same behavior for `v2`, you can set the `path` to the name of the artifact so an extra directory gets created.
|
||||
```
|
||||
- uses: actions/download-artifact@v2
|
||||
with:
|
||||
@@ -93,9 +93,9 @@ Example, if there are two artifacts `Artifact-A` and `Artifact-B`, and the direc
|
||||
Download all artifacts to a specific directory
|
||||
```yaml
|
||||
steps:
|
||||
- uses: actions/checkout@v3
|
||||
- uses: actions/checkout@v2
|
||||
|
||||
- uses: actions/download-artifact@v3
|
||||
- uses: actions/download-artifact@v2
|
||||
with:
|
||||
path: path/to/artifacts
|
||||
|
||||
@@ -107,9 +107,9 @@ steps:
|
||||
Download all artifacts to the current working directory
|
||||
```yaml
|
||||
steps:
|
||||
- uses: actions/checkout@v3
|
||||
- uses: actions/checkout@v2
|
||||
|
||||
- uses: actions/download-artifact@v3
|
||||
- uses: actions/download-artifact@v2
|
||||
|
||||
- name: Display structure of downloaded files
|
||||
run: ls -R
|
||||
@@ -121,9 +121,9 @@ The `download-path` step output contains information regarding where the artifac
|
||||
|
||||
```yaml
|
||||
steps:
|
||||
- uses: actions/checkout@v3
|
||||
- uses: actions/checkout@v2
|
||||
|
||||
- uses: actions/download-artifact@v3
|
||||
- uses: actions/download-artifact@v2
|
||||
id: download
|
||||
with:
|
||||
name: 'my-artifact'
|
||||
|
||||
24
action.yml
24
action.yml
@@ -1,31 +1,13 @@
|
||||
name: 'Download a Build Artifact'
|
||||
description: 'Download a build artifact that was previously uploaded in the workflow by the upload-artifact action'
|
||||
author: 'GitHub'
|
||||
inputs:
|
||||
inputs:
|
||||
name:
|
||||
description: 'Artifact name'
|
||||
required: false
|
||||
path:
|
||||
description: 'Destination path'
|
||||
required: false
|
||||
github-token:
|
||||
description: 'The GitHub token used to authenticate with the GitHub API.
|
||||
This is required when downloading artifacts from a different repository or from a different workflow run.
|
||||
If this is not specified, the action will attempt to download artifacts from the current repository and the current workflow run.'
|
||||
required: false
|
||||
repository:
|
||||
description: 'The repository owner and the repository name joined together by "/".
|
||||
If github-token is specified, this is the repository that artifacts will be downloaded from.'
|
||||
required: false
|
||||
default: ${{ github.repository }}
|
||||
run-id:
|
||||
description: 'The id of the workflow run where the desired download artifact was uploaded from.
|
||||
If github-token is specified, this is the run that artifacts will be downloaded from.'
|
||||
required: false
|
||||
default: ${{ github.run_id }}
|
||||
outputs:
|
||||
download-path:
|
||||
description: 'Path of artifact download'
|
||||
runs:
|
||||
using: 'node20'
|
||||
main: 'dist/index.js'
|
||||
using: 'node12'
|
||||
main: 'dist/index.js'
|
||||
110429
dist/index.js
vendored
110429
dist/index.js
vendored
File diff suppressed because one or more lines are too long
3962
package-lock.json
generated
3962
package-lock.json
generated
File diff suppressed because it is too large
Load Diff
11
package.json
11
package.json
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "download-artifact",
|
||||
"version": "3.0.0",
|
||||
"version": "2.0.0",
|
||||
"description": "Download a build artifact that was previously uploaded in the workflow by the upload-artifact action",
|
||||
"main": "dist/index.js",
|
||||
"scripts": {
|
||||
@@ -28,14 +28,13 @@
|
||||
},
|
||||
"homepage": "https://github.com/actions/download-artifact#readme",
|
||||
"dependencies": {
|
||||
"@actions/artifact": "^2.0.0",
|
||||
"@actions/core": "^1.10.0",
|
||||
"@actions/github": "^5.1.1"
|
||||
"@actions/artifact": "^0.6.0",
|
||||
"@actions/core": "^1.10.0"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@types/node": "^12.12.6",
|
||||
"@typescript-eslint/eslint-plugin": "^5.40.1",
|
||||
"@vercel/ncc": "^0.33.4",
|
||||
"@typescript-eslint/parser": "^2.30.0",
|
||||
"@zeit/ncc": "^0.22.1",
|
||||
"concurrently": "^5.2.0",
|
||||
"eslint": "^7.4.0",
|
||||
"eslint-plugin-github": "^4.1.1",
|
||||
|
||||
@@ -1,11 +1,7 @@
|
||||
export enum Inputs {
|
||||
Name = 'name',
|
||||
Path = 'path',
|
||||
GitHubToken = 'github-token',
|
||||
Repository = 'repository',
|
||||
RunID = 'run-id'
|
||||
Path = 'path'
|
||||
}
|
||||
|
||||
export enum Outputs {
|
||||
DownloadPath = 'download-path'
|
||||
}
|
||||
|
||||
@@ -1,115 +1,61 @@
|
||||
import * as os from 'os'
|
||||
import * as path from 'path'
|
||||
import * as core from '@actions/core'
|
||||
import artifactClient from '@actions/artifact'
|
||||
import type {Artifact, FindOptions} from '@actions/artifact'
|
||||
import * as artifact from '@actions/artifact'
|
||||
import * as os from 'os'
|
||||
import {resolve} from 'path'
|
||||
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> {
|
||||
const inputs = {
|
||||
name: core.getInput(Inputs.Name, {required: false}),
|
||||
path: core.getInput(Inputs.Path, {required: false}),
|
||||
token: core.getInput(Inputs.GitHubToken, {required: false}),
|
||||
repository: core.getInput(Inputs.Repository, {required: false}),
|
||||
runID: parseInt(core.getInput(Inputs.RunID, {required: false}))
|
||||
}
|
||||
try {
|
||||
const name = core.getInput(Inputs.Name, {required: false})
|
||||
const path = core.getInput(Inputs.Path, {required: false})
|
||||
|
||||
if (!inputs.path) {
|
||||
inputs.path = process.env['GITHUB_WORKSPACE'] || process.cwd()
|
||||
}
|
||||
let resolvedPath
|
||||
// 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)
|
||||
}
|
||||
core.debug(`Resolved path is ${resolvedPath}`)
|
||||
|
||||
if (inputs.path.startsWith(`~`)) {
|
||||
inputs.path = inputs.path.replace('~', os.homedir())
|
||||
}
|
||||
|
||||
const isSingleArtifactDownload = !!inputs.name
|
||||
const resolvedPath = path.resolve(inputs.path)
|
||||
core.debug(`Resolved path is ${resolvedPath}`)
|
||||
|
||||
const options: FindOptions = {}
|
||||
if (inputs.token) {
|
||||
const [repositoryOwner, repositoryName] = inputs.repository.split('/')
|
||||
if (!repositoryOwner || !repositoryName) {
|
||||
throw new Error(
|
||||
`Invalid repository: '${inputs.repository}'. Must be in format owner/repo`
|
||||
const artifactClient = artifact.create()
|
||||
if (!name) {
|
||||
// download all artifacts
|
||||
core.info('No artifact name specified, downloading all artifacts')
|
||||
core.info(
|
||||
'Creating an extra directory for each artifact that is being downloaded'
|
||||
)
|
||||
const downloadResponse = await artifactClient.downloadAllArtifacts(
|
||||
resolvedPath
|
||||
)
|
||||
core.info(`There were ${downloadResponse.length} artifacts downloaded`)
|
||||
for (const artifact of downloadResponse) {
|
||||
core.info(
|
||||
`Artifact ${artifact.artifactName} was downloaded to ${artifact.downloadPath}`
|
||||
)
|
||||
}
|
||||
} else {
|
||||
// download a single artifact
|
||||
core.info(`Starting download for ${name}`)
|
||||
const downloadOptions = {
|
||||
createArtifactFolder: false
|
||||
}
|
||||
const downloadResponse = await artifactClient.downloadArtifact(
|
||||
name,
|
||||
resolvedPath,
|
||||
downloadOptions
|
||||
)
|
||||
core.info(
|
||||
`Artifact ${downloadResponse.artifactName} was downloaded to ${downloadResponse.downloadPath}`
|
||||
)
|
||||
}
|
||||
|
||||
options.findBy = {
|
||||
token: inputs.token,
|
||||
workflowRunId: inputs.runID,
|
||||
repositoryName,
|
||||
repositoryOwner
|
||||
}
|
||||
// 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.setOutput(Outputs.DownloadPath, resolvedPath)
|
||||
core.info('Artifact download has finished successfully')
|
||||
} catch (err) {
|
||||
core.setFailed(err.message)
|
||||
}
|
||||
|
||||
let artifacts: Artifact[] = []
|
||||
|
||||
if (isSingleArtifactDownload) {
|
||||
core.info(`Downloading single artifact`)
|
||||
|
||||
const {artifact: targetArtifact} = await artifactClient.getArtifact(
|
||||
inputs.name,
|
||||
options
|
||||
)
|
||||
|
||||
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 {
|
||||
core.info(
|
||||
`No input name specified, downloading all artifacts. Extra directory with the artifact name will be created for each download`
|
||||
)
|
||||
|
||||
const listArtifactResponse = await artifactClient.listArtifacts({
|
||||
latest: true,
|
||||
...options
|
||||
})
|
||||
|
||||
if (listArtifactResponse.artifacts.length === 0) {
|
||||
throw new Error(
|
||||
`No artifacts found for run '${inputs.runID}' in '${inputs.repository}'`
|
||||
)
|
||||
}
|
||||
|
||||
core.debug(`Found ${listArtifactResponse.artifacts.length} artifacts`)
|
||||
artifacts = listArtifactResponse.artifacts
|
||||
}
|
||||
|
||||
const downloadPromises = artifacts.map(artifact =>
|
||||
artifactClient.downloadArtifact(artifact.id, {
|
||||
...options,
|
||||
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.info('Download artifact has finished successfully')
|
||||
}
|
||||
|
||||
run().catch(err =>
|
||||
core.setFailed(`Unable to download artifact(s): ${err.message}`)
|
||||
)
|
||||
run()
|
||||
|
||||
Reference in New Issue
Block a user