skuba 9.2.0-old-lang-opts-20250115050141 → 10.0.0-main-20250312042528

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 (105) hide show
  1. package/lib/cli/configure/analyseDependencies.js +4 -1
  2. package/lib/cli/configure/analyseDependencies.js.map +2 -2
  3. package/lib/cli/init/index.js +2 -2
  4. package/lib/cli/init/index.js.map +2 -2
  5. package/lib/cli/init/prompts.d.ts +1 -1
  6. package/lib/cli/lint/internal.js +2 -1
  7. package/lib/cli/lint/internal.js.map +2 -2
  8. package/lib/cli/lint/internalLints/detectBadCodeowners.d.ts +4 -0
  9. package/lib/cli/lint/internalLints/detectBadCodeowners.js +72 -0
  10. package/lib/cli/lint/internalLints/detectBadCodeowners.js.map +7 -0
  11. package/lib/cli/lint/internalLints/upgrade/patches/9.1.0/index.d.ts +2 -0
  12. package/lib/cli/lint/internalLints/upgrade/patches/9.1.0/index.js +35 -0
  13. package/lib/cli/lint/internalLints/upgrade/patches/9.1.0/index.js.map +7 -0
  14. package/lib/cli/lint/internalLints/upgrade/patches/9.1.0/upgradeNode.d.ts +2 -0
  15. package/lib/cli/lint/internalLints/upgrade/patches/9.1.0/upgradeNode.js +59 -0
  16. package/lib/cli/lint/internalLints/upgrade/patches/9.1.0/upgradeNode.js.map +7 -0
  17. package/lib/cli/migrate/index.js +10 -1
  18. package/lib/cli/migrate/index.js.map +2 -2
  19. package/lib/cli/migrate/nodeVersion/checks.d.ts +14 -0
  20. package/lib/cli/migrate/nodeVersion/checks.js +165 -0
  21. package/lib/cli/migrate/nodeVersion/checks.js.map +7 -0
  22. package/lib/cli/migrate/nodeVersion/getNodeTypesVersion.d.ts +6 -0
  23. package/lib/cli/migrate/nodeVersion/getNodeTypesVersion.js +58 -0
  24. package/lib/cli/migrate/nodeVersion/getNodeTypesVersion.js.map +7 -0
  25. package/lib/cli/migrate/nodeVersion/index.d.ts +5 -1
  26. package/lib/cli/migrate/nodeVersion/index.js +119 -36
  27. package/lib/cli/migrate/nodeVersion/index.js.map +2 -2
  28. package/lib/index.js +3 -3
  29. package/lib/utils/copy.d.ts +1 -1
  30. package/lib/utils/copy.js +11 -3
  31. package/lib/utils/copy.js.map +2 -2
  32. package/lib/utils/template.d.ts +2 -2
  33. package/lib/utils/template.js +0 -5
  34. package/lib/utils/template.js.map +2 -2
  35. package/lib/utils/version.d.ts +17 -1
  36. package/lib/utils/version.js +48 -18
  37. package/lib/utils/version.js.map +3 -3
  38. package/package.json +17 -19
  39. package/template/base/tsconfig.json +2 -2
  40. package/template/express-rest-api/.buildkite/pipeline.yml +4 -4
  41. package/template/express-rest-api/.gantry/common.yml +1 -3
  42. package/template/express-rest-api/.nvmrc +1 -1
  43. package/template/express-rest-api/Dockerfile +1 -1
  44. package/template/express-rest-api/Dockerfile.dev-deps +2 -2
  45. package/template/express-rest-api/package.json +4 -4
  46. package/template/greeter/.buildkite/pipeline.yml +1 -1
  47. package/template/greeter/.nvmrc +1 -1
  48. package/template/greeter/Dockerfile +2 -2
  49. package/template/greeter/README.md +1 -1
  50. package/template/greeter/package.json +4 -4
  51. package/template/koa-rest-api/.buildkite/pipeline.yml +4 -4
  52. package/template/koa-rest-api/.gantry/common.yml +1 -3
  53. package/template/koa-rest-api/.nvmrc +1 -1
  54. package/template/koa-rest-api/Dockerfile +1 -1
  55. package/template/koa-rest-api/Dockerfile.dev-deps +2 -2
  56. package/template/koa-rest-api/package.json +3 -3
  57. package/template/koa-rest-api/tsconfig.json +2 -2
  58. package/template/lambda-sqs-worker-cdk/.buildkite/pipeline.yml +2 -2
  59. package/template/lambda-sqs-worker-cdk/.nvmrc +1 -1
  60. package/template/lambda-sqs-worker-cdk/Dockerfile +3 -3
  61. package/template/lambda-sqs-worker-cdk/infra/__snapshots__/appStack.test.ts.snap +2 -2
  62. package/template/lambda-sqs-worker-cdk/infra/appStack.ts +4 -4
  63. package/template/lambda-sqs-worker-cdk/infra/config.ts +1 -1
  64. package/template/lambda-sqs-worker-cdk/infra/index.ts +3 -5
  65. package/template/lambda-sqs-worker-cdk/package.json +6 -6
  66. package/template/lambda-sqs-worker-cdk/tsconfig.json +2 -2
  67. package/template/oss-npm-package/.github/workflows/release.yml +1 -1
  68. package/template/oss-npm-package/.github/workflows/validate.yml +1 -1
  69. package/template/oss-npm-package/.nvmrc +1 -1
  70. package/template/oss-npm-package/_package.json +1 -1
  71. package/template/private-npm-package/.nvmrc +1 -1
  72. package/template/private-npm-package/_package.json +2 -2
  73. package/template/lambda-sqs-worker/.buildkite/pipeline.yml +0 -108
  74. package/template/lambda-sqs-worker/.env +0 -1
  75. package/template/lambda-sqs-worker/.nvmrc +0 -1
  76. package/template/lambda-sqs-worker/Dockerfile +0 -17
  77. package/template/lambda-sqs-worker/README.md +0 -132
  78. package/template/lambda-sqs-worker/_.npmrc +0 -13
  79. package/template/lambda-sqs-worker/docker-compose.yml +0 -10
  80. package/template/lambda-sqs-worker/package.json +0 -45
  81. package/template/lambda-sqs-worker/serverless.yml +0 -213
  82. package/template/lambda-sqs-worker/skuba.template.js +0 -33
  83. package/template/lambda-sqs-worker/src/app.test.ts +0 -116
  84. package/template/lambda-sqs-worker/src/app.ts +0 -57
  85. package/template/lambda-sqs-worker/src/config.ts +0 -62
  86. package/template/lambda-sqs-worker/src/framework/handler.test.ts +0 -61
  87. package/template/lambda-sqs-worker/src/framework/handler.ts +0 -43
  88. package/template/lambda-sqs-worker/src/framework/logging.ts +0 -27
  89. package/template/lambda-sqs-worker/src/framework/metrics.ts +0 -14
  90. package/template/lambda-sqs-worker/src/framework/validation.test.ts +0 -84
  91. package/template/lambda-sqs-worker/src/framework/validation.ts +0 -10
  92. package/template/lambda-sqs-worker/src/hooks.ts +0 -95
  93. package/template/lambda-sqs-worker/src/mapping/jobScorer.ts +0 -22
  94. package/template/lambda-sqs-worker/src/services/aws.ts +0 -5
  95. package/template/lambda-sqs-worker/src/services/jobScorer.test.ts +0 -44
  96. package/template/lambda-sqs-worker/src/services/jobScorer.ts +0 -59
  97. package/template/lambda-sqs-worker/src/services/pipelineEventSender.test.ts +0 -40
  98. package/template/lambda-sqs-worker/src/services/pipelineEventSender.ts +0 -33
  99. package/template/lambda-sqs-worker/src/testing/handler.ts +0 -13
  100. package/template/lambda-sqs-worker/src/testing/logging.ts +0 -19
  101. package/template/lambda-sqs-worker/src/testing/services.ts +0 -28
  102. package/template/lambda-sqs-worker/src/testing/types.ts +0 -33
  103. package/template/lambda-sqs-worker/src/types/jobScorer.ts +0 -15
  104. package/template/lambda-sqs-worker/src/types/pipelineEvents.ts +0 -21
  105. package/template/lambda-sqs-worker/tsconfig.json +0 -13
