Skip to content

Commit 9b8a266

Browse files
committed
Allow inputs to accept stringified JSON
1 parent 0b90c2e commit 9b8a266

File tree

4 files changed

+92
-45
lines changed

4 files changed

+92
-45
lines changed

README.md

+8
Original file line numberDiff line numberDiff line change
@@ -67,6 +67,14 @@ steps:
6767
!path/**/*.tmp
6868
```
6969
70+
### Upload multiple artifacts using a JSON string
71+
```yaml
72+
- uses: actions/upload-artifact@v2
73+
with:
74+
name: '["my-artifact", "my-artifact-2"]'
75+
path: '["path/to/artifact/1/", "path/to/artifact/2/"]'
76+
```
77+
7078
For supported wildcards along with behavior and documentation, see [@actions/glob](https://github.com/actions/toolkit/tree/main/packages/glob) which is used internally to search for files.
7179
7280
If a wildcard pattern is used, the path hierarchy will be preserved after the first wildcard pattern.

action.yml

+1-2
Original file line numberDiff line numberDiff line change
@@ -3,8 +3,7 @@ description: 'Upload a build artifact that can be used by subsequent workflow st
33
author: 'GitHub'
44
inputs:
55
name:
6-
description: 'Artifact name'
7-
default: 'artifact'
6+
description: 'Artifact name, default is "artifact"'
87
path:
98
description: 'A file, directory or wildcard pattern that describes what to upload'
109
required: true

dist/index.js

+29-19
Original file line numberDiff line numberDiff line change
@@ -6581,12 +6581,16 @@ const constants_1 = __webpack_require__(694);
65816581
function getInputs() {
65826582
const name = core.getInput(constants_1.Inputs.Name);
65836583
const path = core.getInput(constants_1.Inputs.Path, { required: true });
6584-
const searchPath = Array.isArray(path) ? path : [path];
6584+
const searchPath = parseFromJSON(path) || [path];
65856585
const defaultArtifactName = 'artifact';
65866586
// Accepts an individual value or an array as input, if array sizes don't match, use default value instead
6587-
const artifactName = Array.isArray(name)
6588-
? name.concat(new Array(Math.max(0, searchPath.length - name.length)).fill(defaultArtifactName))
6589-
: new Array(searchPath.length).fill(name || defaultArtifactName);
6587+
const artifactName = parseParamaterToArrayFromInput(name, searchPath.length, defaultArtifactName, (defaultInput, index) => {
6588+
const artifactIndexStr = index == 0 ? '' : `_${index + 1}`;
6589+
return `${defaultInput}${artifactIndexStr}`;
6590+
});
6591+
// Accepts an individual value or an array as input
6592+
const retention = core.getInput(constants_1.Inputs.RetentionDays);
6593+
const retentionDays = parseParamaterToArrayFromInput(retention, searchPath.length, undefined, defaultInput => defaultInput).map(parseRetentionDays);
65906594
const ifNoFilesFound = core.getInput(constants_1.Inputs.IfNoFilesFound);
65916595
const noFileBehavior = constants_1.NoFileOptions[ifNoFilesFound];
65926596
if (!noFileBehavior) {
@@ -6595,23 +6599,31 @@ function getInputs() {
65956599
const inputs = {
65966600
artifactName,
65976601
searchPath,
6602+
retentionDays,
65986603
ifNoFilesFound: noFileBehavior
65996604
};
6600-
// Accepts an individual value or an array as input
6601-
const retentionDays = core.getInput(constants_1.Inputs.RetentionDays);
6602-
if (Array.isArray(retentionDays)) {
6603-
// If array sizes don't match, use default value instead
6604-
inputs.retentionDays = retentionDays
6605-
.map(parseRetentionDays)
6606-
.concat(new Array(Math.max(0, searchPath.length - retentionDays.length)).fill(undefined));
6607-
}
6608-
else {
6609-
const retention = parseRetentionDays(retentionDays);
6610-
inputs.retentionDays = new Array(searchPath.length).fill(retention);
6611-
}
66126605
return inputs;
66136606
}
66146607
exports.getInputs = getInputs;
6608+
function parseParamaterToArrayFromInput(input, requiredLength, defaultInput, defaultFunc) {
6609+
// Accepts an individual value or an array as input, if array size doesn't match the required length, fill the rest with a default value
6610+
const inputArray = parseFromJSON(input || '[]');
6611+
if (inputArray) {
6612+
// If a stringified JSON array is provided, use it and concat it with the default when required
6613+
return inputArray.concat(Array.from({ length: Math.max(0, requiredLength - inputArray.length) }, (_, index) => defaultFunc(defaultInput, index)));
6614+
}
6615+
// If a string is provided, fill the array with that value
6616+
return Array.from({ length: Math.max(0, requiredLength) }, (_, index) => defaultFunc(input || defaultInput, index));
6617+
}
6618+
function parseFromJSON(jsonStr) {
6619+
try {
6620+
return JSON.parse(jsonStr);
6621+
}
6622+
catch (_err) {
6623+
// Input wasn't a stringified JSON array (string[]), return undefined to signal an invalid JSON was provided
6624+
}
6625+
return undefined;
6626+
}
66156627
function parseRetentionDays(retentionDaysStr) {
66166628
if (retentionDaysStr) {
66176629
const retentionDays = parseInt(retentionDaysStr);
@@ -6620,9 +6632,7 @@ function parseRetentionDays(retentionDaysStr) {
66206632
}
66216633
return retentionDays;
66226634
}
6623-
else {
6624-
return undefined;
6625-
}
6635+
return undefined;
66266636
}
66276637

66286638

src/input-helper.ts

+54-24
Original file line numberDiff line numberDiff line change
@@ -9,17 +9,28 @@ export function getInputs(): UploadInputs {
99
const name = core.getInput(Inputs.Name)
1010
const path = core.getInput(Inputs.Path, {required: true})
1111

12-
const searchPath = Array.isArray(path) ? path : [path]
12+
const searchPath = parseFromJSON(path) || [path]
1313

1414
const defaultArtifactName = 'artifact'
1515
// Accepts an individual value or an array as input, if array sizes don't match, use default value instead
16-
const artifactName = Array.isArray(name)
17-
? name.concat(
18-
new Array(Math.max(0, searchPath.length - name.length)).fill(
19-
defaultArtifactName
20-
)
21-
)
22-
: new Array(searchPath.length).fill(name || defaultArtifactName)
16+
const artifactName = parseParamaterToArrayFromInput(
17+
name,
18+
searchPath.length,
19+
defaultArtifactName,
20+
(defaultInput, index) => {
21+
const artifactIndexStr = index == 0 ? '' : `_${index + 1}`
22+
return `${defaultInput}${artifactIndexStr}`
23+
}
24+
)
25+
26+
// Accepts an individual value or an array as input
27+
const retention = core.getInput(Inputs.RetentionDays)
28+
const retentionDays = parseParamaterToArrayFromInput(
29+
retention,
30+
searchPath.length,
31+
undefined,
32+
defaultInput => defaultInput
33+
).map(parseRetentionDays)
2334

2435
const ifNoFilesFound = core.getInput(Inputs.IfNoFilesFound)
2536
const noFileBehavior: NoFileOptions = NoFileOptions[ifNoFilesFound]
@@ -37,26 +48,46 @@ export function getInputs(): UploadInputs {
3748
const inputs = {
3849
artifactName,
3950
searchPath,
51+
retentionDays,
4052
ifNoFilesFound: noFileBehavior
4153
} as UploadInputs
4254

43-
// Accepts an individual value or an array as input
44-
const retentionDays = core.getInput(Inputs.RetentionDays)
45-
if (Array.isArray(retentionDays)) {
46-
// If array sizes don't match, use default value instead
47-
inputs.retentionDays = retentionDays
48-
.map(parseRetentionDays)
49-
.concat(
50-
new Array(Math.max(0, searchPath.length - retentionDays.length)).fill(
51-
undefined
52-
)
55+
return inputs
56+
}
57+
58+
function parseParamaterToArrayFromInput(
59+
input: string | undefined,
60+
requiredLength: number,
61+
defaultInput: string | undefined,
62+
defaultFunc: (
63+
defaultInput: string | undefined,
64+
index: number
65+
) => string | undefined
66+
): (string | undefined)[] {
67+
// Accepts an individual value or an array as input, if array size doesn't match the required length, fill the rest with a default value
68+
const inputArray = parseFromJSON(input || '[]')
69+
if (inputArray) {
70+
// If a stringified JSON array is provided, use it and concat it with the default when required
71+
return (<(string | undefined)[]>inputArray).concat(
72+
Array.from(
73+
{length: Math.max(0, requiredLength - inputArray.length)},
74+
(_, index) => defaultFunc(defaultInput, index)
5375
)
54-
} else {
55-
const retention = parseRetentionDays(retentionDays)
56-
inputs.retentionDays = new Array(searchPath.length).fill(retention)
76+
)
5777
}
78+
// If a string is provided, fill the array with that value
79+
return Array.from({length: Math.max(0, requiredLength)}, (_, index) =>
80+
defaultFunc(input || defaultInput, index)
81+
)
82+
}
5883

59-
return inputs
84+
function parseFromJSON(jsonStr: string): string[] | undefined {
85+
try {
86+
return <string[]>JSON.parse(jsonStr)
87+
} catch (_err) {
88+
// Input wasn't a stringified JSON array (string[]), return undefined to signal an invalid JSON was provided
89+
}
90+
return undefined
6091
}
6192

6293
function parseRetentionDays(
@@ -68,7 +99,6 @@ function parseRetentionDays(
6899
core.setFailed('Invalid retention-days')
69100
}
70101
return retentionDays
71-
} else {
72-
return undefined
73102
}
103+
return undefined
74104
}

0 commit comments

Comments
 (0)