Skip to content

Commit

Permalink
Merge pull request #1 from ratel-pay/work/auto-release-pr
Browse files Browse the repository at this point in the history
auto-release-pr
  • Loading branch information
andooown authored Aug 24, 2020
2 parents fd22c6b + b86a748 commit 964ec33
Show file tree
Hide file tree
Showing 7 changed files with 242 additions and 0 deletions.
15 changes: 15 additions & 0 deletions .github/workflows/auto-release-pr-test.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
name: Test auto-release-pr
on:
# To test, comment-in following line. The PR body will be generated.
#pull_request:
# dummy trigger
repository_dispatch:
jobs:
test:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v2
- uses: ./auto-release-pr
with:
githubToken: ${{ secrets.GITHUB_TOKEN }}
releasePRNumber: ${{ github.event.pull_request.number }}
2 changes: 2 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,2 +1,4 @@
# github-actions
Shared Github Actions

- [`auto-release-pr`](https://github.com/ratel-pay/github-actions/blob/master/auto-release-pr): リリースPRの本文を自動で更新
8 changes: 8 additions & 0 deletions auto-release-pr/Dockerfile
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
FROM python:3

ADD . /app
WORKDIR /app

RUN pip install -r requirements.txt

CMD ["python", "/app/release-pr.py"]
70 changes: 70 additions & 0 deletions auto-release-pr/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,70 @@
# auto-release-pr

リリースPull Requestの本文を自動で書き換えるActionです。

以下の動作をします。

1. 対象となるリリースPRを探索、見つからなければ新たに作成します。
1. リリースPRに含まれる各コミットのコミットメッセージから含まれているPRの一覧を取得します。
1. リリースPRの本文を更新して、前後の差分をコメントに残します。

## Inputs
| パラメータ | Required | Default | |
|-|-|-|-|
| `githubToken` || | GitHub Token。PRの探索や更新に利用されます。 |
| `baseBranch` | | `release` | リリースPRのBase Branch。PRの探索や作成時に利用されます。 |
| `headBranch` | | `master` | リリースPRのHead Branch。PRの探索や作成時に利用されます。 |
| `releasePRNumber` | | | リリースPRの番号。 `releasePRNumber` が指定されると `baseBranch`/`headBranch` は無視されます。 |
| `bodyTemplate` | | [`action.yml`](https://github.com/ratel-pay/github-actions/blob/master/auto-release-pr/action.yml) を参照 | PR本文の生成テンプレート。テンプレート内の `{summary}` が差分の箇条書きに置き換えられます。 |
| `commentTemplate` | | [`action.yml`](https://github.com/ratel-pay/github-actions/blob/master/auto-release-pr/action.yml) を参照 | 本文の更新差分のコメントのテンプレート。テンプレート内の `{diff}` が差分表示に置き換えられます。 |

## Usage

ブランチ運用フローによって2つの使い方があります。

### `master` ブランチを直接 `release` ブランチに取り込む場合

`master` 向きのPRがマージされるたびに、 `master` から `release` ブランチに向いているPRを探索 or 作成し、その本文を置き換えます。

```yaml
on:
pull_request:
types:
- closed
branches:
- master
jobs:
update:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v2
- uses: ratel-pay/github-actions/auto-release-pr@master
with:
githubToken: ${{ secrets.GITHUB_TOKEN }}
# Set if needed
# baseBranch: release
# headBranch: master
```

### リリースのたびにブランチを切ってPull Requestを作成している場合

`release` に向けたPRのBranchが更新されるたびに、その本文を置き換えます。

```yaml
on:
pull_request:
types:
- opened
- synchronized
branches:
- release
jobs:
update:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v2
- uses: ratel-pay/github-actions/auto-release-pr@master
with:
githubToken: ${{ secrets.GITHUB_TOKEN }}
releasePRNumber: ${{ github.event.pull_request.number }}
```
49 changes: 49 additions & 0 deletions auto-release-pr/action.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
name: Update Release PR
description: Find or create release Pull Request and update its body automatically.
inputs:
githubToken:
description: GitHub Token
required: true
baseBranch:
description: |
The base branch of Pull Request to find.
It will be ignored if `releasePRNumber` is passed.
required: true
default: release
headBranch:
description: |
The head branch of Pull Request to find.
It will be ignored if `releasePRNumber` is passed.
required: true
default: master
releasePRNumber:
description: The number of release Pull Request.
required: false
bodyTemplate:
description: |
The template of generating release Pull Request.
`{summary}` will be replaced with generating body.
required: true
default: |
## Changes
{summary}
commentTemplate:
description: |
The template of generating comment.
`{diff}` will be replaced with diff.
required: true
default: |
PR body is updated!
<details><summary>diff</summary>
<p>
```diff
{diff}
```
</p>
</detail>
runs:
using: "docker"
image: "Dockerfile"
89 changes: 89 additions & 0 deletions auto-release-pr/release-pr.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,89 @@
import github

from typing import Optional
import difflib
import os
import re
import sys


GITHUB_TOKEN: str = os.environ['INPUT_GITHUBTOKEN']
REPO_NAME: str = os.environ['GITHUB_REPOSITORY']
BASE_BRANCH: str = os.environ['INPUT_BASEBRANCH']
HEAD_BRANCH: str = os.environ['INPUT_HEADBRANCH']
RELEASE_PR_NUMBER: Optional[str] = os.environ.get('INPUT_RELEASEPRNUMBER')

BODY_TEMPLATE: str = os.environ['INPUT_BODYTEMPLATE']
COMMENT_TEMPLATE: str = os.environ['INPUT_COMMENTTEMPLATE']


# release 向きの最新 PR を取得
def find_latest_release_pr(repo: github.Repository.Repository, base: str, head: str) -> Optional[github.PullRequest.PullRequest]:
prs = repo.get_pulls(state='open', base=base, head=head, sort='created', direction='desc')

if prs.totalCount > 0:
return prs[0]
else:
return None

# release 向きの最新 PR を取得を探して、なかったら作成する
def find_or_create_release_pr(repo: github.Repository.Repository, base: str, head: str, number: Optional[str]) -> github.PullRequest.PullRequest:
if number:
return repo.get_pull(int(number))

latest = find_latest_release_pr(repo)
if latest:
return latest
else:
return repo.create_pull(title='[リリース]',
body='',
base=base,
head=head,
draft=True)

# PR のコミットメッセージから含まれる PR を探して新しいの PR の body を作る
def make_new_body(pr: github.PullRequest.PullRequest, template: str) -> Optional[str]:
commit_messages = [cm.commit.message for cm in pr.get_commits()]
merge_commit_messages = [m for m in commit_messages if m.startswith("Merge pull request")]

# 複数行のコミットメッセージから箇条書きの一行を生成する
def convert_to_body_line(message: str) -> str:
lines = message.splitlines()

number = re.search(r'#\d+', lines[0]).group()
title = lines[2]

return f'- {number}: {title}'

body_lines = '\n'.join(map(convert_to_body_line, merge_commit_messages))
if len(body_lines) > 0:
return template.format(summary=body_lines)
else:
return None

def main():
g = github.Github(GITHUB_TOKEN)
repo = g.get_repo(REPO_NAME)
release_pr = find_or_create_release_pr(repo, base=BASE_BRANCH, head=HEAD_BRANCH, number=RELEASE_PR_NUMBER)

# body を生成
new_body = make_new_body(release_pr, template=BODY_TEMPLATE)
if not new_body:
print("Failed to generate new PR body.")
sys.exit(1)

# diff を生成
old_body_lines = release_pr.body.splitlines()
new_body_lines = new_body.splitlines()
diff = '\n'.join(difflib.unified_diff(old_body_lines, new_body_lines))

# PR 本文を更新
release_pr.edit(body=new_body)

# comment に diff を残す
comment_body = COMMENT_TEMPLATE.format(diff=diff)
release_pr.as_issue().create_comment(comment_body)


if __name__ == "__main__":
main()
9 changes: 9 additions & 0 deletions auto-release-pr/requirements.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
certifi==2020.6.20
chardet==3.0.4
Deprecated==1.2.10
idna==2.10
PyGithub==1.53
PyJWT==1.7.1
requests==2.24.0
urllib3==1.25.10
wrapt==1.12.1

0 comments on commit 964ec33

Please sign in to comment.