Upgrade to Pro — share decks privately, control downloads, hide ads and more …

Scala をインタラクティブにデバッグする方法あれこれ

Sponsored · Your Podcast. Everywhere. Effortlessly. Share. Educate. Inspire. Entertain. You do you. We'll handle the rest.
Avatar for 110416 110416
October 13, 2023
1.7k

Scala をインタラクティブにデバッグする方法あれこれ

Tips for interactively debugging Scala libraries and applications.

- sbt console
- test
- publishLocal & import from local repository
- import from private maven repository

Avatar for 110416

110416

October 13, 2023
Tweet

More Decks by 110416

Transcript

  1. WHOAMI GitHub: i10416 X(Twitter): @by110416 Scala & Rust developer 最近の

    Scala OSS コントリビューション https://github.com/neotypes/neotypes/releases/tag/v1.0.0-M3
  2. 前提:次のようなパッケージをデバッグする想定で説明する. // src/main/scala/Lib.scala package com.example object Lib { def doSomething():

    Int = 42 } // build.sbt ThisBuild / organization := "com.example" val lib = project.in(file(".")) .settings( scalaVersion := "3.3.1", version := "0.1.0-SNAPSHOT", libraryDependencies ++= Seq( "org.scalameta" %% "munit" % "1.0.0-M7" % Test ) )
  3. Table of Contents sbt console test publishLocal & import from

    local repository import from private maven repository
  4. 予習: sbt shell と sbt console sbt shell: 通常のシェル(zsh、fish や bash)で

    sbt と入力したときに開始される sbt の インタラクティブなインターフェース. sbt console: sbt shell から呼び出せる Scala REPL 環境 以下の例ではコードブロックの行頭が sbt> と書かれている場合 sbt shell 内でのコマンド実 行を、scala> と書かれている場合は Scala REPL 内でのコマンド実行を意味する.
  5. sbt console でデバッグ 複数行の入力 scala>:paste // Entering paste mode (ctrl-D

    to finish) object DeepThought { val theAnswer = 42 } // ctrl-D
  6. sbt console でデバッグ: 初期化コマンドの設定 console/initialCommands を設定すれば sbt console の初期化処理を追加できる. 毎回特定のモジュールやライブラリやインポートする場合は設定しておくと楽.

    // build.sbt val lib = project.in(file(".")) .settings( scalaVersion := "3.3.1", version := "0.1.0-SNAPSHOT", console / initialCommands := "import java.nio.file._", libraryDependencies ++= Seq( "org.scalameta" %% "munit" % "1.0.0-M7" % Test ) )
  7. sbt console でデバッグ: multi modules 特定のサブプロジェクトのデバッグをしたい場合は sbt shell 内で projects

    コマンドを実行し サブプロジェクトの名前を確認し projectname/console(下の例では sbt contrib/console ) とすればいい. ├── build.sbt ├── contrib/src/main/scala/... └── core/src/main/scala/... // build.sbt lazy val core = project.in(file("core")) ... lazy val contrib = project.in(file("contrib")) ...
  8. sbt console でデバッグ: Pros & Cons Pros 楽. セットアップや(ローカル)リリースが必要ない. 期待する動作がそこまで定まっていなくてもいい.

    Cons パッケージやアプリケーション全体をデバッグするのには向かない. JS や Native ではデバッグできない. コンパイルが通っている必要がある(consoleQuick を使えば回避できる)
  9. test(& sbt testOnly) でデバッグ // src/test/scala/Test.scala package com.example class Test

    extends munit.FunSuite { test("Lib.doSomething returns 42") { assertEquals(Lib.doSomething, 42) } } test sbt>test testOnly sbt>testOnly com.example.Test
  10. test でデバッグ: Pros & Cons Pros JS や Native でも動作確認できる.

    console より IDE のサポートを活用できる. Cons コンパイルを通さないといけない. テストを書かないといけない. ユニットテストが書きにくいコードベースだと辛い. ある程度期待する動作が定まっている必要がある.
  11. import from Scala CLI Scala CLI では using dep でパッケージを読み込める.

    using dep はデフォルトで maven のレポジトリとローカルのレポジトリからパッケージを探す. //> using dep "com.example::lib:0.1.0-SNAPSHOT" import com.example.Lib @main def run = println(Lib.doSomething()) //=> 42
  12. import from ammonite REPL ammonite REPL では $ivy. のマジックインポートを使ってパッケージを読み込める. @

    import $ivy.`com.example::lib:0.1.0-SNAPSHOT` @ import com.example.Lib @ Lib.doSomething() res0: Int = 42 @
  13. sbt publishLocal でデバッグ: Pros & Cons Pros ライブラリ全体の動作確認をできる. Cons 配布+新しいプロジェクトを作成しないといけないのでやや手間.

    バージョンでキャッシュされるのでバージョンを上げるかコミットハッシュなどを付与 する必要がある.
  14. Private な Maven レポジトリに配布されたパッケージをデバッグする 代表的なのは社内レポジトリから private パッケージを取得するユースケース. ここでは GCP の

    asia-northeast1 の example-project プロジェクトに example という Artifact Registry がある想定で説明する. GCP を例にするが基本的なアイディアは同じ(...なはず)
  15. sbt project から GCP Artifact Registry にアクセスする sbt gcs resolver

    を利用する. この sbt plugin は GCS や Artifact Registry へのパッケージの配布・取得機能を提供する. // project/plugins.sbt addSbtPlugin("org.latestbit" % "sbt-gcs-plugin" % "1.8.0") デフォルトの認証情報を設定しておけば plugin がよしなに読み取ってくれる. gcloud auth application-default login
  16. sbt project から GCP Artifact Registry にアクセスする // build.sbt resolvers

    += "My Maven Artifact Registry" at "artifactregistry://asia-northeast1-maven.pkg.dev/example-project/example" libraryDependencies ++= Seq( "com.example::lib:0.1.0-SNAPSHOT" )
  17. Scala CLI から GCP Artifact Registry にアクセスする 認証情報を設定する. repository のホストが

    asia-northeast1-maven.pkg.dev の時に指定した 認証情報が使われる. scala-cli --power config \ repositories.credentials "asia-northeast1-maven.pkg.dev" \ value:_json_key_base64 value:eyXXInR5cXXiOiXXc2..... value::eyXXInR5cXXiOiXXc2..... の部分はサービスアカウント has-access-to-artifact- [email protected] のJSON鍵ファイルを base64 エンコ ードしたもの.
  18. Scala CLI から GCP Artifact Registry にアクセスする using repository で

    maven やローカル以外のレポジトリを追加できる. //> using repository "https://asia-northeast1-maven.pkg.dev/examle-project/example" //> using dep "com.example::lib:0.1.0-SNAPSHOT" import com.example._ @main def run = println(Lib.doSomething())
  19. Scala CLI から認証付きレポジトリにアクセスする scala-cli --power config \ repositories.credentials <HOST> \

    <USERNAME> <PASSWORD> GitHub Packages などの認証付きレポジトリも同様に利用できる. scala-cli --power config \ repositories.credentials "maven.pkg.github.com" \ value:PrivateToken env:GITHUB_TOKEN /> using repository "https://maven.pkg.github.com/<org>/_"
  20. Misc remove/unset scala-cli --power config --remove repositories.credentials coursier fetch cs

    fetch -r https://asia-northeast1-maven.pkg.dev/example-project/example \ --credentials "asia-northeast1-maven.pkg.dev _json_key_base64:eyXXInR5cXXiOiXXc2....." sbt help <cmd> sbt> help help