Travis and Spring Boot

By

Feb 11, 2022

Contents

In this series of tech blog Friday by Montana Mendy, we will learn how to run maven build goals, perform test coverage validation whether this be Coveralls, SonarCloud or Docker. Are you ready? I’m ready. Let’s jump in.

Getting started

There’s choices and choices. In this example I’ll be using Maven, but you can obviously use Gradle as well. Next, you’ll want to create a SpringBoot project either using http://start.spring.io or alternatively use your IDE.

Create your .travis.yml file

We have to enable your .travis.yml file and the way we do that is by the following:

language: java
jdk: oraclejdk8

Now this just invokes Travis into your project, this is sufficient enough for Travis to see that there’s a build that needs to be triggered, how Travis is architected Travis will run mvn test -B for building the project. If Travis finds mvnw wrapper then it will be used like ./mvnw test -B. as you can see it’s a bit recursive. You can instruct Travis to run different commands in your script: hook in your .travis.yml.

Adding Coverage Checks for Travis

Add the Maven specific JaCoCo plugin to pom.xml with flags that define what is the desired code coverage percentage, classes, etc:

<Plugin>
    <GroupId>org.jacoco</GroupId>
    <ArtifactId>jacoco-maven-plugin</ArtifactId>
    <Version>0.7.9</Version>
    <Configuration>
        <Excludes>
            <Exclude>in/sivalabs/freelancerkit/entities/*</Exclude>
            <Exclude>in/sivalabs/freelancerkit/*Application</Exclude>
        </Excludes>
    </Configuration>
    <Executions>
        <Execution>
            <Id>default-prepare-agent</Id>
            <Goals>
                <Goal>prepare-agent</Goal>
            </Goals>
        </Execution>
        <Execution>
            <Id>default-prepare-agent-integration</Id>
            <Goals>
                <Goal>prepare-agent-integration</Goal>
            </Goals>
        </Execution>
        <Execution>
            <Id>default-report</Id>
            <Phase>verify</Phase>
            <Goals>
                <Goal>report</Goal>
            </Goals>
        </Execution>
        <Execution>
            <Id>default-report-integration</Id>
            <Goals>
                <Goal>report-integration</Goal>
            </Goals>
        </Execution>
        <Execution>
            <Id>default-check</Id>
            <Goals>
                <Goal>check</Goal>
            </Goals>
            <Configuration>
                <Rules>
                 <Rule Implementation="Org.Jacoco.Maven.RuleConfiguration">
                        <Element>BUNDLE</Element>
                        <Limits>
                            <Limit Implementation="Org.Jacoco.Report.Check.Limit">
                                <Counter>COMPLEXITY</Counter>
                                <Value>COVEREDRATIO</Value>
                                <Minimum>0.60</Minimum>
                            </Limit>
                        </Limits>
                    </Rule>
                </Rules>
            </Configuration>
        </Execution>
    </Executions>
</Plugin>

Classifiers

To fix the classifier issue, the workaround is to add the classifier configuration to spring-boot-maven-plugin as follows:

<Plugin>
    <GroupId>org.springframework.boot</GroupId>
    <ArtifactId>spring-boot-maven-plugin</ArtifactId>
    <Configuration>
        <Classifier>exec</Classifier>
    </Configuration>
</Plugin>

Now let’s take a look at our travis.yml file, and be on the lookout for the script: hook:

language: java
jdk: oraclejdk8
  
script:
- ./mvnw clean install -B

You can see in our script: hook we’ve added ./mvnw vlean install -B and that’s going to be key. Now let’s get a .travis.yml that has SonarCloud. Now remember to set your environment variables you grabbed from SonarCloud and also add them to Travis, here’s a .travis.yml demonstrating this:

language: java
jdk: oraclejdk8
  
env:
  global:
  - secure: (ENV_VARS_HERE)
  
addons:
  sonarcloud:
    organization: "montanamendy-from-travis"
    token:
      secure: $SONAR_TOKEN
  
script:
- ./mvnw clean install -B
- ./mvnw clean org.jacoco:jacoco-maven-plugin:prepare-agent package sonar:sonar

Now let’s build a Dockerfile that mirrors essentially that .travis.yml:

ROM frolvlad/alpine-oraclejdk8:slim
VOLUME /tmp
ADD target/freelancer-kit-0.0.1-SNAPSHOT.jar app.jar
RUN sh -c 'touch /app.jar'
ENV JAVA_OPTS="-Xdebug -Xrunjdwp:server=y,transport=dt_socket,address=8787,suspend=n"
EXPOSE 8080 8787
ENTRYPOINT [ "sh", "-c", "java $JAVA_OPTS -Djava.security.egd=file:/dev/./urandom -Dspring.profiles.active=docker -jar /app.jar" ]

That Dockerfile is going to grab alpine-oraclejdk8:slim the slim flag is making sure it’s grabbinb the slim version.

Deploying

Now let’s say you’re using Heroku for deployment, you’ll need to grab all those credentials as well and add them to your deploy: hook. We can add your Heroku key and secrets by running the following command in the CLI:

travis encrypt HEROKU_API_KEY=”HEROKU_KEY"

You’ll now want to add the following to your .travis.yml:

deploy:
  provider: heroku
  api_key: $HEROKU_API_KEY
  app: montana

Now that you’ve added your Heroku secrets, it’s time to see the final .travis.yml:

sudo: required
language: java
jdk: oraclejdk8
  
services:
- docker
  
env:
  global:
  - secure: "encrypted-sonar-token"
  - secure: "encrypted-dockerhub-username"
  - secure: "encrypted-dockerhub-password"
  - secure: "encrypted-heroku-api-key"
  - COMMIT=${TRAVIS_COMMIT::7}
  
addons:
  sonarcloud:
    organization: "montanamendy-travis"
    token:
      secure: $SONAR_TOKEN
  
script:
- ./mvnw clean install -B
- ./mvnw clean org.jacoco:jacoco-maven-plugin:prepare-agent package sonar:sonar
  
after_success:
- docker login -u $DOCKER_USER -p $DOCKER_PASS
- export TAG=`if [ "$TRAVIS_BRANCH" == "master" ]; then echo "latest"; else echo $TRAVIS_BRANCH&amp;amp;amp;amp;amp;amp;lt;span data-mce-type="bookmark" style="display: inline-block; width: 0px; overflow: hidden; line-height: 0;" class="mce_SELRES_start"&amp;amp;amp;amp;amp;amp;gt;&amp;amp;amp;amp;amp;amp;lt;/span&amp;amp;amp;amp;amp;amp;gt;; fi`
- export IMAGE_NAME=sivaprasadreddy/freelancer-kit
- docker build -t $IMAGE_NAME:$COMMIT .
- docker tag $IMAGE_NAME:$COMMIT $IMAGE_NAME:$TAG
- docker push $IMAGE_NAME
  
deploy:
  provider: heroku
  api_key: $HEROKU_API_KEY
  app: montanamendy-from-travis

If all is successful, you should see this in your Travis build log:

153654615 eeb8a300 5b0b 4c74 8de5 a61b965b8199

Conclusion

There you go, we just used unit testing, Spring Boot and Travis CI into our project. The integration was kind of easy wasn’t it?

As always if you have any questions, any questions at all, please email me at [email protected].

Happy building!

Written By

Reviewed By