Skip to content

Commit 953f4fc

Browse files
authored
fix(release-script): install render-pptx before regenerating the showcase (#455)
Step 4 runs ShowcaseSync from the examples module after the version bump, so every train sibling the examples depend on must already be in the local cache at the new version. The list it installs from was written before render-pptx existed and never gained it, while examples/pom.xml took a compile dependency on it for the PPTX twins. The cut therefore aborts mid-flight — "Could not find artifact graph-compose-render-pptx:jar:2.1.0" — with every pom, README and the changelog date already rewritten, leaving a dirty tree to unwind by hand. A new guard derives the required set from examples/pom.xml and fails the build when the two drift. It matches only dependencies pinned to ${graphcompose.version}: fonts and emoji keep independent release lines and resolve from Central. It does not assert the reverse, because the list legitimately carries render-pdf, which the examples reach through the wrapper and which is bumped all the same.
1 parent 5b92778 commit 953f4fc

2 files changed

Lines changed: 113 additions & 2 deletions

File tree

Lines changed: 105 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,105 @@
1+
package com.demcha.documentation;
2+
3+
import org.junit.jupiter.api.Test;
4+
5+
import java.io.IOException;
6+
import java.nio.file.Files;
7+
import java.nio.file.Path;
8+
import java.util.LinkedHashSet;
9+
import java.util.Set;
10+
import java.util.regex.Matcher;
11+
import java.util.regex.Pattern;
12+
13+
import static org.assertj.core.api.Assertions.assertThat;
14+
15+
/**
16+
* Guards the hand-maintained module list that {@code cut-release.ps1} installs
17+
* before it runs {@code ShowcaseSync}.
18+
*
19+
* <p>Step 4 of the release script regenerates {@code web/examples.json} by running
20+
* {@code exec:java} in the examples module. By that point every train pom carries
21+
* the just-bumped release version, which exists in no repository yet — so each
22+
* sibling the examples module depends on at that version must have been installed
23+
* into the local cache first. The script does that from a literal list.</p>
24+
*
25+
* <p>A module added to {@code examples/pom.xml} but not to that list fails the cut
26+
* <em>mid-flight</em>, after the version bump has already rewritten every pom,
27+
* README and the changelog date, leaving a dirty tree to unwind by hand. That is
28+
* how {@code graph-compose-render-pptx} — which the examples gained for the PPTX
29+
* twin examples — aborted a 2.1.0 cut. This test fails in CI instead.</p>
30+
*
31+
* <p>Only dependencies pinned to {@code ${graphcompose.version}} are checked. The
32+
* independently-versioned companions ({@code graph-compose-fonts},
33+
* {@code graph-compose-emoji}) keep their own release lines and resolve from
34+
* Central, so the cut never has to build them.</p>
35+
*
36+
* <p>The reverse direction is deliberately not asserted: the list legitimately
37+
* carries modules the examples reach only transitively — {@code render-pdf} comes
38+
* in through the {@code graph-compose} wrapper, and it too is bumped, so it too
39+
* must be installed.</p>
40+
*/
41+
class ReleaseScriptInstallListGuardTest {
42+
43+
private static final Path PROJECT_ROOT = RepoRoot.get();
44+
45+
/** A {@code graph-compose-*} dependency pinned to the train version. */
46+
private static final Pattern TRAIN_DEPENDENCY = Pattern.compile(
47+
"<artifactId>(graph-compose[a-z-]*)</artifactId>\\s*"
48+
+ "<version>\\$\\{graphcompose\\.version}</version>");
49+
50+
/** The literal PowerShell array the script installs from. */
51+
private static final Pattern INSTALL_LIST = Pattern.compile(
52+
"\\$exampleSnapshotSiblings\\s*=\\s*@\\(([^)]*)\\)", Pattern.DOTALL);
53+
54+
@Test
55+
void releaseScriptInstallsEveryTrainSiblingTheExamplesDependOn() throws IOException {
56+
Set<String> required = examplesTrainSiblings();
57+
58+
assertThat(required)
59+
.describedAs("sanity: the examples module must depend on at least one train sibling — "
60+
+ "an empty set would make this guard pass against anything")
61+
.isNotEmpty();
62+
assertThat(scriptInstallList())
63+
.describedAs("cut-release.ps1 must keep $exampleSnapshotSiblings in lockstep with "
64+
+ "examples/pom.xml — a train sibling missing here aborts Step 4 of the cut "
65+
+ "after the version bump has already rewritten the tree")
66+
.containsAll(required);
67+
}
68+
69+
/**
70+
* Artifact ids of the train-versioned {@code graph-compose-*} siblings the
71+
* examples depend on, ignoring the {@code <parent>} coordinate.
72+
*/
73+
private static Set<String> examplesTrainSiblings() throws IOException {
74+
String pom = Files.readString(PROJECT_ROOT.resolve("examples/pom.xml"))
75+
.replaceAll("(?s)<parent>.*?</parent>", "");
76+
Set<String> ids = new LinkedHashSet<>();
77+
Matcher matcher = TRAIN_DEPENDENCY.matcher(pom);
78+
while (matcher.find()) {
79+
ids.add(matcher.group(1));
80+
}
81+
return ids;
82+
}
83+
84+
/**
85+
* Artifact ids the script installs, derived from the pom paths in its list
86+
* ({@code render-pptx/pom.xml} → {@code graph-compose-render-pptx}, and the
87+
* directory {@code wrapper/} → the bare {@code graph-compose} coordinate).
88+
*/
89+
private static Set<String> scriptInstallList() throws IOException {
90+
String script = Files.readString(PROJECT_ROOT.resolve("scripts/cut-release.ps1"));
91+
Matcher list = INSTALL_LIST.matcher(script);
92+
assertThat(list.find())
93+
.describedAs("cut-release.ps1 no longer declares $exampleSnapshotSiblings — this guard "
94+
+ "is reading a list that moved, so it is no longer guarding anything")
95+
.isTrue();
96+
97+
Set<String> ids = new LinkedHashSet<>();
98+
Matcher path = Pattern.compile("'([^']+)/pom\\.xml'").matcher(list.group(1));
99+
while (path.find()) {
100+
String module = path.group(1);
101+
ids.add(module.equals("wrapper") ? "graph-compose" : "graph-compose-" + module);
102+
}
103+
return ids;
104+
}
105+
}

scripts/cut-release.ps1

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -514,8 +514,14 @@ function Run-ShowcaseSync {
514514
# as a single literal argument.
515515
$execProp = '"-Dexec.mainClass=com.demcha.examples.support.ShowcaseSync"'
516516
# The examples module depends on these bumped SNAPSHOT siblings (not on
517-
# Central); each must be installed before exec:java can resolve them.
518-
$exampleSnapshotSiblings = @('render-pdf/pom.xml', 'wrapper/pom.xml', 'render-docx/pom.xml', 'templates/pom.xml', 'testing/pom.xml')
517+
# Central); each must be installed before exec:java can resolve them. Keep
518+
# this list in lockstep with examples/pom.xml — a module the examples depend
519+
# on but that is missing here fails Step 4 with "Could not find artifact
520+
# …:<new version>", because the just-bumped version exists nowhere yet.
521+
# ReleaseScriptInstallListGuardTest fails the build if the two drift apart.
522+
# render-pptx must follow render-pdf: it depends on it at compile scope.
523+
$exampleSnapshotSiblings = @('render-pdf/pom.xml', 'wrapper/pom.xml', 'render-docx/pom.xml',
524+
'render-pptx/pom.xml', 'templates/pom.xml', 'testing/pom.xml')
519525
if ($DryRun) {
520526
Write-Host " [DRY RUN] $mvnw -B -ntp -DskipTests install -pl :graph-compose-core" -ForegroundColor Yellow
521527
foreach ($modulePom in $exampleSnapshotSiblings) {

0 commit comments

Comments
 (0)