Skip to content

Commit 1ede83f

Browse files
committed
Merge branch 'develop' into production
Changes include a fix to the rate limiting, updated test results, and a change to the deploy/infrastructure to get it tied more closely to the AppRunner/Route 53 toolchain.
2 parents b4cea6b + 0a34066 commit 1ede83f

40 files changed

+4239
-4180
lines changed

.github/workflows/deploy.yml

Lines changed: 78 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@ env:
1010
jobs:
1111
deploy:
1212
runs-on: ubuntu-latest
13+
timeout-minutes: 30
1314

1415
steps:
1516
- name: Checkout code
@@ -21,10 +22,12 @@ jobs:
2122
echo "ENVIRONMENT=prod" >> $GITHUB_ENV
2223
echo "STACK_NAME=neoapi-prod" >> $GITHUB_ENV
2324
echo "RDSDB=neotoma" >> $GITHUB_ENV
25+
echo "ENDPOINT=api.neotomadb.org" >> $GITHUB_ENV
2426
else
2527
echo "ENVIRONMENT=dev" >> $GITHUB_ENV
2628
echo "STACK_NAME=neoapi-dev" >> $GITHUB_ENV
2729
echo "RDSDB=neotomatank" >> $GITHUB_ENV
30+
echo "ENDPOINT=api-dev.neotomadb.org" >> $GITHUB_ENV
2831
fi
2932
3033
- name: Configure AWS credentials
@@ -40,12 +43,14 @@ jobs:
4043

4144
- name: Create ECR repository if it doesn't exist
4245
run: |
43-
aws ecr describe-repositories --repository-names neoapi-${{ env.ENVIRONMENT }} --region ${{ env.AWS_REGION }} 2>/dev/null || \
46+
aws ecr describe-repositories \
47+
--repository-names neoapi-${{ env.ENVIRONMENT }} \
48+
--region ${{ env.AWS_REGION }} 2>/dev/null || \
4449
aws ecr create-repository \
4550
--repository-name neoapi-${{ env.ENVIRONMENT }} \
4651
--region ${{ env.AWS_REGION }} \
47-
--image-scanning-configuration scanOnPush=true
48-
52+
--image-scanning-configuration scanOnPush=true \
53+
--encryption-configuration encryptionType=AES256
4954
- name: Build, tag, and push image to Amazon ECR
5055
run: |
5156
ECR_REPOSITORY=${{ steps.login-ecr.outputs.registry }}/neoapi-${{ env.ENVIRONMENT }}
@@ -62,6 +67,17 @@ jobs:
6267
echo "IMAGE_URI=$ECR_REPOSITORY:$IMAGE_TAG" >> $GITHUB_ENV
6368
echo "ECR_REPOSITORY=$ECR_REPOSITORY" >> $GITHUB_ENV
6469
70+
- name: Debug parameters
71+
run: |
72+
echo "Subnets value: '${{ secrets.PRIVATE_SUBNETS }}'"
73+
echo "Length: ${#PRIVATE_SUBNETS}"
74+
PRIVATE_SUBNETS="${{ secrets.PRIVATE_SUBNETS }}"
75+
if [ -z "$PRIVATE_SUBNETS" ]; then
76+
echo "ERROR: PRIVATE_SUBNETS is empty!"
77+
exit 1
78+
fi
79+
echo "SUBNET_LIST=subnet-0e66614ca7e9e7247,subnet-013f8ff069404c987" >> $GITHUB_ENV
80+
6581
- name: Deploy CloudFormation stack
6682
run: |
6783
echo "Deploying infrastructure with image: ${{ env.IMAGE_URI }}"
@@ -70,23 +86,18 @@ jobs:
7086
--template-file infrastructure/cloudformation-template.yaml \
7187
--stack-name ${{ env.STACK_NAME }} \
7288
--parameter-overrides \
73-
Environment=${{ env.ENVIRONMENT }} \
74-
ImageUri=${{ env.IMAGE_URI }} \
75-
RDSHostname=${{ secrets.RDS_HOSTNAME }} \
76-
RDSDatabase=${{ env.RDSDB }} \
77-
RDSUsername=${{ secrets.RDS_USERNAME }} \
78-
RDSPassword=${{ secrets.RDS_PASSWORD }} \
79-
VPCId=${{ secrets.VPC_ID }} \
80-
PrivateSubnets=${{ secrets.PRIVATE_SUBNETS }} \
89+
"Environment=${{ env.ENVIRONMENT }}" \
90+
"ImageUri=${{ env.IMAGE_URI }}" \
91+
"RDSHostname=${{ secrets.RDS_HOSTNAME }}" \
92+
"RDSDatabase=${{ env.RDSDB }}" \
93+
"RDSUsername=${{ secrets.RDS_USERNAME }}" \
94+
"RDSPassword=${{ secrets.RDS_PASSWORD }}" \
95+
"VPCId=${{ secrets.VPC_ID }}" \
96+
"PrivateSubnets=${{ env.SUBNET_LIST }}" \
97+
"DomainName=${{ env.ENDPOINT }}" \
8198
--capabilities CAPABILITY_NAMED_IAM \
82-
--region ${{ env.AWS_REGION }}
83-
84-
- name: Wait for deployment to complete
85-
run: |
86-
echo "Waiting for CloudFormation stack to complete..."
87-
aws cloudformation wait stack-create-complete \
88-
--stack-name ${{ env.STACK_NAME }} \
89-
--region ${{ env.AWS_REGION }}
99+
--region ${{ env.AWS_REGION }} \
100+
--no-fail-on-empty-changeset
90101
91102
- name: Get ECR repository URI
92103
run: |
@@ -105,28 +116,63 @@ jobs:
105116
--output text \
106117
--region ${{ env.AWS_REGION }})
107118
119+
echo "SERVICE_URL=$SERVICE_URL" >> $GITHUB_ENV
120+
echo "service_url=$SERVICE_URL" >> $GITHUB_OUTPUT
121+
108122
echo "🚀 Deployment complete!"
109123
echo "Service URL: $SERVICE_URL"
110124
echo "Environment: ${{ env.ENVIRONMENT }}"
111125
echo "Image: ${{ env.IMAGE_URI }}"
112126
113127
- name: Health check
114128
run: |
115-
SERVICE_URL=$(aws cloudformation describe-stacks \
116-
--stack-name ${{ env.STACK_NAME }} \
117-
--query 'Stacks[0].Outputs[?OutputKey==`ServiceUrl`].OutputValue' \
118-
--output text \
119-
--region ${{ env.AWS_REGION }})
120-
121-
echo "Performing health check..."
122-
sleep 30 # Give the service time to start
123-
124-
for i in {1..5}; do
125-
if curl -f -s "${SERVICE_URL}/v2.0/routes/healthwatch" > /dev/null; then
126-
echo "✅ Health check passed!"
129+
SERVICE_URL="${{ env.SERVICE_URL }}"
130+
HEALTH_ENDPOINT="${SERVICE_URL}/healthcheck"
131+
132+
echo "Performing health check on: $HEALTH_ENDPOINT"
133+
echo "Waiting 60 seconds for App Runner to start..."
134+
sleep 60
135+
136+
MAX_ATTEMPTS=10
137+
ATTEMPT=1
138+
139+
while [ $ATTEMPT -le $MAX_ATTEMPTS ]; do
140+
echo "Health check attempt $ATTEMPT/$MAX_ATTEMPTS..."
141+
142+
HTTP_CODE=$(curl -s -o /dev/null -w "%{http_code}" "$HEALTH_ENDPOINT" || echo "000")
143+
144+
if [ "$HTTP_CODE" = "200" ]; then
145+
echo "✅ Health check passed! (HTTP $HTTP_CODE)"
127146
exit 0
128147
else
129-
echo "⏳ Health check attempt $i/5 failed, retrying in 30 seconds..."
148+
echo "⏳ Health check failed with HTTP code: $HTTP_CODE"
149+
150+
if [ $ATTEMPT -eq $MAX_ATTEMPTS ]; then
151+
echo "❌ Health check failed after $MAX_ATTEMPTS attempts"
152+
exit 1
153+
fi
154+
155+
echo "Retrying in 30 seconds..."
130156
sleep 30
131157
fi
158+
159+
ATTEMPT=$((ATTEMPT + 1))
132160
done
161+
162+
- name: Notify deployment status
163+
if: always()
164+
run: |
165+
if [ "${{ job.status }}" = "success" ]; then
166+
echo "✅ Deployment successful for ${{ env.ENVIRONMENT }}"
167+
echo "URL: ${{ env.SERVICE_URL }}"
168+
else
169+
echo "❌ Deployment failed for ${{ env.ENVIRONMENT }}"
170+
fi
171+
172+
- name: Rollback on failure
173+
if: failure()
174+
run: |
175+
echo "Deployment failed, initiating rollback..."
176+
aws cloudformation cancel-update-stack \
177+
--stack-name ${{ env.STACK_NAME }} \
178+
--region ${{ env.AWS_REGION }} || true

