GitHub Actions 実践入門

最近GitBucketのCIをTravisからGitHub Actionsに移行したりしていたのですが、達人出版会さんのセールでこの本が半額になっていたので購入してみました。

tatsu-zine.com

内容的にはGitHub Actionsの基本的な使い方から様々な機能、アクションの作り方まで一通りのトピックがカバーされています。

GitHub Actionsは公式のドキュメントが充実しており、日本語化もされているので概ね困ることはないと思うのですが、やはり書籍の形だと目を通しやすいですし、公式のドキュメントでは触れられていない実用的なTipsなども含まれています。欲をいえばサンプルレシピはもっとバリエーションが欲しかったかもとか、オフィシャルのアクションについて詳細な解説が欲しかったかもという気はしますが、GitHub Actionsでどんなことができるかを押さえるには最適な書籍なのではないかと思います。

なお、著者さんのブログによるとこの書籍は同人誌として執筆されたものだそうで、同人版も引き続き販売されているそうです。商業版の出版に当たって見直された内容は同人版にも反映されているとのことですし、最新情報にも随時アップデートされるとのことですので、特に拘りのない方はこちらを購入されたほうがお得かもしれません。

www.kaizenprogrammer.com

GraalVMでネイティブイメージを生成可能なScalaベースのCLIアプリケーションのためのgiter8テンプレートを作ってみた

以前PicocliとGraalVMを使ってScalaでネイティブCLIアプリケーションを作成する方法を試してみたのですが、その後細々とスタンドアロンのネイティブイメージを作成するのに適したScalaライブラリの組み合わせを試したりしていたので、これらをまとめてgiter8テンプレートにしてみました。

github.com

使い方は簡単で、まずは以下のようにしてプロジェクトを作成します。

$ sbt new takezoe/scala-native-cli.g8

scoptを使った簡単なサンプルコードも生成されるようになっているのでこれをベースにコマンドを実装したら、以下のコマンドを実行するとtarget/graalvm-native-imageディレクトリにネイティブイメージが生成されます(GraalVMとnative-imageコマンドは予めインストールしておく必要があります)。

$ sbt graalvm-native-image:packageBin

テンプレートといってもscala-native-packagerと、CLIツールを作るのに便利そうないくつかのライブラリを設定済みのsbtプロジェクトを生成するだけですが、他にもIOやファイル操作関連のライブラリを入れておくと便利そうな気がします。テンプレートにいろいろライブラリを入れておいて、必要なもの以外はコメントアウトして使うというような使い方が良いかもしれません。このあたりは自分でも使いながらブラッシュアップしていこうかと思います。

実は同様のgiter8テンプレートも既に存在するのですが、自分のユースケースにあわせてデフォルトのライブラリをカスタマイズできた方が便利そうということで…。

github.com

ただ、こちらのテンプレートはDockerイメージの作成にも対応しているようです。もちろんツールの利用者はDockerさえインストールされていれば使えますし、ビルドもDockerで行うためビルド時にローカルにGraalVMをインストールする必要もないようです。これは中々便利そうな機能なので時間があれば自分のテンプレートにも取り入れてみようかと思います。

MetalsプロジェクトでBloopのCLIを活用する

以前Metalsユーザ向けのBloopの紹介記事を見かけたのですが、確かにVS CodeなどでMetalsを使っている場合、BloopやMetalsサーバが常にVS Codeの背後で起動しているのでターミナルでのコンパイルやテストの実行にもBloopのCLIを活用するには理に適っているかもしれません。

chris-kipp.io

というわけで少し試してみました。BloopのCLI自体はMacであればHomebrewでインストールできます。

$ brew install scalacenter/bloop/bloop

コンパイルしてみます。sbtと違って必ずプロジェクト名を指定しないといけないという点に注意してください(マルチプロジェクトでない場合でも)。プロジェクトの一覧は bloop projects で表示できます。テストコードをコンパイルする場合は プロジェクト名-test を指定します。また、-wオプションを付けるとソースディレクトリを監視してファイルの変更時に自動的に再コンパイル結果を表示してくれます。

# プロジェクトの一覧
$ bloop projects
sample
sample-test

# ソースコードのコンパイル
$ bloop compile sample

# テストコードのコンパイル
$ bloop compile sample-test

# 自動再コンパイル
$ bloop compile sample -w

テストを実行する場合は以下のようにします。特定のテストケースのみ実行することももちろん可能です。

