Compare commits
7 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| f8ed3d69aa | |||
| b964159d66 | |||
| 60ddbdae44 | |||
| ac9370a921 | |||
| 679c362502 | |||
| df4bb2b47c | |||
| 484a0b528f |
@@ -1,49 +0,0 @@
|
||||
# `dist/index.js` is a special file in Actions.
|
||||
# When you reference an action with `uses:` in a workflow,
|
||||
# `index.js` is the code that will run.
|
||||
# For our project, we generate this file through a build process
|
||||
# from other source files.
|
||||
# We need to make sure the checked-in `index.js` actually matches what we expect it to be.
|
||||
name: Check dist/
|
||||
|
||||
on:
|
||||
push:
|
||||
branches:
|
||||
- main
|
||||
pull_request:
|
||||
workflow_dispatch:
|
||||
|
||||
jobs:
|
||||
check-dist:
|
||||
runs-on: ubuntu-latest
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
|
||||
- name: Setup Node 24
|
||||
uses: actions/setup-node@v4
|
||||
with:
|
||||
node-version: 24.x
|
||||
cache: 'npm'
|
||||
|
||||
- name: Install dependencies
|
||||
run: npm ci
|
||||
|
||||
- name: Rebuild the dist/ directory
|
||||
run: npm run build
|
||||
|
||||
- name: Compare the expected and actual dist/ directories
|
||||
run: |
|
||||
if [ "$(git diff --ignore-space-at-eol dist/ | wc -l)" -gt "0" ]; then
|
||||
echo "Detected uncommitted changes after build. See status below:"
|
||||
git diff
|
||||
exit 1
|
||||
fi
|
||||
id: diff
|
||||
|
||||
# If index.js was different than expected, upload the expected version as an artifact
|
||||
- uses: actions/upload-artifact@v4
|
||||
if: ${{ failure() && steps.diff.conclusion == 'failure' }}
|
||||
with:
|
||||
name: dist
|
||||
path: dist/
|
||||
@@ -1,49 +0,0 @@
|
||||
name: "Code scanning - action"
|
||||
|
||||
on:
|
||||
push:
|
||||
branches-ignore: "dependabot/**"
|
||||
pull_request:
|
||||
paths-ignore:
|
||||
- '**.md'
|
||||
schedule:
|
||||
- cron: '0 11 * * 5'
|
||||
|
||||
jobs:
|
||||
CodeQL-Build:
|
||||
|
||||
strategy:
|
||||
fail-fast: false
|
||||
|
||||
# CodeQL runs on ubuntu-latest and windows-latest
|
||||
runs-on: ubuntu-latest
|
||||
|
||||
steps:
|
||||
- name: Checkout repository
|
||||
uses: actions/checkout@v4
|
||||
|
||||
# Initializes the CodeQL tools for scanning.
|
||||
- name: Initialize CodeQL
|
||||
uses: github/codeql-action/init@v2
|
||||
# Override language selection by uncommenting this and choosing your languages
|
||||
# with:
|
||||
# languages: go, javascript, csharp, python, cpp, java
|
||||
|
||||
# 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
|
||||
|
||||
# ℹ️ Command-line programs to run using the OS shell.
|
||||
# 📚 https://git.io/JvXDl
|
||||
|
||||
# ✏️ If the Autobuild fails above, remove it and uncomment the following three lines
|
||||
# and modify them (or add more) to build your code if your project
|
||||
# uses a compiled language
|
||||
|
||||
#- run: |
|
||||
# make bootstrap
|
||||
# make release
|
||||
|
||||
- name: Perform CodeQL Analysis
|
||||
uses: github/codeql-action/analyze@v2
|
||||
@@ -1,24 +0,0 @@
|
||||
name: Licensed
|
||||
|
||||
on:
|
||||
push:
|
||||
branches:
|
||||
- main
|
||||
pull_request:
|
||||
branches:
|
||||
- main
|
||||
|
||||
jobs:
|
||||
test:
|
||||
runs-on: ubuntu-latest
|
||||
name: Check licenses
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
- run: npm ci
|
||||
- name: Install licensed
|
||||
run: |
|
||||
cd $RUNNER_TEMP
|
||||
curl -Lfs -o licensed.tar.gz https://github.com/github/licensed/releases/download/2.12.2/licensed-2.12.2-linux-x64.tar.gz
|
||||
sudo tar -xzf licensed.tar.gz
|
||||
sudo mv licensed /usr/local/bin/licensed
|
||||
- run: licensed status
|
||||
@@ -1,20 +0,0 @@
|
||||
name: 'Publish Immutable Action Version'
|
||||
|
||||
on:
|
||||
release:
|
||||
types: [published]
|
||||
|
||||
jobs:
|
||||
publish:
|
||||
runs-on: ubuntu-latest
|
||||
permissions:
|
||||
contents: read
|
||||
id-token: write
|
||||
packages: write
|
||||
|
||||
steps:
|
||||
- name: Checking out
|
||||
uses: actions/checkout@v4
|
||||
- name: Publish
|
||||
id: publish
|
||||
uses: actions/publish-immutable-action@0.0.3
|
||||
@@ -1,27 +0,0 @@
|
||||
name: Release new action version
|
||||
on:
|
||||
release:
|
||||
types: [released]
|
||||
workflow_dispatch:
|
||||
inputs:
|
||||
TAG_NAME:
|
||||
description: 'Tag name that the major tag will point to'
|
||||
required: true
|
||||
|
||||
env:
|
||||
TAG_NAME: ${{ github.event.inputs.TAG_NAME || github.event.release.tag_name }}
|
||||
permissions:
|
||||
contents: write
|
||||
|
||||
jobs:
|
||||
update_tag:
|
||||
name: Update the major tag to include the ${{ github.event.inputs.TAG_NAME || github.event.release.tag_name }} changes
|
||||
environment:
|
||||
name: releaseNewActionVersion
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: Update the ${{ env.TAG_NAME }} tag
|
||||
uses: actions/publish-action@v0.3.0
|
||||
with:
|
||||
source-tag: ${{ env.TAG_NAME }}
|
||||
slack-webhook: ${{ secrets.SLACK_WEBHOOK }}
|
||||
@@ -1,322 +0,0 @@
|
||||
name: Test
|
||||
on:
|
||||
push:
|
||||
paths-ignore:
|
||||
- '**.md'
|
||||
pull_request:
|
||||
paths-ignore:
|
||||
- '**.md'
|
||||
|
||||
jobs:
|
||||
build:
|
||||
name: Build
|
||||
|
||||
strategy:
|
||||
matrix:
|
||||
runs-on: [ubuntu-latest, macos-latest, windows-latest]
|
||||
fail-fast: false
|
||||
|
||||
runs-on: ${{ matrix.runs-on }}
|
||||
|
||||
steps:
|
||||
- name: Checkout
|
||||
uses: actions/checkout@v4
|
||||
|
||||
- name: Setup Node 24
|
||||
uses: actions/setup-node@v4
|
||||
with:
|
||||
node-version: 24.x
|
||||
cache: 'npm'
|
||||
|
||||
- name: npm install
|
||||
run: npm install
|
||||
|
||||
- name: Compile
|
||||
run: npm run build
|
||||
|
||||
- name: Lint
|
||||
run: npm run lint
|
||||
|
||||
- name: Format
|
||||
run: npm run format-check
|
||||
|
||||
- name: Run Unit Tests
|
||||
run: npm test
|
||||
|
||||
- name: Create artifacts
|
||||
run: |
|
||||
mkdir -p path/to/artifact-A
|
||||
mkdir -p path/to/artifact-B
|
||||
echo "Lorem ipsum dolor sit amet" > path/to/artifact-A/file-A.txt
|
||||
echo "Hello world from file B" > path/to/artifact-B/file-B.txt
|
||||
|
||||
- name: Upload artifact A
|
||||
uses: actions/upload-artifact@v4
|
||||
with:
|
||||
name: Artifact-A-${{ matrix.runs-on }}
|
||||
path: path/to/artifact-A
|
||||
|
||||
- name: Upload artifact B
|
||||
uses: actions/upload-artifact@v4
|
||||
with:
|
||||
name: Artifact-B-${{ matrix.runs-on }}
|
||||
path: path/to/artifact-B
|
||||
|
||||
# Test downloading a single artifact
|
||||
- name: Download artifact A (absolute path)
|
||||
uses: ./
|
||||
with:
|
||||
name: Artifact-A-${{ matrix.runs-on }}
|
||||
path: some/new/path
|
||||
|
||||
# Test downloading an artifact using tilde expansion
|
||||
- name: Download artifact A (tilde expansion)
|
||||
uses: ./
|
||||
with:
|
||||
name: Artifact-A-${{ matrix.runs-on }}
|
||||
path: ~/some/path/with/a/tilde
|
||||
|
||||
- name: Verify successful download
|
||||
run: |
|
||||
$file1 = "some/new/path/file-A.txt"
|
||||
$file2 = "~/some/path/with/a/tilde/file-A.txt"
|
||||
if(!(Test-Path -path $file1) -or !(Test-Path -path $file2))
|
||||
{
|
||||
Write-Error "Expected files do not exist"
|
||||
}
|
||||
if(!((Get-Content $file1) -ceq "Lorem ipsum dolor sit amet") -or !((Get-Content $file2) -ceq "Lorem ipsum dolor sit amet"))
|
||||
{
|
||||
Write-Error "File contents of downloaded artifacts are incorrect"
|
||||
}
|
||||
shell: pwsh
|
||||
|
||||
# Test downloading both artifacts at once
|
||||
- name: Download all Artifacts
|
||||
uses: ./
|
||||
with:
|
||||
path: some/other/path
|
||||
|
||||
- name: Verify successful download
|
||||
run: |
|
||||
$fileA = "some/other/path/Artifact-A-${{ matrix.runs-on }}/file-A.txt"
|
||||
$fileB = "some/other/path/Artifact-B-${{ matrix.runs-on }}/file-B.txt"
|
||||
if(!(Test-Path -path $fileA) -or !(Test-Path -path $fileB))
|
||||
{
|
||||
Write-Error "Expected files do not exist"
|
||||
}
|
||||
if(!((Get-Content $fileA) -ceq "Lorem ipsum dolor sit amet") -or !((Get-Content $fileB) -ceq "Hello world from file B"))
|
||||
{
|
||||
Write-Error "File contents of downloaded artifacts are incorrect"
|
||||
}
|
||||
shell: pwsh
|
||||
|
||||
# Test glob downloading both artifacts to same directory
|
||||
- name: Download all Artifacts
|
||||
uses: ./
|
||||
with:
|
||||
pattern: Artifact-*
|
||||
path: single/directory
|
||||
merge-multiple: true
|
||||
|
||||
- name: Verify successful download
|
||||
run: |
|
||||
$fileA = "single/directory/file-A.txt"
|
||||
$fileB = "single/directory/file-B.txt"
|
||||
if(!(Test-Path -path $fileA) -or !(Test-Path -path $fileB))
|
||||
{
|
||||
Write-Error "Expected files do not exist"
|
||||
}
|
||||
if(!((Get-Content $fileA) -ceq "Lorem ipsum dolor sit amet") -or !((Get-Content $fileB) -ceq "Hello world from file B"))
|
||||
{
|
||||
Write-Error "File contents of downloaded artifacts are incorrect"
|
||||
}
|
||||
shell: pwsh
|
||||
|
||||
# Test downloading artifact without decompressing (skip-decompress)
|
||||
- name: Download artifact A without decompressing
|
||||
uses: ./
|
||||
with:
|
||||
name: Artifact-A-${{ matrix.runs-on }}
|
||||
path: skip-decompress-test
|
||||
skip-decompress: true
|
||||
|
||||
- name: Verify skip-decompress download
|
||||
run: |
|
||||
$rawFile = "skip-decompress-test/Artifact-A-${{ matrix.runs-on }}.zip"
|
||||
if(!(Test-Path -path $rawFile))
|
||||
{
|
||||
Write-Error "Expected raw artifact file does not exist at $rawFile"
|
||||
}
|
||||
$fileInfo = Get-Item $rawFile
|
||||
if($fileInfo.Length -eq 0)
|
||||
{
|
||||
Write-Error "Downloaded artifact file is empty"
|
||||
}
|
||||
Write-Host "Successfully downloaded artifact without decompressing: $rawFile (size: $($fileInfo.Length) bytes)"
|
||||
shell: pwsh
|
||||
|
||||
# Regression test for artifact filename vs content-type mismatch
|
||||
# When an archived artifact has a name with a file extension that doesn't
|
||||
# match the blob type (e.g. "report.txt" but blob is zip), the server
|
||||
# should append .zip to the content-disposition filename.
|
||||
- name: Create and upload archived artifact with misleading extension
|
||||
shell: bash
|
||||
run: |
|
||||
mkdir -p path/to/extension-test
|
||||
echo '{"key": "value"}' > path/to/extension-test/data.json
|
||||
- uses: actions/upload-artifact@v4 # V4 is important here to ensure we're supporting older versions correctly
|
||||
with:
|
||||
name: report.txt-${{ matrix.runs-on }}.json
|
||||
path: path/to/extension-test/data.json
|
||||
|
||||
- name: Download misleading-extension artifact without decompressing
|
||||
uses: ./
|
||||
with:
|
||||
name: report.txt-${{ matrix.runs-on }}.json
|
||||
path: ext-test/raw
|
||||
skip-decompress: true
|
||||
|
||||
- name: Verify downloaded file has .zip extension appended
|
||||
shell: bash
|
||||
run: |
|
||||
expected="ext-test/raw/report.txt-${{ matrix.runs-on }}.json.zip"
|
||||
if [ -f "$expected" ]; then
|
||||
echo "PASS: Downloaded file has .zip appended: $expected"
|
||||
else
|
||||
echo "FAIL: Expected $expected but got:"
|
||||
ls -al ext-test/raw/
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# Test uploading and downloading artifacts with CJK (Chinese, Japanese, Korean) characters
|
||||
# Regression test: certain non-ASCII chars (e.g. U+571F 土) caused 400 errors from
|
||||
# Azure Blob Storage due to encoding issues in the Content-Disposition / rscd parameter
|
||||
- name: Create artifacts with CJK names
|
||||
shell: bash
|
||||
run: |
|
||||
mkdir -p path/to/cjk-artifacts
|
||||
# Chinese - 土 (U+571F) known to fail, 日 (U+65E5) known to work
|
||||
echo "Content for 土" > "path/to/cjk-artifacts/file-土-${{ matrix.runs-on }}.txt"
|
||||
echo "Content for 中文测试" > "path/to/cjk-artifacts/file-中文测试-${{ matrix.runs-on }}.txt"
|
||||
# Japanese - katakana and kanji
|
||||
echo "Content for テスト" > "path/to/cjk-artifacts/file-テスト-${{ matrix.runs-on }}.txt"
|
||||
echo "Content for 東京タワー" > "path/to/cjk-artifacts/file-東京タワー-${{ matrix.runs-on }}.txt"
|
||||
# Korean - Hangul
|
||||
echo "Content for 테스트" > "path/to/cjk-artifacts/file-테스트-${{ matrix.runs-on }}.txt"
|
||||
echo "Content for 서울시" > "path/to/cjk-artifacts/file-서울시-${{ matrix.runs-on }}.txt"
|
||||
|
||||
- name: Upload CJK artifact - Chinese 土
|
||||
uses: actions/upload-artifact@v7
|
||||
with:
|
||||
path: path/to/cjk-artifacts/file-土-${{ matrix.runs-on }}.txt
|
||||
archive: false
|
||||
|
||||
- name: Upload CJK artifact - Chinese 中文测试
|
||||
uses: actions/upload-artifact@v7
|
||||
with:
|
||||
path: path/to/cjk-artifacts/file-中文测试-${{ matrix.runs-on }}.txt
|
||||
archive: false
|
||||
|
||||
- name: Upload CJK artifact - Japanese テスト
|
||||
uses: actions/upload-artifact@v7
|
||||
with:
|
||||
path: path/to/cjk-artifacts/file-テスト-${{ matrix.runs-on }}.txt
|
||||
archive: false
|
||||
|
||||
- name: Upload CJK artifact - Japanese 東京タワー
|
||||
uses: actions/upload-artifact@v7
|
||||
with:
|
||||
path: path/to/cjk-artifacts/file-東京タワー-${{ matrix.runs-on }}.txt
|
||||
archive: false
|
||||
|
||||
- name: Upload CJK artifact - Korean 테스트
|
||||
uses: actions/upload-artifact@v7
|
||||
with:
|
||||
path: path/to/cjk-artifacts/file-테스트-${{ matrix.runs-on }}.txt
|
||||
archive: false
|
||||
|
||||
- name: Upload CJK artifact - Korean 서울시
|
||||
uses: actions/upload-artifact@v7
|
||||
with:
|
||||
path: path/to/cjk-artifacts/file-서울시-${{ matrix.runs-on }}.txt
|
||||
archive: false
|
||||
|
||||
- name: Download CJK artifact - Chinese 土
|
||||
uses: ./
|
||||
with:
|
||||
name: file-土-${{ matrix.runs-on }}.txt
|
||||
path: cjk-download/土
|
||||
|
||||
- name: Download CJK artifact - Chinese 中文测试
|
||||
uses: ./
|
||||
with:
|
||||
name: file-中文测试-${{ matrix.runs-on }}.txt
|
||||
path: cjk-download/中文测试
|
||||
|
||||
- name: Download CJK artifact - Japanese テスト
|
||||
uses: ./
|
||||
with:
|
||||
name: file-テスト-${{ matrix.runs-on }}.txt
|
||||
path: cjk-download/テスト
|
||||
|
||||
- name: Download CJK artifact - Japanese 東京タワー
|
||||
uses: ./
|
||||
with:
|
||||
name: file-東京タワー-${{ matrix.runs-on }}.txt
|
||||
path: cjk-download/東京タワー
|
||||
|
||||
- name: Download CJK artifact - Korean 테스트
|
||||
uses: ./
|
||||
with:
|
||||
name: file-테스트-${{ matrix.runs-on }}.txt
|
||||
path: cjk-download/테스트
|
||||
|
||||
- name: Download CJK artifact - Korean 서울시
|
||||
uses: ./
|
||||
with:
|
||||
name: file-서울시-${{ matrix.runs-on }}.txt
|
||||
path: cjk-download/서울시
|
||||
|
||||
- name: Verify CJK artifact downloads
|
||||
shell: bash
|
||||
run: |
|
||||
set -e
|
||||
fail=0
|
||||
|
||||
check_file() {
|
||||
local file="$1"
|
||||
local expected="$2"
|
||||
if [ ! -f "$file" ]; then
|
||||
echo "FAIL: Missing file: $file"
|
||||
fail=1
|
||||
return
|
||||
fi
|
||||
actual=$(cat "$file")
|
||||
if [ "$actual" != "$expected" ]; then
|
||||
echo "FAIL: Content mismatch in $file"
|
||||
echo " Expected: '$expected'"
|
||||
echo " Got: '$actual'"
|
||||
fail=1
|
||||
return
|
||||
fi
|
||||
echo "PASS: $file"
|
||||
}
|
||||
|
||||
echo "=== Chinese ==="
|
||||
check_file "cjk-download/土/file-土-${{ matrix.runs-on }}.txt" "Content for 土"
|
||||
check_file "cjk-download/中文测试/file-中文测试-${{ matrix.runs-on }}.txt" "Content for 中文测试"
|
||||
|
||||
echo "=== Japanese ==="
|
||||
check_file "cjk-download/テスト/file-テスト-${{ matrix.runs-on }}.txt" "Content for テスト"
|
||||
check_file "cjk-download/東京タワー/file-東京タワー-${{ matrix.runs-on }}.txt" "Content for 東京タワー"
|
||||
|
||||
echo "=== Korean ==="
|
||||
check_file "cjk-download/테스트/file-테스트-${{ matrix.runs-on }}.txt" "Content for 테스트"
|
||||
check_file "cjk-download/서울시/file-서울시-${{ matrix.runs-on }}.txt" "Content for 서울시"
|
||||
|
||||
if [ "$fail" -ne 0 ]; then
|
||||
echo "Some CJK artifact checks failed"
|
||||
ls -alR cjk-download/ || true
|
||||
exit 1
|
||||
fi
|
||||
echo "All CJK artifact downloads verified successfully"
|
||||
@@ -4,87 +4,23 @@ Download [Actions Artifacts](https://docs.github.com/en/actions/using-workflows/
|
||||
|
||||
See also [upload-artifact](https://github.com/actions/upload-artifact).
|
||||
|
||||
- [`@actions/download-artifact`](#actionsdownload-artifact)
|
||||
- [v7 - What's new](#v7---whats-new)
|
||||
- [v5 - What's new](#v5---whats-new)
|
||||
- [v4 - What's new](#v4---whats-new)
|
||||
- [Improvements](#improvements)
|
||||
- [Breaking Changes](#breaking-changes)
|
||||
- [Note](#note)
|
||||
- [Usage](#usage)
|
||||
- [Inputs](#inputs)
|
||||
- [Outputs](#outputs)
|
||||
- [Examples](#examples)
|
||||
- [Download Single Artifact](#download-single-artifact)
|
||||
- [Download Artifacts by ID](#download-artifacts-by-id)
|
||||
- [Download All Artifacts](#download-all-artifacts)
|
||||
- [Download multiple (filtered) Artifacts to the same directory](#download-multiple-filtered-artifacts-to-the-same-directory)
|
||||
- [Download Artifacts from other Workflow Runs or Repositories](#download-artifacts-from-other-workflow-runs-or-repositories)
|
||||
- [Limitations](#limitations)
|
||||
- [Permission Loss](#permission-loss)
|
||||
- [What's new](#whats-new)
|
||||
- [Note](#note)
|
||||
- [GHES Support](#ghes-support)
|
||||
- [Usage](#usage)
|
||||
- [Inputs](#inputs)
|
||||
- [Outputs](#outputs)
|
||||
- [Examples](#examples)
|
||||
- [Download Single Artifact](#download-single-artifact)
|
||||
- [Download Artifacts by ID](#download-artifacts-by-id)
|
||||
- [Download All Artifacts](#download-all-artifacts)
|
||||
- [Download multiple (filtered) Artifacts to the same directory](#download-multiple-filtered-artifacts-to-the-same-directory)
|
||||
- [Download Artifacts from other Workflow Runs or Repositories](#download-artifacts-from-other-workflow-runs-or-repositories)
|
||||
- [Maintaining File Permissions](#maintaining-file-permissions)
|
||||
|
||||
## v8 - What's new
|
||||
## What's new
|
||||
|
||||
> [!IMPORTANT]
|
||||
> actions/download-artifact@v8 has been migrated to an ESM module. This should be transparent to the caller but forks might need to make significant changes.
|
||||
|
||||
> [!IMPORTANT]
|
||||
> Hash mismatches will now error by default. Users can override this behavior with a setting change (see below).
|
||||
|
||||
- Downloads will check the content-type returned to determine if a file can be decompressed and skip the decompression stage if so. This removes previous failures where we were trying to decompress a non-zip file. Since this is making a big change to the default behavior, we're making it opt-in via a version bump.
|
||||
- Users can also download a zip file without decompressing it with the new `skip-decompress` flag.
|
||||
|
||||
- Introduces a new parameter `digest-mismatch` that allows callers to specify what to do when the downloaded hash doesn't match the expected hash (`ignore`, `info`, `warn`, `error`). To ensure security by default, the default value is `error`.
|
||||
|
||||
- Chore: we've bumped versions on a lot of our dev packages to get them up to date with the latest bugfixes/security patches.
|
||||
|
||||
### v8.0.1
|
||||
|
||||
- Support for CJK (Chinese/Japanese/Korean) characters in the file name.
|
||||
|
||||
## v7 - What's new
|
||||
|
||||
> [!IMPORTANT]
|
||||
> actions/download-artifact@v7 now runs on Node.js 24 (`runs.using: node24`) and requires a minimum Actions Runner version of 2.327.1. If you are using self-hosted runners, ensure they are updated before upgrading.
|
||||
|
||||
### Node.js 24
|
||||
|
||||
This release updates the runtime to Node.js 24. v6 had preliminary support for Node 24, however this action was by default still running on Node.js 20. Now this action by default will run on Node.js 24.
|
||||
|
||||
## v5 - What's new
|
||||
|
||||
Previously, **single artifact downloads** behaved differently depending on how you specified the artifact:
|
||||
|
||||
- **By name**: `name: my-artifact` → extracted to `path/` (direct)
|
||||
- **By ID**: `artifact-ids: 12345` → extracted to `path/my-artifact/` (nested)
|
||||
|
||||
Now both methods are consistent:
|
||||
|
||||
- **By name**: `name: my-artifact` → extracted to `path/` (unchanged)
|
||||
- **By ID**: `artifact-ids: 12345` → extracted to `path/` (updated - now direct)
|
||||
|
||||
Note: This change also applies to patterns that only match a single artifact.
|
||||
|
||||
## v4 - What's new
|
||||
|
||||
> [!IMPORTANT]
|
||||
> download-artifact@v4+ is not currently supported on GitHub Enterprise Server (GHES) yet. If you are on GHES, you must use [v3](https://github.com/actions/download-artifact/releases/tag/v3) (Node 16) or [v3-node20](https://github.com/actions/download-artifact/releases/tag/v3-node20) (Node 20).
|
||||
|
||||
The release of upload-artifact@v4 and download-artifact@v4 are major changes to the backend architecture of Artifacts. They have numerous performance and behavioral improvements.
|
||||
|
||||
For more information, see the [`@actions/artifact`](https://github.com/actions/toolkit/tree/main/packages/artifact) documentation.
|
||||
|
||||
### Improvements
|
||||
|
||||
1. Downloads are significantly faster, upwards of 90% improvement in worst case scenarios.
|
||||
2. Artifacts can be downloaded from other workflow runs and repositories when supplied with a PAT.
|
||||
|
||||
### Breaking Changes
|
||||
|
||||
1. On self hosted runners, additional [firewall rules](https://github.com/actions/toolkit/tree/main/packages/artifact#breaking-changes) may be required.
|
||||
2. Downloading artifacts that were created from `action/upload-artifact@v3` and below are not supported.
|
||||
|
||||
For assistance with breaking changes, see [MIGRATION.md](docs/MIGRATION.md).
|
||||
Check out the [releases page](https://github.com/actions/download-artifact/releases) for details on what's new.
|
||||
|
||||
## Note
|
||||
|
||||
@@ -104,12 +40,16 @@ We will still provide security updates for this project and fix major breaking c
|
||||
|
||||
You are welcome to still raise bugs in this repo.
|
||||
|
||||
## GHES Support
|
||||
|
||||
`download-artifact@v4+` is not currently supported on GitHub Enterprise Server (GHES) yet. If you are on GHES, you must use [v3](https://github.com/actions/download-artifact/releases/tag/v3) (Node 16) or [v3-node20](https://github.com/actions/download-artifact/releases/tag/v3-node20) (Node 20).
|
||||
|
||||
## Usage
|
||||
|
||||
### Inputs
|
||||
|
||||
```yaml
|
||||
- uses: actions/download-artifact@v5
|
||||
- uses: actions/download-artifact@v8
|
||||
with:
|
||||
# Name of the artifact to download.
|
||||
# If unspecified, all artifacts for the run are downloaded.
|
||||
@@ -151,6 +91,17 @@ You are welcome to still raise bugs in this repo.
|
||||
# If github-token is specified, this is the run that artifacts will be downloaded from.
|
||||
# Optional. Default is ${{ github.run_id }}
|
||||
run-id:
|
||||
|
||||
# Whether to skip decompressing a zip file (if detected).
|
||||
# If true, the downloaded artifact will not be automatically extracted/decompressed.
|
||||
# This is useful when you want to handle the artifact as-is without extraction.
|
||||
# Optional. Default is `false`
|
||||
skip-decompress:
|
||||
|
||||
# What to do if the action detects a mismatch between the downloaded hash and the expected hash from the server.
|
||||
# Can be one of: `ignore`, `info`, `warn`, `error`
|
||||
# Optional. Default is `error`
|
||||
digest-mismatch:
|
||||
```
|
||||
|
||||
### Outputs
|
||||
@@ -167,7 +118,7 @@ Download to current working directory (`$GITHUB_WORKSPACE`):
|
||||
|
||||
```yaml
|
||||
steps:
|
||||
- uses: actions/download-artifact@v5
|
||||
- uses: actions/download-artifact@v8
|
||||
with:
|
||||
name: my-artifact
|
||||
- name: Display structure of downloaded files
|
||||
@@ -178,7 +129,7 @@ Download to a specific directory (also supports `~` expansion):
|
||||
|
||||
```yaml
|
||||
steps:
|
||||
- uses: actions/download-artifact@v5
|
||||
- uses: actions/download-artifact@v8
|
||||
with:
|
||||
name: my-artifact
|
||||
path: your/destination/dir
|
||||
@@ -186,15 +137,24 @@ steps:
|
||||
run: ls -R your/destination/dir
|
||||
```
|
||||
|
||||
Directly download a non-zipped file (only supports files uploaded with `actions/upload-artifact@v7` and `archive: false` set):
|
||||
|
||||
```yaml
|
||||
steps:
|
||||
- uses: actions/download-artifact@v8
|
||||
with:
|
||||
name: my-artifact.json # corresponds to the uploaded file name
|
||||
```
|
||||
|
||||
### Download Artifacts by ID
|
||||
|
||||
The `artifact-ids` input allows downloading artifacts using their unique ID rather than name. This is particularly useful when working with immutable artifacts from `actions/upload-artifact@v4` which assigns a unique ID to each artifact.
|
||||
The `artifact-ids` input allows downloading artifacts using their unique ID rather than name. This is particularly useful when working with immutable artifacts from `actions/upload-artifact@v4+` which assigns a unique ID to each artifact.
|
||||
|
||||
Download a single artifact by ID to the current working directory (`$GITHUB_WORKSPACE`):
|
||||
|
||||
```yaml
|
||||
steps:
|
||||
- uses: actions/download-artifact@v5
|
||||
- uses: actions/download-artifact@v8
|
||||
with:
|
||||
artifact-ids: 12345
|
||||
- name: Display structure of downloaded files
|
||||
@@ -205,7 +165,7 @@ Download a single artifact by ID to a specific directory:
|
||||
|
||||
```yaml
|
||||
steps:
|
||||
- uses: actions/download-artifact@v5
|
||||
- uses: actions/download-artifact@v8
|
||||
with:
|
||||
artifact-ids: 12345
|
||||
path: your/destination/dir
|
||||
@@ -219,7 +179,7 @@ Multiple artifacts can be downloaded by providing a comma-separated list of IDs:
|
||||
|
||||
```yaml
|
||||
steps:
|
||||
- uses: actions/download-artifact@v5
|
||||
- uses: actions/download-artifact@v8
|
||||
with:
|
||||
artifact-ids: 12345,67890
|
||||
path: path/to/artifacts
|
||||
@@ -247,7 +207,7 @@ Download all artifacts to the current working directory:
|
||||
|
||||
```yaml
|
||||
steps:
|
||||
- uses: actions/download-artifact@v5
|
||||
- uses: actions/download-artifact@v8
|
||||
- name: Display structure of downloaded files
|
||||
run: ls -R
|
||||
```
|
||||
@@ -256,7 +216,7 @@ Download all artifacts to a specific directory:
|
||||
|
||||
```yaml
|
||||
steps:
|
||||
- uses: actions/download-artifact@v5
|
||||
- uses: actions/download-artifact@v8
|
||||
with:
|
||||
path: path/to/artifacts
|
||||
- name: Display structure of downloaded files
|
||||
@@ -267,7 +227,7 @@ To download them to the _same_ directory:
|
||||
|
||||
```yaml
|
||||
steps:
|
||||
- uses: actions/download-artifact@v5
|
||||
- uses: actions/download-artifact@v8
|
||||
with:
|
||||
path: path/to/artifacts
|
||||
merge-multiple: true
|
||||
@@ -298,7 +258,7 @@ jobs:
|
||||
- name: Create a File
|
||||
run: echo "hello from ${{ matrix.runs-on }}" > file-${{ matrix.runs-on }}.txt
|
||||
- name: Upload Artifact
|
||||
uses: actions/upload-artifact@v4
|
||||
uses: actions/upload-artifact@v7
|
||||
with:
|
||||
name: my-artifact-${{ matrix.runs-on }}
|
||||
path: file-${{ matrix.runs-on }}.txt
|
||||
@@ -307,7 +267,7 @@ jobs:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: Download All Artifacts
|
||||
uses: actions/download-artifact@v5
|
||||
uses: actions/download-artifact@v8
|
||||
with:
|
||||
path: my-artifact
|
||||
pattern: my-artifact-*
|
||||
@@ -330,7 +290,7 @@ It may be useful to download Artifacts from other workflow runs, or even other r
|
||||
|
||||
```yaml
|
||||
steps:
|
||||
- uses: actions/download-artifact@v5
|
||||
- uses: actions/download-artifact@v8
|
||||
with:
|
||||
name: my-other-artifact
|
||||
github-token: ${{ secrets.GH_PAT }} # token with actions:read permissions on target repo
|
||||
@@ -338,21 +298,30 @@ steps:
|
||||
run-id: 1234
|
||||
```
|
||||
|
||||
## Limitations
|
||||
### Maintaining File Permissions
|
||||
|
||||
### Permission Loss
|
||||
Zipping files will remove file permissions during artifact upload. All directories will have `755` and all files will have `644`. For example, if you make a file executable using `chmod` and then upload that file as a zip file, post-download the file is no longer guaranteed to be set as an executable.
|
||||
|
||||
File permissions are not maintained during artifact upload. All directories will have `755` and all files will have `644`. For example, if you make a file executable using `chmod` and then upload that file, post-download the file is no longer guaranteed to be set as an executable.
|
||||
|
||||
If you must preserve permissions, you can `tar` all of your files together before artifact upload. Post download, the `tar` file will maintain file permissions and case sensitivity.
|
||||
If you must preserve permissions, you can `tar` all of your files together before artifact upload and upload it as a single file (using V7+ of `actions/upload-artifact`). Then download the file directly and unpack it manually:
|
||||
|
||||
```yaml
|
||||
|
||||
- name: 'Tar files'
|
||||
run: tar -cvf my_files.tar /path/to/my/directory
|
||||
|
||||
- name: 'Upload Artifact'
|
||||
uses: actions/upload-artifact@v4
|
||||
uses: actions/upload-artifact@v7
|
||||
with:
|
||||
name: my-artifact
|
||||
path: my_files.tar
|
||||
```
|
||||
archive: false
|
||||
|
||||
----
|
||||
|
||||
# Later, download the file by name
|
||||
|
||||
- name: 'Download Artifact'
|
||||
uses: actions/download-artifact@v8
|
||||
with:
|
||||
name: my_files.tar
|
||||
|
||||
```
|
||||
Reference in New Issue
Block a user