Kengo's blog

Technical articles about original projects, JVM, Static Analysis and TypeScript.

JJUG CCC 2021 FallでLT参加してきました

JJUG CCC 2021 FallにてJSR305に代わる静的解析用標準アノテーションの策定を目指す活動について紹介しました。スライドは以下からご覧いただけます:

speakerdeck.com

2021年11月24日更新:動画はJJUG公式から公開いただいています:

www.youtube.com

以下、単に感想です。

静的解析用アノテーションが多数存在する件

この17年間で生まれた静的解析アノテーション、数はかなりあるんですが歴史等まとまっているものではないので、Maven Centralにデプロイされた日をベースに整理していました。スライド草案に記載した歴史は以下のように非常に長いものになりました:

f:id:eller:20211121203045p:plain
関連アノテーションの歴史

地味に困ったのがJSR305に関する意思決定がJCPのサイトで公開されていないことです。

JCPからリンクされているGoogle Groupを見ても「なぜ活動が止まったか」はわかりません。ここでの活動自体が非活発になったので。近年のJEPがチケットやメーリングリストで管理され透明性が高いのは、こうした反省を踏まえたものなのかもとか思いました。

わかりやすい動画を作成したい

私の動画はmacOSのスクリーンキャプチャ機能で録画しただけのものです。解像度を変えるためにQuickResを購入しましたが、ほかはマイクのようなハードウェア含め工夫をしていません。

が、今回みなさんの動画を見ていると、画面隅に顔を映している方がいらして、しかもその方が気持ちわかりやすかったりするんですよね。デジタル表現の工夫や技法は重要になっていますし、きちんと学びたいなと思いました。まぁ動画編集の時間が作れるかは別の問題ですけど……(今回も体調不良で急遽幼稚園を休んだ子供の面倒を見ながらの録画だった)

JJUG CCCでの過去発表へのリンク

ソフトウェアプロジェクトではないGitHubリポジトリにどのようなライセンスを適用するか

ソフトウェアプロジェクトではないGitHubリポジトリにどのようなライセンスを適用するか?という問いを東京都オープン・ソース・ソフトウェア公開ガイドラインのIssueで見かけたので意見を述べてみます。結論を急がれる方は以下のサイトをどうぞ。

choosealicense.com

なお筆者は弁護士でも法律家でもないので、ここの記載内容はあくまでも参考に留めるようご注意ください。また本投稿では、Open Source Initiative (OSI)による承認を受けたオープンソースソフトウェアライセンスに限らず、その他のライセンスも含めて「ライセンス」と呼んでいます。

GitHubリポジトリにライセンスを適用しないとどうなるのか

GitHubの利用規約には以下の定めがあります:

  1. License Grant to Other Users Any User-Generated Content you post publicly, including issues, comments, and contributions to other Users' repositories, may be viewed by others. By setting your repositories to be viewed publicly, you agree to allow others to view and "fork" your repositories (this means that others may make their own copies of Content from your repositories in repositories they control). If you set your pages and repositories to be viewed publicly, you grant each User of GitHub a nonexclusive, worldwide license to use, display, and perform Your Content through the GitHub Service and to reproduce Your Content solely on GitHub as permitted through GitHub's functionality (for example, through forking).

またGitHubのヘルプには以下の記載があります:

You're under no obligation to choose a license. However, without a license, the default copyright laws apply, meaning that you retain all rights to your source code and no one may reproduce, distribute, or create derivative works from your work.

これを合わせると、publicなGitHubリポジトリにライセンスを適用しなかった場合、

  1. GitHub上での閲覧やforkは可能だが、
  2. そのコンテンツを複製・再頒布することはできず、また
  3. 派生物を作成することもできない

状態になると解釈できます。公開はしているが使っていいとは言っていない、というやつです。

なおこの場合でも「著作権法が適用される」という記述から著作権者を明確にするのは必須と考えられます。ライセンスを適用しない場合でも必ず README.md などをリポジトリにコミットして著作権者を明確にしてください。Organizationの方に説明が書いてあっても(利用規約によりforkが許可されている以上)不十分と考えられますので、必ずリポジトリ単体で説明責任を果たすようにしましょう。

