Skip to content

Commit 2548fa8

Browse files
committed
wap
1 parent e33676c commit 2548fa8

File tree

16 files changed

+4596
-1
lines changed

16 files changed

+4596
-1
lines changed
Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
1+
name: Deploy Reminder
2+
3+
on:
4+
push:
5+
branches:
6+
- main
7+
8+
jobs:
9+
deploy:
10+
runs-on: ubuntu-latest
11+
steps:
12+
- name: Checkout repository
13+
uses: actions/checkout@v4
14+
15+
- uses: pnpm/action-setup@v4
16+
name: Install PNPM
17+
with:
18+
version: 9.0.5
19+
20+
- name: Set up Node.js
21+
uses: actions/setup-node@v4
22+
with:
23+
node-version: 18 # Specify your Node.js version
24+
cache: 'pnpm'
25+
26+
- name: Install dependencies
27+
run: |
28+
pnpm install --frozen-lockfile
29+
30+
- name: Build project
31+
run: |
32+
pnpm run build
33+
34+
- name: Deploy
35+
run: |
36+
pnpm run deploy

.vscode/settings.json

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,5 +16,9 @@
1616
"$website/routes/": "${workspaceRoot}/apps/website/src/routes/",
1717
"$website/": "${workspaceRoot}/apps/website/",
1818
"$packages/": "${workspaceRoot}/packages/"
19-
}
19+
},
20+
"deno.enable": true,
21+
"deno.enablePaths": [
22+
"./apps/reminders/src"
23+
]
2024
}

apps/reminders/.gitignore

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
*.js
2+
!jest.config.js
3+
*.d.ts
4+
node_modules
5+
6+
# CDK asset staging directory
7+
.cdk.staging
8+
cdk.out

apps/reminders/.npmignore

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
*.ts
2+
!*.d.ts
3+
4+
# CDK asset staging directory
5+
.cdk.staging
6+
cdk.out

apps/reminders/Dockerfile

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
# Set up the base image
2+
FROM public.ecr.aws/awsguru/aws-lambda-adapter:0.8.4 AS aws-lambda-adapter
3+
FROM denoland/deno:bin-1.45.2 AS deno_bin
4+
FROM debian:bookworm-20230703-slim AS deno_runtime
5+
COPY --from=aws-lambda-adapter /lambda-adapter /opt/extensions/lambda-adapter
6+
COPY --from=deno_bin /deno /usr/local/bin/deno
7+
ENV PORT=8000
8+
EXPOSE 8000
9+
RUN mkdir /var/deno_dir
10+
ENV DENO_DIR=/var/deno_dir
11+
12+
# Copy the function code
13+
WORKDIR "/var/task"
14+
COPY src/ /var/task
15+
16+
# Warmup caches
17+
RUN timeout 10s deno run -A index.ts || [ $? -eq 124 ] || exit 1
18+
19+
CMD ["deno", "run", "-A", "index.ts"]

apps/reminders/README.md

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
# Welcome to your CDK TypeScript project
2+
3+
This is a blank project for CDK development with TypeScript.
4+
5+
The `cdk.json` file tells the CDK Toolkit how to execute your app.
6+
7+
## Useful commands
8+
9+
* `npm run build` compile typescript to js
10+
* `npm run watch` watch for changes and compile
11+
* `npm run test` perform the jest unit tests
12+
* `npx cdk deploy` deploy this stack to your default AWS account/region
13+
* `npx cdk diff` compare deployed stack with current state
14+
* `npx cdk synth` emits the synthesized CloudFormation template

apps/reminders/bin/reminders.ts

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
#!/usr/bin/env node
2+
import 'source-map-support/register';
3+
import * as cdk from 'aws-cdk-lib';
4+
import { RemindersStack, validateEnvironment } from '../lib/reminders-stack';
5+
6+
const app = new cdk.App();
7+
const env = process.env.STACK_ENV || 'dev';
8+
9+
if (!validateEnvironment(env)) throw new Error('Invalid environment specified');
10+
11+
new RemindersStack(app, 'RemindersStack', {
12+
/* If you don't specify 'env', this stack will be environment-agnostic.
13+
* Account/Region-dependent features and context lookups will not work,
14+
* but a single synthesized template can be deployed anywhere. */
15+
/* Uncomment the next line to specialize this stack for the AWS Account
16+
* and Region that are implied by the current CLI configuration. */
17+
// env: { account: process.env.CDK_DEFAULT_ACCOUNT, region: process.env.CDK_DEFAULT_REGION },
18+
/* Uncomment the next line if you know exactly what Account and Region you
19+
* want to deploy the stack to. */
20+
environment: env,
21+
// env: { account: '123456789012', region: 'us-east-1' },
22+
/* For more information, see https://docs.aws.amazon.com/cdk/latest/guide/environments.html */
23+
});

