All notable changes to this project will be documented in this file.
The format is based on Keep a Changelog, and this project adheres to Semantic Versioning.
v2.0.0 - 2026-05-08
The v2 marketplace tag is moving — this entry covers everything in it
as of today, from the original Rust rewrite (initially released
2026-04-20) through the Gitea support added 2026-05-05 and the Gitea
fast-forward fix on 2026-05-08.
- Action rewritten in Rust. The action is now a single Rust binary
shipped as a Docker container action and no longer requires a Node.js
runtime on the runner. API calls go through
octocrab. The user-facing inputs surface (github-token,number,merge-method,allowed-usernames-regex,filter-label,merge-title,merge-message) is unchanged. - Distribution moved from Docker Hub to GitHub Container Registry
(
ghcr.io/sudo-bot/action-pull-request-merge). Published on thelatesttag in addition to versioned tags. - Build pipeline reworked: multi-stage Dockerfile, Debian build stage, Alpine runtime, Docker image smoke-tested in CI before publish.
- Workflows declare least-privilege
permissionsblocks; CI actions bumped to current versions. - README rewritten with an inputs table, required permissions block, and worked examples for each merge method.
OctocrabClient::get_pulldeserialises responses straight into the action's minimalPullRequestprojection instead of going through octocrab's typedpulls().get()API and serde-cycling the result. Same wire request, more resilient to forks that omit optional GitHub fields.octocrabupgraded0.49→0.50.
- Gitea self-hosted support. The action auto-detects Gitea Actions (via
the
GITEA_ACTIONS=trueenv var the runner sets, or a/api/v1suffix onGITHUB_API_URL) and routes API calls through a Gitea-aware client that handles the three places Gitea diverges from GitHub:POST(notPUT) on/pulls/{n}/mergewith the CamelCaseDo/MergeTitleField/MergeMessageField/head_commit_idbody, label removal by numeric id (with a name→id lookup), and an empty-body merge response. No new runtime dependency. The existing GitHub path is unchanged. - README section documenting Gitea-compatible workflow gates — using
contains(github.event.pull_request.labels.*.name, '...')instead ofgithub.event.label.name, which Gitea does not populate. fast-forwardmerge method. CallsPATCH /repos/{o}/{r}/git/refs/heads/{base}to advance the base branch to the PR's head SHA — a true fast-forward with no merge commit. Fails if the base is not an ancestor of the head.fast-forward_or_mergemerge method. Attempts a fast-forward first and falls back to a regular merge if the fast-forward isn't possible.filter-labelis interpreted as a regex (matched against each PR label's name). After a successful merge the literal matched label is removed, not the regex pattern.
remove_labelnow percent-encodes the full label name. The previous encoder only handled%, space, and/, so labels containing?,#,&,+,=,:, or any non-ASCII byte (e.g.café, emoji) produced malformed URLs that GitHub would reject. Replaced with an RFC 3986 path-segment encoder that keeps the unreserved set and percent-encodes every other byte.- Label removal correctly removes the matched label even when
filter-labelis a regex (previously the regex string was sent to the delete endpoint). Cargo.toml'slicensefield saidMITwhile the actualLICENSEfile in the repository (and the rest of thesudo-botactions family) is the Mozilla Public License 2.0. Corrected the metadata to match:license = "MPL-2.0".- Gitea fast-forward.
merge-method: fast-forwardand the fast-forward leg offast-forward_or_mergewere callingPATCH /repos/{o}/{r}/git/refs/heads/{base}against Gitea, which returns405 Method Not Allowedbecause Gitea'sgit/refsAPI is read-only. The action now drives Gitea fast-forwards through the merge endpoint withDo: "fast-forward-only"andhead_commit_id. Gitea ≥ 1.22 is required for the FF path; on older Gitea,fast-forward_or_mergestill works because the unknown-Do422 falls through to a plain merge — purefast-forwardhard-fails (no equivalent operation exists on the older API). GitHub's path is unchanged. - Gitea HTTP error messages now include the URL path the action
called, so a
405/404from a misconfigured Gitea instance no longer requires reading the action source to diagnose.
- Test count grew from 19 to 74. New coverage:
wiremockintegration tests pin HTTP method, URL, headers and body for every endpoint on both clients; theis_giteadetection rule extracted to a unit-testedpick_backend();StdoutLoggerbyte-level verification via aWriteLogger<W: Write>parameterisation; error-propagation paths, multi-label match semantics, and Gitea label-id resolution edge cases all now have direct tests.
v1.2.0 - 2022-07-10
- Upgrade @actions/core from 1.2.6 to 1.9.0
- Upgrade @actions/github from 3.0.0 to 5.0.3
- Bump node-fetch from 2.6.0 to 2.6.7
- Upgrade from node 12 to node 16
v1.1.1 - 2020-06-03
- Fix label matching rules
- Upgrade @actions/core from 1.2.3 to 1.2.4
- Upgrade @actions/github from 2.1.1 to 3.0.0
- Migrate the code after @actions/github upgrade
v1.1.0 - 2020-02-26 [DEPRECATED]
- Make filter-label optional (#5)
- Upgrade dependencies
- Update examples in README.md
- Fix error when label is already removed
v1.0.3 - 2019-12-09 [DEPRECATED]
- First working version
v1.0.2 - 2019-12-09 [DEPRECATED]
- Some fixes
v1.0.1 - 2019-12-09 [DEPRECATED]
- Some fixes
v1.0.0 - 2019-12-09 [DEPRECATED]
- First stable version