Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
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
202 changes: 202 additions & 0 deletions .github/workflows/google-registry-gke-playground.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,202 @@
# This workflow build and push a Docker container to Google Artifact Registry and deploy it on Google Kubernetes Engine when a commit is pushed to the "develop" branch
# You can start your commit with `#update` and the workflow will just trigger an update of the Helm installation, without building a new image
#
# To configure this workflow:
#
# 1. Ensure the required Google Cloud APIs are enabled in the project:
#
# Cloud Build cloudbuild.googleapis.com
# Kubernetes Engine API container.googleapis.com
# Artifact Registry artifactregistry.googleapis.com
#
# 2. Create a service account (if you don't have one) with the following fields:
#
# Service Account Name <PROJECT-NAME>-github-actions
# Service Account ID <PROJECT-NAME>-github-actions
#
# 3. Ensure the service account have the required IAM permissions granted:
#
# Kubernetes Engine Developer
# roles/container.developer (kubernetes engine developer)
#
# Artifact Registry
# roles/artifactregistry.repoAdmin (artifact registry repository administrator)
# roles/artifactregistry.admin (artifact registry administrator)
#
# Service Account
# roles/iam.serviceAccountUser (act as the Cloud Run runtime service account)
#
# Basic Roles
# roles/viewer (viewer)
#
# NOTE: You should always follow the principle of least privilege when assigning IAM roles
#
# 4. Ensure you have the following GitHub Secrets and Variables:
#
# GitHub Secrets
# GCP_SA_KEY (Google Cloud Project Service Account Key) ref visit https://github.com/Datawheel/company/wiki/Setting-Up-a-Service-Account-for-Workflows#use-the-service-account-on-github-secrets
#
# GitHub Variables
# GCP_PROJECT_ID (Google Cloud Project ID)
# GCP_ARTIFACT_REGISTRY_NAME (Google Cloud Articaft Registry Repository Name)
# GCP_ARTIFACT_REGISTRY_LOCATION (Google Cloud Artifact Registry Reposotiry Location)
#
# 5. Ensure you have the following GitHub Variables for each environment that you will set up:
#
# GitHub Variables
# GCP_IMAGE_NAME (Docker Image Name)
# GKE_APP_NAME (Google Kubernetes Engine Deployment Name)
# GKE_APP_NAMESPACE (Google Kubernetes Engine Deployment Namespace)
# GKE_CLUSTER (Google Kubernetes Engine Cluster Name)
# GKE_ZONE (Google Kubernetes Engine Cluster Zone)
#
# Further reading:
# Kubernetes Developer - https://cloud.google.com/iam/docs/understanding-roles#container.developer
# Artifact Registry IAM permissions - https://cloud.google.com/artifact-registry/docs/access-control#roles
# Container Registry vs Artifact Registry - https://cloud.google.com/blog/products/application-development/understanding-artifact-registry-vs-container-registry
# Principle of least privilege - https://cloud.google.com/blog/products/identity-security/dont-get-pwned-practicing-the-principle-of-least-privilege
# Deploy CloudRun Github Actions - https://github.com/google-github-actions/deploy-cloudrun
name: "[GCP][DEV] Build API to Registry and Deploy via Helm"

