Skip to content

Commit

Permalink
Use comma-separated format for enum array inputs (#30)
Browse files Browse the repository at this point in the history
  • Loading branch information
anthony-c-martin authored Sep 30, 2024
1 parent 5ce6c93 commit c1ed178
Show file tree
Hide file tree
Showing 7 changed files with 219 additions and 67 deletions.
42 changes: 18 additions & 24 deletions dist/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -58631,10 +58631,10 @@ var __importStar = (this && this.__importStar) || function (mod) {
return result;
};
Object.defineProperty(exports, "__esModule", ({ value: true }));
exports.getRequiredEnumInput = getRequiredEnumInput;
exports.getOptionalEnumInput = getOptionalEnumInput;
exports.getRequiredStringInput = getRequiredStringInput;
exports.getOptionalStringInput = getOptionalStringInput;
exports.getRequiredEnumInput = getRequiredEnumInput;
exports.getOptionalEnumInput = getOptionalEnumInput;
exports.getOptionalFilePath = getOptionalFilePath;
exports.getOptionalBooleanInput = getOptionalBooleanInput;
exports.getOptionalStringArrayInput = getOptionalStringArrayInput;
Expand All @@ -58645,18 +58645,18 @@ exports.getOptionalStringDictionaryInput = getOptionalStringDictionaryInput;
// Licensed under the MIT License.
const core = __importStar(__nccwpck_require__(2186));
const file_1 = __nccwpck_require__(8922);
function getRequiredEnumInput(inputName, allowedValues) {
return getInput(inputName, allowedValues, true);
}
function getOptionalEnumInput(inputName, allowedValues) {
return getInput(inputName, allowedValues, false);
}
function getRequiredStringInput(inputName) {
return getInput(inputName, undefined, true);
}
function getOptionalStringInput(inputName) {
return getInput(inputName, undefined, false);
}
function getRequiredEnumInput(inputName, allowedValues) {
return getInput(inputName, allowedValues, true);
}
function getOptionalEnumInput(inputName, allowedValues) {
return getInput(inputName, allowedValues, false);
}
function getOptionalFilePath(inputName) {
const input = getOptionalStringInput(inputName);
if (!input) {
Expand All @@ -58681,19 +58681,7 @@ function getOptionalBooleanInput(inputName) {
}
function getOptionalStringArrayInput(inputName) {
const inputString = getOptionalStringInput(inputName);
if (!inputString) {
return [];
}
const input = tryParseJson(inputString);
if (!Array.isArray(input)) {
throw new Error(`Action input '${inputName}' must be a JSON string array`);
}
input.forEach(val => {
if (typeof val !== "string") {
throw new Error(`Action input '${inputName}' must be a JSON string array`);
}
});
return input;
return inputString ? parseCommaSeparated(inputString) : [];
}
function getOptionalEnumArrayInput(inputName, allowedValues) {
const values = getOptionalStringArrayInput(inputName);
Expand All @@ -58712,21 +58700,21 @@ function getOptionalDictionaryInput(inputName) {
}
const input = tryParseJson(inputString);
if (typeof input !== "object") {
throw new Error(`Action input '${inputName}' must be a dictionary`);
throw new Error(`Action input '${inputName}' must be a valid JSON object`);
}
return input;
}
function getOptionalStringDictionaryInput(inputName) {
const input = getOptionalDictionaryInput(inputName);
Object.keys(input).forEach(key => {
if (typeof input[key] !== "string") {
throw new Error(`Action input '${inputName}' must be a dictionary of string values`);
throw new Error(`Action input '${inputName}' must be a valid JSON object containing only string values`);
}
});
return input;
}
function getInput(inputName, allowedValues, throwOnMissing = true) {
const inputValue = core.getInput(inputName);
const inputValue = core.getInput(inputName)?.trim();
if (!inputValue) {
if (throwOnMissing) {
throw new Error(`Action input '${inputName}' is required but not provided`);
Expand All @@ -58748,6 +58736,12 @@ function tryParseJson(value) {
return undefined;
}
}
function parseCommaSeparated(value) {
return value
.split(",")
.map(val => val.trim())
.filter(val => val.length > 0);
}


/***/ }),
Expand Down
2 changes: 1 addition & 1 deletion dist/index.js.map

Large diffs are not rendered by default.

47 changes: 19 additions & 28 deletions src/helpers/input.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,14 @@ import * as core from "@actions/core";

import { resolvePath } from "./file";

export function getRequiredStringInput(inputName: string): string {
return getInput(inputName, undefined, true) as string;
}

export function getOptionalStringInput(inputName: string): string | undefined {
return getInput(inputName, undefined, false);
}

export function getRequiredEnumInput<TEnum extends string>(
inputName: string,
allowedValues: TEnum[],
Expand All @@ -18,14 +26,6 @@ export function getOptionalEnumInput<TEnum extends string>(
return getInput(inputName, allowedValues, false) as TEnum | undefined;
}

export function getRequiredStringInput(inputName: string): string {
return getInput(inputName, undefined, true) as string;
}

export function getOptionalStringInput(inputName: string): string | undefined {
return getInput(inputName, undefined, false);
}

export function getOptionalFilePath(inputName: string): string | undefined {
const input = getOptionalStringInput(inputName);
if (!input) {
Expand All @@ -52,24 +52,8 @@ export function getOptionalBooleanInput(inputName: string): boolean {

export function getOptionalStringArrayInput(inputName: string): string[] {
const inputString = getOptionalStringInput(inputName);
if (!inputString) {
return [];
}

const input = tryParseJson(inputString);
if (!Array.isArray(input)) {
throw new Error(`Action input '${inputName}' must be a JSON string array`);
}

input.forEach(val => {
if (typeof val !== "string") {
throw new Error(
`Action input '${inputName}' must be a JSON string array`,
);
}
});

return input;
return inputString ? parseCommaSeparated(inputString) : [];
}

export function getOptionalEnumArrayInput<TEnum extends string>(
Expand Down Expand Up @@ -100,7 +84,7 @@ export function getOptionalDictionaryInput(

const input = tryParseJson(inputString);
if (typeof input !== "object") {
throw new Error(`Action input '${inputName}' must be a dictionary`);
throw new Error(`Action input '${inputName}' must be a valid JSON object`);
}

return input;
Expand All @@ -114,7 +98,7 @@ export function getOptionalStringDictionaryInput(
Object.keys(input).forEach(key => {
if (typeof input[key] !== "string") {
throw new Error(
`Action input '${inputName}' must be a dictionary of string values`,
`Action input '${inputName}' must be a valid JSON object containing only string values`,
);
}
});
Expand All @@ -127,7 +111,7 @@ function getInput(
allowedValues?: string[],
throwOnMissing = true,
): string | undefined {
const inputValue = core.getInput(inputName);
const inputValue = core.getInput(inputName)?.trim();
if (!inputValue) {
if (throwOnMissing) {
throw new Error(
Expand All @@ -154,3 +138,10 @@ function tryParseJson(value: string) {
return undefined;
}
}

function parseCommaSeparated(value: string) {
return value
.split(",")
.map(val => val.trim())
.filter(val => val.length > 0);
}
12 changes: 6 additions & 6 deletions test/config.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -25,14 +25,14 @@ describe("input validation", () => {
it("requires valid json for tags", async () => {
configureGetInputMock({ type: "deployment", tags: "invalid" });
expect(() => parseConfig()).toThrow(
"Action input 'tags' must be a dictionary"
"Action input 'tags' must be a valid JSON object"
);
});

it("requires valid json for tags", async () => {
configureGetInputMock({ type: "deployment", tags: '{"foo": {}}' });
expect(() => parseConfig()).toThrow(
"Action input 'tags' must be a dictionary"
"Action input 'tags' must be a valid JSON object"
);
});

Expand Down Expand Up @@ -120,7 +120,7 @@ describe("input validation", () => {
scope: "resourceGroup",
"subscription-id": "foo",
"resource-group-name": "mockRg",
"what-if-exclude-change-types": "[\"blah\"]",
"what-if-exclude-change-types": "blah",
});
expect(() => parseConfig()).toThrow(
"Action input 'what-if-exclude-change-types' must be one of the following values: 'create', 'delete', 'modify', 'deploy', 'noChange', 'ignore', 'unsupported'"
Expand Down Expand Up @@ -244,7 +244,7 @@ describe("input parsing", () => {
parameters: '{"foo": "bar2"}',
description: "mockDescription",
tags: '{"foo": "bar"}',
"what-if-exclude-change-types": "[\"noChange\"]",
"what-if-exclude-change-types": "noChange",
});

const config = parseConfig();
Expand Down Expand Up @@ -291,8 +291,8 @@ describe("input parsing", () => {
"action-on-unmanage-resourcegroups": "delete",
"action-on-unmanage-managementgroups": "delete",
"deny-settings-mode": "none",
"deny-settings-excluded-actions": JSON.stringify(["abc", "def"]),
"deny-settings-excluded-principals": JSON.stringify(["ghi", "jkl"]),
"deny-settings-excluded-actions": "abc,def",
"deny-settings-excluded-principals": "ghi,jkl",
"bypass-stack-out-of-sync-error": "true",
});

Expand Down
4 changes: 0 additions & 4 deletions test/file.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,10 +6,6 @@ import { FileConfig } from "../src/config";
import { getJsonParameters, getTemplateAndParameters } from "../src/helpers/file";
import { readTestFile } from "./utils";

beforeEach(() => {
jest.clearAllMocks();
});

describe("file parsing", () => {
it("reads and parses template and parameters files", async () => {
const config: FileConfig = {
Expand Down
4 changes: 0 additions & 4 deletions test/handler.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,10 +9,6 @@ import { Deployment, DeploymentExtended, DeploymentProperties, ErrorResponse } f
import { DeploymentStack, DeploymentStackProperties } from '@azure/arm-resourcesdeploymentstacks';
import { Color, colorize } from "../src/helpers/logging";

beforeEach(() => {
jest.clearAllMocks();
});

describe('deployment execution', () => {
describe('subscription scope', () => {
const scope: SubscriptionScope = {
Expand Down
Loading

0 comments on commit c1ed178

Please sign in to comment.