Skip to main content
Advertisement

18.2 Automated CI/CD with GitHub Actions

GitHub Actions automates the full pipeline — test → Docker image build → EC2 deploy — on every push to main.

1. CI Pipeline (.github/workflows/ci.yml)

name: CI - Test and Build

on:
push:
branches: [ main, develop ]
pull_request:
branches: [ main ]

jobs:
test:
runs-on: ubuntu-latest
services:
mysql:
image: mysql:8.0
env:
MYSQL_ROOT_PASSWORD: test
MYSQL_DATABASE: testdb
ports:
- 3306:3306
options: --health-cmd="mysqladmin ping" --health-interval=5s

steps:
- uses: actions/checkout@v4
- name: Set up JDK 21
uses: actions/setup-java@v4
with:
java-version: '21'
distribution: 'temurin'
cache: 'gradle'
- name: Run Tests
run: ./gradlew test
env:
SPRING_DATASOURCE_URL: jdbc:mysql://localhost:3306/testdb
SPRING_DATASOURCE_PASSWORD: test

2. CD Pipeline — Docker Build and EC2 Deploy

  deploy:
needs: test
runs-on: ubuntu-latest
if: github.ref == 'refs/heads/main'

steps:
- uses: actions/checkout@v4
- name: Login to Docker Hub
uses: docker/login-action@v3
with:
username: ${{ secrets.DOCKERHUB_USERNAME }}
password: ${{ secrets.DOCKERHUB_TOKEN }}
- name: Build and push Docker image
run: |
docker build -t ${{ secrets.DOCKERHUB_USERNAME }}/todo-app:${{ github.sha }} .
docker push ${{ secrets.DOCKERHUB_USERNAME }}/todo-app:${{ github.sha }}
- name: Deploy via SSH to EC2
uses: appleboy/ssh-action@v1.0.3
with:
host: ${{ secrets.EC2_HOST }}
username: ubuntu
key: ${{ secrets.EC2_PRIVATE_KEY }}
script: |
docker pull ${{ secrets.DOCKERHUB_USERNAME }}/todo-app:${{ github.sha }}
docker stop todo-app || true
docker rm todo-app || true
docker run -d --name todo-app -p 8080:8080 \
-e SPRING_DATASOURCE_URL=${{ secrets.DB_URL }} \
-e SPRING_DATASOURCE_PASSWORD=${{ secrets.DB_PASSWORD }} \
${{ secrets.DOCKERHUB_USERNAME }}/todo-app:${{ github.sha }}

Store sensitive values in Repository Settings → Secrets and variables → Actions and reference them safely as ${{ secrets.XXX }}.

Advertisement