Continuous Integration (CI) with GitHub Actions and Java Spring Boot
In today’s software development landscape, Continuous Integration and Continuous Delivery (CI/CD) have become essential for teams aiming to release code quickly, efficiently, and reliably. CI/CD automates and optimizes the software delivery process, allowing teams to focus on quality and iteration speed. When working with Java Spring Boot applications, integrating CI/CD through GitHub Actions is especially powerful. GitHub Actions not only offers seamless integration but also provides robust customization options for automated testing, building, and deployment.
This guide explores how to set up a CI pipeline using GitHub Actions for a Java Spring Boot project, creating a reliable, automated workflow that integrates code changes.
Table of Contents
- Why Use GitHub Actions for CI/CD with Java Spring Boot?
- Setting Up the Java Spring Boot Project
- Create a Spring Boot Project
- Configure the Build Tool
- Setting Up the GitHub Repository
- Create a Repository on GitHub
- Initialize a Local Git Repository
- Optional: Add `.gitignore` for Java Projects
- Verify Your Repository on GitHub
- Setting Up the GitHub Actions Workflow
- What Is GitHub Actions?
- Benefits of Using GitHub Actions
- Prerequisites for Setting Up GitHub Actions
- How GitHub Actions Work: Key Concepts
- Creating Your First Workflow
- Your First Workflow
- Suggested Improvements
- Test Phase
- Artifact Upload
- Enhanced Caching
- Static Code Analysis
- Deployment
- Final Enhanced Workflow Example
- Adding Security-Focused SCA to a CI/CD Workflow
- Integrating OWASP Dependency-Check
- Integrating SonarQube for Security Analysis
- Using Snyk for Dependency Security
- Integrating Secrets and Environment Variables
- Best Practices for GitHub Actions
- Common Issues and Troubleshooting
Why Use GitHub Actions for CI/CD with Java Spring Boot?
GitHub Actions allows developers to automate a range of tasks directly within GitHub repositories, making it an ideal tool for setting up CI/CD. Below, we’ll cover key reasons why GitHub Actions is particularly useful for Java Spring Boot applications:- Built-In Automation: GitHub Actions is embedded in the GitHub ecosystem, making it simple to set up and configure workflows that trigger based on repository events, such as code pushes or pull requests.
- Scalability: GitHub Actions can support projects of varying sizes, from simple workflows for small applications to complex pipelines that deploy to multiple environments.
- Reusable Workflows: You can create reusable workflows across multiple repositories, which is highly beneficial for teams managing multiple Spring Boot projects with similar CI/CD needs.
- Rich Marketplace of Actions: The GitHub Marketplace offers many pre-built actions for testing, building, deployment, and monitoring, reducing setup time and ensuring best practices.
Setting Up the Java Spring Boot Project
Before setting up CI/CD, you’ll need a Java Spring Boot project. Follow these steps to initialize it:Create a Spring Boot Project
Use Spring Initializr to set up the project:
- Choose Java as the language and Spring Boot as the framework.
- Select a stable version, typically the latest long-term support (LTS) release.
- Add dependencies, such as Spring Web (for REST APIs) and Spring Boot DevTools (for easier development and testing).
- Generate the project, download the `.zip` file, and extract it locally.
![]() |
Use Spring Initializr to set up the project |
Configure the Build Tool
Spring Boot supports both Maven and Gradle as build tools. Configure the dependencies as follows:
- Maven: In `pom.xml`, ensure you have the necessary dependencies, such as `spring-boot-starter-web`, `spring-boot-starter-test`, and other required libraries.
- Gradle: In `build.gradle`, set up the Spring Boot plugin and add necessary dependencies.
Example `pom.xml` Configuration for Maven:
<properties>
<java.version>17</java.version>
</properties>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
</plugins>
</build>
![]() |
Java project structure |
Setting Up the GitHub Repository
To share a Spring project on GitHub, follow these steps:Create a Repository on GitHub
- Log in to your [GitHub account](https://github.com).
- Click the + icon in the top-right corner and select New repository.
- Fill in the details:
- Repository name: Give it a name (e.g., `my-spring-project`).
- Visibility: Choose `Public` or `Private`.
- Leave Initialize this repository with a README** unchecked.
- Click Create repository.
![]() |
Create a Repository on GitHub |
![]() |
Repository on GitHub |
Set workflow permissions
- Go to Your Repository:
- Navigate to the repository where you want to configure workflow permissions.
- Access Repository Settings:
- Click on the Settings tab (found in the repository menu).
- Locate Actions Settings:
- Scroll down to Code and automation and select Actions.
- Set Workflow Permissions:
- Under the General section, look for Workflow permissions.
- Choose one following option:
- Read and write permissions: Grants workflows both read and write access to the repository's contents.
- Save Changes:
- Click Save to apply the new settings.
![]() |
Set workflow permissions |
Enable the Dependency Graph
- Ensure the Repository is Public (or Private with GitHub Advanced Security)
- The dependency graph is automatically enabled for public repositories.
- For private repositories, it requires GitHub Advanced Security (available for Enterprise and Team plans).
- Enabling the Dependency Graph
- Go to Your Repository:
- Open the repository for which you want to enable the dependency graph.
- Access Repository Settings:
- Click on the Settings tab in the repository menu.
- Enable Features:
- Scroll down to the Code and automation section and look for Dependency graph.
- If the feature is available but not enabled, click the button to activate it.
- Allow GitHub to Process Dependencies:
- If prompted, grant permission for GitHub to analyze your codebase for dependencies.
- This is often automatic if your repository includes supported dependency files (e.g., `package.json`, `requirements.txt`, `pom.xml`).
![]() |
Enable the Dependency Graph |
Initialize a Local Git Repository
Make sure your project is ready for version control:- Open a terminal in the root directory of your Spring project.
- Run the following commands to initialize a Git repository:
git clone https://github.com/<username>/my-spring-project.git
copy all files from demo.zip file to my-spring-project directory
git branch -M main
git add .
git commit -m "first commit"
git push -u origin main
3. Optional: Add `.gitignore` for Java Projects
Example `.gitignore` for a Spring project:
# Maven
target/
# IntelliJ IDEA
.idea/
*.iml
# Logs
*.log
# OS generated files
.DS_Store
Thumbs.db
Add it to your repository:
echo "/target/" >> .gitignore
git add .gitignore
git commit -m "Add .gitignore"
git push -u origin main
4. Verify Your Repository on GitHub
![]() |
Verify Your Repository on GitHub |
Setting Up the GitHub Actions Workflow
GitHub Actions provides a robust way to automate, build, test, and deploy your code directly from GitHub. Whether you're setting up a CI pipeline or running automated scripts, GitHub Actions can handle it all. This guide will walk you through the steps to set up a GitHub Actions workflow, highlight its key features, and provide tips for getting the most out of this powerful tool.What Is GitHub Actions?
GitHub Actions is an integrated CI/CD platform that allows developers to automate tasks such as testing, building, and deploying code. With its YAML-based configuration and tight integration into GitHub, it eliminates the need for external tools to manage workflows.Benefits of Using GitHub Actions
Here are some reasons why GitHub Actions has become the go-to choice for many developers:- Native Integration: Directly accessible within GitHub repositories.
- Customizable Workflows: Define workflows to suit any task, from linting to full-scale deployment.
- Reusable Components: Leverage a marketplace of pre-built actions or create your own.
- Parallelization: Execute tasks concurrently to save time.
- Multi-Platform Support: Run workflows on Linux, macOS, and Windows environments.
Prerequisites for Setting Up GitHub Actions
To get started, ensure you have the following:- GitHub repository where you'll set up workflows.
- Basic knowledge of YAML, the configuration language used in GitHub Actions.
- Appropriate repository access permissions for creating and editing workflows.
How GitHub Actions Work: Key Concepts
Before diving into workflow creation, it’s important to understand the building blocks of GitHub Actions:- Workflows: Defined in `.github/workflows` and specify automated tasks.
- Jobs: Units of work that run sequentially or in parallel within a workflow.
- Steps: Individual tasks executed in a job.
- Events: Triggers such as `push`, `pull_request`, or `schedule` that initiate workflows.
- Runners: Servers that execute the tasks in your workflows.
Creating Your First Workflow
- Open your repository on GitHub.
- Navigate to the Actions tab.
- Click New Workflow and select a template or create a blank file.
- Add your workflow code.
- Commit the file to the `.github/workflows` directory.
![]() |
Get started workflow page |
![]() |
Workflow file configuration |
Your First Workflow
You can extend your workflows by adding steps, such as:name: Java CI with Maven
Additionally, you can use pre-built actions from the [GitHub Marketplace](https://github.com/marketplace).
Update the main.yml workflow file and commit your changes. Following the commit, the workflow will trigger the build automatically.
![]() |
Successful build |
Suggested Improvements
Test Phase
Add a step to run tests explicitly before packaging:- name: Run tests
run: mvn test
Artifact Upload
Store build artifacts (e.g., JAR files) for use in other workflows or for debugging:Enhanced Caching
Use Maven’s cache more effectively by adding a fallback mechanism:Static Code Analysis
Integrate tools like Checkstyle or SpotBugs to maintain code quality:- name: Static Code Analysis
run: mvn checkstyle:check
Deployment
Include a deployment step for production or staging environments. For example, deploy a Dockerized app to a cloud registry:- name: Deploy Docker Image
run: |
docker build -t my-app:${{ github.sha }} .
docker tag my-app:${{ github.sha }} my-dockerhub-username/my-app:latest
docker push my-dockerhub-username/my-app:latest
Final Enhanced Workflow Example
Here’s the improved version of your workflow:Update pom.xml file of the Spring Boot application with the following:
Include the checkstyle.xml file in the root directory of the Spring Boot project:
<?xml version="1.0"?>
<!DOCTYPE module PUBLIC
"-//Checkstyle//DTD Checkstyle Configuration 1.3//EN"
"https://checkstyle.org/dtds/configuration_1_3.dtd">
<module name="Checker">
<!-- Charset of the source code -->
<property name="charset" value="UTF-8"/>
<!-- Maximum line length -->
<module name="LineLength">
<property name="max" value="120"/>
</module>
<module name="TreeWalker">
<!-- Code structure checks -->
<module name="PackageDeclaration"/>
<!-- Import declarations -->
<module name="AvoidStarImport"/>
<module name="UnusedImports"/>
<!-- Naming conventions -->
<module name="TypeName"/>
<module name="MethodName"/>
<module name="LocalVariableName"/>
<!-- Whitespace checks -->
<module name="WhitespaceAfter"/>
<module name="WhitespaceAround"/>
<module name="NoWhitespaceAfter"/>
<module name="NoWhitespaceBefore"/>
<!-- Blocks and braces -->
<module name="NeedBraces"/>
<module name="EmptyBlock">
<property name="option" value="text"/>
</module>
<!-- Javadoc checks -->
<module name="JavadocMethod"/>
<module name="JavadocType"/>
<module name="JavadocVariable"/>
<!-- Local variable final modifier check -->
<module name="FinalLocalVariable"/>
<!-- String literal equality check -->
<module name="StringLiteralEquality"/>
</module>
</module>
![]() |
Java project structure with checkstyle file |
push changes to GitHub repository:
git pull
git add .
git commit -m “Added checkstyle”
git push -u origin main
Following the commit, the workflow will trigger the build automatically.
![]() |
Build results with checkstyle plugin |
![]() |
Checkstyle results |
Adding Security-Focused SCA to a CI/CD Workflow
To add security-focused Static Code Analysis (SCA) checks to your CI/CD workflow, you can use tools like SonarQube, OWASP Dependency-Check, or Snyk. These tools identify potential vulnerabilities and security risks in your code or its dependencies.Integrating OWASP Dependency-Check
OWASP Dependency-Check is a widely used tool to identify vulnerable dependencies in your project.Add the Maven Plugin
Include the OWASP Dependency-Check plugin in your `pom.xml`:<build>
<plugins>
<plugin>
<groupId>org.owasp</groupId>
<artifactId>dependency-check-maven</artifactId>
<version>11.1.0</version>
<executions>
<execution>
<phase>verify</phase>
<goals>
<goal>check</goal>
</goals>
</execution>
</executions>
</plugin>
</plugins>
</build>
push changes to GitHub repository:
git pull
git add .
git commit -m “Added OWASP-Check”
git push -u origin main
Run Locally
Execute the following command to check for known vulnerabilities in your dependencies:mvn dependency-check:check
Add to GitHub Actions Workflow
Update your workflow file (`.github/workflows/ci.yml`) to include OWASP Dependency-Check:- name: OWASP Dependency-Check
![]() |
Build results with OWASP dependency check |
![]() |
OWASP dependency check |
Integrating SonarQube for Security Analysis
SonarQube is a comprehensive tool for analyzing code quality and identifying security vulnerabilities.Configure SonarQube
Set up a SonarQube server (cloud or self-hosted) and generate a project-specific token.Add SonarQube Plugin to `pom.xml`
Include the following configuration in your `pom.xml`:
<build>
<plugins>
<plugin>
<groupId>org.sonarsource.scanner.maven</groupId>
<artifactId>sonar-maven-plugin</artifactId>
<version>3.9.1.2184</version>
</plugin>
</plugins>
</build>
Run SonarQube Analysis Locally
Use the following command to scan your codebase:mvn sonar:sonar \
-Dsonar.projectKey=your_project_key \
-Dsonar.host.url=https://your-sonarqube-server-url \
-Dsonar.login=your_project_token
Add SonarQube to GitHub Actions Workflow
Update the workflow file:- name: SonarQube Analysis
run: mvn sonar:sonar \
-Dsonar.projectKey=${{ secrets.SONAR_PROJECT_KEY }} \
-Dsonar.host.url=${{ secrets.SONAR_HOST_URL }} \
-Dsonar.login=${{ secrets.SONAR_TOKEN }}
Using Snyk for Dependency Security
Snyk scans your dependencies for known vulnerabilities.Install Snyk CLI
Add the Snyk CLI as part of the workflow. Update `.github/workflows/ci.yml`:- name: Install Snyk
run: npm install -g snyk
Authenticate Snyk
Set up your Snyk API token in GitHub secrets and authenticate:- name: Authenticate Snyk
run: snyk auth ${{ secrets.SNYK_TOKEN }}
Run a Snyk Scan
Add a step to scan for vulnerabilities:- name: Snyk Vulnerability Scan
run: snyk test
These tools add security-focused SCA checks to your pipeline:
- Use OWASP Dependency-Check to identify vulnerable dependencies.
- Integrate SonarQube for in-depth security and code quality analysis.
- Use Snyk for real-time dependency scanning and vulnerability management.
Integrating Secrets and Environment Variables
Secrets, such as API keys or passwords, can be securely stored in GitHub and accessed in workflows:- Go to Settings > Secrets and Variables > Actions.
- Click New Repository Secret and add your secret.
env:
API_KEY: ${{ secrets.MY_API_KEY }}
run: curl -H "Authorization: Bearer $API_KEY" https://api.example.com/data
Best Practices for GitHub Actions
- Version Control for Actions: Use specific versions (e.g., `@v3`) to prevent breaking changes.
- Use Secrets Securely: Never hardcode sensitive information in workflows.
- Optimize Workflow Duration: Reduce unnecessary steps and leverage caching.
- Monitor Workflow Runs: Review logs and set up notifications for failures.
Common Issues and Troubleshooting
- Trigger Issues: Ensure the `on` triggers match your use case.
- Permission Denied Errors: Check token permissions in settings.
- Workflow Stalls: Split long-running jobs into smaller units for easier debugging.
Conclusion
GitHub Actions simplifies automation and CI pipelines, helping teams focus on writing code rather than managing workflows. Start with a basic workflow, explore advanced features, and customize workflows to suit your development needs.References
- GitHub Actions Documentation
- Spring Boot Documentation
- Building and Testing Java with Maven in GitHub Actions
- CI/CD Best Practices
- YAML Syntax for GitHub Actions
- GitHub Marketplace for Actions
- Spring Boot and GitHub Actions Tutorial
- Illustrations generated with the help of OpenAI's AI.
Your Feedback Matters!
Have ideas or suggestions? Follow the blog and share your thoughts in the comments.
About Me
I am passionate about IT technologies. If you’re interested in learning more or staying updated with my latest articles, feel free to connect with me on:
Feel free to reach out through any of these platforms if you have any questions!
Comments
Post a Comment