From 35fe6abba6abcb09c2c4d14e1d11a48636a7638e Mon Sep 17 00:00:00 2001 From: master3395 Date: Fri, 27 Mar 2026 22:29:58 +0100 Subject: [PATCH] Version Management: show fork + upstream tips; upstream-only when origin is official - Parse git origin; show fork block only when not usmannasir/cyberpanel - Always fetch official upstream branch tip; fetch fork tip when fork - Notecheck: fork installs vs fork tip; official vs upstream tip - Template: tracking branch, optional fork rows, drift info; clarify warning --- .../baseTemplate/versionManagment.html | 13 +- baseTemplate/views.py | 232 +++++++++--------- 2 files changed, 117 insertions(+), 128 deletions(-) diff --git a/baseTemplate/templates/baseTemplate/versionManagment.html b/baseTemplate/templates/baseTemplate/versionManagment.html index 734fb1391..3d1d745bd 100644 --- a/baseTemplate/templates/baseTemplate/versionManagment.html +++ b/baseTemplate/templates/baseTemplate/versionManagment.html @@ -341,7 +341,12 @@ {% endif %} - {% if local_behind_official and not Notecheck %} + {% if show_fork_block and fork_drift_upstream %} +
+ + {% trans "Info: Your fork branch tip on GitHub differs from the official upstream tip on the same branch. That is normal if you have not merged upstream yet." %} +
+ {% elif 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." %} @@ -419,18 +424,14 @@
{% endif %} - {% if on_dev_branch %} + {% if upstream_commit %}
{% trans "Official upstream (usmannasir/cyberpanel) — latest on GitHub" %} - {% if upstream_commit %} {{ upstream_commit_short }} {% if upstream_commit_url %} {% trans "View commit" %} {% endif %} - {% else %} - {% trans "Unavailable" %} (API) - {% endif %}
{% elif latestcomit and not fork_remote_commit and not on_dev_branch %} diff --git a/baseTemplate/views.py b/baseTemplate/views.py index 0ffd00142..871a8551e 100644 --- a/baseTemplate/views.py +++ b/baseTemplate/views.py @@ -55,6 +55,34 @@ def _version_compare(a, b): return 0 +def _parse_github_origin(remote_out): + """Return (owner, repo) or (None, None) if unparseable.""" + if not remote_out: + return None, None + m = re.search(r'github\.com[:/]([^/]+)/([^/]+?)(?:\.git)?$', remote_out.strip()) + if not m: + return None, None + owner, repo = m.group(1), m.group(2).rstrip('.git') + return owner, repo + + +def _github_branch_tip_sha(owner, repo, branch_ref): + """First commit SHA on branch via GitHub API, or empty string on failure.""" + try: + u = 'https://api.github.com/repos/%s/%s/commits?sha=%s' % (owner, repo, branch_ref) + r = requests.get(u, timeout=10) + r.raise_for_status() + data = r.json() + if not data: + return '' + sha = data[0].get('sha', '') or '' + return sha + except (requests.RequestException, IndexError, KeyError, TypeError) as e: + logging.CyberCPLogFileWriter.writeToFile( + '[versionManagment] GitHub API %s/%s @%s failed: %s' % (owner, repo, branch_ref, str(e))) + return '' + + @ensure_csrf_cookie def renderBase(request): template = 'baseTemplate/homePage.html' @@ -67,49 +95,8 @@ def renderBase(request): @ensure_csrf_cookie def versionManagement(request): - currentVersion = VERSION - currentBuild = str(BUILD) - - getVersion = requests.get('https://cyberpanel.net/version.txt') - latest = getVersion.json() - latestVersion = latest['version'] - latestBuild = latest['build'] - branch_ref = 'v%s.%s' % (latestVersion, latestBuild) - - notechk = True - Currentcomt = '' - latestcomit = '' - - if _version_compare(currentVersion, latestVersion) > 0: - notechk = False - else: - 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 '') - - if is_usmannasir: - u = "https://api.github.com/repos/usmannasir/cyberpanel/commits?sha=%s" % branch_ref - logging.CyberCPLogFileWriter.writeToFile(u) - try: - r = requests.get(u, timeout=10) - r.raise_for_status() - latestcomit = r.json()[0]['sha'] - except (requests.RequestException, IndexError, KeyError) as e: - logging.CyberCPLogFileWriter.writeToFile('[versionManagement] GitHub API failed: %s' % str(e)) - head_cmd = 'git -C /usr/local/CyberCP rev-parse HEAD 2>/dev/null || true' - Currentcomt = ProcessUtilities.outputExecutioner(head_cmd).rstrip('\n') - if latestcomit and Currentcomt == latestcomit: - notechk = False - else: - notechk = False - - template = 'baseTemplate/versionManagment.html' - finalData = {'build': currentBuild, 'currentVersion': currentVersion, 'latestVersion': latestVersion, - 'latestBuild': latestBuild, 'latestcomit': latestcomit, "Currentcomt": Currentcomt, - "Notecheck": notechk} - - proc = httpProc(request, template, finalData, 'versionManagement') - return proc.render() + """Legacy entrypoint; same UI as versionManagment (URLs use versionManagment).""" + return versionManagment(request) @ensure_csrf_cookie @@ -297,6 +284,13 @@ def versionManagment(request): latestcomit = '' latestVersion = '0' latestBuild = '0' + upstream_latest_sha = '' + fork_latest_sha = '' + show_fork_block = False + fork_display = '' + fork_commit_url = '' + upstream_commit_url = '' + fork_drift_upstream = False on_dev_branch = (currentVersion == '2.5.5' and currentBuild == 'dev') @@ -311,114 +305,108 @@ def versionManagment(request): if on_dev_branch: latestVersion, latestBuild = '2.5.5', 'dev' - # Dev branch: compare against v2.5.5-dev, show dev version info if on_dev_branch: branch_ref = 'v2.5.5-dev' latestVersion, latestBuild = '2.5.5', 'dev' else: branch_ref = 'v%s.%s' % (latestVersion, latestBuild) - # Always fetch local HEAD for display head_cmd = 'git -C /usr/local/CyberCP rev-parse HEAD 2>/dev/null || true' Currentcomt = (ProcessUtilities.outputExecutioner(head_cmd) or '').rstrip('\n') 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) + remote_out = (ProcessUtilities.outputExecutioner(remote_cmd) or '') + origin_owner, origin_repo = _parse_github_origin(remote_out) + if origin_owner and origin_repo: + remote_display = '%s/%s' % (origin_owner, origin_repo) + is_official = (origin_owner.lower() == 'usmannasir' and origin_repo.lower() == 'cyberpanel') + show_fork_block = not is_official + if show_fork_block: + fork_display = remote_display else: - remote_display = ((remote_out or '').strip() or '') + remote_display = (remote_out.strip() or '—') + logging.CyberCPLogFileWriter.writeToFile( + '[versionManagment] Unparseable git origin, upstream-only UI: %s' + % (remote_out[:200] if remote_out else '(empty)')) + show_fork_block = False + + upstream_latest_sha = _github_branch_tip_sha('usmannasir', 'cyberpanel', branch_ref) + latestcomit = upstream_latest_sha + if upstream_latest_sha: + upstream_commit_url = 'https://github.com/usmannasir/cyberpanel/commit/%s' % upstream_latest_sha + + if show_fork_block and origin_owner and origin_repo: + fork_latest_sha = _github_branch_tip_sha(origin_owner, origin_repo, branch_ref) + if fork_latest_sha: + fork_commit_url = 'https://github.com/%s/%s/commit/%s' % ( + origin_owner, origin_repo, fork_latest_sha) + + if (fork_latest_sha and upstream_latest_sha and fork_latest_sha != upstream_latest_sha): + fork_drift_upstream = True - # Stable: newer than cyberpanel.net = up to date; dev: compare commits if not on_dev_branch and notechk and _version_compare(currentVersion, latestVersion) > 0: notechk = False elif notechk: - # Dev branch: official remote compares to usmannasir/cyberpanel; forks compare to their own GitHub repo - fetch_branch = branch_ref if (is_usmannasir or on_dev_branch) else None - if fetch_branch: - u = None - if on_dev_branch and not is_usmannasir: - m = re.search(r'github\.com[:/]([^/]+)/([^/]+?)(?:\.git)?$', (remote_out or '').strip()) - if m: - owner, repo = m.group(1), m.group(2).rstrip('.git') - u = "https://api.github.com/repos/%s/%s/commits?sha=%s" % (owner, repo, fetch_branch) - if u is None: - u = "https://api.github.com/repos/usmannasir/cyberpanel/commits?sha=%s" % fetch_branch - logging.CyberCPLogFileWriter.writeToFile(u) - try: - r = requests.get(u, timeout=10) - r.raise_for_status() - latestcomit = r.json()[0]['sha'] - if Currentcomt and latestcomit and Currentcomt == latestcomit: - notechk = False - except (requests.RequestException, IndexError, KeyError) as e: - logging.CyberCPLogFileWriter.writeToFile('[versionManagment] GitHub API failed: %s' % str(e)) - elif not on_dev_branch: - # Stable fork: fetch from fork's branch - m = re.search(r'github\.com[:/]([^/]+)/([^/]+?)(?:\.git)?$', (remote_out or '').strip()) - if m: - owner, repo = m.group(1), m.group(2).rstrip('.git') - try: - u = "https://api.github.com/repos/%s/%s/commits?sha=%s" % (owner, repo, branch_ref) - r = requests.get(u, timeout=10) - r.raise_for_status() - latestcomit = r.json()[0]['sha'] - if Currentcomt and latestcomit and Currentcomt == latestcomit: - notechk = False - except (requests.RequestException, IndexError, KeyError): - pass + cur = (Currentcomt or '').strip().lower() + if show_fork_block: + fk = (fork_latest_sha or '').strip().lower() + up = (upstream_latest_sha or '').strip().lower() + if fk: + notechk = not (bool(cur) and cur == fk) + elif up: + notechk = not (bool(cur) and cur == up) + else: + notechk = False + else: + up = (upstream_latest_sha or '').strip().lower() + if up: + notechk = not (bool(cur) and cur == up) + else: + notechk = False - # 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)) + is_usmannasir = not show_fork_block + fork_remote_commit = fork_latest_sha if show_fork_block else '' + upstream_commit = upstream_latest_sha + notecheck_compare_remote = fork_display if show_fork_block else 'usmannasir/cyberpanel' + local_behind_official = bool( + on_dev_branch and Currentcomt and upstream_commit and Currentcomt != upstream_commit) 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, '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, + 'build': currentBuild, + 'currentVersion': currentVersion, + 'latestVersion': latestVersion, + 'latestBuild': latestBuild, + 'latestcomit': latestcomit, + 'Currentcomt': Currentcomt, + 'Notecheck': notechk, + 'show_fork_block': show_fork_block, + 'tracking_branch': branch_ref, + 'branch_ref': branch_ref, + 'fork_display': fork_display, + 'fork_latest_sha': fork_latest_sha, + 'upstream_latest_sha': upstream_latest_sha, + 'fork_commit_url': fork_commit_url, 'upstream_commit_url': upstream_commit_url, + 'fork_drift_upstream': fork_drift_upstream, + 'remote_display': remote_display, + 'is_usmannasir': is_usmannasir, + 'fork_remote_commit': fork_remote_commit, + 'upstream_commit': upstream_commit, + 'notecheck_compare_remote': notecheck_compare_remote, + 'local_behind_official': local_behind_official, + 'on_dev_branch': on_dev_branch, '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, + 'fork_latest_sha_short': _short_sha(fork_latest_sha), + 'upstream_latest_sha_short': _short_sha(upstream_latest_sha), } proc = httpProc(request, template, finalData, 'versionManagement')