ソフトウェアではないコンテンツの利用・再頒布・派生物を許可するにはどのライセンスを適用するべきか

以上の理由から、ソフトウェアではないコンテンツであっても第三者による利用・再頒布・派生物を期待するならば、ライセンスを適用する必要があると言えます。ではどんなライセンスを適用するべきでしょうか。

同じくGitHubが提供しているchoose a licenseというサイトには、オープンソースソフトウェアライセンスやメディア用のオープンライセンスを適用可能だと記載されています:

Any open source software license or open license for media (see above) also applies to software documentation. If you use different licenses for your software and its documentation, be sure to specify that source code examples in the documentation are also licensed under the software license.

確認のため、ここで前例を見てみましょう。いくつか有名どころのガイドラインについてライセンスを調べてみました:

Creative CommonsApache Licenseが利用されることが多そうです。Apache Licenseは以下に引用するとおりドキュメントが明確にライセンス対象として定義されていることから、オープンソースソフトウェアライセンスとしては使いやすいものと思われます:

"Source" form shall mean the preferred form for making modifications, including but not limited to software source code, documentation source, and configuration files.

"Object" form shall mean any form resulting from mechanical transformation or translation of a Source form, including but not limited to compiled object code, generated documentation, and conversions to other media types.

またソースコードを含むリポジトリにおいては「ドキュメント内に掲載されるソースコード」に「ソースコードに適用するライセンス」と「ドキュメントに適用するライセンス」どちらを適用するか、明確にする必要もあります。AWSの例ではREADMEでこれを明確にしています

まとめ

GitHubでソフトウェアプロジェクトではないリポジトリを公開する場合においても、オープンソースソフトウェアライセンスやその他のライセンスを適用することが可能です。特に再利用や再頒布を期待するのであれば必須と言えます。現時点ではCreative Commons 4.0を適用することが多いようです。またライセンスを適用しない場合でも、著作権表示はすることが望ましいでしょう。

「New Relic実践入門」感想、あるいはなぜ監視SaaS使うんだっけという話

New Relic アニキこと清水さんから共著書「New Relic実践入門」をいただきました。ありがとうございます。清水さんにはかつてRDBMSの性能調査をいかに効率的かつ実践的にするかご教示いただいた恩があるのですが、今もその道を追求し活躍されていると知れて嬉しく思います。

破壊的イノベーションを現場の「あたりまえ」にする本書

さて本書は「Part 1. New Relicを知る」「Part 2. New Relicを始める」「Part 3. New Relicを活用する」の3部で構成されていますが、特に「Part 1. New Relicを知る」が割り切った構成になっています。「監視とは何か?」「既存手法にはどのような限界があったか?」「近年の技術革新による新たな課題は?」といった背景をすべてすっとばし、いきなり「オブザーバビリティとは何か?」の説明から入っているのです。まるでTypeScript入門書でJavaScriptの説明を省略するような思い切りの良さです。

結果的にはこの思い切りが、幅広い読者にオブザーバビリティという概念を先入観なく伝えるための仕組みとして作用したように感じました。オブザーバビリティが従来の概念に積み上げる持続的イノベーションではなくDevOpsのような破壊的イノベーションである*1ことを踏まえると、複雑な現状を取っ払ってあるべき姿をまず描くこのアプローチは合理的です。

またNew Relicの利用者は開発者からマネージャまで多様な役割を想定しているようなので、運用技術的土地勘があまり無い読者にも読みやすいというのは狙ったところなのかなと思います。若手からシニアまでまぜた読書会とかもやりやすそうです。これはマネジメントやテックリードとしては「チームに共通理解と合意をもたらす手段」として活用できるというということで、けっこう重要だと思います。

なおPart 2. 以降で既存手法の課題についても都度整理されますし、Part 3. でもケーススタディがこれでもかと出てきます。ので運用経験者も改善手法を学ぶ技術書として興味を持って読めると思いますし、若手とのコミュニケーション手段にもできるかもしれません。

実際にわかりやすく実践入門できるのかという話

