Update config change checker script and workflow (#37226)

* Update config change checker script and workflow

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>

* Update check_config_changes_ci.py

---------

Co-authored-by: Claude Sonnet 4.6 <noreply@anthropic.com>
Co-authored-by: Mattermost Build <build@mattermost.com>
This commit is contained in:
authored and GitHub committed 2026-07-14 13:04:40 +03:00
1 parent 444b5c46b9
commit 6b4b77723c
2 files changed
+33 -29

No files matched your search

+25 -21
View File
@@ -127,11 +127,11 @@ def file_at(ref: str, path: str) -> str:
).stdout
except subprocess.CalledProcessError:
return ""
def _compute_merge_base() -> str:
"""Resolve the merge-base of BASE_SHA and HEAD_SHA.
Per-checker comparisons must use this rather than BASE_SHA. BASE_SHA is the
tip of the target branch at PR-event time; if that branch advances on a
watched file after the PR diverges, comparing branch-tip vs target-tip
@@ -143,8 +143,8 @@ def _compute_merge_base() -> str:
["git", "merge-base", BASE_SHA, HEAD_SHA],
capture_output=True, text=True, check=True,
).stdout.strip()
MERGE_BASE = _compute_merge_base()
@@ -182,8 +182,11 @@ def _scan_struct_fields(src: str) -> set[tuple[str, str]]:
while struct_stack and depth <= struct_stack[-1][1]:
struct_stack.pop()
# Record fields only when we're directly inside exactly one named struct
if len(struct_stack) == 1:
# Record fields only when we're directly inside the named struct body.
# The depth check (depth == struct_stack[0][1] + 1) ensures that fields
# inside nested anonymous struct { ... } blocks are not incorrectly
# attributed to the outer named struct.
if len(struct_stack) == 1 and depth == struct_stack[0][1] + 1:
fm = _FIELD_LINE_RE.match(line)
if fm:
fields.add((struct_stack[0][0], fm.group(1)))
@@ -195,7 +198,7 @@ def check_config(patches: dict[str, str]) -> CheckResult:
"""
Detect exported Go struct field additions/removals in config.go.
Compares full-file snapshots at BASE_SHA and HEAD_SHA so that fields
Compares full-file snapshots at MERGE_BASE and HEAD_SHA so that fields
are always attributed to the correct struct regardless of which diff
hunks are present.
"""
@@ -209,8 +212,8 @@ def check_config(patches: dict[str, str]) -> CheckResult:
added = head_fields - base_fields
removed = base_fields - head_fields
result.additions = sorted(f"`{s}.{f}`" for s, f in added)
result.removals = sorted(f"`{s}.{f}`" for s, f in removed)
result.additions = sorted(f"``{s}.{f}``" for s, f in added)
result.removals = sorted(f"``{s}.{f}``" for s, f in removed)
return result
@@ -273,7 +276,7 @@ def check_api(patches: dict[str, str]) -> CheckResult:
"""
Detect API endpoint additions/removals in the api4/ directory.
Compares full-file snapshots at BASE_SHA and HEAD_SHA via set arithmetic,
Compares full-file snapshots at MERGE_BASE and HEAD_SHA via set arithmetic,
so multi-line and multi-method registrations are handled correctly.
"""
result = CheckResult(label="API Changes (`api4`)")
@@ -320,7 +323,7 @@ def check_audit_events(patches: dict[str, str]) -> CheckResult:
"""
Detect AuditEvent* constant additions/removals.
Uses full-file snapshots at BASE_SHA/HEAD_SHA so reorderings and
Uses full-file snapshots at MERGE_BASE/HEAD_SHA so reorderings and
cross-constant name collisions don't produce false results.
"""
result = CheckResult(label="Audit Log Event Changes")
@@ -330,8 +333,8 @@ def check_audit_events(patches: dict[str, str]) -> CheckResult:
base_events = _parse_audit_events(file_at(MERGE_BASE, _AUDIT_EVENT_PATH))
head_events = _parse_audit_events(file_at(HEAD_SHA, _AUDIT_EVENT_PATH))
result.additions = sorted(f"`{e}`" for e in head_events - base_events)
result.removals = sorted(f"`{e}`" for e in base_events - head_events)
result.additions = sorted(f"``{e}``" for e in head_events - base_events)
result.removals = sorted(f"``{e}``" for e in base_events - head_events)
return result
@@ -366,9 +369,9 @@ def check_go_version(patches: dict[str, str]) -> CheckResult:
new_ver = _parse_go_version(file_at(HEAD_SHA, _DOCKERFILE_PATH))
if old_ver and new_ver and old_ver != new_ver:
result.changes.append(f"Go updated: `{old_ver}` → `{new_ver}`")
result.changes.append(f"Go updated: ``{old_ver}`` → ``{new_ver}``")
elif new_ver and not old_ver:
result.additions.append(f"`{new_ver}`")
result.additions.append(f"``{new_ver}``")
return result
@@ -376,10 +379,11 @@ def check_go_version(patches: dict[str, str]) -> CheckResult:
# Matches lines that were auto-generated by this script so they can be stripped
# before re-injecting a fresh set on subsequent commits.
# Handles both single-backtick (older runs) and double-backtick (current) format.
_AUTO_LINE_RE = re.compile(
r"^(Added|Removed) `[^`]+`.*(configuration setting|API endpoint|audit log event)\."
r"^(Added|Removed) `{1,2}[^`]+`{1,2}.*(configuration setting|API endpoint|audit log event)\."
r"|^Go runtime updated from \S+ to \S+\."
r"|^Go runtime set to `[^`]+`\."
r"|^Go runtime set to `{1,2}[^`]+`{1,2}\."
r"|^🆕 New API file:"
r"|^🗑️ Removed API file:"
)
@@ -415,11 +419,11 @@ def _format_lines(result: CheckResult) -> list[str]:
elif "Go Runtime" in result.label:
for item in result.additions:
# item is e.g. "`1.22`" — strip backticks for the prose form
# item is e.g. "``1.22``"
lines.append(f"Go runtime set to {item}.")
for c in result.changes:
# c arrives as "Go updated: `1.21` → `1.22`" — rewrite it
m = re.search(r"`([^`]+)`\s*→\s*`([^`]+)`", c)
# c arrives as "Go updated: ``1.21`` → ``1.22``" — rewrite it
m = re.search(r"``([^`]+)``\s*→\s*``([^`]+)``", c)
if m:
lines.append(f"Go runtime updated from {m.group(1)} to {m.group(2)}.")
else:
+8 -8
View File
@@ -11,9 +11,9 @@
# • server/build/Dockerfile.buildenv — Go runtime version changes
#
# No secrets needed — uses the built-in GITHUB_TOKEN.
name: Config Change Checker
on:
pull_request:
types: [opened, synchronize, reopened]
@@ -22,7 +22,7 @@ on:
- 'server/channels/api4/**'
- 'server/public/model/audit_events.go'
- 'server/build/Dockerfile.buildenv'
# Cancel any in-progress run for the same PR when a new commit is pushed.
concurrency:
group: ${{ github.workflow }}-${{ github.event.pull_request.number || github.ref }}
@@ -38,11 +38,11 @@ jobs:
# not touch these paths intentionally and cannot receive description updates
# via GITHUB_TOKEN anyway (fork-like restrictions apply to most bots).
if: github.event.pull_request.user.type != 'Bot'
permissions:
pull-requests: write # needed to update the PR description
contents: read
steps:
- name: Checkout code
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
@@ -50,15 +50,15 @@ jobs:
persist-credentials: false
# Fetch enough history to diff against the base branch
fetch-depth: 0
- name: Set up Python
uses: actions/setup-python@a309ff8b426b58ec0e2a45f0f869d46889d02405 # v6.2.0
with:
python-version: '3.11'
- name: Install dependencies
run: pip install requests==2.32.3 --quiet
- name: Detect changes and update PR description
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}