Skip to content

Commit fca9f50

Browse files
authored
Merge pull request #1861 from philips-labs/develop
Release
2 parents 28dc5f0 + 819fa4f commit fca9f50

File tree

19 files changed

+800
-726
lines changed

19 files changed

+800
-726
lines changed

README.md

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -304,10 +304,11 @@ For time zones please check [TZ database name column](https://en.wikipedia.org/w
304304
Currently a beta feature! You can configure runners to be ephemeral, runners will be used only for one job. The feature should be used in conjunction with listening for the workflow job event. Please consider the following:
305305

306306
- The scale down lambda is still active, and should only remove orphan instances. But there is no strict check in place. So ensure you configure the `minimum_running_time_in_minutes` to a value that is high enough to got your runner booted and connected to avoid it got terminated before executing a job.
307-
- The messages sent from the webhook lambda to scale-up lambda are by default delayed delayed by SQS, to give available runners to option to start the job before the decision is made to scale more runners. For ephemeral runners there is no need to wait. Set `delay_webhook_event` to `0`.
307+
- The messages sent from the webhook lambda to scale-up lambda are by default delayed delayed by SQS, to give available runners to option to start the job before the decision is made to scale more runners. For ephemeral runners there is no need to wait. Set `delay_webhook_event` to `0`.
308+
- All events on the queue will lead to a new runner crated by the lambda. By setting `enable_job_queued_check` to `true` you can enforce only create a runner if the event has a correlated queued job. Setting this can avoid creating useless runners, for example whn jobs got cancelled before a runner is created. We suggest to use this in combination with a pool.
308309
- To ensure runners are created in the same order GitHub sends the events we use by default a FIFO queue, this is mainly relevant for repo level runners. For ephemeral runners you can set `fifo_build_queue` to `false`.
309310
- Error related to scaling should be retried via SQS. You can configure `job_queue_retention_in_seconds` `redrive_build_queue` to tune the behavior. We have no mechanism to avoid events will never processed, which means potential no runner could be created and the job in GitHub can time out in 6 hours.
310-
311+
311312
The example for [ephemeral runners](./examples/ephemeral) is based on the [default example](./examples/default). Have look on the diff to see the major configuration differences.
312313

313314
### Prebuilt Images
@@ -407,6 +408,7 @@ In case the setup does not work as intended follow the trace of events:
407408
| <a name="input_disable_runner_autoupdate"></a> [disable\_runner\_autoupdate](#input\_disable\_runner\_autoupdate) | Disable the auto update of the github runner agent. Be-aware there is a grace period of 30 days, see also the [GitHub article](https://github.blog/changelog/2022-02-01-github-actions-self-hosted-runners-can-now-disable-automatic-updates/) | `bool` | `false` | no |
408409
| <a name="input_enable_cloudwatch_agent"></a> [enable\_cloudwatch\_agent](#input\_enable\_cloudwatch\_agent) | Enabling the cloudwatch agent on the ec2 runner instances, the runner contains default config. Configuration can be overridden via `cloudwatch_config`. | `bool` | `true` | no |
409410
| <a name="input_enable_ephemeral_runners"></a> [enable\_ephemeral\_runners](#input\_enable\_ephemeral\_runners) | Enable ephemeral runners, runners will only be used once. | `bool` | `false` | no |
411+
| <a name="input_enable_job_queued_check"></a> [enable\_job\_queued\_check](#input\_enable\_job\_queued\_check) | Only scale if the job event received by the scale up lambda is is in the state queued. By default enabled for non ephemeral runners and disabled for ephemeral. Set this variable to overwrite the default behavior. | `bool` | `null` | no |
410412
| <a name="input_enable_managed_runner_security_group"></a> [enable\_managed\_runner\_security\_group](#input\_enable\_managed\_runner\_security\_group) | Enabling the default managed security group creation. Unmanaged security groups can be specified via `runner_additional_security_group_ids`. | `bool` | `true` | no |
411413
| <a name="input_enable_organization_runners"></a> [enable\_organization\_runners](#input\_enable\_organization\_runners) | Register runners to organization, instead of repo level | `bool` | `false` | no |
412414
| <a name="input_enable_ssm_on_runners"></a> [enable\_ssm\_on\_runners](#input\_enable\_ssm\_on\_runners) | Enable to allow access the runner instances for debugging purposes via SSM. Note that this adds additional permissions to the runner instances. | `bool` | `false` | no |

examples/ephemeral/main.tf

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -63,6 +63,9 @@ module "runners" {
6363
# size = 20
6464
# schedule_expression = "cron(* * * * ? *)"
6565
# }]
66+
#
67+
#
68+
enable_job_queued_check = true
6669

6770
# configure your pre-built AMI
6871
# enabled_userdata = false

main.tf

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -148,6 +148,7 @@ module "runners" {
148148
github_app_parameters = local.github_app_parameters
149149
enable_organization_runners = var.enable_organization_runners
150150
enable_ephemeral_runners = var.enable_ephemeral_runners
151+
enable_job_queued_check = var.enable_job_queued_check
151152
disable_runner_autoupdate = var.disable_runner_autoupdate
152153
enable_managed_runner_security_group = var.enable_managed_runner_security_group
153154
scale_down_schedule_expression = var.scale_down_schedule_expression

modules/runner-binaries-syncer/lambdas/runner-binaries-syncer/package.json

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,7 @@
2323
"@typescript-eslint/eslint-plugin": "^4.33.0",
2424
"@typescript-eslint/parser": "^4.33.0",
2525
"@vercel/ncc": "^0.33.3",
26-
"aws-sdk": "^2.1090.0",
26+
"aws-sdk": "^2.1094.0",
2727
"eslint": "^7.32.0",
2828
"eslint-plugin-prettier": "4.0.0",
2929
"jest": "^27.5.1",
@@ -34,7 +34,7 @@
3434
"typescript": "^4.6.2"
3535
},
3636
"dependencies": {
37-
"axios": "^0.26.0",
37+
"axios": "^0.26.1",
3838
"tslog": "^3.3.2"
3939
}
4040
}

modules/runner-binaries-syncer/lambdas/runner-binaries-syncer/yarn.lock

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1086,10 +1086,10 @@ asynckit@^0.4.0:
10861086
resolved "https://registry.yarnpkg.com/asynckit/-/asynckit-0.4.0.tgz#c79ed97f7f34cb8f2ba1bc9790bcc366474b4b79"
10871087
integrity sha1-x57Zf380y48robyXkLzDZkdLS3k=
10881088

1089-
aws-sdk@^2.1090.0:
1090-
version "2.1090.0"
1091-
resolved "https://registry.yarnpkg.com/aws-sdk/-/aws-sdk-2.1090.0.tgz#c30e4cbc177e4c3b7792020cc79dfaf155cc8197"
1092-
integrity sha512-oHdfbiuSjK9mn6rrm5fsitdwv7jEiYzaYB0Xz1kqjIczcVX3JEc+9ySdxlueQf4o5G3RVUcLRF2pIc5j9vcHSg==
1089+
aws-sdk@^2.1094.0:
1090+
version "2.1094.0"
1091+
resolved "https://registry.yarnpkg.com/aws-sdk/-/aws-sdk-2.1094.0.tgz#85cc5fb416ce7af356f1dd1b14fbb714cd923800"
1092+
integrity sha512-g/pjEl1JKs8+UZSdfdTMwUh7oNSWy6LXkjd0WfI3TBVgU5+yE5bd1VtAiJxJ/kIOFwcWyGPy0fNkGjAqL6NAGw==
10931093
dependencies:
10941094
buffer "4.9.2"
10951095
events "1.1.1"
@@ -1101,10 +1101,10 @@ aws-sdk@^2.1090.0:
11011101
uuid "3.3.2"
11021102
xml2js "0.4.19"
11031103

1104-
axios@^0.26.0:
1105-
version "0.26.0"
1106-
resolved "https://registry.yarnpkg.com/axios/-/axios-0.26.0.tgz#9a318f1c69ec108f8cd5f3c3d390366635e13928"
1107-
integrity sha512-lKoGLMYtHvFrPVt3r+RBMp9nh34N0M8zEfCWqdWZx6phynIEhQqAdydpyBAAG211zlhX9Rgu08cOamy6XjE5Og==
1104+
axios@^0.26.1:
1105+
version "0.26.1"
1106+
resolved "https://registry.yarnpkg.com/axios/-/axios-0.26.1.tgz#1ede41c51fcf51bbbd6fd43669caaa4f0495aaa9"
1107+
integrity sha512-fPwcX4EvnSHuInCMItEhAGnaSEXRBjtzh9fOtsE6E1G6p7vl7edEeZe11QHf18+6+9gR5PbKV/sGKNaD8YaMeA==
11081108
dependencies:
11091109
follow-redirects "^1.14.8"
11101110

modules/runners/README.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -124,6 +124,7 @@ yarn run dist
124124
| <a name="input_egress_rules"></a> [egress\_rules](#input\_egress\_rules) | List of egress rules for the GitHub runner instances. | <pre>list(object({<br> cidr_blocks = list(string)<br> ipv6_cidr_blocks = list(string)<br> prefix_list_ids = list(string)<br> from_port = number<br> protocol = string<br> security_groups = list(string)<br> self = bool<br> to_port = number<br> description = string<br> }))</pre> | <pre>[<br> {<br> "cidr_blocks": [<br> "0.0.0.0/0"<br> ],<br> "description": null,<br> "from_port": 0,<br> "ipv6_cidr_blocks": [<br> "::/0"<br> ],<br> "prefix_list_ids": null,<br> "protocol": "-1",<br> "security_groups": null,<br> "self": null,<br> "to_port": 0<br> }<br>]</pre> | no |
125125
| <a name="input_enable_cloudwatch_agent"></a> [enable\_cloudwatch\_agent](#input\_enable\_cloudwatch\_agent) | Enabling the cloudwatch agent on the ec2 runner instances, the runner contains default config. Configuration can be overridden via `cloudwatch_config`. | `bool` | `true` | no |
126126
| <a name="input_enable_ephemeral_runners"></a> [enable\_ephemeral\_runners](#input\_enable\_ephemeral\_runners) | Enable ephemeral runners, runners will only be used once. | `bool` | `false` | no |
127+
| <a name="input_enable_job_queued_check"></a> [enable\_job\_queued\_check](#input\_enable\_job\_queued\_check) | Only scale if the job event received by the scale up lambda is is in the state queued. By default enabled for non ephemeral runners and disabled for ephemeral. Set this variable to overwrite the default behavior. | `bool` | `null` | no |
127128
| <a name="input_enable_managed_runner_security_group"></a> [enable\_managed\_runner\_security\_group](#input\_enable\_managed\_runner\_security\_group) | Enabling the default managed security group creation. Unmanaged security groups can be specified via `runner_additional_security_group_ids`. | `bool` | `true` | no |
128129
| <a name="input_enable_organization_runners"></a> [enable\_organization\_runners](#input\_enable\_organization\_runners) | n/a | `bool` | n/a | yes |
129130
| <a name="input_enable_ssm_on_runners"></a> [enable\_ssm\_on\_runners](#input\_enable\_ssm\_on\_runners) | Enable to allow access to the runner instances for debugging purposes via SSM. Note that this adds additional permissions to the runner instances. | `bool` | n/a | yes |

modules/runners/lambdas/runners/package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -36,7 +36,7 @@
3636
"ts-node-dev": "^1.1.6"
3737
},
3838
"dependencies": {
39-
"@aws-sdk/client-ssm": "^3.53.0",
39+
"@aws-sdk/client-ssm": "^3.54.0",
4040
"@octokit/auth-app": "3.6.1",
4141
"@octokit/rest": "^18.12.0",
4242
"@octokit/types": "^6.34.0",

modules/runners/lambdas/runners/src/aws/runners.test.ts

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -217,7 +217,7 @@ describe('create runner', () => {
217217
expect(mockSSM.putParameter).toBeCalledWith({
218218
Name: `unit-test-environment-${instance}`,
219219
Type: 'SecureString',
220-
Value: 'bla',
220+
Value: '--token foo --url http://github.com',
221221
});
222222
}
223223
});
@@ -247,7 +247,7 @@ describe('create runner', () => {
247247
await createRunner(createRunnerConfig(defaultRunnerConfig));
248248
expect(mockSSM.putParameter).toBeCalledWith({
249249
Name: `${ENVIRONMENT}-i-1234`,
250-
Value: 'bla',
250+
Value: '--token foo --url http://github.com',
251251
Type: 'SecureString',
252252
});
253253
});
@@ -358,7 +358,7 @@ interface RunnerConfig {
358358

359359
function createRunnerConfig(runnerConfig: RunnerConfig): RunnerInputParameters {
360360
return {
361-
runnerServiceConfig: 'bla',
361+
runnerServiceConfig: ['--token foo', '--url http://github.com'],
362362
environment: ENVIRONMENT,
363363
runnerType: runnerConfig.type,
364364
runnerOwner: REPO_NAME,

modules/runners/lambdas/runners/src/aws/runners.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,7 @@ export interface ListRunnerFilters {
2929
}
3030

3131
export interface RunnerInputParameters {
32-
runnerServiceConfig: string;
32+
runnerServiceConfig: string[];
3333
environment: string;
3434
runnerType: 'Org' | 'Repo';
3535
runnerOwner: string;
@@ -207,7 +207,7 @@ export async function createRunner(runnerParameters: RunnerInputParameters): Pro
207207
await ssm
208208
.putParameter({
209209
Name: `${runnerParameters.environment}-${instance}`,
210-
Value: runnerParameters.runnerServiceConfig,
210+
Value: runnerParameters.runnerServiceConfig.join(' '),
211211
Type: 'SecureString',
212212
})
213213
.promise();

modules/runners/lambdas/runners/src/scale-runners/scale-up.test.ts

Lines changed: 59 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -53,7 +53,7 @@ const cleanEnv = process.env;
5353

5454
const EXPECTED_RUNNER_PARAMS: RunnerInputParameters = {
5555
environment: 'unit-test-environment',
56-
runnerServiceConfig: `--url https://github.enterprise.something/${TEST_DATA.repositoryOwner} --token 1234abcd`,
56+
runnerServiceConfig: [`--url https://github.enterprise.something/${TEST_DATA.repositoryOwner}`, '--token 1234abcd'],
5757
runnerType: 'Org',
5858
runnerOwner: TEST_DATA.repositoryOwner,
5959
launchTemplateName: 'lt-1',
@@ -236,8 +236,11 @@ describe('scaleUp with GHES', () => {
236236
process.env.RUNNER_EXTRA_LABELS = 'label1,label2';
237237
process.env.RUNNER_GROUP_NAME = 'TEST_GROUP';
238238
await scaleUpModule.scaleUp('aws:sqs', TEST_DATA);
239-
expectedRunnerParams.runnerServiceConfig =
240-
expectedRunnerParams.runnerServiceConfig + ` --labels label1,label2 --runnergroup TEST_GROUP`;
239+
expectedRunnerParams.runnerServiceConfig = [
240+
...expectedRunnerParams.runnerServiceConfig,
241+
'--labels label1,label2',
242+
'--runnergroup TEST_GROUP',
243+
];
241244
expect(createRunner).toBeCalledWith(expectedRunnerParams);
242245
});
243246
});
@@ -248,10 +251,10 @@ describe('scaleUp with GHES', () => {
248251
expectedRunnerParams = { ...EXPECTED_RUNNER_PARAMS };
249252
expectedRunnerParams.runnerType = 'Repo';
250253
expectedRunnerParams.runnerOwner = `${TEST_DATA.repositoryOwner}/${TEST_DATA.repositoryName}`;
251-
expectedRunnerParams.runnerServiceConfig =
252-
`--url ` +
253-
`https://github.enterprise.something/${TEST_DATA.repositoryOwner}/${TEST_DATA.repositoryName} ` +
254-
`--token 1234abcd`;
254+
expectedRunnerParams.runnerServiceConfig = [
255+
`--url https://github.enterprise.something/${TEST_DATA.repositoryOwner}/${TEST_DATA.repositoryName}`,
256+
`--token 1234abcd`,
257+
];
255258
});
256259

257260
it('gets the current repo level runners', async () => {
@@ -317,15 +320,21 @@ describe('scaleUp with GHES', () => {
317320
it('creates a runner with correct config and labels', async () => {
318321
process.env.RUNNER_EXTRA_LABELS = 'label1,label2';
319322
await scaleUpModule.scaleUp('aws:sqs', TEST_DATA);
320-
expectedRunnerParams.runnerServiceConfig = expectedRunnerParams.runnerServiceConfig + ` --labels label1,label2`;
323+
expectedRunnerParams.runnerServiceConfig = [
324+
...expectedRunnerParams.runnerServiceConfig,
325+
`--labels label1,label2`,
326+
];
321327
expect(createRunner).toBeCalledWith(expectedRunnerParams);
322328
});
323329

324330
it('creates a runner and ensure the group argument is ignored', async () => {
325331
process.env.RUNNER_EXTRA_LABELS = 'label1,label2';
326332
process.env.RUNNER_GROUP_NAME = 'TEST_GROUP_IGNORED';
327333
await scaleUpModule.scaleUp('aws:sqs', TEST_DATA);
328-
expectedRunnerParams.runnerServiceConfig = expectedRunnerParams.runnerServiceConfig + ` --labels label1,label2`;
334+
expectedRunnerParams.runnerServiceConfig = [
335+
...expectedRunnerParams.runnerServiceConfig,
336+
`--labels label1,label2`,
337+
];
329338
expect(createRunner).toBeCalledWith(expectedRunnerParams);
330339
});
331340

@@ -353,6 +362,12 @@ describe('scaleUp with public GH', () => {
353362
});
354363
});
355364

365+
it('not checking queued workflows', async () => {
366+
process.env.ENABLE_JOB_QUEUED_CHECK = 'false';
367+
await scaleUpModule.scaleUp('aws:sqs', TEST_DATA);
368+
expect(mockOctokit.actions.getJobForWorkflowRun).not.toBeCalled();
369+
});
370+
356371
it('does not retrieve installation id if already set', async () => {
357372
const appSpy = jest.spyOn(ghAuth, 'createGithubAppAuth');
358373
const installationSpy = jest.spyOn(ghAuth, 'createGithubInstallationAuth');
@@ -393,8 +408,10 @@ describe('scaleUp with public GH', () => {
393408
beforeEach(() => {
394409
process.env.ENABLE_ORGANIZATION_RUNNERS = 'true';
395410
expectedRunnerParams = { ...EXPECTED_RUNNER_PARAMS };
396-
expectedRunnerParams.runnerServiceConfig =
397-
`--url https://github.com/${TEST_DATA.repositoryOwner} ` + `--token 1234abcd`;
411+
expectedRunnerParams.runnerServiceConfig = [
412+
`--url https://github.com/${TEST_DATA.repositoryOwner}`,
413+
`--token 1234abcd`,
414+
];
398415
});
399416

400417
it('gets the current org level runners', async () => {
@@ -435,8 +452,11 @@ describe('scaleUp with public GH', () => {
435452
process.env.RUNNER_EXTRA_LABELS = 'label1,label2';
436453
process.env.RUNNER_GROUP_NAME = 'TEST_GROUP';
437454
await scaleUpModule.scaleUp('aws:sqs', TEST_DATA);
438-
expectedRunnerParams.runnerServiceConfig =
439-
expectedRunnerParams.runnerServiceConfig + ` --labels label1,label2 --runnergroup TEST_GROUP`;
455+
expectedRunnerParams.runnerServiceConfig = [
456+
...expectedRunnerParams.runnerServiceConfig,
457+
`--labels label1,label2`,
458+
`--runnergroup TEST_GROUP`,
459+
];
440460
expect(createRunner).toBeCalledWith(expectedRunnerParams);
441461
});
442462
});
@@ -447,8 +467,10 @@ describe('scaleUp with public GH', () => {
447467
expectedRunnerParams = { ...EXPECTED_RUNNER_PARAMS };
448468
expectedRunnerParams.runnerType = 'Repo';
449469
expectedRunnerParams.runnerOwner = `${TEST_DATA.repositoryOwner}/${TEST_DATA.repositoryName}`;
450-
expectedRunnerParams.runnerServiceConfig =
451-
`--url https://github.com/${TEST_DATA.repositoryOwner}/${TEST_DATA.repositoryName} ` + `--token 1234abcd`;
470+
expectedRunnerParams.runnerServiceConfig = [
471+
`--url https://github.com/${TEST_DATA.repositoryOwner}/${TEST_DATA.repositoryName}`,
472+
`--token 1234abcd`,
473+
];
452474
});
453475

454476
it('gets the current repo level runners', async () => {
@@ -499,20 +521,27 @@ describe('scaleUp with public GH', () => {
499521
it('creates a runner with correct config and labels', async () => {
500522
process.env.RUNNER_EXTRA_LABELS = 'label1,label2';
501523
await scaleUpModule.scaleUp('aws:sqs', TEST_DATA);
502-
expectedRunnerParams.runnerServiceConfig = expectedRunnerParams.runnerServiceConfig + ` --labels label1,label2`;
524+
expectedRunnerParams.runnerServiceConfig = [
525+
...expectedRunnerParams.runnerServiceConfig,
526+
`--labels label1,label2`,
527+
];
503528
expect(createRunner).toBeCalledWith(expectedRunnerParams);
504529
});
505530

506531
it('creates a runner and ensure the group argument is ignored', async () => {
507532
process.env.RUNNER_EXTRA_LABELS = 'label1,label2';
508533
process.env.RUNNER_GROUP_NAME = 'TEST_GROUP_IGNORED';
509534
await scaleUpModule.scaleUp('aws:sqs', TEST_DATA);
510-
expectedRunnerParams.runnerServiceConfig = expectedRunnerParams.runnerServiceConfig + ` --labels label1,label2`;
535+
expectedRunnerParams.runnerServiceConfig = [
536+
...expectedRunnerParams.runnerServiceConfig,
537+
`--labels label1,label2`,
538+
];
511539
expect(createRunner).toBeCalledWith(expectedRunnerParams);
512540
});
513541

514542
it('ephemeral runners only run with workflow_job event, others should fail.', async () => {
515543
process.env.ENABLE_EPHEMERAL_RUNNERS = 'true';
544+
process.env.ENABLE_JOB_QUEUED_CHECK = 'false';
516545
await expect(
517546
scaleUpModule.scaleUp('aws:sqs', {
518547
...TEST_DATA,
@@ -523,15 +552,26 @@ describe('scaleUp with public GH', () => {
523552

524553
it('creates a ephemeral runner.', async () => {
525554
process.env.ENABLE_EPHEMERAL_RUNNERS = 'true';
555+
process.env.ENABLE_JOB_QUEUED_CHECK = 'false';
556+
await scaleUpModule.scaleUp('aws:sqs', TEST_DATA);
557+
expectedRunnerParams.runnerServiceConfig = [...expectedRunnerParams.runnerServiceConfig, `--ephemeral`];
558+
expect(mockOctokit.actions.getJobForWorkflowRun).not.toBeCalled();
559+
expect(createRunner).toBeCalledWith(expectedRunnerParams);
560+
});
561+
562+
it('creates a ephemeral runner after checking job is queued.', async () => {
563+
process.env.ENABLE_EPHEMERAL_RUNNERS = 'true';
564+
process.env.ENABLE_JOB_QUEUED_CHECK = 'true';
526565
await scaleUpModule.scaleUp('aws:sqs', TEST_DATA);
527-
expectedRunnerParams.runnerServiceConfig = expectedRunnerParams.runnerServiceConfig + ` --ephemeral`;
566+
expect(mockOctokit.actions.getJobForWorkflowRun).toBeCalled();
567+
expectedRunnerParams.runnerServiceConfig = [...expectedRunnerParams.runnerServiceConfig, `--ephemeral`];
528568
expect(createRunner).toBeCalledWith(expectedRunnerParams);
529569
});
530570

531571
it('disable auto update on the runner.', async () => {
532572
process.env.DISABLE_RUNNER_AUTOUPDATE = 'true';
533573
await scaleUpModule.scaleUp('aws:sqs', TEST_DATA);
534-
expectedRunnerParams.runnerServiceConfig = expectedRunnerParams.runnerServiceConfig + ` --disableupdate`;
574+
expectedRunnerParams.runnerServiceConfig = [...expectedRunnerParams.runnerServiceConfig, `--disableupdate`];
535575
expect(createRunner).toBeCalledWith(expectedRunnerParams);
536576
});
537577

0 commit comments

Comments
 (0)