mirror of
https://github.com/actions/upload-artifact.git
synced 2026-02-26 05:32:32 +00:00
Support direct file uploads (#764)
* Cache licenses * Bump minimatch to 10.1.1 * Try fixing licenced issues * More licensed fixes * Support direct file uploads * Add CI tests for direct uploads * Use download-artifact@main temporarily * CI: clean up artifacts on successful runs * Use script v8 * Fix some issues with the cleanup * Add unit tests * Clarify naming
This commit is contained in:
150
.github/workflows/test.yml
vendored
150
.github/workflows/test.yml
vendored
@ -10,6 +10,10 @@ on:
|
|||||||
paths-ignore:
|
paths-ignore:
|
||||||
- '**.md'
|
- '**.md'
|
||||||
|
|
||||||
|
permissions:
|
||||||
|
contents: read
|
||||||
|
actions: write
|
||||||
|
|
||||||
jobs:
|
jobs:
|
||||||
build:
|
build:
|
||||||
name: Build
|
name: Build
|
||||||
@ -94,7 +98,7 @@ jobs:
|
|||||||
|
|
||||||
# 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@main
|
||||||
with:
|
with:
|
||||||
name: 'Artifact-A-${{ matrix.runs-on }}'
|
name: 'Artifact-A-${{ matrix.runs-on }}'
|
||||||
path: some/new/path
|
path: some/new/path
|
||||||
@ -114,7 +118,7 @@ jobs:
|
|||||||
|
|
||||||
# Download Artifact #2 and verify the correctness of the content
|
# Download Artifact #2 and verify the correctness of the content
|
||||||
- name: 'Download artifact #2'
|
- name: 'Download artifact #2'
|
||||||
uses: actions/download-artifact@v4
|
uses: actions/download-artifact@main
|
||||||
with:
|
with:
|
||||||
name: 'Artifact-Wildcard-${{ matrix.runs-on }}'
|
name: 'Artifact-Wildcard-${{ matrix.runs-on }}'
|
||||||
path: some/other/path
|
path: some/other/path
|
||||||
@ -135,7 +139,7 @@ jobs:
|
|||||||
|
|
||||||
# Download Artifact #4 and verify the correctness of the content
|
# Download Artifact #4 and verify the correctness of the content
|
||||||
- name: 'Download artifact #4'
|
- name: 'Download artifact #4'
|
||||||
uses: actions/download-artifact@v4
|
uses: actions/download-artifact@main
|
||||||
with:
|
with:
|
||||||
name: 'Multi-Path-Artifact-${{ matrix.runs-on }}'
|
name: 'Multi-Path-Artifact-${{ matrix.runs-on }}'
|
||||||
path: multi/artifact
|
path: multi/artifact
|
||||||
@ -155,7 +159,7 @@ jobs:
|
|||||||
shell: pwsh
|
shell: pwsh
|
||||||
|
|
||||||
- name: 'Download symlinked artifact'
|
- name: 'Download symlinked artifact'
|
||||||
uses: actions/download-artifact@v4
|
uses: actions/download-artifact@main
|
||||||
with:
|
with:
|
||||||
name: 'Symlinked-Artifact-${{ matrix.runs-on }}'
|
name: 'Symlinked-Artifact-${{ matrix.runs-on }}'
|
||||||
path: from/symlink
|
path: from/symlink
|
||||||
@ -196,7 +200,7 @@ jobs:
|
|||||||
|
|
||||||
# Download replaced Artifact #1 and verify the correctness of the content
|
# Download replaced Artifact #1 and verify the correctness of the content
|
||||||
- name: 'Download artifact #1 again'
|
- name: 'Download artifact #1 again'
|
||||||
uses: actions/download-artifact@v4
|
uses: actions/download-artifact@main
|
||||||
with:
|
with:
|
||||||
name: 'Artifact-A-${{ matrix.runs-on }}'
|
name: 'Artifact-A-${{ matrix.runs-on }}'
|
||||||
path: overwrite/some/new/path
|
path: overwrite/some/new/path
|
||||||
@ -213,6 +217,101 @@ jobs:
|
|||||||
Write-Error "File contents of downloaded artifact are incorrect"
|
Write-Error "File contents of downloaded artifact are incorrect"
|
||||||
}
|
}
|
||||||
shell: pwsh
|
shell: pwsh
|
||||||
|
|
||||||
|
# Upload a single file without archiving (direct file upload)
|
||||||
|
- name: 'Create direct upload file'
|
||||||
|
run: echo -n 'direct file upload content' > direct-upload-${{ matrix.runs-on }}.txt
|
||||||
|
shell: bash
|
||||||
|
|
||||||
|
- name: 'Upload direct file artifact'
|
||||||
|
uses: ./
|
||||||
|
with:
|
||||||
|
name: 'Direct-File-${{ matrix.runs-on }}'
|
||||||
|
path: direct-upload-${{ matrix.runs-on }}.txt
|
||||||
|
archive: false
|
||||||
|
|
||||||
|
- name: 'Download direct file artifact'
|
||||||
|
uses: actions/download-artifact@main
|
||||||
|
with:
|
||||||
|
name: direct-upload-${{ matrix.runs-on }}.txt
|
||||||
|
path: direct-download
|
||||||
|
|
||||||
|
- name: 'Verify direct file artifact'
|
||||||
|
run: |
|
||||||
|
$file = "direct-download/direct-upload-${{ matrix.runs-on }}.txt"
|
||||||
|
if(!(Test-Path -path $file))
|
||||||
|
{
|
||||||
|
Write-Error "Expected file does not exist"
|
||||||
|
}
|
||||||
|
if(!((Get-Content $file -Raw).TrimEnd() -ceq "direct file upload content"))
|
||||||
|
{
|
||||||
|
Write-Error "File contents of downloaded artifact are incorrect"
|
||||||
|
}
|
||||||
|
shell: pwsh
|
||||||
|
|
||||||
|
upload-html-report:
|
||||||
|
name: Upload HTML Report
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
|
||||||
|
steps:
|
||||||
|
- name: Checkout
|
||||||
|
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: Compile
|
||||||
|
run: npm run build
|
||||||
|
|
||||||
|
- name: Create HTML report
|
||||||
|
run: |
|
||||||
|
cat > report.html << 'EOF'
|
||||||
|
<!DOCTYPE html>
|
||||||
|
<html lang="en">
|
||||||
|
<head>
|
||||||
|
<meta charset="UTF-8">
|
||||||
|
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||||
|
<title>Artifact Upload Test Report</title>
|
||||||
|
<style>
|
||||||
|
body { font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Helvetica, Arial, sans-serif; max-width: 800px; margin: 40px auto; padding: 0 20px; color: #24292f; }
|
||||||
|
h1 { border-bottom: 1px solid #d0d7de; padding-bottom: 8px; }
|
||||||
|
.success { color: #1a7f37; }
|
||||||
|
.info { background: #ddf4ff; border: 1px solid #54aeff; border-radius: 6px; padding: 12px 16px; margin: 16px 0; }
|
||||||
|
table { border-collapse: collapse; width: 100%; margin: 16px 0; }
|
||||||
|
th, td { border: 1px solid #d0d7de; padding: 8px 12px; text-align: left; }
|
||||||
|
th { background: #f6f8fa; }
|
||||||
|
</style>
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
<h1>Artifact Upload Test Report</h1>
|
||||||
|
<div class="info">
|
||||||
|
<strong>This HTML file was uploaded as a single un-zipped artifact.</strong>
|
||||||
|
If you can see this in the browser, the feature is working correctly!
|
||||||
|
</div>
|
||||||
|
<table>
|
||||||
|
<tr><th>Property</th><th>Value</th></tr>
|
||||||
|
<tr><td>Upload method</td><td><code>archive: false</code></td></tr>
|
||||||
|
<tr><td>Content-Type</td><td><code>text/html</code></td></tr>
|
||||||
|
<tr><td>File</td><td><code>report.html</code></td></tr>
|
||||||
|
</table>
|
||||||
|
<p class="success">✔ Single file upload is working!</p>
|
||||||
|
</body>
|
||||||
|
</html>
|
||||||
|
EOF
|
||||||
|
|
||||||
|
- name: Upload HTML report (no archive)
|
||||||
|
uses: ./
|
||||||
|
with:
|
||||||
|
name: 'test-report'
|
||||||
|
path: report.html
|
||||||
|
archive: false
|
||||||
|
|
||||||
merge:
|
merge:
|
||||||
name: Merge
|
name: Merge
|
||||||
needs: build
|
needs: build
|
||||||
@ -230,7 +329,7 @@ jobs:
|
|||||||
# easier to identify each of the merged artifacts
|
# easier to identify each of the merged artifacts
|
||||||
separate-directories: true
|
separate-directories: true
|
||||||
- name: 'Download merged artifacts'
|
- name: 'Download merged artifacts'
|
||||||
uses: actions/download-artifact@v4
|
uses: actions/download-artifact@main
|
||||||
with:
|
with:
|
||||||
name: merged-artifacts
|
name: merged-artifacts
|
||||||
path: all-merged-artifacts
|
path: all-merged-artifacts
|
||||||
@ -266,7 +365,7 @@ jobs:
|
|||||||
|
|
||||||
# Download merged artifacts and verify the correctness of the content
|
# Download merged artifacts and verify the correctness of the content
|
||||||
- name: 'Download merged artifacts'
|
- name: 'Download merged artifacts'
|
||||||
uses: actions/download-artifact@v4
|
uses: actions/download-artifact@main
|
||||||
with:
|
with:
|
||||||
name: Merged-Artifact-As
|
name: Merged-Artifact-As
|
||||||
path: merged-artifact-a
|
path: merged-artifact-a
|
||||||
@ -290,3 +389,40 @@ jobs:
|
|||||||
}
|
}
|
||||||
shell: pwsh
|
shell: pwsh
|
||||||
|
|
||||||
|
cleanup:
|
||||||
|
name: Cleanup Artifacts
|
||||||
|
needs: [build, merge]
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
|
||||||
|
steps:
|
||||||
|
- name: Delete test artifacts
|
||||||
|
uses: actions/github-script@v8
|
||||||
|
with:
|
||||||
|
script: |
|
||||||
|
const keep = ['report.html'];
|
||||||
|
const owner = context.repo.owner;
|
||||||
|
const repo = context.repo.repo;
|
||||||
|
const runId = context.runId;
|
||||||
|
|
||||||
|
const {data: {artifacts}} = await github.rest.actions.listWorkflowRunArtifacts({
|
||||||
|
owner,
|
||||||
|
repo,
|
||||||
|
run_id: runId
|
||||||
|
});
|
||||||
|
|
||||||
|
for (const a of artifacts) {
|
||||||
|
if (keep.includes(a.name)) {
|
||||||
|
console.log(`Keeping artifact '${a.name}'`);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
try {
|
||||||
|
await github.rest.actions.deleteArtifact({
|
||||||
|
owner,
|
||||||
|
repo,
|
||||||
|
artifact_id: a.id
|
||||||
|
});
|
||||||
|
console.log(`Deleted artifact '${a.name}'`);
|
||||||
|
} catch (err) {
|
||||||
|
console.log(`Could not delete artifact '${a.name}': ${err.message}`);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|||||||
@ -72,6 +72,7 @@ const mockInputs = (
|
|||||||
[Inputs.RetentionDays]: 0,
|
[Inputs.RetentionDays]: 0,
|
||||||
[Inputs.CompressionLevel]: 6,
|
[Inputs.CompressionLevel]: 6,
|
||||||
[Inputs.Overwrite]: false,
|
[Inputs.Overwrite]: false,
|
||||||
|
[Inputs.Archive]: true,
|
||||||
...overrides
|
...overrides
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -273,4 +274,57 @@ describe('upload', () => {
|
|||||||
`Skipping deletion of '${fixtures.artifactName}', it does not exist`
|
`Skipping deletion of '${fixtures.artifactName}', it does not exist`
|
||||||
)
|
)
|
||||||
})
|
})
|
||||||
|
|
||||||
|
test('passes skipArchive when archive is false', async () => {
|
||||||
|
mockInputs({
|
||||||
|
[Inputs.Archive]: false
|
||||||
|
})
|
||||||
|
|
||||||
|
mockFindFilesToUpload.mockResolvedValue({
|
||||||
|
filesToUpload: [fixtures.filesToUpload[0]],
|
||||||
|
rootDirectory: fixtures.rootDirectory
|
||||||
|
})
|
||||||
|
|
||||||
|
await run()
|
||||||
|
|
||||||
|
expect(artifact.default.uploadArtifact).toHaveBeenCalledWith(
|
||||||
|
fixtures.artifactName,
|
||||||
|
[fixtures.filesToUpload[0]],
|
||||||
|
fixtures.rootDirectory,
|
||||||
|
{compressionLevel: 6, skipArchive: true}
|
||||||
|
)
|
||||||
|
})
|
||||||
|
|
||||||
|
test('does not pass skipArchive when archive is true', async () => {
|
||||||
|
mockInputs({
|
||||||
|
[Inputs.Archive]: true
|
||||||
|
})
|
||||||
|
|
||||||
|
mockFindFilesToUpload.mockResolvedValue({
|
||||||
|
filesToUpload: [fixtures.filesToUpload[0]],
|
||||||
|
rootDirectory: fixtures.rootDirectory
|
||||||
|
})
|
||||||
|
|
||||||
|
await run()
|
||||||
|
|
||||||
|
expect(artifact.default.uploadArtifact).toHaveBeenCalledWith(
|
||||||
|
fixtures.artifactName,
|
||||||
|
[fixtures.filesToUpload[0]],
|
||||||
|
fixtures.rootDirectory,
|
||||||
|
{compressionLevel: 6}
|
||||||
|
)
|
||||||
|
})
|
||||||
|
|
||||||
|
test('fails when archive is false and multiple files are provided', async () => {
|
||||||
|
mockInputs({
|
||||||
|
[Inputs.Archive]: false
|
||||||
|
})
|
||||||
|
|
||||||
|
await run()
|
||||||
|
|
||||||
|
expect(core.setFailed).toHaveBeenCalledWith(
|
||||||
|
`When 'archive' is set to false, only a single file can be uploaded. Found ${fixtures.filesToUpload.length} files to upload.`
|
||||||
|
)
|
||||||
|
expect(artifact.default.uploadArtifact).not.toHaveBeenCalled()
|
||||||
|
})
|
||||||
})
|
})
|
||||||
|
|||||||
10
action.yml
10
action.yml
@ -3,10 +3,10 @@ description: 'Upload a build artifact that can be used by subsequent workflow st
|
|||||||
author: 'GitHub'
|
author: 'GitHub'
|
||||||
inputs:
|
inputs:
|
||||||
name:
|
name:
|
||||||
description: 'Artifact name'
|
description: 'Artifact name. If the `archive` input is `false`, the name of the file uploaded will be the artifact name.'
|
||||||
default: 'artifact'
|
default: 'artifact'
|
||||||
path:
|
path:
|
||||||
description: 'A file, directory or wildcard pattern that describes what to upload'
|
description: 'A file, directory or wildcard pattern that describes what to upload.'
|
||||||
required: true
|
required: true
|
||||||
if-no-files-found:
|
if-no-files-found:
|
||||||
description: >
|
description: >
|
||||||
@ -45,6 +45,12 @@ inputs:
|
|||||||
If true, hidden files will be included in the artifact.
|
If true, hidden files will be included in the artifact.
|
||||||
If false, hidden files will be excluded from the artifact.
|
If false, hidden files will be excluded from the artifact.
|
||||||
default: 'false'
|
default: 'false'
|
||||||
|
archive:
|
||||||
|
description: >
|
||||||
|
If true, the artifact will be archived (zipped) before uploading.
|
||||||
|
If false, the artifact will be uploaded as-is without archiving.
|
||||||
|
When `archive` is `false`, only a single file can be uploaded. The name of the file will be used as the artifact name (ignoring the `name` parameter).
|
||||||
|
default: 'true'
|
||||||
|
|
||||||
outputs:
|
outputs:
|
||||||
artifact-id:
|
artifact-id:
|
||||||
|
|||||||
13
dist/upload/index.js
vendored
13
dist/upload/index.js
vendored
@ -130457,6 +130457,7 @@ var Inputs;
|
|||||||
Inputs["CompressionLevel"] = "compression-level";
|
Inputs["CompressionLevel"] = "compression-level";
|
||||||
Inputs["Overwrite"] = "overwrite";
|
Inputs["Overwrite"] = "overwrite";
|
||||||
Inputs["IncludeHiddenFiles"] = "include-hidden-files";
|
Inputs["IncludeHiddenFiles"] = "include-hidden-files";
|
||||||
|
Inputs["Archive"] = "archive";
|
||||||
})(Inputs || (Inputs = {}));
|
})(Inputs || (Inputs = {}));
|
||||||
var NoFileOptions;
|
var NoFileOptions;
|
||||||
(function (NoFileOptions) {
|
(function (NoFileOptions) {
|
||||||
@ -130485,6 +130486,7 @@ function getInputs() {
|
|||||||
const path = getInput(Inputs.Path, { required: true });
|
const path = getInput(Inputs.Path, { required: true });
|
||||||
const overwrite = getBooleanInput(Inputs.Overwrite);
|
const overwrite = getBooleanInput(Inputs.Overwrite);
|
||||||
const includeHiddenFiles = getBooleanInput(Inputs.IncludeHiddenFiles);
|
const includeHiddenFiles = getBooleanInput(Inputs.IncludeHiddenFiles);
|
||||||
|
const archive = getBooleanInput(Inputs.Archive);
|
||||||
const ifNoFilesFound = getInput(Inputs.IfNoFilesFound);
|
const ifNoFilesFound = getInput(Inputs.IfNoFilesFound);
|
||||||
const noFileBehavior = NoFileOptions[ifNoFilesFound];
|
const noFileBehavior = NoFileOptions[ifNoFilesFound];
|
||||||
if (!noFileBehavior) {
|
if (!noFileBehavior) {
|
||||||
@ -130495,7 +130497,8 @@ function getInputs() {
|
|||||||
searchPath: path,
|
searchPath: path,
|
||||||
ifNoFilesFound: noFileBehavior,
|
ifNoFilesFound: noFileBehavior,
|
||||||
overwrite: overwrite,
|
overwrite: overwrite,
|
||||||
includeHiddenFiles: includeHiddenFiles
|
includeHiddenFiles: includeHiddenFiles,
|
||||||
|
archive: archive
|
||||||
};
|
};
|
||||||
const retentionDaysStr = getInput(Inputs.RetentionDays);
|
const retentionDaysStr = getInput(Inputs.RetentionDays);
|
||||||
if (retentionDaysStr) {
|
if (retentionDaysStr) {
|
||||||
@ -130576,6 +130579,11 @@ async function run() {
|
|||||||
const s = searchResult.filesToUpload.length === 1 ? '' : 's';
|
const s = searchResult.filesToUpload.length === 1 ? '' : 's';
|
||||||
info(`With the provided path, there will be ${searchResult.filesToUpload.length} file${s} uploaded`);
|
info(`With the provided path, there will be ${searchResult.filesToUpload.length} file${s} uploaded`);
|
||||||
core_debug(`Root artifact directory is ${searchResult.rootDirectory}`);
|
core_debug(`Root artifact directory is ${searchResult.rootDirectory}`);
|
||||||
|
// Validate that only a single file is uploaded when archive is false
|
||||||
|
if (!inputs.archive && searchResult.filesToUpload.length > 1) {
|
||||||
|
setFailed(`When 'archive' is set to false, only a single file can be uploaded. Found ${searchResult.filesToUpload.length} files to upload.`);
|
||||||
|
return;
|
||||||
|
}
|
||||||
if (inputs.overwrite) {
|
if (inputs.overwrite) {
|
||||||
await deleteArtifactIfExists(inputs.artifactName);
|
await deleteArtifactIfExists(inputs.artifactName);
|
||||||
}
|
}
|
||||||
@ -130586,6 +130594,9 @@ async function run() {
|
|||||||
if (typeof inputs.compressionLevel !== 'undefined') {
|
if (typeof inputs.compressionLevel !== 'undefined') {
|
||||||
options.compressionLevel = inputs.compressionLevel;
|
options.compressionLevel = inputs.compressionLevel;
|
||||||
}
|
}
|
||||||
|
if (!inputs.archive) {
|
||||||
|
options.skipArchive = true;
|
||||||
|
}
|
||||||
await upload_artifact_uploadArtifact(inputs.artifactName, searchResult.filesToUpload, searchResult.rootDirectory, options);
|
await upload_artifact_uploadArtifact(inputs.artifactName, searchResult.filesToUpload, searchResult.rootDirectory, options);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
2
package-lock.json
generated
2
package-lock.json
generated
@ -9,7 +9,7 @@
|
|||||||
"version": "7.0.0",
|
"version": "7.0.0",
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@actions/artifact": "^6.1.0",
|
"@actions/artifact": "^6.2.0",
|
||||||
"@actions/core": "^3.0.0",
|
"@actions/core": "^3.0.0",
|
||||||
"@actions/github": "^9.0.0",
|
"@actions/github": "^9.0.0",
|
||||||
"@actions/glob": "^0.6.1",
|
"@actions/glob": "^0.6.1",
|
||||||
|
|||||||
@ -33,7 +33,7 @@
|
|||||||
"node": ">=24"
|
"node": ">=24"
|
||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@actions/artifact": "^6.1.0",
|
"@actions/artifact": "^6.2.0",
|
||||||
"@actions/core": "^3.0.0",
|
"@actions/core": "^3.0.0",
|
||||||
"@actions/github": "^9.0.0",
|
"@actions/github": "^9.0.0",
|
||||||
"@actions/glob": "^0.6.1",
|
"@actions/glob": "^0.6.1",
|
||||||
|
|||||||
@ -6,7 +6,8 @@ export enum Inputs {
|
|||||||
RetentionDays = 'retention-days',
|
RetentionDays = 'retention-days',
|
||||||
CompressionLevel = 'compression-level',
|
CompressionLevel = 'compression-level',
|
||||||
Overwrite = 'overwrite',
|
Overwrite = 'overwrite',
|
||||||
IncludeHiddenFiles = 'include-hidden-files'
|
IncludeHiddenFiles = 'include-hidden-files',
|
||||||
|
Archive = 'archive'
|
||||||
}
|
}
|
||||||
|
|
||||||
export enum NoFileOptions {
|
export enum NoFileOptions {
|
||||||
|
|||||||
@ -10,6 +10,7 @@ export function getInputs(): UploadInputs {
|
|||||||
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 includeHiddenFiles = core.getBooleanInput(Inputs.IncludeHiddenFiles)
|
||||||
|
const archive = core.getBooleanInput(Inputs.Archive)
|
||||||
|
|
||||||
const ifNoFilesFound = core.getInput(Inputs.IfNoFilesFound)
|
const ifNoFilesFound = core.getInput(Inputs.IfNoFilesFound)
|
||||||
const noFileBehavior: NoFileOptions = NoFileOptions[ifNoFilesFound]
|
const noFileBehavior: NoFileOptions = NoFileOptions[ifNoFilesFound]
|
||||||
@ -29,7 +30,8 @@ export function getInputs(): UploadInputs {
|
|||||||
searchPath: path,
|
searchPath: path,
|
||||||
ifNoFilesFound: noFileBehavior,
|
ifNoFilesFound: noFileBehavior,
|
||||||
overwrite: overwrite,
|
overwrite: overwrite,
|
||||||
includeHiddenFiles: includeHiddenFiles
|
includeHiddenFiles: includeHiddenFiles,
|
||||||
|
archive: archive
|
||||||
} as UploadInputs
|
} as UploadInputs
|
||||||
|
|
||||||
const retentionDaysStr = core.getInput(Inputs.RetentionDays)
|
const retentionDaysStr = core.getInput(Inputs.RetentionDays)
|
||||||
|
|||||||
@ -57,6 +57,14 @@ export async function run(): Promise<void> {
|
|||||||
)
|
)
|
||||||
core.debug(`Root artifact directory is ${searchResult.rootDirectory}`)
|
core.debug(`Root artifact directory is ${searchResult.rootDirectory}`)
|
||||||
|
|
||||||
|
// Validate that only a single file is uploaded when archive is false
|
||||||
|
if (!inputs.archive && searchResult.filesToUpload.length > 1) {
|
||||||
|
core.setFailed(
|
||||||
|
`When 'archive' is set to false, only a single file can be uploaded. Found ${searchResult.filesToUpload.length} files to upload.`
|
||||||
|
)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
if (inputs.overwrite) {
|
if (inputs.overwrite) {
|
||||||
await deleteArtifactIfExists(inputs.artifactName)
|
await deleteArtifactIfExists(inputs.artifactName)
|
||||||
}
|
}
|
||||||
@ -70,6 +78,10 @@ export async function run(): Promise<void> {
|
|||||||
options.compressionLevel = inputs.compressionLevel
|
options.compressionLevel = inputs.compressionLevel
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (!inputs.archive) {
|
||||||
|
options.skipArchive = true
|
||||||
|
}
|
||||||
|
|
||||||
await uploadArtifact(
|
await uploadArtifact(
|
||||||
inputs.artifactName,
|
inputs.artifactName,
|
||||||
searchResult.filesToUpload,
|
searchResult.filesToUpload,
|
||||||
|
|||||||
@ -35,4 +35,10 @@ export interface UploadInputs {
|
|||||||
* Whether or not to include hidden files in the artifact
|
* Whether or not to include hidden files in the artifact
|
||||||
*/
|
*/
|
||||||
includeHiddenFiles: boolean
|
includeHiddenFiles: boolean
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Whether or not to archive (zip) the artifact before uploading.
|
||||||
|
* When false, only a single file can be uploaded.
|
||||||
|
*/
|
||||||
|
archive: boolean
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user