skuba 4.3.0-beta.0 → 4.4.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (80) hide show
  1. package/README.md +1 -1
  2. package/jest/moduleNameMapper.test.ts +7 -8
  3. package/lib/api/git/pull.d.ts +3 -3
  4. package/lib/api/git/pull.js +1 -1
  5. package/lib/api/github/index.d.ts +1 -1
  6. package/lib/api/github/index.js +4 -4
  7. package/lib/api/github/index.js.map +1 -1
  8. package/lib/api/github/push.d.ts +25 -14
  9. package/lib/api/github/push.js +41 -26
  10. package/lib/api/github/push.js.map +1 -1
  11. package/lib/api/jest/index.d.ts +23 -24
  12. package/lib/api/jest/index.js.map +1 -1
  13. package/lib/cli/configure/analyseDependencies.js +1 -2
  14. package/lib/cli/configure/analyseDependencies.js.map +1 -1
  15. package/lib/cli/configure/ensureTemplateCompletion.js +2 -2
  16. package/lib/cli/configure/ensureTemplateCompletion.js.map +1 -1
  17. package/lib/cli/configure/modules/tsconfig.js +3 -2
  18. package/lib/cli/configure/modules/tsconfig.js.map +1 -1
  19. package/lib/cli/configure/processing/package.d.ts +2 -2
  20. package/lib/cli/configure/processing/package.js +8 -10
  21. package/lib/cli/configure/processing/package.js.map +1 -1
  22. package/lib/cli/lint/autofix.js +3 -2
  23. package/lib/cli/lint/autofix.js.map +1 -1
  24. package/lib/cli/test/reporters/github/annotations.js +4 -1
  25. package/lib/cli/test/reporters/github/annotations.js.map +1 -1
  26. package/lib/utils/args.d.ts +1 -1
  27. package/lib/utils/version.d.ts +1 -0
  28. package/lib/utils/version.js +11 -3
  29. package/lib/utils/version.js.map +1 -1
  30. package/package.json +51 -24
  31. package/template/base/_.eslintignore +5 -2
  32. package/template/base/_.gitignore +3 -2
  33. package/template/base/_.prettierignore +5 -2
  34. package/template/express-rest-api/.buildkite/pipeline.yml +4 -4
  35. package/template/express-rest-api/.gantry/common.yml +1 -1
  36. package/template/express-rest-api/Dockerfile +1 -1
  37. package/template/express-rest-api/Dockerfile.dev-deps +1 -1
  38. package/template/express-rest-api/README.md +11 -14
  39. package/template/express-rest-api/gantry.apply.yml +2 -0
  40. package/template/express-rest-api/gantry.build.yml +2 -0
  41. package/template/express-rest-api/package.json +1 -1
  42. package/template/greeter/.buildkite/pipeline.yml +1 -1
  43. package/template/greeter/Dockerfile +1 -1
  44. package/template/greeter/README.md +12 -15
  45. package/template/koa-rest-api/.buildkite/pipeline.yml +4 -4
  46. package/template/koa-rest-api/.gantry/common.yml +1 -1
  47. package/template/koa-rest-api/Dockerfile +1 -1
  48. package/template/koa-rest-api/Dockerfile.dev-deps +1 -1
  49. package/template/koa-rest-api/README.md +11 -14
  50. package/template/koa-rest-api/gantry.apply.yml +2 -0
  51. package/template/koa-rest-api/gantry.build.yml +2 -0
  52. package/template/koa-rest-api/package.json +5 -5
  53. package/template/koa-rest-api/src/api/jobs/postJob.test.ts +7 -3
  54. package/template/koa-rest-api/src/framework/server.test.ts +18 -18
  55. package/template/koa-rest-api/src/framework/validation.test.ts +15 -6
  56. package/template/lambda-sqs-worker/.buildkite/pipeline.yml +2 -3
  57. package/template/lambda-sqs-worker/Dockerfile +1 -1
  58. package/template/lambda-sqs-worker/README.md +10 -13
  59. package/template/lambda-sqs-worker/package.json +1 -1
  60. package/template/lambda-sqs-worker/serverless.yml +0 -3
  61. package/template/lambda-sqs-worker/src/app.test.ts +7 -7
  62. package/template/lambda-sqs-worker/src/framework/handler.test.ts +3 -3
  63. package/template/lambda-sqs-worker/src/framework/validation.test.ts +17 -10
  64. package/template/lambda-sqs-worker/src/services/jobScorer.test.ts +2 -2
  65. package/template/lambda-sqs-worker/src/services/pipelineEventSender.test.ts +1 -1
  66. package/template/lambda-sqs-worker-cdk/.buildkite/pipeline.yml +2 -2
  67. package/template/lambda-sqs-worker-cdk/Dockerfile +1 -1
  68. package/template/lambda-sqs-worker-cdk/infra/__snapshots__/appStack.test.ts.snap +224 -218
  69. package/template/lambda-sqs-worker-cdk/infra/appStack.ts +1 -0
  70. package/template/oss-npm-package/README.md +9 -11
  71. package/template/oss-npm-package/_package.json +1 -1
  72. package/template/private-npm-package/README.md +6 -12
  73. package/template/private-npm-package/_package.json +1 -1
  74. package/template/express-rest-api/.me +0 -22
  75. package/template/greeter/.me +0 -20
  76. package/template/koa-rest-api/.me +0 -22
  77. package/template/lambda-sqs-worker/.me +0 -22
  78. package/template/lambda-sqs-worker-cdk/.me +0 -22
  79. package/template/oss-npm-package/.me +0 -21
  80. package/template/private-npm-package/.me +0 -21
