Maven
-
<repository>
- <id>jitpack.io</id>
- <url>https://jitpack.io</url>
-</repository>
-
-<dependency>
- <groupId>com.github.DemchaAV</groupId>
- <artifactId>GraphCompose</artifactId>
- <version>v1.6.5</version>
+<dependency>
+ <groupId>io.github.demchaav</groupId>
+ <artifactId>graphcompose</artifactId>
+ <version>1.6.6</version>
</dependency>
Gradle
-
repositories {
- maven { url 'https://jitpack.io' }
-}
-
-dependencies {
+dependencies {
implementation(
- 'com.github.DemchaAV:GraphCompose:v1.6.5'
+ 'io.github.demchaav:graphcompose:1.6.6'
)
}
diff --git a/scripts/cut-release.ps1 b/scripts/cut-release.ps1
index 41b76744..57a989ae 100644
--- a/scripts/cut-release.ps1
+++ b/scripts/cut-release.ps1
@@ -162,28 +162,49 @@ function Update-ReadmeInstallVersion($readmePath, $newVersion) {
$tag = "v$newVersion"
$changed = $false
- # The README JitPack install snippets pin the git tag (vX.Y.Z). They must
- # flip in the SAME commit the release tag is cut from, so a new user who
- # copy-pastes the README resolves the version this release actually
- # publishes (Phase 2.3 of the release skill: README version flips at
- # release-execution time, never earlier). Two snippets carry it:
- # Maven:
GraphComposevX.Y.Z
- # Gradle: implementation("...:GraphCompose:vX.Y.Z")
- # Lookbehind/lookahead so only the version token is rewritten.
- $mavenRegex = [regex]'(?<=
GraphCompose\s*
)v?[\w\.\-]+(?=)'
- $afterMaven = $mavenRegex.Replace($content, $tag, 1)
+ # The README Maven Central install snippets pin the published version
+ # (X.Y.Z, no `v` prefix). They must flip in the SAME commit the release
+ # tag is cut from, so a new user who copy-pastes the README resolves
+ # the version this release actually publishes (Phase 2.3 of the
+ # release skill: README version flips at release-execution time,
+ # never earlier). Two snippets carry it:
+ # Maven:
graphcomposeX.Y.Z
+ # Gradle: implementation("io.github.demchaav:graphcompose:X.Y.Z")
+ # Lookbehind/lookahead so only the version token is rewritten. A
+ # secondary fallback handles the legacy JitPack format
+ # (
GraphCompose / GraphCompose:vX.Y.Z) so
+ # the script still works if a future change re-introduces a JitPack
+ # snippet for documentation purposes.
+ $mavenCentralRegex = [regex]'(?<=
graphcompose\s*
)v?[\w\.\-]+(?=)'
+ $afterMaven = $mavenCentralRegex.Replace($content, $newVersion, 1)
if ($content -ne $afterMaven) {
$content = $afterMaven
$changed = $true
- Note "bumped README Maven snippet -> $tag"
+ Note "bumped README Maven Central snippet -> $newVersion"
+ } else {
+ $mavenLegacyRegex = [regex]'(?<=
GraphCompose\s*
)v?[\w\.\-]+(?=)'
+ $afterMavenLegacy = $mavenLegacyRegex.Replace($content, $tag, 1)
+ if ($content -ne $afterMavenLegacy) {
+ $content = $afterMavenLegacy
+ $changed = $true
+ Note "bumped README legacy JitPack Maven snippet -> $tag"
+ }
}
- $gradleRegex = [regex]'(?<=:GraphCompose:)v?[\w\.\-]+(?=")'
- $afterGradle = $gradleRegex.Replace($content, $tag, 1)
+ $gradleCentralRegex = [regex]'(?<=io\.github\.demchaav:graphcompose:)v?[\w\.\-]+(?=")'
+ $afterGradle = $gradleCentralRegex.Replace($content, $newVersion, 1)
if ($content -ne $afterGradle) {
$content = $afterGradle
$changed = $true
- Note "bumped README Gradle snippet -> $tag"
+ Note "bumped README Maven Central Gradle snippet -> $newVersion"
+ } else {
+ $gradleLegacyRegex = [regex]'(?<=:GraphCompose:)v?[\w\.\-]+(?=")'
+ $afterGradleLegacy = $gradleLegacyRegex.Replace($content, $tag, 1)
+ if ($content -ne $afterGradleLegacy) {
+ $content = $afterGradleLegacy
+ $changed = $true
+ Note "bumped README legacy JitPack Gradle snippet -> $tag"
+ }
}
if (-not $changed) {
@@ -207,19 +228,20 @@ function Update-IndexHtmlVersion($indexHtmlPath, $newVersion) {
$tag = "v$newVersion"
$changed = $false
- # The GitHub Pages showcase (docs/index.html) hardcodes the version in five
- # spots that do NOT inherit from the pom โ they previously sat at v1.6.1
- # while the library shipped v1.6.4. VersionConsistencyGuardTest fails the
- # verify gate if any lags, so flip all five in lockstep with README + poms:
- # JSON-LD softwareVersion (bare), JitPack downloadUrl, hero badge, and the
- # Maven + Gradle install snippets (all v-prefixed). Lookbehind/lookahead so
- # only the version token is rewritten.
+ # The GitHub Pages showcase (docs/index.html) hardcodes the version in
+ # several spots that do NOT inherit from the pom โ they previously sat at
+ # v1.6.1 while the library shipped v1.6.4. VersionConsistencyGuardTest
+ # fails the verify gate if any lags, so flip them all in lockstep with the
+ # README + poms. The Maven Central format coordinates use bare semver
+ # ($newVersion), the hero badge keeps the v-prefix ($tag), and the
+ # downloadUrl points at the Central artefact page. Lookbehind/lookahead
+ # so only the version token is rewritten.
$replacements = @(
- @{ Regex = [regex]'(?<="softwareVersion": ")v?[\w\.\-]+(?=")'; Value = $newVersion; Label = 'JSON-LD softwareVersion' },
- @{ Regex = [regex]'(?<=jitpack\.io/#DemchaAV/GraphCompose/)v?[\w\.\-]+(?=")'; Value = $tag; Label = 'JitPack downloadUrl' },
- @{ Regex = [regex]'(?<=Java · )v?[\w\.\-]+(?= · MIT)'; Value = $tag; Label = 'hero badge' },
- @{ Regex = [regex]'(?<=<version>)v?[\w\.\-]+(?=</version>)'; Value = $tag; Label = 'Maven snippet' },
- @{ Regex = [regex]"(?<=:GraphCompose:)v?[\w\.\-]+(?=')"; Value = $tag; Label = 'Gradle snippet' }
+ @{ Regex = [regex]'(?<="softwareVersion": ")v?[\w\.\-]+(?=")'; Value = $newVersion; Label = 'JSON-LD softwareVersion' },
+ @{ Regex = [regex]'(?<=https://central\.sonatype\.com/artifact/io\.github\.demchaav/graphcompose/)v?[\w\.\-]+(?=")'; Value = $newVersion; Label = 'Central downloadUrl' },
+ @{ Regex = [regex]'(?<=Java · )v?[\w\.\-]+(?= · MIT)'; Value = $tag; Label = 'hero badge' },
+ @{ Regex = [regex]'(?<=<artifactId>graphcompose</artifactId>\s*<version>)v?[\w\.\-]+(?=</version>)'; Value = $newVersion; Label = 'Maven Central snippet' },
+ @{ Regex = [regex]"(?<=io\.github\.demchaav:graphcompose:)v?[\w\.\-]+(?=')"; Value = $newVersion; Label = 'Gradle Central snippet' }
)
foreach ($r in $replacements) {
diff --git a/src/test/java/com/demcha/documentation/VersionConsistencyGuardTest.java b/src/test/java/com/demcha/documentation/VersionConsistencyGuardTest.java
index a4cb2d8c..de8943b1 100644
--- a/src/test/java/com/demcha/documentation/VersionConsistencyGuardTest.java
+++ b/src/test/java/com/demcha/documentation/VersionConsistencyGuardTest.java
@@ -11,6 +11,8 @@
import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Path;
+import java.util.LinkedHashSet;
+import java.util.Set;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
@@ -18,16 +20,26 @@
/**
* Guards that the GraphCompose version propagates identically to every module
- * and to the README install snippets.
+ * and to the README + showcase install snippets.
*
*
This is the safety net behind the aggregator-reactor version model
* (see {@code aggregator/pom.xml}): the library {@code pom.xml} is the single
* version source, the aggregator bumps every module in lockstep via
* {@code versions:set}, and the child modules inherit their version rather than
* pinning a literal. This test fails the build the moment a bump leaves any
- * module โ or the README copy-paste snippet โ pointing at a different version,
+ * module โ or a copy-paste install snippet โ pointing at a different version,
* which is the drift class that previously let the benchmarks module run
* against the previous release.
+ *
+ *
The snippet checks accept the version as matching either
+ * the current {@code pom.xml} version or the version named in
+ * the top {@code CHANGELOG.md} {@code Planned} entry. This makes the
+ * forward-looking Maven Central snippet (which has to advertise the
+ * about-to-ship version so users copy a coord that will resolve once the tag
+ * lands) compatible with the pre-cut window where {@code pom.xml} still carries
+ * the previous release version. {@code cut-release.ps1} bumps both pom and
+ * snippet to the same target in the release commit, after which the two paths
+ * converge and the test continues to pass.
*/
class VersionConsistencyGuardTest {
@@ -72,50 +84,106 @@ void benchmarksDependencyDerivesVersionAndIsNotHardcoded() throws IOException {
@Test
void readmeInstallSnippetsMatchTheProjectVersion() throws Exception {
- String root = effectiveVersion(PROJECT_ROOT.resolve("pom.xml"));
+ Set targets = acceptableTargets();
String readme = Files.readString(PROJECT_ROOT.resolve("README.md"));
- String mavenSnippetVersion = firstGroup(readme,
- "GraphCompose\\s*v?([0-9][^<]*)");
- String gradleSnippetVersion = firstGroup(readme,
- "GraphCompose:v?([0-9][^\")]*)");
+ String mavenSnippetVersion = firstMatchingGroup(readme, INSTALL_SNIPPET_PATTERNS_README_MAVEN);
+ String gradleSnippetVersion = firstMatchingGroup(readme, INSTALL_SNIPPET_PATTERNS_README_GRADLE);
assertThat(mavenSnippetVersion)
- .describedAs("README Maven/JitPack snippet must reference the current project version (%s)", root)
- .isEqualTo(root);
+ .describedAs("README Maven install snippet must reference the current pom or CHANGELOG Planned version (one of %s)", targets)
+ .isIn(targets);
assertThat(gradleSnippetVersion)
- .describedAs("README Gradle/JitPack snippet must reference the current project version (%s)", root)
- .isEqualTo(root);
+ .describedAs("README Gradle install snippet must reference the current pom or CHANGELOG Planned version (one of %s)", targets)
+ .isIn(targets);
}
/**
* The GitHub Pages showcase ({@code docs/index.html}) hardcodes the version
- * in five spots โ JSON-LD {@code softwareVersion}, the JitPack download URL,
- * the hero badge, and the Maven + Gradle install snippets. None of these
- * inherit from the pom, so without this guard they silently drift (they sat
- * at v1.6.1 while the library shipped v1.6.4). {@code cut-release.ps1} flips
- * them on release; this fails the verify gate if any spot lags behind.
+ * in three spots โ JSON-LD {@code softwareVersion}, the hero badge, and the
+ * Maven + Gradle install snippets. None inherit from the pom, so without
+ * this guard they silently drift. {@code cut-release.ps1} flips them on
+ * release; this fails the verify gate if any spot lags behind.
*/
@Test
void showcaseSiteVersionMatchesTheProjectVersion() throws Exception {
- String root = effectiveVersion(PROJECT_ROOT.resolve("pom.xml"));
+ Set targets = acceptableTargets();
String site = Files.readString(PROJECT_ROOT.resolve("docs/index.html"));
assertThat(firstGroup(site, "\"softwareVersion\":\\s*\"v?([0-9][^\"]*)\""))
- .describedAs("docs/index.html JSON-LD softwareVersion must equal the project version (%s)", root)
- .isEqualTo(root);
- assertThat(firstGroup(site, "jitpack\\.io/#DemchaAV/GraphCompose/v?([0-9][^\"]*)"))
- .describedAs("docs/index.html JitPack downloadUrl must equal the project version (%s)", root)
- .isEqualTo(root);
+ .describedAs("docs/index.html JSON-LD softwareVersion must equal the current pom or planned version (one of %s)", targets)
+ .isIn(targets);
assertThat(firstGroup(site, "v([0-9][0-9.]*)\\s*·\\s*MIT"))
- .describedAs("docs/index.html hero version badge must equal the project version (%s)", root)
- .isEqualTo(root);
- assertThat(firstGroup(site, "<version>v?([0-9][^&]*)</version>"))
- .describedAs("docs/index.html Maven install snippet must equal the project version (%s)", root)
- .isEqualTo(root);
- assertThat(firstGroup(site, "GraphCompose:v?([0-9][^')]*)"))
- .describedAs("docs/index.html Gradle install snippet must equal the project version (%s)", root)
- .isEqualTo(root);
+ .describedAs("docs/index.html hero version badge must equal the current pom or planned version (one of %s)", targets)
+ .isIn(targets);
+ assertThat(firstMatchingGroup(site, INSTALL_SNIPPET_PATTERNS_SHOWCASE_MAVEN))
+ .describedAs("docs/index.html Maven install snippet must equal the current pom or planned version (one of %s)", targets)
+ .isIn(targets);
+ assertThat(firstMatchingGroup(site, INSTALL_SNIPPET_PATTERNS_SHOWCASE_GRADLE))
+ .describedAs("docs/index.html Gradle install snippet must equal the current pom or planned version (one of %s)", targets)
+ .isIn(targets);
+ }
+
+ // โโ Install-snippet patterns โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
+ // Each install snippet check tries the Maven Central format first
+ // (canonical from v1.6.6 onwards) and falls back to the legacy
+ // JitPack format (kept resolvable for v1.6.5-and-earlier pinned
+ // consumers and possibly still present during the migration
+ // window). The first regex with a match wins.
+
+ private static final String[] INSTALL_SNIPPET_PATTERNS_README_MAVEN = {
+ "graphcompose\\s*v?([0-9][^<]*)",
+ "GraphCompose\\s*v?([0-9][^<]*)"
+ };
+ private static final String[] INSTALL_SNIPPET_PATTERNS_README_GRADLE = {
+ "io\\.github\\.demchaav:graphcompose:v?([0-9][^\")]*)",
+ "GraphCompose:v?([0-9][^\")]*)"
+ };
+ private static final String[] INSTALL_SNIPPET_PATTERNS_SHOWCASE_MAVEN = {
+ "<artifactId>graphcompose</artifactId>\\s*<version>v?([0-9][^&]*)</version>",
+ "<version>v?([0-9][^&]*)</version>"
+ };
+ private static final String[] INSTALL_SNIPPET_PATTERNS_SHOWCASE_GRADLE = {
+ "io\\.github\\.demchaav:graphcompose:v?([0-9][^')]*)",
+ "GraphCompose:v?([0-9][^')]*)"
+ };
+
+ /**
+ * Returns the set of versions that any install snippet may legitimately
+ * advertise: the current {@code pom.xml} version always, plus the version
+ * named in the top {@code CHANGELOG.md} {@code Planned} entry if one
+ * exists. The Planned entry covers the pre-cut window where {@code pom.xml}
+ * still carries the previous release version while the README + showcase
+ * already advertise the about-to-ship version.
+ */
+ private Set acceptableTargets() throws Exception {
+ Set targets = new LinkedHashSet<>();
+ targets.add(effectiveVersion(PROJECT_ROOT.resolve("pom.xml")));
+ String changelog = Files.readString(PROJECT_ROOT.resolve("CHANGELOG.md"));
+ Matcher planned = Pattern.compile("^## v([0-9][^ \\n]*)\\s*[\\u2014\\-]\\s*Planned\\b", Pattern.MULTILINE)
+ .matcher(changelog);
+ if (planned.find()) {
+ targets.add(planned.group(1));
+ }
+ return targets;
+ }
+
+ /**
+ * Returns the captured group of the first regex in {@code patterns} that
+ * matches. Fails with a descriptive message listing every pattern tried if
+ * none matches.
+ */
+ private static String firstMatchingGroup(String text, String[] patterns) {
+ for (String regex : patterns) {
+ Matcher matcher = Pattern.compile(regex).matcher(text);
+ if (matcher.find()) {
+ return matcher.group(1);
+ }
+ }
+ assertThat(false)
+ .describedAs("Expected at least one version token matching one of these patterns: %s", String.join(" | ", patterns))
+ .isTrue();
+ throw new IllegalStateException("unreachable");
}
private static String firstGroup(String text, String regex) {