apps/reminders/cdk.json

Lines changed: 72 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,72 @@
1+
{
2+
"app": "pnpm ts-node --prefer-ts-exts bin/reminders.ts",
3+
"watch": {
4+
"include": [
5+
"**"
6+
],
7+
"exclude": [
8+
"README.md",
9+
"cdk*.json",
10+
"**/*.d.ts",
11+
"**/*.js",
12+
"tsconfig.json",
13+
"package*.json",
14+
"yarn.lock",
15+
"node_modules",
16+
"test"
17+
]
18+
},
19+
"context": {
20+
"@aws-cdk/aws-lambda:recognizeLayerVersion": true,
21+
"@aws-cdk/core:checkSecretUsage": true,
22+
"@aws-cdk/core:target-partitions": [
23+
"aws",
24+
"aws-cn"
25+
],
26+
"@aws-cdk-containers/ecs-service-extensions:enableDefaultLogDriver": true,
27+
"@aws-cdk/aws-ec2:uniqueImdsv2TemplateName": true,
28+
"@aws-cdk/aws-ecs:arnFormatIncludesClusterName": true,
29+
"@aws-cdk/aws-iam:minimizePolicies": true,
30+
"@aws-cdk/core:validateSnapshotRemovalPolicy": true,
31+
"@aws-cdk/aws-codepipeline:crossAccountKeyAliasStackSafeResourceName": true,
32+
"@aws-cdk/aws-s3:createDefaultLoggingPolicy": true,
33+
"@aws-cdk/aws-sns-subscriptions:restrictSqsDescryption": true,
34+
"@aws-cdk/aws-apigateway:disableCloudWatchRole": true,
35+
"@aws-cdk/core:enablePartitionLiterals": true,
36+
"@aws-cdk/aws-events:eventsTargetQueueSameAccount": true,
37+
"@aws-cdk/aws-ecs:disableExplicitDeploymentControllerForCircuitBreaker": true,
38+
"@aws-cdk/aws-iam:importedRoleStackSafeDefaultPolicyName": true,
39+
"@aws-cdk/aws-s3:serverAccessLogsUseBucketPolicy": true,
40+
"@aws-cdk/aws-route53-patters:useCertificate": true,
41+
"@aws-cdk/customresources:installLatestAwsSdkDefault": false,
42+
"@aws-cdk/aws-rds:databaseProxyUniqueResourceName": true,
43+
"@aws-cdk/aws-codedeploy:removeAlarmsFromDeploymentGroup": true,
44+
"@aws-cdk/aws-apigateway:authorizerChangeDeploymentLogicalId": true,
45+
"@aws-cdk/aws-ec2:launchTemplateDefaultUserData": true,
46+
"@aws-cdk/aws-secretsmanager:useAttachedSecretResourcePolicyForSecretTargetAttachments": true,
47+
"@aws-cdk/aws-redshift:columnId": true,
48+
"@aws-cdk/aws-stepfunctions-tasks:enableEmrServicePolicyV2": true,
49+
"@aws-cdk/aws-ec2:restrictDefaultSecurityGroup": true,
50+
"@aws-cdk/aws-apigateway:requestValidatorUniqueId": true,
51+
"@aws-cdk/aws-kms:aliasNameRef": true,
52+
"@aws-cdk/aws-autoscaling:generateLaunchTemplateInsteadOfLaunchConfig": true,
53+
"@aws-cdk/core:includePrefixInUniqueNameGeneration": true,
54+
"@aws-cdk/aws-efs:denyAnonymousAccess": true,
55+
"@aws-cdk/aws-opensearchservice:enableOpensearchMultiAzWithStandby": true,
56+
"@aws-cdk/aws-lambda-nodejs:useLatestRuntimeVersion": true,
57+
"@aws-cdk/aws-efs:mountTargetOrderInsensitiveLogicalId": true,
58+
"@aws-cdk/aws-rds:auroraClusterChangeScopeOfInstanceParameterGroupWithEachParameters": true,
59+
"@aws-cdk/aws-appsync:useArnForSourceApiAssociationIdentifier": true,
60+
"@aws-cdk/aws-rds:preventRenderingDeprecatedCredentials": true,
61+
"@aws-cdk/aws-codepipeline-actions:useNewDefaultBranchForCodeCommitSource": true,
62+
"@aws-cdk/aws-cloudwatch-actions:changeLambdaPermissionLogicalIdForLambdaAction": true,
63+
"@aws-cdk/aws-codepipeline:crossAccountKeysDefaultValueToFalse": true,
64+
"@aws-cdk/aws-codepipeline:defaultPipelineTypeToV2": true,
65+
"@aws-cdk/aws-kms:reduceCrossAccountRegionPolicyScope": true,
66+
"@aws-cdk/aws-eks:nodegroupNameAttribute": true,
67+
"@aws-cdk/aws-ec2:ebsDefaultGp3Volume": true,
68+
"@aws-cdk/aws-ecs:removeDefaultDeploymentAlarm": true,
69+
"@aws-cdk/custom-resources:logApiResponseDataPropertyTrueDefault": false,
70+
"@aws-cdk/aws-s3:keepNotificationInImportedBucket": false
71+
}
72+
}

