commit | author | age
|
6c33bb
|
1 |
plugins { |
a2f2fd
|
2 |
id 'java' |
810c39
|
3 |
id 'org.springframework.boot' version '2.7.5' |
0e4602
|
4 |
id 'io.openapiprocessor.openapi-processor' version '2022.2' |
810c39
|
5 |
id 'io.spring.dependency-management' version '1.1.0' |
c4531c
|
6 |
id 'com.github.jk1.dependency-license-report' version '2.1' |
810c39
|
7 |
id "org.owasp.dependencycheck" version "7.3.0" |
398f15
|
8 |
id "com.diffplug.spotless" version "6.11.0" |
a66ed8
|
9 |
id 'jacoco' |
7d4815
|
10 |
id 'info.solidsoft.pitest' version '1.9.0' |
8b4e78
|
11 |
id 'se.patrikerdes.use-latest-versions' version '0.2.18' |
810c39
|
12 |
id 'com.github.ben-manes.versions' version '0.43.0' |
6c33bb
|
13 |
} |
MH |
14 |
|
|
15 |
group = 'net.hostsharing' |
|
16 |
version = '0.0.1-SNAPSHOT' |
|
17 |
|
d9ee00
|
18 |
wrapper { |
MH |
19 |
distributionType = Wrapper.DistributionType.BIN |
|
20 |
gradleVersion = '7.5' |
|
21 |
} |
|
22 |
|
6c33bb
|
23 |
configurations { |
MH |
24 |
compileOnly { |
|
25 |
extendsFrom annotationProcessor |
|
26 |
} |
3de8b0
|
27 |
testCompile { |
3eec8a
|
28 |
extendsFrom testAnnotationProcessor |
MH |
29 |
|
3de8b0
|
30 |
// Only JUNit 5 (Jupiter) should be used at compile time. |
MH |
31 |
// For runtime it's still needed by testcontainers, though. |
|
32 |
exclude group: 'junit', module: 'junit' |
|
33 |
exclude group: 'org.junit.vintage', module: 'junit-vintage-engine' |
|
34 |
} |
6c33bb
|
35 |
} |
MH |
36 |
|
|
37 |
repositories { |
|
38 |
mavenCentral() |
433d0e
|
39 |
} |
MH |
40 |
|
|
41 |
java { |
|
42 |
toolchain { |
|
43 |
languageVersion = JavaLanguageVersion.of(17) |
|
44 |
} |
6c33bb
|
45 |
} |
MH |
46 |
|
|
47 |
ext { |
|
48 |
set('testcontainersVersion', "1.17.3") |
|
49 |
} |
a2f2fd
|
50 |
|
MH |
51 |
// wrapper |
6c33bb
|
52 |
|
MH |
53 |
dependencies { |
|
54 |
implementation 'org.springframework.boot:spring-boot-starter-data-jpa' |
|
55 |
implementation 'org.springframework.boot:spring-boot-starter-data-rest' |
|
56 |
implementation 'org.springframework.boot:spring-boot-starter-jdbc' |
|
57 |
implementation 'org.springframework.boot:spring-boot-starter-web' |
67e850
|
58 |
implementation 'org.springframework.boot:spring-boot-starter-validation' |
c6d92e
|
59 |
implementation 'com.github.gavlyukovskiy:datasource-proxy-spring-boot-starter:1.8.1' |
810c39
|
60 |
implementation 'org.springdoc:springdoc-openapi-ui:1.6.12' |
6c33bb
|
61 |
implementation 'org.liquibase:liquibase-core' |
810c39
|
62 |
implementation 'com.vladmihalcea:hibernate-types-55:2.20.0' |
4f22df
|
63 |
implementation 'com.fasterxml.jackson.datatype:jackson-datatype-jsr310:2.13.4' |
0e4602
|
64 |
implementation 'org.openapitools:jackson-databind-nullable:0.2.3' |
eeab68
|
65 |
implementation 'org.modelmapper:modelmapper:3.1.0' |
d98b8f
|
66 |
implementation 'org.iban4j:iban4j:3.2.3-RELEASE' |
6c33bb
|
67 |
|
MH |
68 |
compileOnly 'org.projectlombok:lombok' |
3eec8a
|
69 |
testCompileOnly 'org.projectlombok:lombok' |
6c33bb
|
70 |
|
MH |
71 |
developmentOnly 'org.springframework.boot:spring-boot-devtools' |
|
72 |
|
|
73 |
runtimeOnly 'org.postgresql:postgresql' |
|
74 |
|
|
75 |
annotationProcessor 'org.projectlombok:lombok' |
3eec8a
|
76 |
testAnnotationProcessor 'org.projectlombok:lombok' |
6c33bb
|
77 |
|
MH |
78 |
testImplementation 'org.springframework.boot:spring-boot-starter-test' |
|
79 |
testImplementation 'org.testcontainers:testcontainers' |
|
80 |
testImplementation 'org.testcontainers:junit-jupiter' |
|
81 |
testImplementation 'org.testcontainers:postgresql' |
398f15
|
82 |
testImplementation 'com.tngtech.archunit:archunit-junit5:1.0.0' |
0e4602
|
83 |
testImplementation 'io.rest-assured:spring-mock-mvc' |
9fb661
|
84 |
testImplementation 'org.hamcrest:hamcrest-core:2.2' |
398f15
|
85 |
testImplementation 'org.pitest:pitest-junit5-plugin:1.1.0' |
6c33bb
|
86 |
} |
MH |
87 |
|
|
88 |
dependencyManagement { |
|
89 |
imports { |
|
90 |
mavenBom "org.testcontainers:testcontainers-bom:${testcontainersVersion}" |
|
91 |
} |
|
92 |
} |
|
93 |
|
a66ed8
|
94 |
// Java Compiler Options |
433d0e
|
95 |
tasks.withType(JavaCompile) { |
a66ed8
|
96 |
options.compilerArgs += [ |
MH |
97 |
"-parameters" // keep parameter names => no need for @Param for SpringData |
|
98 |
] |
433d0e
|
99 |
} |
MH |
100 |
|
a66ed8
|
101 |
// Use JUnit Jupiter |
6c33bb
|
102 |
tasks.named('test') { |
MH |
103 |
useJUnitPlatform() |
|
104 |
} |
a2f2fd
|
105 |
|
a66ed8
|
106 |
// OpenAPI Source Code Generation |
eeab68
|
107 |
openapiProcessor { |
cd9be1
|
108 |
springRoot { |
MH |
109 |
processorName 'spring' |
67e850
|
110 |
processor 'io.openapiprocessor:openapi-processor-spring:2022.5' |
eeab68
|
111 |
apiPath "$projectDir/src/main/resources/api-definition.yaml" |
MH |
112 |
mapping "$projectDir/src/main/resources/api-mappings.yaml" |
cd9be1
|
113 |
targetDir "$projectDir/build/generated/sources/openapi" |
MH |
114 |
showWarnings true |
|
115 |
openApiNullable true |
|
116 |
} |
|
117 |
springRbac { |
|
118 |
processorName 'spring' |
67e850
|
119 |
processor 'io.openapiprocessor:openapi-processor-spring:2022.5' |
cd9be1
|
120 |
apiPath "$projectDir/src/main/resources/api-definition/rbac/rbac.yaml" |
MH |
121 |
mapping "$projectDir/src/main/resources/api-definition/rbac/api-mappings.yaml" |
|
122 |
targetDir "$projectDir/build/generated/sources/openapi" |
|
123 |
showWarnings true |
|
124 |
openApiNullable true |
|
125 |
} |
|
126 |
springTest { |
|
127 |
processorName 'spring' |
67e850
|
128 |
processor 'io.openapiprocessor:openapi-processor-spring:2022.5' |
cd9be1
|
129 |
apiPath "$projectDir/src/main/resources/api-definition/test/test.yaml" |
MH |
130 |
mapping "$projectDir/src/main/resources/api-definition/test/api-mappings.yaml" |
|
131 |
targetDir "$projectDir/build/generated/sources/openapi" |
eeab68
|
132 |
showWarnings true |
0e4602
|
133 |
openApiNullable true |
eeab68
|
134 |
} |
af90fe
|
135 |
springHs { |
MH |
136 |
processorName 'spring' |
67e850
|
137 |
processor 'io.openapiprocessor:openapi-processor-spring:2022.5' |
4e90f5
|
138 |
apiPath "$projectDir/src/main/resources/api-definition/hs-office/hs-office.yaml" |
MH |
139 |
mapping "$projectDir/src/main/resources/api-definition/hs-office/api-mappings.yaml" |
af90fe
|
140 |
targetDir "$projectDir/build/generated/sources/openapi" |
MH |
141 |
showWarnings true |
|
142 |
openApiNullable true |
|
143 |
} |
eeab68
|
144 |
} |
MH |
145 |
sourceSets.main.java.srcDir 'build/generated/sources/openapi' |
af90fe
|
146 |
abstract class ProcessSpring extends DefaultTask {} |
MH |
147 |
tasks.register('processSpring', ProcessSpring) |
|
148 |
['processSpringRoot', 'processSpringRbac', 'processSpringTest', 'processSpringHs'].each { |
|
149 |
project.tasks.processSpring.dependsOn it |
cd9be1
|
150 |
} |
af90fe
|
151 |
project.tasks.processResources.dependsOn processSpring |
MH |
152 |
project.tasks.compileJava.dependsOn processSpring |
eeab68
|
153 |
|
a66ed8
|
154 |
// Spotless Code Formatting |
a2f2fd
|
155 |
spotless { |
MH |
156 |
java { |
0e4602
|
157 |
// removeUnusedImports() TODO: reactivate once it can deal with multi-line-strings |
MH |
158 |
indentWithSpaces(4) |
a2f2fd
|
159 |
endWithNewline() |
MH |
160 |
toggleOffOn() |
eeab68
|
161 |
|
0e4602
|
162 |
target fileTree(rootDir) { |
eeab68
|
163 |
include '**/*.java' |
MH |
164 |
exclude '**/generated/**/*.java' |
|
165 |
} |
a2f2fd
|
166 |
} |
MH |
167 |
} |
80b1e0
|
168 |
project.tasks.check.dependsOn(spotlessCheck) |
MH |
169 |
|
a66ed8
|
170 |
// OWASP Dependency Security Test |
80b1e0
|
171 |
dependencyCheck { |
MH |
172 |
cveValidForHours=4 |
|
173 |
format = 'ALL' |
|
174 |
suppressionFile = 'etc/owasp-dependency-check-suppression.xml' |
|
175 |
failOnError = true |
|
176 |
failBuildOnCVSS = 7 |
|
177 |
} |
|
178 |
project.tasks.check.dependsOn(dependencyCheckAnalyze) |
4ec261
|
179 |
project.tasks.dependencyCheckAnalyze.doFirst { // Why not doLast? See README.md! |
fd96bf
|
180 |
println "OWASP Dependency Security Report: file:///${project.rootDir}/build/reports/dependency-check-report.html" |
MH |
181 |
} |
|
182 |
|
c4531c
|
183 |
|
a66ed8
|
184 |
// License Check |
c4531c
|
185 |
licenseReport { |
MH |
186 |
excludeBoms = true |
|
187 |
allowedLicensesFile = new File("$projectDir/etc/allowed-licenses.json") |
|
188 |
} |
|
189 |
project.tasks.check.dependsOn(checkLicense) |
a66ed8
|
190 |
|
MH |
191 |
// JaCoCo Test Code Coverage |
|
192 |
jacoco { |
|
193 |
toolVersion = "0.8.8" |
|
194 |
} |
|
195 |
test { |
|
196 |
finalizedBy jacocoTestReport // generate report after tests |
|
197 |
excludes = [ |
cd9be1
|
198 |
'net.hostsharing.hsadminng.**.generated.**', |
a66ed8
|
199 |
] |
MH |
200 |
} |
|
201 |
jacocoTestReport { |
|
202 |
dependsOn test |
|
203 |
afterEvaluate { |
|
204 |
classDirectories.setFrom(files(classDirectories.files.collect { |
|
205 |
fileTree(dir: it, exclude: [ |
cd9be1
|
206 |
"net/hostsharing/hsadminng/**/generated/**/*.class", |
4e90f5
|
207 |
"net/hostsharing/hsadminng/hs/HsadminNgApplication.class" |
a66ed8
|
208 |
]) |
MH |
209 |
})) |
|
210 |
} |
4ec261
|
211 |
doFirst { // Why not doLast? See README.md! |
a66ed8
|
212 |
println "HTML Jacoco Test Code Coverage Report: file://${reports.html.outputLocation.get()}/index.html" |
MH |
213 |
} |
|
214 |
} |
|
215 |
project.tasks.check.dependsOn(jacocoTestCoverageVerification) |
|
216 |
jacocoTestCoverageVerification { |
|
217 |
violationRules { |
|
218 |
rule { |
|
219 |
limit { |
894150
|
220 |
minimum = 0.92 |
a66ed8
|
221 |
} |
MH |
222 |
} |
|
223 |
|
|
224 |
// element: PACKAGE, BUNDLE, CLASS, SOURCEFILE or METHOD |
|
225 |
// counter: INSTRUCTION, BRANCH, LINE, COMPLEXITY, METHOD, or CLASS |
|
226 |
// value: TOTALCOUNT, COVEREDCOUNT, MISSEDCOUNT, COVEREDRATIO or MISSEDRATIO |
|
227 |
|
|
228 |
rule { |
|
229 |
element = 'CLASS' |
|
230 |
excludes = [ |
cd9be1
|
231 |
'net.hostsharing.hsadminng.**.generated.**', |
a66ed8
|
232 |
'net.hostsharing.hsadminng.HsadminNgApplication', |
5ada0d
|
233 |
'net.hostsharing.hsadminng.ping.PingController', |
MH |
234 |
'net.hostsharing.hsadminng.mapper.Mapper' |
a66ed8
|
235 |
] |
MH |
236 |
|
|
237 |
limit { |
|
238 |
counter = 'LINE' |
|
239 |
value = 'COVEREDRATIO' |
6ec4c8
|
240 |
minimum = 0.98 |
a66ed8
|
241 |
} |
MH |
242 |
} |
|
243 |
rule { |
|
244 |
element = 'METHOD' |
|
245 |
excludes = [ |
cd9be1
|
246 |
'net.hostsharing.hsadminng.**.generated.**', |
2124d4
|
247 |
'net.hostsharing.hsadminng.HsadminNgApplication.main', |
5ada0d
|
248 |
'net.hostsharing.hsadminng.ping.PingController.*' |
4aa8b8
|
249 |
] |
a66ed8
|
250 |
|
MH |
251 |
limit { |
|
252 |
counter = 'BRANCH' |
|
253 |
value = 'COVEREDRATIO' |
6ec4c8
|
254 |
minimum = 1.00 |
a66ed8
|
255 |
} |
MH |
256 |
} |
|
257 |
} |
|
258 |
} |
|
259 |
|
9fb661
|
260 |
// pitest mutation testing |
MH |
261 |
pitest { |
|
262 |
targetClasses = ['net.hostsharing.hsadminng.**'] |
|
263 |
excludedClasses = [ |
|
264 |
'net.hostsharing.hsadminng.config.**', |
af90fe
|
265 |
'net.hostsharing.hsadminng.**.*Controller', |
cd9be1
|
266 |
'net.hostsharing.hsadminng.**.generated.**' |
9fb661
|
267 |
] |
MH |
268 |
|
|
269 |
targetTests = ['net.hostsharing.hsadminng.**.*UnitTest', 'net.hostsharing.hsadminng.**.*RestTest'] |
|
270 |
excludedTestClasses = ['**AcceptanceTest*', '**IntegrationTest*'] |
|
271 |
|
|
272 |
pitestVersion = '1.9.0' |
|
273 |
junit5PluginVersion = '1.0.0' |
|
274 |
|
|
275 |
threads = 4 |
|
276 |
|
|
277 |
// As Java unit tests are pretty pointless in our case, this maybe makes not much sense. |
af90fe
|
278 |
mutationThreshold = 71 |
MH |
279 |
coverageThreshold = 57 |
d3312c
|
280 |
testStrengthThreshold = 87 |
9fb661
|
281 |
|
MH |
282 |
outputFormats = ['XML', 'HTML'] |
|
283 |
timestampedReports = false |
|
284 |
} |
|
285 |
project.tasks.check.dependsOn(project.tasks.pitest) |
4ec261
|
286 |
project.tasks.pitest.doFirst { // Why not doLast? See README.md! |
9fb661
|
287 |
println "PiTest Mutation Report: file:///${project.rootDir}/build/reports/pitest/index.html" |
MH |
288 |
} |
|
289 |
|
|
290 |
|
8b4e78
|
291 |
// Dependency Versions Upgrade |
MH |
292 |
useLatestVersions { |
|
293 |
finalizedBy check |
|
294 |
} |
810c39
|
295 |
|
MH |
296 |
def isNonStable = { String version -> |
|
297 |
def stableKeyword = ['RELEASE', 'FINAL', 'GA'].any { it -> version.toUpperCase().contains(it) } |
|
298 |
def regex = /^[0-9,.v-]+(-r)?$/ |
|
299 |
return !stableKeyword && !(version ==~ regex) |
|
300 |
} |
|
301 |
|
|
302 |
tasks.named("dependencyUpdates").configure { |
|
303 |
rejectVersionIf { |
|
304 |
isNonStable(it.candidate.version) |
|
305 |
} |
|
306 |
} |