Skip to content

Commit c9a14f0

Browse files
authored
Merge pull request #192 from NeotomaDB/develop
Develop
2 parents e19d86b + e553fbc commit c9a14f0

File tree

46 files changed

+6260
-5631
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

46 files changed

+6260
-5631
lines changed

.github/workflows/deploy.yml

Lines changed: 89 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,89 @@
1+
name: Deploy Neotoma API
2+
3+
on:
4+
push:
5+
branches: [main, deveop]
6+
7+
env:
8+
AWS_REGION: us-east-2
9+
10+
jobs:
11+
deploy:
12+
runs-on: ubuntu-latest
13+
14+
steps:
15+
- name: Checkout code
16+
uses: actions/checkout@v4
17+
18+
- name: Set environment based on branch
19+
run: |
20+
if [[ ${{ github.ref }} == 'refs/heads/main' ]]; then
21+
echo "ENVIRONMENT=prod" >> $GITHUB_ENV
22+
echo "STACK_NAME=neotoma-api-prod" >> $GITHUB_ENV
23+
else
24+
echo "ENVIRONMENT=dev" >> $GITHUB_ENV
25+
echo "STACK_NAME=neotoma-api-dev" >> $GITHUB_ENV
26+
fi
27+
28+
- name: Configure AWS credentials
29+
uses: aws-actions/configure-aws-credentials@v4
30+
with:
31+
aws-access-key-id: ${{ secrets.AWS_ACCESS_KEY_ID }}
32+
aws-secret-access-key: ${{ secrets.AWS_SECRET_ACCESS_KEY }}
33+
aws-region: ${{ env.AWS_REGION }}
34+
35+
- name: Login to Amazon ECR
36+
id: login-ecr
37+
uses: aws-actions/amazon-ecr-login@v2
38+
39+
- name: Deploy CloudFormation stack
40+
run: |
41+
aws cloudformation deploy \
42+
--template-file infrastructure/cloudformation-template.yaml \
43+
--stack-name ${{ env.STACK_NAME }} \
44+
--parameter-overrides \
45+
Environment=${{ env.ENVIRONMENT }} \
46+
ImageUri="placeholder" \
47+
RDSHostname=${{ secrets.RDS_HOSTNAME }} \
48+
RDSDatabase=${{ secrets.RDS_DATABASE }} \
49+
VPCId=${{ secrets.VPC_ID }} \
50+
PrivateSubnets=${{ secrets.PRIVATE_SUBNETS }} \
51+
--capabilities CAPABILITY_NAMED_IAM \
52+
--region ${{ env.AWS_REGION }}
53+
54+
- name: Get ECR repository URI
55+
run: |
56+
ECR_URI=$(aws cloudformation describe-stacks \
57+
--stack-name ${{ env.STACK_NAME }} \
58+
--query 'Stacks[0].Outputs[?OutputKey==`ECRRepository`].OutputValue' \
59+
--output text \
60+
--region ${{ env.AWS_REGION }})
61+
echo "ECR_REPOSITORY=$ECR_URI" >> $GITHUB_ENV
62+
63+
- name: Build, tag, and push image to Amazon ECR
64+
run: |
65+
IMAGE_TAG=${{ github.sha }}
66+
docker build -t $ECR_REPOSITORY:$IMAGE_TAG .
67+
docker tag $ECR_REPOSITORY:$IMAGE_TAG $ECR_REPOSITORY:latest
68+
docker push $ECR_REPOSITORY:$IMAGE_TAG
69+
docker push $ECR_REPOSITORY:latest
70+
echo "IMAGE_URI=$ECR_REPOSITORY:$IMAGE_TAG" >> $GITHUB_ENV
71+
72+
- name: Update App Runner service with new image
73+
run: |
74+
aws cloudformation update-stack \
75+
--stack-name ${{ env.STACK_NAME }} \
76+
--use-previous-template \
77+
--parameters \
78+
ParameterKey=Environment,UsePreviousValue=true \
79+
ParameterKey=ImageUri,ParameterValue=${{ env.IMAGE_URI }} \
80+
ParameterKey=RDSHostname,UsePreviousValue=true \
81+
ParameterKey=RDSDatabase,UsePreviousValue=true \
82+
ParameterKey=VPCId,UsePreviousValue=true \
83+
ParameterKey=PrivateSubnets,UsePreviousValue=true \
84+
--capabilities CAPABILITY_NAMED_IAM \
85+
--region ${{ env.AWS_REGION }}
86+
87+
aws cloudformation wait stack-update-complete \
88+
--stack-name ${{ env.STACK_NAME }} \
89+
--region ${{ env.AWS_REGION }}
File renamed without changes.

cloudformation-template.yml