入門書を名乗るからにはちゃんとNew Relicに入門できるのかというのは気になるところです。筆者の場合は本書を読んで1日ほどで、手元のspring-boot webfluxアプリにAPM, Infrastructure, Synthetics, Browserを導入してダッシュボードでパフォーマンスを確認するところまで持っていけました。スクリーンショットや表が多くわかりやすく構成されているのと製品のUIが統一されているのとで、さほど迷わなかったと感じます。

f:id:eller:20211019205034p:plain
最終的に得られた解析結果

残念ながらJava agentの最新リリースである7.3.0はJava 17に対応しておらず、ランタイムをJava 16にダウングレードする必要がありました。これは次の7.4.0リリースで対応されるようです。

github.com

なぜ私達ソフトウェアエンジニアはSaaSを監視に使うのか

O'Reillyの「入門 監視」§2.3では、監視ツールはまず「作るのではなく買う」のが大切だと述べています。そのほうが安く良いものを得て、プロダクトにフォーカスできるからです。

本書も§4.1.2において、「運用のための運用」問題を解決する手段としてNew Relicが有効であると主張しています。そもそも監視ツールはIaaSやPaaS、CDNなどのビルディングブロックが不調に陥っても正常に稼働することが求められるため、可用性や対障害性能といった要求が非常に高いのが特徴です。最悪、開発したいプロダクト以上に運用に力を入れるなんてことにもなりかねません。ので監視ツールを「作るのではなく買う」のは多くの場合、合理的な選択になるでしょう。

これに加えて本書§2.1.4では以下に引用するようにノウハウ、すなわち試行錯誤や積み重ねの結果をすべてのエンジニアに提供することを目指していると述べています(強調は筆者による)。オブザーバビリティの重要性を理解して多くの事例を見て支えてきたであろうSaaSベンダーのノウハウを使える、巨人の肩に乗れるというのも、監視にSaaSを使う大きな理由になるでしょう:

次に重要なステップが、収集したテレメトリーデータを意味のある情報として分析、可視化することです。つまり、ありとあらゆるデータを収集できていたとしても、その情報を活用できるかどうかがオブザーバビリティの真価を発揮できるかどうかの分かれ目となります。 従来、この作業は熟練したエンジニアのスキルと経験が必要とされるものでした。New Relic Oneではそのスキルと経験に代わるノウハウを、すべてのエンジニアに提供するということを目指しています

本書の魅力として最後に忘れてはいけないのは、New Relic日本法人に強力な技術メンバーが揃っていることの証明になっている点です。この本は日本法人による書き下ろしで、翻訳本ではないそうです。そして執筆陣10名のうち3名を個人的に存じ上げているのですが、いずれも魅力ある優れたエンジニアです。彼らのような専門家が日本の商習慣や組織を理解して顧客を支えてくれるサービスが日本にある、というのが本書が一番言いたいことなのかなと思いました。職場楽しそう。

オブザーバビリティの入門としておすすめの一冊

ということで単にオブザーバビリティを学ぶ入門書としても、New Relicというサービスを活用し実践する参考書としても、現場にある課題に立ち向かうヒントを得るための事例集としても活用できる興味深い一冊だと思います。運用の現場に関わっている方はもちろんそうでない方も「今技術をフル活用すると、どこまでサービスの実態から洞察を得られるのか?」を考えるきっかけを得ることができるはずです。New Relicを使うにしても使わないにしても、読んでみて損はないと思います。

*1:これは本書の主張ではなく筆者の意見

個人サービスやOSS開発の保守運用から何を学んだか

というようなことを私はよく主に採用の文脈で口走るのですが、ちゃんと内容をまとめておこうと思ったのでメモ。特に保守運用を経験しているというのが強いと思っているので、そこに注力して書いてみます。

障害対応の経験が積める

10年ほど前にTwistoire (ついすとわーる)というサービスを運営した際に、利用想定の甘さから半日程度のサービス停止を招いたことがありました。

blog.kengo-toda.jp

個人が無償で提供していたサービスとはいえ、使ってくれているユーザに対してそれなりの責任を感じた記憶があります。またひとりで使っていたころには発生しなかった障害なので、単純に課題の分析と解決が面白そうに映るのも事実です。こうした体験から一次対応の必要性や根本解決ないしポストモーテムのあり方について実体験を持って考えられるようになります。