apps/reminders/jest.config.js

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
module.exports = {
2+
testEnvironment: 'node',
3+
roots: ['<rootDir>/test'],
4+
testMatch: ['**/*.test.ts'],
5+
transform: {
6+
'^.+\\.tsx?$': 'ts-jest'
7+
}
8+
};
Lines changed: 67 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,67 @@
1+
import * as cdk from 'aws-cdk-lib';
2+
import { Construct } from 'constructs';
3+
import * as ses from 'aws-cdk-lib/aws-ses';
4+
import * as events from 'aws-cdk-lib/aws-events';
5+
import * as lambda from 'aws-cdk-lib/aws-lambda';
6+
import * as targets from 'aws-cdk-lib/aws-events-targets';
7+
import { join } from 'node:path';
8+
9+
export type Environment = 'dev' | 'prod' | 'staging';
10+
11+
export interface ReminderStackProps extends cdk.StackProps {
12+
environment: Environment;
13+
}
14+
15+
export function validateEnvironment(
16+
environment: string,
17+
): environment is Environment {
18+
return ['dev', 'prod', 'staging'].includes(environment);
19+
}
20+
21+
export class RemindersStack extends cdk.Stack {
22+
constructor(
23+
scope: Construct,
24+
id: string,
25+
props: ReminderStackProps = {
26+
environment: 'dev',
27+
},
28+
) {
29+
super(scope, id, props);
30+
31+
// Setup the identity domain for SES
32+
33+
const identityDomain =
34+
this.environment !== 'prod'
35+
? 'staging.notifications.sungmanito.app'
36+
: 'notifications.sungmanito.app';
37+
38+
const sesEmailDomain = ses.Identity.domain(identityDomain);
39+
40+
const reminderTemplateProps: ses.CfnTemplate.TemplateProperty = {
41+
templateName: 'reminder',
42+
subjectPart: '{household}: You have {count} coming up soon',
43+
textPart: 'You have {count} bills coming up soon.',
44+
htmlPart: `<p>You have {count} bills coming up soon.</p>{billList}`,
45+
};
46+
47+
const reminderTemplate = new ses.CfnTemplate(this, 'reminderTemplate', {
48+
template: reminderTemplateProps,
49+
});
50+
51+
// Setup cron scheduler
52+
const rule = new events.Rule(this, 'Daily8amPSTRule', {
53+
schedule: events.Schedule.cron({ minute: '0', hour: '16' }), // 16:00 UTC is 8:00 PST
54+
});
55+
56+
// Define the Lambda function
57+
const reminderLambda = new lambda.DockerImageFunction(
58+
this,
59+
'ReminderLambda',
60+
{
61+
code: lambda.DockerImageCode.fromImageAsset(join(__dirname, '..'), {}),
62+
},
63+
);
64+
65+
rule.addTarget(new targets.LambdaFunction(reminderLambda));
66+
}
67+
}

0 commit comments

Comments
 (0)