Skip to content

Commit

Permalink
Merge pull request #550 from canopas/hosting-service-side-rendering-o…
Browse files Browse the repository at this point in the history
…f-resources

Hosting: Server side rendering on AWS lambda
  • Loading branch information
cp-sumi-k authored Feb 16, 2024
2 parents 820ea18 + 60ab152 commit 66a5276
Show file tree
Hide file tree
Showing 33 changed files with 874 additions and 699 deletions.
28 changes: 22 additions & 6 deletions .github/workflows/deploy-frontend-dev.yml
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
name: DeployFrontendDev
name: DeployFrontendServerlessDev

on:
workflow_run:
Expand Down Expand Up @@ -28,13 +28,29 @@ jobs:
role-to-assume: arn:aws:iam::${{ secrets.AWS_ACCOUNT_ID }}:role/github-actions-frontend-access
aws-region: ap-south-1

- name: Build frontend and copy to S3
- name: Build frontend and copy zip to S3
run: |
cd nuxt-frontend
sed -i "s|VITE_RECAPTCHA_SITE_KEY_VALUE|${{ secrets.RECAPTCHA_SITE_KEY }}|g" config.js
sed -i "s|RESOURCES_URL|${{ secrets.RESOURCES_URL }}|g" config.js
sed -i "s|CLOUDFRONT_URL_VALUE|${{ secrets.CLOUDFRONT_URL_VALUE_DEV }}|g" config.js
sh ./../deploy/generate-sitemap.sh https://dev-stack.canopas.com https://dev-stack-api.canopas.com
yarn install --frozen-lockfile && yarn generate
aws s3 sync ./.output/public s3://dev-stack.canopas.com --exclude "*.js"
aws s3 sync ./.output/public s3://dev-stack.canopas.com --include "*.js" --content-type "application/javascript"
aws cloudfront create-invalidation --distribution-id ${{ secrets.DEV_CLOUDFRONT_DISTRIBUTION_ID }} --paths "/*"
yarn install --frozen-lockfile && yarn build
aws s3 rm s3://canopas-website-ssr-dev --recursive
cd .output/server && zip canopas_website_SSR_dev_${{ github.sha }}-${{ github.run_attempt }}.zip -r . && aws s3 cp canopas_website_SSR_dev_${{ github.sha }}-${{ github.run_attempt }}.zip s3://canopas-lambda-handlers && cd ../..
aws s3 sync --cache-control 'max-age=604800' --exclude *.html ./.output/public s3://canopas-website-ssr-dev
aws s3 sync ./.output/public s3://canopas-website-ssr-dev
- name: Deploy cloudformation stack
id: canopas-website-dev-lambda-stack-frontend
uses: aws-actions/aws-cloudformation-github-deploy@v1
with:
name: canopas-website-dev-lambda-stack-frontend
template: infrastructure/frontend.yml
capabilities: CAPABILITY_IAM,CAPABILITY_NAMED_IAM, CAPABILITY_AUTO_EXPAND
timeout-in-minutes: "10"
no-fail-on-empty-changeset: "1"
parameter-overrides: >-
EnvName=dev,
ZipFileName=canopas_website_SSR_dev_${{ github.sha }}-${{ github.run_attempt }}.zip,
CloudfrontURL=${{ secrets.CLOUDFRONT_URL_VALUE_DEV }}
28 changes: 22 additions & 6 deletions .github/workflows/deploy-frontend-prod.yml
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
name: DeployFrontendProd
name: DeployFrontendServerlessProd

on:
workflow_run:
Expand Down Expand Up @@ -28,14 +28,30 @@ jobs:
role-to-assume: arn:aws:iam::${{ secrets.AWS_ACCOUNT_ID }}:role/github-actions-frontend-access
aws-region: ap-south-1

