This post shows how to create workflows that package Java application with Maven and then store it as an artifact or publish to GitHub Packages.
In the previous post we described GitHub Actions and how they work, so if you need a quick reminder on the jobs, steps and syntax check it out.
Development environment
On the following link you can find repository with the source code. It's a simple Spring Boot application that returns students from the database. The application was bootstrapped using Spring Initializr. For the dependencies we added Spring Web
which is used for building web applications using Spring MVC. This package also uses Apache Tomcat as the default embedded container. We also used Spring Data JDBC
for persisting data in SQL with plain JDBC and PostgreSQL Driver
that allows Java programs to connect to a Postgres database using standard, database independent Java code.
For local development, we can easily start Postgres instance with Docker by using the following command:
docker run -d --name postgresDB -p <port>:5432 -e POSTGRES_PASSWORD=<YourPassword>-v /postgresdata:/var/lib/postgresql/data postgres:latest
Spring Boot follows a layered architecture in which each layer communicates with the layer directly below or above it. We followed that practice and implemented Controller, Service and Repository inside our application and demonstrated dependency injection principles. Source code also contains StudentConfig
class which simply inserts student in database.
After successfully setting up development environment and writing some code we decided to push our work into the source control management system, in this case GitHub. Now we need to build the code and publish it as a Maven package. This process can be done manually, but we would like to do it automatically when changes are merged into the main
branch. In this way we will avoid manual tasks when publishing a new version.
Like most other things, this problem can be solved in several ways, and we will use two different approaches. Firstly, we will publish our package as an build artifact and make it available for download, while in the second approach we will publish package to the GitHub Packages Maven repository.
Storing workflow data as artifacts
In the main.yaml
file first couple of lines tell us which events will start the workflow. Except push and pull request on the main branch we also added workflow_dispatch
tag to enable manual workflow run.
Under the jobs section we defined build
job that will be executed on the Ubuntu runner. First two steps checkout main branch from GitHub and set up JDK (Java Development Kit).
Next up, we build the project and set up a cache for Maven:
- name: Build Maven project
run: |
mvn -B package --file pom.xml -Dmaven.test.skip
mkdir staging && cp target/*.jar staging
- name: Set up a cache for Maven
uses: actions/cache@v2
with:
path: ~/.m2
key: ${{ runner.os }}-m2-${{ hashFiles('**/pom.xml') }}
restore-keys: ${{ runner.os }}-m2
Once the build is completed, staging directory will contain produced .jar file. Each job in a workflow runs in a fresh virtual environment which means that once the build
job is done we cannot access that environment and our .jar file is gone. That's where our last step comes in place which uploads artifacts from your workflow allowing you to share data between jobs and store data once a workflow is complete.
- name: Persist workflow data as artifacts
uses: actions/upload-artifact@v2
with:
name: github-actions-artifact
path: staging
By default, the artifacts generated by workflows are retained for 90 days before they are automatically deleted. You can adjust the retention period, depending on the type of repository. When you customize the retention period, it only applies to new artifacts and does not retroactively apply to existing objects.
Artifacts can be found under the Actions tab when you click on the desired workflow run.
Publishing to the GitHub Packages
You can configure Apache Maven to publish packages to GitHub Packages and to use packages stored on GitHub Packages as dependencies in a Java project.
Beside Maven, GitHub Packages offers different package registries for commonly used package managers like npm, NuGet, Gradle and RubyGems. It's also possible to store Docker and other OCI images. With all these features you can create end-to-end DevOps solutions and centralize your software development on GitHub.
In maven-publish.yaml
file you can find workflow details for publishing package to the GitHub Packages. Just like in the previous solution we provide name and events that will trigger workflow run. Next, under the jobs section we selected Ubuntu runner as environment for the publish
job and defined permissions to read the content and write packages.
name: Publish package to GitHub Packages
on:
push:
branches: [main]
jobs:
publish:
runs-on: ubuntu-latest
permissions:
contents: read
packages: write
In the following steps we checkout the main branch and set up JDK with java-version
parameter. The last step is publishing the package and it needs personal access token for the authentication. PAT is a sensitive information and we don't want to store it as a plain text, so we defined the secret on the repository level and accessed it as an environment variable. For simplicity we skipped the tests during deployment.
- name: Publish package
run: mvn --batch-mode deploy -Dmaven.test.skip
env:
GITHUB_TOKEN: ${{ secrets.TOKEN }}
Before running the workflow we also need one configuration change in the application source code. Inside pom.xml
file we need to pass information about package distribution management.
<project ...>
...
<distributionManagement>
<repository>
<id>github</id>
<name>GitHub Packages</name>
<url>https://maven.pkg.github.com/cvitaa11/java-spring-demo</url>
</repository>
</distributionManagement>
</project>
After pushing changes to the main branch workflow starts automatically and we can follow the log output under the Actions tab on the repository page. When all steps are completed we can see Maven package, ready for use, in our code repository under the Packages section.
With these two approaches, we have successfully solved the problem of automatic publish of Java applications as Maven packages and demonstrated use of GitHub Actions and GitHub Packages to create complete end-to-end development solution in one place.
Top comments (0)