Skip to content

Commit

Permalink
Merge pull request #22 from luoziqing99/milestone6-yp
Browse files Browse the repository at this point in the history
Milestone6 yp CI/CD app_deploy
  • Loading branch information
Lliillyy authored Dec 12, 2023
2 parents 8c36783 + 27dc7f8 commit 49e4e8b
Show file tree
Hide file tree
Showing 11 changed files with 222 additions and 9 deletions.
51 changes: 51 additions & 0 deletions .github/workflows/ci-cd.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
name: Continuous Integration and Continuous Deployment
run-name: ${{ github.actor }} submitted a CI CD Action
on:
push:
branches: [ "main", "milestone6", "milestone6-yp"]

jobs:
Explore-GitHub-Actions:
if: contains(github.event.head_commit.message, '/run-')
runs-on: ubuntu-latest
steps:
- run: echo "Comment ${{ github.event.head_commit.message }}"
- run: echo "Job was automatically triggered by a ${{ github.event_name }} event."
- run: echo "Job is now running on a ${{ runner.os }} server hosted by GitHub!"
- run: echo "Branch is ${{ github.ref }} and your repository is ${{ github.repository }}."
- name: Check out repository code
uses: actions/checkout@v4
- id: 'auth'
uses: google-github-actions/auth@v1
with:
credentials_json: '${{ secrets.GOOGLE_APPLICATION_CREDENTIALS }}'
- name: Configure Google Cloud SDK
uses: google-github-actions/setup-gcloud@v1
- name: Configure Docker Client
run: |-
gcloud auth configure-docker # --quiet #authenticate to gcr
- run: echo "💡 The ${{ github.repository }} repository has been cloned to the runner."
- run: echo "🖥️ The workflow is now ready to test your code on the runner."
- name: List files in the repository
run: |
ls ${{ github.workspace }}
- name: Build App Deploy Container
run: |-
cd ${{ github.workspace }}/src/app_deploy/
docker build -t app_deployment --platform=linux/amd64 -f Dockerfile .
- name: Run Deploy App
if: contains(github.event.head_commit.message, '/run-deploy-app')
run: |-
docker run --rm --name app_deployment \
-v /var/run/docker.sock:/var/run/docker.sock \
-v $HOME/.ssh:/home/app/.ssh \
-v ${{ github.workspace }}/src/frontend:/frontend-react \
-v ${{ github.workspace }}/src/api-service:/api-service \
--volume $GITHUB_WORKSPACE:/workspace \
--mount type=bind,source=$GOOGLE_APPLICATION_CREDENTIALS,target=/secrets/deployment.json \
--env GOOGLE_APPLICATION_CREDENTIALS=/secrets/deployment.json \
-e USE_GKE_GCLOUD_AUTH_PLUGIN=True \
-e GCP_PROJECT=ac215project-398401 \
-e GCP_ZONE=us-west3-b \
app_deployment ./deploy-app.sh
- run: echo "Job's status is ${{ job.status }}."
11 changes: 8 additions & 3 deletions src/api-service/api/model_backend.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,8 +9,6 @@
pwd = Path(__file__).parent.resolve()
import sys, os
sys.path.insert(0, "LLaVA")
# print(sys.path)
# print(os.environ.get("PYTHONPATH"))
from llava.constants import IMAGE_TOKEN_INDEX, DEFAULT_IMAGE_TOKEN, DEFAULT_IM_START_TOKEN, DEFAULT_IM_END_TOKEN
from llava.conversation import conv_templates, SeparatorStyle
from llava.model.builder import load_pretrained_model
Expand Down Expand Up @@ -115,8 +113,15 @@ def post(self):
app = Flask(__name__)

swagger = Swagger(app)

app.add_url_rule('/chat', view_func=ChatView.as_view('chat'), methods=['POST'])

@app.route('/status', methods=['GET'])
def get_api_status():
return jsonify({
"api_version": "1.0",
"torch_version": torch.__version__
})

CORS(app)

# Run the Flask app
Expand Down
5 changes: 4 additions & 1 deletion src/app_deploy/Dockerfile
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,9 @@ FROM ubuntu:20.04

