Merge pull request #362 from naturallaw777/arena/019fae4f-sovran-systemsos
Show deployed PHP app versions in service titles
This commit is contained in:
@@ -2544,6 +2544,47 @@ _NIX_WRAPPER_SUFFIX_RE = re.compile(
|
||||
r"-(?:env|wrapper|wrapped|script|hook|setup|compat)$"
|
||||
)
|
||||
|
||||
# These two applications are downloaded into /var/lib/www at install time, so
|
||||
# their PHP-FPM pool units identify the runtime but not the deployed application
|
||||
# release. Read each application's own version file instead of reporting a PHP
|
||||
# or Nix package version that can be unrelated to what Caddy is serving.
|
||||
_DEPLOYED_WEB_APPLICATION_VERSION_FILES: dict[str, tuple[str, re.Pattern[str]]] = {
|
||||
"phpfpm-nextcloud.service": (
|
||||
"/var/lib/www/nextcloud/version.php",
|
||||
re.compile(r"^\s*\$OC_VersionString\s*=\s*['\"]([^'\"]+)['\"]\s*;", re.MULTILINE),
|
||||
),
|
||||
"phpfpm-wordpress.service": (
|
||||
"/var/lib/www/wordpress/wp-includes/version.php",
|
||||
re.compile(r"^\s*\$wp_version\s*=\s*['\"]([^'\"]+)['\"]\s*;", re.MULTILINE),
|
||||
),
|
||||
}
|
||||
|
||||
|
||||
def _get_deployed_web_application_version(unit: str) -> str | None:
|
||||
"""Return the version embedded in a PHP application deployed under /var/lib/www."""
|
||||
spec = _DEPLOYED_WEB_APPLICATION_VERSION_FILES.get(unit)
|
||||
if spec is None:
|
||||
return None
|
||||
|
||||
path, version_pattern = spec
|
||||
try:
|
||||
# The version files are short PHP metadata files. Limiting the read makes
|
||||
# this safe even if an installation is damaged or has been replaced.
|
||||
with open(path, "r", encoding="utf-8", errors="replace") as fh:
|
||||
contents = fh.read(64 * 1024)
|
||||
except OSError:
|
||||
return None
|
||||
|
||||
match = version_pattern.search(contents)
|
||||
if match is None:
|
||||
return None
|
||||
|
||||
version = match.group(1).strip()
|
||||
if not version or len(version) > 64:
|
||||
return None
|
||||
return version if version.startswith("v") else f"v{version}"
|
||||
|
||||
|
||||
# Cache: unit → (monotonic_timestamp, version_str | None)
|
||||
_svc_version_cache: dict[str, tuple[float, str | None]] = {}
|
||||
_SVC_VERSION_CACHE_TTL = 300 # 5 minutes — versions only change on system update
|
||||
@@ -2552,10 +2593,13 @@ _SVC_VERSION_CACHE_TTL = 300 # 5 minutes — versions only change on system upd
|
||||
def _get_service_version(unit: str) -> str | None:
|
||||
"""Extract the version of a service.
|
||||
|
||||
Checks the Nix-generated build-time versions reference file (loaded via load_versions()) first.
|
||||
Falls back to running ``systemctl show <unit> --property=ExecStart --value`` and parsing
|
||||
the Nix store path embedded in the output if the reference file is missing or incomplete.
|
||||
PHP applications deployed under /var/lib/www are read from their own version
|
||||
files. Other services first use the Nix-generated build-time version reference
|
||||
and then fall back to parsing a Nix store path in their systemd ExecStart.
|
||||
"""
|
||||
if unit in _DEPLOYED_WEB_APPLICATION_VERSION_FILES:
|
||||
return _get_deployed_web_application_version(unit)
|
||||
|
||||
try:
|
||||
versions_ref = load_versions()
|
||||
ver = versions_ref.get(unit)
|
||||
|
||||
@@ -256,44 +256,6 @@
|
||||
color: var(--text-primary);
|
||||
}
|
||||
|
||||
/* Version is secondary metadata: keep it available without making it a focal point. */
|
||||
.svc-detail-version-row {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 7px;
|
||||
margin: -2px 0 16px;
|
||||
padding: 4px 0;
|
||||
color: var(--text-dim);
|
||||
font-size: 0.74rem;
|
||||
opacity: 0.78;
|
||||
}
|
||||
|
||||
.svc-detail-version-icon {
|
||||
color: var(--text-dim);
|
||||
font-size: 1rem;
|
||||
line-height: 1;
|
||||
opacity: 0.7;
|
||||
}
|
||||
|
||||
.svc-detail-version-label {
|
||||
font-weight: 600;
|
||||
}
|
||||
|
||||
.svc-detail-version-value {
|
||||
min-width: 0;
|
||||
color: var(--text-secondary);
|
||||
font-family: 'JetBrains Mono', 'Fira Code', monospace;
|
||||
font-size: 0.74rem;
|
||||
word-break: break-word;
|
||||
}
|
||||
|
||||
.svc-detail-version-row--unavailable .svc-detail-version-value,
|
||||
.svc-detail-version-row--not-applicable .svc-detail-version-value {
|
||||
color: var(--text-dim);
|
||||
font-family: inherit;
|
||||
font-style: italic;
|
||||
}
|
||||
|
||||
/* ── Service detail: Domain ──────────────────────────────────────── */
|
||||
|
||||
.svc-detail-domain-value {
|
||||
|
||||
@@ -673,30 +673,6 @@ async function openServiceDetailModal(unit, name, icon) {
|
||||
'</div>' +
|
||||
'</div>');
|
||||
|
||||
// Keep package versions in the detail modal rather than the compact tile.
|
||||
// The API uses `version` for regular services and `bitcoin_version` for
|
||||
// older Bitcoin payloads, so accept both while the backend is upgraded.
|
||||
var serviceVersion = data.version || data.bitcoin_version || '';
|
||||
// These services are wrappers, setup helpers, or application stacks rather
|
||||
// than a single versioned daemon represented by the tile's systemd unit.
|
||||
var versionNotApplicable = [
|
||||
'zeus-connect-setup.service', 'sparrow-autoconnect.service'
|
||||
].indexOf(unit) !== -1;
|
||||
var versionState = serviceVersion ? 'detected' : (versionNotApplicable ? 'not-applicable' : 'unavailable');
|
||||
var versionText = serviceVersion || (versionNotApplicable
|
||||
? 'This service does not expose a single package version'
|
||||
: (effectiveEnabled ? 'Version could not be detected' : 'Start the service to detect its version'));
|
||||
var versionBadge = serviceVersion ? 'Detected' : (versionNotApplicable ? 'Not applicable' : 'Not detected');
|
||||
// Version is useful supporting information, but not the primary reason for
|
||||
// opening this modal. Keep it as a quiet metadata row instead of a large
|
||||
// callout so it does not compete with status and service actions.
|
||||
addSetup('<div class="svc-detail-version-row svc-detail-version-row--' + versionState + '"' +
|
||||
' title="' + escHtml(versionText) + '">' +
|
||||
'<span class="svc-detail-version-icon" aria-hidden="true">⌁</span>' +
|
||||
'<span class="svc-detail-version-label">Version</span>' +
|
||||
'<span class="svc-detail-version-value">' + escHtml(serviceVersion || versionBadge) + '</span>' +
|
||||
'</div>');
|
||||
|
||||
// Section B2: BIP-110 live status (bip110 tile only)
|
||||
if (icon === 'bip110' && data.bip110) {
|
||||
var bip110 = data.bip110;
|
||||
|
||||
@@ -12,7 +12,5 @@
|
||||
"matrix-synapse.service": "1.115.0",
|
||||
"livekit.service": "1.5.2",
|
||||
"vaultwarden.service": "1.32.0",
|
||||
"phpfpm-nextcloud.service": "29.0.0",
|
||||
"phpfpm-wordpress.service": "6.5.0",
|
||||
"haven-relay.service": "0.1.0"
|
||||
}
|
||||
|
||||
@@ -132,8 +132,8 @@ let
|
||||
"matrix-synapse.service" = if pkgs ? matrix-synapse then pkgs.matrix-synapse.version else "1.115.0";
|
||||
"livekit.service" = if pkgs ? livekit then pkgs.livekit.version else "1.5.2";
|
||||
"vaultwarden.service" = if pkgs ? vaultwarden then pkgs.vaultwarden.version else "1.32.0";
|
||||
"phpfpm-nextcloud.service" = if pkgs ? nextcloud then pkgs.nextcloud.version else "29.0.0";
|
||||
"phpfpm-wordpress.service" = if pkgs ? wordpress then pkgs.wordpress.version else "6.5.0";
|
||||
# Nextcloud and WordPress are downloaded into /var/lib/www, so their
|
||||
# deployed versions are read from their own PHP version files by the Hub.
|
||||
"haven-relay.service" = if pkgs ? haven-relay then pkgs.haven-relay.version else (if pkgs ? haven then pkgs.haven.version else "0.1.0");
|
||||
});
|
||||
|
||||
|
||||
Reference in New Issue
Block a user