-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
* WIP: Add files for aws deployment option * Add deploy to aws script * Add deploy to AWS workflow * Update workflow file
- Loading branch information
1 parent
465899d
commit aab53c2
Showing
7 changed files
with
289 additions
and
2 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
24 changes: 24 additions & 0 deletions
24
{{cookiecutter.project_slug}}/.github/workflows/deploy_to_aws.yml
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,24 @@ | ||
{% raw %} | ||
name: Deploy to AWS Elastic Beanstalk | ||
|
||
on: | ||
push: | ||
branches: | ||
- main | ||
workflow_dispatch: | ||
|
||
env: | ||
AWS_ACCESS_KEY_ID: ${{ secrets.AWS_ACCESS_KEY_ID }} | ||
AWS_SECRET_ACCESS_KEY: ${{ secrets.AWS_SECRET_ACCESS_KEY }} | ||
AWS_REGION: ${{ secrets.AWS_REGION }} | ||
AWS_DEFAULT_REGION: ${{ secrets.AWS_REGION }} | ||
OPENAI_API_KEY: ${{ secrets.OPENAI_API_KEY }} | ||
|
||
jobs: | ||
deploy: | ||
runs-on: ubuntu-latest | ||
steps: | ||
- uses: actions/checkout@v4 | ||
# AWS CLI is pre-installed on GitHub Actions | ||
- name: Deploy to Azure containerapps | ||
run: ./scripts/deploy_to_ebs.sh{% endraw %} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,253 @@ | ||
#!/bin/bash | ||
# Script to deploy to AWS Elastic Beanstalk | ||
# Prerequisites: | ||
# - AWS CLI installed and configured | ||
# - Docker installed | ||
# - EB CLI installed | ||
|
||
# Variables | ||
export APPLICATION_NAME="{{ cookiecutter.project_slug.replace("_", "-") }}" | ||
export ENVIRONMENT_NAME="{{ cookiecutter.project_slug.replace("_", "-") }}-env" | ||
export AWS_REGION=${AWS_REGION:-"eu-central-1"} | ||
export ECR_REPOSITORY="{{ cookiecutter.project_slug.replace("_", "-") }}" | ||
export BUCKET_NAME="{{ cookiecutter.project_slug.replace("_", "-") }}" | ||
export INSTANCE_PROFILE_NAME="aws-elasticbeanstalk-ec2-role" | ||
export ROLE_NAME="aws-elasticbeanstalk-ec2-role" | ||
|
||
|
||
# Color codes for echo | ||
GREEN="\033[0;32m" | ||
YELLOW="\033[1;33m" | ||
RED="\033[0;31m" | ||
RESET="\033[0m" | ||
|
||
# Function for colored echo | ||
colored_echo() { | ||
echo -e "${GREEN}$1${RESET}" | ||
} | ||
|
||
# Function for yellow warning echo | ||
warning_echo() { | ||
echo -e "${YELLOW}$1${RESET}" | ||
} | ||
|
||
# Function for error echo | ||
error_echo() { | ||
echo -e "${RED}$1${RESET}" | ||
} | ||
|
||
|
||
# Check AWS CLI configuration | ||
echo -e "\033[0;32mChecking if AWS CLI is configured\033[0m" | ||
if ! aws sts get-caller-identity > /dev/null 2>&1; then | ||
echo -e "\033[0;32mAWS CLI is not configured. Please run 'aws configure' first.\033[0m" | ||
exit 1 | ||
else | ||
echo -e "\033[0;32mAWS CLI is configured.\033[0m" | ||
fi | ||
|
||
AWS_ACCOUNT_ID=$(aws sts get-caller-identity --query "Account" --output text) | ||
|
||
if ! aws iam get-role --role-name $ROLE_NAME --region $AWS_REGION > /dev/null 2>&1; then | ||
colored_echo "Creating IAM role for Elastic Beanstalk EC2 instances" | ||
aws iam create-role \ | ||
--region $AWS_REGION \ | ||
--role-name $ROLE_NAME \ | ||
--assume-role-policy-document '{ | ||
"Version": "2012-10-17", | ||
"Statement": [ | ||
{ | ||
"Effect": "Allow", | ||
"Principal": { | ||
"Service": "ec2.amazonaws.com" | ||
}, | ||
"Action": "sts:AssumeRole" | ||
} | ||
] | ||
}' | ||
fi | ||
|
||
# Policies to attach | ||
POLICIES=( | ||
"arn:aws:iam::aws:policy/AWSElasticBeanstalkWebTier" | ||
"arn:aws:iam::aws:policy/AWSElasticBeanstalkWorkerTier" | ||
"arn:aws:iam::aws:policy/AWSElasticBeanstalkMulticontainerDocker" | ||
"arn:aws:iam::aws:policy/AmazonECS_FullAccess" | ||
"arn:aws:iam::aws:policy/service-role/AmazonEC2ContainerServiceforEC2Role" | ||
) | ||
|
||
# Attach policies | ||
for POLICY_ARN in "${POLICIES[@]}"; do | ||
if ! aws iam list-attached-role-policies --role-name $ROLE_NAME --region $AWS_REGION | grep -q $(basename "$POLICY_ARN"); then | ||
colored_echo "Attaching policy: $(basename "$POLICY_ARN")" | ||
aws iam attach-role-policy \ | ||
--region $AWS_REGION \ | ||
--role-name $ROLE_NAME \ | ||
--policy-arn "$POLICY_ARN" | ||
fi | ||
done | ||
|
||
# Create instance profile if it doesn't exist | ||
if ! aws iam get-instance-profile --instance-profile-name $INSTANCE_PROFILE_NAME --region $AWS_REGION > /dev/null 2>&1; then | ||
colored_echo "Creating instance profile" | ||
aws iam create-instance-profile \ | ||
--region $AWS_REGION \ | ||
--instance-profile-name $INSTANCE_PROFILE_NAME | ||
fi | ||
|
||
# Remove and re-add role to instance profile | ||
warning_echo "Ensuring role is correctly attached to instance profile" | ||
|
||
# Remove existing role if present | ||
CURRENT_ROLE=$(aws iam get-instance-profile --instance-profile-name $INSTANCE_PROFILE_NAME --region $AWS_REGION --query 'InstanceProfile.Roles[0].RoleName' --output text 2>/dev/null) | ||
if [ "$CURRENT_ROLE" != "None" ] && [ -n "$CURRENT_ROLE" ]; then | ||
aws iam remove-role-from-instance-profile \ | ||
--region $AWS_REGION \ | ||
--instance-profile-name $INSTANCE_PROFILE_NAME \ | ||
--role-name "$CURRENT_ROLE" | ||
fi | ||
|
||
# Add role to instance profile | ||
aws iam add-role-to-instance-profile \ | ||
--region $AWS_REGION \ | ||
--instance-profile-name $INSTANCE_PROFILE_NAME \ | ||
--role-name $ROLE_NAME | ||
|
||
# Verify role attachment | ||
ATTACHED_ROLE=$(aws iam get-instance-profile --instance-profile-name $INSTANCE_PROFILE_NAME --region $AWS_REGION --query 'InstanceProfile.Roles[0].RoleName' --output text) | ||
|
||
if [ "$ATTACHED_ROLE" == "$ROLE_NAME" ]; then | ||
colored_echo "✅ Instance profile successfully configured" | ||
else | ||
error_echo "❌ Failed to attach role to instance profile" | ||
exit 1 | ||
fi | ||
|
||
# Create ECR repository if it doesn't exist | ||
if ! aws ecr describe-repositories --repository-names $ECR_REPOSITORY --region $AWS_REGION > /dev/null 2>&1; then | ||
colored_echo "Creating ECR repository" | ||
aws ecr create-repository --repository-name $ECR_REPOSITORY --region $AWS_REGION | ||
fi | ||
|
||
# Login to AWS ECR | ||
colored_echo "Logging into Amazon ECR" | ||
rm ~/.docker/config.json | ||
aws ecr get-login-password --region $AWS_REGION | docker login --username AWS --password-stdin $(aws ecr describe-repositories --repository-names $ECR_REPOSITORY --query 'repositories[0].repositoryUri' --output text | sed 's/'"$ECR_REPOSITORY"'$//') | ||
|
||
# Build Docker image | ||
colored_echo "Building Docker image" | ||
docker build -t $ECR_REPOSITORY:latest -f docker/Dockerfile . | ||
|
||
# Tag and push Docker image to ECR | ||
colored_echo "Tagging and pushing Docker image to ECR" | ||
REPOSITORY_URI=$(aws ecr describe-repositories --repository-names $ECR_REPOSITORY --query 'repositories[0].repositoryUri' --output text --region $AWS_REGION) | ||
docker tag $ECR_REPOSITORY:latest $REPOSITORY_URI:latest | ||
docker push $REPOSITORY_URI:latest | ||
|
||
colored_echo $REPOSITORY_URI | ||
|
||
# Create Elastic Beanstalk application if it doesn't exist | ||
colored_echo "Creating/Updating Elastic Beanstalk Application" | ||
aws elasticbeanstalk create-application --application-name $APPLICATION_NAME --region $AWS_REGION || true | ||
|
||
# Check if the S3 bucket exists and create it if it doesn't | ||
if ! aws s3api head-bucket --bucket "$BUCKET_NAME" 2>/dev/null; then | ||
colored_echo "Creating S3 bucket: $BUCKET_NAME" | ||
aws s3api create-bucket \ | ||
--bucket "$BUCKET_NAME" \ | ||
--region "$AWS_REGION" \ | ||
--create-bucket-configuration LocationConstraint="$AWS_REGION" | ||
else | ||
colored_echo "S3 bucket $BUCKET_NAME already exists" | ||
fi | ||
|
||
# Prepare Dockerrun.aws.json for Elastic Beanstalk | ||
colored_echo "Creating Dockerrun.aws.json" | ||
cat > Dockerrun.aws.json << EOF | ||
{ | ||
"AWSEBDockerrunVersion": "1", | ||
"Image": { | ||
"Name": "$REPOSITORY_URI:latest", | ||
"Update": "true" | ||
}, | ||
"Ports": [ | ||
{ | ||
"ContainerPort": {% if cookiecutter.app_type == 'fastapi' %}"8008"{% else %}"8888"{% endif %}, | ||
"HostPort": "80" | ||
}, | ||
{ | ||
"ContainerPort": {% if cookiecutter.app_type == 'fastapi' %}"8008"{% else %}"8888"{% endif %}, | ||
"HostPort": "443" | ||
}{% if "nats" in cookiecutter.app_type %}, | ||
{ | ||
"ContainerPort": "8000", | ||
"HostPort": "8000" | ||
}{%- endif %}{% if "fastapi" in cookiecutter.app_type and cookiecutter.app_type != "fastapi" %}, | ||
{ | ||
"ContainerPort": "8008", | ||
"HostPort": "8008" | ||
}{%- endif %} | ||
], | ||
"Volumes": [] | ||
} | ||
EOF | ||
|
||
# Package Dockerrun.aws.json into a ZIP file | ||
PACKAGE_NAME="app-deployment.zip" | ||
colored_echo "Packaging Dockerrun.aws.json into $PACKAGE_NAME" | ||
zip -r $PACKAGE_NAME Dockerrun.aws.json | ||
|
||
# Upload the ZIP package to S3 | ||
colored_echo "Uploading $PACKAGE_NAME to S3 bucket $BUCKET_NAME" | ||
aws s3 cp $PACKAGE_NAME s3://$BUCKET_NAME/$PACKAGE_NAME | ||
|
||
rm Dockerrun.aws.json $PACKAGE_NAME | ||
|
||
# Create a new application version in Elastic Beanstalk | ||
VERSION_LABEL="v$(date +%Y%m%d%H%M%S)" | ||
colored_echo "Creating new application version: $VERSION_LABEL" | ||
aws elasticbeanstalk create-application-version \ | ||
--region "$AWS_REGION" \ | ||
--application-name "$APPLICATION_NAME" \ | ||
--version-label "$VERSION_LABEL" \ | ||
--source-bundle S3Bucket="$BUCKET_NAME",S3Key="$PACKAGE_NAME" | ||
|
||
# Create Elastic Beanstalk environment | ||
colored_echo "Creating/Updating Elastic Beanstalk Environment" | ||
aws elasticbeanstalk create-environment \ | ||
--region $AWS_REGION \ | ||
--application-name $APPLICATION_NAME \ | ||
--environment-name $ENVIRONMENT_NAME \ | ||
--solution-stack-name "64bit Amazon Linux 2023 v4.4.1 running Docker" \ | ||
--option-settings '[{"Namespace":"aws:autoscaling:asg","OptionName":"MinSize","Value":"1"},{"Namespace":"aws:autoscaling:asg","OptionName":"MaxSize","Value":"2"},{"Namespace":"aws:elasticbeanstalk:environment","OptionName":"EnvironmentType","Value":"LoadBalanced"},{"Namespace":"aws:autoscaling:launchconfiguration","OptionName":"IamInstanceProfile","Value":"'$INSTANCE_PROFILE_NAME'"}]' \ | ||
--version-label $VERSION_LABEL \ | ||
|| aws elasticbeanstalk update-environment \ | ||
--region $AWS_REGION \ | ||
--application-name $APPLICATION_NAME \ | ||
--environment-name $ENVIRONMENT_NAME \ | ||
--version-label $VERSION_LABEL | ||
|
||
# Wait for environment to be ready and get URL | ||
colored_echo "Waiting for environment to be ready" | ||
aws elasticbeanstalk wait environment-updated --application-name $APPLICATION_NAME --environment-name $ENVIRONMENT_NAME --region $AWS_REGION | ||
|
||
# Set environment variables | ||
colored_echo "Setting environment variables" | ||
aws elasticbeanstalk update-environment \ | ||
--region $AWS_REGION \ | ||
--application-name $APPLICATION_NAME \ | ||
--environment-name $ENVIRONMENT_NAME \ | ||
--option-settings Namespace=aws:elasticbeanstalk:application:environment,OptionName=OPENAI_API_KEY,Value=$OPENAI_API_KEY | ||
|
||
# Wait for environment to be ready and get URL | ||
colored_echo "Waiting for environment to be ready" | ||
aws elasticbeanstalk wait environment-updated --application-name $APPLICATION_NAME --environment-name $ENVIRONMENT_NAME --region $AWS_REGION | ||
|
||
# Fetch and display environment URL | ||
ENVIRONMENT_URL=$(aws elasticbeanstalk describe-environments \ | ||
--application-name $APPLICATION_NAME \ | ||
--environment-names $ENVIRONMENT_NAME \ | ||
--query "Environments[0].CNAME" \ | ||
--output text) | ||
|
||
colored_echo "Your AWS Elastic Beanstalk application is deployed at: http://$ENVIRONMENT_URL" |