app.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,7 @@ const onlyStatus200 = (req, res) => res.statusCode === 200;
2323
const cacheSuccesses = cache('5 minutes', onlyStatus200);
2424

2525
const limiter = rateLimiter({
26-
max: 50,
26+
max: 5000,
2727
windowMS: 10000, // 1 second
2828
message: 'You can\'t make any more requests at the moment. Try again later',
2929
statusCode: 429,

infrastructure/cloudformation-template.yaml

Lines changed: 17 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,16 @@ Parameters:
77
AllowedValues: [dev, prod]
88
Description: Environment name
99

10+
HostedZoneId:
11+
Type: String
12+
Description: Route 53 Hosted Zone ID
13+
Default: "Z06678132YXCZ3LP39MIP"
14+
15+
DomainName:
16+
Type: String
17+
Description: Domain name for the API
18+
Default: "api-dev.neotoma.org"
19+
1020
ImageUri:
1121
Type: String
1222
Description: ECR image URI
@@ -138,12 +148,12 @@ Resources:
138148
VpcConnectorArn: !GetAtt VPCConnector.VpcConnectorArn
139149
HealthCheckConfiguration:
140150
Protocol: HTTP
141-
Path: /v2.0/routes/healthwatch
151+
Path: /healthcheck
142152
Interval: 20
143153
Timeout: 5
144154
HealthyThreshold: 1
145155
UnhealthyThreshold: 5
146-
156+
147157
Outputs:
148158
ServiceUrl:
149159
Description: App Runner service URL
@@ -156,4 +166,8 @@ Outputs:
156166
Description: ECR Repository URI
157167
Value: !Sub '${AWS::AccountId}.dkr.ecr.${AWS::Region}.amazonaws.com/neoapi-${Environment}'
158168
Export:
159-
Name: !Sub '${AWS::StackName}-ECRRepository'
169+
Name: !Sub '${AWS::StackName}-ECRRepository'
170+
171+
CustomDomainURL:
172+
Description: Custom domain URL
173+
Value: !Sub 'https://${DomainName}'

public/assets/app.css

Lines changed: 1 addition & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

public/assets/app.js

Lines changed: 2 additions & 2 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

0 commit comments

Comments
 (0)