From 7b3a8d91d5e6496f1fa6cb959797b2575b4dbd5b Mon Sep 17 00:00:00 2001 From: Janet Blackquill Date: Mon, 13 Jul 2026 20:55:24 -0400 Subject: [PATCH 1/5] mrrrp --- .github/workflows/publish.yml | 9 +++ Tools/actions_apply_test_merges.py | 101 +++++++++++++++++++++++++++++ 2 files changed, 110 insertions(+) create mode 100755 Tools/actions_apply_test_merges.py diff --git a/.github/workflows/publish.yml b/.github/workflows/publish.yml index 4aa40732b21..332f7e6f3fb 100644 --- a/.github/workflows/publish.yml +++ b/.github/workflows/publish.yml @@ -12,6 +12,9 @@ on: jobs: build: runs-on: ubuntu-latest + permissions: + contents: read + pull-requests: read steps: - name: Install dependencies @@ -31,6 +34,12 @@ jobs: git fetch --depth=1 rm Robust.Shared.Tests/Networking/NetEncryptionDoSTest.cs # DeltaV - work around bug in the backport + - name: Apply Test Merge PRs + run: Tools/actions_apply_test_merges.py + env: + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + GITHUB_REPOSITORY: ${{ vars.GITHUB_REPOSITORY }} + - name: Install dependencies run: dotnet restore diff --git a/Tools/actions_apply_test_merges.py b/Tools/actions_apply_test_merges.py new file mode 100755 index 00000000000..4ddc4302ca3 --- /dev/null +++ b/Tools/actions_apply_test_merges.py @@ -0,0 +1,101 @@ +#!/usr/bin/env python3 + +""" +Applies test merge pull requests to the build. +Explodes violently if it fails to do so. +""" + +import datetime +import os +import subprocess +import sys + +import requests +import yaml + +GITHUB_TOKEN = os.environ["GITHUB_TOKEN"] +GITHUB_REPOSITORY = os.environ["GITHUB_REPOSITORY"] +GITHUB_API_URL = os.environ.get("GITHUB_API_URL", "https://api.github.com") + +TEST_MERGE_LABEL = "Test Merge" +CHANGELOG_FILE = "Resources/Changelog/DeltaVTestMerges.yml" + +session = requests.Session() +session.headers["Authorization"] = f"Bearer {GITHUB_TOKEN}" +session.headers["Accept"] = "application/vnd.github+json" + + +def get_test_merge_prs(): + prs = [] + url = f"{GITHUB_API_URL}/repos/{GITHUB_REPOSITORY}/issues" + params = {"labels": TEST_MERGE_LABEL, "state": "open", "per_page": 100} + + while url: + resp = session.get(url, params=params) + resp.raise_for_status() + for item in resp.json(): + if "pull_request" in item: + prs.append(item) + + url = resp.links.get("next", {}).get("url") + params = None + + prs.sort(key=lambda item: item["number"]) + return prs + + +def run(*args): + return subprocess.run(args, check=False) + + +def apply_test_merge(pr): + number = pr["number"] + branch = f"tm-{number}" + + fetch = run("git", "fetch", "origin", f"pull/{number}/head:{branch}") + if fetch.returncode != 0: + print(f"::error::Failed to fetch PR #{number} ({pr['html_url']})") + sys.exit(1) + + merge = run("git", "merge", "--no-ff", "--no-edit", branch) + if merge.returncode != 0: + print(f"::error::Failed to merge PR #{number} ({pr['html_url']}) - conflicts?") + run("git", "merge", "--abort") + sys.exit(1) + + +def write_changelog(prs): + now = datetime.datetime.now(datetime.timezone.utc).isoformat() + + entries = [ + { + "id": pr["number"], + "author": pr["user"]["login"], + "time": now, + "url": pr["html_url"], + "changes": [{"type": "Add", "message": pr["title"]}], + } + for pr in prs + ] + + data = {"Name": "Test Merges", "Order": 99, "Entries": entries} + + with open(CHANGELOG_FILE, "w", encoding="utf-8-sig") as f: + yaml.safe_dump(data, f, sort_keys=False) + + +def main(): + run("git", "config", "user.name", "Test Merge Bot") + run("git", "config", "user.email", "action@github.com") + + prs = get_test_merge_prs() + print(f"Found {len(prs)} open PR(s) labelled '{TEST_MERGE_LABEL}'") + + for pr in prs: + print(f"Applying PR #{pr['number']}: {pr['title']} ({pr['html_url']})") + apply_test_merge(pr) + + write_changelog(prs) + + +main() From 3ca860f93b3cbeb15695248782b5444ed9530512 Mon Sep 17 00:00:00 2001 From: Janet Blackquill Date: Mon, 13 Jul 2026 21:07:33 -0400 Subject: [PATCH 2/5] stop submoduling it idiot --- Tools/actions_apply_test_merges.py | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/Tools/actions_apply_test_merges.py b/Tools/actions_apply_test_merges.py index 4ddc4302ca3..7d76788de58 100755 --- a/Tools/actions_apply_test_merges.py +++ b/Tools/actions_apply_test_merges.py @@ -52,12 +52,18 @@ def apply_test_merge(pr): number = pr["number"] branch = f"tm-{number}" - fetch = run("git", "fetch", "origin", f"pull/{number}/head:{branch}") + fetch = run( + "git", "-c", "submodule.recurse=false", + "fetch", "origin", f"pull/{number}/head:{branch}", + ) if fetch.returncode != 0: print(f"::error::Failed to fetch PR #{number} ({pr['html_url']})") sys.exit(1) - merge = run("git", "merge", "--no-ff", "--no-edit", branch) + merge = run( + "git", "-c", "submodule.recurse=false", + "merge", "--no-ff", "--no-edit", branch, + ) if merge.returncode != 0: print(f"::error::Failed to merge PR #{number} ({pr['html_url']}) - conflicts?") run("git", "merge", "--abort") From 8f2a2e081f8a890b9602024c65bb1f24e221b422 Mon Sep 17 00:00:00 2001 From: Janet Blackquill Date: Mon, 13 Jul 2026 21:20:16 -0400 Subject: [PATCH 3/5] so shallow --- Tools/actions_apply_test_merges.py | 25 ++++++++++++++++++++++++- 1 file changed, 24 insertions(+), 1 deletion(-) diff --git a/Tools/actions_apply_test_merges.py b/Tools/actions_apply_test_merges.py index 7d76788de58..2e95aefbed7 100755 --- a/Tools/actions_apply_test_merges.py +++ b/Tools/actions_apply_test_merges.py @@ -48,6 +48,25 @@ def run(*args): return subprocess.run(args, check=False) +def unshallow(): + is_shallow = subprocess.run( + ["git", "rev-parse", "--is-shallow-repository"], + check=True, capture_output=True, text=True, + ).stdout.strip() + + if is_shallow != "true": + return + + print("Repository is shallow, fetching full (blobless) history") + result = run( + "git", "-c", "submodule.recurse=false", + "fetch", "--unshallow", "--filter=blob:none", "origin", + ) + if result.returncode != 0: + print("::error::Failed to unshallow repository") + sys.exit(1) + + def apply_test_merge(pr): number = pr["number"] branch = f"tm-{number}" @@ -66,7 +85,8 @@ def apply_test_merge(pr): ) if merge.returncode != 0: print(f"::error::Failed to merge PR #{number} ({pr['html_url']}) - conflicts?") - run("git", "merge", "--abort") + if os.path.exists(".git/MERGE_HEAD"): + run("git", "merge", "--abort") sys.exit(1) @@ -97,6 +117,9 @@ def main(): prs = get_test_merge_prs() print(f"Found {len(prs)} open PR(s) labelled '{TEST_MERGE_LABEL}'") + if prs: + unshallow() + for pr in prs: print(f"Applying PR #{pr['number']}: {pr['title']} ({pr['html_url']})") apply_test_merge(pr) From d6661bb4997b807d532a9a43f70131a8f0bc37e3 Mon Sep 17 00:00:00 2001 From: Janet Blackquill Date: Mon, 13 Jul 2026 21:24:59 -0400 Subject: [PATCH 4/5] dont fetch EVERYTHING... --- Tools/actions_apply_test_merges.py | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/Tools/actions_apply_test_merges.py b/Tools/actions_apply_test_merges.py index 2e95aefbed7..ab0d2b1413e 100755 --- a/Tools/actions_apply_test_merges.py +++ b/Tools/actions_apply_test_merges.py @@ -15,6 +15,7 @@ import yaml GITHUB_TOKEN = os.environ["GITHUB_TOKEN"] GITHUB_REPOSITORY = os.environ["GITHUB_REPOSITORY"] +GITHUB_REF_NAME = os.environ["GITHUB_REF_NAME"] GITHUB_API_URL = os.environ.get("GITHUB_API_URL", "https://api.github.com") TEST_MERGE_LABEL = "Test Merge" @@ -60,7 +61,8 @@ def unshallow(): print("Repository is shallow, fetching full (blobless) history") result = run( "git", "-c", "submodule.recurse=false", - "fetch", "--unshallow", "--filter=blob:none", "origin", + "fetch", "--unshallow", "--filter=blob:none", + "origin", GITHUB_REF_NAME, ) if result.returncode != 0: print("::error::Failed to unshallow repository") From bd0dd7ff8209d2a32a841da31ef4e27f9330f6af Mon Sep 17 00:00:00 2001 From: Janet Blackquill Date: Mon, 13 Jul 2026 21:28:03 -0400 Subject: [PATCH 5/5] add ftl --- Resources/Locale/en-US/_DV/changelog/changelog-window.ftl | 1 + 1 file changed, 1 insertion(+) diff --git a/Resources/Locale/en-US/_DV/changelog/changelog-window.ftl b/Resources/Locale/en-US/_DV/changelog/changelog-window.ftl index 8567957ec61..144d40f3f28 100644 --- a/Resources/Locale/en-US/_DV/changelog/changelog-window.ftl +++ b/Resources/Locale/en-US/_DV/changelog/changelog-window.ftl @@ -1,2 +1,3 @@ changelog-tab-title-DeltaVChangelog = DeltaV changelog-tab-title-DeltaVAdmin = DeltaV Admin +changelog-tab-title-DeltaVTestMerges = Test Merges