メインコンテンツまでスキップ

StashからBitbucket Serverへプラグインを移行する話

Sato Taichi

Stash is now called Bitbucket Server

らしいです、はい。ブランドだけ変わって中身はそのまま何だろとか思ってたら、そんなことは無く大変な事になっております。ええ。

尚、本番環境の移行できていません。

Stash 用に作りこんだプラグインをこっそり持っておりまして、それを Bitbucket Server で動くように修正することには成功したので、情報共有しておきます。

但し、これは全ての変更差分を厳密に精査したわけではなく僕の利用範囲において対応が必要だった部分についてまとめているという事に留意して下さい。

Stash 4.0.0 系 == Bitbucket Server 問題#

まずおさえておきたいのは最後の安定板 Stash が3.11.3という事です。 それに対して Bitbucket Server は4.0.1です。 バージョン番号の採番ルールには変更がないので破壊的変更を伴う修正のあるリリースという事です。

ここでいう破壊的な変更と言うのは、もしブランド名が Stash のままだとしても行われることが予定されていた破壊的な変更も含まれています。ある種の非推奨 API の削除などがこれに含まれます。

例えば4.0.1のソースコードリリースでは、削除された筈のPullRequestFromRefRescopedNotificationHandlerを参照しているPullRequestActivityRenderContextというクラスがコンパイルエラーになります。

Bitbucket Server 4.0.1 はクリーンビルドせずにリリースしたという事が分かる事例ですね。

pom.xml 内に影響のある変更#

ビルドできる環境を作れないことにはバージョンアップもへったくれも無いので、pom.xml を頑張って修正します。

まず、Atlassian Plugin SDK 5.1.10では、Bitbucket Server 対応できていません。なので、Bitbucket Server のソースコードリリースに含まれている pom.xml から変更差分を読み取ります。

pom.xml の import を変更する#

まず、stash-parentへの pom.xml の依存をbitbucket-parentに変更します。今までこういう風に書いていたものを

<dependency>    <groupId>com.atlassian.stash</groupId>    <artifactId>stash-parent</artifactId>    <version>${stash.version}</version>    <type>pom</type>    <scope>import</scope></dependency>

こういう風に変更します。${stash.version}から${bitbucket.version}は、同じ pom.xml 内の<properties>タグで設定するものなので変更しなくても良いのですが作業漏れを発見し易くするために変えます。

<dependency>    <groupId>com.atlassian.bitbucket.server</groupId>    <artifactId>bitbucket-parent</artifactId>    <version>${bitbucket.version}</version>    <type>pom</type>    <scope>import</scope></dependency>

Stash Plugin API への依存を Bitbucket Server API への依存に変更する#

まず、com.atlassian.stashという groupId は、com.atlassian.bitbucket.serverに変わります。 次に、artifactId 内に含まれていたstash部分がbitbucketに変わります。

これらをまとめると、変更前はこういう宣言になっていたものが、

<dependency>    <groupId>com.atlassian.stash</groupId>    <artifactId>stash-api</artifactId>    <scope>provided</scope></dependency><dependency>    <groupId>com.atlassian.stash</groupId>    <artifactId>stash-spi</artifactId>    <scope>provided</scope></dependency><dependency>    <groupId>com.atlassian.stash</groupId>    <artifactId>stash-page-objects</artifactId>    <scope>provided</scope></dependency>

変更後はこういう風になります。

<dependency>    <groupId>com.atlassian.bitbucket.server</groupId>    <artifactId>bitbucket-api</artifactId>    <scope>provided</scope></dependency><dependency>    <groupId>com.atlassian.bitbucket.server</groupId>    <artifactId>bitbucket-spi</artifactId>    <scope>provided</scope></dependency><dependency>    <groupId>com.atlassian.bitbucket.server</groupId>    <artifactId>bitbucket-page-objects</artifactId>    <scope>provided</scope></dependency>

Servlet API がどっかいった問題#

