Skip to content

Commit

Permalink
chore(cdk): so close
Browse files Browse the repository at this point in the history
  • Loading branch information
meza committed Feb 22, 2023
1 parent 2f96305 commit b680566
Show file tree
Hide file tree
Showing 16 changed files with 488 additions and 43 deletions.
4 changes: 2 additions & 2 deletions .github/workflows/deploy.yml
Original file line number Diff line number Diff line change
Expand Up @@ -44,13 +44,13 @@ jobs:
SPLIT_DEBUG: ${{ env.ARC_ENV == 'production' && 'false' || 'true' }}
- name: 📦 Deploy Production
if: github.ref_name == 'main'
run: pnpm exec arc deploy -e production --production --name main -v
run: pnpm exec cdk deploy --all --require-approval never
env:
AWS_ACCESS_KEY_ID: ${{ secrets.AWS_ACCESS_KEY_ID }}
AWS_SECRET_ACCESS_KEY: ${{ secrets.AWS_SECRET_ACCESS_KEY }}
- name: 📦 Deploy ${{ github.ref_name }}
if: github.ref_name != 'main'
run: pnpm exec arc deploy -e staging --name ${{ github.ref_name }} -v
run: pnpm exec cdk deploy --all --require-approval never --context name=${{ github.ref_name }}
env:
AWS_ACCESS_KEY_ID: ${{ secrets.AWS_ACCESS_KEY_ID }}
AWS_SECRET_ACCESS_KEY: ${{ secrets.AWS_SECRET_ACCESS_KEY }}
Expand Down
4 changes: 4 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,10 @@
.idea
.vscode

# CDK asset staging directory
.cdk.staging
cdk.out

