Gradle用のsemantic-releaseプラグインはJavaでsemantic-releaseを再実装したものしか無かったので、TypeScriptで書いたものを作りました。
./gradlew publish
を叩くだけのシンプルなものですが、CI周りの設定はGradle側に寄せてあるはずなのでこれで問題なく運用できます。バージョンをgradle.properties
で管理する必要がある点にのみ注意してください。
Gradle用のsemantic-releaseプラグインはJavaでsemantic-releaseを再実装したものしか無かったので、TypeScriptで書いたものを作りました。
./gradlew publish
を叩くだけのシンプルなものですが、CI周りの設定はGradle側に寄せてあるはずなのでこれで問題なく運用できます。バージョンをgradle.properties
で管理する必要がある点にのみ注意してください。
最近Java周りでもsemantic-releaseの利用機会が増えています。Gradle pluginとMaven pluginが生まれ、特に後者はyarn*1で実行されるため既存のプラグインとも組み合わせやすく、JavaScriptと比較しても遜色ない状態と言えそうです。
2019年3月時点で、Java特にMavenがどのようにsemantic-releaseを活用できるのか、まとめてみます。
プロジェクトにおいて以下の制約を導入することで、リリース作業をより一段階自動化する仕組みです。
すでにJavaコミュニティにおいてもSemantic Versioningは標準となっているため、実際に学ばなければならないのはConventional Commit Messageだけと言えます。
semantic-releaseは具体的なリリース作業を定義しません。このため使っているプロジェクト管理ツールやCIサービスを問わずに利用可能です。代わりに、リリース手順を構成するステップを定義しており、利用者はステップごとに必要な処理をフックできます。 これは、Mavenがビルドライフサイクルを構成するフェーズを定義しているのと近いです。Maven自身が各フェーズにおける具体的な処理を定義せずプラグインに委ねているように、semantic-releaseも具体的なリリース作業の定義をプラグインに委ねています。
各Stepの説明はsemantic-releaseのREADME.md
に書かれています:
Step名 | 説明 |
---|---|
Verify Conditions | リリースに必要な条件がすべて揃っていることを確認する |
Get last release | Git tagsから最新(前回)のリリースバージョンを取得する |
Analyze commits | 最新(前回)のリリースから今回のリリースまでに含まれるすべてのコミットを解析する |
Verify release | リリース可能な状態かどうか検証する |
Generate notes | 最新(前回)のリリースから今回のリリースまでに含まれるすべてのコミットからリリースノートを生成する |
Create Git tag | 新しくGitタグを作成する |
Prepare | リリースの準備をする |
Publish | リリースを出荷する |
Notify | 新しく作成したリリース、または発生したエラーについて通知する |
GitHub Actionsを使えば、PR後にPrepare Stepまで処理を進め、承認を受けたらPublish & Notifyするという運用もできそうです。出荷承認プロセスを持つコミュニティでも活用できるでしょう。
semantic-releaseをMavenと併用する場合、semantic-releaseがMavenを実行する形になります。Publish Stepでmvn deploy
する形です。
package.json
は必須ではないですが、実際にはこのように作成してしまったほうがプロジェクトの見通しは良くなると思われます。これはpom.xml
をコミットするために@semantic-release/git
のカスタマイズが必要となるためです。またdevDependenciesにsemantic-releaseとそのプラグインが列記されるため、それらのバージョン管理がしやすくなる利点もあります。
プロジェクトにpom.xml
とpackage.json
が同居するので、CIツール側で設定ファイルの有無によるビルドツールの推定をしている場合は注意が必要かもしれません。
semantic-release最大の利点は、なんと言っても頻繁にリリースが行えることです。何も考えずPull Requestをマージするだけで、すべてのリリース作業が実施されMaven Cental等にデプロイを行うことができます。LeanやContinuous Deliveryが証明したように、高速かつ頻繁にユーザへ変更を届けることはプロジェクトの成功へダイレクトに効きます。導入可能なプロジェクトでは速やかに入れていくことが望ましいと思います。
他には、semantic-releaseを利用することでリリースマネージャの手作業、例えばタグ打ちやCHANGELOG作成を自動化できる点も嬉しいです。GitHub Releaseの更新のような従来から別の自動化手法があったものも、コミットコメントをSingle Sourceとして利用する手法に切り替えることで、透明性と正確性を確保できます。
一般に、頻繁なリリースはユーザに追随するための負担を強いる可能性がありますが、semantic-releaseはバージョン番号をSemantic Versionに従った形で決めるので、ユーザもバージョン更新の必要性と負担を簡単に見積ることができます。デプロイ回数が増えるのでMaven Repositoryの記憶容量が気になるかもしれませんが、メリットに比較して十分に安いコストではと感じます。OSS開発においてはここは特に気にならない問題でしょう。
デメリットが小さいならJavaコミュニティにもすぐに普及するでしょうか?個人的には懐疑的です。大きく分けて2つの問題があります。
まずSemantic Commit Message自体、そこまでクリアに定義されているものではありません。AngularJS Commit Message Conventionsから生まれたもので、多様なプロジェクトに適合できるものにはまだなっていません。
またSemantic Commit Messageに定義されていないコミット種別を利用することも禁止されていません。プロジェクトごとにコミット種別の亜種が生まれ、収集つかなくなる可能性がありそうです。
例えば依存ライブラリのバージョンアップはchore
, build
, fix
, security
のいずれにするべきでしょう?実際にProbotプロジェクトではchore(package)
, chore(dependencies)
, build(package)
, fix(package)
のすべてが使われています。1プロジェクト内でも統一されていないわけです。
今のところ周辺ツールもあまり賢くないので、PRレビュー時にレビュアーがコミット種別を確認する必要があります。プロジェクト導入時の最初の難関は、不明瞭な定義をローカルルールに落とし込んできちんと普及させる、このプロセスにあるでしょう。
次に、Semantic Commit Messageの利用を忘れたときに、コミットコメントの修正が面倒という問題があります。Gitはこれをサポートしていますが、コミット履歴の修正は基本的な操作と比べて難度が高いため、ある程度の慣れが必要です。 これについてはPRをSquash Commitしてしまうという、若干粗い解決方法があります。GitHubはSquashしてマージする時のコミットコメントをPRタイトルから取るので、PRタイトルをSemantic Commit Messageに準じたものにすればよいのです。PRタイトルはWeb画面から簡単に修正できるので、慣れていない人でも回しやすいでしょう。なおSemantic Commit Probotはこの運用を想定した実装になっていて、コミットコメントがSemantic Commit Messageとして不正な場合でもPRタイトルが問題なければパスしてくれます。
以上で、Java屋がsemantic-releaseに思うことを見てきました。
機能的には充分で、すぐにプロジェクトに適用することができます。nexus-staging-maven-plugin
やmaven-release-plugin
などの既存設定をそのまま使えるので、新規プロジェクトのみならず既存プロジェクトへの導入も簡単でしょう。
まだJavaコミュニティにおいてはさほど知名度がないため、コミュニティでの開発に浸透するのはまだ先だと思いますが、個人プロジェクトではぜひ使ってほしいです。ユーザが増え実績が積まれれば、Javaコミュニティにおいても利用が進むことでしょう。
*1:npmでも良いはずだが、semantic-release-pluginのドキュメントはyarnで統一されているので、長いものには巻かれておく
最近新しいMaven Plugin用サイトを作ったので、mvn site
で作成できるサイトについて現時点での注意点をまとめる。
maven-fluido-skinが最も使われていてかつ実用的と思われる。以下の記述はこのskinのv1.7を利用することを前提とする。
Maven3から<reportPlugins>
による設定が可能になっているが、最新の公式サイトでは非推奨になっているので利用を避ける。
This new configuration format is not actually ready for end-users: please don't use it for the moment.
ページのフッターにCopyright情報が記載されるが、これはpom.xml
の<organization>
と<inceptionYear>
から情報を得て生成される。データが得られないとCopyright Holderが空になり違和感があるので、記入しておくと良い。
maven-site-plugin
にdoxia-module-markdown
に対する依存を追加すれば良い。.mdファイルはsrc/site/markdown
以下に置く。
<plugin> <groupId>org.apache.maven.plugins</groupId> <artifactId>maven-site-plugin</artifactId> <version>3.7.1</version> <dependencies> <dependency> <groupId>org.apache.maven.doxia</groupId> <artifactId>doxia-module-markdown</artifactId> <version>1.8</version> </dependency> </dependencies> </plugin>
plugin-info.html
にMaven、JDK 1.8、MemoryそしてDisk SpaceのRequirementを明記することができる。これはmaven-plugin-plugin
の機能で、<requirements>
を利用して設定できる。他にも特殊なRequirementがあるなら<others>
を使って明記することもできるようだ。
<plugin> <groupId>org.apache.maven.plugins</groupId> <artifactId>maven-plugin-plugin</artifactId> <configuration> <requirements> <maven>${maven.version}</maven> <jdk>1.8</jdk> </requirements> </configuration> </plugin>
昔から変わらないのでコピペで良い。
GitHubによると、今年は合計950 Contributions(25日時点)でした。仕事でほぼ使ってないのにこの数字というのは、多いのでしょうか少ないのでしょうか。
私は2018年にGitHubで927コントリビュートし、Findy内で1412位でした。月間の最大は154 (7月)、一日あたりの平均は2.6/日でした。あなたも2018年のコントリビューション活動をチェックしよう! https://t.co/XmkuTxXbHf #findy #コントリビューションオブザイヤー
— 爱我你就抱抱我 (@Kengo_TODA) December 19, 2018
2018年もSpotBugsが一番活発な開発でした。新機能開発はほぼ無く純粋なバグ修正がほとんどですが、リリース周りも担っていたので100 commitsを超える貢献をしていました。
同organizationの他プロジェクトでもsonar-findbugs 48 commits, spotbugs-gradle-plugin 43 commits, spotbugs-archetype 17 commitsという感じで、Mavenプラグインを除けば最も活発なcontributorでした。
個人プロジェクトではrtd-bot 72 commits, errorprone-slf4j 46 commits, findbugs-slf4j 44 commits, gradle-helper-for-java-8 40 commits, javadocky 39 commits, what-is-maven 13 commitsという感じでした。
rtd-botで使っているGitHub Probotはいろんな自動化が気軽にできそうで楽しいです。Sentryでサービスの監視をしていますが、Heroku上でChromeが起動しないことがあり、サービス自体はあまり安定させられていません。コストを掛けてサーバのスペックを上げないと解決でき無さそうなので、Read The Doc側のAPIが整備されるのを待つ形です。
今年でErrorproneプラグインもだいたい書けるようになり、これでPMD・Checkstyle・SpotBugs(FindBugs)・ErrorproneとJava周りの静的解析ツールはひととおりプラグインを実装できるようになりました。最近はJenkinsやMavenのプラグインに加えGradleのプラグインも学習中なので、ビルド周りの自由度はだいぶ上がった気がします。
個人的に気になっているProject Reactorについては、Javadocky以外に使いみちを見いだせていないのが残念な感じです。流行りのサーバーレスと合わせるならSpring Cloud Functionのような使いみちになるのでしょうが、そもそもサーバーレスではSpring自体ほぼ使わないという……。GraalVMでの起動高速化が一般的になれば別でしょうが、それまではJavaを利用しないという選択肢も有力だと個人的には考えています。
SpotBugs本体は旧バージョンのメンテナンスを止めて新機能開発に注力できる予定なので、以前からやりたいと話しているマルチスレッド対応を盛り込めればと思っています。1年でできるとは正直思ってませんが、とりあえず依存関係を整理してスレッドアンセーフなクラスを特定することはできるでしょう。おそらくBCELに依存するほぼすべてのDetectorがダメだとは思いますが……。
加えるなら、TypeScript・Kotlin・Rustといった言語の開拓でしょうか。基礎はもうあると思いますし、簡単なツールなら実装済みなのですが、もう少し複雑な事例も経験しておきたいところです。
私がSpotBugsなどで使っているドキュメントホスティングサービス、Read The Docsを使う上で助けになるGitHub Probotを作成しました。
ドキュメントがいつもどおり全部英語なので、日本語での解説をここに書いておきます。
rtd-bot
ユーザをメンテナーとして招待しておく。.github/config.yml
に rtd.project
を作成し、Read The Docsプロジェクト名とその言語を指定する。このプロジェクトではCommitizenとSemantic Releaseを導入しました。思っていたよりも使いやすく、またDependabotがすでにcommitizen風コミットコメントに対応していたため、特に導入に障害はありませんでした。MavenやGradleでも使えたら良いんですが、そこはまだハックが必要そうです。
Read The DocsのAPIはまだ機能不足が目立ちます。最近出たAPI v2でも認証機能すら無く、公開データへの読み取りアクセスしかできません。 今回はこの問題の回避にPuppeteerを使っています。つまり管理画面をNode.jsで操作しています。だいぶダーティハックですが、利用規約上も問題ないはずです。画面の更新には逐次追随する必要がありますが、過去の経験から言ってRead The Docsの画面はさほど大きく変更が入らないと思われます。
直近の予定としては、i18nには対応したいと考えています。他にも対応必要な設定があればROADMAP.mdに追記のPRを送ってください。
クラスメソッドさんのブログでSonarQubeの紹介がされています。そちらの記事では記事の半分ほどを割いてインストール方法を説明していますが、dockerを使えばより楽に行えますのでその方法を紹介します。
以下のコマンドで、組み込みデータベースを使用したサーバが立ち上がります。ユーザ名admin、パスワードadminでログインできます。 このコマンドは英文公式ページからの引用です。
$ docker run -d --name sonarqube -p 9000:9000 -p 9092:9092 sonarqube
なおalpineを使ったイメージもあるのですが、2018年8月1日現在でClassNotFoundErrorが出るなど不安定なようです。7.1-slpine
などのバージョンではなく、7.1
などのバージョンの利用を推奨します。
組み込みデータベースでの運用は検証用にのみ推奨されていますので、本番運用はRDBMSの利用が必要です。
以下のページにSonarQubeとPostgreSQLを立ち上げるdocker-compose.yml
が紹介されていますので、これを保存したディレクトリでdocker-compose up
すればSonarQubeとPostgreSQLが立ち上がります。
docker-sonarqube/recipes.md at master · SonarSource/docker-sonarqube · GitHub
$SONARQUBE_HOME/extensions/plugins
ディレクトリにプラグインの.jarファイルを保存することで、プラグインをインストールし有効化できます。
例えばSonarQube 6.7.4 LTSに sonar-findbugsとそれが依存しているSonarJavaをインストールするDockerfile
は以下のようになります:
FROM sonarqube:7.1 RUN wget -P $SONARQUBE_HOME/extensions/plugins/ --no-verbose https://github.com/spotbugs/sonar-findbugs/releases/download/3.7.0/sonar-findbugs-plugin-3.7.0.jar && \ wget -P $SONARQUBE_HOME/extensions/plugins/ --no-verbose https://sonarsource.bintray.com/Distribution/sonar-java-plugin/sonar-java-plugin-5.6.0.15032.jar
https://dev.to/kengotoda にて英語での情報発信をはじめました。宜しければそちらもご購読を。