これ、言葉で「実体験を持って考えられる」と書くと軽いんですが、本人としては結構深刻に落ち込んでいて当時のツイート↓を見てもかなり悔しかったのだと思われます。

業務でメンテしていたシステムでも近い経験はできたので、ホビープログラマ固有の特徴かというとそんなことはないと思います。 ただ最近読んだシステム障害対応の教科書でも指摘されていましたが、障害対応は暗黙知と習熟とが必要になりがちです。そのため、むしろすべて自分でコントロールできる=SECIモデルのプロセスを自分の中で完結できる趣味開発というのは、学習効率の面からも悪くないと思います。

「運用しやすさ」という見えない品質に気づける

「いいログを書くためには何を勉強すればいいですか?」という質問をシニアなプログラマに聞くと、だいたいは「運用経験を積む」という回答が返ってきます(n=10くらい)。逆に言うと、運用を経験していないと悪いログを書きがちということです。思いつく「悪いログ」の例はこんな感じです:

  • 単純に量が多い。ログローテーションや保存、実行時性能に悪影響を及ぼす。
  • ひとつの情報が複数行に渡って表示する、パースしにくい書式を使うなど、機械による利用を想定していない。grepやログ解析サービスで追いにくい。
  • 何が起こったかだけ表示し、何が問題で何をすべきかを教えてくれない。次のアクションに必要な情報が入っていない。
  • 情報が足りず、ソースコードと照らし合わせることで初めて意味が理解できる。
  • 出力してはいけない情報が出力されている。

こういう問題は世に出ているガイドラインなどを参照すれば回避可能ですし、アーキテクトやテックリードがちゃんと統制しろという話もあるんですが、やはりプログラマ個々人が運用を意識してコードを書けた方が良いです。経験は最悪を回避するだけでなく、よりよいログを見出すのにも役立ってくれます。思いつく「良いログ」の例はこんな感じです:

  • 発生しやすい問題や運用時の関心事を考慮したもの
    • TRACEログにバッチ処理の進捗度を出力するとか(処理が進んでいないのか遅いだけなのかの切り分け、完了時間の見積の役に立てる)
    • 処理失敗の原因になりやすい「外部から受け取ったパラメータ」を残してくれるとか
    • ガイドライン化しにくい気がしている
  • 読み手が取るべきアクションがわかるもの
    • 「予期せぬのエラーが発生しました」の真逆
    • エラーコード、参照すべきURL、検索を助けるキーワードなど
    • ガイドラインによってエラーレベル(FATAL, ERROR, WARNINGなど)の使い分け方針を定めておくだけでもだいぶ違うが、最終的には想定力がモノを言う印象

このへんは、コーナーケース想定やテストシナリオ設計に通じるところがありますね。サービス運用やアプリリリースの経験があれば、こうした想定の幅が広がり、様々な面からソフトウェア品質の改善に役立てることができます。

品質を落とさないためのリグレッションテストや統合テストを大切にできるようになる

「良いテストを書けるようになるには何を勉強をすればいいですか?」という質問をシニアなプログラマに聞くと、だいたいは「ソフトウェアプロジェクトを継続して運用する」という回答が返ってきます。「テストを書くクセをつけるには?」という質問も同様です。

ここでソフトウェアプロジェクトの運用というのは、コードを書いて成果物を届けるという動きを継続して行うことを指しています。

個人プロダクトを始めた理由は「やりたいことがあるから」のはずです。それはお手玉をしながら綱渡りで火の輪くぐりをするような「あっちこっちを意識しながら壊れないように祈りつつコードを書く」体験とは大きく異なります。しかしながら、テスト設計も自動テストも無いプロジェクトでは容易にこうした体験が醸成されてしまいます。機能ひとつ手を加えるごとに他の機能や非機能要件に対する影響を確認しなければならない状況が生まれ、インクリメンタルに成果を積み上げ「やりたいこと」に近づくことすら難しくなります。

ので品質を落とさないための、というか「新しいことをやっているときに他のことを心配しなくて済むための」リグレッションテストや統合テストを大切にできるようになります。私の場合、同じ理由でシステム監視や運用の自動化、開発環境構築の自動化も関心領域になりました。