dist
reports
node_modules
Expand Down
6 changes: 6 additions & 0 deletions .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
48 changes: 48 additions & 0 deletions cdk.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
{
"app": "npx ts-node --prefer-ts-exts deployment/cdk.ts",
"watch": {
"include": [
"**"
],
"exclude": [
"README.md",
"cdk*.json",
"**/*.d.ts",
"**/*.js",
"tsconfig.json",
"package*.json",
"pnpm*.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-iam:standardizedServicePrincipals": 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
}
}
14 changes: 14 additions & 0 deletions deployment/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
* `cdk deploy` deploy this stack to your default AWS account/region
* `cdk diff` compare deployed stack with current state
* `cdk synth` emits the synthesized CloudFormation template
20 changes: 20 additions & 0 deletions deployment/cdk.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
#!/usr/bin/env node
import 'source-map-support/register';
import * as cdk from 'aws-cdk-lib';
import { name } from '../package.json';
import { CdkStack } from './lib/cdkStack';

const app = new cdk.App();
// eslint-disable-next-line no-new
new CdkStack(app, name, {
env: {
account: process.env.CDK_DEFAULT_ACCOUNT,
region: 'us-east-1' // must be us-east-1 to allow Lambda@Edge
}

/* Uncomment the next line if you know exactly what Account and Region you
* want to deploy the stack to. */
// env: { account: '123456789012', region: 'us-east-1' },

/* For more information, see https://docs.aws.amazon.com/cdk/latest/guide/environments.html */
});
19 changes: 19 additions & 0 deletions deployment/lib/cdkStack.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
// import * as cdk from 'aws-cdk-lib';
// import { Template } from 'aws-cdk-lib/assertions';
// import * as Cdk from '../lib/cdk-stack';

// example test. To run these tests, uncomment this file along with the
// example resource in lib/cdk-stack.ts
import { it } from 'vitest';

it.skip('SQS Queue Created', () => {
// const app = new cdk.App();
// // WHEN
// const stack = new Cdk.CdkStack(app, 'MyTestStack');
// // THEN
// const template = Template.fromStack(stack);

// template.hasResourceProperties('AWS::SQS::Queue', {
// VisibilityTimeout: 300
// });
});
140 changes: 140 additions & 0 deletions deployment/lib/cdkStack.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,140 @@
import path from 'node:path';
import { HttpApi } from '@aws-cdk/aws-apigatewayv2-alpha';
import { HttpLambdaIntegration } from '@aws-cdk/aws-apigatewayv2-integrations-alpha';
import { Duration, Stack } from 'aws-cdk-lib';
import { Certificate } from 'aws-cdk-lib/aws-certificatemanager';
import {
AllowedMethods, CacheCookieBehavior, CacheHeaderBehavior,
CachePolicy, CacheQueryStringBehavior,
Distribution,
OriginRequestCookieBehavior,
OriginRequestHeaderBehavior,
OriginRequestPolicy,
OriginRequestQueryStringBehavior,
PriceClass,
ViewerProtocolPolicy
} from 'aws-cdk-lib/aws-cloudfront';
import { HttpOrigin, S3Origin } from 'aws-cdk-lib/aws-cloudfront-origins';
import { CompositePrincipal, Role, ServicePrincipal } from 'aws-cdk-lib/aws-iam';
import { Runtime, Tracing } from 'aws-cdk-lib/aws-lambda';
import { NodejsFunction } from 'aws-cdk-lib/aws-lambda-nodejs';
import { RetentionDays } from 'aws-cdk-lib/aws-logs';
import { ARecord, HostedZone, RecordTarget } from 'aws-cdk-lib/aws-route53';
import { CloudFrontTarget } from 'aws-cdk-lib/aws-route53-targets';
import { Bucket } from 'aws-cdk-lib/aws-s3';
import { BucketDeployment, CacheControl, Source } from 'aws-cdk-lib/aws-s3-deployment';
import { ParameterTier, StringParameter } from 'aws-cdk-lib/aws-ssm';
import type { StackProps } from 'aws-cdk-lib';
import type { AddBehaviorOptions } from 'aws-cdk-lib/aws-cloudfront';
import type { Construct } from 'constructs';

export class CdkStack extends Stack {
readonly distributionUrlParameterName = '/remix/distribution/url';
readonly domainName = 'trance-stack.vsbmeza.com';
readonly certificateArn = 'arn:aws:acm:us-east-1:816237403055:certificate/028f6e6d-99c3-493b-92e6-3d17c6f37a48';

constructor(scope: Construct, id: string, props?: StackProps) {
super(scope, id, props);

const bucket = new Bucket(this, 'TranceStackBucket');

// eslint-disable-next-line no-new
new BucketDeployment(this, 'DeployStaticAssets', {
sources: [Source.asset(path.join(__dirname, '../../public'))],
destinationBucket: bucket,
destinationKeyPrefix: '_static',
cacheControl: [
CacheControl.maxAge(Duration.days(365)),
CacheControl.sMaxAge(Duration.days(365))
]
});

const lambdaRole = new Role(this, 'TranceStackLambdaRole', {
assumedBy: new CompositePrincipal(new ServicePrincipal('lambda.amazonaws.com'))
});

const fn = new NodejsFunction(this, 'TranceStackRequestHandler', {
runtime: Runtime.NODEJS_18_X,
entry: path.join(__dirname, '../../server/index.js'),
bundling: {
nodeModules: ['@remix-run/architect', 'react', 'react-dom']
},
timeout: Duration.seconds(10),
logRetention: RetentionDays.THREE_DAYS,
tracing: Tracing.ACTIVE,
role: lambdaRole
});

const integration = new HttpLambdaIntegration('TranceStackHttpLambdaIntegration', fn);

const httpApi = new HttpApi(this, 'TranceStackApi', {
defaultIntegration: integration
});

const httpApiUrl = `${httpApi.httpApiId}.execute-api.${Stack.of(this).region}.${Stack.of(this).urlSuffix}`;
const originRequestPolicy = new OriginRequestPolicy(this, 'TranceStackRequestHandlerPolicy', {
originRequestPolicyName: 'website-request-handler',
queryStringBehavior: OriginRequestQueryStringBehavior.all(),
cookieBehavior: OriginRequestCookieBehavior.all(),
// https://stackoverflow.com/questions/65243953/pass-query-params-from-cloudfront-to-api-gateway
headerBehavior: OriginRequestHeaderBehavior.allowList(
'Accept-Charset', 'Origin', 'Access-Control-Request-Method', 'Access-Control-Request-Headers', 'Referer', 'Accept-Language', 'Accept-Datetime'
)
});

const cachePolicy = new CachePolicy(this, 'TranceStackCachePolicy', {
cachePolicyName: 'remix-cache-policy',
defaultTtl: Duration.seconds(86400),
minTtl: Duration.seconds(0),
maxTtl: Duration.seconds(31536000),
cookieBehavior: CacheCookieBehavior.none(),
headerBehavior: CacheHeaderBehavior.allowList('Origin', 'Access-Control-Request-Method', 'Access-Control-Request-Headers', 'Referer', 'Accept-Language', 'Accept-Datetime'),
queryStringBehavior: CacheQueryStringBehavior.none()
});
const requestHandlerBehavior: AddBehaviorOptions = {
allowedMethods: AllowedMethods.ALLOW_ALL,
viewerProtocolPolicy: ViewerProtocolPolicy.REDIRECT_TO_HTTPS,
cachePolicy: cachePolicy,
originRequestPolicy: originRequestPolicy
};

const assetOrigin = new S3Origin(bucket);
const assetBehaviorOptions = {
viewerProtocolPolicy: ViewerProtocolPolicy.REDIRECT_TO_HTTPS
};

const distribution = new Distribution(this, 'TranceStackCloudFront', {
domainNames: [this.domainName],
certificate: Certificate.fromCertificateArn(this, 'TranceStackCertificate', this.certificateArn),
defaultBehavior: {
compress: true,
origin: new HttpOrigin(httpApiUrl),
...requestHandlerBehavior
},
priceClass: PriceClass.PRICE_CLASS_ALL,
additionalBehaviors: {
'/_static/*': {
origin: assetOrigin,
...assetBehaviorOptions
}
}
});

// eslint-disable-next-line no-new
new ARecord(this, 'TranceStackAliasRecord', {
zone: HostedZone.fromHostedZoneAttributes(this, 'HostedZone', {
hostedZoneId: 'Z2UAK2IOFEOI1W',
zoneName: 'vsbmeza.com'
}),
recordName: this.domainName,
target: RecordTarget.fromAlias(new CloudFrontTarget(distribution))
});

// eslint-disable-next-line no-new
new StringParameter(this, 'TranceStackDistributionUrlParameter', {
parameterName: this.distributionUrlParameterName,
stringValue: distribution.distributionDomainName,
tier: ParameterTier.STANDARD
});
}
}
13 changes: 11 additions & 2 deletions package.json
Original file line number Diff line number Diff line change
@@ -1,12 +1,13 @@
{
"version": "0.0.0-dev",
"name": "remix-trance-stack",
"private": true,
"sideEffects": false,
"scripts": {
"build": "run-s build:remix",
"build:remix": "remix build",
"deploy:arc": "arc deploy",
"deploy:prod": "run-s build:remix \"deploy:arc --production --name main -v\"",
"deploy:cdk": "cdk deploy --all --require-approval never",
"deploy:prod": "run-s build:remix deploy:cdk",
"dev:remix": "cross-env NODE_ENV=development remix watch",
"dev:arc": "cross-env NODE_ENV=development arc sandbox -p 3000 --verbose",
"dev": "run-p dev:remix dev:arc",
Expand Down Expand Up @@ -56,6 +57,8 @@
},
"devDependencies": {
"@architect/architect": "^10.7.2",
"@aws-cdk/aws-apigatewayv2-alpha": "2.66.0-alpha.0",
"@aws-cdk/aws-apigatewayv2-integrations-alpha": "2.66.0-alpha.0",
"@babel/core": "^7.20.12",
"@commitlint/cli": "17.4.4",
"@commitlint/config-conventional": "17.4.4",
Expand All @@ -64,6 +67,7 @@
"@playwright/test": "^1.30.0",
"@remix-run/dev": "^1.13.0",
"@remix-run/eslint-config": "^1.13.0",
"@remix-run/serve": "^1.13.0",
"@semantic-release/commit-analyzer": "^9.0.2",
"@semantic-release/github": "^8.0.7",
"@semantic-release/release-notes-generator": "^10.0.3",
Expand Down Expand Up @@ -99,11 +103,15 @@
"@vitejs/plugin-react": "^3.1.0",
"@vitest/coverage-c8": "^0.28.5",
"autoprefixer": "^10.4.13",
"aws-cdk": "^2.66.0",
"aws-cdk-lib": "^2.66.0",
"c8": "7.13.0",
"colorguard": "^1.2.1",
"constructs": "^10.1.257",
"cssnano": "^5.1.14",
"doiuse": "^4.4.1",
"esbuild": "^0.17.10",
"esbuild-copy-static-files": "^0.1.0",
"esbuild-plugin-env": "^1.0.5",
"esbuild-plugin-environment": "^0.2.4",
"eslint": "^8.27.0",
Expand Down Expand Up @@ -139,6 +147,7 @@
"stylelint": "^15.1.0",
"stylelint-config-standard": "^30.0.1",
"stylelint-order": "^6.0.2",
"ts-node": "^10.9.1",
"tsconfig-paths": "^4.1.2",
"tsconfig-paths-webpack-plugin": "^4.0.0",
"typescript": "^4.9.5",
Expand Down
Loading

0 comments on commit b680566

Please sign in to comment.