- name: Build frontend and copy to S3
- name: Build frontend and copy zip to S3
run: |
cd nuxt-frontend
sed -i "s|VITE_RECAPTCHA_SITE_KEY_VALUE|${{ secrets.RECAPTCHA_SITE_KEY }}|g" config.prod.js
sed -i "s|RESOURCES_URL|${{ secrets.RESOURCES_URL }}|g" config.prod.js
sed -i "s|CLOUDFRONT_URL_VALUE|${{ secrets.CLOUDFRONT_URL_VALUE_PROD }}|g" config.prod.js
mv config.prod.js config.js
sh ./../deploy/generate-sitemap.sh https://canopas.com https://prod-stack-api.canopas.com
yarn install --frozen-lockfile && yarn generate
aws s3 sync ./.output/public s3://canopas.com --exclude "*.js"
aws s3 sync ./.output/public s3://canopas.com --include "*.js" --content-type "application/javascript"
aws cloudfront create-invalidation --distribution-id ${{ secrets.PROD_CLOUDFRONT_DISTRIBUTION_ID }} --paths "/*"
yarn install --frozen-lockfile && yarn build
aws s3 rm s3://canopas-website-ssr-prod --recursive
cd .output/server && zip canopas_website_SSR_prod_${{ github.sha }}-${{ github.run_attempt }}.zip -r . && aws s3 cp canopas_website_SSR_prod_${{ github.sha }}-${{ github.run_attempt }}.zip s3://canopas-lambda-handlers && cd ../..
aws s3 sync --cache-control 'max-age=604800' --exclude *.html ./.output/public s3://canopas-website-ssr-prod
aws s3 sync ./.output/public s3://canopas-website-ssr-prod
- name: Deploy cloudformation stack
id: canopas-website-prod-lambda-stack-frontend
uses: aws-actions/aws-cloudformation-github-deploy@v1
with:
name: canopas-website-prod-lambda-stack-frontend
template: infrastructure/frontend.yml
capabilities: CAPABILITY_IAM,CAPABILITY_NAMED_IAM, CAPABILITY_AUTO_EXPAND
timeout-in-minutes: "10"
no-fail-on-empty-changeset: "1"
parameter-overrides: >-
EnvName=prod,
ZipFileName=canopas_website_SSR_prod_${{ github.sha }}-${{ github.run_attempt }}.zip,
CloudfrontURL=${{ secrets.CLOUDFRONT_URL_VALUE_PROD }}
167 changes: 98 additions & 69 deletions infrastructure/frontend.yml
Original file line number Diff line number Diff line change
@@ -1,82 +1,111 @@
AWSTemplateFormatVersion: 2010-09-09
Description: An ECS with launchType EC2 frontend stack
AWSTemplateFormatVersion: "2010-09-09"
Transform:
- AWS::LanguageExtensions
- AWS::Serverless-2016-10-31

Description: Canopas website serverless deployment with SSR.

Parameters:
EnvName:
Type: String
Description: Name of an environment. 'dev', 'staging', 'prod' and any name.
Description: Name of an environment.
AllowedPattern: ^.*[^0-9]$
ConstraintDescription: Must end with non-numeric character.
ClusterName:
Type: String
Description: Name of ECS cluster
ImageTag:
Type: String
Description: Website Docker frontend image tag
NginxImageTag:
AllowedValues:
- dev
- prod
ZipFileName:
Type: String
Description: NGINX Docker image tag
BlogImageTag:
Description: Name of the zip file.
CloudfrontURL:
Type: String
Description: Blog Docker image tag
Description: Cloudfront URL.

Resources:
TaskDefinition:
Type: AWS::ECS::TaskDefinition
HttpApi:
Type: AWS::Serverless::HttpApi
Properties:
Family:
Fn::Sub: canopas-website-${EnvName}-full-stack-task-definition
ExecutionRoleArn:
Fn::Sub: arn:aws:iam::${AWS::AccountId}:role/ecsTaskExecutionRole
NetworkMode: "bridge"
ContainerDefinitions:
- Name: "canopas-website-nginx"
Hostname: "canopas-website-nginx"
Memory: 128
Cpu: 128
Essential: true
Image:
Fn::Sub: ${AWS::AccountId}.dkr.ecr.${AWS::Region}.amazonaws.com/canopas-website-nginx:${NginxImageTag}
PortMappings:
- ContainerPort: 80
HostPort: 80
Protocol: tcp
Links:
- canopas-website-frontend
- canopas-blog