# Set the environment variable for non-interactive installations
ENV DEBIAN_FRONTEND=noninteractive
ENV LANG=C.UTF-8
ENV PYENV_SHELL=/bin/bash
ENV PYTHONUNBUFFERED=1

# Install required dependencies
RUN apt-get update && \
Expand Down Expand Up @@ -32,7 +35,7 @@ RUN curl -fsSL https://pkgs.k8s.io/core:/stable:/v1.28/deb/Release.key | gpg --d
curl https://baltocdn.com/helm/signing.asc | apt-key add -&& \
echo "deb https://baltocdn.com/helm/stable/debian/ all main" | tee /etc/apt/sources.list.d/helm-stable-debian.list && \
apt-get update && \
apt-get install -y --no-install-recommends kubectl helm python3 python3-pip && \
apt-get install -y --no-install-recommends kubectl helm python3.9 python3-pip && \
pip install openshift ansible docker apache-libcloud

RUN useradd -ms /bin/bash app -d /home/app -u 1000 -p "$(openssl passwd -1 passw0rd)" && \
Expand Down
5 changes: 5 additions & 0 deletions src/app_deploy/deploy-app-init.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
# Build and Push Docker Containers to GCR
ansible-playbook deploy-docker-images.yml -i inventory.yml
# Create and Deploy Cluster
ansible-playbook deploy-k8s-cluster.yml -i inventory.yml --extra-vars cluster_state=present
# Once the command runs go to http://<YOUR INGRESS IP>.sslip.io
4 changes: 4 additions & 0 deletions src/app_deploy/deploy-app.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
# Build and Push Docker Containers to GCR
ansible-playbook deploy-docker-images.yml -i inventory.yml
# Update Cluster
ansible-playbook update-k8s-cluster.yml -i inventory-prod.yml
10 changes: 9 additions & 1 deletion src/app_deploy/docker-entrypoint.sh
Original file line number Diff line number Diff line change
Expand Up @@ -9,4 +9,12 @@ gcloud config set project $GCP_PROJECT
# Configure GCR
gcloud auth configure-docker gcr.io -q

/bin/bash
args="$@"
echo $args

if [[ -z ${args} ]];
then
/bin/bash
else
/bin/bash $args
fi
2 changes: 1 addition & 1 deletion src/app_deploy/docker-shell.sh
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
#!/bin/bash

# exit immediately if a command exits with a non-zero status
#set -e
set -e

# Define some environment variables
export IMAGE_NAME="app_deployment"
Expand Down
9 changes: 9 additions & 0 deletions src/app_deploy/inventory-prod.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
all:
vars:
gcp_service_account_file: "/secrets/deployment.json"
gcp_service_account_email: "[email protected]"
gcp_auth_kind: "serviceaccount"
gcp_scopes: "https://www.googleapis.com/auth/compute"
gcp_project: "ac215project-398401"
gcp_region: "us-west3"
gcp_zone: "us-west3-b"
30 changes: 30 additions & 0 deletions src/app_deploy/update-deploy-app.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
#!/bin/bash

# exit immediately if a command exits with a non-zero status
set -e

# Define some environment variables
export IMAGE_NAME="app_deployment"
export BASE_DIR=$(pwd)
export SECRETS_DIR=$(pwd)/../../../secrets/
export GCP_PROJECT="ac215project-398401" # Change to your GCP Project
export GCP_ZONE="us-west3-b"
export GOOGLE_APPLICATION_CREDENTIALS=/secrets/deployment.json

# Build the image based on the Dockerfile
#docker build -t $IMAGE_NAME -f Dockerfile .
docker build -t $IMAGE_NAME --platform=linux/amd64 -f Dockerfile .

# Run the container
docker run --rm --name $IMAGE_NAME \
-v /var/run/docker.sock:/var/run/docker.sock \
-v "$BASE_DIR":/app \
-v "$SECRETS_DIR":/secrets \
-v "$HOME/.ssh":/home/app/.ssh \
-v "$BASE_DIR/../api-service":/api-service \
-v "$BASE_DIR/../frontend":/frontend-react \
-e GOOGLE_APPLICATION_CREDENTIALS=$GOOGLE_APPLICATION_CREDENTIALS \
-e USE_GKE_GCLOUD_AUTH_PLUGIN=True \
-e GCP_PROJECT=$GCP_PROJECT \
-e GCP_ZONE=$GCP_ZONE \
$IMAGE_NAME ./deploy-app.sh
82 changes: 82 additions & 0 deletions src/app_deploy/update-k8s-cluster.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,82 @@
---
- name: "Update Kubernetes Cluster"
hosts: localhost
gather_facts: false

