1
0
Fork 0
mirror of https://github.com/actions/upload-artifact synced 2024-12-22 14:32:44 +00:00

Add new option to specify behavior if no files found (#104)

* Add new option to specify behavior if no files found
This commit is contained in:
Konrad Pabjan 2020-07-31 17:27:37 +02:00 committed by GitHub
parent 5f948bc1f0
commit 5ba29a7d5b
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
7 changed files with 188 additions and 25 deletions

View file

@ -88,6 +88,18 @@ Relative and absolute file paths are both allowed. Relative paths are rooted aga
The [@actions/artifact](https://github.com/actions/toolkit/tree/main/packages/artifact) package is used internally to handle most of the logic around uploading an artifact. There is extra documentation around upload limitations and behavior in the toolkit repo that is worth checking out. The [@actions/artifact](https://github.com/actions/toolkit/tree/main/packages/artifact) package is used internally to handle most of the logic around uploading an artifact. There is extra documentation around upload limitations and behavior in the toolkit repo that is worth checking out.
### Customization if no files are found
If a path (or paths), result in no files being found for the artifact, the action will succeed but print out a warning. In certain scenarios it may be desirable to fail the action or suppress the warning. The `if-no-files-found` option allows you to customize the behavior of the action if no files are found.
```yaml
- uses: actions/upload-artifact@v2
with:
name: my-artifact
path: path/to/artifact/
if-no-files-found: error # 'warn' or 'ignore' are also available, defaults to `warn`
```
### Conditional Artifact Upload ### Conditional Artifact Upload
To upload artifacts only when the previous step of a job failed, use [`if: failure()`](https://help.github.com/en/articles/contexts-and-expression-syntax-for-github-actions#job-status-check-functions): To upload artifacts only when the previous step of a job failed, use [`if: failure()`](https://help.github.com/en/articles/contexts-and-expression-syntax-for-github-actions#job-status-check-functions):

View file

@ -4,10 +4,19 @@ author: 'GitHub'
inputs: inputs:
name: name:
description: 'Artifact name' description: 'Artifact name'
required: false 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:
description: >
The desired behavior if no files are found using the provided path.
Available Options:
warn: Output a warning but do not fail the action
error: Fail the action with an error message
ignore: Do not output any warnings or errors, the action does not fail
default: 'warn'
runs: runs:
using: 'node12' using: 'node12'
main: 'dist/index.js' main: 'dist/index.js'

85
dist/index.js vendored
View file

@ -3987,25 +3987,39 @@ var __importStar = (this && this.__importStar) || function (mod) {
Object.defineProperty(exports, "__esModule", { value: true }); Object.defineProperty(exports, "__esModule", { value: true });
const core = __importStar(__webpack_require__(470)); const core = __importStar(__webpack_require__(470));
const artifact_1 = __webpack_require__(214); const artifact_1 = __webpack_require__(214);
const constants_1 = __webpack_require__(694);
const search_1 = __webpack_require__(575); const search_1 = __webpack_require__(575);
const input_helper_1 = __webpack_require__(583);
const constants_1 = __webpack_require__(694);
function run() { function run() {
return __awaiter(this, void 0, void 0, function* () { return __awaiter(this, void 0, void 0, function* () {
try { try {
const name = core.getInput(constants_1.Inputs.Name, { required: false }); const inputs = input_helper_1.getInputs();
const path = core.getInput(constants_1.Inputs.Path, { required: true }); const searchResult = yield search_1.findFilesToUpload(inputs.searchPath);
const searchResult = yield search_1.findFilesToUpload(path);
if (searchResult.filesToUpload.length === 0) { if (searchResult.filesToUpload.length === 0) {
core.warning(`No files were found for the provided path: ${path}. No artifacts will be uploaded.`); // No files were found, different use cases warrant different types of behavior if nothing is found
switch (inputs.ifNoFilesFound) {
case constants_1.NoFileOptions.warn: {
core.warning(`No files were found with the provided path: ${inputs.searchPath}. No artifacts will be uploaded.`);
break;
}
case constants_1.NoFileOptions.error: {
core.setFailed(`No files were found with the provided path: ${inputs.searchPath}. No artifacts will be uploaded.`);
break;
}
case constants_1.NoFileOptions.ignore: {
core.info(`No files were found with the provided path: ${inputs.searchPath}. No artifacts will be uploaded.`);
break;
}
}
} }
else { else {
core.info(`With the provided path, there will be ${searchResult.filesToUpload.length} files uploaded`); core.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}`);
const artifactClient = artifact_1.create(); const artifactClient = artifact_1.create();
const options = { const options = {
continueOnError: false continueOnError: false
}; };
const uploadResponse = yield artifactClient.uploadArtifact(name || constants_1.getDefaultArtifactName(), searchResult.filesToUpload, searchResult.rootDirectory, options); const uploadResponse = yield artifactClient.uploadArtifact(inputs.artifactName, searchResult.filesToUpload, searchResult.rootDirectory, options);
if (uploadResponse.failedItems.length > 0) { if (uploadResponse.failedItems.length > 0) {
core.setFailed(`An error was encountered when uploading ${uploadResponse.artifactName}. There were ${uploadResponse.failedItems.length} items that failed to upload.`); core.setFailed(`An error was encountered when uploading ${uploadResponse.artifactName}. There were ${uploadResponse.failedItems.length} items that failed to upload.`);
} }
@ -6335,6 +6349,43 @@ function findFilesToUpload(searchPath, globOptions) {
exports.findFilesToUpload = findFilesToUpload; exports.findFilesToUpload = findFilesToUpload;
/***/ }),
/***/ 583:
/***/ (function(__unusedmodule, exports, __webpack_require__) {
"use strict";
var __importStar = (this && this.__importStar) || function (mod) {
if (mod && mod.__esModule) return mod;
var result = {};
if (mod != null) for (var k in mod) if (Object.hasOwnProperty.call(mod, k)) result[k] = mod[k];
result["default"] = mod;
return result;
};
Object.defineProperty(exports, "__esModule", { value: true });
const core = __importStar(__webpack_require__(470));
const constants_1 = __webpack_require__(694);
/**
* Helper to get all the inputs for the action
*/
function getInputs() {
const name = core.getInput(constants_1.Inputs.Name);
const path = core.getInput(constants_1.Inputs.Path, { required: true });
const ifNoFilesFound = core.getInput(constants_1.Inputs.IfNoFilesFound);
const noFileBehavior = constants_1.NoFileOptions[ifNoFilesFound];
if (!noFileBehavior) {
core.setFailed(`Unrecognized ${constants_1.Inputs.IfNoFilesFound} input. Provided: ${ifNoFilesFound}. Available options: ${Object.keys(constants_1.NoFileOptions)}`);
}
return {
artifactName: name,
searchPath: path,
ifNoFilesFound: noFileBehavior
};
}
exports.getInputs = getInputs;
/***/ }), /***/ }),
/***/ 590: /***/ 590:
@ -7249,11 +7300,23 @@ var Inputs;
(function (Inputs) { (function (Inputs) {
Inputs["Name"] = "name"; Inputs["Name"] = "name";
Inputs["Path"] = "path"; Inputs["Path"] = "path";
Inputs["IfNoFilesFound"] = "if-no-files-found";
})(Inputs = exports.Inputs || (exports.Inputs = {})); })(Inputs = exports.Inputs || (exports.Inputs = {}));
function getDefaultArtifactName() { var NoFileOptions;
return 'artifact'; (function (NoFileOptions) {
} /**
exports.getDefaultArtifactName = getDefaultArtifactName; * Default. Output a warning but do not fail the action
*/
NoFileOptions["warn"] = "warn";
/**
* Fail the action with an error message
*/
NoFileOptions["error"] = "error";
/**
* Do not output any warnings or errors, the action does not fail
*/
NoFileOptions["ignore"] = "ignore";
})(NoFileOptions = exports.NoFileOptions || (exports.NoFileOptions = {}));
/***/ }), /***/ }),

View file

@ -1,8 +1,22 @@
export enum Inputs { export enum Inputs {
Name = 'name', Name = 'name',
Path = 'path' Path = 'path',
IfNoFilesFound = 'if-no-files-found'
} }
export function getDefaultArtifactName(): string { export enum NoFileOptions {
return 'artifact' /**
* Default. Output a warning but do not fail the action
*/
warn = 'warn',
/**
* Fail the action with an error message
*/
error = 'error',
/**
* Do not output any warnings or errors, the action does not fail
*/
ignore = 'ignore'
} }

30
src/input-helper.ts Normal file
View file

@ -0,0 +1,30 @@
import * as core from '@actions/core'
import {Inputs, NoFileOptions} from './constants'
import {UploadInputs} from './upload-inputs'
/**
* Helper to get all the inputs for the action
*/
export function getInputs(): UploadInputs {
const name = core.getInput(Inputs.Name)
const path = core.getInput(Inputs.Path, {required: true})
const ifNoFilesFound = core.getInput(Inputs.IfNoFilesFound)
const noFileBehavior: NoFileOptions = NoFileOptions[ifNoFilesFound]
if (!noFileBehavior) {
core.setFailed(
`Unrecognized ${
Inputs.IfNoFilesFound
} input. Provided: ${ifNoFilesFound}. Available options: ${Object.keys(
NoFileOptions
)}`
)
}
return {
artifactName: name,
searchPath: path,
ifNoFilesFound: noFileBehavior
}
}

View file

@ -1,21 +1,38 @@
import * as core from '@actions/core' import * as core from '@actions/core'
import {create, UploadOptions} from '@actions/artifact' import {create, UploadOptions} from '@actions/artifact'
import {Inputs, getDefaultArtifactName} from './constants'
import {findFilesToUpload} from './search' import {findFilesToUpload} from './search'
import {getInputs} from './input-helper'
import {NoFileOptions} from './constants'
async function run(): Promise<void> { async function run(): Promise<void> {
try { try {
const name = core.getInput(Inputs.Name, {required: false}) const inputs = getInputs()
const path = core.getInput(Inputs.Path, {required: true}) const searchResult = await findFilesToUpload(inputs.searchPath)
const searchResult = await findFilesToUpload(path)
if (searchResult.filesToUpload.length === 0) { if (searchResult.filesToUpload.length === 0) {
core.warning( // No files were found, different use cases warrant different types of behavior if nothing is found
`No files were found for the provided path: ${path}. No artifacts will be uploaded.` switch (inputs.ifNoFilesFound) {
) case NoFileOptions.warn: {
core.warning(
`No files were found with the provided path: ${inputs.searchPath}. No artifacts will be uploaded.`
)
break
}
case NoFileOptions.error: {
core.setFailed(
`No files were found with the provided path: ${inputs.searchPath}. No artifacts will be uploaded.`
)
break
}
case NoFileOptions.ignore: {
core.info(
`No files were found with the provided path: ${inputs.searchPath}. No artifacts will be uploaded.`
)
break
}
}
} else { } else {
core.info( core.info(
`With the provided path, there will be ${searchResult.filesToUpload.length} files uploaded` `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}`)
@ -24,7 +41,7 @@ async function run(): Promise<void> {
continueOnError: false continueOnError: false
} }
const uploadResponse = await artifactClient.uploadArtifact( const uploadResponse = await artifactClient.uploadArtifact(
name || getDefaultArtifactName(), inputs.artifactName,
searchResult.filesToUpload, searchResult.filesToUpload,
searchResult.rootDirectory, searchResult.rootDirectory,
options options

18
src/upload-inputs.ts Normal file
View file

@ -0,0 +1,18 @@
import {NoFileOptions} from './constants'
export interface UploadInputs {
/**
* The name of the artifact that will be uploaded
*/
artifactName: string
/**
* The search path used to describe what to upload as part of the artifact
*/
searchPath: string
/**
* The desired behavior if no files are found with the provided search path
*/
ifNoFilesFound: NoFileOptions
}