Skip to content

Commit 832994e

Browse files
authored
ci(guards): run every guard the job names, and compile docs-only pull requests (#474)
* ci(guards): run every guard the job names, and compile docs-only pull requests The "Architecture and Documentation Guards" job selected eight test classes while scoping the reactor to graph-compose-core. Two had been deleted months earlier; two live in graph-compose-qa and graph-compose-render-pdf. Surefire aborts only when a selection is entirely empty, so the four names that did match kept the job green while it ran half of what it advertised. The list is now the five guards that live in the engine module, and CiGuardListGuardTest parses the workflow and fails the job when a name in it stops resolving under core/src/test/java — inside the very job it protects. Markdown was also missing from change detection, so a pull request touching only .md skipped the reactor build entirely and merged without DocumentationSnippetCompileTest ever compiling the java fences it publishes. A separate `docs` filter routes those changes into the reactor slice that carries the qa guards, on the baseline JDK; example generation stays gated on `code`, since rendering the catalogue proves nothing about prose. PackageMapGuardTest scanned gitignored docs/private/, where a local note routinely names a retired package in order to record that it is retired. A hit there fails the release runbook's local verify gate for a reason CI can never reproduce, so the directory is excluded — as CanonicalSurfaceGuardTest already excludes it. Three workflow comments claimed things that are not true: that render-docx, render-pptx and graph-compose-testing are absent from Maven Central (they are published; the examples pin them to the reactor's -SNAPSHOT), that the pptx module is a semantic backend (its primary backend is fixed-layout), and that the CodeQL scope matches the canonical verify gate (it is narrower, and the render backends ship unscanned). graph-compose-render-pptx compiles against org.apache.pdfbox types while declaring only fontbox; the dependency is now explicit. Both modules pin pdfbox.version to 3.0.8, so the resolved version is unchanged. * ci(guards): run the guard-list tripwire in the job it guards, and resolve wildcards CiGuardListGuardTest asserted that every name in the workflow's -Dtest list resolves under core/src/test/java, and its own Javadoc claimed it "runs inside the very job it protects". It was not in that list. It ran only in the full reactor build, so a phantom name added to the guard step would still have passed the guard step. Adding the test to the list makes the claim true and costs nothing — it is core-resident like the other five. Wildcard selectors were accepted without resolving them. A pattern that matches nothing is the same silent skip as a deleted class name: Surefire drops it as long as a sibling matches. Every accepted form is now resolved against the tree — plain name, package-qualified name, #method suffix and glob alike — by translating the selector to a regex (** spans packages, * and ? stay inside one segment) and matching it against both the simple name and the package path of each test source. Exercising that surfaced a defect in the parser itself: the character class reading the -Dtest value omitted '?', so a selector containing one was silently truncated and the guard then checked a name nobody wrote. '?', '/', '!' and '+' are now admitted, and a leading '!' marks an exclusion — it subtracts from the selection rather than claiming coverage, so it is skipped rather than required to resolve.
1 parent fe6bbdd commit 832994e

7 files changed

Lines changed: 287 additions & 25 deletions

File tree

.github/workflows/ci.yml

Lines changed: 47 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -45,23 +45,32 @@ jobs:
4545
java-version: '17'
4646
cache: maven
4747

