From 72ac1ae76f733bfc6dab90141df73fd2fb2f980a Mon Sep 17 00:00:00 2001 From: Sebb Date: Sat, 14 Mar 2026 23:37:59 +0000 Subject: [PATCH 1/7] Add sort check --- members_check.py | 30 ++++++++++++++++++++++++------ 1 file changed, 24 insertions(+), 6 deletions(-) diff --git a/members_check.py b/members_check.py index ffec1709d8..59c5eee198 100644 --- a/members_check.py +++ b/members_check.py @@ -19,8 +19,10 @@ # # -# Check contents of members.md to ensure entries are valid ids and in the correct section -# Intended to be run by a GitHub Action, but can also be run from a local checkout +""" +Check contents of members.md to ensure entries are valid ids and in the correct section +Intended to be run by a GitHub Action, but can also be run from a local checkout +""" import sys import requests @@ -29,26 +31,36 @@ MEMBERS_MD ='content/foundation/members.md' def main(failOnWarn=False): - member_info = requests.get(MEMBER_INFO).json() + """ + Parse members.md reporting any findings. + Exit with non-zero status if: + - any error is detected + - any warning is detected and failOnWarn is True + """ + + member_info = requests.get(MEMBER_INFO, timeout=60).json() members = member_info['members'] ex_members = member_info['ex_members'] errors = 0 warnings = 0 + previd = '' with open(MEMBERS_MD, 'r', encoding='utf-8') as md: section = None for line in md: if line.startswith('| Id | Name | Projects |'): + previd = '' section = 'members' print("Checking members section") continue - elif line.startswith('| Id | Name |'): + if line.startswith('| Id | Name |'): + previd = '' section = 'emeritus' print("Checking emeritus section") continue - elif len(line.strip()) == 0: + if len(line.strip()) == 0: section = None continue - elif line.startswith('|---'): + if line.startswith('|---'): continue if section is None: continue @@ -59,6 +71,12 @@ def main(failOnWarn=False): parts = line.strip().split('|') parts.pop(0) availid = parts.pop(0).strip() + if availid < previd: + status = f"Incorrect sort order in {section}: previous: {previd} current: {availid}" + warnings += 1 + level = 'WARNING' + print(f"{level}: {status}") + previd = availid name = parts.pop(0).strip() if section == 'members': if not availid in members: From d5a03350451526e0b8d6a5154820101a4bd40aee Mon Sep 17 00:00:00 2001 From: Sebb Date: Sun, 15 Mar 2026 12:51:59 +0000 Subject: [PATCH 2/7] Document status types [skip ci] --- members_check.py | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/members_check.py b/members_check.py index 59c5eee198..f5036f0fd3 100644 --- a/members_check.py +++ b/members_check.py @@ -33,6 +33,12 @@ def main(failOnWarn=False): """ Parse members.md reporting any findings. + ERRORS: + - avalid not found in members listing + WARNINGS: + - not correctly sorted + - entry in wrong section + Exit with non-zero status if: - any error is detected - any warning is detected and failOnWarn is True From 05c1182231094a6944f7a457c1dcad3b5331ce43 Mon Sep 17 00:00:00 2001 From: Sebb Date: Sun, 15 Mar 2026 12:53:54 +0000 Subject: [PATCH 3/7] Document status types [skip ci] --- members_check.py | 1 + 1 file changed, 1 insertion(+) diff --git a/members_check.py b/members_check.py index f5036f0fd3..05b87d6d7a 100644 --- a/members_check.py +++ b/members_check.py @@ -35,6 +35,7 @@ def main(failOnWarn=False): Parse members.md reporting any findings. ERRORS: - avalid not found in members listing + - unexpected format WARNINGS: - not correctly sorted - entry in wrong section From 51d2a440dfc8b5c1bebac097c152283e8376dd0e Mon Sep 17 00:00:00 2001 From: Sebb Date: Sun, 15 Mar 2026 14:29:46 +0000 Subject: [PATCH 4/7] Also check for correct number of parts --- members_check.py | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/members_check.py b/members_check.py index 05b87d6d7a..0a761562ae 100644 --- a/members_check.py +++ b/members_check.py @@ -76,7 +76,12 @@ def main(failOnWarn=False): print(line.strip()) errors += 1 parts = line.strip().split('|') - parts.pop(0) + parts.pop(0) # drop empty prefix + if len(parts) < 3 or len(parts) > 4: + status = f"Incorrect number of parts (expected 3 or 4) in {section}: count: {len(parts)} {line}" + warnings += 1 + level = 'WARNING' + print(f"{level}: {status}") availid = parts.pop(0).strip() if availid < previd: status = f"Incorrect sort order in {section}: previous: {previd} current: {availid}" From 30b0915135400bec03e4ff39fd1cd66d543ce0ef Mon Sep 17 00:00:00 2001 From: Sebb Date: Sun, 29 Mar 2026 11:51:14 +0100 Subject: [PATCH 5/7] Check for duplicates --- members_check.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/members_check.py b/members_check.py index 0a761562ae..e9cdddd3d9 100644 --- a/members_check.py +++ b/members_check.py @@ -83,7 +83,7 @@ def main(failOnWarn=False): level = 'WARNING' print(f"{level}: {status}") availid = parts.pop(0).strip() - if availid < previd: + if availid <= previd: status = f"Incorrect sort order in {section}: previous: {previd} current: {availid}" warnings += 1 level = 'WARNING' From 41b3d9b6f64a68a37068b02bc0348c93292ea24d Mon Sep 17 00:00:00 2001 From: Sebb Date: Sun, 29 Mar 2026 11:58:17 +0100 Subject: [PATCH 6/7] =?UTF-8?q?Allow=20for=20duplicate=20=E2=80=98=3F?= =?UTF-8?q?=E2=80=99=20ids?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- members_check.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/members_check.py b/members_check.py index e9cdddd3d9..d12c68401a 100644 --- a/members_check.py +++ b/members_check.py @@ -83,7 +83,7 @@ def main(failOnWarn=False): level = 'WARNING' print(f"{level}: {status}") availid = parts.pop(0).strip() - if availid <= previd: + if availid < previd or (availid == previd and availid != '?'): status = f"Incorrect sort order in {section}: previous: {previd} current: {availid}" warnings += 1 level = 'WARNING' From 80edcedf68c9ff61fda664213ffd4f0b2050d8bd Mon Sep 17 00:00:00 2001 From: Sebb Date: Sun, 29 Mar 2026 13:34:42 +0100 Subject: [PATCH 7/7] Check availid for valid characters --- members_check.py | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/members_check.py b/members_check.py index d12c68401a..c1f8645b03 100644 --- a/members_check.py +++ b/members_check.py @@ -25,6 +25,7 @@ """ import sys +import re import requests MEMBER_INFO = 'https://whimsy.apache.org/public/member-info.json' @@ -83,6 +84,12 @@ def main(failOnWarn=False): level = 'WARNING' print(f"{level}: {status}") availid = parts.pop(0).strip() + # Note that '-' is not allowed in new availids, but is present in some historic ones + if availid != '?' and re.fullmatch('[a-z][-_a-z0-9]+', availid) is None: + status = f"Unexpected availid in {section}: {availid} - must be lowercase alphanumeric" + warnings += 1 + level = 'WARNING' + print(f"{level}: {status}") if availid < previd or (availid == previd and availid != '?'): status = f"Incorrect sort order in {section}: previous: {previd} current: {availid}" warnings += 1