Skip to content

Commit 33fca78

Browse files
authored
Add update checker to notify about new versions (#22)
Checks GitHub releases API on startup and logs a message if a newer version is available. The check runs asynchronously to avoid blocking server startup.
1 parent d9855ef commit 33fca78

File tree

2 files changed

+94
-0
lines changed

2 files changed

+94
-0
lines changed

core/src/main/java/com/minekube/connect/ConnectPlatform.java

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -43,6 +43,7 @@
4343
import com.minekube.connect.register.WatcherRegister;
4444
import com.minekube.connect.tunnel.Tunneler;
4545
import com.minekube.connect.util.Metrics;
46+
import com.minekube.connect.util.UpdateChecker;
4647
import java.io.IOException;
4748
import java.nio.file.Files;
4849
import java.nio.file.Path;
@@ -127,6 +128,9 @@ public boolean enable(Module... postInitializeModules) {
127128
}
128129
logger.info("Your public address: " + config.getEndpoint() + DOMAIN_SUFFIX);
129130

131+
// Check for updates asynchronously
132+
guice.getInstance(UpdateChecker.class).checkForUpdates();
133+
130134
return true;
131135
}
132136

Lines changed: 90 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,90 @@
1+
package com.minekube.connect.util;
2+
3+
import com.google.gson.JsonObject;
4+
import com.google.inject.Inject;
5+
import com.minekube.connect.api.logger.ConnectLogger;
6+
7+
public class UpdateChecker {
8+
private static final String GITHUB_API_URL =
9+
"https://api.github.com/repos/minekube/connect-java/releases/latest";
10+
11+
private final ConnectLogger logger;
12+
13+
@Inject
14+
public UpdateChecker(ConnectLogger logger) {
15+
this.logger = logger;
16+
}
17+
18+
public void checkForUpdates() {
19+
HttpUtils.asyncGet(GITHUB_API_URL).thenAccept(response -> {
20+
if (!response.isCodeOk()) {
21+
logger.debug("Failed to check for updates: HTTP " + response.getHttpCode());
22+
return;
23+
}
24+
25+
JsonObject json = response.getResponse();
26+
if (json == null || !json.has("tag_name")) {
27+
logger.debug("Failed to parse update response");
28+
return;
29+
}
30+
31+
String latestVersion = json.get("tag_name").getAsString();
32+
String currentVersion = Constants.VERSION;
33+
34+
// Remove 'v' prefix if present
35+
if (latestVersion.startsWith("v")) {
36+
latestVersion = latestVersion.substring(1);
37+
}
38+
39+
// Skip check for development versions
40+
if (currentVersion.contains("SNAPSHOT") || currentVersion.contains("${")) {
41+
logger.debug("Running development version, skipping update check");
42+
return;
43+
}
44+
45+
if (isNewerVersion(latestVersion, currentVersion)) {
46+
logger.info("A new version of Connect is available: " + latestVersion
47+
+ " (current: " + currentVersion + ")");
48+
logger.info("Download: https://github.com/minekube/connect-java/releases/latest");
49+
} else {
50+
logger.debug("Connect is up to date (version " + currentVersion + ")");
51+
}
52+
}).exceptionally(throwable -> {
53+
logger.debug("Failed to check for updates: " + throwable.getMessage());
54+
return null;
55+
});
56+
}
57+
58+
/**
59+
* Compares two semantic version strings.
60+
* @return true if latestVersion is newer than currentVersion
61+
*/
62+
private boolean isNewerVersion(String latestVersion, String currentVersion) {
63+
try {
64+
int[] latest = parseVersion(latestVersion);
65+
int[] current = parseVersion(currentVersion);
66+
67+
for (int i = 0; i < Math.max(latest.length, current.length); i++) {
68+
int l = i < latest.length ? latest[i] : 0;
69+
int c = i < current.length ? current[i] : 0;
70+
if (l > c) return true;
71+
if (l < c) return false;
72+
}
73+
return false;
74+
} catch (Exception e) {
75+
// If parsing fails, do string comparison
76+
return !latestVersion.equals(currentVersion);
77+
}
78+
}
79+
80+
private int[] parseVersion(String version) {
81+
// Remove any suffix like -SNAPSHOT, -beta, etc.
82+
String cleanVersion = version.split("-")[0];
83+
String[] parts = cleanVersion.split("\\.");
84+
int[] result = new int[parts.length];
85+
for (int i = 0; i < parts.length; i++) {
86+
result[i] = Integer.parseInt(parts[i]);
87+
}
88+
return result;
89+
}
90+
}

0 commit comments

Comments
 (0)