大富豪プログラミングに気づける

クラウドが生まれAPIやボタンひとつでデプロイが行えるありがたい時代になりました。私が初めて運用したサービスは有償レンタルサーバー上で動いていましたが、前出のTwistoireはGAE/Jで動いていましたし、最近はHerokuやさくらインターネットのHacobuneのような無償あるいは安価に使えるものも多くなっています。

しかし完全に無料でサービスを続けられるかというとそんなことはなく、ある程度はコストをかけていくことになります。そしてある日、想定していたよりもコストが高くなるという事態が生じます。Twistoireの場合はGAE/Jの料金プラン変更がその契機でしたが、アクセス集中や不具合によって気づくこともあるでしょう:

blog.kengo-toda.jp

趣味開発プログラマはこうした機会をコードが計算機資源を効率よく扱えていないというシグナルとして受け止め、プロジェクトとスキルの改善に繋げることができます。「性能足りなかったらサーバースペック上げればいい」ときもあるかもしれませんが、小型の趣味開発システムだとリスクを取った変更がしやすいということもありコスト効率を追求しやすいはずです。リスクや資源を自分でコントロールできるので、勉強会資料や個人Webサービスシステム構成事典↓のような情報を試しやすいというのもあります:

techbookfest.org

以上、まとめるとホビープログラマは勝手に試行錯誤していろんなことの重要性を理解しているかもしれません。落ち込んでいるときも計画していない出費ができてしまったときもあるでしょうから、元気なさそうだったら話を聞いてあげたら良いんじゃないでしょうか。

SonarQube解析をGitHub Actionsのpull_request_targetイベントで回す

SQ解析が現時点ではあまりpull_request_targetイベントをサポートしておらず、ちょいちょい手間が必要だったのでまとめます。 完全なYAMLのサンプルは↓にあります。

github.com

checkout する場合はrefを指定する

pull_request_target イベントでcheckoutを実行すると標準ではデフォルトブランチをチェックアウトしてしまいます。 よって fetch-depth: 0 に加えて ref の指定も必要です。以下のようにHEADをチェックアウトするか:

      - uses: actions/checkout@v2
        with:
          fetch-depth: 0
          ref: ${{ github.event.pull_request.head.ref || github.ref }}

以下のようにマージコミットをチェックアウトすることで解決できます*1

      - name: Decide the ref to check out
        uses: haya14busa/action-cond@v1
        id: condval
        with:
          cond: ${{ github.event_name == 'pull_request_target' }}
          if_true: refs/pull/${{ github.event.pull_request.number }}/merge
          if_false: ${{ github.ref }}
      - uses: actions/checkout@v2
        with:
          fetch-depth: 0
          ref: ${{ steps.condval.outputs.value }}

2021年11月17日更新:前者の方法だとforkからのPRでは動作しないので、後者がおすすめです。

PR解析用のオプションを加える

おそらくScanner側の問題だと思うのですが、Developer Editionの機能のためかコードは見つけられていません。現時点では sonar.pullrequest.keysonar.pullrequest.branch の双方を手動で設定する必要があります*2

        run: |
          mvn org.jacoco:jacoco-maven-plugin:prepare-agent verify sonar:sonar -B -e -V \
            ${PR_NUMBER:+ -Dsonar.pullrequest.key=$PR_NUMBER -Dsonar.pullrequest.branch=${{ github.event.pull_request.head.ref }} }
        env:
          PR_NUMBER: ${{ github.event.pull_request.number }}

2021年8月30日更新:

上記実装では脆弱性が残ることをazu さんにご指摘いただきました。ありがとうございました! ブランチ名はPR作成者が決定可能なので、一度環境変数で受けてから使用するべきとのことです。

        run: |
          mvn org.jacoco:jacoco-maven-plugin:prepare-agent verify sonar:sonar -B -e -V \
            ${PR_NUMBER:+ -Dsonar.pullrequest.key=$PR_NUMBER -Dsonar.pullrequest.branch=${PR_BRANCH} }
        env:
          PR_NUMBER: ${{ github.event.pull_request.number }}
          PR_BRANCH: ${{ github.event.pull_request.head.ref }}

