BitbucketでPR作成時に表示されるコミットメッセージリストをPR説明テンプレート有りでも表示する

この記事は[PONOS Advent Calendar 2022](https://qiita.com/advent-calendar/2022/ponos)の19日目の記事です。
昨日は[@caramel_cafe](https://qiita.com/caramel_cafe)さんの[UnityのゲームでModが作られる手順について](https://qiita.com/caramel_cafe/private/1c007d26555c289b359d)でした。

# はじめに
弊社ではGitコード管理にBitbucketを使用しています。
Bitbucketには、プルリクエストを作成する際にデフォルトでdescriptionにマージ先ブランチとの差分コミットメッセージのリストが表示される機能があります。
私が所属しているチームでは、コミットメッセージの記入ルールがあり、このコミットメッセージがdescriptionに表示されることで、どんな対応をしたのか一目でわかるメリットがありました。

## が、しかし
プルリクエストのdescriptionにコミットメッセージが表示される条件には、[プルリクエストdescriptionテンプレート](https://bitbucket.org/blog/save-time-with-default-pull-request-descriptions)を設定していないことが必要でした。
現在は以下の内容でdescriptionテンプレートを設定しているため、テンプレートの内容+差分コミットメッセージのリストを表示したいことが今回の目的になります。ちなみに2022年12月時点でdescriptionテンプレートを設定している場合のコミットメッセージリスト表示機能は、公式から提供されていません・・・。

```
## 対応背景

## 対応内容

※ここにコミットメッセージのリストを表示したい

## UI 変更前 / 変更後

## 動作確認方法

## 備考
```

## Bitbucket Cloud Issuesでコミットメッセージの追加が熱望されている様子
https://jira.atlassian.com/browse/BCLOUD-17743

![スクリーンショット 2022-12-06 14.01.46.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/339435/73d20d10-816b-c462-9dfc-35bcbf1a5864.png)

# 実装環境
- Bitbucket Cloud
- Bitbucket Cloud REST API
- Jenkins
- Jenkins Generic Webhook Trigger

# 構成図
Bitbucket Cloudでプルリクエストが作成された際にWebhookを使用してJenkinsのジョブを実行します。Jenkinsでは、まず[Jenkins Generic Webhook Trigger Plugin](https://plugins.jenkins.io/generic-webhook-trigger/)を使用し、対象のプルリクエストの情報を取得します。
その後、[Bitbucket Cloud REST API](https://developer.atlassian.com/cloud/bitbucket/rest/intro/)を使用したプルリクエストのdescriptionを更新するジョブを実行します。

![プルリクエスト更新構成図.drawio (1).png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/339435/2ea6519c-e383-4b3e-0f56-2995c8b4aee5.png)

# Bitbucketの設定
1. [Bitbucketアカウントのアプリパスワードを発行する](https://developer.atlassian.com/cloud/bitbucket/rest/intro/#app-passwords) ※APIコール時の認証情報で使用します
1. [Bitbucket Webhook](https://support.atlassian.com/ja/bitbucket-cloud/docs/manage-webhooks/)でプルリクエストの作成時にWebhookが走るように設定する。

# Jenkinsジョブの設定
1. JenkinsにGeneric Webhook Triggerをインストール
1. Jenkinsジョブを作成
1. Jenkinsジョブのソースコード管理でGitを指定し、リポジトリのURLとビルドするブランチを設定する
1. Jenkinsジョブのビルド・トリガでGeneric Webhook Triggerにチェック
1. Post content parametersでプルリクエストの欲しい情報を変数化して代入する

## Generic Webhook Triggerで取得可能なペイロード情報
https://support.atlassian.com/bitbucket-cloud/docs/event-payloads/

# Jenkinsスクリプト
以下のスクリプトをJenkinsジョブに設定します。
このスクリプトが実行されることで、プルリクエストのdescriptionの対応内容のセクション内にコミットメッセージのリストが挿入されます。

```
# Generic Webhook Triggerで取得したプルリクエストID、マージ先ブランチ名、作業ブランチ名
echo "pullrequest_id: ${PR_ID}"
echo "desination_branch_name: ${PR_DESTINATION_BRANCH_NAME}"
echo "source_branch_name: ${PR_SOURCE_BRANCH_NAME}"
echo "repository_fullname: $SOURCE_REPOSITORY_FULL_NAME"

# 作業ブランチのHEADをリモートブランチと強制一致させる(git fetch2回は念の為)
git checkout "${PR_DESTINATION_BRANCH_NAME}"
git fetch origin
git checkout "${PR_SOURCE_BRANCH_NAME}"
git fetch origin
git reset --hard origin/${PR_SOURCE_BRANCH_NAME}

# 対象のプルリクエストのコミットメッセージのリストを取得する(マージ元ブランチとマージ先ブランチの比較)
COMMIT_LISTS=`git log --pretty=format:"%s" --no-merges ${PR_DESTINATION_BRANCH_NAME}..${PR_SOURCE_BRANCH_NAME}`

# コミットメッセージのリストをカンマ区切りの配列にする
# 区切り文字をカンマとする
IFS=,
ARR=($(echo $COMMIT_LISTS | tr "\n" ","))

# コミットメッセージのリストの個数をカウントする
COUNT=`echo ${#ARR[@]}`
echo "count：${COUNT}"

# コミットメッセージのリストの個数分ループを回す
for (( i=0; i< $COUNT ; i++ )); do
  # 箇条書きリストの文字列を作成する
  STR="$STR* ${ARR[i]}\n\n"
done

# Bitbucket RESTAPI実行に必要な情報。
BITBUCKET_ACCOUNT=[Bitbucketアカウント名]
BITBUCKET_API_URL="https://api.bitbucket.org/2.0/repositories/[Bitbucket Cloud ドメイン名]/${PROJECT_NAME}/pullrequests/${PR_ID}"

# 対象のプルリクエストの説明欄の対応内容にコミットメッセージのリストを追加する
curl --request PUT \
  --url ${BITBUCKET_API_URL} \
  -u  ${BITBUCKET_ACCOUNT}:${BITBUCKET_APP_PASSWORD}\
  --header 'Accept: application/json' \
  --header 'Content-Type: application/json' \
  --data "{ 
    \"description\": \"## 対応背景\r\n\r\n## 対応内容\n\n ${STR}\r\n\r\n## UI 変更前 / 変更\r\n\r\n## 動作確認方法\r\n\r\n## 備考\r\n\r\n\"
  }"
```
※ Bitbucketのアプリパスワードは、[Jenkins Manege Credentials](https://www.jenkins.io/doc/book/using/using-credentials/)で管理しています。

# Before
プルリクエストの説明テンプレートを設定しているため、コミットメッセージリストが表示されていない。
![スクリーンショット 2022-12-12 15.33.45.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/339435/c5b878fd-aa60-a533-ba17-cde748e25d5b.png)

# After
JenkinsからBitbucketのプルリクエスト更新APIを実行し、対応内容にコミットメッセージリストが表示されている。
![スクリーンショット 2022-12-12 19.21.43.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/339435/a34ec781-2468-0b61-f0d5-ccb30aaa5c12.png)


# 課題
- コミットメッセージの追加を実現出来たが、プルリクエストのdescriptionを更新するAPIが走ってしまうため、プルリクエスト作成時にdescriptionの編集が出来ない
- プルリクエスト作成時のWebhookでJenkinsジョブが実行されるため、プルリクエストのdescriptionが更新されるのを30秒〜1分程度待たないといけない
- descriptionに追加されるコミットメッセージは初回の差分のみ(デフォルトもそうなので大した問題ではない)

# まとめ
今回は、Bitbucket　プルリクエストのdescriptionテンプレートが設定されている場合でも、コミットメッセージのリストをdescriptionに追加する対応を実施しました。
GithubやSlackを用いたプルリクエスト管理ですとあまり悩まなくていい部分ではありますが、使用可能なアプリケーションが社内で限定されている場合や、公式から機能が提供されていない場合でも柔軟に対応することができ、自身のスキルアップに繋がったかなと考えています。
特にJenkinsは、様々なアプリケーションと連携出来ます。一度連携出来てしまえばシェルスクリプトをJenkinsジョブで実行出来るため、スクリプト内で外部のREST APIを実行する形が取れます。これはかなり応用が効くのではないかなと考えています。
今後もJenkinsを用いた課題解決をどんどん実施していきたいです。

明日は[@aibausoundさん](https://qiita.com/aibausound)です！