Bitbucket Server (Stash) プラグイン開発

オンプレミス向けGitリポジトリ管理のソフトウェアの1つに[Bitbucket Server (旧Stash)](https://ja.atlassian.com/software/bitbucket/server)があります。オンプレミスだと[GitHub Enterprise](https://enterprise.github.com/home)やOSSの[GitBucket](https://github.com/gitbucket/gitbucket)、[GitLab](https://about.gitlab.com/)を使っている方が多いかもしれませんが、Bitbucket ServerはJIRAで有名なAtlassian社の商用製品であり、[10名までなら$10の買い切り価格](https://ja.atlassian.com/software/bitbucket/pricing?tab=host-on-your-server)と小規模なら激安で使うことができます。また、[Atlassian Marketplace](https://marketplace.atlassian.com/plugins/app/bitbucket?application=bitbucket&category=&cost=&hosting=&marketingLabel=&q=)で様々な有償/無償プラグインが公開されているのも特徴の一つ。本記事ではこのBitbucket Serverのプラグイン開発に関する情報をつらつらとまとめておきます。

なお、StashというのはBitbucket Serverのバージョン3までの名前です。昨年のバージョン4リリースのタイミングでStash → Bitbucket Serverに名称変更されています。名前が変わっただけ、といっても **大部分のパッケージ名やクラス名変更という最高に互換性のない変更** が行われたため、Stash時代に書かれたプラグイン開発情報を見て真似てもそのままではBitbucket Server向けには動作しないので要注意です。

# プラグイン開発解説サイト
## 日本語
* [Atlassian製品プラグイン作成事始め](https://gist.github.com/raydive/10788095)
* [Stash プラグインの開発環境を構築するには](http://blog.satotaichi.info/setup-stash-plugin-dev-env/)

両方ともStashの頃に書かれた情報なので、最新のBitbucket Server向けのプラグインを開発したい方は要注意。ただしBitbucket Serverになっても基本的な開発の仕方は変わりません。上記サイトで書かれている[Atlassian Plugin SDK](https://developer.atlassian.com/docs/getting-started/set-up-the-atlassian-plugin-sdk-and-build-a-project)を使用して開発します。

## 英語
[Bitbucket Server Docs](https://developer.atlassian.com/bitbucket/server/docs/latest/)が開発者向けの公式サイト。ここから下記のような個別の解説記事へ辿ることができます。
 
* [Installing the Atlassian SDK](https://developer.atlassian.com/docs/getting-started/set-up-the-atlassian-plugin-sdk-and-build-a-project)
* [Creating a Bitbucket Server plugin](https://developer.atlassian.com/bitbucket/server/docs/latest/how-tos/creating-a-bitbucket-server-plugin.html#Following_a_tutorial)
* [Bitbucket Server Plugin Tutorials](https://developer.atlassian.com/bitbucket/server/docs/latest/tutorials-and-examples/bitbucket-server-tutorials.html)

初めての方は[Atlassian Plugin SDK](https://developer.atlassian.com/docs/getting-started/set-up-the-atlassian-plugin-sdk-and-build-a-project)をとりあえずインストールし、[チュートリアル](https://developer.atlassian.com/bitbucket/server/docs/latest/tutorials-and-examples/bitbucket-server-tutorials.html)を試してみると良いかと思います。ただし、Mavenを普段利用している方は[Stash プラグインの開発環境を構築するには](http://blog.satotaichi.info/setup-stash-plugin-dev-env/)で書かれているように`settings.xml`の置き換えをしておいたほうが無難です。後、インターネットに直接出れない環境の人は`settings.xml`にプロキシ設定を行うのを忘れずにしておくこと。

チュートリアルの中でAtlassian Plugin SDKが提供するコマンド`atlas-*`を実行するのですが、初回実行ではライブラリを数百MBダウンロードするためかなり時間がかかりますのでランチタイムに行く前に実行するなどが良いでしょう...

# プラグインでできること
[Bitbucket Server Docs](https://developer.atlassian.com/bitbucket/server/docs/latest/)にてPlugin typesとして、どういうことができるのか大体書かれています。

* [Hosting Application Events](https://developer.atlassian.com/bitbucket/server/docs/latest/overviews/hosting-application-events.html)
* [Global Hooks](https://developer.atlassian.com/bitbucket/server/docs/latest/how-tos/global-hooks.html)
* [Repository Hooks](https://developer.atlassian.com/bitbucket/server/docs/latest/how-tos/repository-hooks.html)
* [Global Merge conditions](https://developer.atlassian.com/bitbucket/server/docs/latest/tutorials-and-examples/controlling-when-pull-requests-can-be-merged.html)
* [Repository Merge conditions](https://developer.atlassian.com/bitbucket/server/docs/latest/how-tos/repository-hooks.html)
* [Adding commit metadata](https://developer.atlassian.com/bitbucket/server/docs/latest/overviews/adding-commit-metadata.html)

Gitリポジトリに対するpushをフックしたり、ブラウザからの操作(リポジトリ作成、ブランチ作成、プルリクエストの処理など)をフックすることができます。
プラグインで独自に画面を追加することもできますし、既存の画面を拡張するポイントも用意されている箇所があります。例えば、[Adding a column to the branch listing](https://developer.atlassian.com/bitbucket/server/docs/latest/how-tos/adding-column-to-branch-listing.html)というHow to記事では既存のブランチ一覧画面にカラムを追加する方法について解説しています。

# 開発環境
チュートリアルで登場しますが、[Atlassian Plugin SDK](https://developer.atlassian.com/docs/getting-started/set-up-the-atlassian-plugin-sdk-and-build-a-project)をインストールすると入る`atlas-run`コマンドを実行するとローカルでBitbucket Serverが起動し、プラグインをビルド＆デプロイし動作確認することができます。なお、`atlas-run-standalone`コマンドというものもあるのですが、こちらはプラグインの自動テプロイはしません。

`atlas-run`コマンドは初回はかなり遅いですが、2回目以降もそれなりに時間がかかります。そもそもBitbucket Serverの起動がめちゃくちゃ遅い。この遅さに耐えれなくてプラグイン開発を諦める人がでそうな気がするくらい遅い。一応、[FastDev](https://developer.atlassian.com/docs/developer-tools/automatic-plugin-reinstallation-with-fastdev)や[QuickReload](https://developer.atlassian.com/docs/developer-tools/automatic-plugin-reinstallation-with-quickreload)というプラグインを動的に再インストールして効率化する方法があります。今後は[FastDev](https://developer.atlassian.com/docs/developer-tools/automatic-plugin-reinstallation-with-fastdev)は非推奨でQuickReloadが推奨のようですが、まだ解説しているサイトは少ないですし、[Atlassian Plugin SDK](https://developer.atlassian.com/docs/getting-started/set-up-the-atlassian-plugin-sdk-and-build-a-project)が生成するプロジェクト雛形も今はまだ[FastDev](https://developer.atlassian.com/docs/developer-tools/automatic-plugin-reinstallation-with-fastdev)をデフォルトで使っています。[FastDev](https://developer.atlassian.com/docs/developer-tools/automatic-plugin-reinstallation-with-fastdev)は[リロードされないものがあったりとトラブルもある](https://answers.atlassian.com/questions/32972059/answers/32973137)ようです。それを解決したのが後継の[QuickReload](https://developer.atlassian.com/docs/developer-tools/automatic-plugin-reinstallation-with-quickreload)のようです。なお、Bitbucket Serverプラグイン開発でQuickReloadを利用するには、上記の[FastDevだとリロードされない問題](https://answers.atlassian.com/questions/32972059/answers/32973137)の解答が参考になります。

また、クラスのリロードに関してはお金を出して[JRebel](https://zeroturnaround.com/software/jrebel/)を使うというのも手です。圧倒的に速い。[こちら](https://davidsimpson.me/2015/05/08/speeding-up-atlassian-sdk-with-jrebel/)で利用方法が解説されています。Bitbucket Server本体のJARの中にも何気に`jrebel.xml`が格納されているものもあり、Atlassian社の開発者も使っていそうな気がします。


# REST APIの利用
プラグインで開発する画面からJavaScriptでBitbucket Serverが提供するREST APIを呼び出し、様々なリソースを利用することができます。[REST APIのドキュメント](https://developer.atlassian.com/bitbucket/server/docs/latest/reference/rest-api.html)ではJSON例も書かれていますので、読むとどういうAPIか大体想像ができるかと思います。

# データの永続化
実装したいプラグイン内容によっては、何らかのデータを永続化したいこともあるでしょう。[Bitbucket Server Docs](https://developer.atlassian.com/bitbucket/server/docs/latest/)のCommon tasksから下記情報へ辿れます。

* [Storing data: active objects](https://developer.atlassian.com/docs/atlassian-platform-common-components/active-objects)
* [Storing data: plugin settings](https://developer.atlassian.com/display/SAL/Storing+plugin+settings)

後者は簡単なKey-Valueストアの仕組みであり、プラグインの設定情報の格納に利用すると良いでしょう。前者はActive ObjectsというORM (object relational mapping)を利用する汎用的な方式です。プラグインで独自にRDBMSにテーブルを定義して好きなデータを格納することができます。

# 画面開発
[Bitbucket Server Docs](https://developer.atlassian.com/bitbucket/server/docs/latest/)のReferenceから[Web UI API](https://developer.atlassian.com/bitbucket/server/docs/latest/reference/web-ui-api.html)へ辿れます。画面(UI)を構成するAPIがたくさん用意されています。
特徴的なのは[Soy API](https://developer.atlassian.com/bitbucket/server/docs/latest/reference/soy-api.html)というテンプレートAPIを使っているところでしょうか。

# プラグイン実装例
[Bitbucket Server Docs](https://developer.atlassian.com/bitbucket/server/docs/latest/)のReferenceから[Plugin Module Types](https://developer.atlassian.com/bitbucket/server/docs/latest/reference/plugin-module-types/plugin-modules.html)を開くとプラグインサンプルやHow to記事がいくつかあるので参考になるかと思います。

また、OSSで公開されているプラグインもいくつかあるので、それらのソースを読むのも参考になるかと思います。[Open source at Atlassian](http://atlassian.bitbucket.org/#bitbucketserver)で紹介されていますし、GitHubでソース公開されているプラグインもあります([これ](https://github.com/sford/yet-another-commit-checker)とか[これ](https://github.com/palantir/stash-disapproval-plugin))。


(随時更新するかもしれません)