Sonar Scannerの実行にはJava 11が必要

pull_request_targetと直接関係はありませんが、最近更新が入ったようなので念のため。

Sonar Scannerは実行にJava 11以上が必要なので、Java 8のコードを書いている場合でもJDK 11以上でビルドする必要があります。MavenもGradle*3--release オプションをサポートしているので、それを使うと良いでしょう。Java 8に無いAPIを見つけてコンパイルエラーにしてくれるので、 --target よりも安心です。

勝手を知らないプロジェクトにPull Requestを送るときに気にしていること

初心者向けのPull Request(PR)作成方法はopensource.guideをはじめとして数多く見るのですが、もうちょっと突っ込んだというか中級的な内容の記事を読みたかったので自分で書きます。題材として主に直近で書いた大きめの機能追加用PRを使っています:

github.com

修正や新機能を入れる利点を明確に伝える

何かを提案する場合、その背景には必ず動機となる利点があるはずです。これはとても単純に伝えられることもあれば、テストやグラフを作成しないと伝わりにくいものもあります。

今回の変更では、GitHub Actions workflowの定義ファイル簡素化とパフォーマンス改善が利点でした。定義ファイルが簡素化されることはドキュメントで簡単に伝えられますが、パフォーマンスは測定しなければわかりません。よってパフォーマンス検証用のリポジトリを作成し測定を行うことで、ビルド時間が約28%高速化されることを示しました。

github.com

このリポジトリにあるActionsを実行すると、グラフを描くために必要なCSVが出力されます。それをGoogle Sheetsに突っ込んで以下のようなグラフを作成し、PRページに添付しています。結果として、本当に高速化に繋がるのか?といった疑問や質問は来ず、純粋に実装手法についての議論から入ることができました。

f:id:eller:20210826152424p:plain
パフォーマンスがどの程度具合を説明するためのグラフ

こうして根拠となる事実を自動的に出せるようにしておくと、レビューを受けて実装が変わったときに再確認を行えるという利点もあります。今回の例で言うとキャッシュの解決とJDKのインストールとを並行することでの高速化を意図していたのですが、セキュリティ上の兼ね合いから順次実行するようコードを変更せざるを得ませんでした。このような大きな変更があっても、既に自動化されたパフォーマンス比較手段があったため、パフォーマンス改善が維持できていることを示せました。

考慮すべきことも伝える

変更には利点だけではなく、互換性や運用など考慮しなければならないこともあります。これらをどこまで認識していて、どのような検証を行ったのかを事前に共有することで、多角的な議論の下地とすることができます。

今回の変更では upload-chunk-size が設定できなくなりユーザの自由度が失われること、IvyやGrapeといったより多くのパッケージマネージャをサポートすべきかもしれないことを俎上に載せ、その上でそれらが現時点で問題にならない理由を述べています。

新機能をメンテナンスし続けることのコストを最小化する

新機能追加のためにPRを送る場合、その機能のメンテナンスを行うのが自分ではなく相手だという点を意識する必要があります。言い換えれば、メンテナンスの工数が高いと判断された場合、PRをマージしてもらえない可能性があるということです。

基本的には単体テストと統合テストの双方を実装し提供することで対応します。単体テストがあることで実装自体のテスト可能性を担保し、統合テストがあることでリグレッションに気づける状態を作ります。またユーザに対する説明が必要な機能なら、READMEのような書類もあわせて準備します。

また自己流のやり方を持ち込むのではなく、既存のコードベースに溶け込むコードを書くことも重要です。今回は既にある定数クラスを再利用したり、統合テストのための仕組みに乗ったりという工夫をしました。特に統合テストのやり方はリポジトリによって様々なので、既存のビルド設定やコードに目を通す必要があります。

早めに返信するが、相手には求めない

質問や指摘があった場合、24時間以内には必ず何らかのリアクションを返すようにします。どうせタイムゾーンの問題があるので”即レス”は難しいのですが、できるだけ早めに返すことで議論の沈静化を防ぎます。