# テストを実行
$ bloop test sample

# 特定のテストケースのみ実行
$ bloop test sample -o com.github.takezoe.sample.SampleTest

# ワイルドカードも使用可能
$ bloop test sample -o *SampleTest

同様にプログラムの実行も可能です。プロジェクト内に起動クラスが複数存在する場合は -m で実行するクラス名を指定します。また、引数を渡したい場合は -- に続けて指定します。

# プログラムを実行
$ bloop run sample

# 起動クラスを指定して実行
$ bloop run sample -m com.github.takezoe.sample.SampleApp

# 引数を指定
$ bloop run sample -- arg1 arg2
$ bloop run sample -m com.github.takezoe.sample.SampleApp -- arg1 arg2

より詳細な使い方やオプションについては以下のBloopのドキュメントを参照してください。

実際に試してみたところ、当たり前と言えば当たり前なのですが確かに速いです。ただ、これはそもそもMetalsでも同様ですが、ビルド時にsbtでコード生成している場合などは事前に一度sbtを走らせてからでないとビルドが通らなかったりなど、bloopコマンドで完全にsbtを置き換えることはできません。また、プログラムの実行やテストなどはMetalsのUI上で行うことでエディタ上でのデバッグも可能になるといったメリットもあります。BloopのCLIはあくまで補助ツールとして使うと良い感じだと思います。

ScalaのLanguage Server「Metals」にコントリビュートしてみた

Metalsも最近は随分出来が良くなってきて割とVSCodeでも割と不自由せずにScalaの開発ができるようになってきました。Emacsvimユーザの方もMetalsを導入することで実用的なScala開発環境を構築できるのではないかと思います。

ひとつ気になっていたのが、業務上エディタでの保存時にscalafmtが実行されるようVS Code側でFormat on Saveを有効にしているのですが、OSSScalaプロジェクトなどscalafmtが設定されていないプロジェクトを触る際にエディタで保存するたびに何度「Not now」を選択しても無限に以下のダイアログが表示されてしまうという問題です。

f:id:takezoe:20200509205423p:plain

簡単に治せそうだったのでプルリクを出してみました。状態はデータベースに保存しておく方が望ましいなどコメントをいただき修正に少し時間がかかってしまいましたが無事マージしていただき、最新のMetals 0.9.0に含めていただくことができました。

github.com

さて、ここでは実際にMetalsに手を入れる際の方法を簡単に紹介したいと思います。

Metals(Language Server)自体はScalaで実装されており、通常のsbtプロジェクトですので普通にVSCodeIntelliJで開発を行うことができます。テストする際はまずsbt publishLocalでローカルにSNAPSHOTバージョンをpublishした上でVSCodeの設定で使用するMetalsのバージョンをSNAPSHOTバージョンに書き換えます。

f:id:takezoe:20200509213104p:plain

その後、VSCodeでReload Windowを実行すれば修正したMetalsを使うことができます(上記の画面で設定を変更するとリロードするかどうかを選択するダイアログが表示されますし、コマンドパレットから明示的にリロードすることもできます)。二度目からはsbt publishLocalしてReload Windowを行うだけでOKです。すぐに動作を確認できるのでラウンドトリップがやりやすいです。

ちなみにMetalsのコードから出力したログなどはVSCodeで開いたプロジェクトの.metals/metals.logに出力されています。また、Metalsは設定情報などをH2データベースに保存しており、このファイルも.metals/metals.h2.dbにあります。H2データベースのマイグレーションにはFlywayが使われています。ちょっと凝った機能を追加したりする場合はこのあたりも弄る必要があるかもしれません。

MetalsはScalaで実装されているので割と簡単に手を入れられますし、自分でも日常的に使うツールなので改善するモチベーションになります。Eclipseプラグイン開発時代のノウハウが活かせる部分も多いので、今後も気になった部分や追加した機能があれば積極的にコントリビュートしていきたいと思います。

Presto: The Definitive Guide: SQL at Any Scale, on Any Storage, in Any Environment

昨年から執筆中という話だったオライリーのPresto本がこの4月に発売になったとのことでゴールデンウィーク中に読んでみました。

Kindleでも7000円以上という高価格ですが、実は著者の皆さんが勤務されている米Starburst社のWebサイトから無料でダウンロードすることができます(メールアドレスの登録が必要ですが)。

www.starburstdata.com

