GitHub Actions provide a seamless way to integrate CI/CD into your repository, automating various tasks like running tests, building artifacts, and deploying your project.
Workflow for SNAPSHOT
This workflow is triggered on non-main branches or manually through the workflow dispatch event. It includes the following steps:
- Run tests: Ensures that your code passes all tests.
- Build the JAR file: Compiles your Spring Boot application.
- Build Docker image and push it to GitHub Docker Registry: Creates a Docker image from the generated artifact and pushes it to the GitHub Container Registry.
name: Test and Build Snapshot
on:
push:
branches-ignore:
- main
workflow_dispatch:
permissions:
contents: read
packages: write
jobs:
maven-verify:
if: "!contains(github.event.head_commit.message, '[skip ci]')"
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: Set up JDK 21
uses: actions/setup-java@v4
with:
java-version: '21'
distribution: 'temurin'
cache: maven
cache-dependency-path: '**/pom.xml'
- name: Verify
run: mvn -B clean verify --file pom.xml
maven-build:
needs: maven-verify
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: Set up JDK 21
uses: actions/setup-java@v4
with:
java-version: '21'
distribution: 'temurin'
cache: maven
cache-dependency-path: '**/pom.xml'
- name: Build
run: mvn -B package --file pom.xml
- name: Upload artifact
uses: actions/upload-artifact@v4
with:
name: app.jar
path: target/*.jar
docker-build-push:
needs: maven-build
runs-on: ubuntu-latest
env:
CURRENT_VERSION: ''
steps:
- uses: actions/checkout@v4
- name: Download artifact
uses: actions/download-artifact@v4
with:
name: app.jar
path: target
- name: Set up Docker Buildx
uses: docker/setup-buildx-action@v3
- name: Log in to GitHub Container Registry
uses: docker/login-action@v3
with:
registry: ghcr.io
username: ${{ github.repository_owner }}
password: ${{ secrets.GHCR_PAT }}
- name: Get Version
run: echo "CURRENT_VERSION=$(mvn help:evaluate -Dexpression=project.version -q -DforceStdout)" >> $GITHUB_ENV
- name: Build Docker image
uses: docker/build-push-action@v6
with:
context: .
push: true
tags: ghcr.io/${{ github.repository_owner }}/${{ github.event.repository.name }}:${{ env.CURRENT_VERSION }}-${{ github.run_id }}
Workflow for RELEASE
This workflow runs when changes are pushed to the main
branch and includes the following steps:
- Build the release version: Compiles the release version of your project.
- Build Docker image and push it to GitHub Docker Registry: Creates and pushes the Docker image to the GitHub Container Registry.
- Increment SNAPSHOT version: Updates the version in
pom.xml
for future snapshot versions.
name: Build Release
on:
push:
branches:
- main
workflow_dispatch:
permissions:
contents: read
packages: write
jobs:
maven-build-release:
if: "!contains(github.event.head_commit.message, '[skip ci]')"
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: Set up JDK 21
uses: actions/setup-java@v4
with:
java-version: '21'
distribution: 'temurin'
cache: maven
cache-dependency-path: '**/pom.xml'
- name: Prepare Release Version
run: mvn versions:set -DremoveSnapshot
- name: Build
run: mvn -B clean package --file pom.xml -DskipTests
- name: Upload artifact
uses: actions/upload-artifact@v4
with:
name: app.jar
path: target/*.jar
docker-build-push:
needs: maven-build-release
runs-on: ubuntu-latest
env:
CURRENT_VERSION: ''
steps:
- uses: actions/checkout@v4
- name: Download artifact
uses: actions/download-artifact@v4
with:
name: app.jar
path: target
- name: Set up Docker Buildx
uses: docker/setup-buildx-action@v3
- name: Log in to GitHub Container Registry
uses: docker/login-action@v3
with:
registry: ghcr.io
username: ${{ github.repository_owner }}
password: ${{ secrets.GHCR_PAT }}
- name: Get Version
run: |
mvn versions:set -DremoveSnapshot
echo "CURRENT_VERSION=$(mvn help:evaluate -Dexpression=project.version -q -DforceStdout)" >> $GITHUB_ENV
- name: Build Docker image
uses: docker/build-push-action@v6
with:
context: .
push: true
tags: ghcr.io/${{ github.repository_owner }}/${{ github.event.repository.name }}:${{ env.CURRENT_VERSION }}-${{ github.run_id }}
increment-version:
needs: docker-build-push
runs-on: ubuntu-latest
permissions:
contents: write
steps:
- uses: actions/checkout@v4
with:
token: ${{ secrets.GIT_PAT }}
- name: Configure Git
run: |
git config --global user.name "github-actions[bot]"
git config --global user.email "github-actions[bot]@users.noreply.github.com"
- name: Increment Snapshot Version
run: |
# Extract current version and increment patch version
CURRENT_VERSION=$(mvn help:evaluate -Dexpression=project.version -q -DforceStdout)
MAJOR=$(echo $CURRENT_VERSION | cut -d. -f1)
MINOR=$(echo $CURRENT_VERSION | cut -d. -f2)
PATCH=$(echo $CURRENT_VERSION | cut -d. -f3 | cut -d- -f1)
NEW_PATCH=$((PATCH + 1))
NEW_VERSION="$MAJOR.$MINOR.$NEW_PATCH-SNAPSHOT"
# Update version in pom.xml
mvn versions:set -DnewVersion=$NEW_VERSION
mvn versions:commit
# Commit and push the new snapshot version
git add pom.xml
git commit -m "Increment version to $NEW_VERSION [skip ci]"
git push origin $(git rev-parse --abbrev-ref HEAD)
Bonus workflow
The CodeQL workflow analyzes your Java code to identify potential vulnerabilities and issues.
name: CodeQL
on:
pull_request:
branches: [ "main" ]
workflow_dispatch:
jobs:
analyze:
name: Analyze
runs-on: ubuntu-latest
permissions:
actions: read
contents: read
security-events: write
strategy:
fail-fast: false
matrix:
language: [ 'java' ]
steps:
- name: Checkout repository
uses: actions/checkout@v4
- name: Setup Java
uses: actions/setup-java@v4
with:
java-version: '21'
distribution: 'temurin'
cache: maven
cache-dependency-path: '**/pom.xml'
- name: Initialize CodeQL
uses: github/codeql-action/init@v3
with:
languages: ${{ matrix.language }}
- name: Autobuild
uses: github/codeql-action/autobuild@v3
- name: Perform CodeQL Analysis
uses: github/codeql-action/analyze@v3
with:
category: "/language:${{matrix.language}}"
Updated Dockerfile
### Build stage
FROM eclipse-temurin:21-jre-alpine AS builder
# Set the working directory inside the container
WORKDIR /tmp
# Copy the source code into the container
COPY target/*.jar app.jar
# Extract the layers
RUN java -Djarmode=layertools -jar app.jar extract
### Run stage
# Create a minimal production image
FROM eclipse-temurin:21-jre-alpine
# Set the working directory inside the container
WORKDIR /app
# Set the working directory inside the container
COPY --from=builder /tmp/dependencies/ ./
COPY --from=builder /tmp/snapshot-dependencies/ ./
COPY --from=builder /tmp/spring-boot-loader/ ./
COPY --from=builder /tmp/application/ ./
# Run the binary when the container starts
ENTRYPOINT ["java", "org.springframework.boot.loader.launch.JarLauncher"]
Top comments (0)