Lines changed: 172 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,172 @@
1+
AWSTemplateFormatVersion: '2010-09-09'
2+
Description: 'Neotoma API infrastructure'
3+
4+
Parameters:
5+
Environment:
6+
Type: String
7+
AllowedValues: [dev, prod]
8+
Description: Environment name
9+
10+
ImageUri:
11+
Type: String
12+
Description: ECR image URI
13+
14+
RDSHostname:
15+
Type: String
16+
Description: RDS endpoint
17+
18+
RDSPort:
19+
Type: String
20+
Default: '5432'
21+
22+
RDSDatabase:
23+
Type: String
24+
Description: Database name
25+
26+
VPCId:
27+
Type: AWS::EC2::VPC::Id
28+
Description: VPC ID where resources will be created
29+
30+
PrivateSubnets:
31+
Type: List<AWS::EC2::Subnet::Id>
32+
Description: Private subnets for VPC connector
33+
34+
Resources:
35+
# ECR Repository
36+
ECRRepository:
37+
Type: AWS::ECR::Repository
38+
Properties:
39+
RepositoryName: !Sub 'neotoma-api-${Environment}'
40+
ImageScanningConfiguration:
41+
ScanOnPush: true
42+
LifecyclePolicy:
43+
LifecyclePolicyText: |
44+
{
45+
"rules": [
46+
{
47+
"rulePriority": 1,
48+
"selection": {
49+
"tagStatus": "untagged",
50+
"countType": "sinceImagePushed",
51+
"countUnit": "days",
52+
"countNumber": 1
53+
},
54+
"action": {
55+
"type": "expire"
56+
}
57+
}
58+
]
59+
}
60+
61+
# Secrets for database credentials
62+
DatabaseSecret:
63+
Type: AWS::SecretsManager::Secret
64+
Properties:
65+
Name: !Sub 'neotoma-api/${Environment}/rds-credentials'
66+
Description: RDS credentials for Neotoma API
67+
GenerateSecretString:
68+
SecretStringTemplate: '{"username": "your-username"}'
69+
GenerateStringKey: 'password'
70+
PasswordLength: 32
71+
ExcludeCharacters: '"@/\'
72+
73+
# Security Group for App Runner
74+
AppRunnerSecurityGroup:
75+
Type: AWS::EC2::SecurityGroup
76+
Properties:
77+
GroupName: !Sub 'apprunner-neotoma-${Environment}-sg'
78+
GroupDescription: Security group for Neotoma App Runner service
79+
VpcId: !Ref VPCId
80+
SecurityGroupEgress:
81+
- IpProtocol: tcp
82+
FromPort: 5432
83+
ToPort: 5432
84+
CidrIp: 10.0.0.0/8
85+
- IpProtocol: tcp
86+
FromPort: 443
87+
ToPort: 443
88+
CidrIp: 0.0.0.0/0
89+
90+
# VPC Connector for App Runner
91+
VPCConnector:
92+
Type: AWS::AppRunner::VpcConnector
93+
Properties:
94+
VpcConnectorName: !Sub 'neotoma-vpc-connector-${Environment}'
95+
Subnets: !Ref PrivateSubnets
96+
SecurityGroups:
97+
- !Ref AppRunnerSecurityGroup
98+
99+
# App Runner Service
100+
AppRunnerService:
101+
Type: AWS::AppRunner::Service
102+
Properties:
103+
ServiceName: !Sub 'neotoma-api-${Environment}'
104+
SourceConfiguration:
105+
ImageRepository:
106+
ImageIdentifier: !Ref ImageUri
107+
ImageConfiguration:
108+
Port: '3001'
109+
RuntimeEnvironmentVariables:
110+
NODE_ENV: !Ref Environment
111+
RDS_HOSTNAME: !Ref RDSHostname
112+
RDS_PORT: !Ref RDSPort
113+
RDS_DATABASE: !Ref RDSDatabase
114+
DB_SSL: 'true'
115+
PORT: '3001'
116+
RuntimeEnvironmentSecrets:
117+
RDS_USERNAME: !Sub '${DatabaseSecret}:username::'
118+
RDS_PASSWORD: !Sub '${DatabaseSecret}:password::'
119+
ImageRepositoryType: ECR
120+
AutoDeploymentsEnabled: true
121+
InstanceConfiguration:
122+
Cpu: 0.25 vCPU
123+
Memory: 0.5 GB
124+
InstanceRoleArn: !GetAtt AppRunnerInstanceRole.Arn
125+
NetworkConfiguration:
126+
EgressConfiguration:
127+
EgressType: VPC
128+
VpcConnectorArn: !GetAtt VPCConnector.VpcConnectorArn
129+
HealthCheckConfiguration:
130+
Protocol: HTTP
131+
Path: /v2.0/routes/healthwatch
132+
Interval: 20
133+
Timeout: 5
134+
HealthyThreshold: 1
135+
UnhealthyThreshold: 5
136+
137+
# IAM Role for App Runner Instance
138+
AppRunnerInstanceRole:
139+
Type: AWS::IAM::Role
140+
Properties:
141+
RoleName: !Sub 'AppRunnerInstanceRole-${Environment}'
142+
AssumeRolePolicyDocument:
143+
Version: '2012-10-17'
144+
Statement:
145+
- Effect: Allow
146+
Principal:
147+
Service: tasks.apprunner.amazonaws.com
148+
Action: sts:AssumeRole
149+
ManagedPolicyArns:
150+
- arn:aws:iam::aws:policy/service-role/AWSAppRunnerServicePolicyForECRAccess
151+
Policies:
152+
- PolicyName: SecretsManagerAccess
153+
PolicyDocument:
154+
Version: '2012-10-17'
155+
Statement:
156+
- Effect: Allow
157+
Action:
158+
- secretsmanager:GetSecretValue
159+
Resource: !Ref DatabaseSecret
160+
161+
Outputs:
162+
ServiceUrl:
163+
Description: App Runner service URL
164+
Value: !Sub 'https://${AppRunnerService.ServiceUrl}'
165+
Export:
166+
Name: !Sub '${AWS::StackName}-ServiceUrl'
167+
168+
ECRRepository:
169+
Description: ECR Repository URI
170+
Value: !Sub '${AWS::AccountId}.dkr.ecr.${AWS::Region}.amazonaws.com/${ECRRepository}'
171+
Export:
172+
Name: !Sub '${AWS::StackName}-ECRRepository'

0 commit comments

Comments
 (0)