Setup Docker build and deployment + Jenkinsfile #3
nclazz/nclazz-mail-relay/pipeline/head There was a failure building this commit Details

pull/21/head
Niclas Thobaben 2022-02-15 14:23:57 +01:00
parent 48d5a75b6d
commit db40d40305
7 changed files with 572 additions and 0 deletions

25
Dockerfile 100644
View File

@ -0,0 +1,25 @@
# Multi-Stage-Build builder
# Extract layers from application to minimize image size
FROM adoptopenjdk/openjdk11:alpine-slim AS builder
WORKDIR application
ARG JAR_FILE=target/*.jar
COPY ${JAR_FILE} application.jar
RUN java -Djarmode=layertools -jar application.jar extract
# Build the actual image
FROM adoptopenjdk/openjdk11:alpine-slim
WORKDIR /application
COPY --from=builder application/dependencies/ ./
COPY --from=builder application/spring-boot-loader/ ./
COPY --from=builder application/snapshot-dependencies/ ./
COPY --from=builder application/application/ ./
EXPOSE 8080
ENV JAVA_OPTIONS=""
HEALTHCHECK --interval=30s --timeout=30s --retries=3 \
CMD wget --no-verbose --spider http://localhost:8080/actuator/health || exit 1
CMD ["java", "org.springframework.boot.loader.JarLauncher", "-XX:+UseSerialGC", "-XX:MaxRAM=256m", "${JAVA_OPTIONS}" ]

144
Jenkinsfile vendored 100644
View File

@ -0,0 +1,144 @@
pipeline {
agent any
environment {
NEXUS = credentials('jenkins_nexus')
DOCKER_REGISTRY = "docker.nclazz.de"
DOCKER_GROUP = 'nclazz-service'
DOCKER_IMAGE = 'mail-relay'
DOCKER_TAG = "${ BRANCH_NAME == "master" ? "latest" : "develop" }"
DOCKER_VERSION = "0.0.1-SNAPSHOT"
DEPLOY_ENV = "${ BRANCH_NAME == "master" ? "production" : "staging" }"
}
options {
timeout(time: 30, unit: "MINUTES")
}
parameters {
booleanParam(name: 'RUN_INTEGRATION', defaultValue: false, description: 'Run integration tests.')
booleanParam(name: 'RUN_DEPLOYMENT', defaultValue: false, description: 'Run deployment to staging or production environment.')
}
stages {
stage('Run Maven') {
agent {
docker 'maven:3.8.3-openjdk-11'
}
stages {
stage('Run Maven Build') {
steps {
sh 'mvn install -DskipTests -B -s settings.xml'
stash includes: '**/target/*.jar', name: 'BUILD_ARTIFACTS'
}
}
stage('Run All Tests') {
steps {
sh 'mvn test -P test -B -s settings.xml'
}
}
}
post {
always {
junit(
allowEmptyResults: true,
testResults: '**/target/surefire-reports/*.xml, **/target/failsafe-reports/*.xml'
)
jacoco(
changeBuildStatus: true,
exclusionPattern: '**/*Application.class, ' +
'**/*Configuration.class',
minimumInstructionCoverage: env.MIN_INSTRUCTION_COVERAGE,
maximumInstructionCoverage: env.MAX_INSTRUCTION_COVERAGE,
minimumClassCoverage: env.MIN_CLASS_COVERAGE,
maximumClassCoverage: env.MAX_CLASS_COVERAGE
)
recordIssues(
enabledForFailure: true,
aggregatingResults: true,
tools: [java(), checkStyle(), findBugs(pattern: '**/target/spotbugsXml.xml')]
)
}
}
}
stage('Run Docker Builds') {
agent { label 'docker' }
when {
anyOf {
branch 'master'
branch 'develop'
}
}
steps {
unstash 'BUILD_ARTIFACTS'
script {
docker.withRegistry("https://$DOCKER_REGISTRY", "jenkins_nexus") {
def apiImage = docker.build("$DOCKER_GROUP/$DOCKER_IMAGE")
apiImage.push("${env.DOCKER_VERSION}")
apiImage.push("${env.DOCKER_TAG}")
}
}
}
}
stage('Run Deployment') {
agent { label 'provision' }
when {
allOf {
anyOf {
branch 'master'
branch 'develop'
expression { return params.RUN_DEPLOYMENT }
}
}
}
steps {
deployToSwarm(
name: 'nclazz-mail-relay',
file: "${env.WORKSPACE}/docker-compose.yml",
forceUpdate: true,
askApproval: !params.RUN_DEPLOYMENT,
slackChannel: 'deployment',
env: [
PORT: 7006,
VERSION: env.DOCKER_VERSION
]
)
exposeService(
name: 'nclazz-email-relay',
fqdn: 'api.nclazz.de',
description: 'nclazz email relay service',
location: '/mail',
backendPort: 7006
)
}
}
}
post {
always {
cleanWs()
}
failure {
slackSend(
channel: "notifications",
color: "danger",
message: "There is a *build failure* in ${env.JOB_NAME}.\nBuild: ${env.RUN_DISPLAY_URL} "
)
}
unstable {
slackSend(
channel: "notifications",
color: "warning",
message: "Some tests have failed in ${env.JOB_NAME}.\nBuild: ${env.RUN_DISPLAY_URL} "
)
}
fixed {
slackSend(
channel: "notifications",
color: "good",
message: "The build ${env.JOB_NAME} completed successfully and is back to normal.\nBuild: ${env.RUN_DISPLAY_URL} "
)
}
}
}

