Skip to content

Commit 1e8cf36

Browse files
committed
Autocheck for new DOMjudge releases
Discussed during the hackathon in 2023. We allow admins to toggle an autoquery to domjudge.org for 2 reasons: - Alerting users that a new version might exist, helping us in case of security releases. - Giving a gentle nudge for people to upgrade making support easier. - Getting some information on what installations are out there.
1 parent d6dd5b3 commit 1e8cf36

File tree

6 files changed

+124
-3
lines changed

6 files changed

+124
-3
lines changed

etc/db-config.yaml

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -392,6 +392,11 @@
392392
description: Time in seconds after an external contest source reader last checked in before showing its status as `critical`.
393393
regex: /^\d+$/
394394
error_message: A non-negative number is required.
395+
- name: check_new_version
396+
type: bool
397+
default_value: false
398+
public: false
399+
description: Automatically check for new DOMjudge release?
395400
- name: adminer_enabled
396401
type: bool
397402
default_value: false

webapp/composer.json

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -111,7 +111,8 @@
111111
"twig/extra-bundle": "^3.5",
112112
"twig/markdown-extra": "^3.5",
113113
"twig/string-extra": "^3.5",
114-
"twig/twig": "^3.6"
114+
"twig/twig": "^3.6",
115+
"z4kn4fein/php-semver": "^3.0"
115116
},
116117
"require-dev": {
117118
"ext-dom": "*",

webapp/composer.lock

Lines changed: 56 additions & 2 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

webapp/src/Service/DOMJudgeService.php

Lines changed: 53 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -63,6 +63,7 @@
6363
use Symfony\Component\Security\Core\Authorization\AuthorizationCheckerInterface;
6464
use Symfony\Component\Security\Core\User\UserInterface;
6565
use Twig\Environment;
66+
use z4kn4fein\SemVer\Version;
6667
use ZipArchive;
6768

6869
class DOMJudgeService
@@ -1671,4 +1672,56 @@ public function getAllowedLanguagesForContest(?Contest $contest) : array {
16711672
->getQuery()
16721673
->getResult();
16731674
}
1675+
1676+
public function checkNewVersion(): string|false {
1677+
if (!$this->config->get('check_new_version')) {
1678+
return false;
1679+
}
1680+
$versionLocalString = explode("/", str_replace("DEV", "-prerelease", DOMJUDGE_VERSION))[0];
1681+
$versionLocal = Version::parse($versionLocalString, false);
1682+
$versionUrl = 'http://localhost:81/versions.json';
1683+
$options = ['http' => ['method' => 'GET', 'header' => "User-Agent: tarball/" . $versionLocalString . "\r\n"]];
1684+
$context = stream_context_create($options);
1685+
$response = file_get_contents($versionUrl, false, $context);
1686+
$versions = json_decode($response, true);
1687+
/* Steer towards to the latest patch first
1688+
* the user can see on the website if there is a new Major/minor themselves
1689+
* otherwise the latest minor, or Major release. So the user might make the upgrade path:
1690+
* DJ6.0.0 -> DJ6.0.6 -> DJ6.6.0 -> DJ9.0.0 instead of
1691+
* -> DJ6.0.[1..6] -> DJ6.[1..6] -> DJ[7..9].0.0
1692+
*/
1693+
$latestPatchString = $versionLocal;
1694+
if (isset($versions[$versionLocal->getMajor()][$versionLocal->getMinor()])) {
1695+
$latestPatchString = Version::rsortString($versions[$versionLocal->getMajor()][$versionLocal->getMinor()])[0];
1696+
$latestPatch = Version::parse($latestPatchString);
1697+
if (Version::compare($versionLocal, $latestPatch) < 0) {
1698+
return $latestPatchString;
1699+
}
1700+
}
1701+
$latestMinorString = $versionLocal;
1702+
if (isset($versions[$versionLocal->getMajor()])) {
1703+
$highestMinorInMajor = array_keys($versions[$versionLocal->getMajor()]);
1704+
rsort($highestMinorInMajor);
1705+
$latestMinorString = Version::rsortString($versions[$versionLocal->getMajor()][$highestMinorInMajor[0]])[0];
1706+
$latestMinor = Version::parse($latestMinorString);
1707+
if (Version::compare($versionLocal, $latestMinor) < 0) {
1708+
return $latestMinorString;
1709+
}
1710+
}
1711+
$latestMajorString = $versionLocal;
1712+
try {
1713+
$highestMajor = array_keys($versions);
1714+
rsort($highestMajor);
1715+
$highestMinorInMajor = array_keys($versions[$highestMajor[0]]);
1716+
rsort($highestMinorInMajor);
1717+
$latestMajorString = Version::rsortString($versions[$highestMajor[0]][$highestMinorInMajor[0]])[0];
1718+
$latestMajor = Version::parse($latestMajorString);
1719+
if (Version::compare($versionLocal, $latestMajor) < 0) {
1720+
return $latestMajorString;
1721+
}
1722+
} catch (Exception $e) {
1723+
return false;
1724+
}
1725+
return false;
1726+
}
16741727
}

webapp/src/Twig/TwigExtension.php

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -159,6 +159,7 @@ public function getGlobals(): array
159159
'doc_links' => $this->dj->getDocLinks(),
160160
'allow_registration' => $selfRegistrationCategoriesCount !== 0,
161161
'enable_ranking' => $this->config->get('enable_ranking'),
162+
'new_version_available' => $this->dj->checkNewVersion(),
162163
'editor_themes' => [
163164
'vs' => ['name' => 'Visual Studio (light)'],
164165
'vs-dark' => ['name' => 'Visual Studio (dark)'],

webapp/templates/jury/menu.html.twig

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -93,6 +93,13 @@
9393
</li>
9494
</ul>
9595
{% endif %}
96+
{% if new_version_available %}
97+
<ul class="navbar-nav">
98+
<li class="nav-item nav-link">
99+
<i class="fa-solid fa-ship fa-2x"></i> New release {{ new_version_available }} available.
100+
</li>
101+
</ul>
102+
{% endif %}
96103

97104
<ul class="navbar-nav ml-auto">
98105

0 commit comments

Comments
 (0)