Pull Requestベースでgit revertできる pr-revert / pr-revert-action を作った

記事タイトルをみて「え?それもうあるじゃん」と思った方、半分正解で半分不正解かもしれません(私が知らないだけかもしれません)。

マージしたPull Requestをリバート(して新たなPull Requestを作成)する機能はあります。

f:id:k1LoW:20210802231024p:plain

マージ済みのPull Requestのページの上記画像でいうと赤枠の部分にあります。

リバート機能はあります。ただし、Web UI上にだけです。

マージ済みPull Requestを指定してリバートする機能は、実は公式のghコマンドにもGitHub APIにもないのです*1

ところで、開発の現場では必ずPull Requestでレビューを実施したあとマージ、そしてリリースという流れになっていることが多いです。

Pull Requestは何かしらの意味をもったコード差分の塊になっているため、「マージ済みPull Request単位でのリバート」は何かあった場合の有効な選択肢の1つとなります。

というわけで、様々な自動化のための1つのパーツとして「マージ済みPull Request単位でのリバート」を実現する pr-revert を作成しました。

github.com

pr-revert

pr-revertのデフォルトの振る舞いとしては以下の通りです。

  1. 対象のリポジトリ(リモートリポジトリ)を一時的なディレクトリにclone。
  2. リバートコミットを積むブランチ(リバートブランチ)を作成。
  3. Pull Requestをリバート。
  4. リバートブランチをリモートリポジトリにPush。
  5. リバートブランチでPull Requestを作成。
  6. 一時的なディレクトリを削除。

また、事項には以下の環境変数の設定が必要です( GITHUB_TOKEN 以外はGitHub Actions上では自動で設定される値です)。

環境変数 説明 デフォルト値
GITHUB_TOKEN リポジトリのアクセストーク -
GITHUB_REPOSITORY 対象リポジトリ ( owner/repo ) -
GITHUB_SERVER_URL GitHubのWeb UIのURL https://github.com
GITHUB_API_URL GitHub APIのURL https://api.github.com
GITHUB_GRAPHQL_URL GitHub GraphQL APIのURL https://api.github.com/graphql
$ export GITHUB_TOKEN=XXXxxxxxxXXXXxXXXXXXXX
$ export GITHUB_REPOSITORY=owner/repo

あとは、pr-revertコマンドを用途に合わせたオプションをつけて実行するだけです。

マージ済みPull Requestを指定してリバートする

(実装が間違っていなければ)Web UIとほぼ同じ機能になります。

$ pr-revert --number 3

マージされた最新5件のマージ済みPull Requestをまとめてリバートする

複数のマージ済みPull RequestをまとめてリバートするPull Requestを作ることが可能です。

$ pr-revert --latest 5

2時間前までにマージされたPull Requstをまとめてリバートする

期間指定も可能です。

$ pr-revert --until '2 hours'

新しいリバートPull Requestを作らずにブランチのPushだけをする

デフォルトの振る舞いの5番を実施しません。

$ pr-revert --latest 3 --no-pull-request

一時ディレクトリ を削除しない

デフォルトの振る舞いの6番を実施しません。

$ pr-revert --latest 3 --no-cleanup

ブランチを作成せずに直接デフォルトブランチにリバートする

デフォルトの振る舞いの2番を実施しません。

$ pr-revert --latest 3 --no-branch

pr-revert-action

pr-revertは最終的に自動化の一部として使われることを想定しています。GitHub Actionsによる自動化のためにactionも作成しています。

github.com

pr-revertに渡すオプションは全て環境変数で受け取れるようになっているので、例えば workflow_dispatch を作成する場合などは以下のようなワークフローを作成できます。

# .github/workflows/revert.yml
name: Revert

on:
  workflow_dispatch:
    inputs:
      latest:
        description: '--latest: マージ済みPull Requestを何件リバートするか指定してください'
        required: false
      until:
        description: '--until: マージ済みPull Requestをどれくらいの期間リバートするか指定してください'
        required: false
      number:
        description: '--number: マージ済みPull Requestの番号を指定してください'
        required: false

jobs:
  revert:
    runs-on: ubuntu-latest
    steps:
      -
        uses: k1LoW/pr-revert-action@v0
        env:
          GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
          PR_REVERT_LATEST: ${{ github.event.inputs.latest }}
          PR_REVERT_UNTIL: ${{ github.event.inputs.until }}
          PR_REVERT_NUMBER: ${{ github.event.inputs.number }}

というわけで

とりあえずパーツを作っただけですが、これからこれをうまく組み込んで、いろいろ作ってみたいと思っています(まだ)。

もし使ってみた方が現れましたらフィードバックお待ちしています。

*1:2021年7月時点で少なくとも私が探した限りは見つかりませんでした。