193
checkstyle.xml 100644
View File

@ -0,0 +1,193 @@
<?xml version="1.0"?>
<!DOCTYPE module PUBLIC
"-//Checkstyle//DTD Checkstyle Configuration 1.3//EN"
"https://checkstyle.org/dtds/configuration_1_3.dtd">
<!--
Checkstyle configuration that checks the sun coding conventions from:
- the Java Language Specification at
https://docs.oracle.com/javase/specs/jls/se11/html/index.html
- the Sun Code Conventions at https://www.oracle.com/java/technologies/javase/codeconventions-contents.html
- the Javadoc guidelines at
https://www.oracle.com/technical-resources/articles/java/javadoc-tool.html
- the JDK Api documentation https://docs.oracle.com/en/java/javase/11/
- some best practices
Checkstyle is very configurable. Be sure to read the documentation at
https://checkstyle.org (or in your downloaded distribution).
Most Checks are configurable, be sure to consult the documentation.
To completely disable a check, just comment it out or delete it from the file.
To suppress certain violations please review suppression filters.
Finally, it is worth reading the documentation.
-->
<module name="Checker">
<!--
If you set the basedir property below, then all reported file
names will be relative to the specified directory. See
https://checkstyle.org/config.html#Checker
<property name="basedir" value="${basedir}"/>
-->
<property name="severity" value="error"/>
<property name="fileExtensions" value="java, properties, xml"/>
<!-- Excludes all 'module-info.java' files -->
<!-- See https://checkstyle.org/config_filefilters.html -->
<module name="BeforeExecutionExclusionFileFilter">
<property name="fileNamePattern" value="module\-info\.java$"/>
</module>
<!-- https://checkstyle.org/config_filters.html#SuppressionFilter -->
<module name="SuppressionFilter">
<property name="file" value="${org.checkstyle.sun.suppressionfilter.config}"
default="checkstyle-suppressions.xml" />
<property name="optional" value="true"/>
</module>
<!-- Checks that a package-info.java file exists for each package. -->
<!-- See https://checkstyle.org/config_javadoc.html#JavadocPackage -->
<!-- <module name="JavadocPackage"/>-->
<!-- Checks whether files end with a new line. -->
<!-- See https://checkstyle.org/config_misc.html#NewlineAtEndOfFile -->
<!-- <module name="NewlineAtEndOfFile"/>-->
<!-- Checks that property files contain the same keys. -->
<!-- See https://checkstyle.org/config_misc.html#Translation -->
<module name="Translation"/>
<!-- Checks for Size Violations. -->
<!-- See https://checkstyle.org/config_sizes.html -->
<module name="FileLength"/>
<module name="LineLength">
<property name="fileExtensions" value="java"/>
<property name="max" value="130"/>
</module>
<!-- Checks for whitespace -->
<!-- See https://checkstyle.org/config_whitespace.html -->
<module name="FileTabCharacter"/>
<!-- Miscellaneous other checks. -->
<!-- See https://checkstyle.org/config_misc.html -->
<module name="RegexpSingleline">
<property name="format" value="\s+$"/>
<property name="minimum" value="0"/>
<property name="maximum" value="0"/>
<property name="message" value="Line has trailing spaces."/>
</module>
<!-- Checks for Headers -->
<!-- See https://checkstyle.org/config_header.html -->
<!-- <module name="Header"> -->
<!-- <property name="headerFile" value="${checkstyle.header.file}"/> -->
<!-- <property name="fileExtensions" value="java"/> -->
<!-- </module> -->
<module name="TreeWalker">
<!-- Checks for Javadoc comments. -->
<!-- See https://checkstyle.org/config_javadoc.html -->
<module name="InvalidJavadocPosition"/>
<module name="JavadocMethod"/>
<!-- <module name="JavadocType"/>-->
<!-- <module name="JavadocVariable"/>-->
<module name="JavadocStyle"/>
<!-- <module name="MissingJavadocMethod"/>-->
<!-- Checks for Naming Conventions. -->
<!-- See https://checkstyle.org/config_naming.html -->
<module name="ConstantName"/>
<module name="LocalFinalVariableName"/>
<module name="LocalVariableName"/>
<module name="MemberName"/>
<!-- <module name="MethodName"/>-->
<module name="PackageName"/>
<module name="ParameterName"/>
<module name="StaticVariableName"/>
<module name="TypeName"/>
<!-- Checks for imports -->
<!-- See https://checkstyle.org/config_imports.html -->
<module name="AvoidStarImport"/>
<module name="IllegalImport"/> <!-- defaults to sun.* packages -->
<module name="RedundantImport"/>
<module name="UnusedImports">
<property name="processJavadoc" value="true"/>
</module>
<!-- Checks for Size Violations. -->
<!-- See https://checkstyle.org/config_sizes.html -->
<module name="MethodLength"/>
<module name="ParameterNumber"/>
<!-- Checks for whitespace -->
<!-- See https://checkstyle.org/config_whitespace.html -->
<module name="EmptyForIteratorPad"/>
<module name="GenericWhitespace"/>
<module name="MethodParamPad"/>
<module name="NoWhitespaceAfter"/>
<module name="NoWhitespaceBefore"/>
<module name="OperatorWrap"/>
<module name="ParenPad"/>
<module name="TypecastParenPad"/>
<!-- <module name="WhitespaceAfter"/>-->
<!-- <module name="WhitespaceAround"/>-->
<!-- Modifier Checks -->
<!-- See https://checkstyle.org/config_modifier.html -->
<module name="ModifierOrder"/>
<module name="RedundantModifier"/>
<!-- Checks for blocks. You know, those {}'s -->
<!-- See https://checkstyle.org/config_blocks.html -->
<module name="AvoidNestedBlocks"/>
<module name="EmptyBlock"/>
<module name="LeftCurly"/>
<module name="NeedBraces"/>
<module name="RightCurly"/>
<!-- Checks for common coding problems -->
<!-- See https://checkstyle.org/config_coding.html -->
<module name="EmptyStatement"/>
<module name="EqualsHashCode"/>
<!-- <module name="HiddenField"/>-->
<module name="IllegalInstantiation"/>
<module name="InnerAssignment"/>
<module name="MagicNumber"/>
<module name="MissingSwitchDefault"/>
<module name="MultipleVariableDeclarations"/>
<module name="SimplifyBooleanExpression"/>
<module name="SimplifyBooleanReturn"/>
<!-- Checks for class design -->
<!-- See https://checkstyle.org/config_design.html -->
<!-- <module name="DesignForExtension"/>-->
<!-- <module name="FinalClass"/>-->
<!-- <module name="HideUtilityClassConstructor"/>-->
<module name="InterfaceIsType"/>
<module name="VisibilityModifier"/>
<!-- Miscellaneous other checks. -->
<!-- See https://checkstyle.org/config_misc.html -->
<module name="ArrayTypeStyle"/>
<!-- <module name="FinalParameters"/>-->
<module name="TodoComment"/>
<module name="UpperEll"/>
<!-- https://checkstyle.org/config_filters.html#SuppressionXpathFilter -->
<module name="SuppressionXpathFilter">
<property name="file" value="${org.checkstyle.sun.suppressionxpathfilter.config}"
default="checkstyle-xpath-suppressions.xml"/>
<property name="optional" value="true"/>
</module>
<!-- <module name="SuppressionCommentFilter">-->
<!-- <property name="offCommentFormat" value="CHECKSTYLE.OFF\: ([\w\|]+)"/>-->
<!-- <property name="onCommentFormat" value="CHECKSTYLE.ON\: ([\w\|]+)"/>-->
<!-- <property name="checkFormat" value="$1"/>-->
<!-- </module>-->
</module>
</module>