@@ -1,108 +0,0 @@
1
- agents:
2
- queue: <%- prodBuildkiteQueueName %>
3
-
4
- configs:
5
- plugins:
6
- - &aws-sm
7
- seek-oss/aws-sm#v2.3.2:
8
- env:
9
- NPM_READ_TOKEN: arn:aws:secretsmanager:ap-southeast-2:987872074697:secret:npm/npm-read-token
10
-
11
- - &docker-ecr-cache
12
- seek-oss/docker-ecr-cache#v2.2.1: &docker-ecr-cache-defaults
13
- cache-on:
14
- - .npmrc
15
- - package.json#.packageManager
16
- - pnpm-lock.yaml
17
- secrets: id=npm,src=/tmp/.npmrc
18
-
19
- - &private-npm
20
- seek-oss/private-npm#v1.3.0:
21
- env: NPM_READ_TOKEN
22
- output-path: /tmp/
23
-
24
- base-steps:
25
- - &deploy
26
- commands:
27
- - echo '--- pnpm install --offline'
28
- - pnpm install --offline
29
- - echo '+++ pnpm run deploy'
30
- - pnpm run deploy
31
- concurrency: 1
32
- plugins:
33
- - artifacts#v1.9.4:
34
- build: ${BUILDKITE_BUILD_ID}
35
- download: lib/*
36
- - *aws-sm
37
- - *private-npm
38
- - *docker-ecr-cache
39
- - docker-compose#v5.5.0:
40
- dependencies: false
41
- run: app
42
- propagate-environment: true
43
- retry:
44
- manual:
45
- # Only use this if you need to roll back a deployment ASAP.
46
- # Always follow up with a proper revert or fix in Git history.
47
- permit_on_passed: true
48
-
49
- env:
50
- VERSION: ${BUILDKITE_COMMIT:0:7}.${BUILDKITE_BUILD_NUMBER}
51
-
52
- steps:
53
- - label: 🧪 Test, Lint & Build
54
- artifact_paths: lib/**/*
55
- commands:
56
- - echo '--- pnpm install --offline'
57
- - pnpm install --offline
58
- - echo '+++ pnpm test:ci'
59
- - pnpm test:ci
60
- - echo '--- pnpm lint'
61
- - pnpm lint
62
- - echo '--- pnpm build'
63
- - pnpm build
64
- env:
65
- GET_GITHUB_TOKEN: please
66
- plugins:
67
- - *aws-sm
68
- - *private-npm
69
- - *docker-ecr-cache
70
- - docker-compose#v5.5.0:
71
- run: app
72
- environment:
73
- - GITHUB_API_TOKEN
74
- propagate-environment: true
75
- timeout_in_minutes: 10
76
-
77
- - agents:
78
- queue: <%- devBuildkiteQueueName %>
79
- branches: '!renovate-*'
80
- label: 🧖‍♀️ Warm Dev
81
- command: ':'
82
- plugins:
83
- - *aws-sm
84
- - *private-npm
85
- - seek-oss/docker-ecr-cache#v2.2.1:
86
- <<: *docker-ecr-cache-defaults
87
- skip-pull-from-cache: true
88
-
89
- - wait
90
- - block: 🙋🏻‍♀️ Deploy Dev
91
- branches: '!${BUILDKITE_PIPELINE_DEFAULT_BRANCH}'
92
-
93
- - <<: *deploy
94
- agents:
95
- queue: <%- devBuildkiteQueueName %>
96
- env:
97
- ENVIRONMENT: dev
98
- concurrency_group: <%- repoName %>/deploy/dev
99
- label: 🤞 Deploy Dev
100
-
101
- - wait
102
-
103
- - <<: *deploy
104
- env:
105
- ENVIRONMENT: prod
106
- branches: ${BUILDKITE_PIPELINE_DEFAULT_BRANCH}
107
- concurrency_group: <%- repoName %>/deploy/prod
108
- label: 🚀 Deploy Prod
@@ -1 +0,0 @@
1
- ENVIRONMENT=local
@@ -1 +0,0 @@
1
- 20
@@ -1,17 +0,0 @@
1
- # syntax=docker/dockerfile:1.12
2
-
3
- FROM public.ecr.aws/docker/library/node:20-alpine AS dev-deps
4
-
5
- RUN --mount=type=bind,source=package.json,target=package.json \
6
- corepack enable pnpm && corepack install
7
-
8
- RUN --mount=type=bind,source=package.json,target=package.json \
9
- pnpm config set store-dir /root/.pnpm-store
10
-
11
- WORKDIR /workdir
12
-
13
- RUN --mount=type=bind,source=.npmrc,target=.npmrc \
14
- --mount=type=bind,source=package.json,target=package.json \
15
- --mount=type=bind,source=pnpm-lock.yaml,target=pnpm-lock.yaml \
16
- --mount=type=secret,id=npm,dst=/root/.npmrc,required=true \
17
- pnpm fetch
@@ -1,132 +0,0 @@
1
- # <%- repoName %>
2
-
3
- [![Powered by skuba](https://img.shields.io/badge/🤿%20skuba-powered-009DC4)](https://github.com/seek-oss/skuba)
4
-
5
- Next steps:
6
-
7
- 1. [ ] Finish templating if this was skipped earlier:
8
-
9
- ```shell
10
- pnpm exec skuba configure
11
- ```
12
-
13
- 2. [ ] Create a new repository in the appropriate GitHub organisation.
14
- 3. [ ] Add the repository to BuildAgency;
15
- see our internal [Buildkite Docs] for more information.
16
- 4. [ ] Add Datadog extension, deployment bucket configuration and data classification tags to [serverless.yml](serverless.yml).
17
- 5. [ ] Push local commits to the upstream GitHub branch.
18
- 6. [ ] Configure [GitHub repository settings].
19
- 7. [ ] Delete this checklist 😌.
20
-
21
- [Buildkite Docs]: https://backstage.myseek.xyz/docs/default/component/buildkite-docs
22
- [GitHub repository settings]: https://github.com/<%-orgName%>/<%-repoName%>/settings
23
-
24
- ## Design
25
-
26
- <%-repoName %> is a Node.js [Lambda] application built in line with our [Technical Guidelines].
27
- It is backed by a typical SQS message + dead letter queue configuration and uses common SEEK packages.
28
- Workers enable fault-tolerant asynchronous processing of events.
29
-
30
- The `lambda-sqs-worker` template is modelled after a hypothetical enricher that scores job advertisements.
31
- It's stubbed out with in-memory [scoring service](src/services/jobScorer.ts).
32
- This would be replaced with internal logic or an external service in production.
33
-
34
- This project is deployed with [Serverless].
35
- The Lambda runtime provisions a single Node.js process per container.
36
- The supplied [serverless.yml](serverless.yml) starts out with a minimal `memorySize` which may require tuning based on workload.
37
- Under load, we autoscale horizontally in terms of container count up to `reservedConcurrency`.
38
-
39
- Serverless configures [CodeDeploy] for a blue-green deployment approach.
40
- A smoke test is run against the new version before traffic is switched over,
41
- providing an opportunity to test access and connectivity to online dependencies.
42
- This defaults to an invocation with an empty object `{}`, per [src/hooks.ts](src/hooks.ts).
43
-
44
- ## Development
45
-
46
- ### Test
47
-
48
- ```shell
49
- # Run Jest tests locally
50
- pnpm test
51
-
52
- # Authenticate to dev account
53
- awsauth
54
-
55
- # Run smoke test against deployed application
56
- ENVIRONMENT=dev pnpm smoke
57
- ```
58
-
59
- ### Lint
60
-
61
- ```shell
62
- # Fix issues
63
- pnpm format
64
-
65
- # Check for issues
66
- pnpm lint
67
- ```
68
-
69
- ### Start
70
-
71
- ```shell
72
- # Start a local HTTP server
73
- pnpm start
74
-
75
- # Start with Node.js Inspector enabled
76
- pnpm start:debug
77
- ```
78
-
79
- This serves the Lambda application over HTTP.
80
- For example, to invoke the handler with an empty object `{}` for smoke testing:
81
-
82
- ```shell
83
- curl --data '[{}, {"awsRequestId": "local"}]' --include localhost:<%- port %>
84
- ```
85
-
86
- ### Deploy
87
-
88
- This project is deployed through a [Buildkite pipeline](.buildkite/pipeline.yml).
89
-
90
- - Commits to a feature branch can be deployed to the dev environment by unblocking a step in the Buildkite UI
91
- - Commits to the default branch are automatically deployed to the dev and prod environments in sequence
92
-
93
- To deploy locally:
94
-
95
- ```shell
96
- # Authenticate to dev account
97
- awsauth
98
-
99
- ENVIRONMENT=dev pnpm run deploy
100
- ```
101
-
102
- To rapidly roll back a change,
103
- retry an individual deployment step from the previous build in Buildkite.
104
- Note that this will introduce drift between the head of the default Git branch and the live environment;
105
- use with caution and always follow up with a proper revert or fix in Git history.
106
-
107
- ## Support
108
-
109
- ### Dev
110
-
111
- TODO: add support links for the dev environment.
112
-
113
- <!--
114
- - CloudWatch dashboard
115
- - Datadog dashboard
116
- - Splunk logs
117
- -->
118
-
119
- ### Prod
120
-
121
- TODO: add support links for the prod environment.
122
-
123
- <!--
124
- - CloudWatch dashboard
125
- - Datadog dashboard
126
- - Splunk logs
127
- -->
128
-
129
- [CodeDeploy]: https://docs.aws.amazon.com/codedeploy
130
- [Lambda]: https://docs.aws.amazon.com/lambda
131
- [Serverless]: https://www.serverless.com/
132
- [Technical Guidelines]: https://myseek.atlassian.net/wiki/spaces/AA/pages/2358346017/
@@ -1,13 +0,0 @@
1
- # managed by skuba
2
- package-manager-strict-version=true
3
- public-hoist-pattern[]="@types*"
4
- public-hoist-pattern[]="*eslint*"
5
- public-hoist-pattern[]="*prettier*"
6
- public-hoist-pattern[]="esbuild"
7
- public-hoist-pattern[]="jest"
8
- public-hoist-pattern[]="tsconfig-seek"
9
- # end managed by skuba
10
-
11
- # Required for Serverless packaging
12
- node-linker=hoisted
13
- shamefully-hoist=true
@@ -1,10 +0,0 @@
1
- services:
2
- app:
3
- image: ${BUILDKITE_PLUGIN_DOCKER_IMAGE:-''}
4
- init: true
5
- volumes:
6
- - ./:/workdir
7
- # Mount agent for Buildkite annotations.
8
- - /usr/bin/buildkite-agent:/usr/bin/buildkite-agent
9
- # Mount cached dependencies.
10
- - /workdir/node_modules
@@ -1,45 +0,0 @@
1
- {
2
- "name": "@seek/<%- serviceName %>",
3
- "private": true,
4
- "license": "UNLICENSED",
5
- "scripts": {
6
- "build": "skuba build",
7
- "deploy": "serverless deploy --force --verbose",
8
- "format": "skuba format",
9
- "lint": "skuba lint",
10
- "smoke": "serverless invoke --data '{}' --function Worker",
11
- "start": "skuba start --port <%- port %>",
12
- "start:debug": "pnpm --silent start --inspect-brk",
13
- "test": "skuba test",
14
- "test:ci": "skuba test --coverage",
15
- "test:watch": "skuba test --watch"
16
- },
17
- "dependencies": {
18
- "@aws-sdk/client-codedeploy": "^3.363.0",
19
- "@aws-sdk/client-lambda": "^3.363.0",
20
- "@aws-sdk/client-sns": "^3.363.0",
21
- "@seek/logger": "^9.0.0",
22
- "datadog-lambda-js": "^9.0.0",
23
- "dd-trace": "^5.0.0",
24
- "skuba-dive": "^2.0.0",
25
- "zod": "^3.19.1"
26
- },
27
- "devDependencies": {
28
- "@types/aws-lambda": "^8.10.84",
29
- "@types/chance": "^1.1.3",
30
- "@types/node": "^20.16.5",
31
- "aws-sdk-client-mock": "^4.0.0",
32
- "aws-sdk-client-mock-jest": "^4.0.0",
33
- "chance": "^1.1.8",
34
- "pino-pretty": "^13.0.0",
35
- "serverless": "^3.39.0",
36
- "serverless-plugin-canary-deployments": "^0.8.0",
37
- "serverless-plugin-datadog": "^5.12.0",
38
- "serverless-prune-plugin": "^2.0.0",
39
- "skuba": "*"
40
- },
41
- "packageManager": "pnpm@9.15.3",
42
- "engines": {
43
- "node": ">=20"
44
- }
45
- }
@@ -1,213 +0,0 @@
1
- service: <%- serviceName %>
2
-
3
- configValidationMode: error
4
-
5
- params:
6
- default:
7
- datadogApiKeySecretArn: 'TODO: arn:aws:secretsmanager:${aws:region}:${aws:accountId}:secret:SECRET-NAME'
8
- dataStoreTags:
9
- - Key: seek:auto:backup:frequency
10
- Value: none
11
- # TODO: https://rfc.skinfra.xyz/RFC019-AWS-Tagging-Standard.html#data-services
12
- # - Key: seek:data:derived
13
- # Value: copy
14
- # - Key: seek:data:domain
15
- # Value: unassigned
16
- # - Key: seek:data:jurisdiction-source
17
- # Value: australia hong-kong indonesia malaysia new-zealand philippines singapore thailand
18
- # - Key: seek:data:types:restricted
19
- # Value: job-ads
20
- description: <%- description %>
21
- dev:
22
- deploymentBucket: 'TODO: deployment-bucket-name'
23
- concurrency: 2
24
- prod:
25
- deploymentBucket: 'TODO: deployment-bucket-name'
26
- concurrency: 20
27
-
28
- custom:
29
- datadog:
30
- addLayers: false
31
- apiKeySecretArn: ${param:datadogApiKeySecretArn}
32
- enableDDLogs: false
33
- # TODO: enable Datadog extension
34
- enabled: false
35
- exclude:
36
- - WorkerPreHook
37
- injectLogContext: false
38
- version: ${env:VERSION}
39
- prune:
40
- automatic: true
41
- number: 3
42
-
43
- plugins:
44
- - serverless-plugin-canary-deployments
45
- - serverless-plugin-datadog
46
- - serverless-prune-plugin
47
-
48
- provider:
49
- logRetentionInDays: 30
50
- name: aws
51
- region: ap-southeast-2
52
- runtime: nodejs20.x
53
- architecture: <%- lambdaServerlessArchitecture %>
54
- deploymentMethod: direct
55
- stackName: ${self:service}
56
- stage: ${env:ENVIRONMENT}
57
- deploymentBucket:
58
- # Use a shared account-level bucket for Lambda bundles and other artefacts.
59
- # This is easier to manage in terms of access, deployment, and tagging.
60
- name: ${param:deploymentBucket}
61
- environment:
62
- NODE_ENV: production
63
- # https://nodejs.org/api/cli.html#cli_node_options_options
64
- NODE_OPTIONS: --enable-source-maps
65
- iam:
66
- role:
67
- statements:
68
- - Action:
69
- - kms:Decrypt
70
- - kms:GenerateDataKey*
71
- Effect: Allow
72
- Resource: !GetAtt EncryptionKey.Arn
73
- - Action: lambda:InvokeFunction
74
- Effect: Allow
75
- Resource: !Sub arn:aws:lambda:${AWS::Region}:${AWS::AccountId}:function:${self:functions.Worker.name}
76
- - Action: secretsmanager:GetSecretValue
77
- Effect: Allow
78
- Resource: ${param:datadogApiKeySecretArn}-??????
79
- - Action: sns:Publish
80
- Effect: Allow
81
- Resource: !Ref DestinationTopic
82
- stackTags:
83
- seek:env:label: ${env:ENVIRONMENT}
84
- seek:source:sha: ${env:BUILDKITE_COMMIT, 'na'}
85
- seek:source:url: 'https://github.com/SEEK-Jobs/<%- repoName %>'
86
- seek:system:deployed-by: CFN
87
- # seek:system:name: 'TODO: https://rfc.skinfra.xyz/RFC019-AWS-Tagging-Standard.html#required-tags'
88
-
89
- package:
90
- patterns:
91
- - '!**'
92
- - lib/**
93
- - node_modules/**
94
-
95
- functions:
96
- Worker:
97
- name: ${self:service}
98
- handler: lib/app.handler
99
- description: ${param:description}
100
- memorySize: 128
101
- reservedConcurrency: ${param:concurrency}
102
- timeout: 30
103
- deploymentSettings:
104
- type: AllAtOnce
105
- alias: Live
106
- preTrafficHook: WorkerPreHook
107
- environment:
108
- ENVIRONMENT: ${env:ENVIRONMENT}
109
- SERVICE: ${self:service}
110
- VERSION: ${env:VERSION, 'local'}
111
-
112
- DESTINATION_SNS_TOPIC_ARN: !Ref DestinationTopic
113
- events:
114
- - sqs:
115
- arn: !GetAtt MessageQueue.Arn
116
- batchSize: 1
117
- maximumConcurrency: ${param:concurrency}
118
- WorkerPreHook:
119
- name: ${self:functions.Worker.name}-pre-hook
120
- handler: lib/hooks.pre
121
- memorySize: 128
122
- # This is generous because a timeout will hang the deployment
123
- timeout: 300
124
- environment:
125
- FUNCTION_NAME_TO_INVOKE: ${self:functions.Worker.name}
126
-
127
- resources:
128
- # This becomes the Lambda application's description
129
- Description: ${param:description}
130
-
131
- Resources:
132
- DeadLetterQueue:
133
- Type: AWS::SQS::Queue
134
- Properties:
135
- MessageRetentionPeriod: 1209600
136
- KmsDataKeyReusePeriodSeconds: 300
137
- KmsMasterKeyId: !Ref EncryptionKey
138
- QueueName: ${self:service}-dead-letters
139
- Tags: ${param:dataStoreTags}
140
-
141
- MessageQueue:
142
- Type: AWS::SQS::Queue
143
- Properties:
144
- MessageRetentionPeriod: 1209600
145
- KmsDataKeyReusePeriodSeconds: 300
146
- KmsMasterKeyId: !Ref EncryptionKey
147
- QueueName: ${self:service}-messages
148
- RedrivePolicy:
149
- deadLetterTargetArn: !GetAtt DeadLetterQueue.Arn
150
- maxReceiveCount: 3
151
- Tags: ${param:dataStoreTags}
152
- VisibilityTimeout: 180
153
-
154
- # MessageQueuePolicy:
155
- # Type: AWS::SQS::QueuePolicy
156
- # Properties:
157
- # PolicyDocument:
158
- # Version: '2012-10-17'
159
- # Statement:
160
- # - Action: sqs:SendMessage
161
- # Condition:
162
- # ArnEquals:
163
- # aws:SourceArn: 'TODO: sourceSnsTopicArn'
164
- # Effect: 'Allow'
165
- # Principal:
166
- # AWS: '*'
167
- # Resource: '*'
168
- # Queues:
169
- # - !Ref MessageQueue
170
-
171
- # TopicSubscription:
172
- # Type: AWS::SNS::Subscription
173
- # Properties:
174
- # Endpoint: !GetAtt MessageQueue.Arn
175
- # Protocol: sqs
176
- # RawMessageDelivery: true # Remove this property if you require end to end datadog tracing
177
- # TopicArn: 'TODO: sourceSnsTopicArn'
178
-
179
- DestinationTopic:
180
- Type: AWS::SNS::Topic
181
- Properties:
182
- KmsMasterKeyId: alias/aws/sns
183
- Tags: ${param:dataStoreTags}
184
- TopicName: ${self:service}
185
-
186
- EncryptionKey:
187
- Type: AWS::KMS::Key
188
- Properties:
189
- Description: ${self:service}
190
- EnableKeyRotation: true
191
- KeyPolicy:
192
- Version: '2012-10-17'
193
- Statement:
194
- - Sid: Admin access
195
- Effect: Allow
196
- Action: kms:*
197
- Principal:
198
- AWS: !Ref AWS::AccountId
199
- Resource: '*'
200
- - Sid: SNS compatibility
201
- Effect: Allow
202
- Action:
203
- - kms:Decrypt
204
- - kms:GenerateDataKey*
205
- Principal:
206
- Service: sns.amazonaws.com
207
- Resource: '*'
208
-
209
- EncryptionKeyAlias:
210
- Type: AWS::KMS::Alias
211
- Properties:
212
- AliasName: alias/seek/${self:service}
213
- TargetKeyId: !Ref EncryptionKey
@@ -1,33 +0,0 @@
1
- /**
2
- * Run `skuba configure` to finish templating and remove this file.
3
- */
4
-
5
- module.exports = {
6
- entryPoint: 'src/app.ts#handler',
7
- fields: [
8
- {
9
- name: 'serviceName',
10
- message: 'Service slug',
11
- initial: 'my-project',
12
- },
13
- {
14
- name: 'description',
15
- message: 'Description',
16
- initial: 'A project just for me',
17
- },
18
- {
19
- name: 'devBuildkiteQueueName',
20
- message: 'Dev Buildkite queue',
21
- initial: 'my-team-aws-account-dev:cicd',
22
- validate: (value) => /^.+:.+$/.test(value),
23
- },
24
- {
25
- name: 'prodBuildkiteQueueName',
26
- message: 'Prod Buildkite queue',
27
- initial: 'my-team-aws-account-prod:cicd',
28
- validate: (value) => /^.+:.+$/.test(value),
29
- },
30
- ],
31
- packageManager: 'pnpm',
32
- type: 'application',
33
- };
@@ -1,116 +0,0 @@
1
- import { PublishCommand } from '@aws-sdk/client-sns';
2
-
3
- import { metricsClient } from 'src/framework/metrics';
4
- import { createCtx, createSqsEvent } from 'src/testing/handler';
5
- import { logger } from 'src/testing/logging';
6
- import { scoringService, sns } from 'src/testing/services';
7
- import { chance, mockJobPublishedEvent } from 'src/testing/types';
8
-
9
- import * as app from './app';
10
-
11
- describe('app', () => {
12
- it('exports a handler', () => expect(app).toHaveProperty('handler'));
13
- });
14
-
15
- describe('handler', () => {
16
- const ctx = createCtx();
17
-
18
- const jobPublished = mockJobPublishedEvent({ entityId: chance.name() });
19
-
20
- const score = chance.floating({ max: 1, min: 0 });
21
-
22
- const distribution = jest
23
- .spyOn(metricsClient, 'distribution')
24
- .mockReturnValue();
25
-
26
- beforeAll(logger.spy);
27
- beforeAll(scoringService.spy);
28
-
29
- beforeEach(() => {
30
- scoringService.request.mockResolvedValue(score);
31
- sns.publish.resolves({ MessageId: chance.guid({ version: 4 }) });
32
- });
33
-
34
- afterEach(() => {
35
- logger.clear();
36
- distribution.mockClear();
37
- scoringService.clear();
38
- sns.clear();
39
- });
40
-
41
- it('handles one record', async () => {
42
- const event = createSqsEvent([JSON.stringify(jobPublished)]);
43
-
44
- await expect(app.handler(event, ctx)).resolves.toBeUndefined();
45
-
46
- expect(scoringService.request).toHaveBeenCalledTimes(1);
47
-
48
- expect(logger.error).not.toHaveBeenCalled();
49
-
50
- expect(logger.debug.mock.calls).toEqual([
51
- [{ count: 1 }, 'Received jobs'],
52
- [{ snsMessageId: expect.any(String) }, 'Scored job'],
53
- ['Function succeeded'],
54
- ]);
55
-
56
- expect(distribution.mock.calls).toEqual([
57
- ['job.received', 1],
58
- ['job.scored', 1],
59
- ]);
60
-
61
- expect(sns.client).toReceiveCommandTimes(PublishCommand, 1);
62
- });
63
-
64
- it('throws on invalid input', () => {
65
- const event = createSqsEvent(['}']);
66
-
67
- return expect(app.handler(event, ctx)).rejects.toThrow('Function failed');
68
- });
69
-
70
- it('bubbles up scoring service error', async () => {
71
- const err = Error(chance.sentence());
72
-
73
- scoringService.request.mockRejectedValue(err);
74
-
75
- const event = createSqsEvent([JSON.stringify(jobPublished)]);
76
-
77
- await expect(app.handler(event, ctx)).rejects.toThrow('Function failed');
78
-
79
- expect(logger.error).toHaveBeenCalledWith({ err }, 'Function failed');
80
- });
81
-
82
- it('bubbles up SNS error', async () => {
83
- const err = Error(chance.sentence());
84
-
85
- sns.publish.rejects(err);
86
-
87
- const event = createSqsEvent([JSON.stringify(jobPublished)]);
88
-
89
- await expect(app.handler(event, ctx)).rejects.toThrow('Function failed');
90
-
91
- expect(logger.error).toHaveBeenCalledWith({ err }, 'Function failed');
92
- });
93
-
94
- it('throws on zero records', async () => {
95
- const err = new Error('Received 0 records');
96
-
97
- const event = createSqsEvent([]);
98
-
99
- await expect(app.handler(event, ctx)).rejects.toThrow('Function failed');
100
-
101
- expect(logger.error).toHaveBeenCalledWith({ err }, 'Function failed');
102
- });
103
-
104
- it('throws on multiple records', async () => {
105
- const err = new Error('Received 2 records');
106
-
107
- const event = createSqsEvent([
108
- JSON.stringify(jobPublished),
109
- JSON.stringify(jobPublished),
110
- ]);
111
-
112
- await expect(app.handler(event, ctx)).rejects.toThrow('Function failed');
113
-
114
- expect(logger.error).toHaveBeenCalledWith({ err }, 'Function failed');
115
- });
116
- });