Push image for 05-assistive-chatbot to chatbot.navalabs.co #80
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
name: "Build and deploy Docker image" | |
run-name: "Push image for ${{inputs.dockerfile_folder}} to ${{ inputs.subdomain }}.navalabs.co" | |
on: | |
workflow_dispatch: | |
inputs: | |
dockerfile_folder: | |
description: 'Folder containing Dockerfile to build' | |
required: true | |
type: choice | |
options: | |
- '05-assistive-chatbot' | |
- '02-household-queries' | |
subdomain: | |
description: 'Subdomain of navalabs.co' | |
required: true | |
default: 'chat' | |
type: choice | |
options: | |
- 'chat' | |
- 'chatbot' | |
- 'chatbdt' | |
- 'chat-bdt' | |
- 'bdtbot' | |
- 'bdt-bot' | |
- 'bdt-chat' | |
- 'bdt-chatbot' | |
- 'chatbot-prototype' | |
- 'chat.zone' | |
build_image: | |
description: "Build and push image" | |
required: true | |
type: boolean | |
default: true | |
deploy_image: | |
description: "Deploy image" | |
required: true | |
type: boolean | |
default: true | |
env: | |
AWS_REGION: us-east-1 | |
IMAGE_NAME: localimage | |
SERVICE_NAME: ${{ inputs.subdomain }}-svc | |
jobs: | |
publish-image: | |
runs-on: ubuntu-latest | |
steps: | |
- name: "Configure AWS credentials" | |
uses: aws-actions/configure-aws-credentials@v4 | |
with: | |
aws-region: ${{ env.AWS_REGION }} | |
aws-access-key-id: ${{ secrets.AWS_ACCESS_KEY_ID }} | |
aws-secret-access-key: ${{ secrets.AWS_SECRET_ACCESS_KEY }} | |
mask-aws-account-id: true | |
# TODO: secure credentials by using `role-to-assume`: https://github.com/aws-actions/configure-aws-credentials?tab=readme-ov-file#assumerolewithwebidentity-recommended | |
# like in https://medium.com/@lukhee/automating-aws-lightsail-deployments-with-github-actions-53c73c9a1c1f | |
- name: "Setup AWS lightsail command" | |
run: | | |
aws --version | |
sudo curl "https://s3.us-west-2.amazonaws.com/lightsailctl/latest/linux-amd64/lightsailctl" -o "/usr/local/bin/lightsailctl" | |
sudo chmod +x /usr/local/bin/lightsailctl | |
echo "Services:" | |
aws lightsail get-container-services | jq -r '.containerServices[] | "\(.containerServiceName): \tstate=\(.state) \tisDisabled=\(.isDisabled)"' | |
- name: "Check preconditions" | |
run: | | |
echo "Checking if service '$SERVICE_NAME' exists" | |
aws lightsail get-container-services --service-name "$SERVICE_NAME" | |
- name: "Checkout source code" | |
if: inputs.build_image | |
uses: actions/checkout@v4 | |
- name: "Build image: ${{ github.sha }}" | |
if: inputs.build_image | |
run: | | |
cd ${{ inputs.dockerfile_folder }} | |
# TODO: make this more easily editable and secure | |
# The DOT_ENV_FILE_CONTENTS contains LITERAL_API_KEY, OPENAI_API_KEY, and other API keys | |
echo "${{ secrets.DOT_ENV_FILE_CONTENTS }}" > .env | |
# Add extra environment variables for traceability | |
echo "BUILD_DATE=$(date +%Y-%m-%d-%T)" >> .env | |
echo "GIT_SHA=${{ github.sha }}" >> .env | |
docker build -t "$IMAGE_NAME" --build-arg GURU_CARDS_URL="https://docs.google.com/uc?export=download&id=${{ secrets.GURU_CARDS_URL_ID }}" . | |
- name: "Push image to Lightsail" | |
if: inputs.build_image | |
id: push_image | |
env: | |
# LABEL must match regex ^(?:[a-z0-9]{1,2}|[a-z0-9][a-z0-9-]+[a-z0-9])$ | |
LABEL: git-push | |
run: | | |
aws lightsail push-container-image --region $AWS_REGION --service-name "$SERVICE_NAME" --label "$LABEL" --image "$IMAGE_NAME" | |
LS_DOCKER_IMAGE=$(aws lightsail get-container-images --service-name "$SERVICE_NAME" | jq -r .containerImages[0].image) | |
echo "Assigned image name: '$LS_DOCKER_IMAGE'" | |
echo "LS_DOCKER_IMAGE=$LS_DOCKER_IMAGE" >> $GITHUB_ENV | |
- name: "Create new deployment" | |
if: inputs.deploy_image | |
run: | | |
CONFIG_TEMPLATE='{ | |
"serviceName": "$SERVICE_NAME", | |
"containers": { | |
"chatbot": { | |
"image": "$LS_DOCKER_IMAGE", | |
"command": [], | |
"environment": { | |
"ENV": "PROD", | |
"BUILD_DATE": "$BUILD_DATE", | |
"GIT_SHA": "${{ github.sha }}" | |
}, | |
"ports": { | |
"8000": "HTTP" | |
} | |
} | |
}, | |
"publicEndpoint": { | |
"containerName": "chatbot", | |
"containerPort": 8000, | |
"healthCheck": { | |
"healthyThreshold": 2, | |
"unhealthyThreshold": 4, | |
"timeoutSeconds": 20, | |
"intervalSeconds": 60, | |
"path": "/healthcheck", | |
"successCodes": "200-499" | |
} | |
} | |
}' | |
echo "$CONFIG_TEMPLATE" | BUILD_DATE=$(date +%Y-%m-%d-%T%z) envsubst > config.json | |
cat config.json | |
echo "Creating new deployment" | |
aws lightsail create-container-service-deployment --cli-input-json file://config.json | |
echo "Waiting for service to be ready" | |
sleep 30 | |
while true; do | |
sleep 15 | |
DEPLOYMENT_STATE=$(aws lightsail get-container-services --service-name "$SERVICE_NAME" | jq -r '.containerServices[0].currentDeployment.state') | |
echo "service state: $DEPLOYMENT_STATE" | |
if [ "$DEPLOYMENT_STATE" == "ACTIVE" ]; then | |
break | |
fi | |
done | |
# TODO: warm up vector DB on startup |