16
docker-compose.yml 100644
View File

@ -0,0 +1,16 @@
version: '3.8'
services:
service:
image: docker.nclazz.de/nclazz-service/mail-relay:$VERSION
stop_grace_period: 60s
deploy:
replicas: 1
resources:
limits:
memory: 250MB
placement:
max_replicas_per_node: 1
update_config:
order: start-first
ports:
- "${PORT}:8080"

164
pom.xml
View File

@ -25,6 +25,13 @@
<project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
<assertj.version>3.21.0</assertj.version>
<maven.surefire.version>3.0.0-M5</maven.surefire.version>
<maven.failsafe.version>3.0.0-M5</maven.failsafe.version>
<maven.enforcer.version>3.0.0</maven.enforcer.version>
<git.id.version>5.0.0</git.id.version>
<spotbugs.version>4.2.0</spotbugs.version>
<jacoco.version>0.8.7</jacoco.version>
<checkstyle.version>3.1.2</checkstyle.version>
</properties>
<dependencies>
@ -119,6 +126,16 @@
</execution>
</executions>
</plugin>
<plugin>
<groupId>io.github.git-commit-id</groupId>
<artifactId>git-commit-id-maven-plugin</artifactId>
<version>5.0.0</version>
<configuration>
<excludeProperties>
<excludeProperty>^git.local.branch.*$</excludeProperty>
</excludeProperties>
</configuration>
</plugin>
</plugins>
<testResources>
<testResource>
@ -130,4 +147,151 @@
</testResources>
</build>
<profiles>
<profile>
<id>test</id>
<build>
<plugins>
<plugin>
<groupId>com.github.spotbugs</groupId>
<artifactId>spotbugs-maven-plugin</artifactId>
<version>${spotbugs.version}</version>
<configuration>
<xmlOutput>true</xmlOutput>
<effort>Medium</effort>
<threshold>Low</threshold>
<failOnError>false</failOnError>
<excludeFilterFile>spotbugs-ignore.xml</excludeFilterFile>
</configuration>
<executions>
<execution>
<id>compile-findbugs</id>
<phase>compile</phase>
<goals>
<goal>check</goal>
</goals>
</execution>
</executions>
</plugin>
<plugin>
<!-- Intellj doesnt find the plugin for whatever reason, in maven build everything works -->
<groupId>org.apache.maven.plugins</groupId>
<!--suppress MavenModelInspection -->
<artifactId>maven-checkstyle-plugin</artifactId>
<!--suppress MavenModelInspection -->
<version>${checkstyle.version}</version>
<configuration>
<configLocation>checkstyle.xml</configLocation>
<sourceDirectories>
<sourceDirectory>src/main/java</sourceDirectory>
</sourceDirectories>
<failsOnError>false</failsOnError>
<failOnViolation>true</failOnViolation>
<maxAllowedViolations>0</maxAllowedViolations>
</configuration>
<executions>
<execution>
<id>checkstyle-check</id>
<goals>
<goal>check</goal>
</goals>
</execution>
</executions>
</plugin>
<plugin>
<groupId>org.jacoco</groupId>
<artifactId>jacoco-maven-plugin</artifactId>
<version>${jacoco.version}</version>
<configuration>
<rules>
<rule>
<element>BUNDLE</element>
<excludes>
<exclude>**/*Configuration.class</exclude>
<exclude>**/*Application.class</exclude>
</excludes>
</rule>
</rules>
<haltOnFailure>false</haltOnFailure>
</configuration>
<executions>
<execution>
<id>prepare-agent</id>
<goals>
<goal>prepare-agent</goal>
</goals>
</execution>
<execution>
<id>report</id>
<phase>prepare-package</phase>
<goals>
<goal>report</goal>
</goals>
</execution>
<execution>
<id>check</id>
<goals>
<goal>check</goal>
</goals>
</execution>
</executions>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-enforcer-plugin</artifactId>
<version>${maven.enforcer.version}</version>
<configuration>
<rules>
<requireMavenVersion>
<version>3.5</version>
</requireMavenVersion>
<requireJavaVersion>
<version>11</version>
</requireJavaVersion>
<banDuplicatePomDependencyVersions/>
</rules>
</configuration>
<executions>
<execution>
<id>enforce-maven</id>
<goals>
<goal>enforce</goal>
</goals>
</execution>
</executions>
</plugin>
</plugins>
</build>
<reporting>
<plugins>
<plugin>
<groupId>com.github.spotbugs</groupId>
<artifactId>spotbugs-maven-plugin</artifactId>
<version>${spotbugs.version}</version>
<configuration>
<xmlOutput>true</xmlOutput>
<effort>Medium</effort>
<threshold>Low</threshold>
</configuration>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<!--suppress MavenModelInspection -->
<artifactId>maven-checkstyle-plugin</artifactId>
<!--suppress MavenModelInspection -->
<version>${checkstyle.version}</version>
<configuration>
<configLocation>../checkstyle.xml</configLocation>
<sourceDirectories>
<sourceDirectory>src/main/java</sourceDirectory>
</sourceDirectories>
<failsOnError>false</failsOnError>
<failOnViolation>false</failOnViolation>
</configuration>
</plugin>
</plugins>
</reporting>
</profile>
</profiles>
</project>

24
settings.xml 100644
View File

@ -0,0 +1,24 @@
<settings xmlns="http://maven.apache.org/SETTINGS/1.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/SETTINGS/1.0.0
https://maven.apache.org/xsd/settings-1.0.0.xsd">
<localRepository />
<interactiveMode />
<offline />
<pluginGroups />
<mirrors>
<mirror>
<id>nexus.nclazz.de</id>
<url>https://nexus.nclazz.de/repository/maven-public</url>
<mirrorOf>*</mirrorOf>
</mirror>
</mirrors>
<servers>
<server>
<id>nexus.nclazz.de</id>
<username>${env.NEXUS_USR}</username>
<password>${env.NEXUS_PSW}</password>
</server>
</servers>
<proxies />
<profiles />
<activeProfiles />
</settings>

View File

@ -0,0 +1,6 @@
<?xml version="1.0" encoding="UTF-8"?>
<FindBugsFilter>
<Match>
<!-- <Source name="~.*/models/.*"/>-->
</Match>
</FindBugsFilter>