From bdc386935030ce5f450b0de86acb7baacbc2e330 Mon Sep 17 00:00:00 2001 From: kellertk Date: Tue, 19 Aug 2025 21:33:39 -0700 Subject: [PATCH] chore: cleanup input handling --- src/cleanup/index.ts | 7 +++-- src/helpers.ts | 29 ++++++++++++++++++ src/index.ts | 72 +++++++++++++++----------------------------- 3 files changed, 58 insertions(+), 50 deletions(-) diff --git a/src/cleanup/index.ts b/src/cleanup/index.ts index 5cf2fe728..81bbdb546 100644 --- a/src/cleanup/index.ts +++ b/src/cleanup/index.ts @@ -1,5 +1,5 @@ import * as core from '@actions/core'; -import { errorMessage } from '../helpers'; +import { errorMessage, getBooleanInput } from '../helpers'; /** * When the GitHub Actions job is done, clean up any environment variables that @@ -13,8 +13,8 @@ import { errorMessage } from '../helpers'; */ export function cleanup() { - const outputEnvCredentialsInput = core.getInput('output-env-credentials', { required: false }) || 'true'; - if (outputEnvCredentialsInput === 'true') { + // Only attempt to change environment variables if we changed them in the first place + if (getBooleanInput('output-env-credentials', { required: false, default: true })) { try { // The GitHub Actions toolkit does not have an option to completely unset // environment variables, so we overwrite the current value with an empty @@ -30,6 +30,7 @@ export function cleanup() { } } } + /* c8 ignore start */ if (require.main === module) { try { diff --git a/src/helpers.ts b/src/helpers.ts index ce5ff461b..73d51bc0f 100644 --- a/src/helpers.ts +++ b/src/helpers.ts @@ -214,3 +214,32 @@ export async function areCredentialsValid(credentialsClient: CredentialsClient) return false; } } + +/** + * Like core.getBooleanInput, but respects the required option. + * + * From https://github.com/actions/toolkit/blob/6876e2a664ec02908178087905b9155e9892a437/packages/core/src/core.ts + * + * Gets the input value of the boolean type in the YAML 1.2 "core schema" specification. + * Support boolean input list: `true | True | TRUE | false | False | FALSE` . + * The return value is also in boolean type. + * ref: https://yaml.org/spec/1.2/spec.html#id2804923 + * + * @param name name of the input to get + * @param options optional. See core.InputOptions. Also supports optional 'default' if the input is not set + * @returns boolean + */ +export function getBooleanInput(name: string, options?: core.InputOptions & { default?: boolean }): boolean { + const trueValue = ['true', 'True', 'TRUE']; + const falseValue = ['false', 'False', 'FALSE']; + const optionsWithoutDefault = { ...options }; + delete optionsWithoutDefault.default; + const val = core.getInput(name, optionsWithoutDefault); + if (trueValue.includes(val)) return true; + if (falseValue.includes(val)) return false; + if (val === '') return options?.default ?? false; + throw new TypeError( + `Input does not meet YAML 1.2 "Core Schema" specification: ${name}\n` + + `Support boolean input list: \`true | True | TRUE | false | False | FALSE\``, + ); +} diff --git a/src/index.ts b/src/index.ts index 71aa838ca..18894f8bc 100644 --- a/src/index.ts +++ b/src/index.ts @@ -8,6 +8,7 @@ import { exportAccountId, exportCredentials, exportRegion, + getBooleanInput, retryAndBackoff, translateEnvVariables, unsetCredentials, @@ -22,64 +23,41 @@ export async function run() { try { translateEnvVariables(); // Get inputs + // Undefined inputs are empty strings ( or empty arrays) const AccessKeyId = core.getInput('aws-access-key-id', { required: false }); - const SecretAccessKey = core.getInput('aws-secret-access-key', { - required: false, - }); - const sessionTokenInput = core.getInput('aws-session-token', { - required: false, - }); + const SecretAccessKey = core.getInput('aws-secret-access-key', { required: false }); + const sessionTokenInput = core.getInput('aws-session-token', { required: false }); const SessionToken = sessionTokenInput === '' ? undefined : sessionTokenInput; const region = core.getInput('aws-region', { required: true }); const roleToAssume = core.getInput('role-to-assume', { required: false }); const audience = core.getInput('audience', { required: false }); - const maskAccountIdInput = core.getInput('mask-aws-account-id', { required: false }) || 'false'; - const maskAccountId = maskAccountIdInput.toLowerCase() === 'true'; - const roleExternalId = core.getInput('role-external-id', { - required: false, - }); - const webIdentityTokenFile = core.getInput('web-identity-token-file', { - required: false, - }); + const maskAccountId = getBooleanInput('mask-aws-account-id', { required: false }); + const roleExternalId = core.getInput('role-external-id', { required: false }); + const webIdentityTokenFile = core.getInput('web-identity-token-file', { required: false }); const roleDuration = Number.parseInt(core.getInput('role-duration-seconds', { required: false })) || DEFAULT_ROLE_DURATION; const roleSessionName = core.getInput('role-session-name', { required: false }) || ROLE_SESSION_NAME; - const roleSkipSessionTaggingInput = core.getInput('role-skip-session-tagging', { required: false }) || 'false'; - const roleSkipSessionTagging = roleSkipSessionTaggingInput.toLowerCase() === 'true'; + const roleSkipSessionTagging = getBooleanInput('role-skip-session-tagging', { required: false }); const proxyServer = core.getInput('http-proxy', { required: false }) || process.env.HTTP_PROXY; - const inlineSessionPolicy = core.getInput('inline-session-policy', { - required: false, + const inlineSessionPolicy = core.getInput('inline-session-policy', { required: false }); + const managedSessionPolicies = core.getMultilineInput('managed-session-policies', { required: false }).map((p) => { + return { arn: p }; }); - const managedSessionPoliciesInput = core.getMultilineInput('managed-session-policies', { required: false }); - const managedSessionPolicies: { arn: string }[] = []; - const roleChainingInput = core.getInput('role-chaining', { required: false }) || 'false'; - const roleChaining = roleChainingInput.toLowerCase() === 'true'; - const outputCredentialsInput = core.getInput('output-credentials', { required: false }) || 'false'; - const outputCredentials = outputCredentialsInput.toLowerCase() === 'true'; - const outputEnvCredentialsInput = core.getInput('output-env-credentials', { required: false }) || 'true'; - const outputEnvCredentials = outputEnvCredentialsInput.toLowerCase() === 'true'; - const unsetCurrentCredentialsInput = core.getInput('unset-current-credentials', { required: false }) || 'false'; - const unsetCurrentCredentials = unsetCurrentCredentialsInput.toLowerCase() === 'true'; - const disableRetryInput = core.getInput('disable-retry', { required: false }) || 'false'; - let disableRetry = disableRetryInput.toLowerCase() === 'true'; - const specialCharacterWorkaroundInput = - core.getInput('special-characters-workaround', { required: false }) || 'false'; - const specialCharacterWorkaround = specialCharacterWorkaroundInput.toLowerCase() === 'true'; - const useExistingCredentialsInput = core.getInput('use-existing-credentials', { required: false }) || 'false'; - const useExistingCredentials = useExistingCredentialsInput.toLowerCase() === 'true'; + const roleChaining = getBooleanInput('role-chaining', { required: false }); + const outputCredentials = getBooleanInput('output-credentials', { required: false }); + const outputEnvCredentials = getBooleanInput('output-env-credentials', { required: false, default: true }); + const unsetCurrentCredentials = getBooleanInput('unset-current-credentials', { required: false }); + let disableRetry = getBooleanInput('disable-retry', { required: false }); + const specialCharacterWorkaround = getBooleanInput('special-characters-workaround', { required: false }); + const useExistingCredentials = core.getInput('use-existing-credentials', { required: false }); let maxRetries = Number.parseInt(core.getInput('retry-max-attempts', { required: false })) || 12; - switch (true) { - case specialCharacterWorkaround: - // 😳 - disableRetry = false; - maxRetries = 12; - break; - case maxRetries < 1: - maxRetries = 1; - break; - } - for (const managedSessionPolicy of managedSessionPoliciesInput) { - managedSessionPolicies.push({ arn: managedSessionPolicy }); + + if (specialCharacterWorkaround) { + // 😳 + disableRetry = false; + maxRetries = 12; + } else if (maxRetries < 1) { + maxRetries = 1; } // Logic to decide whether to attempt to use OIDC or not