Push image for 05-assistive-chatbot to bdt-chatbot.navalabs.co #83
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 | |
permissions: | |
id-token: write # This is required for requesting the JWT from GitHub's OIDC provider for AWS authentication | |
env: | |
AWS_REGION: us-east-1 | |
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 }} | |
role-to-assume: arn:aws:iam::654654379445:role/Lightsail_Mgmt_role | |
role-session-name: GitHub_to_AWS_via_FederatedOIDC | |
- name: "Setup AWS lightsail command" | |
run: | | |
aws --version | |
aws sts get-caller-identity | |
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: "Populate folder with input files" | |
if: inputs.build_image && ${{ inputs.dockerfile_folder }} == '05-assistive-chatbot' | |
env: | |
GURU_CARDS_URL: https://docs.google.com/uc?export=download&id=${{ secrets.GURU_CARDS_URL_ID }} | |
run: | | |
echo "Downloading from ${GURU_CARDS_URL}" | |
curl -L "${GURU_CARDS_URL}" > download.zip | |
unzip -o download.zip | |
rm download.zip | |
mv guru_cards_for_nava--Multi-benefit.json guru_cards_for_nava.json | |
cd ${{ inputs.dockerfile_folder }} | |
mv ../guru_cards_for_nava.json . | |
# The DOT_ENV_FILE_CONTENTS contains API keys, like LITERAL_API_KEY and OPENAI_API_KEY | |
# As such, make sure the built image is not publicly accessible | |
echo "${{ secrets.DOT_ENV_FILE_CONTENTS }}" > .env | |
- name: "Build image: ${{ github.sha }}" | |
if: inputs.build_image | |
run: | | |
cd ${{ inputs.dockerfile_folder }} | |
# Add extra environment variables to facilitate traceability of an image back to the source code | |
echo " | |
BUILD_DATE=$(date +%Y-%m-%d-%T) | |
GIT_SHA=${{ github.sha }} | |
" >> .env | |
docker build -t mylocalimage . | |
- name: "Push image to Lightsail" | |
if: inputs.build_image | |
id: push_image | |
env: | |
# Lightsail requires that LABEL 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 mylocalimage | |
LS_DOCKER_IMAGE=$(aws lightsail get-container-images --service-name "$SERVICE_NAME" | jq -r .containerImages[0].image) | |
echo "Lightsail 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 |