内容はPrestoのインストール方法、アーキテクチャ、設定方法や外部連携の方法など、Prestoを使う上で必要になる事項が一通り網羅されています。開発者の方々自ら執筆された書籍だけあってPresto自体のアーキテクチャはもちろんのこと各コネクタも設定方法だけでなく内部構造にも触れられていたり、チューニングの勘所が解説されていたりとオンラインドキュメントとの差別化もきちんとなされており、広範囲をカバーした実用的かつ教育的なPrestoの入門書になっています。

Prestoは開発速度が非常に早いので中にはすぐ事情が変わってしまう部分もあるかもしれなかったり、クラウド全盛のこのご時勢に自前でPrestoを運用しようという方がどれくらいいるのかというあたりが若干謎なところではありますが、Prestoを触るのであれば間違いなく読んでおくべき一冊だと思います。

書籍の中では少しだけですが現在私が勤務するTreasure Dataについても触れられていました。Treasure Dataは初期からPrestoのユーザであること、現在では世界でも有数の規模のPrestoユーザであることが述べられています。ミーハーかもしれませんが、米国の著名なテック企業と並んで自分の勤務する企業の名前が挙げられているのを見るのはなんとも感慨深いものがありますね。これらの企業に肩を並べていけるよう引き続き精進していきたいと思います。

Scala Love Conferenceをライブストリーミングで視聴していました

今年はコロナウィルスの影響でScala Daysが延期されてしまったのですが、Scala Loveポッドキャストを配信しているOliさんの主催で先週末にScala Love Conferenceというオンラインカンファレンスが開催されました。

初開催にも関わらず、2トラック構成で休憩も挟みつつ約14時間の長丁場、小田好先生のキーノートもあり、さらには直前になってJetBrains社の提供により3つめのトラックが追加され、さらに当日はTwitchでのライブストリーミングも提供され事前登録者以外にも多くの方が視聴されていたようです。

自分は開催日を認識した時点ですでに参加登録が終了していたのですが、Twitchでライブストリーミング配信が行われていたので、途切れ途切れではありますがいくつかのセッションを視聴させていただきました。スケジュールは以下の通りで、自分は主にJoyルームのセッションを視聴していましたが、両ルームで面白そうなセッションがあった時間帯はブラウザ二枚で同時に視聴したりしていました。

セッション内容について

Li Haoyiさんのティラミスへの拘りとか、小田好先生のインデント構文への入れ込みようが強く記憶に残っています。Li Haoyiさんはとにかくあらゆる車輪を再発明しまくることで知られていますが、それらのLi Haoyiスタックを使ってScalaを学習するための本を執筆中なのだそうです。相変わらずパワフルですね。

Yokotaさんのsbtのセッション、SebastienさんのScala.jsセッションも今後の展望など参考になりました。Scala.jsの最適化はかなり頑張っていて、JVMと比べると数倍程度遅くなるものの手書きのJavaScriptより速くなることもあるとのことです。Yokotaさんの転職先は…大変気になりますね…。

James Wordさんのセッションはsbt-native-packagerを駆使してパッケージング&デプロイを行うライブデモだったのですが、Dockerイメージの各レイヤをビジュアルに確認できるdiveコマンドを使っていて便利そうだなぁと思いました。

LukaさんのMonoidのセッションもわかりやすい説明で面白かったです。後半はだいぶ眠くなってしまって記憶がほぼないので動画が公開されたらもう一度見直したいです。そういえばZLayer(ZIO用DIライブラリ)のセッションではAirframeも名前が出ていました。

オンラインカンファレンスについて

さて、オンラインカンファレンスのメリットとして現地に行かなくてもよいので参加しやすいという点はあるのですが、やはり時差問題は大きく、特に今回のScala Love ConferenceはEUタイムゾーンで朝から夜遅くまでというスケジュールだったのでEU在住の方以外は完走するのは中々厳しかったのではないかと思います。

自分も最後のScala Nativeのセッションを楽しみにしていたのですが、日本時間の朝まで起きていることができず残念ながら視聴することができませんでした。とはいえ、別タイムゾーンで複数日開催だとそれはそれでキツイので長時間でも1日開催の方がマシなのかもしれません。

また、個人的に重要だなと感じたのは、主催者の方々含め全員がリモートから参加している様子が見えることで、オフラインカンファレンスをストリーミングを視聴しているのとは違って、自分もカンファレンスに参加しているという感覚をちゃんと感じることができたという点です。これは実際にリアルタイム視聴してみての発見ですね。

