Add a /rebase slash command for maintainers - #332
Conversation
Zaldaryon
left a comment
There was a problem hiding this comment.
Reviewed the workflow security boundaries, token handling, merge commit verification, and offline test suite.
The security model is solid: the workflow restricts invocation to collaborators with admin, write, or maintain permissions, runs the rebase in an isolated throwaway repository, executes scripts exclusively from the main checkout rather than the PR branch, and passes tokens via a dynamic credential helper rather than embedding them in config or command lines. Refusing to drop merge commits that carry their own resolutions prevents silent code loss during flattening. Running test-rebase-pr.sh passes all 122 checks across all 18 test cases.
Targeting main makes sense here because GitHub Actions requires issue_comment triggers to live on the default branch. LGTM.
A maintainer comments
/rebaseon a pull request and CI does the git chores we keep asking contributors for: it replays the branch's commits onto the current tip of its base branch, drops merge commits, strips trailing whitespace from the lines the pull request added, and force-pushes the result back under a lease. Authors stay authors; the committer becomes github-actions[bot], and the whitespace cleanup lands as one separate bot commit so it is visible.Targets
mainbecauseissue_commentworkflows only ever run from the default branch. CONTRIBUTING gets two paragraphs on the command.What it refuses, with a comment saying why:
indevresolved a README conflict: the command would have said so instead of pushing a branch missing that line.indevormainin this repository (the release pull request would otherwise get flattened and force-pushed).--force-with-leasepinned to the sha seen at the start).Whitespace rules mirror
.editorconfig: only lines the pull request added, never a line it did not touch;*.mdand the generated trees are skipped; in a.patchonly the diff's own+lines are touched, never context or removed lines, which must stay byte identical to the vanilla baseline; CRLF endings are kept; renames are detected; files that contain a NUL byte are left alone.Security shape, since this runs on a comment event with
contents: write:mainfor its own scripts only, and all git work happens in a throwaway repository created by the script, so the pull request's files never land in the workspace.run:block. The script prints one JSON line; the comment is composed by a python script that neutralises backticks and newlines in branch and file names.set -xis deliberately absent.persist-credentialsis off on the checkout.Setup after merge, for an admin: add a repository secret
PR_MAINTENANCE_TOKENholding a classic personal access token with thereposcope, issued by a maintainer account with write access here. GitHub's own token cannot push to a fork even when the pull request allows maintainer edits, so without that secret the command only works for branches that live in this repository and says so on forks. The run ends red on any error so the maintainer who commented gets the failure email.Testing:
.github/scripts/test-rebase-pr.shis an offline harness (file:// remotes, no token) with 122 checks over 18 cases: plain rebase, merge commit dropped with a byte-identical tree, no-op, empty branch, conflict, head moved, lease refused when the fork branch races the push, a merge that carries changes, each whitespace rule including the.patchand rename cases, a hostile fork shipping its own copy of the strip script, workspace integrity, and every comment text. Run it from the repository root withbash .github/scripts/test-rebase-pr.sh. The credential helper form was checked separately withgit credential fill. The workflow itself cannot run before it is onmain; a first live test can be a same-repo branch, which needs no secret.