- Name: "canopas-website-frontend"
Memory: 256
Cpu: 256
Essential: true
Image:
Fn::Sub: ${AWS::AccountId}.dkr.ecr.${AWS::Region}.amazonaws.com/canopas-website-frontend:${ImageTag}
PortMappings:
- ContainerPort: 3080
HostPort: 3080
Protocol: tcp

- Name: "canopas-blog"
Memory: 256
Cpu: 256
Essential: true
Image:
Fn::Sub: ${AWS::AccountId}.dkr.ecr.${AWS::Region}.amazonaws.com/canopas-blog:${BlogImageTag}
PortMappings:
- ContainerPort: 3000
HostPort: 3000
Protocol: tcp
StageName: $default
Description:
Fn::Sub: Canopas Website SSR Frontend API ${EnvName}
DefinitionBody:
openapi: "3.0.1"
info:
title:
Fn::Sub: canopas-website-ssr-frontend-${EnvName}
version: "1.0"
paths:
/favicon.ico:
x-amazon-apigateway-any-method:
responses:
default:
description: "Default response for ANY /favicon.ico"
x-amazon-apigateway-integration:
payloadFormatVersion: "1.0"
type: "http_proxy"
httpMethod: "ANY"
uri:
Fn::Sub: "${CloudfrontURL}favicon.ico"
connectionType: "INTERNET"
/sitemap.xml:
x-amazon-apigateway-any-method:
responses:
default:
description: "Default response for ANY /sitemap.xml"
x-amazon-apigateway-integration:
payloadFormatVersion: "1.0"
type: "http_proxy"
httpMethod: "ANY"
uri:
Fn::Sub: "${CloudfrontURL}sitemap.xml"
connectionType: "INTERNET"
/robots.txt:
x-amazon-apigateway-any-method:
responses:
default:
description: "Default response for ANY /robots.txt"
x-amazon-apigateway-integration:
payloadFormatVersion: "1.0"
type: "http_proxy"
httpMethod: "ANY"
uri:
Fn::Sub: "${CloudfrontURL}robots.txt"
connectionType: "INTERNET"
/apple-touch-icon.png:
x-amazon-apigateway-any-method:
responses:
default:
description: "Default response for ANY /apple-touch-icon.png"
x-amazon-apigateway-integration:
payloadFormatVersion: "1.0"
type: "http_proxy"
httpMethod: "ANY"
uri:
Fn::Sub: "${CloudfrontURL}apple-touch-icon.png"
connectionType: "INTERNET"
x-amazon-apigateway-importexport-version: "1.0"

ECSService:
Type: AWS::ECS::Service
HttpApiFunction:
Type: AWS::Serverless::Function
Properties:
ServiceName: "canopas-website-full-stack"
LaunchType: EC2
Cluster:
Fn::Sub: ${ClusterName}
DesiredCount: 1
TaskDefinition:
Ref: "TaskDefinition"
DeploymentConfiguration:
MaximumPercent: 100
MinimumHealthyPercent: 0
PackageType: Zip
CodeUri:
Fn::Sub: s3://canopas-lambda-handlers/${ZipFileName}
Handler: index.handler
Runtime: nodejs20.x
Architectures:
- x86_64
MemorySize: 256
Timeout: 30
FunctionName:
Fn::Sub: canopas-website-ssr-frontend-${EnvName}
Description:
Fn::Sub: Canopas Website SSR Frontend Lambda ${EnvName}
Events:
ProxyResource:
Type: HttpApi
Properties:
ApiId:
Ref: HttpApi
Path: $default
Method: any
Loading

0 comments on commit 66a5276

Please sign in to comment.