From 820a8589971df49bb9285a236ce1e2955a301abd Mon Sep 17 00:00:00 2001 From: Will Pfleger Date: Tue, 25 Aug 2026 18:50:58 -0400 Subject: [PATCH] fix(release): attribute desktop candidates to the operator (#6831) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The desktop release tooling hardcoded one contributor's personal identity into every release candidate commit. `scripts/prepare-desktop-release.sh` committed the candidate with a `git -c user.name='Wes' -c user.email='wesbillman@users.noreply.github.com'` override, and `scripts/desktop_release.py` `validate` required the candidate author to be exactly `Wes ` plus a matching `Signed-off-by` trailer. That leaked from Wes's working setup into the validation contract in #3568, so a release cut by any other operator was falsely attributed to and signed off by Wes (as happened on #6828). ## Change - `prepare-desktop-release.sh`: drop the `-c` identity overrides so `git commit -s` uses the operator's own configured identity to author and sign off the candidate. The automation `Co-authored-by` trailer is unchanged. - `desktop_release.py` `validate`: replace the exact-Wes checks with structural ones — the commit author must be non-empty, the body must contain a `Signed-off-by` trailer whose name and email match the commit author (honest DCO), and the existing automation `Co-authored-by` regex check stays. Failure messages remain specific. - `test-desktop-release-candidate.sh`: the fixture candidate now commits under the harness's own identity, and a new negative case rewrites the author to a mismatched identity and asserts the validator rejects it. Release authorization is bound to the merged PR via the GitHub API in `scripts/verify-desktop-release-merge.sh`, never the commit author field, so this does not weaken the trust model. `RELEASING.md` and `.github/workflows/desktop-release-candidate.yml` reference no author identity and need no change. Verified locally: `scripts/test-desktop-release-candidate.sh` passes, including the new sign-off/author-mismatch rejection. --------- Signed-off-by: Will Pfleger Co-authored-by: Duncan --- scripts/desktop_release.py | 13 ++++---- scripts/prepare-desktop-release.sh | 3 +- scripts/test-desktop-release-candidate.sh | 36 ++++++++++++++++++++++- 3 files changed, 44 insertions(+), 8 deletions(-) diff --git a/scripts/desktop_release.py b/scripts/desktop_release.py index ce9ceaab93..48e7ce86ce 100755 --- a/scripts/desktop_release.py +++ b/scripts/desktop_release.py @@ -257,12 +257,15 @@ def validate(args: argparse.Namespace) -> None: bad = [str(path.relative_to(ROOT)) for path, value in manifests.items() if value != version] if bad: raise SystemExit(f"version mismatch in: {', '.join(bad)}") - author = git("show", "-s", "--format=%an <%ae>", candidate) + name = git("show", "-s", "--format=%an", candidate) + email = git("show", "-s", "--format=%ae", candidate) + if not name or not email: + raise SystemExit("candidate has no author identity") + author = f"{name} <{email}>" body = git("show", "-s", "--format=%B", candidate) - if author != "Wes ": - raise SystemExit(f"unexpected candidate author: {author}") - if "Signed-off-by: Wes " not in body: - raise SystemExit("candidate is missing Wes Signed-off-by trailer") + signoffs = re.findall(rf"(?m)^Signed-off-by: {re.escape(author)}$", body) + if len(signoffs) != 1: + raise SystemExit(f"candidate must carry exactly one Signed-off-by trailer matching its author {author}") if not re.search(r"(?m)^Co-authored-by: .+ <.+>$", body): raise SystemExit("candidate is missing automation Co-authored-by trailer") print(f"validated immutable desktop candidate {candidate} for desktop-v{version}") diff --git a/scripts/prepare-desktop-release.sh b/scripts/prepare-desktop-release.sh index 43785075a1..eec08ac8c5 100755 --- a/scripts/prepare-desktop-release.sh +++ b/scripts/prepare-desktop-release.sh @@ -42,8 +42,7 @@ chore(release): release Buzz Desktop version $version Co-authored-by: $agent_name <$agent_email> EOF -git -c user.name='Wes' -c user.email='wesbillman@users.noreply.github.com' \ - commit -s -F "$msg" +git commit -s -F "$msg" scripts/desktop_release.py validate --candidate HEAD --version "$version" --repo block/buzz candidate_sha="$(git rev-parse HEAD)" diff --git a/scripts/test-desktop-release-candidate.sh b/scripts/test-desktop-release-candidate.sh index c63a157c00..503c64eb37 100755 --- a/scripts/test-desktop-release-candidate.sh +++ b/scripts/test-desktop-release-candidate.sh @@ -64,8 +64,42 @@ for path in ('desktop/package.json', 'desktop/src-tauri/tauri.conf.json'): open('desktop/src-tauri/Cargo.toml','w').write('[package]\nversion = "1.0.1"\n') PY git add . - git -c user.name=Wes -c user.email=wesbillman@users.noreply.github.com commit -q -s -m 'chore(release): release Buzz Desktop version 1.0.1' -m 'Co-authored-by: Test Automation ' + git commit -q -s -m 'chore(release): release Buzz Desktop version 1.0.1' -m 'Co-authored-by: Test Automation ' PATH="$mock_bin:$PATH" scripts/desktop_release.py validate --version 1.0.1 --repo block/buzz + good_candidate=$(git rev-parse HEAD) + + # A candidate whose Signed-off-by does not match its author is a dishonest + # DCO sign-off and must be rejected. Rewrite the author while keeping the + # original trailer body, then restore the honest candidate. + git -c user.name=Impostor -c user.email=impostor@example.com commit -q --amend --no-edit --reset-author + if PATH="$mock_bin:$PATH" scripts/desktop_release.py validate --version 1.0.1 --repo block/buzz >/dev/null 2>&1; then + echo "validator accepted a candidate whose sign-off does not match its author" >&2; exit 1 + fi + git reset -q --hard "$good_candidate" + + # The trailer must be a complete anchored line, not substring-matched. A prose + # line that merely contains the sign-off text, or a real trailer with trailing + # garbage, must be rejected. Both were accepted before the anchored parse. + for bogus in \ + 'not-a-trailer Signed-off-by: test ' \ + 'Signed-off-by: test trailing-garbage'; do + git commit -q --amend -m 'chore(release): release Buzz Desktop version 1.0.1' \ + -m 'Co-authored-by: Test Automation ' -m "$bogus" + if PATH="$mock_bin:$PATH" scripts/desktop_release.py validate --version 1.0.1 --repo block/buzz >/dev/null 2>&1; then + echo "validator accepted a malformed sign-off: $bogus" >&2; exit 1 + fi + git reset -q --hard "$good_candidate" + done + + # Two matching sign-offs are also invalid: the contract is exactly one. + git commit -q --amend -m 'chore(release): release Buzz Desktop version 1.0.1' \ + -m 'Co-authored-by: Test Automation ' \ + -m 'Signed-off-by: test ' -m 'Signed-off-by: test ' + if PATH="$mock_bin:$PATH" scripts/desktop_release.py validate --version 1.0.1 --repo block/buzz >/dev/null 2>&1; then + echo "validator accepted duplicate Signed-off-by trailers" >&2; exit 1 + fi + git reset -q --hard "$good_candidate" + grep -Fq "$unrelated_before" CHANGELOG.md grep -Fq "$unrelated_after" CHANGELOG.md ! grep -Fq "$prior_merge" CHANGELOG.md