48-
- name: Run guards
48+
- name: Run core architecture and documentation guards
49+
# Every name here must live in graph-compose-core: the run is scoped to
50+
# that module, and Surefire only fails on an empty selection — a name
51+
# that matches nothing while its siblings match is dropped in silence.
52+
# CiGuardListGuardTest asserts each name resolves under core/src/test.
53+
# Guards owned by other modules (PdfRenderInterfaceGuardTest in
54+
# render-pdf, DocumentationExamplesTest and DocumentationSnippetCompileTest
55+
# in qa) run in build-and-test below, which now also covers docs-only PRs.
4956
run: |
5057
./mvnw -B -ntp clean \
51-
"-Dtest=EnginePdfBoundaryTest,CanonicalTemplateComposerPdfBoundaryTest,PdfRenderInterfaceGuardTest,DocumentationCoverageTest,DocumentationExamplesTest,CanonicalSurfaceGuardTest,TemplateComposeApiTest,VersionConsistencyGuardTest" \
58+
"-Dtest=EnginePdfBoundaryTest,DocumentationCoverageTest,CanonicalSurfaceGuardTest,PackageMapGuardTest,VersionConsistencyGuardTest,CiGuardListGuardTest" \
5259
test -pl :graph-compose-core
5360
5461
changes:
5562
# Path-based change detection for selective CI on pull requests. Emits the
5663
# reverse-dependency flags the heavy jobs gate on: `code` (any build input),
57-
# `core` (the root graph-compose-core module — drives japicmp), `perf`
64+
# `docs` (markdown the guard suites read and compile), `core` (the root
65+
# graph-compose-core module — drives japicmp), `perf`
5866
# (modules the smoke benchmark exercises), and `jvm` (published library modules
5967
# + toolchain — drives the JDK matrix width). Pushes/dispatch bypass these gates.
6068
name: Detect changed paths
6169
if: github.event_name != 'schedule'
6270
runs-on: ubuntu-latest
6371
outputs:
6472
code: ${{ steps.filter.outputs.code }}
73+
docs: ${{ steps.filter.outputs.docs }}
6574
core: ${{ steps.filter.outputs.core }}
6675
perf: ${{ steps.filter.outputs.perf }}
6776
jvm: ${{ steps.filter.outputs.jvm }}
@@ -86,6 +95,16 @@ jobs:
8695
- 'mvnw'
8796
- 'mvnw.cmd'
8897
- '.github/workflows/ci.yml'
98+
# Markdown is a build input even though it compiles nothing:
99+
# DocumentationSnippetCompileTest compiles the literal java fences in
100+
# docs/, and the guard suites read README / CONTRIBUTING / docs. Kept
101+
# separate from `code` so a docs-only change runs the reactor (which
102+
# carries those guards) without also running examples-generation,
103+
# which installs eight modules and renders the full example catalogue
104+
# to prove nothing about prose. Deliberately absent from `jvm` too, so
105+
# a docs-only PR uses the baseline JDK alone rather than the matrix.
106+
docs:
107+
- '**/*.md'
89108
core:
90109
- 'core/src/**'
91110
- 'core/pom.xml'
@@ -119,9 +138,12 @@ jobs:
119138
build-and-test:
120139
name: Build and run tests (JDK ${{ matrix.java }})
121140
# Selective CI: on a pull request, skip the heavy reactor build + JDK matrix
122-
# when only docs / non-build files changed (`code` is false). Pushes to the
123-
# integration branches and manual dispatch always run the full gate.
124-
if: github.event_name != 'schedule' && (github.event_name != 'pull_request' || needs.changes.outputs.code == 'true')
141+
# when nothing this reactor slice can check has changed. Markdown counts —
142+
# this slice carries the qa guards that compile the published snippets, so a
143+
# docs-only PR runs here (on the baseline JDK alone, since `jvm` stays false)
144+
# rather than merging without any compiler having read the change. Pushes to
145+
# the integration branches and manual dispatch always run the full gate.
146+
if: github.event_name != 'schedule' && (github.event_name != 'pull_request' || needs.changes.outputs.code == 'true' || needs.changes.outputs.docs == 'true')
125147
needs: [architecture-and-documentation-guards, changes]
126148
runs-on: ubuntu-latest
127149
strategy:
@@ -158,7 +180,9 @@ jobs:
158180
# only via the examples job), the extracted graph-compose-testing module, the
159181
# graph-compose-qa cross-module suites (which need the testing module + the
160182
# engine test-jar on the classpath and so cannot live in the engine's own test
161-
# scope), and the graph-compose-coverage aggregator (JaCoCo over core +
183+
# scope — this is where DocumentationSnippetCompileTest, the guard that
184+
# compiles the literal markdown fences in docs/, and DocumentationExamplesTest
185+
# actually run), and the graph-compose-coverage aggregator (JaCoCo over core +
162186
# render-pdf + templates, counting the qa exec, now with a NON-REGRESSION
163187
# RATCHET — this step fails if aggregate INSTRUCTION or BRANCH coverage drops
164188
# below the floor in coverage/pom.xml). -am pulls the fonts / emoji upstreams;
@@ -189,7 +213,9 @@ jobs:
189213

190214
examples-generation:
191215
name: Examples Generation Smoke Test
192-
# Follows build-and-test: skipped for a docs-only PR, runs otherwise.
216+
# Gated on `code` alone, deliberately narrower than build-and-test above:
217+
# rendering the example catalogue costs eight module installs and proves
218+
# nothing about a markdown change, so a docs-only PR skips it.
193219
if: github.event_name != 'schedule' && (github.event_name != 'pull_request' || needs.changes.outputs.code == 'true')
194220
needs: [build-and-test, changes]
195221
runs-on: ubuntu-latest
@@ -214,9 +240,10 @@ jobs:
214240
run: ./mvnw -B -ntp -f fonts/pom.xml -DskipTests install
215241

216242
- name: Install graph-compose-emoji (consumed by the examples module)
217-
# The emoji example renders colour emoji from the bundled Noto SVG set;
218-
# like graph-compose-fonts it is a standalone artifact not on Maven
219-
# Central, so install it into the local repo before building examples.
243+
# The emoji example renders colour emoji from the bundled Noto SVG set.
244+
# Like graph-compose-fonts it carries its own version line, so the reactor
245+
# slice never builds it; installing from source pins the examples to this
246+
# tree's asset set rather than the cached jar at the same coordinate.
220247
run: ./mvnw -B -ntp -f emoji/pom.xml -DskipTests install
221248

222249
- name: Install root artifact (graph-compose-core)
@@ -235,22 +262,23 @@ jobs:
235262
run: ./mvnw -B -ntp -f wrapper/pom.xml -DskipTests install
236263

