Support direct file uploads

danwkennedy/direct-uploads
Daniel Kennedy 4 weeks ago
parent 4177a106a5
commit 6b68470975

@ -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
} }

@ -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.
default: 'true'
outputs: outputs:
artifact-id: artifact-id:

@ -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

@ -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
} }

Loading…
Cancel
Save