Skip to content

Push image for 05-assistive-chatbot to chatbot.navalabs.co #131

Push image for 05-assistive-chatbot to chatbot.navalabs.co

Push image for 05-assistive-chatbot to chatbot.navalabs.co #131

Workflow file for this run

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'
- '04-call-summaries'
- '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 built image or last deployment"
required: true
type: boolean
default: true
deploy_retries:
description: "Number of times to retry deployment"
required: true
type: number
default: 3
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"
uses: actions/checkout@v4
- name: "Determine secret name for .env file"
run: |
case "${{ inputs.dockerfile_folder }}" in
04-call-summaries) SECRET_NAME=DOT_ENV_FILE_CONTENTS_04;;
05-assistive-chatbot) SECRET_NAME=DOT_ENV_FILE_CONTENTS;;
*) exit 1;;
esac
echo "Using SECRET_NAME: $SECRET_NAME"
echo "SECRET_NAME=$SECRET_NAME" >> $GITHUB_ENV
- name: "Populate .env file"
if: inputs.dockerfile_folder != '05-assistive-chatbot'
run: |
# The 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
cd ${{ inputs.dockerfile_folder }}
echo "${{ secrets[env.SECRET_NAME] }}" > .env
wc .env
- name: "Build image: ${{ github.sha }}"
if: inputs.build_image
env:
GURU_CARDS_URL_ID: ${{ secrets.GURU_CARDS_URL_ID }}
run: |
cd ${{ inputs.dockerfile_folder }}
echo "Populating with input files"
[ -f ./get_input_files.sh ] && ./get_input_files.sh
# 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
wc .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: "Get last deployment"
if: inputs.deploy_image && ! inputs.build_image
run: |
LAST_DEPLOYMENT_IMAGE=$(aws lightsail get-container-service-deployments --service-name "$SERVICE_NAME" | jq -r ".deployments[0].containers.chatbot.image")
echo "LS_DOCKER_IMAGE=$LAST_DEPLOYMENT_IMAGE" >> $GITHUB_ENV
- name: "Submit deployment"
if: inputs.deploy_image
env:
DEPLOY_RETRIES: ${{ inputs.deploy_retries }}
run: |
CONFIG_TEMPLATE='{
"serviceName": "$SERVICE_NAME",
"containers": {
"chatbot": {
"image": "$LS_DOCKER_IMAGE",
"command": [],
"environment": {
"ENV": "PROD",
"BUILD_DATE": "$BUILD_DATE",
"BUILD_FOLDER": "${{ inputs.dockerfile_folder }}",
"GIT_BRANCH": "$GIT_BRANCH",
"GIT_SHA": "${{ github.sha }}"
},
"ports": {
"8000": "HTTP"
}
}
},
"publicEndpoint": {
"containerName": "chatbot",
"containerPort": 8000,
"healthCheck": {
"healthyThreshold": 2,
"unhealthyThreshold": 10,
"timeoutSeconds": 60,
"intervalSeconds": 300,
"path": "/healthcheck",
"successCodes": "200-499"
}
}
}'
export GIT_BRANCH="${GITHUB_HEAD_REF:-${GITHUB_REF#refs/heads/}}"
export BUILD_DATE=$(date +%Y-%m-%d-%T%z)
echo "$CONFIG_TEMPLATE" | envsubst > config.json
cat config.json
for ((i = 0 ; i < ${DEPLOY_RETRIES} ; i++ )); do
echo "## Deploy attempt $((i+1)) of $DEPLOY_RETRIES"
date
echo "Creating new deployment"
aws lightsail create-container-service-deployment --cli-input-json file://config.json
sleep 30
if ./.github/workflows/waitForLightsail.sh deployment; then
echo "Success on attempt $((i+1))"
break;
fi
done
date
- name: "Initialize app"
if: inputs.deploy_image && (inputs.dockerfile_folder == '05-assistive-chatbot')
run: |
# The 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[env.SECRET_NAME] }}" > .env_vars
SVC_URL=$(aws lightsail get-container-services --service-name "$SERVICE_NAME" | jq -r '.containerServices[0].url')
echo "Setting API keys at $SVC_URL"
curl --fail -X POST "${SVC_URL}initenvs" --data-binary '@.env_vars'
# TODO: warm up vector DB on startup