mirror of
https://github.com/actions/download-artifact.git
synced 2025-08-14 12:45:05 +00:00
Merge pull request #416 from actions/single-artifact-id-download-path
fix: inconsistent path behavior for single artifact downloads by ID
This commit is contained in:
commit
634f93cb29
20
README.md
20
README.md
@ -8,6 +8,7 @@ See also [upload-artifact](https://github.com/actions/upload-artifact).
|
|||||||
- [v4 - What's new](#v4---whats-new)
|
- [v4 - What's new](#v4---whats-new)
|
||||||
- [Improvements](#improvements)
|
- [Improvements](#improvements)
|
||||||
- [Breaking Changes](#breaking-changes)
|
- [Breaking Changes](#breaking-changes)
|
||||||
|
- [Note](#note)
|
||||||
- [Usage](#usage)
|
- [Usage](#usage)
|
||||||
- [Inputs](#inputs)
|
- [Inputs](#inputs)
|
||||||
- [Outputs](#outputs)
|
- [Outputs](#outputs)
|
||||||
@ -89,6 +90,7 @@ You are welcome to still raise bugs in this repo.
|
|||||||
# When multiple artifacts are matched, this changes the behavior of the destination directories.
|
# 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 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.
|
# 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'
|
# Optional. Default is 'false'
|
||||||
merge-multiple:
|
merge-multiple:
|
||||||
|
|
||||||
@ -145,6 +147,8 @@ 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.
|
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
|
```yaml
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/download-artifact@v4
|
- uses: actions/download-artifact@v4
|
||||||
@ -154,6 +158,20 @@ steps:
|
|||||||
run: ls -R
|
run: ls -R
|
||||||
```
|
```
|
||||||
|
|
||||||
|
Download a single artifact by ID to a specific directory:
|
||||||
|
|
||||||
|
```yaml
|
||||||
|
steps:
|
||||||
|
- uses: actions/download-artifact@v4
|
||||||
|
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:
|
Multiple artifacts can be downloaded by providing a comma-separated list of IDs:
|
||||||
|
|
||||||
```yaml
|
```yaml
|
||||||
@ -166,7 +184,7 @@ steps:
|
|||||||
run: ls -R path/to/artifacts
|
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
|
### Download All Artifacts
|
||||||
|
|
||||||
|
@ -1,4 +1,5 @@
|
|||||||
import * as core from '@actions/core'
|
import * as core from '@actions/core'
|
||||||
|
import * as path from 'path'
|
||||||
import artifact, {ArtifactNotFoundError} from '@actions/artifact'
|
import artifact, {ArtifactNotFoundError} from '@actions/artifact'
|
||||||
import {run} from '../src/download-artifact'
|
import {run} from '../src/download-artifact'
|
||||||
import {Inputs} from '../src/constants'
|
import {Inputs} from '../src/constants'
|
||||||
@ -371,4 +372,38 @@ describe('download', () => {
|
|||||||
"Inputs 'name' and 'artifact-ids' cannot be used together. Please specify only one."
|
"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
|
||||||
|
})
|
||||||
|
)
|
||||||
|
})
|
||||||
})
|
})
|
||||||
|
4
dist/index.js
vendored
4
dist/index.js
vendored
@ -118883,7 +118883,9 @@ function run() {
|
|||||||
}
|
}
|
||||||
const downloadPromises = artifacts.map(artifact => ({
|
const downloadPromises = artifacts.map(artifact => ({
|
||||||
name: artifact.name,
|
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
|
? resolvedPath
|
||||||
: path.join(resolvedPath, artifact.name), expectedHash: artifact.digest }))
|
: path.join(resolvedPath, artifact.name), expectedHash: artifact.digest }))
|
||||||
}));
|
}));
|
||||||
|
@ -174,7 +174,9 @@ export async function run(): Promise<void> {
|
|||||||
promise: artifactClient.downloadArtifact(artifact.id, {
|
promise: artifactClient.downloadArtifact(artifact.id, {
|
||||||
...options,
|
...options,
|
||||||
path:
|
path:
|
||||||
isSingleArtifactDownload || inputs.mergeMultiple
|
isSingleArtifactDownload ||
|
||||||
|
inputs.mergeMultiple ||
|
||||||
|
artifacts.length === 1
|
||||||
? resolvedPath
|
? resolvedPath
|
||||||
: path.join(resolvedPath, artifact.name),
|
: path.join(resolvedPath, artifact.name),
|
||||||
expectedHash: artifact.digest
|
expectedHash: artifact.digest
|
||||||
|
Loading…
x
Reference in New Issue
Block a user