chore: migrate to biomejs (#1167)

* chore: migrate to biomejs

* chore: migrate to biomejs

* chore: migrate from jest to vitest

* chore: error on lint warnings

* chore: remove obsolete depedencies
This commit is contained in:
Tom Keller
2024-11-04 10:19:12 -08:00
committed by GitHub
parent d90c1f89e1
commit ccbdafa425
17 changed files with 4393 additions and 8410 deletions
+3 -2
View File
@@ -1,5 +1,6 @@
import { info } from '@actions/core';
import { STSClient } from '@aws-sdk/client-sts';
import type { AwsCredentialIdentity } from '@aws-sdk/types';
import { NodeHttpHandler } from '@smithy/node-http-handler';
import { HttpsProxyAgent } from 'https-proxy-agent';
import { errorMessage } from './helpers';
@@ -40,7 +41,7 @@ export class CredentialsClient {
}
public async validateCredentials(expectedAccessKeyId?: string, roleChaining?: boolean) {
let credentials;
let credentials: AwsCredentialIdentity;
try {
credentials = await this.loadCredentials();
if (!credentials.accessKeyId) {
@@ -55,7 +56,7 @@ export class CredentialsClient {
if (expectedAccessKeyId && expectedAccessKeyId !== actualAccessKeyId) {
throw new Error(
'Unexpected failure: Credentials loaded by the SDK do not match the access key ID configured by the action'
'Unexpected failure: Credentials loaded by the SDK do not match the access key ID configured by the action',
);
}
}
+19 -15
View File
@@ -1,6 +1,6 @@
import assert from 'assert';
import fs from 'fs';
import path from 'path';
import assert from 'node:assert';
import fs from 'node:fs';
import path from 'node:path';
import * as core from '@actions/core';
import type { AssumeRoleCommandInput, STSClient, Tag } from '@aws-sdk/client-sts';
import { AssumeRoleCommand, AssumeRoleWithWebIdentityCommand } from '@aws-sdk/client-sts';
@@ -15,7 +15,7 @@ async function assumeRoleWithOIDC(params: AssumeRoleCommandInput, client: STSCli
new AssumeRoleWithWebIdentityCommand({
...params,
WebIdentityToken: webIdentityToken,
})
}),
);
return creds;
} catch (error) {
@@ -27,10 +27,10 @@ async function assumeRoleWithWebIdentityTokenFile(
params: AssumeRoleCommandInput,
client: STSClient,
webIdentityTokenFile: string,
workspace: string
workspace: string,
) {
core.debug(
'webIdentityTokenFile provided. Will call sts:AssumeRoleWithWebIdentity and take session tags from token contents.'
'webIdentityTokenFile provided. Will call sts:AssumeRoleWithWebIdentity and take session tags from token contents.',
);
const webIdentityTokenFilePath = path.isAbsolute(webIdentityTokenFile)
? webIdentityTokenFile
@@ -46,7 +46,7 @@ async function assumeRoleWithWebIdentityTokenFile(
new AssumeRoleWithWebIdentityCommand({
...params,
WebIdentityToken: webIdentityToken,
})
}),
);
return creds;
} catch (error) {
@@ -75,7 +75,7 @@ export interface assumeRoleParams {
webIdentityTokenFile?: string;
webIdentityToken?: string;
inlineSessionPolicy?: string;
managedSessionPolicies?: any[];
managedSessionPolicies?: { arn: string }[];
}
export async function assumeRole(params: assumeRoleParams) {
@@ -108,8 +108,11 @@ export async function assumeRole(params: assumeRoleParams) {
{ Key: 'Actor', Value: sanitizeGitHubVariables(GITHUB_ACTOR) },
{ Key: 'Commit', Value: GITHUB_SHA },
];
if (process.env['GITHUB_REF']) {
tagArray.push({ Key: 'Branch', Value: sanitizeGitHubVariables(process.env['GITHUB_REF']) });
if (process.env.GITHUB_REF) {
tagArray.push({
Key: 'Branch',
Value: sanitizeGitHubVariables(process.env.GITHUB_REF),
});
}
const tags = roleSkipSessionTagging ? undefined : tagArray;
if (!tags) {
@@ -123,7 +126,7 @@ export async function assumeRole(params: assumeRoleParams) {
if (!roleArn.startsWith('arn:aws')) {
assert(
isDefined(sourceAccountId),
'Source Account ID is needed if the Role Name is provided and not the Role Arn.'
'Source Account ID is needed if the Role Name is provided and not the Role Arn.',
);
roleArn = `arn:aws:iam::${sourceAccountId}:role/${roleArn}`;
}
@@ -139,6 +142,7 @@ export async function assumeRole(params: assumeRoleParams) {
PolicyArns: managedSessionPolicies?.length ? managedSessionPolicies : undefined,
};
const keys = Object.keys(commonAssumeRoleParams) as Array<keyof typeof commonAssumeRoleParams>;
// biome-ignore lint/complexity/noForEach: Legacy code
keys.forEach((k) => commonAssumeRoleParams[k] === undefined && delete commonAssumeRoleParams[k]);
// Instantiate STS client
@@ -147,14 +151,14 @@ export async function assumeRole(params: assumeRoleParams) {
// Assume role using one of three methods
if (!!webIdentityToken) {
return assumeRoleWithOIDC(commonAssumeRoleParams, stsClient, webIdentityToken);
} else if (!!webIdentityTokenFile) {
}
if (!!webIdentityTokenFile) {
return assumeRoleWithWebIdentityTokenFile(
commonAssumeRoleParams,
stsClient,
webIdentityTokenFile,
GITHUB_WORKSPACE
GITHUB_WORKSPACE,
);
} else {
return assumeRoleWithCredentials(commonAssumeRoleParams, stsClient);
}
return assumeRoleWithCredentials(commonAssumeRoleParams, stsClient);
}
+4 -3
View File
@@ -23,7 +23,7 @@ export function exportCredentials(creds?: Partial<Credentials>, outputCredential
if (creds?.SessionToken) {
core.setSecret(creds.SessionToken);
core.exportVariable('AWS_SESSION_TOKEN', creds.SessionToken);
} else if (process.env['AWS_SESSION_TOKEN']) {
} else if (process.env.AWS_SESSION_TOKEN) {
// clear session token from previous credentials action
core.exportVariable('AWS_SESSION_TOKEN', '');
}
@@ -116,7 +116,7 @@ export async function retryAndBackoff<T>(
isRetryable: boolean,
maxRetries = 12,
retries = 0,
base = 50
base = 50,
): Promise<T> {
try {
return await fn();
@@ -125,7 +125,8 @@ export async function retryAndBackoff<T>(
throw err;
}
// It's retryable, so sleep and retry.
await sleep(Math.random() * (Math.pow(2, retries) * base));
await sleep(Math.random() * (2 ** retries * base));
// biome-ignore lint/style/noParameterAssign: This is a loop variable
retries += 1;
if (retries >= maxRetries) {
throw err;
+31 -22
View File
@@ -1,13 +1,13 @@
import * as core from '@actions/core';
import type { AssumeRoleCommandOutput } from '@aws-sdk/client-sts';
import { assumeRole } from './assumeRole';
import { CredentialsClient } from './CredentialsClient';
import { assumeRole } from './assumeRole';
import {
errorMessage,
retryAndBackoff,
exportRegion,
exportCredentials,
exportAccountId,
exportCredentials,
exportRegion,
retryAndBackoff,
unsetCredentials,
verifyKeys,
} from './helpers';
@@ -20,24 +20,35 @@ export async function run() {
try {
// Get inputs
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 roleDuration = parseInt(core.getInput('role-duration-seconds', { required: false })) || DEFAULT_ROLE_DURATION;
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 proxyServer = core.getInput('http-proxy', { required: false });
const inlineSessionPolicy = core.getInput('inline-session-policy', { required: false });
const inlineSessionPolicy = core.getInput('inline-session-policy', {
required: false,
});
const managedSessionPoliciesInput = core.getMultilineInput('managed-session-policies', { required: false });
const managedSessionPolicies: any[] = [];
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';
@@ -49,7 +60,7 @@ export async function run() {
const specialCharacterWorkaroundInput =
core.getInput('special-characters-workaround', { required: false }) || 'false';
const specialCharacterWorkaround = specialCharacterWorkaroundInput.toLowerCase() === 'true';
let maxRetries = parseInt(core.getInput('retry-max-attempts', { required: false })) || 12;
let maxRetries = Number.parseInt(core.getInput('retry-max-attempts', { required: false })) || 12;
switch (true) {
case specialCharacterWorkaround:
// 😳
@@ -74,17 +85,17 @@ export async function run() {
!!roleToAssume &&
!webIdentityTokenFile &&
!AccessKeyId &&
!process.env['ACTIONS_ID_TOKEN_REQUEST_TOKEN'] &&
!process.env.ACTIONS_ID_TOKEN_REQUEST_TOKEN &&
!roleChaining
) {
core.info(
'It looks like you might be trying to authenticate with OIDC. Did you mean to set the `id-token` permission? ' +
'If you are not trying to authenticate with OIDC and the action is working successfully, you can ignore this message.'
'If you are not trying to authenticate with OIDC and the action is working successfully, you can ignore this message.',
);
}
return (
!!roleToAssume &&
!!process.env['ACTIONS_ID_TOKEN_REQUEST_TOKEN'] &&
!!process.env.ACTIONS_ID_TOKEN_REQUEST_TOKEN &&
!AccessKeyId &&
!webIdentityTokenFile &&
!roleChaining
@@ -114,7 +125,7 @@ export async function run() {
return core.getIDToken(audience);
},
!disableRetry,
maxRetries
maxRetries,
);
} catch (error) {
throw new Error(`getIDToken call failed: ${errorMessage(error)}`);
@@ -146,7 +157,6 @@ export async function run() {
if (roleToAssume) {
let roleCredentials: AssumeRoleCommandOutput;
do {
// eslint-disable-next-line no-await-in-loop
roleCredentials = await retryAndBackoff(
async () => {
return assumeRole({
@@ -164,17 +174,16 @@ export async function run() {
});
},
!disableRetry,
maxRetries
maxRetries,
);
// eslint-disable-next-line no-unmodified-loop-condition
} while (specialCharacterWorkaround && !verifyKeys(roleCredentials.Credentials));
core.info(`Authenticated as assumedRoleId ${roleCredentials.AssumedRoleUser!.AssumedRoleId!}`);
core.info(`Authenticated as assumedRoleId ${roleCredentials.AssumedRoleUser?.AssumedRoleId}`);
exportCredentials(roleCredentials.Credentials, outputCredentials);
// We need to validate the credentials in 2 of our use-cases
// First: self-hosted runners. If the GITHUB_ACTIONS environment variable
// is set to `true` then we are NOT in a self-hosted runner.
// Second: Customer provided credentials manually (IAM User keys stored in GH Secrets)
if (!process.env['GITHUB_ACTIONS'] || AccessKeyId) {
if (!process.env.GITHUB_ACTIONS || AccessKeyId) {
await credentialsClient.validateCredentials(roleCredentials.Credentials?.AccessKeyId);
}
await exportAccountId(credentialsClient, maskAccountId);
@@ -184,7 +193,7 @@ export async function run() {
} catch (error) {
core.setFailed(errorMessage(error));
const showStackTrace = process.env['SHOW_STACK_TRACE'];
const showStackTrace = process.env.SHOW_STACK_TRACE;
if (showStackTrace === 'true') {
throw error;