Skip to content

Commit

Permalink
Move from SAM to CDK
Browse files Browse the repository at this point in the history
  • Loading branch information
ScriptSmith committed Oct 3, 2023
1 parent 6e170d3 commit f96f4f6
Show file tree
Hide file tree
Showing 25 changed files with 6,453 additions and 809 deletions.
49 changes: 49 additions & 0 deletions .github/workflows/deploy.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
name: Deploy CDK Stack
on:
push:
branches:
- dev
- qa
- prod
jobs:
deploy:
runs-on: ubuntu-latest
environment: ${{ github.ref_name }}
permissions:
actions: write
contents: read
id-token: write
steps:
- uses: actions/checkout@v4
- name: Setup Node.js
uses: actions/setup-node@v3
with:
node-version: '18'
cache: 'npm'
cache-dependency-path: deployment
- name: Install CDK
run: npm install -g aws-cdk
- name: Install dependencies
working-directory: deployment
run: npm install
- uses: aws-actions/configure-aws-credentials@v4
with:
aws-region: ap-southeast-2
role-to-assume: ${{ env.API_ROLE_ARN }}
role-duration-seconds: 900
output-credentials: true
- name: Deploy base stack
working-directory: deployment
run: cdk deploy TranscriptionStack
- name: Save FrontEndEnvironment to file
working-directory: frontend
run: aws cloudformation describe-stacks --stack-name ${{ env.ENVIRONMENT }}-transcription --query "Stacks[0].Outputs[?OutputKey=='FrontEndEnvironment'].OutputValue" --output text > .env.production
- uses: aws-actions/configure-aws-credentials@v4
with:
aws-region: us-east-1
role-to-assume: ${{ env.FRONTEND_ROLE_ARN }}
role-duration-seconds: 900
output-credentials: true
- name: Deploy frontend stack
working-directory: deployment
run: cdk deploy TranscriptionFrontEndStack
18 changes: 0 additions & 18 deletions INSTRUCTIONS.md

This file was deleted.

66 changes: 52 additions & 14 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,8 +5,6 @@
![homepage](images/homepage.png)
![transcription](images/transcription.png)

[Custom deployment instructions](INSTRUCTIONS.md)

## Linting and Formatting

### Frontend
Expand Down Expand Up @@ -34,27 +32,67 @@ git config blame.ignoreRevsFile .git-blame-ignore-revs
## Manual deployment instructions

```
export ENV=dev # or qa, prod
cd deployment
npm install
```

### *Optional: Create GitHub deployment stack*

```
cdk deploy TranscriptionGitHubStack
cdk deploy TranscriptionFrontEndGitHubStack
```

### *Optional: Assume the GitHub role locally*


`~/.aws/config`:

```
[profile qut-dev]
region = ap-southeast-2
[profile qut-dev-github]
role_arn = <TranscriptionGitHubStack.deployRoleArn>
source_profile = qut-dev
[profile qut-dev-github-frontend]
role_arn = <TranscriptionFrontEndGitHubStack.deployRoleArn>
source_profile = qut-dev
region = us-east-1
```

Deploy the stacks with the GitHub role:

```
AWS_PROFILE=qut-dev-github cdk deploy TranscriptionStack
AWS_PROFILE=qut-dev-github-frontend cdk deploy TranscriptionFrontEndStack
```

export STACK_NAME=$ENV-transcription
export LAMBDA_BUCKET_NAME=qut-lambda-code-ap-southeast-2-dev
export S3_PREFIX=dev-transcription
### Deploy base stack

Also builds the lambda functions

```
cdk deploy TranscriptionStack
```

### In root
### Build the frontend

```
sam build
sam deploy --s3-bucket $LAMBDA_BUCKET_NAME --s3-prefix $STACK_NAME --stack-name $STACK_NAME --capabilities CAPABILITY_IAM --profile account-role
aws cloudformation describe-stacks --stack-name $STACK_NAME --query "Stacks[0].Outputs[?OutputKey=='FrontEndEnvironment'].OutputValue" --output text --profile account-role | sed '/^[[:space:]]*$/d' > ./frontend/.env.production
export STACK_NAME=dev-transcription
aws cloudformation describe-stacks --stack-name $STACK_NAME --query "Stacks[0].Outputs[?OutputKey=='FrontEndEnvironment'].OutputValue" --output text > ../frontend/.env.production
```

### In frontend
From the top-level `frontend` directory:

```
yarn install
yarn build
export $(aws cloudformation describe-stacks --stack-name $ENV-transcription --region ap-southeast-2 --query "Stacks[0].Outputs[?OutputKey=='DistributionEnvironment'].OutputValue" --output text --profile account-role | sed '/^[[:space:]]*$/d' | xargs)
aws s3 sync out $DISTRIBUTION_BUCKET --profile account-role
aws cloudfront create-invalidation --distribution-id $DISTRIBUTION_ID --paths "/*" --profile account-role
```

### Deploy frontend stack