いつからなのか分かりませんけども、Atlassian の maven リポジトリにデプロイされている Servlet API の artifactId が変更されています。非常に地味な変更なのでパッと見で気が付きません。

以前は、こうでした。

<dependency>    <groupId>javax.servlet</groupId>    <artifactId>servlet-api</artifactId>    <scope>provided</scope></dependency>

現在はこうなっています。つまり、プレフィックスとしてjavax.が追加されています。

<dependency>    <groupId>javax.servlet</groupId>    <artifactId>javax.servlet-api</artifactId>    <scope>provided</scope></dependency>

既に import 済のbitbucket-parentに依存する Servlet API のバージョンが記述されているので、ここでは version を宣言していません。

Maven 用のプラグインも変わっている#

今までmaven-stash-pluginを使っていましたけども、これからはbitbucket-maven-pluginを使うようです。

僕の手元の環境ではテストサーバを maven から起動する事はできていません。プラグインアーカイブは作成できたので、別途インストールしたサーバにプラグインをインストールして動作確認しています。

以前はこのように maven のプラグインを設定していました。

<plugin>    <groupId>com.atlassian.maven.plugins</groupId>    <artifactId>maven-stash-plugin</artifactId>    <version>${amps.version}</version>    <extensions>true</extensions>    <configuration>        <products>            <product>                <id>stash</id>                <instanceId>stash</instanceId>                <version>${stash.version}</version>                <dataVersion>${stash.data.version}</dataVersion>            </product>        </products>    </configuration></plugin>

これからは、こうなります。尚、${amps.version}は現在6.1.0だけが有効です。

<plugin>    <groupId>com.atlassian.maven.plugins</groupId>    <artifactId>bitbucket-maven-plugin</artifactId>    <version>${amps.version}</version>    <extensions>true</extensions>    <configuration>        <products>            <product>                <id>bitbucket</id>                <instanceId>bitbucket</instanceId>                <version>${bitbucket.version}</version>                <dataVersion>${bitbucket.data.version}</dataVersion>            </product>        </products>    </configuration></plugin>

使えるコンパイラのバージョンが 1.8 になった#

AMPS のバージョンが上がった結果、ついに Atlassian Plugin SDK でも Java8 が使えるようになりました。バンザイ。

今までは、以下のように<maven.compiler.source><maven.compiler.target>を指定していましたけども、ついにこれらを消せます。

<maven.compiler.source>1.7</maven.compiler.source><maven.compiler.target>1.7</maven.compiler.target>

明示的に指定したければ、このようにします。

<maven.compiler.source>1.8</maven.compiler.source><maven.compiler.target>1.8</maven.compiler.target>

Java のコードに影響のある変更#

コンパイルエラーを出せるようになったあら、次は Java のコードを変更します。

パッケージ名の変更#

基本的には、com.atlassian.stashパッケージがcom.atlassian.bitbucketパッケージに置き換わっています。

しかしながら、前述したように 4.0.0 へのバージョンアップに伴う破壊的変更を含んでいますのでリファクタリングも併せて行われています。

例えば、com.atlassian.stash.user.Permissionという Enum はcom.atlassian.bitbucket.permission.Permissionへ変更されています。ブランド名の変更とリファクタリングが同時におこなわれていますね。

同様に、com.atlassian.stash.user.PermissionServiceは、com.atlassian.bitbucket.permission.PermissionServiceに変更されています。

クラス名の変更#

僕が気が付いたアカンやつはどちらかというとクラス名の変更です。

Stash プラグインではイベントの処理を行う際にcom.atlassian.stash.event.StashEventを継承したイベントクラスを作成するのですけども、これが少し汎用的なcom.atlassian.bitbucket.event.ApplicationEventという名前に変更されています。パッケージ名以外の部分にブランド名を入れると碌なことにならないとか、そういう感じでしょうか。

似たような変更としては、Servlet を作っている際にログインユーザの情報を取れるcom.atlassian.stash.user.StashAuthenticationContextが、com.atlassian.bitbucket.auth.AuthenticationContextに変更されています。こいつは、ブランド名の変更、パッケージの移動、クラス名の変更と派手に変わっていますね。どうやって見つけたのか自分でも良く分かりません。

