fix(panel): recognize this fork's -awg.N tags in version comparison

internal/config/version was never bumped past 3.5.0 when v3.5.0-awg.1 was
tagged, so a freshly-updated panel kept reporting its own version as the
plain upstream base. On top of that, parseVersionParts (Go and its
TypeScript mirror) required exactly 3 dot-separated numeric parts, so it
rejected the -awg.N suffix entirely and fell back to a raw string
inequality that reports "update available" any time the strings merely
differ -- which they always do here, even when already on the latest tag.

Bump the embedded version to 3.5.0-awg.1 and extend both parsers to treat
"-awg.N" as an optional 4th, lower-priority component (defaulting to 0 for
a plain tag), so e.g. 3.5.0-awg.2 > 3.5.0-awg.1 > 3.5.0 and a matching tag
compares equal instead of always looking outdated.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
This commit is contained in:
Kuzz007
2026-07-26 12:42:20 +03:00
parent 0372515aa2
commit 814369da38
6 changed files with 71 additions and 20 deletions
+12 -14
View File
@@ -1,17 +1,15 @@
// Mirror of web/service/panel.go isNewerVersion: parse a vMAJOR.MINOR.PATCH tag
// and report whether `latest` is ahead of `current`. When either side isn't a
// clean three-part numeric tag, fall back to a normalized string inequality —
// the same heuristic the Go side uses so the node "update available" badge
// agrees with what the server would decide.
function parseVersionParts(version: string): [number, number, number] | null {
const parts = version.trim().replace(/^v/, '').split('.');
if (parts.length !== 3) return null;
const out: number[] = [];
for (const part of parts) {
if (!/^\d+$/.test(part)) return null;
out.push(Number(part));
}
return [out[0], out[1], out[2]];
// (or this fork's own "vMAJOR.MINOR.PATCH-awg.N" release tag, see
// internal/config/version) and report whether `latest` is ahead of `current`.
// When either side isn't a recognized tag, fall back to a normalized string
// inequality — the same heuristic the Go side uses so the node "update
// available" badge agrees with what the server would decide.
const VERSION_PARTS_PATTERN = /^v?(\d+)\.(\d+)\.(\d+)(?:-awg\.(\d+))?$/;
function parseVersionParts(version: string): [number, number, number, number] | null {
const match = VERSION_PARTS_PATTERN.exec(version.trim());
if (!match) return null;
return [Number(match[1]), Number(match[2]), Number(match[3]), Number(match[4] || 0)];
}
// Format a panel version for display. Dev builds report a "dev+<commit>"
@@ -33,7 +31,7 @@ export function isPanelUpdateAvailable(latest: string, current: string): boolean
if (!a || !b) {
return latest.trim().replace(/^v/, '') !== current.trim().replace(/^v/, '');
}
for (let i = 0; i < 3; i++) {
for (let i = 0; i < 4; i++) {
if (a[i] > b[i]) return true;
if (a[i] < b[i]) return false;
}
+12
View File
@@ -30,6 +30,18 @@ describe('isPanelUpdateAvailable', () => {
expect(isPanelUpdateAvailable('nightly-2', 'nightly-1')).toBe(true);
expect(isPanelUpdateAvailable('nightly-1', 'nightly-1')).toBe(false);
});
// Parity with web/service/panel.go TestIsNewerVersionAwgSuffix -- this
// fork's own "-awg.N" release tags (see internal/config/version).
it('handles this fork\'s -awg.N release tags', () => {
expect(isPanelUpdateAvailable('v3.5.0-awg.1', '3.5.0-awg.1')).toBe(false);
expect(isPanelUpdateAvailable('v3.5.0-awg.2', '3.5.0-awg.1')).toBe(true);
expect(isPanelUpdateAvailable('v3.5.0-awg.1', '3.5.0-awg.2')).toBe(false);
expect(isPanelUpdateAvailable('v3.5.0-awg.1', '3.5.0')).toBe(true);
expect(isPanelUpdateAvailable('v3.5.0', '3.5.0-awg.1')).toBe(false);
expect(isPanelUpdateAvailable('v3.6.0', '3.5.0-awg.1')).toBe(true);
expect(isPanelUpdateAvailable('v3.5.0-awg.1', '3.6.0')).toBe(false);
});
});
describe('formatPanelVersion', () => {