CI and CD with GitHub Actions

The Pipeline

git push main
   |
   v
GitHub Actions: checkout -> set up JDK 21 -> ./mvnw verify (tests) -> build Docker image -> push to registry
   |
   v
deploy job: pull new image on the server / update cloud service -> health check -> done (or roll back)

Workflow File

Example

.github/workflows/ci.yml

name: shopease-ci

on:
  push:
    branches: [main]
  pull_request:

jobs:
  build:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
      - uses: actions/setup-java@v4
        with:
          distribution: temurin
          java-version: '21'
          cache: maven
      - name: Test and package
        run: ./mvnw -B verify
      - name: Log in to GHCR
        if: github.ref == 'refs/heads/main'
        uses: docker/login-action@v3
        with:
          registry: ghcr.io
          username: ${{ github.actor }}
          password: ${{ secrets.GITHUB_TOKEN }}
      - name: Build and push image
        if: github.ref == 'refs/heads/main'
        uses: docker/build-push-action@v6
        with:
          context: .
          push: true
          tags: ghcr.io/${{ github.repository }}:${{ github.sha }}

  deploy:
    needs: build
    if: github.ref == 'refs/heads/main'
    runs-on: ubuntu-latest
    steps:
      - name: Deploy over SSH
        uses: appleboy/ssh-action@v1
        with:
          host: ${{ secrets.VM_HOST }}
          username: deploy
          key: ${{ secrets.VM_SSH_KEY }}
          script: |
            cd /opt/shopease
            IMAGE_TAG=${{ github.sha }} docker compose pull app
            IMAGE_TAG=${{ github.sha }} docker compose up -d app
            sleep 20
            curl -fs localhost:8080/actuator/health

Tip: Pull requests run only the tests; images are built and deployed only from main. Protect main so every change needs a green build.

Practice

Exercise: Add a step to the build job that fails the pipeline if test coverage is below 70% using the JaCoCo Maven plugin (already configured with a check rule).

Show answer
- name: Coverage gate
        run: ./mvnw -B jacoco:report jacoco:check