From nobody Mon Jun 8 06:28:19 2026 X-Original-To: dev-commits-ports-main@mlmmj.nyi.freebsd.org Received: from mx1.freebsd.org (mx1.freebsd.org [IPv6:2610:1c1:1:606c::19:1]) by mlmmj.nyi.freebsd.org (Postfix) with ESMTP id 4gYhtq6jBYz6gvxc for ; Mon, 08 Jun 2026 06:28:19 +0000 (UTC) (envelope-from git@FreeBSD.org) Received: from mxrelay.nyi.freebsd.org (mxrelay.nyi.freebsd.org [IPv6:2610:1c1:1:606c::19:3]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (4096 bits) server-digest SHA256 client-signature RSA-PSS (4096 bits) client-digest SHA256) (Client CN "mxrelay.nyi.freebsd.org", Issuer "R13" (not verified)) by mx1.freebsd.org (Postfix) with ESMTPS id 4gYhtq3WRHz3M6X for ; Mon, 08 Jun 2026 06:28:19 +0000 (UTC) (envelope-from git@FreeBSD.org) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=freebsd.org; s=dkim; t=1780900099; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:mime-version:mime-version:content-type:content-type: content-transfer-encoding:content-transfer-encoding; bh=P1pkj5ggAR8fzS2cZU52+Ir/qlWWz1dLqyVpcu9/73A=; b=jcEmNdfXzUjT+7npp87tQt3YnsQit8ZfLJVlcxZYQrCls4qt2a41We6agDKd7DUoGt5SuV QUDbvw5jcvvLilnKPJ34dmy6NdldmrUxn6Fl+8/3AbqUlLBUw8N7J9XEpFQ2Ba6a03q18o G0ySz9jAXOjJAUtjF9nkPFBD/1ZaAJdANPVH7PuVObXsIaEOAFq8QahWKmVGLNK6m4Kyrw CnkfsQB4PlFfXvsXyCjdovCLnDfeGknzP+tcZxwJj0UySVCMzcPgIPYRRe9iaSsJJCquNo xsNVHp49ppJNSELcDXDKV1SIMrIUiQZjDClt1KCx/y8wQqi6thvmEWJA1JMChg== ARC-Seal: i=1; s=dkim; d=freebsd.org; t=1780900099; a=rsa-sha256; cv=none; b=lUvL9TM6hzF35rnAJhevwEp5Cl/O2TFS5M4RLekOuuTtpfcGeQSt4M0Wq4MvRAzskB/0+J x0CEqGlYP2837zxRhMrBPpWdIvd+Ve0u4T6Nj44D2jpzqMSJE9hS/TPqBrmhpDa9xYZpRi IhDJko0wBamBsQmMyn7FzdSVMPaAHy49bD/lOdTBE7rWxHmb1SRd3PCLIhXdyUvM7zWhpl 7/YTaM8J6JDxiI9wQuOQtoLycNOtI+BNb/jzYD+VowLuybGX269aVj4UVm8fLwg2KVQxeM 2p/aAHNBV7+Shp3d54To99FvAEiLXBD1fMPk/C7yUtr/fXfckTZdSa/EynjNtg== ARC-Authentication-Results: i=1; mx1.freebsd.org; none ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=freebsd.org; s=dkim; t=1780900099; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:mime-version:mime-version:content-type:content-type: content-transfer-encoding:content-transfer-encoding; bh=P1pkj5ggAR8fzS2cZU52+Ir/qlWWz1dLqyVpcu9/73A=; b=OpmJ+EKGbMIll+HPV20lM/Zu5B7diL9aiXCGU2BHcdQDXx2FyPDUxt7JuaxX1p+tMWPbNG lZAtWbwmHpwUGrTcOhvzL2mo9H0TsrLPlDFBnPMlQ7gmiN5PqbWB99P9IrpvdA6kPAmHMy cnq7PpKAM2jtiEdttccqAEqXu+jr/Va2w6qNsz6fhP/TRdumQeRJNq/Hd4PxSDfwIhCXup Qm7cnHx0QQJlQ9WFypr7Bd2TYshY5tupzGAn6kNed7X2LsyLTUIZOegdVNjwhg3VXQAip0 MWkm+PQrbbCDbraG0553Ng8mVud1noX3eyX/90a1e60+EXCW5+DFpVXKGoAmMg== Received: from gitrepo.freebsd.org (gitrepo.freebsd.org [IPv6:2610:1c1:1:6068::e6a:5]) by mxrelay.nyi.freebsd.org (Postfix) with ESMTP id 4gYhtq35gtzcsd for ; Mon, 08 Jun 2026 06:28:19 +0000 (UTC) (envelope-from git@FreeBSD.org) Received: from git (uid 1279) (envelope-from git@FreeBSD.org) id 3cd81 by gitrepo.freebsd.org (DragonFly Mail Agent v0.13+ on gitrepo.freebsd.org); Mon, 08 Jun 2026 06:28:19 +0000 To: ports-committers@FreeBSD.org, dev-commits-ports-all@FreeBSD.org, dev-commits-ports-main@FreeBSD.org From: Yuri Victorovich Subject: git: 7160053217ef - main - Tools/scripts/report-outdated-for-maintainer.py: Update List-Id: Commits to the main branch of the FreeBSD ports repository List-Archive: https://lists.freebsd.org/archives/dev-commits-ports-main List-Help: List-Post: List-Subscribe: List-Unsubscribe: X-BeenThere: dev-commits-ports-main@freebsd.org Sender: owner-dev-commits-ports-main@FreeBSD.org List-Id: List-Post: List-Help: List-Subscribe: List-Unsubscribe: List-Owner: Precedence: list MIME-Version: 1.0 Content-Type: text/plain; charset=utf-8 Content-Transfer-Encoding: 8bit X-Git-Committer: yuri X-Git-Repository: ports X-Git-Refname: refs/heads/main X-Git-Reftype: branch X-Git-Commit: 7160053217ef2df40a69b1739ad8009681685dc0 Auto-Submitted: auto-generated Date: Mon, 08 Jun 2026 06:28:19 +0000 Message-Id: <6a266103.3cd81.5edbe05d@gitrepo.freebsd.org> The branch main has been updated by yuri: URL: https://cgit.FreeBSD.org/ports/commit/?id=7160053217ef2df40a69b1739ad8009681685dc0 commit 7160053217ef2df40a69b1739ad8009681685dc0 Author: Yuri Victorovich AuthorDate: 2026-06-07 20:09:56 +0000 Commit: Yuri Victorovich CommitDate: 2026-06-08 06:28:11 +0000 Tools/scripts/report-outdated-for-maintainer.py: Update --- Tools/scripts/report-outdated-for-maintainer.py | 124 +++++++++++++++--------- 1 file changed, 78 insertions(+), 46 deletions(-) diff --git a/Tools/scripts/report-outdated-for-maintainer.py b/Tools/scripts/report-outdated-for-maintainer.py index 6ebec0a31db2..a897a0dab147 100755 --- a/Tools/scripts/report-outdated-for-maintainer.py +++ b/Tools/scripts/report-outdated-for-maintainer.py @@ -193,20 +193,49 @@ def resolve_make_value(value, portname): def get_github_repo(makefile_path): - """Return (account, project) for USE_GITHUB=yes ports, else None.""" + """Return (account, project) for USE_GITHUB=yes ports or from WWW field, else None.""" use_github = get_makefile_var(makefile_path, "USE_GITHUB") - if not use_github or use_github.lower() != "yes": - return None - - portname = get_makefile_var(makefile_path, "PORTNAME") - if not portname: - return None - - gh_account = get_makefile_var(makefile_path, "GH_ACCOUNT") or portname - gh_project = get_makefile_var(makefile_path, "GH_PROJECT") or portname - gh_account = resolve_make_value(gh_account.split()[0], portname) - gh_project = resolve_make_value(gh_project.split()[0], portname) - return gh_account, gh_project + if use_github and use_github.lower() == "yes": + portname = get_makefile_var(makefile_path, "PORTNAME") + if not portname: + return None + + gh_account = get_makefile_var(makefile_path, "GH_ACCOUNT") or portname + gh_project = get_makefile_var(makefile_path, "GH_PROJECT") or portname + gh_account = resolve_make_value(gh_account.split()[0], portname) + gh_project = resolve_make_value(gh_project.split()[0], portname) + return gh_account, gh_project + + # If USE_GITHUB is not set, try to extract from WWW field, but only for ports + # that appear to use GitHub releases and are explicitly marked with a comment + # or have DISTVERSION matching a GitHub-style tag pattern (YYYY.M.DD or similar) + version = get_makefile_var(makefile_path, "DISTVERSION") or get_makefile_var(makefile_path, "PORTVERSION") + if version and looks_like_version(version): + # Only query from WWW if version matches GitHub-style patterns: + # - YYYY.M.DD (date-based like 2026.4.26, 2026.4.29) + # - X.Y.Z.W (4+ numeric components) + # This filters out most non-GitHub ports while catching real GitHub releases + parts = re.findall(r"\d+", version) + if len(parts) >= 3: + # Check if it looks like YYYY.M.DD (year >= 2000) + if int(parts[0]) >= 2000 and int(parts[0]) <= 2099: + if int(parts[1]) >= 1 and int(parts[1]) <= 12: + if int(parts[2]) >= 1 and int(parts[2]) <= 31: + # Looks like a date-based version from GitHub + www = get_makefile_var(makefile_path, "WWW") + if www: + m = re.match(r"https?://(?:www\.)?github\.com/([^/]+)/([^/\s]+)", www) + if m: + return m.group(1), m.group(2) + # Also check for simple 4+ component versions (e.g., 1.2.3.4) + elif len(parts) >= 4: + www = get_makefile_var(makefile_path, "WWW") + if www: + m = re.match(r"https?://(?:www\.)?github\.com/([^/]+)/([^/\s]+)", www) + if m: + return m.group(1), m.group(2) + + return None # --- Version handling --- @@ -328,14 +357,16 @@ def get_port_version_via_make(port_dir): def find_maintained_ports(maintainer_email): """ - Return (versions, uses_types, github_repos) keyed by port origin. + Return (versions, uses_types, github_repos, github_version_prefixes) keyed by port origin. versions[origin] = real version string uses_types[origin] = comma-separated port type string github_repos[origin] = (account, project) for USE_GITHUB ports + github_version_prefixes[origin] = (prefix, suffix) to strip from GitHub release tags """ versions = {} uses_types = {} github_repos = {} + github_version_prefixes = {} top_makefile = os.path.join(PORTSDIR, "Makefile") categories = get_subdir_entries(top_makefile) @@ -367,8 +398,15 @@ def find_maintained_ports(maintainer_email): github_repo = get_github_repo(port_makefile) if github_repo: github_repos[origin] = github_repo + portname = get_makefile_var(port_makefile, "PORTNAME") or "" + prefix_raw = get_makefile_var(port_makefile, "DISTVERSIONPREFIX") or "" + suffix_raw = get_makefile_var(port_makefile, "DISTVERSIONSUFFIX") or "" + prefix = resolve_make_value(prefix_raw, portname) + suffix = resolve_make_value(suffix_raw, portname) + if prefix or suffix: + github_version_prefixes[origin] = (prefix, suffix) - return versions, uses_types, github_repos + return versions, uses_types, github_repos, github_version_prefixes # --- Repology API --- @@ -451,48 +489,36 @@ def query_github_latest_release(account, project, cache): if key in cache: return cache[key] - quoted_account = urllib.parse.quote(account, safe="") - quoted_project = urllib.parse.quote(project, safe="") - url = f"{GITHUB_API_BASE}/repos/{quoted_account}/{quoted_project}/releases/latest" - + # Use 'gh' CLI for better rate limit handling and authentication try: - with github_request(url) as resp: - data = json.load(resp) - except urllib.error.HTTPError as e: - if e.code != 404: - print( - f"Warning: Could not query GitHub latest release for {account}/{project}: HTTP {e.code}", - file=sys.stderr, - ) - cache[key] = None - return None - except urllib.error.URLError as e: - print( - f"Warning: Could not query GitHub latest release for {account}/{project}: {e.reason}", - file=sys.stderr, + result = subprocess.run( + ["gh", "release", "view", "--repo", f"{account}/{project}"], + capture_output=True, + text=True, + timeout=30, ) + if result.returncode == 0: + for line in result.stdout.split("\n"): + if line.startswith("tag:"): + tag = line.split(":", 1)[1].strip() + cache[key] = tag.strip() or None + return cache[key] cache[key] = None return None - except Exception as e: - print( - f"Warning: Could not query GitHub latest release for {account}/{project}: {e}", - file=sys.stderr, - ) + except Exception: cache[key] = None return None - tag = (data.get("tag_name") or "").strip() - cache[key] = tag.strip() or None - return cache[key] - -def query_github_releases(github_repos): +def query_github_releases(github_repos, version_prefixes=None): """Return dict {origin: latest_release_tag} for GitHub-based ports with releases.""" cache = {} latest_releases = {} unique_repos = sorted(set(github_repos.values())) - with concurrent.futures.ThreadPoolExecutor(max_workers=16) as executor: + # gh CLI handles rate limiting better than direct API calls, so we can use more workers + max_workers = min(8, len(unique_repos)) if unique_repos else 1 + with concurrent.futures.ThreadPoolExecutor(max_workers=max_workers) as executor: future_map = { executor.submit(query_github_latest_release, account, project, cache): (account, project) for account, project in unique_repos @@ -503,6 +529,12 @@ def query_github_releases(github_repos): for origin, repo in github_repos.items(): latest = cache.get(repo) if latest: + if version_prefixes and origin in version_prefixes: + prefix, suffix = version_prefixes[origin] + if prefix and latest.startswith(prefix): + latest = latest[len(prefix):] + if suffix and latest.endswith(suffix): + latest = latest[:-len(suffix)] latest_releases[origin] = latest return latest_releases @@ -651,7 +683,7 @@ def main(): check_portsdir() print(f"Scanning {PORTSDIR} for ports maintained by {maintainer_email}...", file=sys.stderr) - local_versions, local_uses, github_repos = find_maintained_ports(maintainer_email) + local_versions, local_uses, github_repos, github_version_prefixes = find_maintained_ports(maintainer_email) if not local_versions: print(f"No ports maintained by {maintainer_email}") @@ -662,7 +694,7 @@ def main(): file=sys.stderr, ) outdated_repology = query_repology_outdated(maintainer_email) - github_latest = query_github_releases(github_repos) + github_latest = query_github_releases(github_repos, github_version_prefixes) print(f"Repology reports {len(outdated_repology)} outdated FreeBSD ports.", file=sys.stderr) print(f"GitHub provides latest releases for {len(github_latest)} GitHub-based ports.", file=sys.stderr)