diff --git a/jib-plugins-common/src/main/java/com/google/cloud/tools/jib/plugins/common/UpdateChecker.java b/jib-plugins-common/src/main/java/com/google/cloud/tools/jib/plugins/common/UpdateChecker.java index 6b2d136728..5ac7ecc0d5 100644 --- a/jib-plugins-common/src/main/java/com/google/cloud/tools/jib/plugins/common/UpdateChecker.java +++ b/jib-plugins-common/src/main/java/com/google/cloud/tools/jib/plugins/common/UpdateChecker.java @@ -61,6 +61,57 @@ private static class VersionJsonTemplate implements JsonTemplate { * @param log {@link Consumer} used to log messages * @return a new {@link UpdateChecker} */ + + @VisibleForTesting + static int compareVersions(String v1, String v2) { + String[] p1 = v1.split("\\."); + String[] p2 = v2.split("\\."); + + int len = Math.max(p1.length, p2.length); + for (int i = 0; i < len; i++) { + String s1 = i < p1.length ? p1[i] : "0"; + String s2 = i < p2.length ? p2[i] : "0"; + + int n1 = parseNumericPrefix(s1); + int n2 = parseNumericPrefix(s2); + + if (n1 != n2) { + return Integer.compare(n1, n2); + } + + // Handle suffixes (e.g., "1-SNAPSHOT", "1-beta") + String suf1 = suffix(s1); + String suf2 = suffix(s2); + + if (!suf1.equals(suf2)) { + if (suf1.isEmpty()) return 1; // no suffix ⇒ stable release ⇒ newer + if (suf2.isEmpty()) return -1; // suffix ⇒ prerelease ⇒ older + return suf1.compareTo(suf2); // both have suffix ⇒ lexicographic + } + } + return 0; + } + + private static int parseNumericPrefix(String s) { + int i = 0; + while (i < s.length() && Character.isDigit(s.charAt(i))) i++; + if (i == 0) return 0; + try { + return Integer.parseInt(s.substring(0, i)); + } catch (NumberFormatException ex) { + return 0; + } + } + + private static String suffix(String s) { + int i = 0; + while (i < s.length() && Character.isDigit(s.charAt(i))) i++; + return s.substring(i); // "" if no suffix + } + + + + public static Future> checkForUpdate( ExecutorService executorService, String versionUrl, @@ -118,10 +169,16 @@ static Optional performUpdateCheck( Files.write(lastUpdateCheckTemp, Instant.now().toString().getBytes(StandardCharsets.UTF_8)); Files.move(lastUpdateCheckTemp, lastUpdateCheck, StandardCopyOption.REPLACE_EXISTING); - if (currentVersion.equals(version.latest)) { + if (version.latest == null || version.latest.isEmpty()) { return Optional.empty(); } - return Optional.of(version.latest); + + if (compareVersions(currentVersion, version.latest) < 0) { + return Optional.of(version.latest); // only report if newer + } + + return Optional.empty(); // otherwise equal or older + } finally { httpClient.shutDown(); } diff --git a/jib-plugins-common/src/test/java/com/google/cloud/tools/jib/plugins/common/UpdateCheckerTest.java b/jib-plugins-common/src/test/java/com/google/cloud/tools/jib/plugins/common/UpdateCheckerTest.java index 7b918ee2e0..b9932e09d3 100644 --- a/jib-plugins-common/src/test/java/com/google/cloud/tools/jib/plugins/common/UpdateCheckerTest.java +++ b/jib-plugins-common/src/test/java/com/google/cloud/tools/jib/plugins/common/UpdateCheckerTest.java @@ -62,6 +62,21 @@ public void setUp() configDir = temporaryFolder.getRoot().toPath(); } + @Test + public void testCompareVersions() { + assertThat(UpdateChecker.compareVersions("3.5.0", "3.4.6")).isGreaterThan(0); + assertThat(UpdateChecker.compareVersions("3.4.6", "3.5.0")).isLessThan(0); + assertThat(UpdateChecker.compareVersions("3.5.0", "3.5.0")).isEqualTo(0); + assertThat(UpdateChecker.compareVersions("3.5", "3.5.0")).isEqualTo(0); + assertThat(UpdateChecker.compareVersions("3.5.1", "3.5")).isGreaterThan(0); + assertThat(UpdateChecker.compareVersions("1.0.0-SNAPSHOT", "1.0.0")).isLessThan(0); + assertThat(UpdateChecker.compareVersions("1.0.0-alpha", "1.0.0-beta")).isLessThan(0); + assertThat(UpdateChecker.compareVersions("1.0.0-beta", "1.0.0")).isLessThan(0); + assertThat(UpdateChecker.compareVersions("1.0.0", "1.0.0-alpha")).isGreaterThan(0); + + } + + @After public void tearDown() throws IOException { testWebServer.close();