diff --git a/baseTemplate/templates/baseTemplate/versionManagment.html b/baseTemplate/templates/baseTemplate/versionManagment.html
index 202db35ec..734fb1391 100644
--- a/baseTemplate/templates/baseTemplate/versionManagment.html
+++ b/baseTemplate/templates/baseTemplate/versionManagment.html
@@ -165,6 +165,72 @@
font-weight: 600;
}
+ .alert-info {
+ background: var(--bg-hover, #eef0ff);
+ border: 1px solid var(--border-color, #c7c9f0);
+ color: var(--text-primary, #2f3640);
+ }
+
+ .alert-info a {
+ color: var(--accent-color, #5b5fcf);
+ font-weight: 600;
+ }
+
+ .version-section {
+ margin-top: 20px;
+ margin-bottom: 10px;
+ font-size: 14px;
+ font-weight: 700;
+ color: var(--text-primary, #2f3640);
+ }
+
+ .version-section:first-of-type {
+ margin-top: 0;
+ }
+
+ .version-meta-row {
+ display: flex;
+ flex-direction: column;
+ gap: 8px;
+ width: 100%;
+ margin-bottom: 14px;
+ padding: 12px 14px;
+ border-radius: 8px;
+ border: 1px solid var(--border-color, #e8e9ff);
+ background: var(--bg-hover, #f8f9ff);
+ }
+
+ .version-meta-row-label {
+ font-size: 12px;
+ font-weight: 600;
+ color: var(--text-secondary, #8893a7);
+ text-transform: uppercase;
+ letter-spacing: 0.5px;
+ }
+
+ .version-meta-row-value {
+ font-size: 14px;
+ color: var(--text-primary, #2f3640);
+ word-break: break-word;
+ line-height: 1.5;
+ }
+
+ .version-meta-row-value code,
+ .version-sha {
+ font-family: 'SF Mono', Monaco, monospace;
+ font-size: 13px;
+ background: var(--bg-secondary, white);
+ padding: 2px 8px;
+ border-radius: 4px;
+ border: 1px solid var(--border-color, #e8e9ff);
+ }
+
+ .version-meta-row-value a {
+ font-weight: 600;
+ color: var(--accent-color, #5b5fcf);
+ margin-left: 4px;
+ }
+
/* Info grid */
.info-grid {
display: grid;
@@ -269,7 +335,16 @@
{% if Notecheck %}
+ {% endif %}
+ {% if local_behind_official and not Notecheck %}
+
+
+ {% trans "Your commit differs from the latest on the official CyberPanel repository (usmannasir/cyberpanel). This is informational if you intentionally track a fork." %}
{% endif %}
@@ -294,8 +369,9 @@
-
Version Information
+
{% trans "Version Information" %}
+
{% trans "This installation" %}
{% trans "Current Version" %}
@@ -306,22 +382,65 @@
{{ build }}
- {% trans "Current Commit" %}
- {{ Currentcomt }}
+ {% trans "Current commit" %}
+
+ {% if Currentcomt_short %}{{ Currentcomt_short }}{% else %}—{% endif %}
+
- {% trans "Latest Version" %}
+ {% trans "Published latest version" %}
{{ latestVersion }}
- {% trans "Latest Build" %}
+ {% trans "Published latest build" %}
{{ latestBuild }}
-
- {% trans "Latest Commit" %}
- {{ latestcomit }}
-
+
+
{% trans "Git remotes and branch tips" %}
+
+ {% trans "Origin (git remote)" %}
+ {{ remote_display|default:"—" }}
+
+
+ {% trans "Tracking branch" %}
+ {{ branch_ref }}
+
+
+ {% if fork_remote_commit %}
+
+ {% endif %}
+
+ {% if on_dev_branch %}
+
+ {% elif latestcomit and not fork_remote_commit and not on_dev_branch %}
+
+ {% trans "Latest commit on origin (comparison)" %}
+
+ {{ latestcomit_short }}
+
+
+ {% endif %}
diff --git a/baseTemplate/views.py b/baseTemplate/views.py
index 8a0fcebf5..0ffd00142 100644
--- a/baseTemplate/views.py
+++ b/baseTemplate/views.py
@@ -325,6 +325,14 @@ def versionManagment(request):
remote_cmd = 'git -C /usr/local/CyberCP remote get-url origin 2>/dev/null || true'
remote_out = ProcessUtilities.outputExecutioner(remote_cmd)
is_usmannasir = 'usmannasir/cyberpanel' in (remote_out or '')
+ github_owner, github_repo = None, None
+ m_remote = re.search(r'github\.com[:/]([^/]+)/([^/]+?)(?:\.git)?$', (remote_out or '').strip())
+ if m_remote:
+ github_owner = m_remote.group(1)
+ github_repo = m_remote.group(2).rstrip('.git')
+ remote_display = '%s/%s' % (github_owner, github_repo)
+ else:
+ remote_display = ((remote_out or '').strip() or '')
# Stable: newer than cyberpanel.net = up to date; dev: compare commits
if not on_dev_branch and notechk and _version_compare(currentVersion, latestVersion) > 0:
@@ -365,10 +373,53 @@ def versionManagment(request):
except (requests.RequestException, IndexError, KeyError):
pass
+ # Fork remote tip for UI (empty when origin is official).
+ fork_remote_commit = latestcomit if (latestcomit and not is_usmannasir) else ''
+
+ upstream_commit = ''
+ if on_dev_branch:
+ up_url = "https://api.github.com/repos/usmannasir/cyberpanel/commits?sha=%s" % branch_ref
+ logging.CyberCPLogFileWriter.writeToFile(up_url)
+ try:
+ up_r = requests.get(up_url, timeout=10)
+ up_r.raise_for_status()
+ upstream_commit = up_r.json()[0]['sha']
+ except (requests.RequestException, IndexError, KeyError) as e:
+ logging.CyberCPLogFileWriter.writeToFile('[versionManagment] upstream GitHub API failed: %s' % str(e))
+
+ def _short_sha(commit_hash):
+ if not commit_hash or len(commit_hash) < 7:
+ return commit_hash or ''
+ return commit_hash[:7]
+
+ fork_commit_url = ''
+ if github_owner and github_repo and fork_remote_commit:
+ fork_commit_url = 'https://github.com/%s/%s/commit/%s' % (
+ github_owner, github_repo, fork_remote_commit)
+ upstream_commit_url = ''
+ if upstream_commit:
+ upstream_commit_url = 'https://github.com/usmannasir/cyberpanel/commit/%s' % upstream_commit
+
+ local_behind_official = bool(
+ on_dev_branch and Currentcomt and upstream_commit and Currentcomt != upstream_commit)
+ notecheck_compare_remote = 'usmannasir/cyberpanel' if is_usmannasir else remote_display
+
template = 'baseTemplate/versionManagment.html'
- finalData = {'build': currentBuild, 'currentVersion': currentVersion, 'latestVersion': latestVersion,
- 'latestBuild': latestBuild, 'latestcomit': latestcomit, "Currentcomt": Currentcomt,
- "Notecheck": notechk}
+ finalData = {
+ 'build': currentBuild, 'currentVersion': currentVersion, 'latestVersion': latestVersion,
+ 'latestBuild': latestBuild, 'latestcomit': latestcomit, 'Currentcomt': Currentcomt,
+ 'Notecheck': notechk, 'branch_ref': branch_ref, 'remote_display': remote_display,
+ 'is_usmannasir': is_usmannasir, 'fork_remote_commit': fork_remote_commit,
+ 'upstream_commit': upstream_commit, 'fork_commit_url': fork_commit_url,
+ 'upstream_commit_url': upstream_commit_url,
+ 'Currentcomt_short': _short_sha(Currentcomt),
+ 'latestcomit_short': _short_sha(latestcomit),
+ 'fork_remote_commit_short': _short_sha(fork_remote_commit),
+ 'upstream_commit_short': _short_sha(upstream_commit),
+ 'local_behind_official': local_behind_official,
+ 'notecheck_compare_remote': notecheck_compare_remote,
+ 'on_dev_branch': on_dev_branch,
+ }
proc = httpProc(request, template, finalData, 'versionManagement')
return proc.render()