on:
push:
branches: [ "main" ]
paths:
- .github/workflows/google-registry-gke-playground.yaml
- helm/playground.yaml
- requirements.txt
- schema/**

env:
GCP_PROJECT_ID: ${{ vars.GCP_PROJECT_ID }}
GCP_ARTIFACT_REGISTRY_NAME: ${{ vars.GCP_ARTIFACT_REGISTRY_NAME }}
GCP_ARTIFACT_REGISTRY_LOCATION: ${{ vars.GCP_ARTIFACT_REGISTRY_LOCATION }}
GCP_IMAGE_NAME: ${{ vars.GCP_IMAGE_NAME }}
GKE_APP_NAME: ${{ vars.GKE_APP_NAME }}
GKE_APP_NAMESPACE: ${{ vars.GKE_APP_NAMESPACE }}
GKE_CLUSTER: ${{ vars.GKE_CLUSTER }}
GKE_ZONE: ${{ vars.GKE_ZONE }}
ACTIONS_ALLOW_UNSECURE_COMMANDS: true

jobs:
build:
environment: playground
runs-on: ubuntu-latest
# runs-on: self-hosted
if: ${{ !contains(github.event.head_commit.message, '#update') }}
steps:
- name: Checkout
uses: actions/checkout@v3

# Authentication via credentials json
- name: Google Auth
id: auth
uses: google-github-actions/auth@v2
with:
project_id: ${{ env.GCP_PROJECT_ID }}
credentials_json: ${{ secrets.GCP_SA_KEY }}

# Install Cloud SDK
- name: Set up Cloud SDK
uses: google-github-actions/setup-gcloud@v1
with:
install_components: beta

# Build image on Google Cloud Artifact Registry
- name: Build Docker Image
run: |-
gcloud builds submit \
--quiet \
--timeout=40m \
--config=cloudbuild.yml \
--substitutions=_GCP_PROJECT_ID=${{ env.GCP_PROJECT_ID }},_GCP_ARTIFACT_REGISTRY_NAME=${{ env.GCP_ARTIFACT_REGISTRY_NAME }},_GCP_ARTIFACT_REGISTRY_LOCATION=${{ env.GCP_ARTIFACT_REGISTRY_LOCATION }},_GCP_IMAGE_NAME=${{ env.GCP_IMAGE_NAME }},_GCP_IMAGE_TAG=${{ github.sha }},_GCP_IMAGE_ENVIRONMENT=${{ env.GKE_APP_NAMESPACE }}

deploy:
needs: build
environment: playground
runs-on: ubuntu-latest
# runs-on: self-hosted
steps:
- name: Checkout
uses: actions/checkout@v3

# Authentication via credentials json
- name: Google Auth
id: auth
uses: google-github-actions/auth@v2
with:
project_id: ${{ env.GCP_PROJECT_ID }}
credentials_json: ${{ secrets.GCP_SA_KEY }}

# Get google kubernetes engine credentials
- name: Get GKE Credentials
uses: google-github-actions/get-gke-credentials@v2
with:
cluster_name: ${{ env.GKE_CLUSTER }}
location: ${{ env.GKE_ZONE }}

# Transform GitHub secrets to base64 encoded
- name: Set encoded secret values
run: |
echo "ENCODED_TESSERACT_BACKEND=$(echo -n "${{ secrets.TESSERACT_BACKEND }}" | base64 | tr -d '\n')" >> $GITHUB_ENV

# Install Helm chart
- name: Helm install
uses: WyriHaximus/github-action-helm3@v2
with:
exec: |
helm upgrade --install --create-namespace \
--namespace ${{ env.GKE_APP_NAMESPACE }} \
--set app.environment=${{ env.GKE_APP_NAMESPACE }} \
--set app.release=${{ env.GKE_APP_NAMESPACE }} \
--set image.repository=${{ env.GCP_ARTIFACT_REGISTRY_LOCATION }}-docker.pkg.dev/${{ env.GCP_PROJECT_ID }}/${{ env.GCP_ARTIFACT_REGISTRY_NAME }}/${{ env.GCP_IMAGE_NAME }} \
--set image.tag=${{ github.sha }} \
--set nameOverride=${{ env.GKE_APP_NAME }} \
--set fullnameOverride=${{ env.GKE_APP_NAME }} \
--set secrets.TESSERACT_BACKEND=$ENCODED_TESSERACT_BACKEND \
${{ env.GKE_APP_NAME }} --values=./helm/playground.yaml ./helm

update:
runs-on: ubuntu-latest
environment: playground
# runs-on: self-hosted
if: ${{ contains(github.event.head_commit.message, '#update') }}
steps:
- name: Checkout
uses: actions/checkout@v3

# Authentication via credentials json
- name: Google Auth
id: auth
uses: google-github-actions/auth@v2
with:
project_id: ${{ env.GCP_PROJECT_ID }}
credentials_json: ${{ secrets.GCP_SA_KEY }}

# Get google kubernetes engine credentials
- name: Get GKE Credentials
uses: google-github-actions/get-gke-credentials@v2
with:
cluster_name: ${{ env.GKE_CLUSTER }}
location: ${{ env.GKE_ZONE }}

# Transform GitHub secrets to base64 encoded
- name: Set encoded secret values
run: |
echo "ENCODED_TESSERACT_BACKEND=$(echo -n "${{ secrets.TESSERACT_BACKEND }}" | base64 | tr -d '\n')" >> $GITHUB_ENV

# Install Helm chart
- name: Helm install
uses: WyriHaximus/github-action-helm3@v2
with:
exec: |
helm upgrade --install --create-namespace \
--namespace ${{ env.GKE_APP_NAMESPACE }} \
--set app.environment=${{ env.GKE_APP_NAMESPACE }} \
--set app.release=${{ env.GKE_APP_NAMESPACE }} \
--set image.repository=${{ env.GCP_ARTIFACT_REGISTRY_LOCATION }}-docker.pkg.dev/${{ env.GCP_PROJECT_ID }}/${{ env.GCP_ARTIFACT_REGISTRY_NAME }}/${{ env.GCP_IMAGE_NAME }} \
--set image.tag=${{ github.sha }} \
--set nameOverride=${{ env.GKE_APP_NAME }} \
--set fullnameOverride=${{ env.GKE_APP_NAME }} \
--set secrets.TESSERACT_BACKEND=$ENCODED_TESSERACT_BACKEND \
${{ env.GKE_APP_NAME }} --values=./helm/playground.yaml ./helm
86 changes: 86 additions & 0 deletions helm/playground.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,86 @@
image:
pullPolicy: Always

imagePullSecrets:
- name: github

replicaCount: 1

autoscaling:
enabled: true
minReplicas: 1
maxReplicas: 4
targetCPUUtilizationPercentage: 80
targetMemoryUtilizationPercentage: 120

resources:
requests:
cpu: 250m
memory: 1Gi
limits:
cpu: 500m
memory: 4Gi

livenessProbe:
failureThreshold: 3
httpGet:
path: /
port: 7777
scheme: HTTP
initialDelaySeconds: 30
periodSeconds: 30
timeoutSeconds: 30
successThreshold: 1

readinessProbe:
failureThreshold: 3
httpGet:
path: /
port: 7777
scheme: HTTP
initialDelaySeconds: 30
periodSeconds: 30
timeoutSeconds: 30
successThreshold: 2

service:
type: ClusterIP
port: 7777

serviceAccount:
# Specifies whether a service account should be created
create: true
# Annotations to add to the service account
annotations: {}
# The name of the service account to use.
# If not set and create is true, a name is generated using the fullname template
name: ""

configMap:
TESSERACT_DEBUG: "true"
TESSERACT_SCHEMA: "schema"

# secrets:
# TESSERACT_BACKEND: <BASE64-DATABASE-CONNECTOR-STRING>

ingress:
enabled: true
annotations:
cert-manager.io/cluster-issuer: "letsencrypt-prod"
acme.cert-manager.io/http01-edit-in-place: "true"
ingress.kubernetes.io/ssl-redirect: "true"
nginx.org/proxy-connect-timeout: "120s"
nginx.org/proxy-read-timeout: "120s"
nginx.org/proxy-buffers: "8 16k"
nginx.org/proxy-buffer-size: "16k"
nginx.org/proxy-busy-buffers-size: "64k"
nginx.org/location-snippets: |
add_header Access-Control-Allow-Origin *;
hosts:
- host: playground.api.datawheel.us
paths:
- /
tls:
- secretName: tesseract-api-ingress-tls
hosts:
- playground.api.datawheel.us