Skip to content
Latchkey

CI/CD for a Java + Spring App with Kafka and GitHub Actions

Build with Maven and run Spring tests against a real Kafka broker on every push.

This recipe tests a Spring Boot service that produces and consumes Kafka messages. CI runs the Maven build against a Kafka service container so integration tests exercise a real broker, then packages the jar.

What the pipeline does

  • set up the JDK with Maven cache
  • start a Kafka (KRaft) service container
  • run mvn verify against the broker
  • package the runnable jar
  • upload the jar artifact

The workflow

A single-node Kafka in KRaft mode backs the integration tests. SPRING_KAFKA_BOOTSTRAP_SERVERS points the app at the service container.

.github/workflows/ci.yml
name: CI
on:
  push:
    branches: [main]
  pull_request:
jobs:
  build:
    runs-on: ubuntu-latest
    services:
      kafka:
        image: apache/kafka:3.7.0
        ports: ["9092:9092"]
        options: >-
          --health-cmd "/opt/kafka/bin/kafka-topics.sh --bootstrap-server localhost:9092 --list"
          --health-interval 10s --health-timeout 5s --health-retries 10
    env:
      SPRING_KAFKA_BOOTSTRAP_SERVERS: localhost:9092
    steps:
      - uses: actions/checkout@v4
      - uses: actions/setup-java@v4
        with:
          distribution: temurin
          java-version: "21"
          cache: maven
      - run: mvn -B verify
      - uses: actions/upload-artifact@v4
        with:
          name: app-jar
          path: target/*.jar

Caching and speed

setup-java with cache: maven restores ~/.m2 keyed on pom.xml. Spring context startup plus Kafka integration tests are slow; cheaper managed runners such as Latchkey (around 69% cheaper than GitHub-hosted) keep the suite fast and auto-retry a flaky broker image pull.

Deploying

The runnable jar is the deploy artifact. Add a deploy job that builds a Docker image around it (FROM eclipse-temurin:21-jre) and pushes to your registry, or deploys the jar to your container platform once verify passes on main.

Key takeaways

  • Use a Kafka KRaft service container so integration tests hit a real broker.
  • Point SPRING_KAFKA_BOOTSTRAP_SERVERS at the service in CI.
  • Cache ~/.m2 to avoid re-downloading the dependency tree.

Related guides

Run this faster and cheaper on Latchkey managed runners. Start free →