test #152
Workflow file for this run
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: CI | |
on: | |
push: | |
branches: | |
- main | |
- prod | |
- feat-* | |
- test-* | |
paths: | |
- 'services/**' | |
- '.github/**' | |
workflow_dispatch: | |
jobs: | |
test: | |
name: Run Tests | |
timeout-minutes: 5 | |
runs-on: ubuntu-latest | |
defaults: | |
run: | |
working-directory: services/server | |
steps: | |
- uses: actions/checkout@v4 | |
with: | |
sparse-checkout: | | |
.github | |
services | |
- name: Check Required variables and secrets | |
run: | | |
if [[ -z "${{ secrets.TEST_FIREBASE_API_KEY }}" ]]; then | |
echo "TEST_FIREBASE_API_KEY secret is missing"; | |
exit 1; | |
fi | |
if [[ -z "${{ secrets.TEST_FIREBASE_SERVICE_ACCOUNT_KEY_BASE64 }}" ]]; then | |
echo "TEST_FIREBASE_SERVICE_ACCOUNT_KEY_BASE64 secret is missing"; | |
exit 1; | |
fi | |
- name: Set up Go | |
uses: actions/setup-go@v5 | |
with: | |
go-version: '1.22.2' | |
- name: Install dependencies | |
run: go mod download | |
- name: Create firebase-service-account.json file | |
run: | | |
mkdir -p ./secrets | |
echo "${{ secrets.TEST_FIREBASE_SERVICE_ACCOUNT_KEY_BASE64 }}" | base64 -d > ./secrets/firebase-service-account.json | |
- name: Run tests | |
run: TEST_FIREBASE_API_KEY=${{ secrets.TEST_FIREBASE_API_KEY }} make test | |
ci: | |
name: Build and Push Docker Image, Deploy to Linode K8s | |
env: | |
API_VERSION: v1 | |
timeout-minutes: 5 | |
needs: test | |
defaults: | |
run: | |
working-directory: services/server | |
runs-on: ubuntu-latest | |
steps: | |
- uses: actions/checkout@v4 | |
with: | |
sparse-checkout: | | |
.github | |
services | |
- name: Check Required variables and secrets | |
run: | | |
if [[ -z "${{ secrets.DOCKERHUB_TOKEN }}" ]]; then | |
echo "DOCKERHUB_TOKEN secret is missing"; | |
exit 1; | |
fi | |
if [[ -z "${{ secrets.FIREBASE_SERVICE_ACCOUNT_KEY_BASE64 }}" ]]; then | |
echo "FIREBASE_SERVICE_ACCOUNT_KEY_BASE64 secret is missing"; | |
exit 1; | |
fi | |
if [[ -z "${{ secrets.LINODE_KUBECONFIG }}" ]]; then | |
echo "LINODE_KUBECONFIG secret is missing"; | |
exit 1; | |
fi | |
if [[ -z "${{ secrets.POSTGRES_HOST }}" ]]; then | |
echo "POSTGRES_HOST secret is missing"; | |
exit 1; | |
fi | |
if [[ -z "${{ secrets.POSTGRES_PASSWORD }}" ]]; then | |
echo "POSTGRES_PASSWORD secret is missing"; | |
exit 1; | |
fi | |
if [[ -z "${{ vars.DOCKERHUB_REPO }}" ]]; then | |
echo "DOCKERHUB_REPO variable is missing"; | |
exit 1; | |
fi | |
if [[ -z "${{ vars.DOCKERHUB_USERNAME }}" ]]; then | |
echo "DOCKERHUB_USERNAME variable is missing"; | |
exit 1; | |
fi | |
if [[ -z "${{ vars.HELM_VERSION }}" ]]; then | |
echo "HELM_VERSION variable is missing"; | |
exit 1; | |
fi | |
- name: Set Environment Variables | |
run: | | |
if [[ ${{ github.ref_name }} == 'prod' ]]; then | |
ENVIRONMENT='prod' | |
elif [[ ${{ github.ref_name }} == 'main' ]]; then | |
ENVIRONMENT='staging' | |
else | |
ENVIRONMENT='dev' | |
fi | |
IMAGE_REPO=${{ vars.DOCKERHUB_USERNAME }}/${{ vars.DOCKERHUB_REPO }} | |
SERVER_IMAGE_TAG="$ENVIRONMENT-server-${{ github.sha }}" | |
MIGRATION_IMAGE_TAG="$ENVIRONMENT-migration-${{ github.sha }}" | |
echo "ENVIRONMENT=$ENVIRONMENT" >> $GITHUB_ENV | |
echo "IMAGE_REPO=$IMAGE_REPO" >> $GITHUB_ENV | |
echo "SERVER_IMAGE_TAG=$SERVER_IMAGE_TAG" >> $GITHUB_ENV | |
echo "MIGRATION_IMAGE_TAG=$MIGRATION_IMAGE_TAG" >> $GITHUB_ENV | |
echo "SERVER_IMAGE=$IMAGE_REPO:$SERVER_IMAGE_TAG" >> $GITHUB_ENV | |
echo "MIGRATION_IMAGE=$IMAGE_REPO:$MIGRATION_IMAGE_TAG" >> $GITHUB_ENV | |
echo "HELM_RELEASE=server-$ENVIRONMENT" >> $GITHUB_ENV | |
- uses: azure/k8s-set-context@v4 | |
with: | |
kubeconfig: ${{ secrets.LINODE_KUBECONFIG }} # must be the kubeconfig itself, not the path to it | |
- uses: azure/[email protected] | |
with: | |
version: "${{ vars.HELM_VERSION }}" | |
- name: Build Server Docker Image # different FIREBASE_SERVICE_ACCOUNT_KEY_BASE64 secret for prod and staging | |
run: | | |
docker build \ | |
-f Dockerfile.prod \ | |
-t ${{ env.SERVER_IMAGE }} \ | |
--build-arg FIREBASE_SERVICE_ACCOUNT_KEY_BASE64=$( if [[ ${{ env.ENVIRONMENT }} == 'prod' ]]; then echo "${{ secrets.FIREBASE_SERVICE_ACCOUNT_KEY_BASE64 }}"; else echo "${{ secrets.FIREBASE_SERVICE_ACCOUNT_KEY_BASE64 }}"; fi ) \ | |
. | |
- name: Build Migration Docker Image # different FIREBASE_SERVICE_ACCOUNT_KEY_BASE64 secret for prod and staging | |
run: | | |
docker build \ | |
-f postgres/Dockerfile.migration \ | |
-t ${{ env.MIGRATION_IMAGE }} \ | |
. | |
- name: Login to Docker Hub | |
uses: docker/login-action@v3 | |
with: | |
username: ${{ vars.DOCKERHUB_USERNAME }} | |
password: ${{ secrets.DOCKERHUB_TOKEN }} | |
- name: Push Docker Images | |
run: | | |
docker push ${{ env.SERVER_IMAGE }} | |
docker push ${{ env.MIGRATION_IMAGE }} | |
- name: Adapt app version in Helm Chart | |
run: | | |
sed -i'' \ | |
-e "s/APP_VERSION/${{ github.sha }}/g" \ | |
k8s/server/Chart.yaml | |
- name: Apply Helm Chart in Production | |
if: ${{ env.ENVIRONMENT == 'prod' }} | |
run: | | |
helm upgrade ${{ env.HELM_RELEASE }} k8s/server \ | |
--install \ | |
--set image.repository=${{ env.IMAGE_REPO }} \ | |
--set image.tags.server=${{ env.SERVER_IMAGE_TAG }} \ | |
--set image.tags.migration=${{ env.MIGRATION_IMAGE_TAG }} \ | |
--set postgresql.auth.password=${{ secrets.POSTGRES_PASSWORD }} \ | |
--set postgresql.enabled=false \ | |
--set dbPasswordSecret.enabled=true \ | |
--set dbHost=${{ secrets.POSTGRES_HOST }} \ | |
--set replicaCount=1 \ | |
--set apiVersion=${{ env.API_VERSION }} \ | |
--set secrets.dockerHubSecret.valueBase64="$(cat ~/.docker/config.json | base64 -w 0)" \ | |
--namespace=prod | |
# --wait flag -> wait for all resources to be ready before running the post hook | |
- name: Apply Helm Chart in non-production environments | |
if: ${{ env.ENVIRONMENT != 'prod' }} | |
run: | | |
helm repo add bitnami https://charts.bitnami.com/bitnami | |
helm repo add ingress-nginx https://kubernetes.github.io/ingress-nginx | |
helm dependency build k8s/server | |
helm upgrade ${{ env.HELM_RELEASE }} k8s/server \ | |
--install \ | |
--set image.repository=${{ env.IMAGE_REPO }} \ | |
--set image.tags.server=${{ env.SERVER_IMAGE_TAG }} \ | |
--set image.tags.migration=${{ env.MIGRATION_IMAGE_TAG }} \ | |
--set replicaCount=1 \ | |
--set apiVersion=${{ env.API_VERSION }} \ | |
--set secrets.dockerHubSecret.valueBase64="$(cat ~/.docker/config.json | base64 -w 0)" \ | |
--set postgresql.enabled=true \ | |
--wait \ | |
--namespace=${{ env.ENVIRONMENT }} | |
- name: Verify Deployment | |
if: ${{ env.ENVIRONMENT == 'prod' }} | |
run: | | |
kubectl rollout status deployment/server --namespace=${{ env.ENVIRONMENT }} | |
- name: Perform health check | |
id: health_check | |
if: ${{ env.ENVIRONMENT == 'prod' }} | |
run: | | |
APP_HOST=niko-heidner.com | |
curl http://$APP_HOST/${{ env.API_VERSION }}/health --fail | |
- name: Rollback if failed | |
if: ${{ failure() && steps.health_check.outcome == 'failure' }} | |
run: | | |
helm rollback ${{ env.HELM_RELEASE }} --namespace=${{ env.ENVIRONMENT }} | |
- name: Delete old Images on Docker Hub | |
run: | | |
/bin/bash bash_scripts/delete_old_images/delete_old_images.sh ${{ env.SERVER_IMAGE_REGEX }} 50 5; | |
/bin/bash bash_scripts/delete_old_images/delete_old_images.sh ${{ env.MIGRATION_IMAGE_REGEX }} 50 5; | |
env: | |
SERVER_IMAGE_REGEX: "${{ env.ENVIRONMENT }}-server" | |
MIGRATION_IMAGE_REGEX: "${{ env.ENVIRONMENT }}-migration" | |
DOCKERHUB_USERNAME: ${{ vars.DOCKERHUB_USERNAME }} | |
DOCKERHUB_REPO: ${{ vars.DOCKERHUB_REPO }} | |
DOCKERHUB_PASSWORD: ${{ secrets.DOCKERHUB_TOKEN }} |