```
cdk deploy FrontEndStack
```
2 changes: 1 addition & 1 deletion api/tsconfig.json
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
{
"compilerOptions": {
"target": "es2020",
"module": "commonjs",
"module": "ES2022",
"esModuleInterop": true,
"forceConsistentCasingInFileNames": true,
"strict": true,
Expand Down
21 changes: 1 addition & 20 deletions buildspec.yml
Original file line number Diff line number Diff line change
@@ -1,24 +1,5 @@
version: 0.2
phases:
install:
runtime-versions:
nodejs: 18
commands:
- npm install -g yarn esbuild
- yarn -v
pre_build:
commands:
- mkdir ~/.aws
- echo "[profile account-role]\nrole_arn = ${ACCOUNT_ROLE}\ncredential_source = EcsContainer" >> ~/.aws/config
build:
commands:
- (cd api; npm install)
- (cd api; npm run build)
- sam build
- sam deploy --config-env $ENV --s3-bucket $LAMBDA_BUCKET_NAME --s3-prefix $ENV-$STACK_NAME --stack-name $STACK_NAME --capabilities CAPABILITY_IAM --profile account-role
- aws cloudformation describe-stacks --stack-name $STACK_NAME --query "Stacks[0].Outputs[?OutputKey=='FrontEndEnvironment'].OutputValue" --output text --profile account-role | sed '/^[[:space:]]*$/d' > ./frontend/.env.production
- (cd frontend; yarn install)
- (cd frontend; yarn build)
- export $(aws cloudformation describe-stacks --stack-name $STACK_NAME --query "Stacks[0].Outputs[?OutputKey=='DistributionEnvironment'].OutputValue" --output text --profile account-role | sed '/^[[:space:]]*$/d' | xargs)
- aws s3 sync ./frontend/out $DISTRIBUTION_BUCKET --profile account-role
- aws cloudfront create-invalidation --distribution-id $DISTRIBUTION_ID --paths "/*" --profile account-role
- echo "Doing nothing"
10 changes: 10 additions & 0 deletions deployment/.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
*.js
!jest.config.js
*.d.ts
node_modules

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

cdk.context.json
6 changes: 6 additions & 0 deletions deployment/.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 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
90 changes: 90 additions & 0 deletions deployment/bin/deployment.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,90 @@
#!/usr/bin/env node
import * as cdk from "aws-cdk-lib";
import { ApiStack } from "../lib/api-stack";
import { GitHubStack } from "../lib/github-stack";
import { FrontEndStack } from "../lib/front-end-stack";
import { GetParameterCommand, SSMClient } from "@aws-sdk/client-ssm";

type Environment = "dev" | "qa" | "prod";

interface EnvironmentConfig {
account: string;
region: string;
parameters: {
ApiDomainName: string;
ApplicationName: string;
AwsRoute53CloudFrontHostedZoneId: string;
Environment: Environment;
FrontEndDomainName: string;
GlobalCertificateArn: string;
GlobalWafArn: string;
HostedZoneName: string;
IdentityProviderLogoutURL: string;
LogBucketSuffix: string;
RegionalCertificateArn: string;
RegionalWafArn: string;
SubnetIds: string[];
SupportedIdentityProviders: string[];
UserPoolStackName: string;
VpcId: string;
};
}


const owner = "eresearchqut";
const repo = "transcription";

const envName = (process.env.GITHUB_REF_NAME ?? "dev") as Environment;

const apiStackName = `${envName}-${repo}`;
const frontendStackName = `${envName}-${repo}-frontend`;

const app = new cdk.App({});

new SSMClient().send(new GetParameterCommand({ Name: `/app/${envName}/${repo}/env` }))
.then(({ Parameter }) => JSON.parse(Parameter?.Value ?? "{}"))
.then((env: EnvironmentConfig) => {
const apiGitHubStack = new GitHubStack(app, "TranscriptionGitHubStack", {
envName,
owner,
repo,
stacks: [apiStackName],
env: { account: env.account, region: env.region }
});
const frontEndGitHubStack = new GitHubStack(app, "TranscriptionFrontEndGitHubStack", {
envName,
owner,
repo,
stacks: [frontendStackName],
env: { account: env.account, region: "us-east-1" }
});


const apiStack = new ApiStack(app, "TranscriptionStack", {
stackName: apiStackName,
synthesizer: new cdk.CliCredentialsStackSynthesizer({
fileAssetsBucketName: `${env.account}-${env.region}-${owner}-${repo}`
}),
parameters: env.parameters,
env: { account: env.account, region: env.region }
});
const frontEndStack = new FrontEndStack(app, "TranscriptionFrontEndStack", {
stackName: frontendStackName,
synthesizer: new cdk.CliCredentialsStackSynthesizer({
fileAssetsBucketName: `${env.account}-us-east-1-${owner}-${repo}`
}),
parameters: env.parameters,
env: { account: env.account, region: "us-east-1" }
});

[
apiStack,
apiGitHubStack,
frontEndStack,
frontEndGitHubStack
]
.forEach(stack => cdk.Tags.of(stack).add("EresCdkApp", repo));
});



61 changes: 61 additions & 0 deletions deployment/cdk.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,61 @@
{
"app": "npx ts-node --prefer-ts-exts bin/deployment.ts",
"requireApproval": "never",
"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-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,
"@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
}
}
8 changes: 8 additions & 0 deletions deployment/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'
}
};
Loading

0 comments on commit f96f4f6

Please sign in to comment.