Repository navigation
Expand file tree
/
Copy pathpom.xml
More file actions
567 lines (552 loc) · 27.7 KB
/
Copy pathpom.xml
File metadata and controls
567 lines (552 loc) · 27.7 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>4.1.1</version>
<relativePath/> <!-- lookup parent from repository -->
</parent>
<groupId>io.algernon</groupId>
<artifactId>vespera</artifactId>
<version>0.0.1-SNAPSHOT</version>
<name>vespera</name>
<description>vespera</description>
<url>https://github.com/algernon28/vespera</url>
<licenses>
<license/>
</licenses>
<developers>
<developer/>
</developers>
<scm>
<connection>scm:git:https://github.com/algernon28/vespera.git</connection>
<developerConnection>scm:git:https://github.com/algernon28/vespera.git</developerConnection>
<tag>HEAD</tag>
<url>https://github.com/algernon28/vespera</url>
</scm>
<properties>
<java.version>26</java.version>
<spring-ai.version>2.0.0</spring-ai.version>
<spring-modulith.version>2.1.0</spring-modulith.version>
<picocli.version>4.7.7</picocli.version>
<memoryfilesystem.version>2.8.1</memoryfilesystem.version>
<jsoup.version>1.23.2</jsoup.version>
<!-- ADR-073: pinned to Lingua's latest release, 1.2.2 (2022), the record's own note that this line is stable rather than actively developed. -->
<lingua.version>1.2.2</lingua.version>
<!--
ADR-128: okio is pinned forward to the version okhttp 4.12.0 itself declares. Two things
depend on okio here: lingua's moshi, which declared 2.10.0, and okhttp, which declared
3.6.0. Maven's nearest-wins selected 2.10.0, putting the GzipSource class CVE-2023-3635
lives in on the classpath, and running okhttp against a version it was not built for.
3.6.0 sits above the 3.4.0 fix floor and restores what okhttp asked for; the extraction
tests, which build the language detector and load every bundled model through moshi,
stay green under it.
-->
<okio.version>3.6.0</okio.version>
<!--
Allure is two products on two version lines, which is the easy thing to get wrong.
allure.version is the adapter: the allure-java libraries the tests are woven with, which
write target/allure-results. allure-bom below manages every one of them from this number,
so no Allure dependency carries a version of its own. Its line is 2.x, and there is no 3.x
release of it.
allure-report.version is the generator: the TypeScript program that turns those results
into a page, and the product now at 3.x. Allure 3 reads Allure 2 results, its reader for
them being part of the generator, so a 2.x adapter with a 3.x generator is the documented
pairing rather than a mismatch.
-->
<allure.version>2.35.4</allure.version>
<allure-report.version>3.16.0</allure-report.version>
<allure-maven.version>3.0.3</allure-maven.version>
<gmavenplus-plugin.version>5.1.0</gmavenplus-plugin.version>
<groovy.version>5.1.1</groovy.version>
<aspectj.version>1.9.25.1</aspectj.version>
<!--
ADR-194: what a test class writes goes to <class>-output.txt in target/surefire-reports or
target/failsafe-reports, not to the build's console. Tests that provoke a fault on purpose
log errors and stack traces a reader of a green build took for failures. A failing test's
own assertion and stack still print on the console; what it logged is in that file.
A property rather than plugin configuration, because both plugins read this one and a
property can be overridden: -Dmaven.test.redirectTestOutputToFile=false puts a run's test
output back on the console. A value written into <configuration> would ignore that.
-->
<maven.test.redirectTestOutputToFile>true</maven.test.redirectTestOutputToFile>
</properties>
<dependencies>
<dependency>
<!-- ADR-093: declared explicitly per ADR-046's convention, rather than left to arrive only
transitively via spring-boot-starter-logging. logback-classic itself stays un-added and
BOM-managed, same as every other starter-provided library here. -->
<groupId>org.slf4j</groupId>
<artifactId>slf4j-api</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-batch</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-jdbc</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.ai</groupId>
<artifactId>spring-ai-starter-model-ollama</artifactId>
</dependency>
<dependency>
<!-- The profile is YAML, read and written through Jackson's records support (ADR-061). -->
<groupId>tools.jackson.dataformat</groupId>
<artifactId>jackson-dataformat-yaml</artifactId>
</dependency>
<dependency>
<!--
Extraction's per-document language detection (ADR-073, hand-off spec #45): a document-
level, ranked-confidence API, so a declined detection is representable as null rather
than a guess. All languages are bundled (no subset restriction), which is this
dependency's known cost, a large artifact, accepted per ADR-073 alongside its
stale-release risk, both recorded there rather than re-argued here.
-->
<groupId>com.github.pemistahl</groupId>
<artifactId>lingua</artifactId>
<version>${lingua.version}</version>
</dependency>
<dependency>
<groupId>info.picocli</groupId>
<artifactId>picocli</artifactId>
<version>${picocli.version}</version>
</dependency>
<dependency>
<groupId>org.springframework.modulith</groupId>
<artifactId>spring-modulith-api</artifactId>
</dependency>
<dependency>
<groupId>org.xerial</groupId>
<artifactId>sqlite-jdbc</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-jdbc-test</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-testcontainers</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.springframework.ai</groupId>
<artifactId>spring-ai-spring-boot-testcontainers</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.springframework.modulith</groupId>
<artifactId>spring-modulith-starter-test</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.testcontainers</groupId>
<artifactId>testcontainers-junit-jupiter</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.testcontainers</groupId>
<artifactId>testcontainers-ollama</artifactId>
<scope>test</scope>
</dependency>
<!--
ADR-272: the test of the version-stamping script evaluates the script itself, at the
groovy.version gmavenplus already runs. Nothing shipped carries Groovy.
-->
<dependency>
<groupId>org.apache.groovy</groupId>
<artifactId>groovy</artifactId>
<version>${groovy.version}</version>
<scope>test</scope>
</dependency>
<!--
ADR-297: the control panel's screens are tested through PanelBrowser, which parses each page
the panel serves as a browser parses HTML and reads a form's fields as a browser sends them.
Test scope: the control panel's jar stays on java.base and jdk.httpserver (ADR-285 section 3).
Maven brings nothing with it: its compile dependency re2j is optional, jspecify provided.
-->
<dependency>
<groupId>org.jsoup</groupId>
<artifactId>jsoup</artifactId>
<version>${jsoup.version}</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>io.qameta.allure</groupId>
<artifactId>allure-jupiter</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.assertj</groupId>
<artifactId>assertj-core</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<!--
An in-memory filesystem for the walk's own logic: the accounting identity, the
checkpoint ordinals and subtree skipping on resume, and the unprocessable anomaly a
denied directory produces (ADR-065). It enforces permissions, which is what turns an
environment-dependent skip into a test, and it builds a thousand-entry tree in
milliseconds, which is what makes the resume arithmetic testable at a scale that can
actually break it.
Not for identity. Its Windows model folds dotless i and I together, where NTFS keeps
them as different files, which is the exact case ADR-051 was written about. So path
identity, unencodable names, junctions and traversal order stay on real NTFS under
@TempDir, and its case-sensitivity settings are deliberately not configured to
imitate NTFS: a fixture bent to match a belief can only confirm that belief.
-->
<groupId>com.github.marschall</groupId>
<artifactId>memoryfilesystem</artifactId>
<version>${memoryfilesystem.version}</version>
<scope>test</scope>
</dependency>
</dependencies>
<dependencyManagement>
<dependencies>
<dependency>
<groupId>org.springframework.modulith</groupId>
<artifactId>spring-modulith-bom</artifactId>
<version>${spring-modulith.version}</version>
<type>pom</type>
<scope>import</scope>
</dependency>
<dependency>
<groupId>org.springframework.ai</groupId>
<artifactId>spring-ai-bom</artifactId>
<version>${spring-ai.version}</version>
<type>pom</type>
<scope>import</scope>
</dependency>
<dependency>
<groupId>io.qameta.allure</groupId>
<artifactId>allure-bom</artifactId>
<version>${allure.version}</version>
<type>pom</type>
<scope>import</scope>
</dependency>
<dependency>
<!-- ADR-128: managed here so nothing can reintroduce 2.10.0; see okio.version above. -->
<groupId>com.squareup.okio</groupId>
<artifactId>okio</artifactId>
<version>${okio.version}</version>
</dependency>
</dependencies>
</dependencyManagement>
<build>
<resources>
<!--
Declaring resources at all overrides the default, so src/main/resources has to be
named here too. The second entry carries the file the implementation-versions
execution below generates (ADR-058); generating it into target/generated-resources and
letting maven-resources copy it keeps the generation in generate-resources, where a
generated file belongs, rather than writing into target/classes behind the build's
back.
-->
<resource>
<directory>src/main/resources</directory>
</resource>
<resource>
<directory>${project.build.directory}/generated-resources/implementation-versions</directory>
</resource>
<!--
The compose files and the build context of the Docling image, copied byte for byte into the jar under
sidecars/ (ADR-323 section 4): Vespera starts the sidecars from these, so the jar needs nothing from the
checkout. Unfiltered, so the files in the jar are the files the README and the tests read.
-->
<resource>
<directory>${project.basedir}</directory>
<targetPath>sidecars</targetPath>
<filtering>false</filtering>
<includes>
<include>compose.yaml</include>
<include>compose.gpu.yaml</include>
<include>docker/**</include>
</includes>
</resource>
</resources>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
<plugin>
<!-- Two jars from one build (ADR-285): default-jar, which the Boot plugin repackages, leaves the control panel out; a plain jar with classifier control-panel holds only it, and its manifest names the entry point and the jar beside it (ADR-288). -->
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-jar-plugin</artifactId>
<executions>
<execution>
<id>default-jar</id>
<configuration>
<excludes>
<exclude>io/algernon/controlpanel/**</exclude>
</excludes>
</configuration>
</execution>
<execution>
<id>control-panel</id>
<phase>package</phase>
<goals>
<goal>jar</goal>
</goals>
<configuration>
<classifier>control-panel</classifier>
<includes>
<include>io/algernon/controlpanel/**</include>
</includes>
<archive>
<manifestEntries>
<Main-Class>io.algernon.controlpanel.ControlPanel</Main-Class>
<Vespera-Jar>${project.build.finalName}.jar</Vespera-Jar>
</manifestEntries>
</archive>
</configuration>
</execution>
</executions>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-surefire-plugin</artifactId>
<dependencies>
<dependency>
<groupId>org.aspectj</groupId>
<artifactId>aspectjweaver</artifactId>
<version>${aspectj.version}</version>
</dependency>
</dependencies>
<configuration>
<argLine>-javaagent:"${settings.localRepository}/org/aspectj/aspectjweaver/${aspectj.version}/aspectjweaver-${aspectj.version}.jar"</argLine>
<excludes>
<exclude>**/*IT.java</exclude>
</excludes>
</configuration>
</plugin>
<plugin>
<!--
Some *IT tests need a Docker daemon (VesperaApplicationIT starts Ollama and docling-serve via
Testcontainers); the publish's run against an in-process stub and need none (ADR-320
section 6). All are excluded from surefire above, so `./mvnw test` never needs Docker. `./mvnw verify` runs them here, in integration-test, woven the same way as
surefire; allure.properties sends both suites to the same results directory,
so one report covers the whole build. The publish's tests are *IT tagged `confluence`;
CI runs `verify` with -DexcludedGroups=confluence, so it runs none of them (ADR-320 section 6).
-->
<artifactId>maven-failsafe-plugin</artifactId>
<dependencies>
<dependency>
<groupId>org.aspectj</groupId>
<artifactId>aspectjweaver</artifactId>
<version>${aspectj.version}</version>
</dependency>
</dependencies>
<configuration>
<argLine>-javaagent:"${settings.localRepository}/org/aspectj/aspectjweaver/${aspectj.version}/aspectjweaver-${aspectj.version}.jar"</argLine>
</configuration>
<executions>
<execution>
<goals>
<goal>integration-test</goal>
<goal>verify</goal>
</goals>
</execution>
</executions>
</plugin>
<plugin>
<!--
Wipes target/allure-results before the tests that refill it. Allure results are
append-only and target/ survives between builds, so without this every report
aggregates every run since the last clean rather than the run that just happened.
Bound to process-test-classes: after a clean would have run, and before surefire,
so one report still covers everything a single build executed.
excludeDefaultDirectories is essential. Without it this execution deletes all of
target/, taking the freshly compiled classes with it.
-->
<artifactId>maven-clean-plugin</artifactId>
<executions>
<execution>
<id>clean-allure-results</id>
<phase>process-test-classes</phase>
<goals>
<goal>clean</goal>
</goals>
<configuration>
<excludeDefaultDirectories>true</excludeDefaultDirectories>
<filesets>
<fileset>
<directory>${project.build.directory}/allure-results</directory>
</fileset>
</filesets>
</configuration>
</execution>
</executions>
</plugin>
<plugin>
<groupId>io.qameta.allure</groupId>
<artifactId>allure-maven</artifactId>
<version>${allure-maven.version}</version>
<!--
Everything this generates goes under target/, so it is disposable and no cleanup
step is needed. singleFile is an option of Awesome, the plugin Allure 3 renders
the report with, and makes that report one self-contained
target/allure-report/index.html; the plugin also renders a Maven site wrapper and
the Fluido skin beside it, which cannot be switched off while using the report
goal and does not matter once it lands in target/.
configPath points at allurerc.mjs, which configures the Awesome plugin (the
report UI) and the failure categories. The plugin merges that file underneath
its own generated config and overrides only name, output and singleFile, so
those three stay here and the rest of the report is described there.
reportVersion is pinned deliberately. Left unset, the generator is whatever the
plugin currently defaults to, so an unversioned toolchain can change under a build
that never changed.
-->
<configuration>
<reportVersion>${allure-report.version}</reportVersion>
<resultsDirectory>${project.build.directory}/allure-results</resultsDirectory>
<reportDirectory>${project.build.directory}/allure-report</reportDirectory>
<singleFile>true</singleFile>
<configPath>allurerc.mjs</configPath>
</configuration>
<executions>
<execution>
<id>generate-allure-report</id>
<phase>verify</phase>
<goals>
<goal>report</goal>
</goals>
</execution>
</executions>
</plugin>
<plugin>
<!--
Copies the report to reports/report_<datetime>.html, so the one file worth
opening or sending is out of target/, survives a clean, and says which run
produced it. Nothing here deletes an older report: every run's file gets its
own name, so none is ever overwritten, and reports/ is left to grow with one
file per run. singleFile above means there is exactly one file to copy; the
Maven site wrapper allure-maven renders beside it stays behind in target/.
Neither core Maven plugin does a rename: maven-resources-plugin only places a
file under its source name, and maven-antrun-plugin means mixing Ant into a
Maven build for a one-line job. gmavenplus runs the rename as a few lines of
Groovy instead, with no separate script file and no second build tool.
The stamp is computed here rather than read from maven.build.timestamp: that
property is not exposed on project.properties in this Maven version, and
computing it directly also means it is the JVM's local time, not Maven's UTC.
Declared after allure-maven and bound to the same phase, because plugins bound
to one phase run in declaration order: the report has to exist before it is
copied.
-->
<groupId>org.codehaus.gmavenplus</groupId>
<artifactId>gmavenplus-plugin</artifactId>
<version>${gmavenplus-plugin.version}</version>
<dependencies>
<dependency>
<groupId>org.apache.groovy</groupId>
<artifactId>groovy</artifactId>
<version>${groovy.version}</version>
</dependency>
</dependencies>
<executions>
<execution>
<!--
Stamps each module with the commit that last touched it (ADR-058). The
script says why, and is a .groovy file rather than CDATA so that an editor
can read it as code.
-->
<id>implementation-versions</id>
<phase>generate-resources</phase>
<goals>
<goal>execute</goal>
</goals>
<configuration>
<scripts>
<!--suppress UnresolvedMavenProperty -->
<script>file:///${project.basedir}/.mvn/scripts/implementation-versions.groovy</script>
</scripts>
</configuration>
</execution>
<execution>
<id>publish-allure-report</id>
<phase>verify</phase>
<goals>
<goal>execute</goal>
</goals>
<configuration>
<scripts>
<!--suppress UnresolvedMavenProperty -->
<script>file:///${project.basedir}/.mvn/scripts/publish-allure-report.groovy</script>
</scripts>
</configuration>
</execution>
</executions>
</plugin>
</plugins>
</build>
<!--
Launch shortcuts: each profile builds both jars, skipping the tests, and then starts one of
them with the java running Maven, from the root of the repository, until it ends.
`./mvnw -Pheadless -Dvespera.args="run <root>"` runs one command of the Vespera jar, no
control panel; `./mvnw -Pgui` starts the control panel, which starts that same jar for each
command it runs. Neither starts the sidecars.
-->
<profiles>
<profile>
<id>headless</id>
<properties>
<skipTests>true</skipTests>
<vespera.args/>
</properties>
<build>
<defaultGoal>package</defaultGoal>
<plugins>
<plugin>
<groupId>org.codehaus.mojo</groupId>
<artifactId>exec-maven-plugin</artifactId>
<executions>
<execution>
<id>launch-headless</id>
<phase>package</phase>
<goals>
<goal>exec</goal>
</goals>
<configuration>
<executable>${java.home}/bin/java</executable>
<commandlineArgs>-jar "${project.build.directory}/${project.build.finalName}.jar" ${vespera.args}</commandlineArgs>
</configuration>
</execution>
</executions>
</plugin>
</plugins>
</build>
</profile>
<profile>
<id>gui</id>
<properties>
<skipTests>true</skipTests>
</properties>
<build>
<defaultGoal>package</defaultGoal>
<plugins>
<plugin>
<groupId>org.codehaus.mojo</groupId>
<artifactId>exec-maven-plugin</artifactId>
<executions>
<execution>
<id>launch-gui</id>
<phase>package</phase>
<goals>
<goal>exec</goal>
</goals>
<configuration>
<executable>${java.home}/bin/java</executable>
<commandlineArgs>-jar "${project.build.directory}/${project.build.finalName}-control-panel.jar"</commandlineArgs>
</configuration>
</execution>
</executions>
</plugin>
</plugins>
</build>
</profile>
</profiles>
</project>