Skip to content

Commit

Permalink
Add CDK TypeScript code to deploy frontend to S3 + CloudFront
Browse files Browse the repository at this point in the history
  • Loading branch information
ryichk committed Jan 4, 2025
1 parent f343fe5 commit ac73d4f
Show file tree
Hide file tree
Showing 21 changed files with 5,666 additions and 4 deletions.
15 changes: 11 additions & 4 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -1,12 +1,14 @@
# root
.env
.env.production
tmp

# client
node_modules

/.cache
/build
/public/build
/client/.cache
/client/build
/client/public/build

# api
## Binaries for programs and plugins
Expand All @@ -26,4 +28,9 @@ node_modules
go.work
go.work.sum

tmp
# infra-ts
infra-ts/*.js
!jest.config.js
*.d.ts

.cdk.staging
30 changes: 30 additions & 0 deletions Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -61,3 +61,33 @@ test:

test_v:
$(DOCKER_RUN_API) go test -v -cover ./...

build_client:
$(DOCKER_RUN_CLIENT) npm run build

npm_i_infra-ts:
npm i --prefix ./infra-ts

cdk:
npm run cdk $(CMD) --prefix ./infra-ts

cdk_bootstrap:
npm run cdk:bootstrap --prefix ./infra-ts

cdk_deploy:
npm run cdk:deploy $(STACK) --prefix ./infra-ts

cdk_deploy_all:
npm run cdk:deploy:all --prefix ./infra-ts

cdk_rollback:
npm run cdk:rollback $(STACK) --prefix ./infra-ts

cdk_rollback_all:
npm run cdk:rollback:all --prefix ./infra-ts

cdk_destroy:
npm run cdk:destroy $(STACK) --prefix ./infra-ts

cdk_destroy_all:
npm run cdk:destroy:all --prefix ./infra-ts
34 changes: 34 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,17 @@

- PostgreSQL

### Infrastructure

#### Cloud Vendor

- AWS

#### Tools

- Node.js v22.11.0
- aws-cdk v2.173.4

## Environment Construction

### 1. Install Docker
Expand Down Expand Up @@ -151,3 +162,26 @@ The request handler implements request validation, etc.
### Implement Request Routing

Implement request routing in `api/internal/server/router.go`.

## Infrastructure Construction Procedure

### Setup

```sh
make npm_i_infra-ts
make cdk_bootstrap
```

### Deploy

#### Deploy All Stack

```sh
make cdk_deploy_all
```

#### Deploy Stacks individually

```sh
make cdk_deploy STACK=StackName
```
6 changes: 6 additions & 0 deletions infra-ts/.npmignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
*.ts
!*.d.ts

# CDK asset staging directory
.cdk.staging
cdk.out
14 changes: 14 additions & 0 deletions infra-ts/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
# Welcome to your CDK TypeScript project

This is a blank project for CDK development with TypeScript.

The `cdk.json` file tells the CDK Toolkit how to execute your app.

## Useful commands

* `npm run build` compile typescript to js
* `npm run watch` watch for changes and compile
* `npm run test` perform the jest unit tests
* `npm run cdk deploy` deploy this stack to your default AWS account/region
* `npm run cdk diff` compare deployed stack with current state
* `npm run cdk synth` emits the synthesized CloudFormation template
26 changes: 26 additions & 0 deletions infra-ts/bin/infra.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
#!/usr/bin/env node
import 'source-map-support/register';
import * as cdk from 'aws-cdk-lib';
import { FrontendStack, frontendStackProperties } from '../lib/frontend-stack';
import { CertificateStack, certificateStackProperties } from '../lib/certificate-stack';
import { Route53Stack, route53tackProperties } from '../lib/route53-stack';

const app = new cdk.App();
const route53Stack = new Route53Stack(app, "TodoListRoute53Stack", {
env: route53tackProperties.env,
crossRegionReferences: true,
...route53tackProperties.hostedZone,
});
const certificateStack = new CertificateStack(app, "TodoListCertificateStack", {
env: certificateStackProperties.env,
crossRegionReferences: true,
route53Stack,
...certificateStackProperties.certificate,
});
new FrontendStack(app, 'TodoListFrontendStack', {
env: frontendStackProperties.env,
crossRegionReferences: true,
route53Stack,
certificateStack,
...frontendStackProperties.props,
});
80 changes: 80 additions & 0 deletions infra-ts/cdk.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,80 @@
{
"app": "npx ts-node --prefer-ts-exts bin/infra.ts",
"watch": {
"include": [
"**"
],
"exclude": [
"README.md",
"cdk*.json",
"**/*.d.ts",
"**/*.js",
"tsconfig.json",
"package*.json",
"yarn.lock",
"node_modules",
"test"
]
},
"context": {
"@aws-cdk/aws-lambda:recognizeLayerVersion": true,
"@aws-cdk/core:checkSecretUsage": true,
"@aws-cdk/core:target-partitions": [
"aws",
"aws-cn"
],
"@aws-cdk-containers/ecs-service-extensions:enableDefaultLogDriver": true,
"@aws-cdk/aws-ec2:uniqueImdsv2TemplateName": true,
"@aws-cdk/aws-ecs:arnFormatIncludesClusterName": true,
"@aws-cdk/aws-iam:minimizePolicies": true,
"@aws-cdk/core:validateSnapshotRemovalPolicy": true,
"@aws-cdk/aws-codepipeline:crossAccountKeyAliasStackSafeResourceName": true,
"@aws-cdk/aws-s3:createDefaultLoggingPolicy": true,
"@aws-cdk/aws-sns-subscriptions:restrictSqsDescryption": true,
"@aws-cdk/aws-apigateway:disableCloudWatchRole": true,
"@aws-cdk/core:enablePartitionLiterals": true,
"@aws-cdk/aws-events:eventsTargetQueueSameAccount": true,
"@aws-cdk/aws-ecs:disableExplicitDeploymentControllerForCircuitBreaker": true,
"@aws-cdk/aws-iam:importedRoleStackSafeDefaultPolicyName": true,
"@aws-cdk/aws-s3:serverAccessLogsUseBucketPolicy": true,
"@aws-cdk/aws-route53-patters:useCertificate": true,
"@aws-cdk/customresources:installLatestAwsSdkDefault": false,
"@aws-cdk/aws-rds:databaseProxyUniqueResourceName": true,
"@aws-cdk/aws-codedeploy:removeAlarmsFromDeploymentGroup": true,
"@aws-cdk/aws-apigateway:authorizerChangeDeploymentLogicalId": true,
"@aws-cdk/aws-ec2:launchTemplateDefaultUserData": true,
"@aws-cdk/aws-secretsmanager:useAttachedSecretResourcePolicyForSecretTargetAttachments": true,
"@aws-cdk/aws-redshift:columnId": true,
"@aws-cdk/aws-stepfunctions-tasks:enableEmrServicePolicyV2": true,
"@aws-cdk/aws-ec2:restrictDefaultSecurityGroup": true,
"@aws-cdk/aws-apigateway:requestValidatorUniqueId": true,
"@aws-cdk/aws-kms:aliasNameRef": true,
"@aws-cdk/aws-autoscaling:generateLaunchTemplateInsteadOfLaunchConfig": true,
"@aws-cdk/core:includePrefixInUniqueNameGeneration": true,
"@aws-cdk/aws-efs:denyAnonymousAccess": true,
"@aws-cdk/aws-opensearchservice:enableOpensearchMultiAzWithStandby": true,
"@aws-cdk/aws-lambda-nodejs:useLatestRuntimeVersion": true,
"@aws-cdk/aws-efs:mountTargetOrderInsensitiveLogicalId": true,
"@aws-cdk/aws-rds:auroraClusterChangeScopeOfInstanceParameterGroupWithEachParameters": true,
"@aws-cdk/aws-appsync:useArnForSourceApiAssociationIdentifier": true,
"@aws-cdk/aws-rds:preventRenderingDeprecatedCredentials": true,
"@aws-cdk/aws-codepipeline-actions:useNewDefaultBranchForCodeCommitSource": true,
"@aws-cdk/aws-cloudwatch-actions:changeLambdaPermissionLogicalIdForLambdaAction": true,
"@aws-cdk/aws-codepipeline:crossAccountKeysDefaultValueToFalse": true,
"@aws-cdk/aws-codepipeline:defaultPipelineTypeToV2": true,
"@aws-cdk/aws-kms:reduceCrossAccountRegionPolicyScope": true,
"@aws-cdk/aws-eks:nodegroupNameAttribute": true,
"@aws-cdk/aws-ec2:ebsDefaultGp3Volume": true,
"@aws-cdk/aws-ecs:removeDefaultDeploymentAlarm": true,
"@aws-cdk/custom-resources:logApiResponseDataPropertyTrueDefault": false,
"@aws-cdk/aws-s3:keepNotificationInImportedBucket": false,
"@aws-cdk/aws-ecs:reduceEc2FargateCloudWatchPermissions": true,
"@aws-cdk/aws-dynamodb:resourcePolicyPerReplica": true,
"@aws-cdk/aws-ec2:ec2SumTImeoutEnabled": true,
"@aws-cdk/aws-appsync:appSyncGraphQLAPIScopeLambdaPermission": true,
"@aws-cdk/aws-rds:setCorrectValueForDatabaseInstanceReadReplicaInstanceResourceId": true,
"@aws-cdk/core:cfnIncludeRejectComplexResourceUpdateCreatePolicyIntrinsics": true,
"@aws-cdk/aws-lambda-nodejs:sdkV3ExcludeSmithyPackages": true,
"@aws-cdk/aws-stepfunctions-tasks:fixRunEcsTaskPolicy": true
}
}
8 changes: 8 additions & 0 deletions infra-ts/jest.config.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
module.exports = {
testEnvironment: 'node',
roots: ['<rootDir>/test'],
testMatch: ['**/*.test.ts'],
transform: {
'^.+\\.tsx?$': 'ts-jest'
}
};
49 changes: 49 additions & 0 deletions infra-ts/lib/certificate-stack.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
import * as cdk from "aws-cdk-lib";
import { Construct } from "constructs";
import { ICertificateStack, StackProperties } from "./types";
import { Route53Stack } from "./route53-stack";

export interface ICertificateStackProps extends cdk.StackProps, ICertificateStack {
route53Stack?: Route53Stack
}

export class CertificateStack extends cdk.Stack {
readonly certificate: cdk.aws_certificatemanager.ICertificate

constructor(scope: Construct, id: string, props: ICertificateStackProps) {
super(scope, id, props)

const { certificateArn, certificateDomainName, route53Stack } = props;

if (certificateArn) {
this.certificate = cdk.aws_certificatemanager.Certificate.fromCertificateArn(
this,
"Default",
certificateArn,
);
} else if (certificateDomainName && route53Stack?.publicHostedZone) {
this.certificate = new cdk.aws_certificatemanager.Certificate(
this,
"TodoCertificate",
{
domainName: certificateDomainName,
validation: cdk.aws_certificatemanager.CertificateValidation.fromDns(
route53Stack.publicHostedZone
),
}
);
}
}
}

export const certificateStackProperties: StackProperties & {
certificate: ICertificateStack
} = {
env: {
account: process.env.CDK_DEFAULT_ACCOUNT,
region: "us-east-1",
},
certificate: {
certificateDomainName: "todolist.ryichk.com",
},
}
Loading

0 comments on commit ac73d4f

Please sign in to comment.