Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[AAQ-583] CI/CD for GCP #264

Merged
merged 37 commits into from
Jul 8, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
37 commits
Select commit Hold shift + click to select a range
4ffb991
add gcp github actions workflow
suzinyou Jun 19, 2024
23f9df4
configure deployment env
suzinyou Jun 19, 2024
322c4df
fix provider path and use script
suzinyou Jun 19, 2024
daafb2c
add redeploy script
suzinyou Jun 19, 2024
ff2a045
hardcode repo path
suzinyou Jun 19, 2024
8fde17a
update OIDC provider and add prune statement to redeploy script
suzinyou Jun 25, 2024
032ff89
remove service account to use workload identity federation?
suzinyou Jun 25, 2024
e78e64e
upgrade google-github-actions
suzinyou Jun 25, 2024
c8340c0
fix env to vars
suzinyou Jun 25, 2024
f9265d2
impersonate service account
suzinyou Jun 25, 2024
f7773e4
switch to command in ssh
suzinyou Jun 25, 2024
b423e21
remove redeploy script
suzinyou Jun 25, 2024
16db682
add cloudbuild configs
suzinyou Jun 26, 2024
4e693d6
test caddy deployment workflow to GCP
suzinyou Jun 27, 2024
295ee2b
remove old deploy script and fix branch name in gcp workflow
suzinyou Jun 27, 2024
50c5f0e
fix docker build cloudbuild command syntax
suzinyou Jun 27, 2024
0f6536a
add deployment workflow for backend, admin app, and litellm proxy
suzinyou Jun 27, 2024
fcb997d
fix typos in substitution var name
suzinyou Jun 27, 2024
44cb9db
fix litellm proxy cloudbuild config path
suzinyou Jun 27, 2024
d900544
add restart policy and network
suzinyou Jun 27, 2024
db48026
pass custom CMD for config file path in litellm dockerfile
suzinyou Jun 27, 2024
6dfd919
add docker commands to transition to new containers
suzinyou Jun 27, 2024
d403158
parse passworld for db connection string
suzinyou Jun 27, 2024
f55f380
update restart condition for caddy
suzinyou Jun 27, 2024
a6bccf5
use URL for connection strings
suzinyou Jun 27, 2024
b7a7eed
fix mypy error on port dtype
suzinyou Jun 27, 2024
5540b9c
completely stop and remove existing container before running
suzinyou Jun 27, 2024
b03ec9c
remove this branch from trigger condition
suzinyou Jun 27, 2024
4e86979
check for health after deployment
suzinyou Jun 28, 2024
adf9c3d
show stdout and stderr
suzinyou Jul 1, 2024
0576049
fix caddy typo, and show ssh stderr and stdout
suzinyou Jul 1, 2024
609a08b
fix litellm proxy path in make
suzinyou Jul 3, 2024
bb22c4c
add production branch trigger condition and parametrize deployment en…
suzinyou Jul 3, 2024
07a28e3
clean up step name
suzinyou Jul 3, 2024
62c64c0
Improve gcp deploy (#274)
suzinyou Jul 8, 2024
77538fd
move config files back to docker-compose dir and undo testing code
suzinyou Jul 8, 2024
57ac896
Test push
markbotterill Jul 8, 2024
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
103 changes: 103 additions & 0 deletions .github/workflows/deploy_gcp_admin_app.yaml
Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

All deployment scripts follow the same pattern!

Original file line number Diff line number Diff line change
@@ -0,0 +1,103 @@
name: Deploy admin_app to GCP

on:
push:
branches:
- main
- testing
- production
paths:
- "admin_app/**"
- ".github/workflows/deploy_gcp_admin_app.yaml"
workflow_dispatch:

jobs:
DeployAdminAppToGCP:
runs-on: ubuntu-latest

permissions:
contents: "read"
id-token: "write"

# TODO: replace improve-gcp-deploy with main
environment: gcp-${{ (github.ref_name == 'main' && 'testing') || github.ref_name }}

env:
RESOURCE_PREFIX: ${{ secrets.PROJECT_NAME }}-${{ (github.ref_name == 'main' && 'testing') || github.ref_name }}
REPO: ${{ secrets.DOCKER_REGISTRY_DOMAIN }}/${{ secrets.GCP_PROJECT_ID }}/${{ secrets.PROJECT_NAME }}-${{ (github.ref_name == 'main' && 'testing') || github.ref_name }}

steps:
- uses: "actions/checkout@v4"

- id: "auth"
name: "Authenticate to Google Cloud"
uses: "google-github-actions/auth@v2"
with:
project_id: ${{ secrets.GCP_PROJECT_ID }}
workload_identity_provider: projects/${{ secrets.GCP_PROJECT_NUMBER }}/locations/global/workloadIdentityPools/${{ vars.POOL_ID }}/providers/${{ vars.PROVIDER_ID }}
service_account: ${{ secrets.GCP_SERVICE_ACCOUNT_EMAIL }}

- name: Retrieve secrets from Secret Manager
id: "secrets"
uses: "google-github-actions/get-secretmanager-secrets@v2"
with:
min_mask_length: 4
secrets: |-
domain:${{ secrets.GCP_PROJECT_ID }}/${{ env.RESOURCE_PREFIX }}-domain
google_login_client_id:${{ secrets.GCP_PROJECT_ID }}/${{ env.RESOURCE_PREFIX }}-google-login-client-id

- name: Configure Docker to use gcloud as a credential helper
run: |
gcloud auth configure-docker ${{ secrets.DOCKER_REGISTRY_DOMAIN}}

- name: Build and push admin_app image
working-directory: admin_app
run: |
docker build \
--build-arg NEXT_PUBLIC_BACKEND_URL="https://${{ steps.secrets.outputs.domain }}/api" \
--build-arg NEXT_PUBLIC_GOOGLE_LOGIN_CLIENT_ID="${{ steps.secrets.outputs.google_login_client_id }}" \
-t ${{ env.REPO }}/admin_app:latest \
-t ${{ env.REPO }}/admin_app:${{ github.sha }} \
.
docker image push --all-tags ${{ env.REPO }}/admin_app

- name: Deploy admin_app container
id: "compute-ssh"
uses: "google-github-actions/ssh-compute@v1"
env:
REPO: ${{ secrets.DOCKER_REGISTRY_DOMAIN }}/${{ secrets.GCP_PROJECT_ID }}/${{ env.RESOURCE_PREFIX }}
with:
instance_name: "${{ secrets.DEPLOYMENT_INSTANCE_NAME }}"
zone: "${{ secrets.DEPLOYMENT_ZONE }}"
ssh_private_key: "${{ secrets.GCP_SSH_PRIVATE_KEY }}"
command: |
docker-credential-gcr configure-docker \
--registries ${{ secrets.DOCKER_REGISTRY_DOMAIN }}
docker pull \
${{ env.REPO }}/admin_app:latest
docker stop admin_app
docker rm admin_app
docker run -d \
--log-driver=gcplogs \
--restart always \
--network aaq-network \
--name admin_app \
${{ env.REPO }}/admin_app:latest
docker system prune -f

- name: Show deployment command output
run: |-
echo '${{ steps.compute-ssh.outputs.stdout }}'
echo '${{ steps.compute-ssh.outputs.stderr }}'

- name: Wait for Application to start
id: wait-for-app
run: sleep 1m
shell: bash

- name: Check if deployment was successful
id: check-deployment
run: |
curl -f -X 'GET' \
'https://${{ steps.secrets.outputs.domain }}/api/healthcheck' \
-H 'accept: application/json'
93 changes: 93 additions & 0 deletions .github/workflows/deploy_gcp_caddy.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,93 @@
name: Deploy Caddy to GCP

on:
push:
branches:
- main
- testing
- production
paths:
- "deployment/docker-compose/caddy/**"
- ".github/workflows/deploy_gcp_caddy.yaml"
workflow_dispatch:

jobs:
DeployCaddyToGCP:
runs-on: ubuntu-latest

permissions:
contents: "read"
id-token: "write"

# TODO: replace improve-gcp-deploy with main
environment: gcp-${{ (github.ref_name == 'main' && 'testing') || github.ref_name }}

env:
RESOURCE_PREFIX: ${{ secrets.PROJECT_NAME }}-${{ (github.ref_name == 'main' && 'testing') || github.ref_name }}

steps:
- uses: "actions/checkout@v4"

- id: "auth"
name: "Authenticate to Google Cloud"
uses: "google-github-actions/auth@v2"
with:
project_id: ${{ secrets.GCP_PROJECT_ID }}
workload_identity_provider: projects/${{ secrets.GCP_PROJECT_NUMBER }}/locations/global/workloadIdentityPools/${{ vars.POOL_ID }}/providers/${{ vars.PROVIDER_ID }}
service_account: ${{ secrets.GCP_SERVICE_ACCOUNT_EMAIL }}

- name: Retrieve secrets from Secret Manager
id: "secrets"
uses: "google-github-actions/get-secretmanager-secrets@v2"
with:
secrets: |-
domain:${{ secrets.GCP_PROJECT_ID }}/${{ env.RESOURCE_PREFIX }}-domain

- name: Copy Caddy deployment files
working-directory: deployment/docker-compose
run: |
gcloud compute scp Caddyfile \
${{ secrets.DEPLOYMENT_INSTANCE_NAME }}:~/Caddyfile \
--zone ${{ secrets.DEPLOYMENT_ZONE }}

- name: Deploy Caddy container
id: "compute-ssh"
uses: "google-github-actions/ssh-compute@v1"
with:
instance_name: "${{ secrets.DEPLOYMENT_INSTANCE_NAME }}"
zone: "${{ secrets.DEPLOYMENT_ZONE }}"
ssh_private_key: "${{ secrets.GCP_SSH_PRIVATE_KEY }}"
command: |
docker stop caddy
docker rm caddy
docker run -d \
-v caddy_data:/data \
-v caddy_config:/config \
-e DOMAIN=${{ steps.secrets.outputs.domain }} \
-p 80:80 \
-p 443:443 \
-p 443:443/udp \
-v ~/Caddyfile:/etc/caddy/Caddyfile \
--log-driver=gcplogs \
--restart always \
--network aaq-network \
--name caddy \
caddy:2.7.6
docker system prune --volumes -f

- name: Show deployment command output
run: |-
echo '${{ steps.compute-ssh.outputs.stdout }}'
echo '${{ steps.compute-ssh.outputs.stderr }}'

- name: Wait for Application to start
id: wait-for-app
run: sleep 1m
shell: bash

- name: Check if deployment was successful
id: check-deployment
run: |
curl -f -X 'GET' \
'https://${{ steps.secrets.outputs.domain }}/api/healthcheck' \
-H 'accept: application/json'
122 changes: 122 additions & 0 deletions .github/workflows/deploy_gcp_core_backend.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,122 @@
name: Deploy core_backend to GCP

on:
push:
branches:
- main
- testing
- production
paths:
- "core_backend/**"
- ".github/workflows/deploy_gcp_core_backend.yaml"
workflow_dispatch:

jobs:
DeployCoreBackendToGCP:
runs-on: ubuntu-latest

permissions:
contents: "read"
id-token: "write"

# TODO: replace improve-gcp-deploy with main
environment: gcp-${{ (github.ref_name == 'main' && 'testing') || github.ref_name }}

env:
RESOURCE_PREFIX: ${{ secrets.PROJECT_NAME }}-${{ (github.ref_name == 'main' && 'testing') || github.ref_name }}
REPO: ${{ secrets.DOCKER_REGISTRY_DOMAIN }}/${{ secrets.GCP_PROJECT_ID }}/${{ secrets.PROJECT_NAME }}-${{ (github.ref_name == 'main' && 'testing') || github.ref_name }}

steps:
- uses: "actions/checkout@v4"

- id: "auth"
name: "Authenticate to Google Cloud"
uses: "google-github-actions/auth@v2"
with:
project_id: ${{ secrets.GCP_PROJECT_ID }}
workload_identity_provider: projects/${{ secrets.GCP_PROJECT_NUMBER }}/locations/global/workloadIdentityPools/${{ vars.POOL_ID }}/providers/${{ vars.PROVIDER_ID }}
service_account: ${{ secrets.GCP_SERVICE_ACCOUNT_EMAIL }}

- name: Retrieve secrets from Secret Manager
id: "secrets"
uses: "google-github-actions/get-secretmanager-secrets@v2"
with:
secrets: |-
domain:${{ secrets.GCP_PROJECT_ID }}/${{ env.RESOURCE_PREFIX }}-domain
jwt-secret:${{ secrets.GCP_PROJECT_ID }}/${{ env.RESOURCE_PREFIX }}-jwt-secret
google-login-client-id:${{ secrets.GCP_PROJECT_ID }}/${{ env.RESOURCE_PREFIX }}-google-login-client-id
langfuse-secret-key:${{ secrets.GCP_PROJECT_ID }}/${{ env.RESOURCE_PREFIX }}-langfuse-secret-key
langfuse-public-key:${{ secrets.GCP_PROJECT_ID }}/${{ env.RESOURCE_PREFIX }}-langfuse-public-key
db-host:${{ secrets.GCP_PROJECT_ID }}/${{ env.RESOURCE_PREFIX }}-db-host
db-password:${{ secrets.GCP_PROJECT_ID }}/${{ env.RESOURCE_PREFIX }}-db-password
admin-username:${{ secrets.GCP_PROJECT_ID }}/${{ env.RESOURCE_PREFIX }}-admin-username
admin-password:${{ secrets.GCP_PROJECT_ID }}/${{ env.RESOURCE_PREFIX }}-admin-password
admin-api-key:${{ secrets.GCP_PROJECT_ID }}/${{ env.RESOURCE_PREFIX }}-admin-api-key

- name: Configure Docker to use gcloud as a credential helper
run: |
gcloud auth configure-docker ${{ secrets.DOCKER_REGISTRY_DOMAIN}}

- name: Build and push core_backend image
working-directory: core_backend
run: |
docker build \
-t ${{ env.REPO }}/core_backend:latest \
-t ${{ env.REPO }}/core_backend:${{ github.sha }} \
.
docker image push --all-tags ${{ env.REPO }}/core_backend

- name: Deploy core_backend container
id: "compute-ssh"
uses: "google-github-actions/ssh-compute@v1"
env:
REPO: ${{ secrets.DOCKER_REGISTRY_DOMAIN }}/${{ secrets.GCP_PROJECT_ID }}/${{ env.RESOURCE_PREFIX }}
with:
instance_name: "${{ secrets.DEPLOYMENT_INSTANCE_NAME }}"
zone: "${{ secrets.DEPLOYMENT_ZONE }}"
ssh_private_key: "${{ secrets.GCP_SSH_PRIVATE_KEY }}"
command: |
docker-credential-gcr configure-docker \
--registries ${{ secrets.DOCKER_REGISTRY_DOMAIN }}
docker pull \
${{ env.REPO }}/core_backend:latest
docker stop core_backend
docker rm core_backend
docker run -d \
--log-driver=gcplogs \
--restart always \
--network aaq-network \
--name core_backend \
-e JWT_SECRET="${{ steps.secrets.outputs.jwt-secret }}" \
-e NEXT_PUBLIC_GOOGLE_LOGIN_CLIENT_ID="${{ steps.secrets.outputs.google-login-client-id }}" \
-e DOMAIN="${{ steps.secrets.outputs.domain }}" \
-e POSTGRES_HOST="${{ steps.secrets.outputs.db-host }}" \
-e POSTGRES_PASSWORD="${{ steps.secrets.outputs.db-password }}" \
-e ADMIN_USERNAME="${{ steps.secrets.outputs.admin-username }}" \
-e ADMIN_PASSWORD="${{ steps.secrets.outputs.admin-password }}" \
-e ADMIN_API_KEY="${{ steps.secrets.outputs.admin-api-key }}" \
-e PROMETHEUS_MULTIPROC_DIR=/tmp \
-e LITELLM_ENDPOINT=http://litellm_proxy:4000 \
-e LANGFUSE=True \
-e LANGFUSE_SECRET_KEY="${{ steps.secrets.outputs.langfuse-secret-key }}" \
-e LANGFUSE_PUBLIC_KEY="${{ steps.secrets.outputs.langfuse-public-key }}" \
-e BACKEND_ROOT_PATH=/api \
${{ env.REPO }}/core_backend:latest
docker system prune -f

- name: Show deployment command output
run: |-
echo '${{ steps.compute-ssh.outputs.stdout }}'
echo '${{ steps.compute-ssh.outputs.stderr }}'

- name: Wait for Application to start
id: wait-for-app
run: sleep 1m
shell: bash

- name: Check if deployment was successful
id: check-deployment
run: |
curl -f -X 'GET' \
'https://${{ steps.secrets.outputs.domain }}/api/healthcheck' \
-H 'accept: application/json'
Loading