@@ -1,11 +1,11 @@
1
1
  {
2
2
  "dependencies": {
3
- "@koa/router": "^10.1.1",
3
+ "@koa/router": "^12.0.0",
4
4
  "@opentelemetry/api": "^1.1.0",
5
5
  "@opentelemetry/exporter-collector-grpc": "^0.25.0",
6
- "@opentelemetry/instrumentation-aws-sdk": "^0.7.0",
7
- "@opentelemetry/instrumentation-http": "^0.28.0",
8
- "@opentelemetry/sdk-node": "^0.28.0",
6
+ "@opentelemetry/instrumentation-aws-sdk": "^0.8.0",
7
+ "@opentelemetry/instrumentation-http": "^0.32.0",
8
+ "@opentelemetry/sdk-node": "^0.32.0",
9
9
  "@seek/logger": "^5.0.1",
10
10
  "aws-sdk": "^2.1039.0",
11
11
  "hot-shots": "^9.0.0",
@@ -28,7 +28,7 @@
28
28
  "@types/supertest": "^2.0.11",
29
29
  "@types/uuid": "^8.3.1",
30
30
  "chance": "^1.1.8",
31
- "pino-pretty": "^8.0.0",
31
+ "pino-pretty": "^9.0.0",
32
32
  "skuba": "*",
33
33
  "supertest": "^6.1.6"
34
34
  },
@@ -26,9 +26,13 @@ describe('postJobHandler', () => {
26
26
  .send(jobInput)
27
27
  .expect(422)
28
28
  .expect(({ text }) =>
29
- expect(text).toMatchInlineSnapshot(
30
- `"Expected { hirer: { id: string; }; }, but was incompatible"`,
31
- ),
29
+ expect(text).toMatchInlineSnapshot(`
30
+ "Validation failed:
31
+ {
32
+ "hirer": "Expected { id: string; }, but was missing"
33
+ }.
34
+ Object should match { hirer: { id: string; }; }"
35
+ `),
32
36
  );
33
37
  });
34
38
  });