237264
- name: Install graph-compose-render-docx (consumed by the examples module)
238-
# The DOCX export example depends on the render-docx backend module, which
239-
# is not on Central. Install it after the engine (its graph-compose
240-
# dependency) so the examples build resolves it.
265+
# The DOCX export example depends on the render-docx backend module at
266+
# ${graphcompose.version} — the reactor's -SNAPSHOT, which no repository
267+
# can supply. Install it after the engine (its graph-compose dependency)
268+
# so the examples build resolves it.
241269
run: ./mvnw -B -ntp -f render-docx/pom.xml -DskipTests install
242270

243271
- name: Install graph-compose-testing (consumed by the examples module)
244272
# LayoutSnapshotRegressionExample uses LayoutSnapshotJson and EngineDeckData
245-
# reads benchmark JSON through the jackson it brings; the testing module is
246-
# not on Central, so install it after the engine (its graph-compose
247-
# dependency) before the examples build resolves it.
273+
# reads benchmark JSON through the jackson it brings; the examples pin the
274+
# testing module to the reactor's -SNAPSHOT, so install it after the engine
275+
# (its graph-compose dependency) before the examples build resolves it.
248276
run: ./mvnw -B -ntp -f testing/pom.xml -DskipTests install
249277

250278
- name: Install graph-compose-render-pptx (consumed by the examples module)
251279
# The Engine Deck PPTX example renders the flagship deck through the
252-
# fixed-layout PPTX backend, which is not on Central. Install it after
253-
# the wrapper (its core + render-pdf compile dependencies) AND the
280+
# fixed-layout PPTX backend, pinned to the reactor's -SNAPSHOT version.
281+
# Install it after the wrapper (its core + render-pdf compile dependencies) AND the
254282
# testing module — -DskipTests skips execution but Maven still
255283
# resolves render-pptx's test-scope graph-compose-testing dependency.
256284
run: ./mvnw -B -ntp -f render-pptx/pom.xml -DskipTests install

.github/workflows/codeql.yml

Lines changed: 8 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -50,10 +50,14 @@ jobs:
5050
languages: ${{ matrix.language }}
5151
queries: security-and-quality
5252

53-
- name: Build (library module only)
54-
# `-pl :graph-compose-core` scopes the analysis to the published artifact and matches
55-
# the canonical verify gate. Examples/benchmarks are intentionally
56-
# excluded — they ship no production code.
53+
- name: Build (engine module)
54+
# Scoped to the engine module alone: no `-am`, so nothing but core is built
55+
# and nothing but core reaches the extractor. Since the 2.0 split
56+
# graph-compose-core is one of several artifacts published to Maven Central,
57+
# which makes this narrower than both the publish train and the canonical
58+
# verify gate in ci.yml — the render backends and templates ship unscanned.
59+
# Widening it to the code-bearing published modules is tracked for 2.2,
60+
# together with a triage pass on the standing alert set.
5761
run: ./mvnw -B -ntp -DskipTests -pl :graph-compose-core package
5862

5963
- name: Perform CodeQL analysis

.github/workflows/publish.yml

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -226,8 +226,10 @@ jobs:
226226

227227
- name: Publish render-pptx to Maven Central
228228
if: steps.plan.outputs.run_render_pptx == 'true'
229-
# The semantic PPTX backend, lockstep-versioned with the engine (ships on
230-
# the same v* tag). graph-compose-core resolves from the local repo installed
229+
# The PPTX render backend — a fixed-layout POI XSLF backend consuming the
230+
# same resolved LayoutGraph as the PDF one, alongside the older semantic
231+
# manifest skeleton. Lockstep-versioned with the engine (ships on the same
232+
# v* tag). graph-compose-core resolves from the local repo installed
231233
# by the engine deploy above.
232234
run: ./mvnw -B -ntp -f render-pptx/pom.xml -P release -DskipTests -Dgpg.skip=false deploy
233235
env:

CHANGELOG.md

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,24 @@ follow semantic versioning; release dates are ISO 8601.
55

66
## v2.1.1 — Planned
77

8+
### Build
9+
10+
- **The CI guard job runs every guard it names.** It selected eight test classes
11+
while scoping the reactor to `graph-compose-core`: two had been deleted months
12+
earlier and two live in `graph-compose-qa` and `graph-compose-render-pdf`, so
13+
four never ran. Surefire aborts only when a selection is entirely empty, so the
14+
four that did match kept the job green. The list is now the five guards that
15+
live in the engine module, and `CiGuardListGuardTest` fails the job if a name in
16+
it stops resolving.
17+
- **A documentation-only pull request is compiled.** Markdown was not a
18+
change-detection input, so a PR touching only `.md` skipped the reactor build
19+
and merged without `DocumentationSnippetCompileTest` ever compiling the java
20+
fences it publishes. Markdown now routes to the reactor slice that carries those
21+
guards, on the baseline JDK, and still skips example generation.
22+
- **`graph-compose-render-pptx` declares PDFBox.** It compiles against
23+
`org.apache.pdfbox` types while declaring only `fontbox`, taking the rest
24+
transitively; the resolved version is unchanged.
25+
826
### Fixed
927

1028
- **A heading no longer strands above a block that was asked to stay whole.**

0 commit comments

Comments
 (0)