diff --git a/.licenses/npm/@actions/artifact.dep.yml b/.licenses/npm/@actions/artifact.dep.yml index 5325bd1..63caece 100644 --- a/.licenses/npm/@actions/artifact.dep.yml +++ b/.licenses/npm/@actions/artifact.dep.yml @@ -1,6 +1,6 @@ --- name: "@actions/artifact" -version: 2.3.2 +version: 4.0.0 type: npm summary: Actions artifact lib homepage: https://github.com/actions/toolkit/tree/main/packages/artifact diff --git a/README.md b/README.md index ab6b701..50fac66 100644 --- a/README.md +++ b/README.md @@ -5,9 +5,11 @@ 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) + - [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) @@ -20,11 +22,24 @@ See also [upload-artifact](https://github.com/actions/upload-artifact). - [Limitations](#limitations) - [Permission Loss](#permission-loss) +## 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 GHES yet. If you are on GHES, you must use [v3](https://github.com/actions/download-artifact/releases/tag/v3). +> 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. @@ -65,7 +80,7 @@ You are welcome to still raise bugs in this repo. ### Inputs ```yaml -- uses: actions/download-artifact@v4 +- uses: actions/download-artifact@v5 with: # Name of the artifact to download. # If unspecified, all artifacts for the run are downloaded. @@ -89,6 +104,7 @@ You are welcome to still raise bugs in this repo. # When multiple artifacts are matched, this changes the behavior of the destination directories. # If true, the downloaded artifacts will be in the same directory specified by path. # If false, the downloaded artifacts will be extracted into individual named directories within the specified path. + # Note: When downloading a single artifact (by name or ID), it will always be extracted directly to the specified path. # Optional. Default is 'false' merge-multiple: @@ -122,7 +138,7 @@ Download to current working directory (`$GITHUB_WORKSPACE`): ```yaml steps: -- uses: actions/download-artifact@v4 +- uses: actions/download-artifact@v5 with: name: my-artifact - name: Display structure of downloaded files @@ -133,7 +149,7 @@ Download to a specific directory (also supports `~` expansion): ```yaml steps: -- uses: actions/download-artifact@v4 +- uses: actions/download-artifact@v5 with: name: my-artifact path: your/destination/dir @@ -145,20 +161,36 @@ steps: 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@v4 +- uses: actions/download-artifact@v5 with: artifact-ids: 12345 - name: Display structure of downloaded files run: ls -R ``` +Download a single artifact by ID to a specific directory: + +```yaml +steps: +- uses: actions/download-artifact@v5 + with: + artifact-ids: 12345 + path: your/destination/dir +- name: Display structure of downloaded files + run: ls -R your/destination/dir +``` + +When downloading a single artifact by ID, the behavior is identical to downloading by name - the artifact contents are extracted directly to the specified path without creating a subdirectory. + Multiple artifacts can be downloaded by providing a comma-separated list of IDs: ```yaml steps: -- uses: actions/download-artifact@v4 +- uses: actions/download-artifact@v5 with: artifact-ids: 12345,67890 path: path/to/artifacts @@ -166,7 +198,7 @@ steps: run: ls -R path/to/artifacts ``` -This will download multiple artifacts to separate directories (similar to downloading multiple artifacts by name). +When downloading multiple artifacts by ID, each artifact will be extracted into its own subdirectory named after the artifact (similar to downloading multiple artifacts by name). ### Download All Artifacts @@ -186,7 +218,7 @@ Download all artifacts to the current working directory: ```yaml steps: -- uses: actions/download-artifact@v4 +- uses: actions/download-artifact@v5 - name: Display structure of downloaded files run: ls -R ``` @@ -195,7 +227,7 @@ Download all artifacts to a specific directory: ```yaml steps: -- uses: actions/download-artifact@v4 +- uses: actions/download-artifact@v5 with: path: path/to/artifacts - name: Display structure of downloaded files @@ -206,7 +238,7 @@ To download them to the _same_ directory: ```yaml steps: -- uses: actions/download-artifact@v4 +- uses: actions/download-artifact@v5 with: path: path/to/artifacts merge-multiple: true @@ -246,7 +278,7 @@ jobs: runs-on: ubuntu-latest steps: - name: Download All Artifacts - uses: actions/download-artifact@v4 + uses: actions/download-artifact@v5 with: path: my-artifact pattern: my-artifact-* @@ -269,7 +301,7 @@ It may be useful to download Artifacts from other workflow runs, or even other r ```yaml steps: -- uses: actions/download-artifact@v4 +- uses: actions/download-artifact@v5 with: name: my-other-artifact github-token: ${{ secrets.GH_PAT }} # token with actions:read permissions on target repo diff --git a/__tests__/download.test.ts b/__tests__/download.test.ts index 032d857..0709fbe 100644 --- a/__tests__/download.test.ts +++ b/__tests__/download.test.ts @@ -1,4 +1,5 @@ import * as core from '@actions/core' +import * as path from 'path' import artifact, {ArtifactNotFoundError} from '@actions/artifact' import {run} from '../src/download-artifact' import {Inputs} from '../src/constants' @@ -371,4 +372,38 @@ describe('download', () => { "Inputs 'name' and 'artifact-ids' cannot be used together. Please specify only one." ) }) + + test('downloads single artifact by ID to same path as by name', async () => { + const mockArtifact = { + id: 456, + name: 'test-artifact', + size: 1024, + digest: 'def456' + } + + const testPath = '/test/path' + mockInputs({ + [Inputs.Name]: '', + [Inputs.Pattern]: '', + [Inputs.ArtifactIds]: '456', + [Inputs.Path]: testPath + }) + + jest.spyOn(artifact, 'listArtifacts').mockImplementation(() => + Promise.resolve({ + artifacts: [mockArtifact] + }) + ) + + await run() + + // Verify it downloads directly to the specified path (not nested in artifact name subdirectory) + expect(artifact.downloadArtifact).toHaveBeenCalledWith( + 456, + expect.objectContaining({ + path: path.resolve(testPath), // Should be the resolved path directly, not nested + expectedHash: mockArtifact.digest + }) + ) + }) }) diff --git a/dist/index.js b/dist/index.js index cee1d8d..a6977c4 100644 --- a/dist/index.js +++ b/dist/index.js @@ -75908,7 +75908,9 @@ function run() { } const downloadPromises = artifacts.map(artifact => ({ name: artifact.name, - promise: artifact_1.default.downloadArtifact(artifact.id, Object.assign(Object.assign({}, options), { path: isSingleArtifactDownload || inputs.mergeMultiple + promise: artifact_1.default.downloadArtifact(artifact.id, Object.assign(Object.assign({}, options), { path: isSingleArtifactDownload || + inputs.mergeMultiple || + artifacts.length === 1 ? resolvedPath : path.join(resolvedPath, artifact.name), expectedHash: artifact.digest })) })); diff --git a/package-lock.json b/package-lock.json index be8975e..c7af2e4 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,15 +1,15 @@ { "name": "download-artifact", - "version": "4.3.0", + "version": "6.0.0", "lockfileVersion": 3, "requires": true, "packages": { "": { "name": "download-artifact", - "version": "4.3.0", + "version": "6.0.0", "license": "MIT", "dependencies": { - "@actions/artifact": "5.0.0", + "@actions/artifact": "^5.0.0", "@actions/core": "^2.0.0", "@actions/github": "^6.0.1", "minimatch": "^9.0.3" diff --git a/package.json b/package.json index 967cc75..7c87fcb 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "download-artifact", - "version": "4.3.0", + "version": "6.0.0", "description": "Download an Actions Artifact from a workflow run", "engines": { "node": ">=24" @@ -32,7 +32,7 @@ }, "homepage": "https://github.com/actions/download-artifact#readme", "dependencies": { - "@actions/artifact": "5.0.0", + "@actions/artifact": "^5.0.0", "@actions/core": "^2.0.0", "@actions/github": "^6.0.1", "minimatch": "^9.0.3" diff --git a/src/download-artifact.ts b/src/download-artifact.ts index 5cc6b17..6f2d782 100644 --- a/src/download-artifact.ts +++ b/src/download-artifact.ts @@ -174,7 +174,9 @@ export async function run(): Promise { promise: artifactClient.downloadArtifact(artifact.id, { ...options, path: - isSingleArtifactDownload || inputs.mergeMultiple + isSingleArtifactDownload || + inputs.mergeMultiple || + artifacts.length === 1 ? resolvedPath : path.join(resolvedPath, artifact.name), expectedHash: artifact.digest