atlassian-plugin.xml に影響のある変更#

API の修正が終わったら、次はプラグイン構成ファイルの変更が必要です。

atlassian-plugin.xml は、テスト用とデプロイの二つを作っている筈なので更新漏れの無いようにしましょう。

ここでは、主に<component-import>タグの interface 属性を書き換えていきます。パッケージ名の変更が主なので余り問題はないでしょう。ベリファイアが無いので動かしてぬるぽで落ちるまで、変更漏れを見つけられません。

web-item タグで画面要素を追加している場合#

<web-item>タグの section 属性に記述しうる値は変更されています。例えば、プロジェクト毎に設定項目を追加したい場合、こんな風に書いていました。

<web-item key="my-settings-tab" name="my settings"    section="stash.project.settings.panel"></web-item>

stash部分をbitbucketに変更します。

<web-item key="my-settings-tab" name="my settings"    section="bitbucket.project.settings.panel"></web-item>

soy テンプレートで画面を作っている場合#

今までは、<stash-resource>タグを使っていましたが、これからは、<client-resource>タグを使います。

併せて画面用のリソースに採番されていた名前空間も変わっているので注意してください。具体的には、今までcom.atlassian.stash.stash-web-pluginという名前空間に UI 系のコンポーネントが定義されていましたが、これからはcom.atlassian.bitbucket.server.bitbucket-webという名前空間に定義されています。

これらをまとめると、以前はこういう風に定義していました。

<stash-resource key="my-view-serverside" name="my resource">    <directory location="views">        <include>/**/*.soy</include>    </directory>    <dependency>com.atlassian.stash.stash-web-plugin:server-soy-templates</dependency>    <dependency>com.atlassian.stash.stash-web-plugin:buttons</dependency></stash-resource>

これからは、こうなります。

<client-resource key="my-view-serverside" name="my resource">    <directory location="views">        <include>/**/*.soy</include>    </directory>    <dependency>com.atlassian.bitbucket.server.bitbucket-web:server-soy-templates</dependency>    <dependency>com.atlassian.bitbucket.server.bitbucket-web:buttons</dependency></client-resource>

UI コンポーネントの細かいリファクタリングも相当量ありそうですよね。

soy テンプレートに影響のある変更#

最後に soy テンプレートに関する変更です。

meta タグの decorator#

soy テンプレートでは<head>タグ内の<meta name="decorator">タグを使って Bitbucket Server で用意している共通的なコンポーネントをレンダリングします。具体的には、content 属性に既定の値を入れることで共通的な部品がレンダリングされます。大体この辺にドキュメントがあるやつです。

プレフィックスとしてstashで始まっているものは全てbitbucketに変更されています。

以前はこうだったものが、

<head>    <meta name="decorator" content="stash.project.settings">    <meta name="projectKey" content="{$project.key}">    <meta name="activeTab" content="project-notification-settings-tab"></head>

これからはこういう風に変わります。

<head>    <meta name="decorator" content="bitbucket.project.settings">    <meta name="projectKey" content="{$project.key}">    <meta name="activeTab" content="project-notification-settings-tab"></head>

XSRF 対策 FORM はどこに…#

XSRF 対策の FORM タグをレンダリングしてくれる UI コンポーネントがstash.widget.xsrfProtectedFormという名前で以前は定義されていました。恐らくbitbucket.internal.widget.xsrfProtectedFormが現在のものなんですけども、コンポーネントの名前に internal とか入ってると余り使いたくない気持ちになります。

代替の API は別な場所にあるんでしょうか…。

まとめ

日本で Stash プラグインを書こうなんてマニアは少ないと思いますので、出来る限り助け合っていきたいと考えています、ええ。

当該プラグインが公開されていないのは、社内で動いている細かいサービスに依存してて外に出してもそのままでは動かないからです、ええ。