What We're Building
A complete CI/CD pipeline that:
- Runs tests on every PR
- Builds a Docker image on merge to
main - Pushes to Azure Container Registry
- Deploys to Azure Container Apps
The Workflow File
Create .github/workflows/ci-cd.yml:
name: CI/CD Pipeline
on:
push:
branches: [main]
pull_request:
branches: [main]
jobs:
test:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: actions/setup-java@v4
with:
distribution: 'temurin'
java-version: '21'
cache: 'maven'
- run: mvn verify
build-and-deploy:
needs: test
if: github.ref == 'refs/heads/main'
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: actions/setup-java@v4
with:
distribution: 'temurin'
java-version: '21'
cache: 'maven'
- run: mvn package -DskipTests
- uses: azure/docker-login@v1
with:
login-server: $
username: $
password: $
- run: |
docker build -t $/myapp:$ .
docker push $/myapp:$
Dockerfile
FROM eclipse-temurin:21-jre-alpine
WORKDIR /app
COPY target/*.jar app.jar
EXPOSE 8080
ENTRYPOINT ["java", "-jar", "app.jar"]
Setting Up Secrets
Go to your repo → Settings → Secrets and variables → Actions:
| Secret | Value |
|---|---|
ACR_LOGIN_SERVER |
myregistry.azurecr.io |
ACR_USERNAME |
Service principal app ID |
ACR_PASSWORD |
Service principal secret |
Pro Tips
- Cache Maven dependencies — the
cache: 'maven'option saves 2-3 minutes per build - Use matrix builds to test on Java 17 and 21 simultaneously
- Add a
concurrencygroup to cancel outdated deployments - Never skip tests in CI — if they're too slow, fix them, don't skip them
This pipeline handles 90% of Spring Boot deployment needs. Extend it with integration tests, security scanning, and blue-green deployments as you scale.