逆に、向こうから連絡がなくても気長に待ったほうが良いことも多いです。今回は企業の中の人が業務としてレビューしてくれましたが、それでも2週間ほど返信がなかった期間がありました。自分が相手の立場でもそういう事はあるだろうと気長に待つのが得策です。

変更の理由をオーバー気味に説明する

PRを提案する際、依存先の更新やリファクタリングのような、一見不要に見える変更を入れることがあります。例えばこちらのPRでは、ネットワークエラー発生時でもHTTPリクエストのリトライを行うために typed-rest-client のバージョンを上げています。何も説明しないと、依存を上げるのは他のPRでやればいいのでは?という疑問が湧くかもしれません。

github.com

こうした変更を入れる際は、コミットコメントかPR内コメントでその意図を伝えるようにしています。やはりコードでWHYを伝えるのは難しいので、少しオーバーかなと思うくらいの勢いで伝えたほうが良さそうです。

その他、細かいこと

  • README.md はもちろん、 CONTRIBUTING.mdCODE_OF_CONDUCT.md といったドキュメントに目を通しましょう。
  • Pull Requestテンプレートがある場合は利用しましょう。
  • わからないことはわからないと言い、素直に尋ねる方が良いです。相手もこちらを助けやすくなります。
  • 新しいライブラリの導入など相手に判断を求めるケースでも、自分の考えを述べた上で素直に尋ねるようにしましょう。

以上です。どなたかの参考になれば幸いです。 Happy hacking!

GitPodでJavaプロジェクトを開発する

GitHub Codespacesがなかなか個人向けに来ないので、changelog.comで宣伝していたGitPodを試しています。 どうも公式のJava向けの説明が古いようで、既にDeprecatedになっているtheiaを前提としているため、調べたことをメモしておきます。

最新のJavaを使う

普通に gitpod/workspace-full イメージ内でJavaを起動すると、Zuluの11が使われていることがわかります:

$ java --version
openjdk 11.0.12 2021-07-20 LTS
OpenJDK Runtime Environment Zulu11.50+19-CA (build 11.0.12+7-LTS)
OpenJDK 64-Bit Server VM Zulu11.50+19-CA (build 11.0.12+7-LTS, mixed mode)

SDKMANやhomebrewが入っているので好きなバージョンを入れてもいいですが、ワークスペースを立ち上げる度に実行するのは面倒なので、 azul/zulu-openjdk のようなイメージを使ってしまうのが楽でいいと思います。

# .gitpod.yml
image: azul/zulu-openjdk:16

Mavenの依存をダウンロードしておく

Mavenの場合、dependency:go-offlineプラグインや依存をすべてダウンロードできます。 これをイメージ作成時に実行しておくのが良さそうです。

# .gitpod.yml
image: azul/zulu-openjdk:16

tasks:
  - init: ./mvnw -B dependency:go-offline

Gradleの依存をダウンロードしておく

Gradleには標準的な手法がないので、単にビルドを回しておきます。

# .gitpod.yml
image: azul/zulu-openjdk:16

tasks:
  - init: ./gradlew build

Extensionを導入する

Java向けExtensionを3つ入れて様子を見ています。

# .gitpod.yml
vscode:
  extensions:
    - redhat.java
    - vscjava.vscode-java-dependency
    - vscjava.vscode-java-debug

ポートを開けておく

Spring Framework標準の8080ポートを開けておく場合は ports の設定 で足ります。 が、URLの取得にgpコマンドが必要なので azul/zulu-openjdk ではなく gitpod/workspace-full をベースとしたイメージを用意する必要があります。URLの決定ロジックがいまのところ非常に単純なのでなくてもなんとかなりそうではありますが、一応。

# .gitpod.yml
image:
  file: .gitpod.Dockerfile
ports:
  - port: 8080
# .gitpod.Dockerfile
FROM gitpod/workspace-full
RUN bash -c ". /home/gitpod/.sdkman/bin/sdkman-init.sh && sdk install java 16.0.2-zulu"

バッジを付ける

バッジはDiscourseに落ちています。 README.md とかに貼っておくと、Contributorの敷居が下がって良いんじゃないでしょうか。

community.gitpod.io