今回は自宅に引きこもって悶々としているこのタイミングでこのようなイベントを視聴できとても良い気分転換になりましたが、いずれまたオフラインカンファレンスが何の障害もなく開催できるようになっても、引き続きオンラインカンファレンスがコミュニティイベントの1つの形として普及すると良いなと感じました。

まとめ

Scala3、光曲社のムーブ、そういえばScala Centerも気づけばすっかりメンバーが変わってしまいました。今回はコロナウィルスの影響でScala Daysの延期、そしてオンラインカンファレンス開催と予測不可能なことばかりです。2020年はScala業界にとっても節目の年になるのかもしれません。

ふと思ったのですが、ブログ用の写真とか撮れないのはオンラインカンファレンスのデメリットかもしれないですねw

jenvで複数バージョンのJDKを切り替える

仕事でJava 8とJava 11を行ったり来たりしたり、Javaの特定のマイナーバージョンでのみ発生する問題の調査などをしないといけないケースが出てきて、最初は都度環境変数で切り替えていたのですが、切り替え忘れてうっかり別のバージョンでコンパイルしてしまうということが増えてきたのでjenvというツールを試してみました。

github.com

Macの場合はbrewでインストールできます。

$ brew install jenv

jenvはデフォルトでは~/.jenvに設定などを保存するようです。以下のディレクトリを手動で作成しておく必要がありました。

$ mkdir -p ~/.jenv/versions

.bash_profileなどに以下を追加。

eval "$(jenv init -)"

JDKbrew caskでインストールできるようなのですが、手元にはすでにインストールしたものがあるのでとりあえずそれを追加してみます。

$ /usr/libexec/java_home -V
Matching Java Virtual Machines (1):
    1.8.0_181, x86_64:  "Java SE 8" /Library/Java/JavaVirtualMachines/jdk1.8.0_181.jdk/Contents/Home

/Library/Java/JavaVirtualMachines/jdk1.8.0_181.jdk/Contents/Home

jenv addコマンドでjenvにJDKを認識させます。

$ jenv add /Library/Java/JavaVirtualMachines/jdk1.8.0_181.jdk/Contents/Home

手動でダウンロードしたGraalVMとJava 11も追加してみます。

$ jenv add /Users/takezoe/Downloads/graalvm-ce-java8-20.0.0/Contents/Home
$ jenv add /Users/takezoe/Downloads/amazon-corretto-11.jdk/Contents/Home

これで準備完了です。jenv versionsでjenvが認識しているJDKが一覧表示されます。GraalVMは普通のOpenJDKと区別が付かなくて紛らわしい感じがありますね…。

$ jenv versions
* system (set by /Users/takezoe/.jenv/version)
  1.8
  1.8.0.181
  1.8.0.242
  11.0
  11.0.7
  openjdk64-1.8.0.242
  openjdk64-11.0.7
  oracle64-1.8.0.181

jenv global <version>で使用するバージョンをグローバルに切り替えます。JDKのインストールは自分で行う必要がありますが、一度JDKを認識させてしませば使い勝手はpyenvやrbenvと同じような感じです。

$ jenv global 1.8.0.181

特定のディレクトリだけ別のバージョンを使用するには当該のディレクトリでjenv local <version>を実行します。この場合、ディレクトリに.java-versionというファイルが生成されます。このファイルをGitにコミットしておけばブランチごとに使用するJavaのバージョンが異なる場合でも自動で切り替えることができますね。

$ jenv global 11.0.7

jenvでのバージョン切り替えに応じて環境変数JAVA_HOMEも切り替えるには以下のコマンドを使用してexportプラグインを有効にしておく必要があるようです。

$ jenv enable-plugin export

SDKMANでも複数バージョンのJDKの切り替えができ、こちらはJDKのインストールもできるようですが、ざっとドキュメントを見たところでは「特定のディレクトリのみこのバージョンを使う」という設定ができるかどうかわかりませんでした。ひとまずjenvをしばらく使ってみようと思います。

追記:jenvでJDKディストリビューションの区別が付かないという問題は最新のmasterブランチでは修正されており、jenv addでprovider付きのエイリアスも登録されるようになっていました。ただ、この修正を含むバージョンはまだリリースされていないようで、Homebrewでインストールすることはできません。