Springboot app on Kubernetes: Deploy Application for per commit end to end testing

tldr: We have springboot app with postgres rds which we would like to deploy to kubernetes cluster on EKS using helm chart for End2End/Integration testing per commit/pull request.

Setup

  • Create a public postgres rds db for testing, create `prusr `role, and save credentials to GitHub secrets
  • Add `.github/workflow/pr.yaml`
  • Provide AWS GitHub oidc permission

Build springboot app

Docker push to ecr

Deploy to temp application to EKS

  • Set env POSTGRES_URL
  • Optional set up upterm session for github host debugging
  • Install postgres client
  • Create a temp database with github.sha (append with `pr` since dbname needs to start with alpha char) and grant prusr role access to temp database
  • Helm deploy with specifying new database url string using — set
  • Run integration tests
  • Helm uninstall deploy
  • Drop the temp database
name: Pull Request Verification

on:
pull_request:

# permission can be added at job level or workflow level
permissions:
id-token: write
contents: read
checks: write
statuses: write
jobs:
build:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v2
- name: Set up JDK 17
uses: actions/setup-java@v2
with:
java-version: '17'
distribution: 'temurin'
- name: Build the Application
uses: gradle/gradle-build-action@v2
with:
arguments: assemble foo-docker-image:
...
deploy-foo-service:
name: Deploy foo service
runs-on: ubuntu-latest
needs: [foo-docker-image]
env:
POSTGRES_URL: "foo.us-east-2.rds.amazonaws.com"
steps:
- uses: actions/checkout@v2
- name: Configure AWS credentials
uses: aws-actions/configure-aws-credentials@master
with:
aws-region: us-east-2
role-to-assume: arn:aws:iam::foo:role/github
- name: Git branch name
id: git-branch-name
uses: EthanSK/git-branch-name-action@v1
- name: Echo the branch name
run: echo "Branch name ${GIT_BRANCH_NAME}"
- name: Setup upterm session
uses: lhotari/action-upterm@v1
- name: Install postgres client
run: |
sudo apt-get update
sudo apt-get install --yes --no-install-recommends postgresql-client
- name: Create Temporary Database
run: |
PGPASSWORD=${{ secrets.POSTGRES_PASSWORD }} psql -h ${{ env.POSTGRES_URL }} -U ${{ secrets.POSTGRES_USERNAME }} -d postgres -c "CREATE DATABASE pr${{ github.sha }}"
PGPASSWORD=${{ secrets.POSTGRES_PASSWORD }} psql -h ${{ env.POSTGRES_URL }} -U ${{ secrets.POSTGRES_USERNAME }} -d postgres -c "GRANT ALL PRIVILEGES ON DATABASE pr${{ github.sha }} TO PRUSR"
- name: helm deploy foo-service
uses: koslib/helm-eks-action@master
env:
KUBE_CONFIG_DATA: ${{ secrets.KUBECONFIG_BASE64 }}
with:
command: |
export TOKEN=`aws ecr --region=us-east-2 get-authorization-token --output text --query authorizationData[].authorizationToken | base64 -d | cut -d: -f2`
aws eks update-kubeconfig --region us-east-2 --name foo-service-eks-foo
helm upgrade --install -f ./infra/helm/values-pr.yaml --set webImageVersion=${{ github.sha }} --set envApp.secret.POSTGRES_URL="jdbc:postgresql://${{ env.POSTGRES_URL }}:5432/pr${{ github.sha }}" --set namespace=${{ env.GIT_BRANCH_NAME }} --namespace ${{ env.GIT_BRANCH_NAME }} --create-namespace foo-service-pr ./infra/helm --wait --debug
sleep 20
export BASE_URI=$(kubectl get services --namespace ${{ env.GIT_BRANCH_NAME }} --output jsonpath='{.items[0].status.loadBalancer.ingress[0].hostname}')
echo $BASE_URI
# - name: Set up JDK 17
# uses: actions/setup-java@v2
# with:
# java-version: '17'
# distribution: 'temurin'
# - name: Run End2End Tests
# uses: gradle/gradle-build-action@v2
# with:
# arguments: integrationTest
- name: helm uninstall foo-service
uses: koslib/helm-eks-action@master
if: always()
env:
KUBE_CONFIG_DATA: ${{ secrets.KUBECONFIG_BASE64 }}
with:
command: |
export TOKEN=`aws ecr --region=us-east-2 get-authorization-token --output text --query authorizationData[].authorizationToken | base64 -d | cut -d: -f2`
aws eks update-kubeconfig --region us-east-2 --name foo-service-eks-foo
helm uninstall foo-service-pr --namespace ${{ env.GIT_BRANCH_NAME }}
kubectl delete namespace ${{ env.GIT_BRANCH_NAME }}
- name: Drop Temporary Database
if: always()
run: |
PGPASSWORD=${{ secrets.POSTGRES_PASSWORD }} psql -h ${{ env.POSTGRES_URL }} -U ${{ secrets.POSTGRES_USERNAME }} -d postgres -c "DROP DATABASE pr${{ github.sha }}"
echo "Database dropped."

--

--

Get the Medium app

A button that says 'Download on the App Store', and if clicked it will lead you to the iOS App store
A button that says 'Get it on, Google Play', and if clicked it will lead you to the Google Play store