@@ -29,9 +29,9 @@ describe('createApp', () => {
29
29
  .expect('server', /.+/)
30
30
  .expect('x-api-version', /.+/);
31
31
 
32
- expect(logger.error).not.toBeCalled();
32
+ expect(logger.error).not.toHaveBeenCalled();
33
33
 
34
- expect(logger.info).not.toBeCalled();
34
+ expect(logger.info).not.toHaveBeenCalled();
35
35
 
36
36
  metricsClient.expectTagSubset(['env:test', 'version:test']);
37
37
  metricsClient.expectTagSubset([
@@ -51,9 +51,9 @@ describe('createApp', () => {
51
51
  .expect('server', /.+/)
52
52
  .expect('x-api-version', /.+/);
53
53
 
54
- expect(logger.error).not.toBeCalled();
54
+ expect(logger.error).not.toHaveBeenCalled();
55
55
 
56
- expect(logger.info).not.toBeCalled();
56
+ expect(logger.info).not.toHaveBeenCalled();
57
57
 
58
58
  metricsClient.expectTagSubset([
59
59
  'http_method:put',
@@ -72,9 +72,9 @@ describe('createApp', () => {
72
72
  .expect('server', /.+/)
73
73
  .expect('x-api-version', /.+/);
74
74
 
75
- expect(logger.error).not.toBeCalled();
75
+ expect(logger.error).not.toHaveBeenCalled();
76
76
 
77
- expect(logger.info).nthCalledWith(
77
+ expect(logger.info).toHaveBeenNthCalledWith(
78
78
  1,
79
79
  expect.objectContaining({ status: 404 }),
80
80
  'Client error',
@@ -102,9 +102,9 @@ describe('createApp', () => {
102
102
  .expect('server', /.+/)
103
103
  .expect('x-api-version', /.+/);
104
104
 
105
- expect(logger.error).not.toBeCalled();
105
+ expect(logger.error).not.toHaveBeenCalled();
106
106
 
107
- expect(logger.info).nthCalledWith(
107
+ expect(logger.info).toHaveBeenNthCalledWith(
108
108
  1,
109
109
  expect.objectContaining({ status: 400 }),
110
110
  'Client error',
@@ -129,9 +129,9 @@ describe('createApp', () => {
129
129
  .expect('server', /.+/)
130
130
  .expect('x-api-version', /.+/);
131
131
 
132
- expect(logger.error).not.toBeCalled();
132
+ expect(logger.error).not.toHaveBeenCalled();
133
133
 
134
- expect(logger.info).nthCalledWith(
134
+ expect(logger.info).toHaveBeenNthCalledWith(
135
135
  1,
136
136
  expect.objectContaining({ err: expect.any(Error), status: 400 }),
137
137
  'Client error',
@@ -156,13 +156,13 @@ describe('createApp', () => {
156
156
  .expect('server', /.+/)
157
157
  .expect('x-api-version', /.+/);
158
158
 
159
- expect(logger.error).nthCalledWith(
159
+ expect(logger.error).toHaveBeenNthCalledWith(
160
160
  1,
161
161
  expect.objectContaining({ err: expect.any(Error), status: 500 }),
162
162
  'Server error',
163
163
  );
164
164
 
165
- expect(logger.info).not.toBeCalled();
165
+ expect(logger.info).not.toHaveBeenCalled();
166
166
 
167
167
  metricsClient.expectTagSubset([
168
168
  'http_method:get',
@@ -185,13 +185,13 @@ describe('createApp', () => {
185
185
  .expect('server', /.+/)
186
186
  .expect('x-api-version', /.+/);
187
187
 
188
- expect(logger.error).nthCalledWith(
188
+ expect(logger.error).toHaveBeenNthCalledWith(
189
189
  1,
190
190
  expect.objectContaining({ err, status: 500 }),
191
191
  'Server error',
192
192
  );
193
193
 
194
- expect(logger.info).not.toBeCalled();
194
+ expect(logger.info).not.toHaveBeenCalled();
195
195
 
196
196
  metricsClient.expectTagSubset([
197
197
  'http_method:get',
@@ -213,13 +213,13 @@ describe('createApp', () => {
213
213
  .expect('server', /.+/)
214
214
  .expect('x-api-version', /.+/);
215
215
 
216
- expect(logger.error).nthCalledWith(
216
+ expect(logger.error).toHaveBeenNthCalledWith(
217
217
  1,
218
218
  expect.objectContaining({ err: null, status: 500 }),
219
219
  'Server error',
220
220
  );
221
221
 
222
- expect(logger.info).not.toBeCalled();
222
+ expect(logger.info).not.toHaveBeenCalled();
223
223
 
224
224
  metricsClient.expectTagSubset([
225
225
  'http_method:get',
@@ -242,13 +242,13 @@ describe('createApp', () => {
242
242
  .expect('server', /.+/)
243
243
  .expect('x-api-version', /.+/);
244
244
 
245
- expect(logger.error).nthCalledWith(
245
+ expect(logger.error).toHaveBeenNthCalledWith(
246
246
  1,
247
247
  expect.objectContaining({ err, status: 500 }),
248
248
  'Server error',
249
249
  );
250
250
 
251
- expect(logger.info).not.toBeCalled();
251
+ expect(logger.info).not.toHaveBeenCalled();
252
252
 
253
253
  metricsClient.expectTagSubset([
254
254
  'http_method:get',
@@ -42,9 +42,13 @@ describe('validate', () => {
42
42
  .send({ ...idDescription, id: null })
43
43
  .expect(422)
44
44
  .expect(({ text }) =>
45
- expect(text).toMatchInlineSnapshot(
46
- `"Expected { id: string; description: string; }, but was incompatible"`,
47
- ),
45
+ expect(text).toMatchInlineSnapshot(`
46
+ "Validation failed:
47
+ {
48
+ "id": "Expected string, but was null"
49
+ }.
50
+ Object should match { id: string; description: string; }"
51
+ `),
48
52
  );
49
53
  });
50
54
 
@@ -54,8 +58,13 @@ describe('validate', () => {
54
58
  .send({})
55
59
  .expect(422)
56
60
  .expect(({ text }) =>
57
- expect(text).toMatchInlineSnapshot(
58
- `"Expected { id: string; description: string; }, but was incompatible"`,
59
- ),
61
+ expect(text).toMatchInlineSnapshot(`
62
+ "Validation failed:
63
+ {
64
+ "id": "Expected string, but was missing",
65
+ "description": "Expected string, but was missing"
66
+ }.
67
+ Object should match { id: string; description: string; }"
68
+ `),
60
69
  ));
61
70
  });
@@ -32,10 +32,9 @@ configs:
32
32
  - *aws-sm
33
33
  - *private-npm
34
34
  - *docker-ecr-cache
35
- - docker-compose#v3.9.0:
35
+ - docker-compose#v3.10.0:
36
36
  dependencies: false
37
37
  run: app
38
- tty: false
39
38
  retry:
40
39
  manual:
41
40
  # Only use this if you need to roll back a deployment ASAP.
@@ -61,7 +60,7 @@ steps:
61
60
  - *aws-sm
62
61
  - *private-npm
63
62
  - *docker-ecr-cache
64
- - docker-compose#v3.9.0:
63
+ - docker-compose#v3.10.0:
65
64
  run: app
66
65
  timeout_in_minutes: 10
67
66
 
@@ -1,6 +1,6 @@
1
1
  # syntax=docker/dockerfile:1.2
2
2
 
3
- FROM node:16-alpine AS dev-deps
3
+ FROM --platform=arm64 node:16-alpine AS dev-deps
4
4
 
5
5
  WORKDIR /workdir
6
6
 
@@ -4,23 +4,25 @@
4
4
 
5
5
  Next steps:
6
6
 
7
- 1. [ ] Finish templating if this was skipped earlier:
7
+ 1. [ ] Check if your team has a Graviton-based Buildkite cluster;
8
+ see the [ARM64 guide] for more information.
9
+ 2. [ ] Finish templating if this was skipped earlier:
8
10
 
9
11
  ```shell
10
12
  yarn skuba configure
11
13
  ```
12
14
 
13
- 2. [ ] Create a new repository in the appropriate GitHub organisation.
14
- 3. [ ] Add the repository to BuildAgency;
15
+ 3. [ ] Create a new repository in the appropriate GitHub organisation.
16
+ 4. [ ] Add the repository to BuildAgency;
15
17
  see [Builds at SEEK] for more information.
16
- 4. [ ] Fill out [.me](.me) to power SEEK's system catalogue;
17
- see the [Codex] documentation for more information.
18
18
  5. [ ] Add deployment bucket configuration and data classification tags to [serverless.yml](serverless.yml).
19
19
  6. [ ] Push local commits to the upstream GitHub branch.
20
20
  7. [ ] Configure [GitHub repository settings].
21
- 8. [ ] Keep dependencies up to date with [Renovate];
22
- request installation in [SEEK-Jobs/renovate].
23
- 9. [ ] Delete this checklist 😌.
21
+ 8. [ ] Delete this checklist 😌.
22
+
23
+ [arm64 guide]: https://seek-oss.github.io/skuba/docs/deep-dives/arm64.html
24
+ [builds at seek]: https://builds-at-seek.ssod.skinfra.xyz
25
+ [github repository settings]: https://github.com/<%-orgName%>/<%-repoName%>/settings
24
26
 
25
27
  ## Design
26
28
 
@@ -127,12 +129,7 @@ TODO: add support links for the prod environment.
127
129
  - Splunk logs
128
130
  -->
129
131
 
130
- [builds at seek]: https://builds-at-seek.ssod.skinfra.xyz
131
132
  [codedeploy]: https://docs.aws.amazon.com/codedeploy
132
- [codex]: https://codex.ssod.skinfra.xyz/docs
133
- [github repository settings]: https://github.com/<%-orgName%>/<%-repoName%>/settings
134
133
  [lambda]: https://docs.aws.amazon.com/lambda
135
- [renovate]: https://github.com/apps/renovate
136
- [seek-jobs/renovate]: https://github.com/SEEK-Jobs/renovate
137
134
  [serverless]: https://www.serverless.com/
138
135
  [technology strategy]: https://tech-strategy.ssod.skinfra.xyz
@@ -12,7 +12,7 @@
12
12
  "@types/chance": "^1.1.3",
13
13
  "@types/node": "^16.0.0",
14
14
  "chance": "^1.1.8",
15
- "pino-pretty": "^8.0.0",
15
+ "pino-pretty": "^9.0.0",
16
16
  "serverless": "^3.17.0",
17
17
  "serverless-plugin-canary-deployments": "^0.8.0",
18
18
  "serverless-prune-plugin": "^2.0.0",
@@ -54,9 +54,6 @@ provider:
54
54
  - Action: sns:Publish
55
55
  Effect: Allow
56
56
  Resource: !Ref DestinationTopic
57
- - Action: sqs:SendMessage*
58
- Effect: Allow
59
- Resource: !GetAtt DeadLetterQueue.Arn
60
57
  stackTags:
61
58
  # TODO: add data classification tags
62
59
  # https://rfc.skinfra.xyz/RFC019-AWS-Tagging-Standard.html#seekdataconsumers
@@ -42,9 +42,9 @@ describe('handler', () => {
42
42
 
43
43
  await expect(app.handler(event, ctx)).resolves.toBeUndefined();
44
44
 
45
- expect(scoringService.request).toBeCalledTimes(1);
45
+ expect(scoringService.request).toHaveBeenCalledTimes(1);
46
46
 
47
- expect(logger.error).not.toBeCalled();
47
+ expect(logger.error).not.toHaveBeenCalled();
48
48
 
49
49
  expect(logger.info.mock.calls).toEqual([
50
50
  [{ count: 1 }, 'received jobs'],
@@ -57,7 +57,7 @@ describe('handler', () => {
57
57
  ['job.scored', 1],
58
58
  ]);
59
59
 
60
- expect(sns.publish).toBeCalledTimes(1);
60
+ expect(sns.publish).toHaveBeenCalledTimes(1);
61
61
  });
62
62
 
63
63
  it('throws on invalid input', () => {
@@ -75,7 +75,7 @@ describe('handler', () => {
75
75
 
76
76
  await expect(app.handler(event, ctx)).rejects.toThrow('invoke error');
77
77
 
78
- expect(logger.error).toBeCalledWith({ err }, 'request');
78
+ expect(logger.error).toHaveBeenCalledWith({ err }, 'request');
79
79
  });
80
80
 
81
81
  it('bubbles up SNS error', async () => {
@@ -87,7 +87,7 @@ describe('handler', () => {
87
87
 
88
88
  await expect(app.handler(event, ctx)).rejects.toThrow('invoke error');
89
89
 
90
- expect(logger.error).toBeCalledWith({ err }, 'request');
90
+ expect(logger.error).toHaveBeenCalledWith({ err }, 'request');
91
91
  });
92
92
 
93
93
  it('throws on zero records', async () => {
@@ -97,7 +97,7 @@ describe('handler', () => {
97
97
 
98
98
  await expect(app.handler(event, ctx)).rejects.toThrow('invoke error');
99
99
 
100
- expect(logger.error).toBeCalledWith({ err }, 'request');
100
+ expect(logger.error).toHaveBeenCalledWith({ err }, 'request');
101
101
  });
102
102
 
103
103
  it('throws on multiple records', async () => {
@@ -110,6 +110,6 @@ describe('handler', () => {
110
110
 
111
111
  await expect(app.handler(event, ctx)).rejects.toThrow('invoke error');
112
112
 
113
- expect(logger.error).toBeCalledWith({ err }, 'request');
113
+ expect(logger.error).toHaveBeenCalledWith({ err }, 'request');
114
114
  });
115
115
  });
@@ -25,7 +25,7 @@ describe('createHandler', () => {
25
25
 
26
26
  await expect(handler(input, ctx)).resolves.toBe(output);
27
27
 
28
- expect(logger.error).not.toBeCalled();
28
+ expect(logger.error).not.toHaveBeenCalled();
29
29
 
30
30
  expect(logger.info.mock.calls).toEqual([
31
31
  ['hello from handler'],
@@ -42,7 +42,7 @@ describe('createHandler', () => {
42
42
 
43
43
  expect(logger.error.mock.calls).toEqual([[{ err }, 'request']]);
44
44
 
45
- expect(logger.info).not.toBeCalled();
45
+ expect(logger.info).not.toHaveBeenCalled();
46
46
  });
47
47
 
48
48
  it('handles sync error', async () => {
@@ -56,6 +56,6 @@ describe('createHandler', () => {
56
56
 
57
57
  expect(logger.error.mock.calls).toEqual([[{ err }, 'request']]);
58
58
 
59
- expect(logger.info).not.toBeCalled();
59
+ expect(logger.info).not.toHaveBeenCalled();
60
60
  });
61
61
  });
@@ -28,21 +28,28 @@ describe('validateJson', () => {
28
28
  it('blocks mistyped prop', () => {
29
29
  const input = JSON.stringify({ ...idDescription, id: null });
30
30
 
31
- expect(() =>
32
- validateJson(input, filterIdDescription),
33
- ).toThrowErrorMatchingInlineSnapshot(
34
- `"Expected { id: string; description: string; }, but was incompatible"`,
35
- );
31
+ expect(() => validateJson(input, filterIdDescription))
32
+ .toThrowErrorMatchingInlineSnapshot(`
33
+ "Validation failed:
34
+ {
35
+ "id": "Expected string, but was null"
36
+ }.
37
+ Object should match { id: string; description: string; }"
38
+ `);
36
39
  });
37
40
 
38
41
  it('blocks missing prop', () => {
39
42
  const input = '{}';
40
43
 
41
- expect(() =>
42
- validateJson(input, filterIdDescription),
43
- ).toThrowErrorMatchingInlineSnapshot(
44
- `"Expected { id: string; description: string; }, but was incompatible"`,
45
- );
44
+ expect(() => validateJson(input, filterIdDescription))
45
+ .toThrowErrorMatchingInlineSnapshot(`
46
+ "Validation failed:
47
+ {
48
+ "id": "Expected string, but was missing",
49
+ "description": "Expected string, but was missing"
50
+ }.
51
+ Object should match { id: string; description: string; }"
52
+ `);
46
53
  });
47
54
 
48
55
  it('blocks invalid JSON', () => {
@@ -25,7 +25,7 @@ describe('scoreJobPublishedEvent', () => {
25
25
  eventType: 'JobScored',
26
26
  });
27
27
 
28
- expect(scoringService.request).toBeCalledTimes(1);
28
+ expect(scoringService.request).toHaveBeenCalledTimes(1);
29
29
  });
30
30
 
31
31
  it('bubbles up scoring service error', async () => {
@@ -39,6 +39,6 @@ describe('scoreJobPublishedEvent', () => {
39
39
  ),
40
40
  ).rejects.toThrow(err);
41
41
 
42
- expect(scoringService.request).toBeCalledTimes(1);
42
+ expect(scoringService.request).toHaveBeenCalledTimes(1);
43
43
  });
44
44
  });
@@ -15,7 +15,7 @@ describe('sendPipelineEvent', () => {
15
15
 
16
16
  await expect(sendPipelineEvent({})).resolves.toBe(messageId);
17
17
 
18
- expect(sns.publish).toBeCalledTimes(1);
18
+ expect(sns.publish).toHaveBeenCalledTimes(1);
19
19
  });
20
20
 
21
21
  it('bubbles up SNS error', () => {
@@ -32,7 +32,7 @@ configs:
32
32
  - *aws-sm
33
33
  - *private-npm
34
34
  - *docker-ecr-cache
35
- - docker-compose#v3.9.0:
35
+ - docker-compose#v3.10.0:
36
36
  dependencies: false
37
37
  run: app
38
38
  retry:
@@ -57,7 +57,7 @@ steps:
57
57
  - *aws-sm
58
58
  - *private-npm
59
59
  - *docker-ecr-cache
60
- - docker-compose#v3.9.0:
60
+ - docker-compose#v3.10.0:
61
61
  run: app
62
62
  timeout_in_minutes: 10
63
63
 
@@ -1,6 +1,6 @@
1
1
  # syntax=docker/dockerfile:1.2
2
2
 
3
- FROM node:16-alpine AS dev-deps
3
+ FROM --platform=arm64 node:16-alpine AS dev-deps
4
4
 
5
5
  WORKDIR /workdir
6
6