mirror of
https://github.com/actions/upload-artifact.git
synced 2025-12-06 08:58:34 +08:00
Compare commits
14 Commits
konradpabj
...
v3.2.0-nod
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
672174a5ba | ||
|
|
9ee08a3b00 | ||
|
|
ff37344dc2 | ||
|
|
d99c5eca07 | ||
|
|
afc7e4a27d | ||
|
|
97a0fba137 | ||
|
|
a8a3f3ad30 | ||
|
|
7b48769c03 | ||
|
|
66630398df | ||
|
|
55e76b779d | ||
|
|
65d862660a | ||
|
|
0b7f8abb15 | ||
|
|
013d2b89ba | ||
|
|
055b8b3f04 |
6
.devcontainer/devcontainer.json
Normal file
6
.devcontainer/devcontainer.json
Normal file
@@ -0,0 +1,6 @@
|
||||
// For format details, see https://aka.ms/devcontainer.json. For config options, see the
|
||||
// README at: https://github.com/devcontainers/templates/tree/main/src/typescript-node
|
||||
{
|
||||
"name": "@actions/upload-artifact",
|
||||
"image": "mcr.microsoft.com/devcontainers/typescript-node:0-16"
|
||||
}
|
||||
@@ -4,13 +4,10 @@
|
||||
"parserOptions": { "ecmaVersion": 9, "sourceType": "module" },
|
||||
"extends": [
|
||||
"eslint:recommended",
|
||||
"plugin:@typescript-eslint/eslint-recommended",
|
||||
"plugin:@typescript-eslint/recommended",
|
||||
"plugin:import/errors",
|
||||
"plugin:import/warnings",
|
||||
"plugin:import/typescript",
|
||||
"plugin:prettier/recommended",
|
||||
"prettier/@typescript-eslint"
|
||||
"plugin:prettier/recommended"
|
||||
],
|
||||
"rules": {
|
||||
"@typescript-eslint/no-empty-function": "off"
|
||||
|
||||
16
.github/workflows/check-dist.yml
vendored
16
.github/workflows/check-dist.yml
vendored
@@ -20,19 +20,23 @@ jobs:
|
||||
runs-on: ubuntu-latest
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@v2
|
||||
- uses: actions/checkout@v3
|
||||
|
||||
- name: Set Node.js 12.x
|
||||
uses: actions/setup-node@v1
|
||||
- name: Setup Node 16
|
||||
uses: actions/setup-node@v3
|
||||
with:
|
||||
node-version: 12.x
|
||||
|
||||
node-version: 16.x
|
||||
cache: 'npm'
|
||||
|
||||
- name: Install dependencies
|
||||
run: npm ci
|
||||
|
||||
- name: Move the committed index.js file
|
||||
run: mv dist/index.js /tmp
|
||||
|
||||
- name: Rebuild with tsc
|
||||
run: npm run build
|
||||
|
||||
- name: Rebuild the index.js file
|
||||
run: npm run release
|
||||
|
||||
@@ -41,7 +45,7 @@ jobs:
|
||||
id: diff
|
||||
|
||||
# If index.js was different than expected, upload the expected version as an artifact
|
||||
- uses: actions/upload-artifact@v2
|
||||
- uses: actions/upload-artifact@v3
|
||||
if: ${{ failure() && steps.diff.conclusion == 'failure' }}
|
||||
with:
|
||||
name: index.js
|
||||
|
||||
6
.github/workflows/codeql-analysis.yml
vendored
6
.github/workflows/codeql-analysis.yml
vendored
@@ -21,7 +21,7 @@ jobs:
|
||||
|
||||
# Initializes the CodeQL tools for scanning.
|
||||
- name: Initialize CodeQL
|
||||
uses: github/codeql-action/init@v1
|
||||
uses: github/codeql-action/init@v2
|
||||
# Override language selection by uncommenting this and choosing your languages
|
||||
# with:
|
||||
# languages: go, javascript, csharp, python, cpp, java
|
||||
@@ -29,7 +29,7 @@ jobs:
|
||||
# Autobuild attempts to build any compiled languages (C/C++, C#, or Java).
|
||||
# If this step fails, then you should remove it and run the build manually (see below)
|
||||
- name: Autobuild
|
||||
uses: github/codeql-action/autobuild@v1
|
||||
uses: github/codeql-action/autobuild@v2
|
||||
|
||||
# ℹ️ Command-line programs to run using the OS shell.
|
||||
# 📚 https://git.io/JvXDl
|
||||
@@ -43,4 +43,4 @@ jobs:
|
||||
# make release
|
||||
|
||||
- name: Perform CodeQL Analysis
|
||||
uses: github/codeql-action/analyze@v1
|
||||
uses: github/codeql-action/analyze@v2
|
||||
|
||||
27
.github/workflows/test.yml
vendored
27
.github/workflows/test.yml
vendored
@@ -25,10 +25,11 @@ jobs:
|
||||
- name: Checkout
|
||||
uses: actions/checkout@v3
|
||||
|
||||
- name: Set Node.js 12.x
|
||||
uses: actions/setup-node@v1
|
||||
- name: Setup Node 16
|
||||
uses: actions/setup-node@v3
|
||||
with:
|
||||
node-version: 12.x
|
||||
node-version: 16.x
|
||||
cache: 'npm'
|
||||
|
||||
- name: Install dependencies
|
||||
run: npm ci
|
||||
@@ -36,21 +37,21 @@ jobs:
|
||||
- name: Compile
|
||||
run: npm run build
|
||||
|
||||
- name: npm test
|
||||
run: npm test
|
||||
|
||||
- name: Lint
|
||||
run: npm run lint
|
||||
|
||||
- name: Format
|
||||
run: npm run format-check
|
||||
|
||||
- name: Test
|
||||
run: npm run test
|
||||
|
||||
# Test end-to-end by uploading two artifacts and then downloading them
|
||||
- name: Create artifact files
|
||||
run: |
|
||||
mkdir -p path/to/dir-1
|
||||
mkdir -p path/to/dir-2
|
||||
mkdir -p path/to/dir-3
|
||||
mkdir -p path/to/dir-3
|
||||
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 "This is a going to be a test for a large enough file that should get compressed with GZip. The @actions/artifact package uses GZip to upload files. This text should have a compression ratio greater than 100% so it should get uploaded using GZip" > path/to/dir-3/gzip.txt
|
||||
@@ -85,11 +86,9 @@ jobs:
|
||||
path/to/dir-[23]/*
|
||||
!path/to/dir-3/*.txt
|
||||
|
||||
# Verify artifacts. Switch to download-artifact@v2 once it's out of preview
|
||||
|
||||
# Download Artifact #1 and verify the correctness of the content
|
||||
- name: 'Download artifact #1'
|
||||
uses: actions/download-artifact@v1
|
||||
uses: actions/download-artifact@v3
|
||||
with:
|
||||
name: 'Artifact-A'
|
||||
path: some/new/path
|
||||
@@ -109,7 +108,7 @@ jobs:
|
||||
|
||||
# Download Artifact #2 and verify the correctness of the content
|
||||
- name: 'Download artifact #2'
|
||||
uses: actions/download-artifact@v1
|
||||
uses: actions/download-artifact@v3
|
||||
with:
|
||||
name: 'artifact'
|
||||
path: some/other/path
|
||||
@@ -127,10 +126,10 @@ jobs:
|
||||
Write-Error "File contents of downloaded artifacts are incorrect"
|
||||
}
|
||||
shell: pwsh
|
||||
|
||||
|
||||
# Download Artifact #3 and verify the correctness of the content
|
||||
- name: 'Download artifact #3'
|
||||
uses: actions/download-artifact@v1
|
||||
uses: actions/download-artifact@v3
|
||||
with:
|
||||
name: 'GZip-Artifact'
|
||||
path: gzip/artifact/path
|
||||
@@ -150,7 +149,7 @@ jobs:
|
||||
shell: pwsh
|
||||
|
||||
- name: 'Download artifact #4'
|
||||
uses: actions/download-artifact@v1
|
||||
uses: actions/download-artifact@v3
|
||||
with:
|
||||
name: 'Multi-Path-Artifact'
|
||||
path: multi/artifact
|
||||
|
||||
BIN
.licenses/npm/@actions/artifact.dep.yml
generated
BIN
.licenses/npm/@actions/artifact.dep.yml
generated
Binary file not shown.
BIN
.licenses/npm/@actions/glob.dep.yml
generated
BIN
.licenses/npm/@actions/glob.dep.yml
generated
Binary file not shown.
BIN
.licenses/npm/@actions/http-client.dep.yml
generated
BIN
.licenses/npm/@actions/http-client.dep.yml
generated
Binary file not shown.
BIN
.licenses/npm/@actions/io.dep.yml
generated
BIN
.licenses/npm/@actions/io.dep.yml
generated
Binary file not shown.
BIN
.licenses/npm/@types/tmp.dep.yml
generated
BIN
.licenses/npm/@types/tmp.dep.yml
generated
Binary file not shown.
BIN
.licenses/npm/glob.dep.yml
generated
BIN
.licenses/npm/glob.dep.yml
generated
Binary file not shown.
BIN
.licenses/npm/minimatch.dep.yml
generated
BIN
.licenses/npm/minimatch.dep.yml
generated
Binary file not shown.
BIN
.licenses/npm/rimraf.dep.yml
generated
BIN
.licenses/npm/rimraf.dep.yml
generated
Binary file not shown.
BIN
.licenses/npm/tmp-promise.dep.yml
generated
BIN
.licenses/npm/tmp-promise.dep.yml
generated
Binary file not shown.
BIN
.licenses/npm/tmp.dep.yml
generated
BIN
.licenses/npm/tmp.dep.yml
generated
Binary file not shown.
BIN
.licenses/npm/uuid.dep.yml
generated
Normal file
BIN
.licenses/npm/uuid.dep.yml
generated
Normal file
Binary file not shown.
23
README.md
23
README.md
@@ -237,6 +237,29 @@ Artifacts are retained for 90 days by default. You can specify a shorter retenti
|
||||
|
||||
The retention period must be between 1 and 90 inclusive. For more information see [artifact and log retention policies](https://docs.github.com/en/free-pro-team@latest/actions/reference/usage-limits-billing-and-administration#artifact-and-log-retention-policy).
|
||||
|
||||
|
||||
### Hidden Files
|
||||
|
||||
By default, hidden files are ignored by this action to avoid unintentionally uploading sensitive information.
|
||||
|
||||
In versions of this action before v3.2.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
|
||||
include-hidden-files: true
|
||||
```
|
||||
|
||||
## Where does the upload go?
|
||||
|
||||
At the bottom of the workflow summary page, there is a dedicated section for artifacts. Here's a screenshot of something you might see:
|
||||
|
||||
@@ -61,6 +61,20 @@ const lonelyFilePath = path.join(
|
||||
'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', () => {
|
||||
beforeAll(async () => {
|
||||
// mock all output so that there is less noise when running tests
|
||||
@@ -92,6 +106,13 @@ describe('Search', () => {
|
||||
await fs.mkdir(path.join(root, 'folder-h', 'folder-j', 'folder-k'), {
|
||||
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(searchItem2Path, 'search item2 file')
|
||||
@@ -110,10 +131,19 @@ describe('Search', () => {
|
||||
await fs.writeFile(amazingFileInFolderHPath, 'amazing file')
|
||||
|
||||
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:
|
||||
root/
|
||||
.hidden-folder/
|
||||
folder-in-hidden-folder/
|
||||
file.txt
|
||||
folder-a/
|
||||
.hidden-folder-in-folder-a/
|
||||
file.txt
|
||||
folder-b/
|
||||
folder-c/
|
||||
search-item1.txt
|
||||
@@ -136,6 +166,7 @@ describe('Search', () => {
|
||||
folder-j/
|
||||
folder-k/
|
||||
lonely-file.txt
|
||||
.hidden-file.txt
|
||||
search-item5.txt
|
||||
*/
|
||||
})
|
||||
@@ -352,4 +383,24 @@ describe('Search', () => {
|
||||
)
|
||||
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)
|
||||
})
|
||||
})
|
||||
|
||||
@@ -23,6 +23,11 @@ inputs:
|
||||
|
||||
Minimum 1 day.
|
||||
Maximum 90 days unless changed from the repository settings page.
|
||||
include-hidden-files:
|
||||
description: >
|
||||
If true, hidden files will be included in the uploaded artifact.
|
||||
If false, hidden files will be excluded from the uploaded artifact.
|
||||
default: 'false'
|
||||
runs:
|
||||
using: 'node16'
|
||||
using: 'node20'
|
||||
main: 'dist/index.js'
|
||||
|
||||
17954
dist/index.js
vendored
17954
dist/index.js
vendored
File diff suppressed because it is too large
Load Diff
17012
package-lock.json
generated
17012
package-lock.json
generated
File diff suppressed because it is too large
Load Diff
34
package.json
34
package.json
@@ -29,25 +29,25 @@
|
||||
},
|
||||
"homepage": "https://github.com/actions/upload-artifact#readme",
|
||||
"dependencies": {
|
||||
"@actions/artifact": "^1.1.0",
|
||||
"@actions/artifact": "^1.1.2",
|
||||
"@actions/core": "^1.10.0",
|
||||
"@actions/glob": "^0.1.0",
|
||||
"@actions/io": "^1.0.2"
|
||||
"@actions/glob": "^0.5.0",
|
||||
"@actions/io": "^1.1.2"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@types/jest": "^25.2.1",
|
||||
"@types/node": "^13.11.1",
|
||||
"@typescript-eslint/parser": "^2.27.0",
|
||||
"@zeit/ncc": "^0.22.1",
|
||||
"concurrently": "^5.1.0",
|
||||
"eslint": "^7.4.0",
|
||||
"eslint-plugin-github": "^4.1.1",
|
||||
"eslint-plugin-jest": "^23.8.2",
|
||||
"glob": "^7.1.6",
|
||||
"jest": "^27.2.5",
|
||||
"jest-circus": "^27.2.5",
|
||||
"prettier": "^2.0.4",
|
||||
"ts-jest": "^27.0.6",
|
||||
"typescript": "^3.8.3"
|
||||
"@types/jest": "^29.2.5",
|
||||
"@types/node": "^18.11.18",
|
||||
"@typescript-eslint/parser": "^5.48.0",
|
||||
"@vercel/ncc": "^0.36.0",
|
||||
"concurrently": "^7.6.0",
|
||||
"eslint": "^8.31.0",
|
||||
"eslint-plugin-github": "^4.6.0",
|
||||
"eslint-plugin-jest": "^27.2.0",
|
||||
"glob": "^8.0.3",
|
||||
"jest": "^29.3.1",
|
||||
"jest-circus": "^29.3.1",
|
||||
"prettier": "^2.8.1",
|
||||
"ts-jest": "^29.0.3",
|
||||
"typescript": "^4.9.4"
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,8 +1,10 @@
|
||||
/* eslint-disable no-unused-vars */
|
||||
export enum Inputs {
|
||||
Name = 'name',
|
||||
Path = 'path',
|
||||
IfNoFilesFound = 'if-no-files-found',
|
||||
RetentionDays = 'retention-days'
|
||||
RetentionDays = 'retention-days',
|
||||
IncludeHiddenFiles = 'include-hidden-files'
|
||||
}
|
||||
|
||||
export enum NoFileOptions {
|
||||
|
||||
@@ -11,6 +11,7 @@ export function getInputs(): UploadInputs {
|
||||
|
||||
const ifNoFilesFound = core.getInput(Inputs.IfNoFilesFound)
|
||||
const noFileBehavior: NoFileOptions = NoFileOptions[ifNoFilesFound]
|
||||
const includeHiddenFiles = core.getBooleanInput(Inputs.IncludeHiddenFiles)
|
||||
|
||||
if (!noFileBehavior) {
|
||||
core.setFailed(
|
||||
@@ -25,7 +26,8 @@ export function getInputs(): UploadInputs {
|
||||
const inputs = {
|
||||
artifactName: name,
|
||||
searchPath: path,
|
||||
ifNoFilesFound: noFileBehavior
|
||||
ifNoFilesFound: noFileBehavior,
|
||||
includeHiddenFiles
|
||||
} as UploadInputs
|
||||
|
||||
const retentionDaysStr = core.getInput(Inputs.RetentionDays)
|
||||
|
||||
@@ -11,11 +11,12 @@ export interface SearchResult {
|
||||
rootDirectory: string
|
||||
}
|
||||
|
||||
function getDefaultGlobOptions(): glob.GlobOptions {
|
||||
function getDefaultGlobOptions(includeHiddenFiles: boolean): glob.GlobOptions {
|
||||
return {
|
||||
followSymbolicLinks: true,
|
||||
implicitDescendants: true,
|
||||
omitBrokenSymbolicLinks: true
|
||||
omitBrokenSymbolicLinks: true,
|
||||
excludeHiddenFiles: !includeHiddenFiles
|
||||
}
|
||||
}
|
||||
|
||||
@@ -80,12 +81,12 @@ function getMultiPathLCA(searchPaths: string[]): string {
|
||||
|
||||
export async function findFilesToUpload(
|
||||
searchPath: string,
|
||||
globOptions?: glob.GlobOptions
|
||||
includeHiddenFiles?: boolean
|
||||
): Promise<SearchResult> {
|
||||
const searchResults: string[] = []
|
||||
const globber = await glob.create(
|
||||
searchPath,
|
||||
globOptions || getDefaultGlobOptions()
|
||||
getDefaultGlobOptions(includeHiddenFiles || false)
|
||||
)
|
||||
const rawSearchResults: string[] = await globber.glob()
|
||||
|
||||
|
||||
@@ -68,8 +68,8 @@ async function run(): Promise<void> {
|
||||
)
|
||||
}
|
||||
}
|
||||
} catch (err) {
|
||||
core.setFailed(err.message)
|
||||
} catch (error) {
|
||||
core.setFailed((error as Error).message)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -20,4 +20,9 @@ export interface UploadInputs {
|
||||
* Duration after which artifact will expire in days
|
||||
*/
|
||||
retentionDays: number
|
||||
|
||||
/**
|
||||
* Whether or not to include hidden files in the artifact
|
||||
*/
|
||||
includeHiddenFiles: boolean
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user