skuba 12.1.0-main-20250810101347 → 12.1.0-main-20250812041011
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.
- package/lib/cli/build/assets.js +1 -1
- package/lib/cli/build/assets.js.map +2 -2
- package/lib/cli/init/getConfig.js +1 -1
- package/lib/cli/init/getConfig.js.map +2 -2
- package/lib/cli/lint/internal.js +1 -1
- package/lib/cli/lint/internal.js.map +2 -2
- package/lib/cli/lint/internalLints/upgrade/patches/8.2.1/upgradeESLint.js +1 -1
- package/lib/cli/lint/internalLints/upgrade/patches/8.2.1/upgradeESLint.js.map +2 -2
- package/package.json +4 -4
- package/template/base/jest.setup.ts +1 -1
- package/template/express-rest-api/.buildkite/pipeline.yml +6 -0
- package/template/express-rest-api/.env +1 -1
- package/template/express-rest-api/.gantry/dev.yml +5 -1
- package/template/express-rest-api/.gantry/prod.yml +5 -1
- package/template/express-rest-api/Dockerfile +1 -1
- package/template/express-rest-api/README.md +5 -5
- package/template/express-rest-api/gantry.apply.yml +17 -1
- package/template/express-rest-api/package.json +9 -3
- package/template/express-rest-api/src/api/healthCheck.ts +2 -2
- package/template/express-rest-api/src/config.ts +7 -7
- package/template/express-rest-api/src/framework/logging.ts +11 -7
- package/template/express-rest-api/src/framework/metrics.ts +1 -1
- package/template/express-rest-api/src/tracing.ts +56 -0
- package/template/greeter/README.md +2 -2
- package/template/greeter/package.json +1 -1
- package/template/koa-rest-api/.buildkite/pipeline.yml +6 -0
- package/template/koa-rest-api/.env +1 -1
- package/template/koa-rest-api/.gantry/dev.yml +3 -3
- package/template/koa-rest-api/.gantry/prod.yml +3 -3
- package/template/koa-rest-api/README.md +6 -6
- package/template/koa-rest-api/gantry.apply.yml +15 -3
- package/template/koa-rest-api/package.json +2 -3
- package/template/koa-rest-api/src/api/healthCheck.ts +2 -2
- package/template/koa-rest-api/src/config.ts +7 -7
- package/template/koa-rest-api/src/framework/logging.ts +12 -8
- package/template/koa-rest-api/src/framework/metrics.ts +1 -1
- package/template/koa-rest-api/src/framework/server.test.ts +7 -7
- package/template/koa-rest-api/src/framework/server.ts +1 -4
- package/template/lambda-sqs-worker-cdk/.buildkite/pipeline.yml +6 -2
- package/template/lambda-sqs-worker-cdk/.env +1 -1
- package/template/lambda-sqs-worker-cdk/README.md +8 -8
- package/template/lambda-sqs-worker-cdk/infra/__snapshots__/appStack.test.ts.snap +34 -8
- package/template/lambda-sqs-worker-cdk/infra/appStack.test.ts +5 -8
- package/template/lambda-sqs-worker-cdk/infra/appStack.ts +11 -5
- package/template/lambda-sqs-worker-cdk/infra/config.ts +26 -17
- package/template/lambda-sqs-worker-cdk/infra/index.ts +1 -1
- package/template/lambda-sqs-worker-cdk/package.json +5 -5
- package/template/lambda-sqs-worker-cdk/src/app.test.ts +4 -4
- package/template/lambda-sqs-worker-cdk/src/config.ts +11 -16
- package/template/lambda-sqs-worker-cdk/src/framework/handler.test.ts +2 -2
- package/template/lambda-sqs-worker-cdk/src/framework/handler.ts +8 -21
- package/template/lambda-sqs-worker-cdk/src/framework/logging.ts +12 -8
- package/template/lambda-sqs-worker-cdk/src/framework/metrics.ts +1 -4
- package/template/oss-npm-package/.github/workflows/release.yml +1 -1
- package/template/oss-npm-package/.github/workflows/validate.yml +1 -1
|
@@ -29,7 +29,7 @@ It uses the [Koa] middleware framework and common SEEK packages.
|
|
|
29
29
|
Resource APIs enable synchronous interactions and serve as the backbone of SEEK's general service architecture.
|
|
30
30
|
|
|
31
31
|
The `koa-rest-api` template is modelled after a hypothetical service for posting and retrieving job advertisements.
|
|
32
|
-
It's stubbed out with in-memory [storage](src/storage) which can observed by standing up
|
|
32
|
+
It's stubbed out with in-memory [storage](src/storage) which can observed by standing up a deployment with multiple instances.
|
|
33
33
|
Storage is local to each instance, so load balancing across the instances may render a read inconsistent with a previous write.
|
|
34
34
|
This would be replaced with an external data store in production.
|
|
35
35
|
|
|
@@ -75,19 +75,19 @@ pnpm start:debug
|
|
|
75
75
|
|
|
76
76
|
This project is deployed through a [Buildkite pipeline](.buildkite/pipeline.yml).
|
|
77
77
|
|
|
78
|
-
- Commits to a feature branch can be deployed to the
|
|
79
|
-
- Commits to the default branch are automatically deployed to the
|
|
78
|
+
- Commits to a feature branch can be deployed to the development environment by unblocking a step in the Buildkite UI
|
|
79
|
+
- Commits to the default branch are automatically deployed to the development and production environments in sequence
|
|
80
80
|
|
|
81
81
|
To rapidly roll back a change,
|
|
82
82
|
retry an individual deployment step from the previous build in Buildkite.
|
|
83
|
-
Note that this will introduce drift between the head of the default Git branch and the live
|
|
83
|
+
Note that this will introduce drift between the head of the default Git branch and the live deployment;
|
|
84
84
|
use with caution and always follow up with a proper revert or fix in Git history.
|
|
85
85
|
|
|
86
86
|
## Support
|
|
87
87
|
|
|
88
88
|
### Dev
|
|
89
89
|
|
|
90
|
-
TODO: add support links for the dev
|
|
90
|
+
TODO: add support links for the dev deployment.
|
|
91
91
|
|
|
92
92
|
<!--
|
|
93
93
|
- CloudWatch dashboard
|
|
@@ -97,7 +97,7 @@ TODO: add support links for the dev environment.
|
|
|
97
97
|
|
|
98
98
|
### Prod
|
|
99
99
|
|
|
100
|
-
TODO: add support links for the prod
|
|
100
|
+
TODO: add support links for the prod deployment.
|
|
101
101
|
|
|
102
102
|
<!--
|
|
103
103
|
- CloudWatch dashboard
|
|
@@ -9,10 +9,14 @@ owner: '{{values "owner"}}'
|
|
|
9
9
|
image: '{{values "image"}}'
|
|
10
10
|
|
|
11
11
|
env:
|
|
12
|
-
|
|
13
|
-
OPENTELEMETRY_ENABLED: '{{.Values.openTelemetry.enabled | default false}}'
|
|
12
|
+
DEPLOYMENT: '{{values "deployment"}}'
|
|
14
13
|
SERVICE: '{{values "service"}}'
|
|
15
14
|
|
|
15
|
+
DD_ENV: '{{values "env"}}'
|
|
16
|
+
DD_SERVICE: '{{values "service"}}'
|
|
17
|
+
|
|
18
|
+
OPENTELEMETRY_ENABLED: '{{values "openTelemetry.enabled"}}'
|
|
19
|
+
|
|
16
20
|
{{if .Values.cloudwatchDashboardDisabled}}
|
|
17
21
|
cloudwatchDashboardDisabled: {{values "cloudwatchDashboardDisabled"}}
|
|
18
22
|
{{end}}
|
|
@@ -21,9 +25,17 @@ cloudwatchDashboardDisabled: {{values "cloudwatchDashboardDisabled"}}
|
|
|
21
25
|
datadogSecretId: '{{values "datadogSecretId"}}'
|
|
22
26
|
{{end}}
|
|
23
27
|
|
|
28
|
+
# Uncomment if the `tin` tier is acceptable for your SEEK Auth Sidecar logs
|
|
29
|
+
# The eeeoh log forwarder bypasses Amazon CloudWatch for cost savings
|
|
30
|
+
# logSink:
|
|
31
|
+
# forwarder: eeeoh
|
|
32
|
+
# splunkIndex: '{{values "logSink.splunkIndex"}}'
|
|
33
|
+
|
|
24
34
|
openTelemetry:
|
|
25
|
-
datadogEnvironmentName: '{{values "
|
|
35
|
+
datadogEnvironmentName: '{{values "env"}}'
|
|
26
36
|
enabled: {{values "openTelemetry.enabled"}}
|
|
37
|
+
useGantryServiceName: true
|
|
38
|
+
|
|
27
39
|
{{if .Values.pagerDutyEndpoint}}
|
|
28
40
|
pagerDutyEndpoint: '{{values "pagerDutyEndpoint"}}'
|
|
29
41
|
{{end}}
|
|
@@ -22,11 +22,11 @@
|
|
|
22
22
|
"@opentelemetry/instrumentation-http": "^0.203.0",
|
|
23
23
|
"@opentelemetry/propagator-b3": "^2.0.0",
|
|
24
24
|
"@opentelemetry/sdk-node": "^0.203.0",
|
|
25
|
-
"@seek/logger": "
|
|
25
|
+
"@seek/logger": "11.0.0",
|
|
26
26
|
"hot-shots": "^11.0.0",
|
|
27
27
|
"koa": "^3.0.1",
|
|
28
28
|
"koa-compose": "^4.1.0",
|
|
29
|
-
"seek-datadog-custom-metrics": "^
|
|
29
|
+
"seek-datadog-custom-metrics": "^6.0.0",
|
|
30
30
|
"seek-koala": "^7.1.0",
|
|
31
31
|
"skuba-dive": "^2.0.0",
|
|
32
32
|
"zod": "^4.0.0"
|
|
@@ -39,7 +39,6 @@
|
|
|
39
39
|
"@types/node": "^22.13.10",
|
|
40
40
|
"@types/supertest": "^6.0.0",
|
|
41
41
|
"chance": "^1.1.8",
|
|
42
|
-
"mime": "^4.0.1",
|
|
43
42
|
"pino-pretty": "^13.0.0",
|
|
44
43
|
"skuba": "*",
|
|
45
44
|
"supertest": "^7.0.0"
|
|
@@ -3,8 +3,8 @@ import type { Middleware } from 'src/types/koa.js';
|
|
|
3
3
|
/**
|
|
4
4
|
* Signifies that the API is available to serve requests.
|
|
5
5
|
*
|
|
6
|
-
* The
|
|
7
|
-
* unhealthy and needs to be recycled.
|
|
6
|
+
* The workload hosting environment calls this endpoint to see if the container
|
|
7
|
+
* is unhealthy and needs to be recycled.
|
|
8
8
|
*/
|
|
9
9
|
export const healthCheckHandler: Middleware = (ctx) => {
|
|
10
10
|
ctx.state.skipRequestLogging = true;
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { Env } from 'skuba-dive';
|
|
2
2
|
|
|
3
3
|
interface Config {
|
|
4
|
-
|
|
4
|
+
deployment: Deployment;
|
|
5
5
|
|
|
6
6
|
logLevel: string;
|
|
7
7
|
name: string;
|
|
@@ -11,17 +11,17 @@ interface Config {
|
|
|
11
11
|
port: number | null;
|
|
12
12
|
}
|
|
13
13
|
|
|
14
|
-
type
|
|
14
|
+
type Deployment = (typeof deployments)[number];
|
|
15
15
|
|
|
16
16
|
const dev = '<%- devGantryEnvironmentName %>';
|
|
17
17
|
const prod = '<%- prodGantryEnvironmentName %>';
|
|
18
18
|
|
|
19
|
-
const
|
|
19
|
+
const deployments = ['local', 'test', dev, prod] as const;
|
|
20
20
|
|
|
21
|
-
const
|
|
21
|
+
const deployment = Env.oneOf(deployments)('DEPLOYMENT');
|
|
22
22
|
|
|
23
23
|
/* istanbul ignore next: config verification makes more sense in a smoke test */
|
|
24
|
-
const configs: Record<
|
|
24
|
+
const configs: Record<Deployment, () => Omit<Config, 'deployment'>> = {
|
|
25
25
|
local: () => ({
|
|
26
26
|
logLevel: 'debug',
|
|
27
27
|
name: '<%- serviceName %>',
|
|
@@ -62,6 +62,6 @@ const configs: Record<Environment, () => Omit<Config, 'environment'>> = {
|
|
|
62
62
|
};
|
|
63
63
|
|
|
64
64
|
export const config: Config = {
|
|
65
|
-
...configs[
|
|
66
|
-
|
|
65
|
+
...configs[deployment](),
|
|
66
|
+
deployment,
|
|
67
67
|
};
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import
|
|
1
|
+
import { createDestination, createLogger } from '@seek/logger';
|
|
2
2
|
import { RequestLogging } from 'seek-koala';
|
|
3
3
|
|
|
4
4
|
import { config } from 'src/config.js';
|
|
@@ -9,26 +9,30 @@ const { createContextMiddleware, mixin } =
|
|
|
9
9
|
export const contextMiddleware = createContextMiddleware();
|
|
10
10
|
|
|
11
11
|
const { destination, stdoutMock } = createDestination({
|
|
12
|
-
mock: config.
|
|
12
|
+
mock: config.deployment === 'test',
|
|
13
13
|
});
|
|
14
14
|
|
|
15
15
|
export { stdoutMock };
|
|
16
16
|
|
|
17
17
|
export const logger = createLogger(
|
|
18
18
|
{
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
19
|
+
eeeoh: {
|
|
20
|
+
/**
|
|
21
|
+
* TODO: choose an appropriate Datadog log tier.
|
|
22
|
+
*
|
|
23
|
+
* https://github.com/seek-oss/logger/blob/master/docs/eeeoh.md#datadog-log-tiers
|
|
24
|
+
*/
|
|
25
|
+
datadog: 'tin',
|
|
26
|
+
team: '<%- teamName %>',
|
|
27
|
+
use: 'environment',
|
|
22
28
|
},
|
|
23
29
|
|
|
24
30
|
mixin,
|
|
25
31
|
|
|
26
32
|
level: config.logLevel,
|
|
27
33
|
|
|
28
|
-
name: config.name,
|
|
29
|
-
|
|
30
34
|
transport:
|
|
31
|
-
config.
|
|
35
|
+
config.deployment === 'local' ? { target: 'pino-pretty' } : undefined,
|
|
32
36
|
},
|
|
33
37
|
destination,
|
|
34
38
|
);
|
|
@@ -7,5 +7,5 @@ import { logger } from './logging.js';
|
|
|
7
7
|
|
|
8
8
|
/* istanbul ignore next: StatsD client is not our responsibility */
|
|
9
9
|
export const metricsClient = createStatsDClient(StatsD, config, (err) =>
|
|
10
|
-
logger.error(
|
|
10
|
+
logger.error(err, 'StatsD error'),
|
|
11
11
|
);
|
|
@@ -132,7 +132,7 @@ describe('createApp', () => {
|
|
|
132
132
|
|
|
133
133
|
expect(stdoutMock.calls).toMatchObject([
|
|
134
134
|
{
|
|
135
|
-
|
|
135
|
+
error: {
|
|
136
136
|
statusCode: 400,
|
|
137
137
|
type: 'BadRequestError',
|
|
138
138
|
},
|
|
@@ -166,7 +166,7 @@ describe('createApp', () => {
|
|
|
166
166
|
|
|
167
167
|
expect(stdoutMock.calls).toMatchObject([
|
|
168
168
|
{
|
|
169
|
-
|
|
169
|
+
error: {
|
|
170
170
|
statusCode: 500,
|
|
171
171
|
type: 'InternalServerError',
|
|
172
172
|
},
|
|
@@ -202,7 +202,7 @@ describe('createApp', () => {
|
|
|
202
202
|
|
|
203
203
|
expect(stdoutMock.calls).toMatchObject([
|
|
204
204
|
{
|
|
205
|
-
|
|
205
|
+
error: {
|
|
206
206
|
message: err.message,
|
|
207
207
|
type: 'Error',
|
|
208
208
|
},
|
|
@@ -236,7 +236,7 @@ describe('createApp', () => {
|
|
|
236
236
|
|
|
237
237
|
expect(stdoutMock.calls).toMatchObject([
|
|
238
238
|
{
|
|
239
|
-
|
|
239
|
+
error: null,
|
|
240
240
|
level: 50,
|
|
241
241
|
method: 'GET',
|
|
242
242
|
msg: 'Server error',
|
|
@@ -255,10 +255,10 @@ describe('createApp', () => {
|
|
|
255
255
|
});
|
|
256
256
|
|
|
257
257
|
it('handles string error', async () => {
|
|
258
|
-
const
|
|
258
|
+
const error = chance.sentence();
|
|
259
259
|
|
|
260
260
|
middleware.mockImplementation(() => {
|
|
261
|
-
throw
|
|
261
|
+
throw error;
|
|
262
262
|
});
|
|
263
263
|
|
|
264
264
|
await agent
|
|
@@ -269,7 +269,7 @@ describe('createApp', () => {
|
|
|
269
269
|
|
|
270
270
|
expect(stdoutMock.calls).toMatchObject([
|
|
271
271
|
{
|
|
272
|
-
|
|
272
|
+
error,
|
|
273
273
|
level: 50,
|
|
274
274
|
method: 'GET',
|
|
275
275
|
msg: 'Server error',
|
|
@@ -30,10 +30,7 @@ const requestLogging = RequestLogging.createMiddleware((ctx, fields, err) => {
|
|
|
30
30
|
: logger.error(fields, 'Server error');
|
|
31
31
|
});
|
|
32
32
|
|
|
33
|
-
const version = VersionMiddleware.create(
|
|
34
|
-
name: config.name,
|
|
35
|
-
version: config.version,
|
|
36
|
-
});
|
|
33
|
+
const version = VersionMiddleware.create(config);
|
|
37
34
|
|
|
38
35
|
export const createApp = <State, Context>(
|
|
39
36
|
...middleware: Array<Koa.Middleware<State, Context>>
|
|
@@ -81,7 +81,9 @@ steps:
|
|
|
81
81
|
agents:
|
|
82
82
|
queue: <%- devBuildkiteQueueName %>
|
|
83
83
|
env:
|
|
84
|
-
|
|
84
|
+
DD_DEPLOYMENT_ENVIRONMENT: development
|
|
85
|
+
DD_DEPLOYMENT_SERVICE: <%- serviceName %>
|
|
86
|
+
DEPLOYMENT: dev
|
|
85
87
|
GET_NPM_TOKEN: please
|
|
86
88
|
label: 🤞 Deploy Dev
|
|
87
89
|
concurrency_group: '<%- repoName %>/deploy/dev'
|
|
@@ -89,7 +91,9 @@ steps:
|
|
|
89
91
|
|
|
90
92
|
- <<: *deploy
|
|
91
93
|
env:
|
|
92
|
-
|
|
94
|
+
DD_DEPLOYMENT_ENVIRONMENT: production
|
|
95
|
+
DD_DEPLOYMENT_SERVICE: <%- serviceName %>
|
|
96
|
+
DEPLOYMENT: prod
|
|
93
97
|
GET_NPM_TOKEN: please
|
|
94
98
|
label: 🚀 Deploy Prod
|
|
95
99
|
branches: ${BUILDKITE_PIPELINE_DEFAULT_BRANCH}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
|
|
1
|
+
DEPLOYMENT=local
|
|
@@ -54,7 +54,7 @@ pnpm test
|
|
|
54
54
|
awsauth
|
|
55
55
|
|
|
56
56
|
# Run smoke test against deployed application
|
|
57
|
-
|
|
57
|
+
DEPLOYMENT=dev pnpm smoke
|
|
58
58
|
```
|
|
59
59
|
|
|
60
60
|
### Lint
|
|
@@ -88,8 +88,8 @@ curl --data '[{}, {"awsRequestId": "local"}]' --include localhost:<%- port %>
|
|
|
88
88
|
|
|
89
89
|
This project is deployed through a [Buildkite pipeline](.buildkite/pipeline.yml).
|
|
90
90
|
|
|
91
|
-
- Commits to a feature branch can be deployed to the
|
|
92
|
-
- Commits to the default branch are automatically deployed to the
|
|
91
|
+
- Commits to a feature branch can be deployed to the development environment by unblocking a step in the Buildkite UI
|
|
92
|
+
- Commits to the default branch are automatically deployed to the development and production environments in sequence
|
|
93
93
|
|
|
94
94
|
To deploy locally:
|
|
95
95
|
|
|
@@ -97,7 +97,7 @@ To deploy locally:
|
|
|
97
97
|
# Authenticate to dev account
|
|
98
98
|
awsauth
|
|
99
99
|
|
|
100
|
-
|
|
100
|
+
DEPLOYMENT=dev pnpm run deploy
|
|
101
101
|
```
|
|
102
102
|
|
|
103
103
|
A hotswap deploy enables faster deployment but come with caveats such as requiring a Lambda to be rebuilt with every build.
|
|
@@ -108,19 +108,19 @@ To deploy a [hotswap]:
|
|
|
108
108
|
# Authenticate to dev account
|
|
109
109
|
awsauth
|
|
110
110
|
|
|
111
|
-
|
|
111
|
+
DEPLOYMENT=dev pnpm run deploy:hotswap
|
|
112
112
|
```
|
|
113
113
|
|
|
114
114
|
To rapidly roll back a change,
|
|
115
115
|
retry an individual deployment step from the previous build in Buildkite.
|
|
116
|
-
Note that this will introduce drift between the head of the default Git branch and the live
|
|
116
|
+
Note that this will introduce drift between the head of the default Git branch and the live deployment;
|
|
117
117
|
use with caution and always follow up with a proper revert or fix in Git history.
|
|
118
118
|
|
|
119
119
|
## Support
|
|
120
120
|
|
|
121
121
|
### Dev
|
|
122
122
|
|
|
123
|
-
TODO: add support links for the dev
|
|
123
|
+
TODO: add support links for the dev deployment.
|
|
124
124
|
|
|
125
125
|
<!--
|
|
126
126
|
- CloudWatch dashboard
|
|
@@ -130,7 +130,7 @@ TODO: add support links for the dev environment.
|
|
|
130
130
|
|
|
131
131
|
### Prod
|
|
132
132
|
|
|
133
|
-
TODO: add support links for the prod
|
|
133
|
+
TODO: add support links for the prod deployment.
|
|
134
134
|
|
|
135
135
|
<!--
|
|
136
136
|
- CloudWatch dashboard
|
|
@@ -180,28 +180,29 @@ exports[`returns expected CloudFormation stack for dev 1`] = `
|
|
|
180
180
|
"Ref": "datadogapikeysecret046FEF06",
|
|
181
181
|
},
|
|
182
182
|
"DD_CAPTURE_LAMBDA_PAYLOAD": "false",
|
|
183
|
+
"DD_ENV": "development",
|
|
183
184
|
"DD_FLUSH_TO_LOG": "false",
|
|
184
185
|
"DD_LAMBDA_HANDLER": "index.handler",
|
|
185
186
|
"DD_LOGS_INJECTION": "false",
|
|
186
187
|
"DD_MERGE_XRAY_TRACES": "false",
|
|
187
188
|
"DD_SERVERLESS_APPSEC_ENABLED": "false",
|
|
188
189
|
"DD_SERVERLESS_LOGS_ENABLED": "false",
|
|
190
|
+
"DD_SERVICE": "serviceName",
|
|
189
191
|
"DD_SITE": "datadoghq.com",
|
|
190
192
|
"DD_TRACE_CLOUD_REQUEST_PAYLOAD_TAGGING": "$.*",
|
|
191
193
|
"DD_TRACE_CLOUD_RESPONSE_PAYLOAD_TAGGING": "$.*",
|
|
192
194
|
"DD_TRACE_ENABLED": "true",
|
|
195
|
+
"DD_VERSION": "local",
|
|
196
|
+
"DEPLOYMENT": "dev",
|
|
193
197
|
"DESTINATION_SNS_TOPIC_ARN": {
|
|
194
198
|
"Ref": "destinationtopicDCE2E0B8",
|
|
195
199
|
},
|
|
196
|
-
"ENVIRONMENT": "dev",
|
|
197
200
|
"NODE_ENV": "production",
|
|
198
201
|
"NODE_OPTIONS": "--enable-source-maps",
|
|
199
|
-
"SERVICE": "serviceName",
|
|
200
|
-
"VERSION": "local",
|
|
201
202
|
},
|
|
202
203
|
},
|
|
203
204
|
"FunctionName": "serviceName",
|
|
204
|
-
"Handler": "node_modules/datadog-lambda-js/
|
|
205
|
+
"Handler": "/opt/nodejs/node_modules/datadog-lambda-js/handler.handler",
|
|
205
206
|
"KmsKeyArn": {
|
|
206
207
|
"Fn::GetAtt": [
|
|
207
208
|
"kmskey49FBC3B3",
|
|
@@ -209,6 +210,18 @@ exports[`returns expected CloudFormation stack for dev 1`] = `
|
|
|
209
210
|
],
|
|
210
211
|
},
|
|
211
212
|
"Layers": [
|
|
213
|
+
{
|
|
214
|
+
"Fn::Join": [
|
|
215
|
+
"",
|
|
216
|
+
[
|
|
217
|
+
"arn:aws:lambda:",
|
|
218
|
+
{
|
|
219
|
+
"Ref": "AWS::Region",
|
|
220
|
+
},
|
|
221
|
+
":464622532012:layer:Datadog-Node22-x:x",
|
|
222
|
+
],
|
|
223
|
+
],
|
|
224
|
+
},
|
|
212
225
|
{
|
|
213
226
|
"Fn::Join": [
|
|
214
227
|
"",
|
|
@@ -920,28 +933,29 @@ exports[`returns expected CloudFormation stack for prod 1`] = `
|
|
|
920
933
|
"Ref": "datadogapikeysecret046FEF06",
|
|
921
934
|
},
|
|
922
935
|
"DD_CAPTURE_LAMBDA_PAYLOAD": "false",
|
|
936
|
+
"DD_ENV": "production",
|
|
923
937
|
"DD_FLUSH_TO_LOG": "false",
|
|
924
938
|
"DD_LAMBDA_HANDLER": "index.handler",
|
|
925
939
|
"DD_LOGS_INJECTION": "false",
|
|
926
940
|
"DD_MERGE_XRAY_TRACES": "false",
|
|
927
941
|
"DD_SERVERLESS_APPSEC_ENABLED": "false",
|
|
928
942
|
"DD_SERVERLESS_LOGS_ENABLED": "false",
|
|
943
|
+
"DD_SERVICE": "serviceName",
|
|
929
944
|
"DD_SITE": "datadoghq.com",
|
|
930
945
|
"DD_TRACE_CLOUD_REQUEST_PAYLOAD_TAGGING": "$.*",
|
|
931
946
|
"DD_TRACE_CLOUD_RESPONSE_PAYLOAD_TAGGING": "$.*",
|
|
932
947
|
"DD_TRACE_ENABLED": "true",
|
|
948
|
+
"DD_VERSION": "local",
|
|
949
|
+
"DEPLOYMENT": "prod",
|
|
933
950
|
"DESTINATION_SNS_TOPIC_ARN": {
|
|
934
951
|
"Ref": "destinationtopicDCE2E0B8",
|
|
935
952
|
},
|
|
936
|
-
"ENVIRONMENT": "prod",
|
|
937
953
|
"NODE_ENV": "production",
|
|
938
954
|
"NODE_OPTIONS": "--enable-source-maps",
|
|
939
|
-
"SERVICE": "serviceName",
|
|
940
|
-
"VERSION": "local",
|
|
941
955
|
},
|
|
942
956
|
},
|
|
943
957
|
"FunctionName": "serviceName",
|
|
944
|
-
"Handler": "node_modules/datadog-lambda-js/
|
|
958
|
+
"Handler": "/opt/nodejs/node_modules/datadog-lambda-js/handler.handler",
|
|
945
959
|
"KmsKeyArn": {
|
|
946
960
|
"Fn::GetAtt": [
|
|
947
961
|
"kmskey49FBC3B3",
|
|
@@ -949,6 +963,18 @@ exports[`returns expected CloudFormation stack for prod 1`] = `
|
|
|
949
963
|
],
|
|
950
964
|
},
|
|
951
965
|
"Layers": [
|
|
966
|
+
{
|
|
967
|
+
"Fn::Join": [
|
|
968
|
+
"",
|
|
969
|
+
[
|
|
970
|
+
"arn:aws:lambda:",
|
|
971
|
+
{
|
|
972
|
+
"Ref": "AWS::Region",
|
|
973
|
+
},
|
|
974
|
+
":464622532012:layer:Datadog-Node22-x:x",
|
|
975
|
+
],
|
|
976
|
+
],
|
|
977
|
+
},
|
|
952
978
|
{
|
|
953
979
|
"Fn::Join": [
|
|
954
980
|
"",
|
|
@@ -15,11 +15,11 @@ jest.useFakeTimers({
|
|
|
15
15
|
now: new Date(currentDate),
|
|
16
16
|
});
|
|
17
17
|
|
|
18
|
-
const
|
|
18
|
+
const originalDeployment = process.env.DEPLOYMENT;
|
|
19
19
|
const originalVersion = process.env.VERSION;
|
|
20
20
|
|
|
21
21
|
afterAll(() => {
|
|
22
|
-
process.env.
|
|
22
|
+
process.env.DEPLOYMENT = originalDeployment;
|
|
23
23
|
process.env.VERSION = originalVersion;
|
|
24
24
|
});
|
|
25
25
|
|
|
@@ -29,8 +29,8 @@ afterEach(() => {
|
|
|
29
29
|
|
|
30
30
|
it.each(['dev', 'prod'])(
|
|
31
31
|
'returns expected CloudFormation stack for %s',
|
|
32
|
-
async (
|
|
33
|
-
process.env.
|
|
32
|
+
async (deployment) => {
|
|
33
|
+
process.env.DEPLOYMENT = deployment;
|
|
34
34
|
process.env.VERSION = 'local';
|
|
35
35
|
|
|
36
36
|
const { AppStack } = await import('./appStack.js');
|
|
@@ -69,10 +69,7 @@ it.each(['dev', 'prod'])(
|
|
|
69
69
|
/"DD_TAGS":"git.commit.sha:([0-9a-f]+),git.repository_url:([^\"]+)",/g,
|
|
70
70
|
'',
|
|
71
71
|
)
|
|
72
|
-
.replaceAll(
|
|
73
|
-
/(layer:Datadog-Extension-.+?:)\d+/g,
|
|
74
|
-
(_, layer) => `${layer}x`,
|
|
75
|
-
);
|
|
72
|
+
.replaceAll(/(layer:Datadog-[^-]+-.+?:)\d+/g, (_, layer) => `${layer}x`);
|
|
76
73
|
expect(JSON.parse(json)).toMatchSnapshot();
|
|
77
74
|
},
|
|
78
75
|
);
|
|
@@ -19,7 +19,10 @@ import { DatadogLambda } from 'datadog-cdk-constructs-v2';
|
|
|
19
19
|
import { config } from './config.js';
|
|
20
20
|
|
|
21
21
|
// Updated by https://github.com/seek-oss/rynovate
|
|
22
|
-
const DATADOG_EXTENSION_LAYER_VERSION =
|
|
22
|
+
const DATADOG_EXTENSION_LAYER_VERSION = 84;
|
|
23
|
+
|
|
24
|
+
// Updated by https://github.com/seek-oss/rynovate
|
|
25
|
+
const DATADOG_NODE_LAYER_VERSION = 126;
|
|
23
26
|
|
|
24
27
|
export class AppStack extends Stack {
|
|
25
28
|
constructor(scope: Construct, id: string, props?: StackProps) {
|
|
@@ -95,7 +98,6 @@ export class AppStack extends Stack {
|
|
|
95
98
|
target: 'node22',
|
|
96
99
|
// aws-sdk-v3 is set as an external module by default, but we want it to be bundled with the function
|
|
97
100
|
externalModules: [],
|
|
98
|
-
nodeModules: ['datadog-lambda-js', 'dd-trace'],
|
|
99
101
|
},
|
|
100
102
|
functionName: '<%- serviceName %>',
|
|
101
103
|
environment: {
|
|
@@ -127,11 +129,15 @@ export class AppStack extends Stack {
|
|
|
127
129
|
);
|
|
128
130
|
|
|
129
131
|
const datadog = new DatadogLambda(this, 'datadog', {
|
|
132
|
+
env: config.env,
|
|
133
|
+
service: config.service,
|
|
134
|
+
version: config.version,
|
|
135
|
+
|
|
130
136
|
apiKeySecret: datadogSecret,
|
|
131
|
-
addLayers: false,
|
|
132
137
|
enableDatadogLogs: false,
|
|
133
|
-
flushMetricsToLogs: false,
|
|
134
138
|
extensionLayerVersion: DATADOG_EXTENSION_LAYER_VERSION,
|
|
139
|
+
flushMetricsToLogs: false,
|
|
140
|
+
nodeLayerVersion: DATADOG_NODE_LAYER_VERSION,
|
|
135
141
|
});
|
|
136
142
|
|
|
137
143
|
datadog.addLambdaFunctions([worker]);
|
|
@@ -142,8 +148,8 @@ export class AppStack extends Stack {
|
|
|
142
148
|
|
|
143
149
|
workerDeployment.alias.addEventSource(
|
|
144
150
|
new aws_lambda_event_sources.SqsEventSource(queue, {
|
|
145
|
-
maxConcurrency: config.workerLambda.reservedConcurrency - 1, // Ensure we have capacity reserved for our blue/green deployment
|
|
146
151
|
batchSize: config.workerLambda.batchSize,
|
|
152
|
+
maxConcurrency: config.workerLambda.reservedConcurrency - 1, // Ensure we have capacity reserved for our blue/green deployment
|
|
147
153
|
reportBatchItemFailures: true,
|
|
148
154
|
}),
|
|
149
155
|
);
|
|
@@ -1,55 +1,64 @@
|
|
|
1
1
|
import { Env } from 'skuba-dive';
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
type Deployment = (typeof deployments)[number];
|
|
4
4
|
|
|
5
|
-
|
|
5
|
+
const deployments = ['dev', 'prod'] as const;
|
|
6
6
|
|
|
7
|
-
const
|
|
7
|
+
const deployment = Env.oneOf(deployments)('DEPLOYMENT');
|
|
8
8
|
|
|
9
9
|
interface Config {
|
|
10
|
-
|
|
10
|
+
env: 'development' | 'production';
|
|
11
|
+
service: string;
|
|
12
|
+
version: string;
|
|
13
|
+
|
|
11
14
|
workerLambda: {
|
|
12
15
|
batchSize: number;
|
|
13
16
|
reservedConcurrency: number;
|
|
14
17
|
environment: {
|
|
15
|
-
|
|
16
|
-
SERVICE: string;
|
|
17
|
-
VERSION: string;
|
|
18
|
+
DEPLOYMENT: Deployment;
|
|
18
19
|
};
|
|
19
20
|
};
|
|
21
|
+
|
|
20
22
|
datadogApiKeySecretArn: string;
|
|
21
23
|
sourceSnsTopicArn: string;
|
|
22
24
|
}
|
|
23
25
|
|
|
24
|
-
const
|
|
26
|
+
const service = '<%- serviceName %>';
|
|
27
|
+
const version = Env.string('VERSION');
|
|
28
|
+
|
|
29
|
+
const configs: Record<Deployment, Config> = {
|
|
25
30
|
dev: {
|
|
26
|
-
|
|
31
|
+
env: 'development',
|
|
32
|
+
service,
|
|
33
|
+
version,
|
|
34
|
+
|
|
27
35
|
workerLambda: {
|
|
28
36
|
batchSize: 10,
|
|
29
37
|
reservedConcurrency: 3,
|
|
30
38
|
environment: {
|
|
31
|
-
|
|
32
|
-
SERVICE: '<%- serviceName %>',
|
|
33
|
-
VERSION: Env.string('VERSION', { default: 'local' }),
|
|
39
|
+
DEPLOYMENT: 'dev',
|
|
34
40
|
},
|
|
35
41
|
},
|
|
42
|
+
|
|
36
43
|
datadogApiKeySecretArn: 'TODO: datadogApiKeySecretArn',
|
|
37
44
|
sourceSnsTopicArn: 'TODO: sourceSnsTopicArn',
|
|
38
45
|
},
|
|
39
46
|
prod: {
|
|
40
|
-
|
|
47
|
+
env: 'production',
|
|
48
|
+
service,
|
|
49
|
+
version,
|
|
50
|
+
|
|
41
51
|
workerLambda: {
|
|
42
52
|
batchSize: 10,
|
|
43
53
|
reservedConcurrency: 20,
|
|
44
54
|
environment: {
|
|
45
|
-
|
|
46
|
-
SERVICE: '<%- serviceName %>',
|
|
47
|
-
VERSION: Env.string('VERSION', { default: 'local' }),
|
|
55
|
+
DEPLOYMENT: 'prod',
|
|
48
56
|
},
|
|
49
57
|
},
|
|
58
|
+
|
|
50
59
|
datadogApiKeySecretArn: 'TODO: datadogApiKeySecretArn',
|
|
51
60
|
sourceSnsTopicArn: 'TODO: sourceSnsTopicArn',
|
|
52
61
|
},
|
|
53
62
|
};
|
|
54
63
|
|
|
55
|
-
export const config: Config = configs[
|
|
64
|
+
export const config: Config = configs[deployment];
|
|
@@ -7,7 +7,7 @@ import { config } from './config.js';
|
|
|
7
7
|
const app = new App();
|
|
8
8
|
|
|
9
9
|
const appStack = new AppStack(app, 'appStack', {
|
|
10
|
-
stackName: config.
|
|
10
|
+
stackName: config.service,
|
|
11
11
|
tags: {
|
|
12
12
|
'seek:source:url': 'https://github.com/SEEK-Jobs/<%- repoName %>',
|
|
13
13
|
// 'seek:system:name': 'TODO: https://rfc.skinfra.xyz/RFC051-AWS-Tagging-Standard.html#tagging-schema',
|