vars:
cluster_name: "science-tutor-cluster"

tasks:
- name: "Connect to cluster (update kubeconfig)"
shell: "gcloud container clusters get-credentials {{ cluster_name }} --zone {{ gcp_zone }} --project {{ gcp_project }}"

- name: "Copy docker tag file"
copy:
src: .docker-tag
dest: .docker-tag
mode: 0644

- name: "Get docker tag"
shell: "cat .docker-tag"
register: tag

- name: "Print tag"
debug:
var: tag

- name: "Update Deployment for Frontend"
k8s:
state: present
definition:
apiVersion: v1
kind: Deployment
metadata:
name: frontend
namespace: "{{cluster_name}}-namespace"
spec:
selector:
matchLabels:
run: frontend
template:
metadata:
labels:
run: frontend
spec:
containers:
- image: "gcr.io/{{ gcp_project }}/science-tutor-frontend-react:{{ tag.stdout}}"
imagePullPolicy: IfNotPresent
name: frontend
ports:
- containerPort: 80
protocol: TCP
restartPolicy: Always

- name: "Update Deployment for API Service"
k8s:
state: present
definition:
apiVersion: v1
kind: Deployment
metadata:
name: api
namespace: "{{cluster_name}}-namespace"
spec:
selector:
matchLabels:
run: api
template:
metadata:
labels:
run: api
spec:
volumes:
- name: persistent-vol
emptyDir: {}
- name: google-cloud-key
secret:
secretName: gcp-service-key
containers:
- image: gcr.io/{{ gcp_project }}/science-tutor-api-service:{{ tag.stdout}}
imagePullPolicy: IfNotPresent
name: api
restartPolicy: Always
22 changes: 19 additions & 3 deletions src/frontend/src/App.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,8 @@ import React, { useState, useEffect } from "react";
import "./App.css";
import { Configuration, OpenAIApi } from "openai";

const APP_VERSION = "1.0";

// Reference: https://github.com/EBEREGIT/react-chatgpt-tutorial

const configuration = new Configuration({
Expand All @@ -15,10 +17,23 @@ function App() {
const [image, setImage] = useState(null);
const [chats, setChats] = useState([]);
const [isTyping, setIsTyping] = useState(false);
const [api_version, setAPIVersion] = useState(null);
const [torch_version, setTorchVersion] = useState(null);

useEffect(() => {
const delayBeforeHello = 1000; // Adjust the delay in milliseconds
console.log("API Version", api_version, torch_version)
fetch("/api/status", {
"method": "GET",
})
.then(response => response.json())
.then(data => {
console.log(data);
setAPIVersion(data.api_version);
setTorchVersion(data.torch_version);
})
.catch(error => console.error('Error:', error));

const delayBeforeHello = 1000; // Adjust the delay in milliseconds
setTimeout(() => {
const systemMessage =
"Hello! This is your Science Tutor. I can provide instant and expert answers to K12 science questions that you may have in different domains such as natural, social and language science. Feel free to ask me any questions you have and upload an image to start!";
Expand Down Expand Up @@ -83,8 +98,8 @@ function App() {
setImage(null);

console.log("Trying to send", chats, formData)
fetch("http://127.0.0.1:5000/chat", {
// fetch("http://34.125.158.148:5000/chat", {
fetch("/api/chat", { // for nginx
// fetch("http://127.0.0.1:5000/chat", { // for Docker.dev
"method": "POST",
body: formData
})
Expand Down Expand Up @@ -115,6 +130,7 @@ function App() {

<main className="main-container">
<h1>ScienceTutor</h1>
<h4>APP v{APP_VERSION} &nbsp; API v{api_version} &nbsp; PyTorch v{torch_version}</h4>

<section>
{chats && chats.length
Expand Down

0 comments on commit 49e4e8b

Please sign in to comment.