Compare commits

..

10 Commits

Author SHA1 Message Date
Daniel Kennedy
2aa2914a67 eslint: don't allow common-js imports 2026-02-25 13:49:28 -05:00
Daniel Kennedy
c36c5fbf26 More licensed fixes 2026-02-25 13:44:14 -05:00
Daniel Kennedy
8c63b6d07a Try fixing licenced issues 2026-02-25 13:30:34 -05:00
Daniel Kennedy
0508a90968 Bump minimatch to 10.1.1 2026-02-25 13:24:55 -05:00
Daniel Kennedy
a2008cd1d8 Cache licenses 2026-02-25 13:18:03 -05:00
Daniel Kennedy
7d7cf5541f Bump the package version 2026-02-25 13:13:12 -05:00
Daniel Kennedy
56b3ba9990 Fix linting issues 2026-02-25 13:12:50 -05:00
Daniel Kennedy
d025a8c768 Push build files 2026-02-25 13:08:22 -05:00
Daniel Kennedy
15be44e9f1 CI: bump node versions 2026-02-25 13:05:51 -05:00
Daniel Kennedy
f119f587c2 Upgrade the module to ESM and bump dependencies 2026-02-25 12:57:27 -05:00
10 changed files with 14 additions and 242 deletions

View File

@@ -10,10 +10,6 @@ on:
paths-ignore: paths-ignore:
- '**.md' - '**.md'
permissions:
contents: read
actions: write
jobs: jobs:
build: build:
name: Build name: Build
@@ -98,7 +94,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@main uses: actions/download-artifact@v4
with: with:
name: 'Artifact-A-${{ matrix.runs-on }}' name: 'Artifact-A-${{ matrix.runs-on }}'
path: some/new/path path: some/new/path
@@ -118,7 +114,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@main uses: actions/download-artifact@v4
with: with:
name: 'Artifact-Wildcard-${{ matrix.runs-on }}' name: 'Artifact-Wildcard-${{ matrix.runs-on }}'
path: some/other/path path: some/other/path
@@ -139,7 +135,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@main uses: actions/download-artifact@v4
with: with:
name: 'Multi-Path-Artifact-${{ matrix.runs-on }}' name: 'Multi-Path-Artifact-${{ matrix.runs-on }}'
path: multi/artifact path: multi/artifact
@@ -159,7 +155,7 @@ jobs:
shell: pwsh shell: pwsh
- name: 'Download symlinked artifact' - name: 'Download symlinked artifact'
uses: actions/download-artifact@main uses: actions/download-artifact@v4
with: with:
name: 'Symlinked-Artifact-${{ matrix.runs-on }}' name: 'Symlinked-Artifact-${{ matrix.runs-on }}'
path: from/symlink path: from/symlink
@@ -200,7 +196,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@main uses: actions/download-artifact@v4
with: with:
name: 'Artifact-A-${{ matrix.runs-on }}' name: 'Artifact-A-${{ matrix.runs-on }}'
path: overwrite/some/new/path path: overwrite/some/new/path
@@ -217,101 +213,6 @@ 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">&#10004; 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
@@ -329,7 +230,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@main uses: actions/download-artifact@v4
with: with:
name: merged-artifacts name: merged-artifacts
path: all-merged-artifacts path: all-merged-artifacts
@@ -365,7 +266,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@main uses: actions/download-artifact@v4
with: with:
name: Merged-Artifact-As name: Merged-Artifact-As
path: merged-artifact-a path: merged-artifact-a
@@ -389,40 +290,3 @@ 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}`);
}
}

View File

@@ -72,7 +72,6 @@ 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
} }
@@ -274,57 +273,4 @@ 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()
})
}) })

View File

@@ -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. If the `archive` input is `false`, the name of the file uploaded will be the artifact name.' description: '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,12 +45,6 @@ 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
View File

@@ -130457,7 +130457,6 @@ 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) {
@@ -130486,7 +130485,6 @@ 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) {
@@ -130497,8 +130495,7 @@ 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) {
@@ -130579,11 +130576,6 @@ 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);
} }
@@ -130594,9 +130586,6 @@ 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
View File

@@ -9,7 +9,7 @@
"version": "7.0.0", "version": "7.0.0",
"license": "MIT", "license": "MIT",
"dependencies": { "dependencies": {
"@actions/artifact": "^6.2.0", "@actions/artifact": "^6.1.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",

View File

@@ -33,7 +33,7 @@
"node": ">=24" "node": ">=24"
}, },
"dependencies": { "dependencies": {
"@actions/artifact": "^6.2.0", "@actions/artifact": "^6.1.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",

View File

@@ -6,8 +6,7 @@ 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 {

View File

@@ -10,7 +10,6 @@ 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]
@@ -30,8 +29,7 @@ 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)

View File

@@ -57,14 +57,6 @@ 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)
} }
@@ -78,10 +70,6 @@ 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,

View File

@@ -35,10 +35,4 @@ 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
} }