mirror of
https://github.com/block/buzz.git
synced 2026-10-27 12:40:30 +00:00
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 <wesbillman@users.noreply.github.com>` 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 <pfleger.will@gmail.com> Co-authored-by: Duncan <dcfd242e557282d7a1e2cf2e6877522682f1e5c6156dc92ca7d90eaedd3b0f95@buzz.block.builderlab.xyz>
83 lines
3.3 KiB
Bash
Executable File
83 lines
3.3 KiB
Bash
Executable File
#!/usr/bin/env bash
|
|
set -euo pipefail
|
|
|
|
version="${1:-}"
|
|
mode="${2:-publish}"
|
|
[[ "$version" =~ ^[0-9]+\.[0-9]+\.[0-9]+(-[0-9A-Za-z.-]+)?$ ]] || {
|
|
echo "usage: $0 <semver> [publish|validate-only]" >&2
|
|
exit 1
|
|
}
|
|
|
|
remote="${RELEASE_REMOTE:-origin}"
|
|
git fetch "$remote" refs/heads/main:refs/remotes/origin/main --no-tags
|
|
git fetch "$remote" '+refs/tags/v*:refs/tags/v*' '+refs/tags/desktop-v*:refs/tags/desktop-v*'
|
|
base_sha="$(git rev-parse refs/remotes/origin/main)"
|
|
branch="version-bump/$version"
|
|
|
|
remote_branch="refs/heads/$branch"
|
|
remote_oid=""
|
|
if remote_oid="$(git ls-remote "$remote" "$remote_branch" | awk '{print $1}')" && [[ -n "$remote_oid" ]]; then
|
|
git fetch "$remote" "$remote_branch:refs/remotes/origin/$branch"
|
|
fi
|
|
|
|
git checkout -B "$branch" "$base_sha"
|
|
just bump-desktop-version "$version"
|
|
scripts/desktop_release.py generate "$version" --base "$base_sha" --repo block/buzz
|
|
|
|
git add \
|
|
.release/desktop-candidate.json \
|
|
CHANGELOG.md \
|
|
desktop/package.json \
|
|
desktop/src-tauri/tauri.conf.json \
|
|
desktop/src-tauri/Cargo.toml \
|
|
desktop/src-tauri/Cargo.lock \
|
|
pnpm-lock.yaml
|
|
|
|
agent_name="${RELEASE_AUTOMATION_NAME:-${AGENT_NAME:-Release Automation}}"
|
|
agent_email="${RELEASE_AUTOMATION_EMAIL:-${AGENT_EMAIL:-release-automation@users.noreply.github.com}}"
|
|
msg="$(mktemp)"
|
|
trap 'rm -f "$msg"' EXIT
|
|
cat >"$msg" <<EOF
|
|
chore(release): release Buzz Desktop version $version
|
|
|
|
Co-authored-by: $agent_name <$agent_email>
|
|
EOF
|
|
git commit -s -F "$msg"
|
|
scripts/desktop_release.py validate --candidate HEAD --version "$version" --repo block/buzz
|
|
|
|
candidate_sha="$(git rev-parse HEAD)"
|
|
previous_tag="$(python3 -c 'import json; print(json.load(open(".release/desktop-candidate.json"))["previous_tag"] or "initial")')"
|
|
printf 'base_sha=%s\ncandidate_sha=%s\nprevious_tag=%s\ntag=desktop-v%s\n' \
|
|
"$base_sha" "$candidate_sha" "$previous_tag" "$version"
|
|
|
|
if [[ "$mode" == validate-only ]]; then
|
|
exit 0
|
|
fi
|
|
[[ "$mode" == publish ]] || { echo "unknown mode: $mode" >&2; exit 1; }
|
|
if [[ -n "$remote_oid" ]]; then
|
|
git push --force-with-lease="$remote_branch:$remote_oid" "$remote" "HEAD:$remote_branch"
|
|
else
|
|
git push --force-with-lease="$remote_branch:" "$remote" "HEAD:$remote_branch"
|
|
fi
|
|
|
|
body="$(mktemp)"
|
|
trap 'rm -f "$msg" "$body"' EXIT
|
|
cat >"$body" <<EOF
|
|
## Buzz Desktop release v$version
|
|
|
|
- **Frozen main:** \`$base_sha\`
|
|
- **Reviewed candidate:** \`$candidate_sha\`
|
|
- **Previous desktop release:** \`$previous_tag\`
|
|
- **Proposed immutable tag:** \`desktop-v$version\`
|
|
|
|
This PR may be **squash merged** after the Desktop Release Candidate check and all protected-branch checks pass. Merging authorizes publication of the exact reviewed candidate; later or unrelated changes on \`main\` cannot alter it.
|
|
|
|
The checked-in changelog accounts for every non-merge commit in the release range. The Desktop tag points to the reviewed candidate commit, not the later squash commit. Publication remains bound to that immutable candidate tag.
|
|
EOF
|
|
if existing="$(gh pr list --repo block/buzz --head "$branch" --state open --json number --jq '.[0].number')" && [[ -n "$existing" ]]; then
|
|
gh pr edit --repo block/buzz "$existing" --title "chore(release): release Buzz Desktop version $version" --body-file "$body"
|
|
else
|
|
gh pr create --repo block/buzz --base main --head "$branch" \
|
|
--title "chore(release): release Buzz Desktop version $version" --body-file "$body"
|
|
fi
|