mirror of
https://github.com/actions/upload-artifact.git
synced 2025-06-14 15:57:12 +02:00
Compare commits
31 Commits
joshmgross
...
v4.5.0
Author | SHA1 | Date | |
---|---|---|---|
6f51ac03b9 | |||
c40c16d999 | |||
735efb4a0a | |||
184d73b71b | |||
b4a0a984a0 | |||
b4b15b8c7c | |||
92b01ebffa | |||
84480863f2 | |||
b1d4642b69 | |||
d50e66084c | |||
aabe6f8050 | |||
604373da63 | |||
0150148bdf | |||
a009b25faa | |||
9f6f6f402e | |||
3eadd8b791 | |||
aeba9f7961 | |||
b18b1d32f3 | |||
d7c12077c4 | |||
50769540e7 | |||
d52396ac5d | |||
710f362075 | |||
3b315f26f6 | |||
3be2180eb7 | |||
453e8d0a40 | |||
0a398c1480 | |||
a0c40cf602 | |||
acb59e4776 | |||
cb6558bb10 | |||
a954e16c38 | |||
a1d85e775a |
8
.github/workflows/codeql-analysis.yml
vendored
8
.github/workflows/codeql-analysis.yml
vendored
@ -17,11 +17,11 @@ jobs:
|
|||||||
|
|
||||||
steps:
|
steps:
|
||||||
- name: Checkout repository
|
- name: Checkout repository
|
||||||
uses: actions/checkout@v3
|
uses: actions/checkout@v4
|
||||||
|
|
||||||
# Initializes the CodeQL tools for scanning.
|
# Initializes the CodeQL tools for scanning.
|
||||||
- name: Initialize CodeQL
|
- name: Initialize CodeQL
|
||||||
uses: github/codeql-action/init@v2
|
uses: github/codeql-action/init@v3
|
||||||
# Override language selection by uncommenting this and choosing your languages
|
# Override language selection by uncommenting this and choosing your languages
|
||||||
# with:
|
# with:
|
||||||
# languages: go, javascript, csharp, python, cpp, java
|
# languages: go, javascript, csharp, python, cpp, java
|
||||||
@ -29,7 +29,7 @@ jobs:
|
|||||||
# Autobuild attempts to build any compiled languages (C/C++, C#, or 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)
|
# If this step fails, then you should remove it and run the build manually (see below)
|
||||||
- name: Autobuild
|
- name: Autobuild
|
||||||
uses: github/codeql-action/autobuild@v2
|
uses: github/codeql-action/autobuild@v3
|
||||||
|
|
||||||
# ℹ️ Command-line programs to run using the OS shell.
|
# ℹ️ Command-line programs to run using the OS shell.
|
||||||
# 📚 https://git.io/JvXDl
|
# 📚 https://git.io/JvXDl
|
||||||
@ -43,4 +43,4 @@ jobs:
|
|||||||
# make release
|
# make release
|
||||||
|
|
||||||
- name: Perform CodeQL Analysis
|
- name: Perform CodeQL Analysis
|
||||||
uses: github/codeql-action/analyze@v2
|
uses: github/codeql-action/analyze@v3
|
||||||
|
20
.github/workflows/publish-immutable-actions.yml
vendored
Normal file
20
.github/workflows/publish-immutable-actions.yml
vendored
Normal file
@ -0,0 +1,20 @@
|
|||||||
|
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
|
43
.github/workflows/test.yml
vendored
43
.github/workflows/test.yml
vendored
@ -46,14 +46,19 @@ jobs:
|
|||||||
- name: Test
|
- name: Test
|
||||||
run: npm run test
|
run: npm run test
|
||||||
|
|
||||||
# Test end-to-end by uploading two artifacts and then downloading them
|
# Test end-to-end by uploading a few artifacts and then downloading them
|
||||||
- name: Create artifact files
|
- name: Create artifact files
|
||||||
run: |
|
run: |
|
||||||
mkdir -p path/to/dir-1
|
mkdir -p path/to/dir-1
|
||||||
mkdir -p path/to/dir-2
|
mkdir -p path/to/dir-2
|
||||||
mkdir -p path/to/dir-3
|
mkdir -p path/to/dir-3
|
||||||
|
mkdir -p symlink/
|
||||||
echo "Lorem ipsum dolor sit amet" > path/to/dir-1/file1.txt
|
echo "Lorem ipsum dolor sit amet" > path/to/dir-1/file1.txt
|
||||||
echo "Hello world from file #2" > path/to/dir-2/file2.txt
|
echo "Hello world from file #2" > path/to/dir-2/file2.txt
|
||||||
|
echo "Hello from a symlinked file" > symlink/original.txt
|
||||||
|
ln -s $(pwd)/symlink/original.txt symlink/abs.txt
|
||||||
|
ln -s original.txt symlink/rel.txt
|
||||||
|
shell: bash
|
||||||
|
|
||||||
# Upload a single file artifact
|
# Upload a single file artifact
|
||||||
- name: 'Upload artifact #1'
|
- name: 'Upload artifact #1'
|
||||||
@ -79,6 +84,14 @@ jobs:
|
|||||||
path/to/dir-[23]/*
|
path/to/dir-[23]/*
|
||||||
!path/to/dir-3/*.txt
|
!path/to/dir-3/*.txt
|
||||||
|
|
||||||
|
- name: 'Upload symlinked artifact'
|
||||||
|
uses: ./
|
||||||
|
with:
|
||||||
|
name: 'Symlinked-Artifact-${{ matrix.runs-on }}'
|
||||||
|
path: |
|
||||||
|
symlink/abs.txt
|
||||||
|
symlink/rel.txt
|
||||||
|
|
||||||
# Download Artifact #1 and verify the correctness of the content
|
# Download Artifact #1 and verify the correctness of the content
|
||||||
- name: 'Download artifact #1'
|
- name: 'Download artifact #1'
|
||||||
uses: actions/download-artifact@v4
|
uses: actions/download-artifact@v4
|
||||||
@ -141,6 +154,34 @@ jobs:
|
|||||||
}
|
}
|
||||||
shell: pwsh
|
shell: pwsh
|
||||||
|
|
||||||
|
- name: 'Download symlinked artifact'
|
||||||
|
uses: actions/download-artifact@v4
|
||||||
|
with:
|
||||||
|
name: 'Symlinked-Artifact-${{ matrix.runs-on }}'
|
||||||
|
path: from/symlink
|
||||||
|
|
||||||
|
- name: 'Verify symlinked artifact'
|
||||||
|
run: |
|
||||||
|
$abs = "from/symlink/abs.txt"
|
||||||
|
if(!(Test-Path -path $abs))
|
||||||
|
{
|
||||||
|
Write-Error "Expected file does not exist"
|
||||||
|
}
|
||||||
|
if(!((Get-Content $abs) -ceq "Hello from a symlinked file"))
|
||||||
|
{
|
||||||
|
Write-Error "File contents of downloaded artifact are incorrect"
|
||||||
|
}
|
||||||
|
$rel = "from/symlink/rel.txt"
|
||||||
|
if(!(Test-Path -path $rel))
|
||||||
|
{
|
||||||
|
Write-Error "Expected file does not exist"
|
||||||
|
}
|
||||||
|
if(!((Get-Content $rel) -ceq "Hello from a symlinked file"))
|
||||||
|
{
|
||||||
|
Write-Error "File contents of downloaded artifact are incorrect"
|
||||||
|
}
|
||||||
|
shell: pwsh
|
||||||
|
|
||||||
- name: 'Alter file 1 content'
|
- name: 'Alter file 1 content'
|
||||||
run: |
|
run: |
|
||||||
echo "This file has changed" > path/to/dir-1/file1.txt
|
echo "This file has changed" > path/to/dir-1/file1.txt
|
||||||
|
6
.licenses/npm/@actions/artifact.dep.yml
generated
6
.licenses/npm/@actions/artifact.dep.yml
generated
@ -1,9 +1,9 @@
|
|||||||
---
|
---
|
||||||
name: "@actions/artifact"
|
name: "@actions/artifact"
|
||||||
version: 2.1.8
|
version: 2.2.0
|
||||||
type: npm
|
type: npm
|
||||||
summary:
|
summary: Actions artifact lib
|
||||||
homepage:
|
homepage: https://github.com/actions/toolkit/tree/main/packages/artifact
|
||||||
license: mit
|
license: mit
|
||||||
licenses:
|
licenses:
|
||||||
- sources: LICENSE.md
|
- sources: LICENSE.md
|
||||||
|
2
.licenses/npm/@actions/core.dep.yml
generated
2
.licenses/npm/@actions/core.dep.yml
generated
@ -1,6 +1,6 @@
|
|||||||
---
|
---
|
||||||
name: "@actions/core"
|
name: "@actions/core"
|
||||||
version: 1.10.1
|
version: 1.11.1
|
||||||
type: npm
|
type: npm
|
||||||
summary:
|
summary:
|
||||||
homepage:
|
homepage:
|
||||||
|
2
.licenses/npm/@actions/glob.dep.yml
generated
2
.licenses/npm/@actions/glob.dep.yml
generated
@ -1,6 +1,6 @@
|
|||||||
---
|
---
|
||||||
name: "@actions/glob"
|
name: "@actions/glob"
|
||||||
version: 0.3.0
|
version: 0.5.0
|
||||||
type: npm
|
type: npm
|
||||||
summary:
|
summary:
|
||||||
homepage:
|
homepage:
|
||||||
|
30
README.md
30
README.md
@ -64,6 +64,7 @@ There is also a new sub-action, `actions/upload-artifact/merge`. For more info,
|
|||||||
Due to how Artifacts are created in this new version, it is no longer possible to upload to the same named Artifact multiple times. You must either split the uploads into multiple Artifacts with different names, or only upload once. Otherwise you _will_ encounter an error.
|
Due to how Artifacts are created in this new version, it is no longer possible to upload to the same named Artifact multiple times. You must either split the uploads into multiple Artifacts with different names, or only upload once. Otherwise you _will_ encounter an error.
|
||||||
|
|
||||||
3. Limit of Artifacts for an individual job. Each job in a workflow run now has a limit of 500 artifacts.
|
3. Limit of Artifacts for an individual job. Each job in a workflow run now has a limit of 500 artifacts.
|
||||||
|
4. With `v4.4` and later, hidden files are excluded by default.
|
||||||
|
|
||||||
For assistance with breaking changes, see [MIGRATION.md](docs/MIGRATION.md).
|
For assistance with breaking changes, see [MIGRATION.md](docs/MIGRATION.md).
|
||||||
|
|
||||||
@ -107,6 +108,12 @@ For assistance with breaking changes, see [MIGRATION.md](docs/MIGRATION.md).
|
|||||||
# Does not fail if the artifact does not exist.
|
# Does not fail if the artifact does not exist.
|
||||||
# Optional. Default is 'false'
|
# Optional. Default is 'false'
|
||||||
overwrite:
|
overwrite:
|
||||||
|
|
||||||
|
# Whether to include hidden files in the provided path in the artifact
|
||||||
|
# The file contents of any hidden files in the path should be validated before
|
||||||
|
# enabled this to avoid uploading sensitive information.
|
||||||
|
# Optional. Default is 'false'
|
||||||
|
include-hidden-files:
|
||||||
```
|
```
|
||||||
|
|
||||||
### Outputs
|
### Outputs
|
||||||
@ -115,6 +122,7 @@ For assistance with breaking changes, see [MIGRATION.md](docs/MIGRATION.md).
|
|||||||
| - | - | - |
|
| - | - | - |
|
||||||
| `artifact-id` | GitHub ID of an Artifact, can be used by the REST API | `1234` |
|
| `artifact-id` | GitHub ID of an Artifact, can be used by the REST API | `1234` |
|
||||||
| `artifact-url` | URL to download an Artifact. Can be used in many scenarios such as linking to artifacts in issues or pull requests. Users must be logged-in in order for this URL to work. This URL is valid as long as the artifact has not expired or the artifact, run or repository have not been deleted | `https://github.com/example-org/example-repo/actions/runs/1/artifacts/1234` |
|
| `artifact-url` | URL to download an Artifact. Can be used in many scenarios such as linking to artifacts in issues or pull requests. Users must be logged-in in order for this URL to work. This URL is valid as long as the artifact has not expired or the artifact, run or repository have not been deleted | `https://github.com/example-org/example-repo/actions/runs/1/artifacts/1234` |
|
||||||
|
| `artifact-digest` | SHA-256 digest of an Artifact | 0fde654d4c6e659b45783a725dc92f1bfb0baa6c2de64b34e814dc206ff4aaaf |
|
||||||
|
|
||||||
## Examples
|
## Examples
|
||||||
|
|
||||||
@ -410,6 +418,28 @@ jobs:
|
|||||||
overwrite: true
|
overwrite: true
|
||||||
```
|
```
|
||||||
|
|
||||||
|
### Uploading Hidden Files
|
||||||
|
|
||||||
|
By default, hidden files are ignored by this action to avoid unintentionally uploading sensitive information.
|
||||||
|
|
||||||
|
If you need to upload hidden files, you can use the `include-hidden-files` input.
|
||||||
|
Any files that contain sensitive information that should not be in the uploaded artifact can be excluded
|
||||||
|
using the `path`:
|
||||||
|
|
||||||
|
```yaml
|
||||||
|
- uses: actions/upload-artifact@v4
|
||||||
|
with:
|
||||||
|
name: my-artifact
|
||||||
|
include-hidden-files: true
|
||||||
|
path: |
|
||||||
|
path/output/
|
||||||
|
!path/output/.production.env
|
||||||
|
```
|
||||||
|
|
||||||
|
Hidden files are defined as any file beginning with `.` or files within folders beginning with `.`.
|
||||||
|
On Windows, files and directories with the hidden attribute are not considered hidden files unless
|
||||||
|
they have the `.` prefix.
|
||||||
|
|
||||||
## Limitations
|
## Limitations
|
||||||
|
|
||||||
### Number of Artifacts
|
### Number of Artifacts
|
||||||
|
@ -61,6 +61,20 @@ const lonelyFilePath = path.join(
|
|||||||
'lonely-file.txt'
|
'lonely-file.txt'
|
||||||
)
|
)
|
||||||
|
|
||||||
|
const hiddenFile = path.join(root, '.hidden-file.txt')
|
||||||
|
const fileInHiddenFolderPath = path.join(
|
||||||
|
root,
|
||||||
|
'.hidden-folder',
|
||||||
|
'folder-in-hidden-folder',
|
||||||
|
'file.txt'
|
||||||
|
)
|
||||||
|
const fileInHiddenFolderInFolderA = path.join(
|
||||||
|
root,
|
||||||
|
'folder-a',
|
||||||
|
'.hidden-folder-in-folder-a',
|
||||||
|
'file.txt'
|
||||||
|
)
|
||||||
|
|
||||||
describe('Search', () => {
|
describe('Search', () => {
|
||||||
beforeAll(async () => {
|
beforeAll(async () => {
|
||||||
// mock all output so that there is less noise when running tests
|
// mock all output so that there is less noise when running tests
|
||||||
@ -93,6 +107,14 @@ describe('Search', () => {
|
|||||||
recursive: true
|
recursive: true
|
||||||
})
|
})
|
||||||
|
|
||||||
|
await fs.mkdir(
|
||||||
|
path.join(root, '.hidden-folder', 'folder-in-hidden-folder'),
|
||||||
|
{recursive: true}
|
||||||
|
)
|
||||||
|
await fs.mkdir(path.join(root, 'folder-a', '.hidden-folder-in-folder-a'), {
|
||||||
|
recursive: true
|
||||||
|
})
|
||||||
|
|
||||||
await fs.writeFile(searchItem1Path, 'search item1 file')
|
await fs.writeFile(searchItem1Path, 'search item1 file')
|
||||||
await fs.writeFile(searchItem2Path, 'search item2 file')
|
await fs.writeFile(searchItem2Path, 'search item2 file')
|
||||||
await fs.writeFile(searchItem3Path, 'search item3 file')
|
await fs.writeFile(searchItem3Path, 'search item3 file')
|
||||||
@ -110,10 +132,19 @@ describe('Search', () => {
|
|||||||
await fs.writeFile(amazingFileInFolderHPath, 'amazing file')
|
await fs.writeFile(amazingFileInFolderHPath, 'amazing file')
|
||||||
|
|
||||||
await fs.writeFile(lonelyFilePath, 'all by itself')
|
await fs.writeFile(lonelyFilePath, 'all by itself')
|
||||||
|
|
||||||
|
await fs.writeFile(hiddenFile, 'hidden file')
|
||||||
|
await fs.writeFile(fileInHiddenFolderPath, 'file in hidden directory')
|
||||||
|
await fs.writeFile(fileInHiddenFolderInFolderA, 'file in hidden directory')
|
||||||
/*
|
/*
|
||||||
Directory structure of files that get created:
|
Directory structure of files that get created:
|
||||||
root/
|
root/
|
||||||
|
.hidden-folder/
|
||||||
|
folder-in-hidden-folder/
|
||||||
|
file.txt
|
||||||
folder-a/
|
folder-a/
|
||||||
|
.hidden-folder-in-folder-a/
|
||||||
|
file.txt
|
||||||
folder-b/
|
folder-b/
|
||||||
folder-c/
|
folder-c/
|
||||||
search-item1.txt
|
search-item1.txt
|
||||||
@ -136,6 +167,7 @@ describe('Search', () => {
|
|||||||
folder-j/
|
folder-j/
|
||||||
folder-k/
|
folder-k/
|
||||||
lonely-file.txt
|
lonely-file.txt
|
||||||
|
.hidden-file.txt
|
||||||
search-item5.txt
|
search-item5.txt
|
||||||
*/
|
*/
|
||||||
})
|
})
|
||||||
@ -352,4 +384,24 @@ describe('Search', () => {
|
|||||||
)
|
)
|
||||||
expect(searchResult.filesToUpload.includes(lonelyFilePath)).toEqual(true)
|
expect(searchResult.filesToUpload.includes(lonelyFilePath)).toEqual(true)
|
||||||
})
|
})
|
||||||
|
|
||||||
|
it('Hidden files ignored by default', async () => {
|
||||||
|
const searchPath = path.join(root, '**/*')
|
||||||
|
const searchResult = await findFilesToUpload(searchPath)
|
||||||
|
|
||||||
|
expect(searchResult.filesToUpload).not.toContain(hiddenFile)
|
||||||
|
expect(searchResult.filesToUpload).not.toContain(fileInHiddenFolderPath)
|
||||||
|
expect(searchResult.filesToUpload).not.toContain(
|
||||||
|
fileInHiddenFolderInFolderA
|
||||||
|
)
|
||||||
|
})
|
||||||
|
|
||||||
|
it('Hidden files included', async () => {
|
||||||
|
const searchPath = path.join(root, '**/*')
|
||||||
|
const searchResult = await findFilesToUpload(searchPath, true)
|
||||||
|
|
||||||
|
expect(searchResult.filesToUpload).toContain(hiddenFile)
|
||||||
|
expect(searchResult.filesToUpload).toContain(fileInHiddenFolderPath)
|
||||||
|
expect(searchResult.filesToUpload).toContain(fileInHiddenFolderInFolderA)
|
||||||
|
})
|
||||||
})
|
})
|
||||||
|
@ -60,7 +60,8 @@ describe('upload', () => {
|
|||||||
|
|
||||||
jest.spyOn(artifact, 'uploadArtifact').mockResolvedValue({
|
jest.spyOn(artifact, 'uploadArtifact').mockResolvedValue({
|
||||||
size: 123,
|
size: 123,
|
||||||
id: 1337
|
id: 1337,
|
||||||
|
digest: 'facefeed'
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
|
||||||
@ -95,6 +96,7 @@ describe('upload', () => {
|
|||||||
await run()
|
await run()
|
||||||
|
|
||||||
expect(core.setOutput).toHaveBeenCalledWith('artifact-id', 1337)
|
expect(core.setOutput).toHaveBeenCalledWith('artifact-id', 1337)
|
||||||
|
expect(core.setOutput).toHaveBeenCalledWith('artifact-digest', 'facefeed')
|
||||||
expect(core.setOutput).toHaveBeenCalledWith(
|
expect(core.setOutput).toHaveBeenCalledWith(
|
||||||
'artifact-url',
|
'artifact-url',
|
||||||
`${github.context.serverUrl}/${github.context.repo.owner}/${
|
`${github.context.serverUrl}/${github.context.repo.owner}/${
|
||||||
|
@ -40,6 +40,11 @@ inputs:
|
|||||||
If false, the action will fail if an artifact for the given name already exists.
|
If false, the action will fail if an artifact for the given name already exists.
|
||||||
Does not fail if the artifact does not exist.
|
Does not fail if the artifact does not exist.
|
||||||
default: 'false'
|
default: 'false'
|
||||||
|
include-hidden-files:
|
||||||
|
description: >
|
||||||
|
If true, hidden files will be included in the artifact.
|
||||||
|
If false, hidden files will be excluded from the artifact.
|
||||||
|
default: 'false'
|
||||||
|
|
||||||
outputs:
|
outputs:
|
||||||
artifact-id:
|
artifact-id:
|
||||||
@ -56,6 +61,9 @@ outputs:
|
|||||||
|
|
||||||
This URL will be valid for as long as the artifact exists and the workflow run and repository exists. Once an artifact has expired this URL will no longer work.
|
This URL will be valid for as long as the artifact exists and the workflow run and repository exists. Once an artifact has expired this URL will no longer work.
|
||||||
Common uses cases for such a download URL can be adding download links to artifacts in descriptions or comments on pull requests or issues.
|
Common uses cases for such a download URL can be adding download links to artifacts in descriptions or comments on pull requests or issues.
|
||||||
|
artifact-digest:
|
||||||
|
description: >
|
||||||
|
SHA-256 digest for the artifact that was just uploaded. Empty if the artifact upload failed.
|
||||||
runs:
|
runs:
|
||||||
using: 'node20'
|
using: 'node20'
|
||||||
main: 'dist/upload/index.js'
|
main: 'dist/upload/index.js'
|
||||||
|
1706
dist/merge/index.js
vendored
1706
dist/merge/index.js
vendored
File diff suppressed because it is too large
Load Diff
1706
dist/upload/index.js
vendored
1706
dist/upload/index.js
vendored
File diff suppressed because it is too large
Load Diff
@ -4,6 +4,7 @@
|
|||||||
- [Multiple uploads to the same named Artifact](#multiple-uploads-to-the-same-named-artifact)
|
- [Multiple uploads to the same named Artifact](#multiple-uploads-to-the-same-named-artifact)
|
||||||
- [Overwriting an Artifact](#overwriting-an-artifact)
|
- [Overwriting an Artifact](#overwriting-an-artifact)
|
||||||
- [Merging multiple artifacts](#merging-multiple-artifacts)
|
- [Merging multiple artifacts](#merging-multiple-artifacts)
|
||||||
|
- [Hidden files](#hidden-files)
|
||||||
|
|
||||||
Several behavioral differences exist between Artifact actions `v3` and below vs `v4`. This document outlines common scenarios in `v3`, and how they would be handled in `v4`.
|
Several behavioral differences exist between Artifact actions `v3` and below vs `v4`. This document outlines common scenarios in `v3`, and how they would be handled in `v4`.
|
||||||
|
|
||||||
@ -189,21 +190,59 @@ jobs:
|
|||||||
- name: Create a File
|
- name: Create a File
|
||||||
run: echo "hello from ${{ matrix.runs-on }}" > file-${{ matrix.runs-on }}.txt
|
run: echo "hello from ${{ matrix.runs-on }}" > file-${{ matrix.runs-on }}.txt
|
||||||
- name: Upload Artifact
|
- name: Upload Artifact
|
||||||
- uses: actions/upload-artifact@v3
|
- uses: actions/upload-artifact@v3
|
||||||
+ uses: actions/upload-artifact@v4
|
+ uses: actions/upload-artifact@v4
|
||||||
with:
|
with:
|
||||||
- name: all-my-files
|
- name: all-my-files
|
||||||
+ name: my-artifact-${{ matrix.runs-on }}
|
+ name: my-artifact-${{ matrix.runs-on }}
|
||||||
path: file-${{ matrix.runs-on }}.txt
|
path: file-${{ matrix.runs-on }}.txt
|
||||||
+ merge:
|
+ merge:
|
||||||
+ runs-on: ubuntu-latest
|
+ runs-on: ubuntu-latest
|
||||||
+ needs: upload
|
+ needs: upload
|
||||||
+ steps:
|
+ steps:
|
||||||
+ - name: Merge Artifacts
|
+ - name: Merge Artifacts
|
||||||
+ uses: actions/upload-artifact/merge@v4
|
+ uses: actions/upload-artifact/merge@v4
|
||||||
+ with:
|
+ with:
|
||||||
+ name: all-my-files
|
+ name: all-my-files
|
||||||
+ pattern: my-artifact-*
|
+ pattern: my-artifact-*
|
||||||
```
|
```
|
||||||
|
|
||||||
Note that this will download all artifacts to a temporary directory and reupload them as a single artifact. For more information on inputs and other use cases for `actions/upload-artifact/merge@v4`, see [the action documentation](../merge/README.md).
|
Note that this will download all artifacts to a temporary directory and reupload them as a single artifact. For more information on inputs and other use cases for `actions/upload-artifact/merge@v4`, see [the action documentation](../merge/README.md).
|
||||||
|
|
||||||
|
## Hidden Files
|
||||||
|
|
||||||
|
By default, hidden files are ignored by this action to avoid unintentionally uploading sensitive
|
||||||
|
information.
|
||||||
|
|
||||||
|
In versions of this action before v4.4.0, these hidden files were included by default.
|
||||||
|
|
||||||
|
If you need to upload hidden files, you can use the `include-hidden-files` input.
|
||||||
|
|
||||||
|
```yaml
|
||||||
|
jobs:
|
||||||
|
upload:
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
steps:
|
||||||
|
- name: Create a Hidden File
|
||||||
|
run: echo "hello from a hidden file" > .hidden-file.txt
|
||||||
|
- name: Upload Artifact
|
||||||
|
uses: actions/upload-artifact@v3
|
||||||
|
with:
|
||||||
|
path: .hidden-file.txt
|
||||||
|
```
|
||||||
|
|
||||||
|
|
||||||
|
```diff
|
||||||
|
jobs:
|
||||||
|
upload:
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
steps:
|
||||||
|
- name: Create a Hidden File
|
||||||
|
run: echo "hello from a hidden file" > .hidden-file.txt
|
||||||
|
- name: Upload Artifact
|
||||||
|
- uses: actions/upload-artifact@v3
|
||||||
|
+ uses: actions/upload-artifact@v4
|
||||||
|
with:
|
||||||
|
path: .hidden-file.txt
|
||||||
|
+ include-hidden-files: true
|
||||||
|
```
|
@ -65,6 +65,7 @@ For most cases, this may not be the most efficient solution. See [the migration
|
|||||||
| - | - | - |
|
| - | - | - |
|
||||||
| `artifact-id` | GitHub ID of an Artifact, can be used by the REST API | `1234` |
|
| `artifact-id` | GitHub ID of an Artifact, can be used by the REST API | `1234` |
|
||||||
| `artifact-url` | URL to download an Artifact. Can be used in many scenarios such as linking to artifacts in issues or pull requests. Users must be logged-in in order for this URL to work. This URL is valid as long as the artifact has not expired or the artifact, run or repository have not been deleted | `https://github.com/example-org/example-repo/actions/runs/1/artifacts/1234` |
|
| `artifact-url` | URL to download an Artifact. Can be used in many scenarios such as linking to artifacts in issues or pull requests. Users must be logged-in in order for this URL to work. This URL is valid as long as the artifact has not expired or the artifact, run or repository have not been deleted | `https://github.com/example-org/example-repo/actions/runs/1/artifacts/1234` |
|
||||||
|
| `artifact-digest` | SHA-256 digest of an Artifact | 0fde654d4c6e659b45783a725dc92f1bfb0baa6c2de64b34e814dc206ff4aaaf |
|
||||||
|
|
||||||
## Examples
|
## Examples
|
||||||
|
|
||||||
|
@ -36,6 +36,11 @@ inputs:
|
|||||||
If true, the artifacts that were merged will be deleted.
|
If true, the artifacts that were merged will be deleted.
|
||||||
If false, the artifacts will still exist.
|
If false, the artifacts will still exist.
|
||||||
default: 'false'
|
default: 'false'
|
||||||
|
include-hidden-files:
|
||||||
|
description: >
|
||||||
|
If true, hidden files will be included in the merged artifact.
|
||||||
|
If false, hidden files will be excluded from the merged artifact.
|
||||||
|
default: 'false'
|
||||||
|
|
||||||
outputs:
|
outputs:
|
||||||
artifact-id:
|
artifact-id:
|
||||||
@ -52,6 +57,9 @@ outputs:
|
|||||||
|
|
||||||
This URL will be valid for as long as the artifact exists and the workflow run and repository exists. Once an artifact has expired this URL will no longer work.
|
This URL will be valid for as long as the artifact exists and the workflow run and repository exists. Once an artifact has expired this URL will no longer work.
|
||||||
Common uses cases for such a download URL can be adding download links to artifacts in descriptions or comments on pull requests or issues.
|
Common uses cases for such a download URL can be adding download links to artifacts in descriptions or comments on pull requests or issues.
|
||||||
|
artifact-digest:
|
||||||
|
description: >
|
||||||
|
SHA-256 digest for the artifact that was just uploaded. Empty if the artifact upload failed.
|
||||||
runs:
|
runs:
|
||||||
using: 'node20'
|
using: 'node20'
|
||||||
main: '../dist/merge/index.js'
|
main: '../dist/merge/index.js'
|
||||||
|
133
package-lock.json
generated
133
package-lock.json
generated
@ -1,18 +1,18 @@
|
|||||||
{
|
{
|
||||||
"name": "upload-artifact",
|
"name": "upload-artifact",
|
||||||
"version": "4.3.6",
|
"version": "4.5.0",
|
||||||
"lockfileVersion": 2,
|
"lockfileVersion": 2,
|
||||||
"requires": true,
|
"requires": true,
|
||||||
"packages": {
|
"packages": {
|
||||||
"": {
|
"": {
|
||||||
"name": "upload-artifact",
|
"name": "upload-artifact",
|
||||||
"version": "4.3.6",
|
"version": "4.5.0",
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@actions/artifact": "2.1.8",
|
"@actions/artifact": "^2.2.0",
|
||||||
"@actions/core": "^1.10.1",
|
"@actions/core": "^1.11.1",
|
||||||
"@actions/github": "^6.0.0",
|
"@actions/github": "^6.0.0",
|
||||||
"@actions/glob": "^0.3.0",
|
"@actions/glob": "^0.5.0",
|
||||||
"@actions/io": "^1.1.2",
|
"@actions/io": "^1.1.2",
|
||||||
"minimatch": "^9.0.3"
|
"minimatch": "^9.0.3"
|
||||||
},
|
},
|
||||||
@ -34,9 +34,10 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/@actions/artifact": {
|
"node_modules/@actions/artifact": {
|
||||||
"version": "2.1.8",
|
"version": "2.2.0",
|
||||||
"resolved": "https://registry.npmjs.org/@actions/artifact/-/artifact-2.1.8.tgz",
|
"resolved": "https://registry.npmjs.org/@actions/artifact/-/artifact-2.2.0.tgz",
|
||||||
"integrity": "sha512-kxgbllgF5f6mEdMeSW6WXlUbV1U77V9ECpA7LOYaY+Tm6RfXOm36EdXbpm+T9VPeaVqXK4QHLAgqay9GSyClgw==",
|
"integrity": "sha512-nDEyBsphN148zHe6ihq1a/UX92MDgC2GS9XmeFx2xs/wztZxzARYllviiP5U1nTDp2n9dEhnUig9RP9eSDcU5g==",
|
||||||
|
"license": "MIT",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@actions/core": "^1.10.0",
|
"@actions/core": "^1.10.0",
|
||||||
"@actions/github": "^5.1.1",
|
"@actions/github": "^5.1.1",
|
||||||
@ -48,7 +49,6 @@
|
|||||||
"@octokit/request-error": "^5.0.0",
|
"@octokit/request-error": "^5.0.0",
|
||||||
"@protobuf-ts/plugin": "^2.2.3-alpha.1",
|
"@protobuf-ts/plugin": "^2.2.3-alpha.1",
|
||||||
"archiver": "^7.0.1",
|
"archiver": "^7.0.1",
|
||||||
"crypto": "^1.0.1",
|
|
||||||
"jwt-decode": "^3.1.2",
|
"jwt-decode": "^3.1.2",
|
||||||
"twirp-ts": "^2.5.0",
|
"twirp-ts": "^2.5.0",
|
||||||
"unzip-stream": "^0.3.1"
|
"unzip-stream": "^0.3.1"
|
||||||
@ -66,12 +66,22 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/@actions/core": {
|
"node_modules/@actions/core": {
|
||||||
"version": "1.10.1",
|
"version": "1.11.1",
|
||||||
"resolved": "https://registry.npmjs.org/@actions/core/-/core-1.10.1.tgz",
|
"resolved": "https://registry.npmjs.org/@actions/core/-/core-1.11.1.tgz",
|
||||||
"integrity": "sha512-3lBR9EDAY+iYIpTnTIXmWcNbX3T2kCkAEQGIQx4NVQ0575nk2k3GRZDTPQG+vVtS2izSLmINlxXf0uLtnrTP+g==",
|
"integrity": "sha512-hXJCSrkwfA46Vd9Z3q4cpEpHB1rL5NG04+/rbqW9d3+CSvtB1tYe8UTpAlixa1vj0m/ULglfEK2UKxMGxCxv5A==",
|
||||||
|
"license": "MIT",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@actions/http-client": "^2.0.1",
|
"@actions/exec": "^1.1.1",
|
||||||
"uuid": "^8.3.2"
|
"@actions/http-client": "^2.0.1"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/@actions/exec": {
|
||||||
|
"version": "1.1.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/@actions/exec/-/exec-1.1.1.tgz",
|
||||||
|
"integrity": "sha512-+sCcHHbVdk93a0XT19ECtO/gIXoxvdsgQLzb2fE2/5sIZmWQuluYyjPQtrtTHdU1YzTZ7bAPN4sITq2xi1679w==",
|
||||||
|
"license": "MIT",
|
||||||
|
"dependencies": {
|
||||||
|
"@actions/io": "^1.0.1"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/@actions/github": {
|
"node_modules/@actions/github": {
|
||||||
@ -191,11 +201,11 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/@actions/glob": {
|
"node_modules/@actions/glob": {
|
||||||
"version": "0.3.0",
|
"version": "0.5.0",
|
||||||
"resolved": "https://registry.npmjs.org/@actions/glob/-/glob-0.3.0.tgz",
|
"resolved": "https://registry.npmjs.org/@actions/glob/-/glob-0.5.0.tgz",
|
||||||
"integrity": "sha512-tJP1ZhF87fd6LBnaXWlahkyvdgvsLl7WnreW1EZaC8JWjpMXmzqWzQVe/IEYslrkT9ymibVrKyJN4UMD7uQM2w==",
|
"integrity": "sha512-tST2rjPvJLRZLuT9NMUtyBjvj9Yo0MiJS3ow004slMvm8GFM+Zv9HvMJ7HWzfUyJnGrJvDsYkWBaaG3YKXRtCw==",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@actions/core": "^1.2.6",
|
"@actions/core": "^1.9.1",
|
||||||
"minimatch": "^3.0.4"
|
"minimatch": "^3.0.4"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
@ -3229,12 +3239,6 @@
|
|||||||
"which": "^2.0.1"
|
"which": "^2.0.1"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/crypto": {
|
|
||||||
"version": "1.0.1",
|
|
||||||
"resolved": "https://registry.npmjs.org/crypto/-/crypto-1.0.1.tgz",
|
|
||||||
"integrity": "sha512-VxBKmeNcqQdiUQUW2Tzq0t377b54N2bMtXO/qiLa+6eRRmmC4qT3D4OnTGoT/U6O9aklQ/jTwbOtRMTTY8G0Ig==",
|
|
||||||
"deprecated": "This package is no longer supported. It's now a built-in Node module. If you've depended on crypto, you should switch to the one that's built-in."
|
|
||||||
},
|
|
||||||
"node_modules/damerau-levenshtein": {
|
"node_modules/damerau-levenshtein": {
|
||||||
"version": "1.0.8",
|
"version": "1.0.8",
|
||||||
"resolved": "https://registry.npmjs.org/damerau-levenshtein/-/damerau-levenshtein-1.0.8.tgz",
|
"resolved": "https://registry.npmjs.org/damerau-levenshtein/-/damerau-levenshtein-1.0.8.tgz",
|
||||||
@ -6101,12 +6105,13 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/micromatch": {
|
"node_modules/micromatch": {
|
||||||
"version": "4.0.5",
|
"version": "4.0.8",
|
||||||
"resolved": "https://registry.npmjs.org/micromatch/-/micromatch-4.0.5.tgz",
|
"resolved": "https://registry.npmjs.org/micromatch/-/micromatch-4.0.8.tgz",
|
||||||
"integrity": "sha512-DMy+ERcEW2q8Z2Po+WNXuw3c5YaUSFjAO5GsJqfEl7UjvtIuFKO6ZrKvcItdy98dwFI2N1tg3zNIdKaQT+aNdA==",
|
"integrity": "sha512-PXwfBhYu0hBCPw8Dn0E+WDYb7af3dSLVWKi3HGv84IdF4TyFoC0ysxFd0Goxw7nSv4T/PzEJQxsYsEiFCKo2BA==",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
|
"license": "MIT",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"braces": "^3.0.2",
|
"braces": "^3.0.3",
|
||||||
"picomatch": "^2.3.1"
|
"picomatch": "^2.3.1"
|
||||||
},
|
},
|
||||||
"engines": {
|
"engines": {
|
||||||
@ -6463,9 +6468,10 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/path-to-regexp": {
|
"node_modules/path-to-regexp": {
|
||||||
"version": "6.2.1",
|
"version": "6.3.0",
|
||||||
"resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-6.2.1.tgz",
|
"resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-6.3.0.tgz",
|
||||||
"integrity": "sha512-JLyh7xT1kizaEvcaXOQwOc2/Yhw6KZOvPf1S8401UyLk86CU79LN3vl7ztXGm/pZ+YjoyAJ4rxmHwbkBXJX+yw=="
|
"integrity": "sha512-Yhpw4T9C6hPpgPeA28us07OJeqZ5EzQTkbfwuhsUg0c237RomFoETJgmp2sa3F/41gfLE6G5cqcYwznmeEeOlQ==",
|
||||||
|
"license": "MIT"
|
||||||
},
|
},
|
||||||
"node_modules/path-type": {
|
"node_modules/path-type": {
|
||||||
"version": "4.0.0",
|
"version": "4.0.0",
|
||||||
@ -7600,9 +7606,10 @@
|
|||||||
"integrity": "sha512-yCzhz6FN2wU1NiiQRogkTQszlQSlpWaw8SvVegAc+bDxbzHgh1vX8uIe8OYyMH6DwH+sdTJsgMl36+mSMdRJIQ=="
|
"integrity": "sha512-yCzhz6FN2wU1NiiQRogkTQszlQSlpWaw8SvVegAc+bDxbzHgh1vX8uIe8OYyMH6DwH+sdTJsgMl36+mSMdRJIQ=="
|
||||||
},
|
},
|
||||||
"node_modules/unzip-stream": {
|
"node_modules/unzip-stream": {
|
||||||
"version": "0.3.1",
|
"version": "0.3.4",
|
||||||
"resolved": "https://registry.npmjs.org/unzip-stream/-/unzip-stream-0.3.1.tgz",
|
"resolved": "https://registry.npmjs.org/unzip-stream/-/unzip-stream-0.3.4.tgz",
|
||||||
"integrity": "sha512-RzaGXLNt+CW+T41h1zl6pGz3EaeVhYlK+rdAap+7DxW5kqsqePO8kRtWPaCiVqdhZc86EctSPVYNix30YOMzmw==",
|
"integrity": "sha512-PyofABPVv+d7fL7GOpusx7eRT9YETY2X04PhwbSipdj6bMxVCFJrr+nm0Mxqbf9hUiTin/UsnuFWBXlDZFy0Cw==",
|
||||||
|
"license": "MIT",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"binary": "^0.3.0",
|
"binary": "^0.3.0",
|
||||||
"mkdirp": "^0.5.1"
|
"mkdirp": "^0.5.1"
|
||||||
@ -7902,9 +7909,9 @@
|
|||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@actions/artifact": {
|
"@actions/artifact": {
|
||||||
"version": "2.1.8",
|
"version": "2.2.0",
|
||||||
"resolved": "https://registry.npmjs.org/@actions/artifact/-/artifact-2.1.8.tgz",
|
"resolved": "https://registry.npmjs.org/@actions/artifact/-/artifact-2.2.0.tgz",
|
||||||
"integrity": "sha512-kxgbllgF5f6mEdMeSW6WXlUbV1U77V9ECpA7LOYaY+Tm6RfXOm36EdXbpm+T9VPeaVqXK4QHLAgqay9GSyClgw==",
|
"integrity": "sha512-nDEyBsphN148zHe6ihq1a/UX92MDgC2GS9XmeFx2xs/wztZxzARYllviiP5U1nTDp2n9dEhnUig9RP9eSDcU5g==",
|
||||||
"requires": {
|
"requires": {
|
||||||
"@actions/core": "^1.10.0",
|
"@actions/core": "^1.10.0",
|
||||||
"@actions/github": "^5.1.1",
|
"@actions/github": "^5.1.1",
|
||||||
@ -7916,7 +7923,6 @@
|
|||||||
"@octokit/request-error": "^5.0.0",
|
"@octokit/request-error": "^5.0.0",
|
||||||
"@protobuf-ts/plugin": "^2.2.3-alpha.1",
|
"@protobuf-ts/plugin": "^2.2.3-alpha.1",
|
||||||
"archiver": "^7.0.1",
|
"archiver": "^7.0.1",
|
||||||
"crypto": "^1.0.1",
|
|
||||||
"jwt-decode": "^3.1.2",
|
"jwt-decode": "^3.1.2",
|
||||||
"twirp-ts": "^2.5.0",
|
"twirp-ts": "^2.5.0",
|
||||||
"unzip-stream": "^0.3.1"
|
"unzip-stream": "^0.3.1"
|
||||||
@ -7936,12 +7942,20 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"@actions/core": {
|
"@actions/core": {
|
||||||
"version": "1.10.1",
|
"version": "1.11.1",
|
||||||
"resolved": "https://registry.npmjs.org/@actions/core/-/core-1.10.1.tgz",
|
"resolved": "https://registry.npmjs.org/@actions/core/-/core-1.11.1.tgz",
|
||||||
"integrity": "sha512-3lBR9EDAY+iYIpTnTIXmWcNbX3T2kCkAEQGIQx4NVQ0575nk2k3GRZDTPQG+vVtS2izSLmINlxXf0uLtnrTP+g==",
|
"integrity": "sha512-hXJCSrkwfA46Vd9Z3q4cpEpHB1rL5NG04+/rbqW9d3+CSvtB1tYe8UTpAlixa1vj0m/ULglfEK2UKxMGxCxv5A==",
|
||||||
"requires": {
|
"requires": {
|
||||||
"@actions/http-client": "^2.0.1",
|
"@actions/exec": "^1.1.1",
|
||||||
"uuid": "^8.3.2"
|
"@actions/http-client": "^2.0.1"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"@actions/exec": {
|
||||||
|
"version": "1.1.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/@actions/exec/-/exec-1.1.1.tgz",
|
||||||
|
"integrity": "sha512-+sCcHHbVdk93a0XT19ECtO/gIXoxvdsgQLzb2fE2/5sIZmWQuluYyjPQtrtTHdU1YzTZ7bAPN4sITq2xi1679w==",
|
||||||
|
"requires": {
|
||||||
|
"@actions/io": "^1.0.1"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"@actions/github": {
|
"@actions/github": {
|
||||||
@ -8036,11 +8050,11 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"@actions/glob": {
|
"@actions/glob": {
|
||||||
"version": "0.3.0",
|
"version": "0.5.0",
|
||||||
"resolved": "https://registry.npmjs.org/@actions/glob/-/glob-0.3.0.tgz",
|
"resolved": "https://registry.npmjs.org/@actions/glob/-/glob-0.5.0.tgz",
|
||||||
"integrity": "sha512-tJP1ZhF87fd6LBnaXWlahkyvdgvsLl7WnreW1EZaC8JWjpMXmzqWzQVe/IEYslrkT9ymibVrKyJN4UMD7uQM2w==",
|
"integrity": "sha512-tST2rjPvJLRZLuT9NMUtyBjvj9Yo0MiJS3ow004slMvm8GFM+Zv9HvMJ7HWzfUyJnGrJvDsYkWBaaG3YKXRtCw==",
|
||||||
"requires": {
|
"requires": {
|
||||||
"@actions/core": "^1.2.6",
|
"@actions/core": "^1.9.1",
|
||||||
"minimatch": "^3.0.4"
|
"minimatch": "^3.0.4"
|
||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
@ -10373,11 +10387,6 @@
|
|||||||
"which": "^2.0.1"
|
"which": "^2.0.1"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"crypto": {
|
|
||||||
"version": "1.0.1",
|
|
||||||
"resolved": "https://registry.npmjs.org/crypto/-/crypto-1.0.1.tgz",
|
|
||||||
"integrity": "sha512-VxBKmeNcqQdiUQUW2Tzq0t377b54N2bMtXO/qiLa+6eRRmmC4qT3D4OnTGoT/U6O9aklQ/jTwbOtRMTTY8G0Ig=="
|
|
||||||
},
|
|
||||||
"damerau-levenshtein": {
|
"damerau-levenshtein": {
|
||||||
"version": "1.0.8",
|
"version": "1.0.8",
|
||||||
"resolved": "https://registry.npmjs.org/damerau-levenshtein/-/damerau-levenshtein-1.0.8.tgz",
|
"resolved": "https://registry.npmjs.org/damerau-levenshtein/-/damerau-levenshtein-1.0.8.tgz",
|
||||||
@ -12562,12 +12571,12 @@
|
|||||||
"dev": true
|
"dev": true
|
||||||
},
|
},
|
||||||
"micromatch": {
|
"micromatch": {
|
||||||
"version": "4.0.5",
|
"version": "4.0.8",
|
||||||
"resolved": "https://registry.npmjs.org/micromatch/-/micromatch-4.0.5.tgz",
|
"resolved": "https://registry.npmjs.org/micromatch/-/micromatch-4.0.8.tgz",
|
||||||
"integrity": "sha512-DMy+ERcEW2q8Z2Po+WNXuw3c5YaUSFjAO5GsJqfEl7UjvtIuFKO6ZrKvcItdy98dwFI2N1tg3zNIdKaQT+aNdA==",
|
"integrity": "sha512-PXwfBhYu0hBCPw8Dn0E+WDYb7af3dSLVWKi3HGv84IdF4TyFoC0ysxFd0Goxw7nSv4T/PzEJQxsYsEiFCKo2BA==",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
"requires": {
|
"requires": {
|
||||||
"braces": "^3.0.2",
|
"braces": "^3.0.3",
|
||||||
"picomatch": "^2.3.1"
|
"picomatch": "^2.3.1"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
@ -12822,9 +12831,9 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"path-to-regexp": {
|
"path-to-regexp": {
|
||||||
"version": "6.2.1",
|
"version": "6.3.0",
|
||||||
"resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-6.2.1.tgz",
|
"resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-6.3.0.tgz",
|
||||||
"integrity": "sha512-JLyh7xT1kizaEvcaXOQwOc2/Yhw6KZOvPf1S8401UyLk86CU79LN3vl7ztXGm/pZ+YjoyAJ4rxmHwbkBXJX+yw=="
|
"integrity": "sha512-Yhpw4T9C6hPpgPeA28us07OJeqZ5EzQTkbfwuhsUg0c237RomFoETJgmp2sa3F/41gfLE6G5cqcYwznmeEeOlQ=="
|
||||||
},
|
},
|
||||||
"path-type": {
|
"path-type": {
|
||||||
"version": "4.0.0",
|
"version": "4.0.0",
|
||||||
@ -13651,9 +13660,9 @@
|
|||||||
"integrity": "sha512-yCzhz6FN2wU1NiiQRogkTQszlQSlpWaw8SvVegAc+bDxbzHgh1vX8uIe8OYyMH6DwH+sdTJsgMl36+mSMdRJIQ=="
|
"integrity": "sha512-yCzhz6FN2wU1NiiQRogkTQszlQSlpWaw8SvVegAc+bDxbzHgh1vX8uIe8OYyMH6DwH+sdTJsgMl36+mSMdRJIQ=="
|
||||||
},
|
},
|
||||||
"unzip-stream": {
|
"unzip-stream": {
|
||||||
"version": "0.3.1",
|
"version": "0.3.4",
|
||||||
"resolved": "https://registry.npmjs.org/unzip-stream/-/unzip-stream-0.3.1.tgz",
|
"resolved": "https://registry.npmjs.org/unzip-stream/-/unzip-stream-0.3.4.tgz",
|
||||||
"integrity": "sha512-RzaGXLNt+CW+T41h1zl6pGz3EaeVhYlK+rdAap+7DxW5kqsqePO8kRtWPaCiVqdhZc86EctSPVYNix30YOMzmw==",
|
"integrity": "sha512-PyofABPVv+d7fL7GOpusx7eRT9YETY2X04PhwbSipdj6bMxVCFJrr+nm0Mxqbf9hUiTin/UsnuFWBXlDZFy0Cw==",
|
||||||
"requires": {
|
"requires": {
|
||||||
"binary": "^0.3.0",
|
"binary": "^0.3.0",
|
||||||
"mkdirp": "^0.5.1"
|
"mkdirp": "^0.5.1"
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "upload-artifact",
|
"name": "upload-artifact",
|
||||||
"version": "4.3.6",
|
"version": "4.5.0",
|
||||||
"description": "Upload an Actions Artifact in a workflow run",
|
"description": "Upload an Actions Artifact in a workflow run",
|
||||||
"main": "dist/upload/index.js",
|
"main": "dist/upload/index.js",
|
||||||
"scripts": {
|
"scripts": {
|
||||||
@ -29,10 +29,10 @@
|
|||||||
},
|
},
|
||||||
"homepage": "https://github.com/actions/upload-artifact#readme",
|
"homepage": "https://github.com/actions/upload-artifact#readme",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@actions/artifact": "2.1.8",
|
"@actions/artifact": "^2.2.0",
|
||||||
"@actions/core": "^1.10.1",
|
"@actions/core": "^1.11.1",
|
||||||
"@actions/github": "^6.0.0",
|
"@actions/github": "^6.0.0",
|
||||||
"@actions/glob": "^0.3.0",
|
"@actions/glob": "^0.5.0",
|
||||||
"@actions/io": "^1.1.2",
|
"@actions/io": "^1.1.2",
|
||||||
"minimatch": "^9.0.3"
|
"minimatch": "^9.0.3"
|
||||||
},
|
},
|
||||||
|
@ -5,5 +5,6 @@ export enum Inputs {
|
|||||||
SeparateDirectories = 'separate-directories',
|
SeparateDirectories = 'separate-directories',
|
||||||
RetentionDays = 'retention-days',
|
RetentionDays = 'retention-days',
|
||||||
CompressionLevel = 'compression-level',
|
CompressionLevel = 'compression-level',
|
||||||
DeleteMerged = 'delete-merged'
|
DeleteMerged = 'delete-merged',
|
||||||
|
IncludeHiddenFiles = 'include-hidden-files'
|
||||||
}
|
}
|
||||||
|
@ -10,6 +10,7 @@ export function getInputs(): MergeInputs {
|
|||||||
const pattern = core.getInput(Inputs.Pattern, {required: true})
|
const pattern = core.getInput(Inputs.Pattern, {required: true})
|
||||||
const separateDirectories = core.getBooleanInput(Inputs.SeparateDirectories)
|
const separateDirectories = core.getBooleanInput(Inputs.SeparateDirectories)
|
||||||
const deleteMerged = core.getBooleanInput(Inputs.DeleteMerged)
|
const deleteMerged = core.getBooleanInput(Inputs.DeleteMerged)
|
||||||
|
const includeHiddenFiles = core.getBooleanInput(Inputs.IncludeHiddenFiles)
|
||||||
|
|
||||||
const inputs = {
|
const inputs = {
|
||||||
name,
|
name,
|
||||||
@ -17,7 +18,8 @@ export function getInputs(): MergeInputs {
|
|||||||
separateDirectories,
|
separateDirectories,
|
||||||
deleteMerged,
|
deleteMerged,
|
||||||
retentionDays: 0,
|
retentionDays: 0,
|
||||||
compressionLevel: 6
|
compressionLevel: 6,
|
||||||
|
includeHiddenFiles
|
||||||
} as MergeInputs
|
} as MergeInputs
|
||||||
|
|
||||||
const retentionDaysStr = core.getInput(Inputs.RetentionDays)
|
const retentionDaysStr = core.getInput(Inputs.RetentionDays)
|
||||||
|
@ -62,7 +62,10 @@ export async function run(): Promise<void> {
|
|||||||
options.compressionLevel = inputs.compressionLevel
|
options.compressionLevel = inputs.compressionLevel
|
||||||
}
|
}
|
||||||
|
|
||||||
const searchResult = await findFilesToUpload(tmpDir)
|
const searchResult = await findFilesToUpload(
|
||||||
|
tmpDir,
|
||||||
|
inputs.includeHiddenFiles
|
||||||
|
)
|
||||||
|
|
||||||
await uploadArtifact(
|
await uploadArtifact(
|
||||||
inputs.name,
|
inputs.name,
|
||||||
|
@ -30,4 +30,9 @@ export interface MergeInputs {
|
|||||||
* If false, the artifacts will be merged into the root of the destination.
|
* If false, the artifacts will be merged into the root of the destination.
|
||||||
*/
|
*/
|
||||||
separateDirectories: boolean
|
separateDirectories: boolean
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Whether or not to include hidden files in the artifact
|
||||||
|
*/
|
||||||
|
includeHiddenFiles: boolean
|
||||||
}
|
}
|
||||||
|
@ -11,11 +11,12 @@ export interface SearchResult {
|
|||||||
rootDirectory: string
|
rootDirectory: string
|
||||||
}
|
}
|
||||||
|
|
||||||
function getDefaultGlobOptions(): glob.GlobOptions {
|
function getDefaultGlobOptions(includeHiddenFiles: boolean): glob.GlobOptions {
|
||||||
return {
|
return {
|
||||||
followSymbolicLinks: true,
|
followSymbolicLinks: true,
|
||||||
implicitDescendants: true,
|
implicitDescendants: true,
|
||||||
omitBrokenSymbolicLinks: true
|
omitBrokenSymbolicLinks: true,
|
||||||
|
excludeHiddenFiles: !includeHiddenFiles
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -80,12 +81,12 @@ function getMultiPathLCA(searchPaths: string[]): string {
|
|||||||
|
|
||||||
export async function findFilesToUpload(
|
export async function findFilesToUpload(
|
||||||
searchPath: string,
|
searchPath: string,
|
||||||
globOptions?: glob.GlobOptions
|
includeHiddenFiles?: boolean
|
||||||
): Promise<SearchResult> {
|
): Promise<SearchResult> {
|
||||||
const searchResults: string[] = []
|
const searchResults: string[] = []
|
||||||
const globber = await glob.create(
|
const globber = await glob.create(
|
||||||
searchPath,
|
searchPath,
|
||||||
globOptions || getDefaultGlobOptions()
|
getDefaultGlobOptions(includeHiddenFiles || false)
|
||||||
)
|
)
|
||||||
const rawSearchResults: string[] = await globber.glob()
|
const rawSearchResults: string[] = await globber.glob()
|
||||||
|
|
||||||
|
@ -19,6 +19,7 @@ export async function uploadArtifact(
|
|||||||
`Artifact ${artifactName} has been successfully uploaded! Final size is ${uploadResponse.size} bytes. Artifact ID is ${uploadResponse.id}`
|
`Artifact ${artifactName} has been successfully uploaded! Final size is ${uploadResponse.size} bytes. Artifact ID is ${uploadResponse.id}`
|
||||||
)
|
)
|
||||||
core.setOutput('artifact-id', uploadResponse.id)
|
core.setOutput('artifact-id', uploadResponse.id)
|
||||||
|
core.setOutput('artifact-digest', uploadResponse.digest)
|
||||||
|
|
||||||
const repository = github.context.repo
|
const repository = github.context.repo
|
||||||
const artifactURL = `${github.context.serverUrl}/${repository.owner}/${repository.repo}/actions/runs/${github.context.runId}/artifacts/${uploadResponse.id}`
|
const artifactURL = `${github.context.serverUrl}/${repository.owner}/${repository.repo}/actions/runs/${github.context.runId}/artifacts/${uploadResponse.id}`
|
||||||
|
@ -5,7 +5,8 @@ export enum Inputs {
|
|||||||
IfNoFilesFound = 'if-no-files-found',
|
IfNoFilesFound = 'if-no-files-found',
|
||||||
RetentionDays = 'retention-days',
|
RetentionDays = 'retention-days',
|
||||||
CompressionLevel = 'compression-level',
|
CompressionLevel = 'compression-level',
|
||||||
Overwrite = 'overwrite'
|
Overwrite = 'overwrite',
|
||||||
|
IncludeHiddenFiles = 'include-hidden-files'
|
||||||
}
|
}
|
||||||
|
|
||||||
export enum NoFileOptions {
|
export enum NoFileOptions {
|
||||||
|
@ -9,6 +9,7 @@ export function getInputs(): UploadInputs {
|
|||||||
const name = core.getInput(Inputs.Name)
|
const name = core.getInput(Inputs.Name)
|
||||||
const path = core.getInput(Inputs.Path, {required: true})
|
const path = core.getInput(Inputs.Path, {required: true})
|
||||||
const overwrite = core.getBooleanInput(Inputs.Overwrite)
|
const overwrite = core.getBooleanInput(Inputs.Overwrite)
|
||||||
|
const includeHiddenFiles = core.getBooleanInput(Inputs.IncludeHiddenFiles)
|
||||||
|
|
||||||
const ifNoFilesFound = core.getInput(Inputs.IfNoFilesFound)
|
const ifNoFilesFound = core.getInput(Inputs.IfNoFilesFound)
|
||||||
const noFileBehavior: NoFileOptions = NoFileOptions[ifNoFilesFound]
|
const noFileBehavior: NoFileOptions = NoFileOptions[ifNoFilesFound]
|
||||||
@ -27,7 +28,8 @@ export function getInputs(): UploadInputs {
|
|||||||
artifactName: name,
|
artifactName: name,
|
||||||
searchPath: path,
|
searchPath: path,
|
||||||
ifNoFilesFound: noFileBehavior,
|
ifNoFilesFound: noFileBehavior,
|
||||||
overwrite: overwrite
|
overwrite: overwrite,
|
||||||
|
includeHiddenFiles: includeHiddenFiles
|
||||||
} as UploadInputs
|
} as UploadInputs
|
||||||
|
|
||||||
const retentionDaysStr = core.getInput(Inputs.RetentionDays)
|
const retentionDaysStr = core.getInput(Inputs.RetentionDays)
|
||||||
|
@ -24,7 +24,10 @@ async function deleteArtifactIfExists(artifactName: string): Promise<void> {
|
|||||||
|
|
||||||
export async function run(): Promise<void> {
|
export async function run(): Promise<void> {
|
||||||
const inputs = getInputs()
|
const inputs = getInputs()
|
||||||
const searchResult = await findFilesToUpload(inputs.searchPath)
|
const searchResult = await findFilesToUpload(
|
||||||
|
inputs.searchPath,
|
||||||
|
inputs.includeHiddenFiles
|
||||||
|
)
|
||||||
if (searchResult.filesToUpload.length === 0) {
|
if (searchResult.filesToUpload.length === 0) {
|
||||||
// No files were found, different use cases warrant different types of behavior if nothing is found
|
// No files were found, different use cases warrant different types of behavior if nothing is found
|
||||||
switch (inputs.ifNoFilesFound) {
|
switch (inputs.ifNoFilesFound) {
|
||||||
|
@ -30,4 +30,9 @@ export interface UploadInputs {
|
|||||||
* Whether or not to replace an existing artifact with the same name
|
* Whether or not to replace an existing artifact with the same name
|
||||||
*/
|
*/
|
||||||
overwrite: boolean
|
overwrite: boolean
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Whether or not to include hidden files in the artifact
|
||||||
|
*/
|
||||||
|
includeHiddenFiles: boolean
|
||||||
}
|
}
|
||||||
|
Reference in New Issue
Block a user