diff --git a/.github/workflows/cloud-runner-integrity-localstack.yml b/.github/workflows/cloud-runner-integrity-localstack.yml
new file mode 100644
index 00000000..ec779bdb
--- /dev/null
+++ b/.github/workflows/cloud-runner-integrity-localstack.yml
@@ -0,0 +1,83 @@
+name: cloud-runner-integrity-localstack
+
+on:
+ workflow_call:
+ inputs:
+ runGithubIntegrationTests:
+ description: 'Run GitHub Checks integration tests'
+ required: false
+ default: 'false'
+ type: string
+
+permissions:
+ checks: write
+ contents: read
+ actions: write
+ packages: read
+ pull-requests: write
+ statuses: write
+ id-token: write
+
+env:
+ AWS_REGION: us-east-1
+ AWS_DEFAULT_REGION: us-east-1
+ AWS_STACK_NAME: game-ci-local
+ AWS_ENDPOINT: http://localhost:4566
+ AWS_ENDPOINT_URL: http://localhost:4566
+ AWS_ACCESS_KEY_ID: test
+ AWS_SECRET_ACCESS_KEY: test
+ CLOUD_RUNNER_BRANCH: ${{ github.ref }}
+ DEBUG: true
+ PROJECT_PATH: test-project
+ USE_IL2CPP: false
+
+jobs:
+ tests:
+ name: Cloud Runner Tests (LocalStack)
+ runs-on: ubuntu-latest
+ services:
+ localstack:
+ image: localstack/localstack
+ ports:
+ - 4566:4566
+ env:
+ SERVICES: cloudformation,ecs,kinesis,cloudwatch,s3,logs
+ strategy:
+ fail-fast: false
+ matrix:
+ test:
+ - 'cloud-runner-end2end-locking'
+ - 'cloud-runner-end2end-caching'
+ - 'cloud-runner-end2end-retaining'
+ - 'cloud-runner-caching'
+ - 'cloud-runner-environment'
+ - 'cloud-runner-image'
+ - 'cloud-runner-hooks'
+ - 'cloud-runner-local-persistence'
+ - 'cloud-runner-locking-core'
+ - 'cloud-runner-locking-get-locked'
+ steps:
+ - uses: actions/checkout@v4
+ with:
+ lfs: false
+ - uses: actions/setup-node@v4
+ with:
+ node-version: 20
+ cache: 'yarn'
+ - run: yarn install --frozen-lockfile
+ - run: yarn run test "${{ matrix.test }}" --detectOpenHandles --forceExit --runInBand
+ timeout-minutes: 60
+ env:
+ UNITY_EMAIL: ${{ secrets.UNITY_EMAIL }}
+ UNITY_PASSWORD: ${{ secrets.UNITY_PASSWORD }}
+ UNITY_SERIAL: ${{ secrets.UNITY_SERIAL }}
+ PROJECT_PATH: test-project
+ TARGET_PLATFORM: StandaloneWindows64
+ cloudRunnerTests: true
+ versioning: None
+ KUBE_STORAGE_CLASS: local-path
+ PROVIDER_STRATEGY: aws
+ AWS_ACCESS_KEY_ID: test
+ AWS_SECRET_ACCESS_KEY: test
+ GIT_PRIVATE_TOKEN: ${{ secrets.GIT_PRIVATE_TOKEN }}
+ GITHUB_TOKEN: ${{ secrets.GIT_PRIVATE_TOKEN }}
diff --git a/README.md b/README.md
index ba406f04..1eba600c 100644
--- a/README.md
+++ b/README.md
@@ -2,39 +2,45 @@
(Not affiliated with Unity Technologies)
-GitHub Action to
-[build Unity projects](https://github.com/marketplace/actions/unity-builder)
-for different platforms.
+GitHub Action to [build Unity projects](https://github.com/marketplace/actions/unity-builder) for different platforms.
-Part of the GameCI open source project.
-
-
+Part of the GameCI open source project.
[](https://github.com/game-ci/unity-builder/actions/workflows/build-tests-ubuntu.yml)
[](https://github.com/game-ci/unity-builder/actions/workflows/build-tests-windows.yml)
[](https://github.com/game-ci/unity-builder/actions/workflows/build-tests-mac.yml)
[](https://codecov.io/gh/game-ci/unity-builder)
-
-
+
## How to use
-Find the
-[docs](https://game.ci/docs/github/builder)
-on the GameCI
-[documentation website](https://game.ci/docs).
+Find the [docs](https://game.ci/docs/github/builder) on the GameCI [documentation website](https://game.ci/docs).
## Related actions
-Visit the
-GameCI Unity Actions
-status repository for related Actions.
+Visit the GameCI Unity Actions status repository for related
+Actions.
+
+## AWS provider with local emulator
+
+The AWS provider can target a local AWS emulator such as [LocalStack](https://github.com/localstack/localstack).
+Configure the endpoint URLs through environment variables before running tests or the action:
+
+```
+AWS_ENDPOINT=http://localhost:4566
+AWS_ACCESS_KEY_ID=test
+AWS_SECRET_ACCESS_KEY=test
+```
+
+When these variables are set, Unity Builder will direct its CloudFormation, ECS, Kinesis, CloudWatch Logs and S3 clients
+to the emulator instead of the real AWS services. See `.github/workflows/cloud-runner-integrity-localstack.yml` for an
+example configuration.
## Community
Feel free to join us on
-
-and engage with the community.
+
and engage with the
+community.
## Contributing
diff --git a/src/model/build-parameters.ts b/src/model/build-parameters.ts
index 55bc29bd..62d731a1 100644
--- a/src/model/build-parameters.ts
+++ b/src/model/build-parameters.ts
@@ -56,6 +56,12 @@ class BuildParameters {
public providerStrategy!: string;
public gitPrivateToken!: string;
public awsStackName!: string;
+ public awsEndpoint?: string;
+ public awsCloudFormationEndpoint?: string;
+ public awsEcsEndpoint?: string;
+ public awsKinesisEndpoint?: string;
+ public awsCloudWatchLogsEndpoint?: string;
+ public awsS3Endpoint?: string;
public kubeConfig!: string;
public containerMemory!: string;
public containerCpu!: string;
@@ -199,6 +205,12 @@ class BuildParameters {
githubRepo: (Input.githubRepo ?? (await GitRepoReader.GetRemote())) || 'game-ci/unity-builder',
isCliMode: Cli.isCliMode,
awsStackName: CloudRunnerOptions.awsStackName,
+ awsEndpoint: CloudRunnerOptions.awsEndpoint,
+ awsCloudFormationEndpoint: CloudRunnerOptions.awsCloudFormationEndpoint,
+ awsEcsEndpoint: CloudRunnerOptions.awsEcsEndpoint,
+ awsKinesisEndpoint: CloudRunnerOptions.awsKinesisEndpoint,
+ awsCloudWatchLogsEndpoint: CloudRunnerOptions.awsCloudWatchLogsEndpoint,
+ awsS3Endpoint: CloudRunnerOptions.awsS3Endpoint,
gitSha: Input.gitSha,
logId: customAlphabet(CloudRunnerConstants.alphabet, 9)(),
buildGuid: CloudRunnerBuildGuid.generateGuid(Input.runNumber, Input.targetPlatform),
diff --git a/src/model/cloud-runner/options/cloud-runner-options.ts b/src/model/cloud-runner/options/cloud-runner-options.ts
index 814d104c..9bd75e29 100644
--- a/src/model/cloud-runner/options/cloud-runner-options.ts
+++ b/src/model/cloud-runner/options/cloud-runner-options.ts
@@ -195,6 +195,30 @@ class CloudRunnerOptions {
return CloudRunnerOptions.getInput('awsStackName') || 'game-ci';
}
+ static get awsEndpoint(): string | undefined {
+ return CloudRunnerOptions.getInput('awsEndpoint');
+ }
+
+ static get awsCloudFormationEndpoint(): string | undefined {
+ return CloudRunnerOptions.getInput('awsCloudFormationEndpoint') || CloudRunnerOptions.awsEndpoint;
+ }
+
+ static get awsEcsEndpoint(): string | undefined {
+ return CloudRunnerOptions.getInput('awsEcsEndpoint') || CloudRunnerOptions.awsEndpoint;
+ }
+
+ static get awsKinesisEndpoint(): string | undefined {
+ return CloudRunnerOptions.getInput('awsKinesisEndpoint') || CloudRunnerOptions.awsEndpoint;
+ }
+
+ static get awsCloudWatchLogsEndpoint(): string | undefined {
+ return CloudRunnerOptions.getInput('awsCloudWatchLogsEndpoint') || CloudRunnerOptions.awsEndpoint;
+ }
+
+ static get awsS3Endpoint(): string | undefined {
+ return CloudRunnerOptions.getInput('awsS3Endpoint') || CloudRunnerOptions.awsEndpoint;
+ }
+
// ### ### ###
// K8s
// ### ### ###
diff --git a/src/model/cloud-runner/providers/aws/aws-client-factory.ts b/src/model/cloud-runner/providers/aws/aws-client-factory.ts
new file mode 100644
index 00000000..7bde368d
--- /dev/null
+++ b/src/model/cloud-runner/providers/aws/aws-client-factory.ts
@@ -0,0 +1,71 @@
+import { CloudFormation } from '@aws-sdk/client-cloudformation';
+import { ECS } from '@aws-sdk/client-ecs';
+import { Kinesis } from '@aws-sdk/client-kinesis';
+import { CloudWatchLogs } from '@aws-sdk/client-cloudwatch-logs';
+import { S3 } from '@aws-sdk/client-s3';
+import { Input } from '../../..';
+import CloudRunnerOptions from '../../options/cloud-runner-options';
+
+export class AwsClientFactory {
+ private static cloudFormation: CloudFormation;
+ private static ecs: ECS;
+ private static kinesis: Kinesis;
+ private static cloudWatchLogs: CloudWatchLogs;
+ private static s3: S3;
+
+ static getCloudFormation(): CloudFormation {
+ if (!this.cloudFormation) {
+ this.cloudFormation = new CloudFormation({
+ region: Input.region,
+ endpoint: CloudRunnerOptions.awsCloudFormationEndpoint,
+ });
+ }
+
+ return this.cloudFormation;
+ }
+
+ static getECS(): ECS {
+ if (!this.ecs) {
+ this.ecs = new ECS({
+ region: Input.region,
+ endpoint: CloudRunnerOptions.awsEcsEndpoint,
+ });
+ }
+
+ return this.ecs;
+ }
+
+ static getKinesis(): Kinesis {
+ if (!this.kinesis) {
+ this.kinesis = new Kinesis({
+ region: Input.region,
+ endpoint: CloudRunnerOptions.awsKinesisEndpoint,
+ });
+ }
+
+ return this.kinesis;
+ }
+
+ static getCloudWatchLogs(): CloudWatchLogs {
+ if (!this.cloudWatchLogs) {
+ this.cloudWatchLogs = new CloudWatchLogs({
+ region: Input.region,
+ endpoint: CloudRunnerOptions.awsCloudWatchLogsEndpoint,
+ });
+ }
+
+ return this.cloudWatchLogs;
+ }
+
+ static getS3(): S3 {
+ if (!this.s3) {
+ this.s3 = new S3({
+ region: Input.region,
+ endpoint: CloudRunnerOptions.awsS3Endpoint,
+ forcePathStyle: true,
+ });
+ }
+
+ return this.s3;
+ }
+}
diff --git a/src/model/cloud-runner/providers/aws/aws-task-runner.ts b/src/model/cloud-runner/providers/aws/aws-task-runner.ts
index afdbfbd8..37b18147 100644
--- a/src/model/cloud-runner/providers/aws/aws-task-runner.ts
+++ b/src/model/cloud-runner/providers/aws/aws-task-runner.ts
@@ -1,5 +1,5 @@
-import { DescribeTasksCommand, ECS, RunTaskCommand, waitUntilTasksRunning } from '@aws-sdk/client-ecs';
-import { DescribeStreamCommand, GetRecordsCommand, GetShardIteratorCommand, Kinesis } from '@aws-sdk/client-kinesis';
+import { DescribeTasksCommand, RunTaskCommand, waitUntilTasksRunning } from '@aws-sdk/client-ecs';
+import { DescribeStreamCommand, GetRecordsCommand, GetShardIteratorCommand } from '@aws-sdk/client-kinesis';
import CloudRunnerEnvironmentVariable from '../../options/cloud-runner-environment-variable';
import * as core from '@actions/core';
import CloudRunnerAWSTaskDef from './cloud-runner-aws-task-def';
@@ -11,10 +11,9 @@ import { CommandHookService } from '../../services/hooks/command-hook-service';
import { FollowLogStreamService } from '../../services/core/follow-log-stream-service';
import CloudRunnerOptions from '../../options/cloud-runner-options';
import GitHub from '../../../github';
+import { AwsClientFactory } from './aws-client-factory';
class AWSTaskRunner {
- public static ECS: ECS;
- public static Kinesis: Kinesis;
private static readonly encodedUnderscore = `$252F`;
static async runTask(
taskDef: CloudRunnerAWSTaskDef,
@@ -61,7 +60,7 @@ class AWSTaskRunner {
throw new Error(`Container Overrides length must be at most 8192`);
}
- const task = await AWSTaskRunner.ECS.send(new RunTaskCommand(runParameters as any));
+ const task = await AwsClientFactory.getECS().send(new RunTaskCommand(runParameters as any));
const taskArn = task.tasks?.[0].taskArn || '';
CloudRunnerLogger.log('Cloud runner job is starting');
await AWSTaskRunner.waitUntilTaskRunning(taskArn, cluster);
@@ -115,7 +114,7 @@ class AWSTaskRunner {
try {
await waitUntilTasksRunning(
{
- client: AWSTaskRunner.ECS,
+ client: AwsClientFactory.getECS(),
maxWaitTime: 120,
},
{ tasks: [taskArn], cluster },
@@ -136,7 +135,7 @@ class AWSTaskRunner {
let delayMs = 1000;
for (let attempt = 1; attempt <= maxAttempts; attempt++) {
try {
- const tasks = await AWSTaskRunner.ECS.send(
+ const tasks = await AwsClientFactory.getECS().send(
new DescribeTasksCommand({ cluster: clusterName, tasks: [taskArn] }),
);
if (tasks.tasks?.[0]) {
@@ -193,12 +192,13 @@ class AWSTaskRunner {
) {
let records: any;
try {
- records = await AWSTaskRunner.Kinesis.send(new GetRecordsCommand({ ShardIterator: iterator }));
+ records = await AwsClientFactory.getKinesis().send(new GetRecordsCommand({ ShardIterator: iterator }));
} catch (error: any) {
const isThrottle = error?.name === 'ThrottlingException' || /rate exceeded/i.test(String(error?.message));
if (isThrottle) {
CloudRunnerLogger.log(`AWS throttled GetRecords, backing off 1000ms`);
await new Promise((r) => setTimeout(r, 1000));
+
return { iterator, shouldReadLogs, output, shouldCleanup };
}
throw error;
@@ -263,13 +263,13 @@ class AWSTaskRunner {
}
private static async getLogStream(kinesisStreamName: string) {
- return await AWSTaskRunner.Kinesis.send(new DescribeStreamCommand({ StreamName: kinesisStreamName }));
+ return await AwsClientFactory.getKinesis().send(new DescribeStreamCommand({ StreamName: kinesisStreamName }));
}
private static async getLogIterator(stream: any) {
return (
(
- await AWSTaskRunner.Kinesis.send(
+ await AwsClientFactory.getKinesis().send(
new GetShardIteratorCommand({
ShardIteratorType: 'TRIM_HORIZON',
StreamName: stream.StreamDescription?.StreamName ?? '',
diff --git a/src/model/cloud-runner/providers/aws/index.ts b/src/model/cloud-runner/providers/aws/index.ts
index 2486d92e..d57febdd 100644
--- a/src/model/cloud-runner/providers/aws/index.ts
+++ b/src/model/cloud-runner/providers/aws/index.ts
@@ -1,6 +1,4 @@
import { CloudFormation, DeleteStackCommand, waitUntilStackDeleteComplete } from '@aws-sdk/client-cloudformation';
-import { ECS as ECSClient } from '@aws-sdk/client-ecs';
-import { Kinesis } from '@aws-sdk/client-kinesis';
import CloudRunnerSecret from '../../options/cloud-runner-secret';
import CloudRunnerEnvironmentVariable from '../../options/cloud-runner-environment-variable';
import CloudRunnerAWSTaskDef from './cloud-runner-aws-task-def';
@@ -16,6 +14,7 @@ import { ProviderResource } from '../provider-resource';
import { ProviderWorkflow } from '../provider-workflow';
import { TaskService } from './services/task-service';
import CloudRunnerOptions from '../../options/cloud-runner-options';
+import { AwsClientFactory } from './aws-client-factory';
class AWSBuildEnvironment implements ProviderInterface {
private baseStackName: string;
@@ -77,7 +76,7 @@ class AWSBuildEnvironment implements ProviderInterface {
defaultSecretsArray: { ParameterKey: string; EnvironmentVariable: string; ParameterValue: string }[],
) {
process.env.AWS_REGION = Input.region;
- const CF = new CloudFormation({ region: Input.region });
+ const CF = AwsClientFactory.getCloudFormation();
await new AwsBaseStack(this.baseStackName).setupBaseStack(CF);
}
@@ -91,10 +90,9 @@ class AWSBuildEnvironment implements ProviderInterface {
secrets: CloudRunnerSecret[],
): Promise {
process.env.AWS_REGION = Input.region;
- const ECS = new ECSClient({ region: Input.region });
- const CF = new CloudFormation({ region: Input.region });
- AwsTaskRunner.ECS = ECS;
- AwsTaskRunner.Kinesis = new Kinesis({ region: Input.region });
+ AwsClientFactory.getECS();
+ const CF = AwsClientFactory.getCloudFormation();
+ AwsClientFactory.getKinesis();
CloudRunnerLogger.log(`AWS Region: ${CF.config.region}`);
const entrypoint = ['/bin/sh'];
const startTimeMs = Date.now();
diff --git a/src/model/cloud-runner/providers/aws/services/garbage-collection-service.ts b/src/model/cloud-runner/providers/aws/services/garbage-collection-service.ts
index ccdddf7a..a92c2cd0 100644
--- a/src/model/cloud-runner/providers/aws/services/garbage-collection-service.ts
+++ b/src/model/cloud-runner/providers/aws/services/garbage-collection-service.ts
@@ -1,14 +1,10 @@
-import {
- CloudFormation,
- DeleteStackCommand,
- DeleteStackCommandInput,
- DescribeStackResourcesCommand,
-} from '@aws-sdk/client-cloudformation';
-import { CloudWatchLogs, DeleteLogGroupCommand } from '@aws-sdk/client-cloudwatch-logs';
-import { ECS, StopTaskCommand } from '@aws-sdk/client-ecs';
+import { DeleteStackCommand, DescribeStackResourcesCommand } from '@aws-sdk/client-cloudformation';
+import { DeleteLogGroupCommand } from '@aws-sdk/client-cloudwatch-logs';
+import { StopTaskCommand } from '@aws-sdk/client-ecs';
import Input from '../../../../input';
import CloudRunnerLogger from '../../../services/core/cloud-runner-logger';
import { TaskService } from './task-service';
+import { AwsClientFactory } from '../aws-client-factory';
export class GarbageCollectionService {
static isOlderThan1day(date: Date) {
@@ -19,9 +15,9 @@ export class GarbageCollectionService {
public static async cleanup(deleteResources = false, OneDayOlderOnly: boolean = false) {
process.env.AWS_REGION = Input.region;
- const CF = new CloudFormation({ region: Input.region });
- const ecs = new ECS({ region: Input.region });
- const cwl = new CloudWatchLogs({ region: Input.region });
+ const CF = AwsClientFactory.getCloudFormation();
+ const ecs = AwsClientFactory.getECS();
+ const cwl = AwsClientFactory.getCloudWatchLogs();
const taskDefinitionsInUse = new Array();
const tasks = await TaskService.getTasks();
@@ -57,8 +53,7 @@ export class GarbageCollectionService {
}
CloudRunnerLogger.log(`Deleting ${element.StackName}`);
- const deleteStackInput: DeleteStackCommandInput = { StackName: element.StackName };
- await CF.send(new DeleteStackCommand(deleteStackInput));
+ await CF.send(new DeleteStackCommand({ StackName: element.StackName }));
}
}
const logGroups = await TaskService.getLogGroups();
diff --git a/src/model/cloud-runner/providers/aws/services/task-service.ts b/src/model/cloud-runner/providers/aws/services/task-service.ts
index 039969bb..f4df3323 100644
--- a/src/model/cloud-runner/providers/aws/services/task-service.ts
+++ b/src/model/cloud-runner/providers/aws/services/task-service.ts
@@ -1,31 +1,17 @@
import {
- CloudFormation,
DescribeStackResourcesCommand,
DescribeStacksCommand,
ListStacksCommand,
- StackSummary,
} from '@aws-sdk/client-cloudformation';
-import {
- CloudWatchLogs,
- DescribeLogGroupsCommand,
- DescribeLogGroupsCommandInput,
- LogGroup,
-} from '@aws-sdk/client-cloudwatch-logs';
-import {
- DescribeTasksCommand,
- DescribeTasksCommandInput,
- ECS,
- ListClustersCommand,
- ListTasksCommand,
- ListTasksCommandInput,
- Task,
-} from '@aws-sdk/client-ecs';
-import { ListObjectsCommand, ListObjectsCommandInput, S3 } from '@aws-sdk/client-s3';
+import { DescribeLogGroupsCommand } from '@aws-sdk/client-cloudwatch-logs';
+import { DescribeTasksCommand, ListClustersCommand, ListTasksCommand } from '@aws-sdk/client-ecs';
+import { ListObjectsCommand } from '@aws-sdk/client-s3';
import Input from '../../../../input';
import CloudRunnerLogger from '../../../services/core/cloud-runner-logger';
import { BaseStackFormation } from '../cloud-formations/base-stack-formation';
import AwsTaskRunner from '../aws-task-runner';
import CloudRunner from '../../../cloud-runner';
+import { AwsClientFactory } from '../aws-client-factory';
export class TaskService {
static async watch() {
@@ -39,11 +25,11 @@ export class TaskService {
return output;
}
public static async getCloudFormationJobStacks() {
- const result: StackSummary[] = [];
+ const result: any[] = [];
CloudRunnerLogger.log(``);
CloudRunnerLogger.log(`List Cloud Formation Stacks`);
process.env.AWS_REGION = Input.region;
- const CF = new CloudFormation({ region: Input.region });
+ const CF = AwsClientFactory.getCloudFormation();
const stacks =
(await CF.send(new ListStacksCommand({}))).StackSummaries?.filter(
(_x) =>
@@ -91,21 +77,20 @@ export class TaskService {
return result;
}
public static async getTasks() {
- const result: { taskElement: Task; element: string }[] = [];
+ const result: { taskElement: any; element: string }[] = [];
CloudRunnerLogger.log(``);
CloudRunnerLogger.log(`List Tasks`);
process.env.AWS_REGION = Input.region;
- const ecs = new ECS({ region: Input.region });
+ const ecs = AwsClientFactory.getECS();
const clusters = (await ecs.send(new ListClustersCommand({}))).clusterArns || [];
CloudRunnerLogger.log(`Task Clusters ${clusters.length}`);
for (const element of clusters) {
- const input: ListTasksCommandInput = {
+ const input = {
cluster: element,
};
-
const list = (await ecs.send(new ListTasksCommand(input))).taskArns || [];
if (list.length > 0) {
- const describeInput: DescribeTasksCommandInput = { tasks: list, cluster: element };
+ const describeInput = { tasks: list, cluster: element };
const describeList = (await ecs.send(new DescribeTasksCommand(describeInput))).tasks || [];
if (describeList.length === 0) {
CloudRunnerLogger.log(`No Tasks`);
@@ -132,7 +117,7 @@ export class TaskService {
}
public static async awsDescribeJob(job: string) {
process.env.AWS_REGION = Input.region;
- const CF = new CloudFormation({ region: Input.region });
+ const CF = AwsClientFactory.getCloudFormation();
try {
const stack =
(await CF.send(new ListStacksCommand({}))).StackSummaries?.find((_x) => _x.StackName === job) || undefined;
@@ -163,10 +148,10 @@ export class TaskService {
}
}
public static async getLogGroups() {
- const result: Array = [];
+ const result: any[] = [];
process.env.AWS_REGION = Input.region;
- const ecs = new CloudWatchLogs();
- let logStreamInput: DescribeLogGroupsCommandInput = {
+ const ecs = AwsClientFactory.getCloudWatchLogs();
+ let logStreamInput: any = {
/* logGroupNamePrefix: 'game-ci' */
};
let logGroupsDescribe = await ecs.send(new DescribeLogGroupsCommand(logStreamInput));
@@ -197,8 +182,8 @@ export class TaskService {
}
public static async getLocks() {
process.env.AWS_REGION = Input.region;
- const s3 = new S3({ region: Input.region });
- const listRequest: ListObjectsCommandInput = {
+ const s3 = AwsClientFactory.getS3();
+ const listRequest = {
Bucket: CloudRunner.buildParameters.awsStackName,
};