Introduction: Why CI/CD is a Must-Have for Java Developers
Modern Java development is unthinkable without automation. Manually running tests, building .jar files, and deploying to a server takes hours and leads to human errors. CI/CD (Continuous Integration / Continuous Deployment) solves this problem: every commit to the repository is automatically checked, built, and, if necessary, sent to production.
GitHub Actions is a built-in GitHub tool that allows you to create pipelines directly in the repository. It is free for public projects, easily integrates with Maven/Gradle, and supports Java 8–21. In this article, we will cover the full cycle: from a push trigger to publishing an artifact.
1. GitHub Actions Basics: Workflow Structure
A workflow is a YAML file located in .github/workflows/. It consists of:
- Triggers (push, pull_request, schedule);
- Jobs that run on virtual machines (runners);
- Steps within each job.
For a Java project, a typical workflow includes setting up the JDK, running Maven/Gradle tests, and building the artifact.
1.1. First Workflow: Testing a Java Project
Create a file .github/workflows/ci.yml with the following content:
name: Java CI
on: push: branches: [ "main" ] pull_request: branches: [ "main" ]
jobs: build: runs-on: ubuntu-latest
steps: - uses: actions/checkout@v4 - name: Set up JDK 17 uses: actions/setup-java@v4 with: java-version: '17' distribution: 'temurin' cache: maven - name: Build with Maven run: mvn -B package --file pom.xml - name: Run tests run: mvn testWhat happens here:
actions/checkout— clones the repository;setup-java— installs JDK 17 (Temurin) and caches Maven dependencies;mvn package— builds the project and runs tests;mvn test— explicitly runs tests (can be combined with package).
After pushing to main, you will see a green checkmark next to the commit — this means the pipeline ran successfully.
2. Advanced Setup for Java: Version Matrix and Caching
Real projects often require testing on multiple Java versions. GitHub Actions supports a matrix strategy.
2.1. JDK Matrix
jobs: test: runs-on: ubuntu-latest strategy: matrix: java: [11, 17, 21] steps: - uses: actions/checkout@v4 - name: Set up JDK ${{ matrix.java }} uses: actions/setup-java@v4 with: java-version: ${{ matrix.java }} distribution: 'temurin' cache: maven - run: mvn testThis approach ensures your code is compatible with LTS versions of Java. The jobs run in parallel, saving time.
2.2. Dependency Caching
We already specified cache: maven — this automatically caches ~/.m2/repository. For Gradle, use cache: gradle. Caching speeds up the build by 2–3 times.
3. Building and Publishing Artifacts (JAR/Docker)
After successful testing, you need to get a ready artifact. Let's look at two popular scenarios.
3.1. Uploading a JAR File to GitHub Artifacts
jobs: build: runs-on: ubuntu-latest steps: - uses: actions/checkout@v4 - name: Set up JDK 17 uses: actions/setup-java@v4 with: java-version: '17' distribution: 'temurin' - run: mvn clean package - name: Upload JAR uses: actions/upload-artifact@v4 with: