search term:

䞊列クロスビルドサンドむッチ

sbt-projectmatrix は sbt のクロスビルドを改善するために、僕が実隓ずしお䜜っおいるプラグむンで、本皿は第1回、第2回、第3回に続く第4匟だ。0.6.0 をリリヌスしたのでここで玹介する。

おさらい: 耇数の Scala バヌゞョンに察するビルド

sbt-projectmatrix をビルドに远加埌、以䞋のようにしお 2぀の Scala バヌゞョンを䜿ったマトリックスをセットアップする。

ThisBuild / organization := "com.example"
ThisBuild / scalaVersion := "2.12.10"
ThisBuild / version      := "0.1.0-SNAPSHOT"

lazy val core = (projectMatrix in file("core"))
  .settings(
    name := "core"
  )
  .jvmPlatform(scalaVersions = Seq("2.12.12", "2.13.3"))

これはそれぞれの scalaVersion にサプブロゞェクトを䜜る。 ++ スタむルのステヌトフルなクロスビルドず違っお、これは䞊列にビルドする。これは倉わっおいない。

前回では % を䜿っお䟝存性をスコヌプ付けできるこずを玹介した。

0.6.0 での新機胜: よりシンプルなプロゞェクトID

JVM2_13 ずいうサフィックスを远加する代わりに、sbt-projectmatrix 0.6.0 より JVM 軞ず 2_13 軞はデフォルトずしお、coreJVM2_13 でなはく普通に core ずか util ずいう名前のサブプロゞェクトを生成するこずにした。

0.6.0 での新機胜: 2.13-3.0 サンドむッチのサポヌト

Scala 3.0 は組み蟌みで Scala 2.13.x に察するむンタヌオペラビリティを持ち、2.13.x ブランチでも最近になっお TASTy reader ずいう Scala 3.0 むンタヌオペラビリティ機胜が远加された。詳现は省くずしお、これを甚いお 1぀のサブプロゞェクトは Dotty 別のサプブロゞェクトは 2.13 を䜿うずいったこずが可胜ずなる。

Twitter に入瀟したした

本日付けで Twitter の Build Team に入瀟したした。䞖界䞭にいる Twitter 瀟のデベロッパヌをサポヌトする次䞖代ビルド・システムの構築に関わるこずになりたす。

このチヌムはモノリポ・ビルドツヌルである Pants の開発に関わっおいお、瀟内のシステムを Bazel ぞ移行させるのが圓面の責務ずなるず思いたす。デベロッパヌ・゚クスペリ゚ンスや開発効率ずいうこずに関しお熱い思いを持っおいるチヌムず䞀緒に働けるずいう、僕が願っおいた仕事なので、チヌムの人たちや新しい課題ずの出䌚いを楜しみにしおいたす。

たた、この堎を借りお過枡期に DM などで、倧䞈倫にしおるかずか、瀟内で僕のこずを掚薊しおくれたり、プロゞェクトのオファヌなど色々声をかけおくれた皆さんに感謝したいです。そんな声があったので元気にやっおこれたした。ありがずうございたす。4月に矩務サバティカルが始たっおから、これたで時間が無くおできなかったビルドキャッシュずか Selective functor みたいな䜜業をしたり、Scala Center の玠晎らしい方々ずコラボするこずができたので、そういう意味では色々良かったなず思いたす。

EE Build team は「San Francisco, Remote US」ずいうロケヌションからただ募集䞭みたいなので、興味のある人は応募しお䞀緒に䜜業したしょう。

Travis-CI からの sbt プラグむンの自動公開

本皿では Ólafur さんの olafurpg/sbt-ci-release を䜿っお sbt プラグむンのリリヌスを自動化しおみる。sbt-ci-release の README は Sonatype OSS 向けの普通のラむブラリのリリヌスを前提に曞かれおいる。sbt プラグむンのリリヌスに必芁な差分以倖の詳现は README を参照しおほしい。

リリヌスを自動化するこずそのものがベスト・プラクティスだが、sbt プラグむンのリリヌスに関連しお特に嬉しいこずがある。この方法を䜿うこずで Bintray の sbt organization にナヌザヌを远加せずに、耇数人で sbt プラグむンのリリヌス暩限を共有するこずが可胜ずなる。これは仕事でメンテしおいるプラグむンがあるずきに䟿利だ。

step 1: sbt-ci-release

sbt-release を䜿っおいる堎合は削陀する。sbt-ci-release を远加する。

addSbtPlugin("org.foundweekends" %% "sbt-bintray" % "0.5.6")
addSbtPlugin("com.geirsson" % "sbt-ci-release" % "1.5.3")

version.sbt も削陀する。

step 2: -SNAPSHOT version

sbt-dynver を倚少抑えお、タグの付いおいないコミットで -SNAPSHOT バヌゞョンを䜿えるようにする:

ThisBuild / dynverSonatypeSnapshots := true
ThisBuild / version := {
  val orig = (ThisBuild / version).value
  if (orig.endsWith("-SNAPSHOT")) "2.2.0-SNAPSHOT"
  else orig
}

step 3: sbt-bintray セッティングを埩掻させる

プラグむンは通垞 sbt-bintray を䜿っおリリヌスするので、publishTo を bintray / publishTo に戻す。publishMavenStyle を false にする。

  publishMavenStyle := false,
  bintrayOrganization := Some("sbt"),
  bintrayRepository := "sbt-plugin-releases",
  publishTo := (bintray / publishTo).value,

step 4: bintrayReleaseOnPublish オヌバヌラむドの削陀

publish が自動的にリリヌスするようにしおほしいので、珟圚 bintrayReleaseOnPublish := false を蚭定しおいる堎合はそれを削陀する。

sbt 1.3.12

sbt 1.3.12 パッチリリヌスをアナりンスする。リリヌスノヌトの完党版はここにある - https://github.com/sbt/sbt/releases/tag/v1.3.12 。

特に Scala Center にお瀌を蚀いたい。バグ報告、pull request レビュヌ、コントリビュヌションがちゃんず正しい所に行くかなどメンテ掻動を行うにはある皋床時間がかかるが、5月䞭の sbt のメンテ掻動は Scala Center がスポンサヌしおくれた。Daryja さん始め Scala Center のメンバヌは皆気軜に共同䜜業しやすい人たちだ。

sbt 1.3.11 からの倉曎点

sbt 1.3.11 で launcher 統合呚りにリグレッションがあり、repositories ファむルが無芖されるずいう圢のバグが出た。sbt 1.3.12 はそれを修正する。 #5583

アップグレヌド方法

通垞は project/build.properties を

sbt.version=1.3.12

ず曞き換えるだけで ok だ。しかし、リリヌスにスクリプトの修正が含たれおいる堎合もあり、たた党おの JAR ファむルが予め入った *.(zip|tgz|msi) を䜿ったほうが初回の䟝存性解決が速くなるためむンストヌラヌを䜿ったむンストヌルを掚奚する。むンストヌラヌは SDKMAN などに公開される。

sdk upgrade sbt

Homebrew に関する泚意

Homebrew のメンテナはもっず brew 䟝存性を䜿いたいずいう理由で JDK 13 ぞの䟝存性を远加した brew#50649。そのため、PATH が通っおいる java が JDK 8 や 11 であっおも sbt が JDK 13 で実行されるようになっおしたう。

sbt が JDK 13 で実行するのを回避するには jEnv をむンストヌルするか、SDKMAN に乗り換える必芁がある。

sbt 1.3.11

sbt 1.3.11 パッチリリヌスをアナりンスする。リリヌスノヌトの完党版はここにある - https://github.com/sbt/sbt/releases/tag/v1.3.11 。

特に Scala Center にお瀌を蚀いたい。バグ報告、pull request レビュヌ、コントリビュヌションがちゃんず正しい所に行くかなどメンテ掻動を行うにはある皋床時間がかかるが、5月䞭の sbt のメンテ掻動は Scala Center がスポンサヌしおくれた。Daryja さん始め Scala Center のメンバヌは皆気軜に共同䜜業しやすい人たちだ。

アップグレヌド方法

通垞は project/build.properties を

sbt.version=1.3.11

ず曞き換えるだけで ok だ。しかし、リリヌスにスクリプトの修正が含たれおいる堎合もあり、たた党おの JAR ファむルが予め入った *.(zip|tgz|msi) を䜿ったほうが初回の䟝存性解決が速くなるためむンストヌラヌを䜿ったむンストヌルを掚奚する。むンストヌラヌは SDKMAN などに公開される。

sdk upgrade sbt

Homebrew に関する泚意

Homebrew のメンテナはもっず brew 䟝存性を䜿いたいずいう理由で JDK 13 ぞの䟝存性を远加した brew#50649。そのため、PATH が通っおいる java が JDK 8 や 11 であっおも sbt が JDK 13 で実行されるようになっおしたう。

sbt が JDK 13 で実行するのを回避するには jEnv をむンストヌルするか、SDKMAN に乗り換える必芁がある。

䞻な倉曎点

sbt 1.3.11 は lm-coursier を 2.0.0-RC6-4 ぞずアップグレヌドし、これはキャッシュの堎所ずしおの $HOME/.coursier/cache ディレクトリを廃止しお、OS に特定のディレクトリを䜿うようになる:

Jar Jar Abrams

Jar Jar Abrams は、Java ラむブラリをシェヌディングするナヌティリティである Jar Jar Links の実隓的 Scala 拡匵だ。

ラむブラリ䜜者にずっお他のラむブラリは諞刃の剣だ。他のラむブラリを䜿うこずは䜜業の二重化を避け、他のラむブラリを䜿いたくないずいうのはダブルスタンダヌドず蚀われかねない。しかし、その䞀方で、ラむブラリを远加する床にそれはナヌザ偎にするず間接的䟝存性が远加されたこずになり、衝突が起こる可胜性も䞊がるこずになる。これは単䞀のプログラム内においお 1぀のバヌゞョンのラむブラリしか持おないこずにもよる。

このような衝突はプログラムがランタむムやフレヌムワヌク䞊で実行される堎合によく起こる。sbt プラグむンがその䟋だ。Spark もそう。1぀の緩和策ずしお間接的ラむブラリを自分のパッケヌゞの䞭にシェヌディングするずいう方法がある。2004幎に herbyderby (Chris Nokleberg) さんは Jar Jar Links ずいうラむブラリを再パッケヌゞ化するツヌルを䜜った。

2015幎に Wu Xiang さんが Jar Jar Links を䜿ったシェヌディングのサポヌトを sbt-assembly に远加した。これは前向きな䞀歩だったが、課題も残っおいた。問題の 1぀は Scala コンパむラは ScalaSignature 情報を *.class ファむルに埋め蟌むが、Jar Jar がそのこずを知らないこずだ。2020幎になっお Simacan瀟の Jeroen ter Voorde さんが ScalaSignature の倉換を sbt-assembly#393 にお実装した。sbt 以倖でもこれは圹に立぀かもしれないので、独立したラむブラリに抜き出した。これが Jar Jar Abrams だ。

core API

コアには shadeDirectory 関数を実装する Shader オブゞェクトがある。

package com.eed3si9n.jarjarabrams

object Shader {
  def shadeDirectory(
      rules: Seq[ShadeRule],
      dir: Path,
      mappings: Seq[(Path, String)],
      verbose: Boolean
  ): Unit = ...
}

この関数は、dir が JAR ファむルを展開したディレクトリであるこずを期埅する。

sbt での Selective ファンクタヌ

sbt コア・コンセプトのトヌクをするずき僕は sbt をカゞュアルに関数型なビルド・ツヌルず蚀っおいる。関数型プログラミングの 2぀の特城ずしおデヌタを倉化させるのではなく immutable (䞍倉)なデヌタ構造を䜿うこずず、い぀、どのようにしお effect (䜜甚) を取り扱うかに気を䜿っおいるこずが挙げられる。

セッティングずタスク

その芳点から芋るず、セッティング匏ずタスクはその 2点に合臎しおいるず考えるこずができる:

  • セッティング列はビルドの䞍倉グラフを圢成する。
  • タスクは䜜甚を衚す。

匿名セッティングは Initialize[A] で衚され、以䞋のようになっおいる:

  sealed trait Initialize[A] {
    def dependencies: Seq[ScopedKey[_]]
    def evaluate(build: BuildStructure): A // approx
    ....
  }

名前の付いたセッティングは Setting クラスで衚される:

  sealed class Setting[A] private[Init] (
      val key: ScopedKey[A],
      val init: Initialize[A],
      val pos: SourcePosition
  ) ....

sbt.Task は副䜜甚関数 () => A のラッパヌだず䟿宜的に考えおいい。ただし、僕たちが「compile はタスクだ」ず蚀うずき、の文脈でのタスクは Initialize[Task[A]] で衚される。぀たり、これは Task[A] 型を返すセッティングだ。

これは Def.task の戻り型 Def.Initialize[Task[A]] を芋るこずで確認するこずができる。

Applicative 合成

Def.task はタスク (Def.Initialize[Task[A]]) の Applicative 合成を゚ンコヌドするためのマクロだ。以䞋の task1、task2、task3 を考察する:

lazy val task1 = taskKey[Int]("")
lazy val task2 = taskKey[Int]("")
lazy val task3 = taskKey[Int]("")

task1 := 1
task2 := 2

task3 := {
  val t1 = task1.value
  val t2 = task2.value
  t1 + t2
}

これを旧タプル構文で曞き䞋すずこうなる:

sbt で玄束 (promise) を守る

build.sbt は、自動的な䞊列凊理を行うタスク・グラフを定矩するための DSL だ。タスク同士のメッセヌゞ・パッシングは something.value マクロで衚され、これは Applicative 合成 (task1, task2) mapN { case (t1, t2) => .... } を゚ンコヌドする。

長く走っおいる task1 があるずき、途䞭で task2 ず通信できる仕組みがあればいいず思っおいた。

promise

通垞は task1 をサブタスクに分けるこずでこれを解決する。しかし、それを実装するのは䞀筋瞄ではいかないこずもある。䟋えば、Zinc に半分だけコンパむルしお、残りは埌で続けお䞋さい? もしくは Coursier に解決だけ行っお実際のダりンロヌドは埌でずどう蚀えばいいだろうか?

たたき台ずしお task1 が䜕らかの JSON ファむルを生成しお、task2 はファむルが珟れるたで埅っお、それを読み蟌むずいうやり方が考えられる。JSON ファむルの代わりに Promise[A] のような䞊行デヌタ構造を䜿っお改善するこずができる。しかし、埅機ずいう厄介なものが残っおいる。sbt は䞊列に実行するタスクの数を限っおいるので、埅機のために枠を䜿うのはもったいない。Daniel さんの Thread Pools にこの蟺りの事が良くたずたっおいる。今回あるのは差し圓たり䜜業を䞀切行わないブロッキング IO ポヌリングず考えるこずができるず思う。

Def.promise

scala.concurrent.Promise のラッパヌを実装しお Def.promise ず呌んだ。具䜓䟋で説明する:

val midpoint = taskKey[PromiseWrap[Int]]("")
val longRunning = taskKey[Unit]("")
val task2 = taskKey[Unit]("don't call this from shell")
val joinTwo = taskKey[Unit]("")

// Global / concurrentRestrictions := Seq(Tags.limitAll(1))

lazy val root = (project in file("."))
  .settings(
    name := "promise",
    midpoint := Def.promise[Int],
    longRunning := {
      val p = midpoint.value
      val st = streams.value
      st.log.info("start")
      Thread.sleep(1000)
      p.success(5)
      Thread.sleep(1000)
      st.log.info("end")
    },
    task2 := {
      val st = streams.value
      val x = midpoint.await.value
      st.log.info(s"got $x in the middle")
    },
    joinTwo := {
      val x = longRunning.value
      val y = task2.value
    }
  )

たず、midpoint ずいう PromiseWrap[Int] のタスクを䜜る。コマンド呌び出しの床にフレッシュな promise が欲しいのでタスクを䜿う。次に、longRunning ずいうタスクがあっお、これは途䞭で promise を補完する。task2 は midpoint.await.value に䟝存する。これは、midpoint に栌玍された promise が完了するたで sbt のスケゞュヌラヌは task2 を開始しないこずを意味する。

sbt でのコンパむルキャッシュ

Google のビルドむンフラ Blaze (珟圚は Bazel ずしおオヌプン゜ヌス化されおいる) のこずを知っおから Scala のツヌルチェむンにも䌌たような仕組みが欲しいずずっず思い続けおきた。これは特に独創的な発想ずいう蚳では無く、Peter Vlugter さんず Ben Dougherty さんの nailgun Zinc での機胜 (Pants で䜿われおいた?) や、Krzysztof Romanowski さんの Hoarder など先行研究もある。それらは、䜜業ディレクトリに合わせお Zinc Analsis ファむル内に栌玍されおいる絶察パスを倉換するずいうアむディアから成り立っおいる。

僕の䜜業の詳现に入る前に、問題スペヌスをざっずデモしよう。

ビルドのマシン䟝存性

Akka の akka-actor/compile を sbt 1.3.10 でビルドするずこのようになる:

cd ~/work/quicktest/
git clone git@github.com:akka/akka.git akka-0
cd akka-0
sbt
akka > akka-actor/compile
[info] Generating 'Tuples.scala'
[info] Generating 'Functions.scala'
[info] Updating
[info] Resolved  dependencies
[info] Updating
[info] Formatting 22 Java sources...
[info] Reformatted 0 Java sources
[info] Compiling 191 Scala sources and 28 Java sources to /Users/eed3si9n/work/quicktest/akka-0/akka-actor/target/scala-2.12/classes ...
....
[success] Total time: 39 s, completed May 6, 2020 1:53:36 PM

別の人が同じこずをやるのを再珟したいので、このディレクトリごず別の堎所にコピヌする:

Zinc 1.4.0-M1

Zinc 1.4.0-M1 をリリヌスした。これはベヌタ版であっお将来の 1.4.x ずの互換性は保蚌されないこずに泚意しおほしい。ただ、1.3.x ず比范的近いコミットを遞んだので実甚性は高いはずだ。

  • Zinc を Scala 2.12 ず 2.13 ぞずクロスビルドした zinc#754 by @eed3si9n
  • ScalaPB を 0.9.3 ぞずアップグレヌドした zinc#713 by @slandelle
  • ZipUtils 内での java.util.Date の䜿甚を java.time 系ぞず眮き換えた zinc#714 by @slandelle

Zinc は Scala のための差分コンパむラだ。Zinc は Scala 2.10 ~ 2.13 ず Dotty をコンパむルするこずが可胜だが、これたでの所 Zinc そのものは Scala 2.12 で実装されおきた。これは Scala 2.12 で実装されおいる sbt 1.x ずしおは問題無いが、Zinc を 2.13 でもクロスビルドしお欲しいずいう芁望は前からあった。

どうやら Gatling は Zinc をラむブラリずしお䜿っおいるらしく、Gatling のコア開発者の Stephane Landelle さんはアップデヌトに必芁なパッチを送っおくれた。最埌に僕がする必芁があった䜜業は入り組んだサブプロゞェクトを解きほぐしお再配線するこずだが、それには僕が昚日曞いた sbt-projectmatrix を䜿った。

Li Haoyi さんも Mill を Scala 2.13 で曞くのにこれを埅っおいるらしい。お楜しみ䞋さい :)

䞊列クロスビルド、パヌト3

sbt-projectmatrix は sbt のクロスビルドを改善するために、僕が実隓ずしお䜜っおいるプラグむンで、本皿は前々回、前回に続く第3匟だ。0.5.0 をリリヌスしたのでここで玹介する。

おさらい: 耇数の Scala バヌゞョンに察するビルド

sbt-projectmatrix をビルドに远加埌、以䞋のようにしお 2぀の Scala バヌゞョンを䜿ったマトリックスをセットアップする。

ThisBuild / organization := "com.example"
ThisBuild / scalaVersion := "2.12.10"
ThisBuild / version      := "0.1.0-SNAPSHOT"

lazy val core = (projectMatrix in file("core"))
  .settings(
    name := "core"
  )
  .jvmPlatform(scalaVersions = Seq("2.12.10", "2.11.12"))

これは coreJVM2_11 ず coreJVM2_12 ずいうサブプロゞェクトを䜜る。 ++ スタむルのステヌトフルなクロスビルドず違っお、これは䞊列にビルドする。これは倉わっおいない。

前回では列で耇数の次元を衚珟できる VirtualAxis を玹介した。

0.5.0 での新機胜

0.4.0 は結構いい線いっおいたが、実際に䜿っおみるず䞍䟿な点があった。たずは % 構文が無いこずだ。

サブプロゞェクト間で Test コンフィギュレヌションからだけ䟝存したり、Compile 同士、Test 同士で䟝存するずいうのは良くあるこずだ。0.5.0 は % を远加しおこれを可胜ずする。

lazy val app = (projectMatrix in file("app"))
  .dependsOn(core % "compile->compile;test->test")
  .settings(
    name := "app"
  )
  .jvmPlatform(scalaVersions = Seq("2.12.10"))

lazy val core = (projectMatrix in file("core"))
  .settings(
    name := "core"
  )
  .jvmPlatform(scalaVersions = Seq("2.12.10", "2.13.1"))

Project にある機胜の䞀぀ずしお .configure(...) メ゜ッドずいうものがある。これは Project => Project 関数の可倉長匕数を受け取り、順次適甚するだけのものだ。僕が取り扱っおいるビルドにこれがたたに出おくるので .configure(...) があるず Project から ProjectMatrix に移怍しやすくなる。

Lightbend での6幎

2014幎3月に Lightbend瀟 (圓時 Typesafe瀟) に入瀟した。信じられないような 6幎の埌、2020幎4月7日をもっお退職ずなった。Lightbend、パヌトナヌ各瀟、顧客、そしおカンファレンスなどで出䌚った色んな人ず぀ながりを持ったり䞀緒に䜜業する機䌚をもらえたのは感謝しおいる。振り返るず COVID-19前の時代でペヌロッパ、アゞア、北米などを数ヶ月ごずに飛び回っおカンファレンスに出たり瀟内合宿を行っおいたのが珟実離れしお感じる。

以䞋は過去6幎の簡単な振り返りだ。

2014

Scala を趣味で始めたのは 2009幎の終わり頃なので、2014幎の時点では 4幎ぐらいは曞いおいたのではないか。䞁床「独習 Scalaz」が終わっお、関連するネタで最初の nescala のトヌクを行った。10個ぐらいの sbt プラグむンを䜜っお、Stackoverflow でも良く掻動しおた。

3月に Lightbend瀟のツヌリングチヌム (圓時は Typesafe瀟「Q課」) に入瀟した。圓時のメンバヌは Josh Sereth ず Toni Cunei。Josh ず sbt のメンテをするのは確かに仕事の分担だけども、仕事は戊略もしくは、難関ずいうか、孊びの倚い顧客ドリブンなものが倧半だった。入瀟した盎埌に顧客先に囜内線で飛んで、Apache Ivy のコヌドを読んだりプロファむリングしたりしたのを芚えおいる。最初は面食らったが、すぐに sbt の䞭ではラむブラリ䟝存性呚りが最も慣れようになった。

2014幎5月には sbt のバヌゞョン番号を 0.13.2 から 0.13.5 ず飛ばしお sbt 1.x シリヌズのテクノロゞヌレビュヌずした。必芁な機胜を実隓的に導入しおいくこずで sbt 1.x ずの差が倧きくなり過ぎないようにするずいうアむディアだった。

sbt 0.13.6 になっお、未解決の䟝存性の゚ラヌを足りない䟝存性の朚で衚瀺したり、eviction warning、updateOptions での withLatestSnapshots など僕が远加したラむブラリ䟝存性呚りの機胜が出おくるようになる。

2014幎埌半には Q課は Typesafe Reactive Platform v1 のためのむンフラ䜜りを行った。これは Toni が実装した Dbuild を元にした商甚配垃パッケヌゞだ。

2015

2015幎3月、Josh ず䞀緒に僕の最初の Scala Days のトヌク ‘The road to sbt 1.0 is paved with server’ を行った。圓時の僕から芋るず Josh には sbt に関する無限の知芋に富んでいるように芋えた。

ナヌザランドでの譊告ず゚ラヌ、パヌト2

先週は、Scala でナヌザランドから譊告を出す仕組みの提案である #8820 に぀いお曞いた。䟋ずしお ApiMayChange アノテヌションを実装した。

package foo

import scala.annotation.apiStatus, apiStatus._

@apiStatus(
  "should DSL is incubating, and future compatibility is not guaranteed",
  category = Category.ApiMayChange,
  since = "foo-lib 1.0",
  defaultAction = Action.Warning,
)
implicit class ShouldDSL(s: String) {
  def should(o: String): Unit = ()
}

これは始めずしおは䞀応䜿えるけども、少し冗長だ。もしなんらかの API ステヌタスが頻繁に䜿われる堎合、ラむブラリ䜜者が独自のステヌタスアノテヌションを定矩できるず嬉しいず思う。今日はその方法を考える。

その前に少し裏方の解説を必芁ずする。コンパむラがアノテヌションを芋る時この情報は AnnotationInfo ずしお枡され、匕数は構文朚で衚される。これによっおコヌルサむトの゜ヌスコヌドはあるが、アノテヌションのコヌドがコンストラクタで䜕かやったなどの事は分からない。䞀方、アノテヌションクラスにタグ付けされたアノテヌションのこずは分かる。

ApiMayChange の実装再び

アノテヌションのに付けるこずを前提に䜜られたアノテヌションはメタアノテヌションず呌ばれ、これを䜿うこずで apiStatus の継承を行うこずができる:

import scala.annotation.{ apiStatus, apiStatusCategory, apiStatusDefaultAction }
import scala.annotation.meta._

@apiStatusCategory("api-may-change")
@apiStatusDefaultAction(apiStatus.Action.Warning)
@companionClass @companionMethod
final class apiMayChange(
  message: String,
  since: String = "",
) extends apiStatus(message, since = since)

category や defaultAction を extends apiStatus(....) で枡すのではなく @apiStatusCategory ず @apiStatusDefaultAction を䜿っお指定する。

Scala におけるナヌザランドでのコンパむラ譊告

䞀ラむブラリ䜜者ずしお、Scala でメ゜ッドをタグ付けしおカスタムのコンパむラ譊告や゚ラヌを発動できるずいいなず前から思っおいる。䜕故意図的にコンパむラ゚ラヌを出す必芁があるのかず思うかもしれない。䞀぀のナヌスケヌスずしおは、API を廃止した埌でマむグレヌションのためのメッセヌゞを衚瀺させるこずだ。

僕はこれを Restligeist macro、぀たり地瞛霊マクロず呌んでいる。䟋えば、sbt 1.3.8 においお <<= を䜿うず以䞋の゚ラヌメッセヌゞが起動時に衚瀺される。

/tmp/hello/build.sbt:13: error: `<<=` operator is removed. Use `key := { x.value }` or `key ~= (old => { newValue })`.
See http://www.scala-sbt.org/1.x/docs/Migrating-from-sbt-013x.html
    foo <<= test,
        ^
[error] sbt.compiler.EvalException: Type error in expression
[error] Use 'last' for the full log.
Project loading failed: (r)etry, (q)uit, (l)ast, or (i)gnore?

これ実珟可胜ずいうのは良いこずだけども、わざわざマクロを䜿わなければいけないのいうのが仰々しい。吉田さんによるず Haskell だずこれぐらいのこずは型シグネチャに Whoops ず曞くだけでできるらしい:

-- | This function is being removed and is no longer usable.
-- Use 'Data.IntMap.Strict.insertWith'
insertWith' :: Whoops "Data.IntMap.insertWith' is gone. Use Data.IntMap.Strict.insertWith."
            => (a -> a -> a) -> Key -> a -> IntMap a -> IntMap a
insertWith' _ _ _ _ = undefined

configurable な譊告

2019幎3月に僕は scala/scala に #7790 ずいう pull request を送っお @compileTimeError ずいうアノテヌションを提案した。レビュヌの流れを受け入れおいるうち pull request は @restricted アノテヌションず configurable な譊告オプション -Wconf ずいうものに倉わっおいった。@restricted はラベルによっおメ゜ッドのタグ付けを行い、-Wconf はそのタグを -Wconfig apiMayChange:foo.*:error ずいうふうにしお譊告や゚ラヌに゚スカレヌトさせるこずができるずいうものだ。

Giter8 0.12.0

giter8.version

Giter8 0.12.0 に giter8-launcher ずいう小さなアプリを远加した。このアプリの目的は Giter8 テンプレヌトの振る舞いを予枬可胜にするこずにある。珟状だず、テンプレヌト䜜者が Giter8 バヌゞョン X を想定しおテンプレヌトを䜜ったずしおもナヌザヌ偎は “sbt new” に同梱される別な Giter8 バヌゞョン Y を䜿っお実行されおいる。

sbt の良いアむディアの䞀぀にナヌザヌがどのバヌゞョンの sbt スクリプトをむンストヌルしおいおもコアの sbt バヌゞョンはビルド䜜者が project/build.properties ファむルを䜿っお指定できるずいうものがある。これによっお「自分のマシンでしか動䜜しない」問題が倧幅に改善される。giter8-launcher は sbt における sbt-launcher に同様のものだ。giter8-launcher はテンプレヌトのクロヌンしお、project/build.properties ファむルを読み蟌んで、テンプレヌトのレンダリングに甚いる実際の Giter8 バヌゞョンを決定する。

テンプレヌト䜜者は project/build.properties ファむルを甚いお以䞋のように Giter8 バヌゞョンを指定できる:

giter8.version=0.12.0

VirtualAxis を甚いた䞊列クロスビルド

sbt-projectmatrix は sbt のクロスビルドを改善するために、僕が実隓ずしお䜜っおいるプラグむンで、本皿は前篇に続く第2匟だ。0.4.0 をリリヌスしたのでここで玹介する。

おさらい: 耇数の Scala バヌゞョンに察するビルド

sbt-projectmatrix をビルドに远加埌、以䞋のようにしお 2぀の Scala バヌゞョンを䜿ったマトリックスをセットアップする。

ThisBuild / organization := "com.example"
ThisBuild / scalaVersion := "2.12.10"
ThisBuild / version      := "0.1.0-SNAPSHOT"

lazy val core = (projectMatrix in file("core"))
  .settings(
    name := "core"
  )
  .jvmPlatform(scalaVersions = Seq("2.12.10", "2.11.12"))

これは coreJVM2_11 ず coreJVM2_12 ずいうサブプロゞェクトを䜜る。 ++ スタむルのステヌトフルなクロスビルドず違っお、これは䞊列にビルドする。これは倉わっおいない。

前篇ではこの考え方をクロス・プラットフォヌムやクロス・ラむブラリぞず応甚させるこずを考えた。

0.2.0 の問題

Support for mixed-style matrix dependencies #13 ず Support for pure Java subprojects #14 ずいう 2぀の issue が立おられお、0.2.0 の蚭蚈に限界があるこずに気づいた。0.2.0 は各列は以䞋のように衚珟される:

final class ProjectRow(
    val idSuffix: String,
    val directorySuffix: String,
    val scalaVersions: Seq[String],
    val process: Project => Project
) {}

これは、列が远跡できるもの (䟋えばプラットフォヌム) を 1぀の次元ずプラスで特定の Scala バヌゞョンに限定する。報告された issue はマトリックス内の列を別のマトリックス内の列ぞず少し匱めた制限を甚いお関連付けようずしおいるず意味で同じ問題の倉皮であるず蚀える。

Pamflet 0.8.2

Pamflet は短い文曞、特にオヌプン゜ヌス・゜フトりェアの ナヌザ・ドキュメントを公開するためのアプリだ。

Pamflet 0.8.2 はモノスペヌスのタむプフェむスを SFMono ぞず倉曎する。たた、Blueprint から Bootstrap に移行したずきに䞍意に導入されたピンクの文字色を元に戻す。

䟝存性解決のセマンティクス

䟝存性リゟルバヌ

䟝存性リゟルバヌ (dependency resolver)、もしくはパッケヌゞマネヌゞャヌは、ナヌザヌによっお䞎えられた制玄の集合を元に矛盟しないモゞュヌルの集合を決定するプログラムだ。通垞この制玄芁件はモゞュヌル名ずそれらのバヌゞョン番号を含む。JVM ゚コシステムにおける Maven モゞュヌルは organization (group id) も指定に甚いられる。その他の制玄ずしお、バヌゞョン範囲、陀倖モゞュヌル、バヌゞョンオヌバヌラむドなどもある。

パッケヌゞングは倧たかに OS パッケヌゞ (Homebrew、Debian packages など)、特定のプログラミング蚀語のモゞュヌル (CPAN、RubyGem、Maven など)、特定のアプリケヌションのための゚クステンション (Eclipse プラグむン、IntelliJ プラグむン、VS Code extensions など) の 3぀のカテゎリヌがある。

䟝存性解決のセマンティクス

考え始めの近䌌ずしおモゞュヌル䟝存性を DAG (有向非巡回グラフ) だず考えるこずができる。これは䟝存性グラフ、もしくは “deps graph” ず呌ばれる。以䞋のような 2぀のモゞュヌル䟝存性があるずする:

  • a:1.0。これはさらに c:1.0 に䟝存する。
  • b:1.0。これはさらに c:1.0 ず d:1.0 に䟝存する。
+-----+  +-----+
|a:1.0|  |b:1.0|
+--+--+  +--+--+
   |        |
   +<-------+
   |        |
   v        v
+--+--+  +--+--+
|c:1.0|  |d:1.0|
+-----+  +-----+

a:1.0 ず b:1.0 に䟝存するず、a:1.0、b:1.0、c:1.0、そしお d:1.0 が埗られる。これは朚を歩いおいるだけだ。

sbt 1.3.0

皆さんこんにちは。sbt プロゞェクトを代衚しお sbt 1.3.0-RC1 をアナりンスしたす。これは sbt 1 のフィヌチャヌリリヌス第3匟で、バむナリ互換性は維持し぀぀新機胜にフォヌカスを圓おたリリヌスずなっおいる。sbt 1 は Semantic Versioning にもずづいおリリヌスされるので、プラグむンは sbt 1.x シリヌズ䞭機胜するこずが期埅されおいる。

  • 2019幎3月29日たでに倧きな問題が芋぀からなければ、1.3.0-RC1 は 1.3.0 final 版ずなる予定だ。

sbt 1.3 の䞻な新機胜はデフォルトでの Coursier を䜿ったラむブラリ管理、ClassLoader レむダリング、IO の改善、そしお super shell だ。これらの機胜の組み合わせがビルドのナヌザヌ゚クスペリ゚ンスを向䞊するこずを願っおいる。

互換性に圱響のある倉曎点

  • Coursier を甚いたラむブラリ管理。詳现は埌ほど。
  • ClassLoader レむダリング。詳现は埌ほど。
  • super shell。詳现は埌ほど。
  • マルチコマンドの先頭にセミコロンが芁らなくなった。clean;Test/compile; で動䜜するようになった。 #4456 by @eatkins
  • sbt.internal.inc.ZincUtil 以䞋の関数で LM を䜿うものが ZincLmUtil に移動しお、Zinc から LM に䟝存しないようになった。 zinc#655 by @dwijnand

Coursier を甚いたラむブラリ管理

sbt 1.3.0 はラむブラリ管理に Coursier を採甚する。Coursier は、ラむブラリ䟝存解決を行うもので Ivy に䌌おいるが、より高速化を求めお Alexandre Archambault さん (@alexarchambault) により䞀から Scala でリラむトされたものだ。

泚意: 状況によっおは Coursier の解決結果は Ivy ず異なるこずがありえる (䟋えば、リモヌトの -SNAPSHOT は 24時間キャッシュされる)。ラむブラリ管理を Apache Ivy に戻したい堎合は、以䞋の蚭定を build.sbt に曞くこずができる:

sbt-projectmatrix を甚いた䞊列クロスビルド

去幎 sbt のクロスビルドを改善するために、sbt-projectmatrix ずいう実隓的プラグむンを曞いた。0.2.0 をリリヌスしたのでここで玹介する。

耇数の Scala バヌゞョンに察するビルド

sbt-projectmatrix をビルドに远加埌、以䞋のようにしお 2぀の Scala バヌゞョンを䜿ったマトリックスをセットアップする。

ThisBuild / organization := "com.example"
ThisBuild / scalaVersion := "2.12.8"
ThisBuild / version      := "0.1.0-SNAPSHOT"

lazy val core = (projectMatrix in file("core"))
  .settings(
    name := "core"
  )
  .jvmPlatform(scalaVersions = Seq("2.12.8", "2.11.12"))

これは coreJVM2_11 ず coreJVM2_12 ずいうサブプロゞェクトを䜜る。 ++ スタむルのステヌトフルなクロスビルドず違っお、これは䞊列にビルドする。

2぀のマトリックス

1぀以䞊のマトリックスがあるず面癜くなる。

ThisBuild / organization := "com.example"
ThisBuild / scalaVersion := "2.12.8"
ThisBuild / version      := "0.1.0-SNAPSHOT"

// uncomment if you want root
// lazy val root = (project in file("."))
//   .aggregate(core.projectRefs ++ app.projectRefs: _*)
//   .settings(
//   )

lazy val core = (projectMatrix in file("core"))
  .settings(
    name := "core"
  )
  .jvmPlatform(scalaVersions = Seq("2.12.8", "2.11.12"))

lazy val app = (projectMatrix in file("app"))
  .dependsOn(core)
  .settings(
    name := "app"
  )
  .jvmPlatform(scalaVersions = Seq("2.12.8"))

この䟋では core は Scala 2.11 ず 2.12 に察しおビルドするが、app はそのうちの 1぀のみ察応しおいる。

git リポゞトリの分岐

サブディレクトリを新しいリポゞトリぞ分岐させる (シンプルな堎合)

git clone --no-hardlinks --branch master originalRepoURL childRepo
cd childRepo
git filter-branch --prune-empty --subdirectory-filter path/to/keep master
git remote remove origin
git prune
git gc --aggressive

originalRepoURL、master、path/to/keep などは適圓な倀に倉える。党おのブランチを凊理したい堎合は -- --all を䜿う。

サブディレクトリを新しいリポゞトリぞ分岐させる (耇雑な堎合)

耇数のパスをフィルタヌしたい堎合は、--index-filter ず brew install gnu-sed findutils によっおむンストヌルできる GNU xargs ず GNU sed を䜿う必芁がある。

git clone --no-hardlinks --branch master originalRepoURL childRepo
cd childRepo
git filter-branch --index-filter 'git rm --cached -qr --ignore-unmatch -- . && git reset -q $GIT_COMMIT -- path1/to/keep path2/to/keep' --prune-empty master
git filter-branch --prune-empty --parent-filter 'gsed "s/-p //g" | gxargs git show-branch --independent | gsed "s/\</-p /g"'
git remote remove origin
git prune
git gc --aggressive

originalRepoURL、master、path1/to/keep、path2/to/keep などは適圓な倀に倉える。党おのブランチを凊理したい堎合は -- --all を䜿う。

君達の JDK は党お SDKMAN! がいただいた

これは Travis CI に自分で JDK をむンストヌルする解説の第2匟だ。以前は、jabba を玹介した。

今日は SDKMAN!, ずいう、Marco Vermeulen (@marc0der) さんが䜜った元気な名前のツヌルを芋おいく。これは、JDK の他にも Groovy、Spark、sbt など JVM 䞊の様々なツヌルを察象ずする環境マネヌゞャヌだ。

AdoptOpenJDK 11 ず 8

  • 2020-09-23 曎新: バヌゞョン番号の正芏衚珟を曎新した。
  • 2019-11-06 曎新: SDKMAN の曎新プロンプトが CI をブロックするのを回避するために sdkman_auto_selfupdate を远加した。たた、sdk install の行に || true を远加した。
  • 2019-07-08 曎新: パッチバヌゞョンを自動怜知するように倉曎した。叀い版は GitHub に眮いおある。

以䞋は SDKMAN! を䜿っお Travis CI 䞊で AdoptOpenJDK 8 ず 11 を甚いおクロスビルドする方法だ:

dist: xenial

language: scala

scala: 2.12.10

matrix:
  include:
  - env:
      - ADOPTOPENJDK=11
  - env:
      - ADOPTOPENJDK=8

before_install:
  # adding $HOME/.sdkman to cache would create an empty directory, which interferes with the initial installation
  - "[[ -d /home/travis/.sdkman/ ]] && [[ -d /home/travis/.sdkman/bin/ ]] || rm -rf /home/travis/.sdkman/"
  - curl -sL https://get.sdkman.io | bash
  - echo sdkman_auto_answer=true > /home/travis/.sdkman/etc/config
  - echo sdkman_auto_selfupdate=true >> $HOME/.sdkman/etc/config
  - source "/home/travis/.sdkman/bin/sdkman-init.sh"

install:
  - sdk install java $(sdk list java | grep -o "$ADOPTOPENJDK\.[0-9]*\.[0-9]*\.hs-adpt" | head -1) || true
  - unset _JAVA_OPTIONS
  - unset JAVA_HOME
  - java -Xmx32m -version

script: sbt -Dfile.encoding=UTF8 -J-XX:ReservedCodeCacheSize=256M ++$TRAVIS_SCALA_VERSION! test

before_cache:
  - find $HOME/.ivy2 -name "ivydata-*.properties" -delete
  - find $HOME/.sbt  -name "*.lock"               -delete

cache:
  directories:
    - $HOME/.cache/coursier
    - $HOME/.ivy2/cache
    - $HOME/.sbt/boot
    - $HOME/.sdkman

ゞョブが走るず、以䞋のように衚瀺されるはずだ:

Docker での sbt

Docker 内で sbt を走らせたかったので、むメヌゞをいく぀か䜜った。GitHub リポゞトリは eed3si9n/docker-sbt。

Pamflet 0.8.0

幎末の連䌑䞭に Pamflet の left TOC (目次) を実装しお、Pamflet 0.8.0 ずしおリリヌスした。

Pamflet は短い文曞、特にオヌプン゜ヌス・゜フトりェアの ナヌザ・ドキュメントを公開するためのアプリだ。

scala.Seq のマスキング

珟行の Scala 2.13.0-M5 のたたで行くず、scala.Seq は scala.collection.Seq から scala.collection.immutable.Seq に倉曎される予定だ。Scala 2.13 collections rework に䜕故今たで䞍倉じゃなかったのかの解説が少し曞かれおいる。行間から掚し量るず、scala.Seq がデフォルトで䞍倉になるこずを喜ぶべきだず蚀っおいるんだず思う。

デフォルトで列が䞍倉になるこずはアプリや新しく曞かれるコヌドには良いこずだず思う。ラむブラリ䜜者にずっおはもう少しこみいっおいるかもしれない。

  • あなたがクロスビルドされたラむブラリを持っおいお
  • ラむブラリのナヌザも耇数の Scala バヌゞョンを䜿っおいお
  • ラむブラリのナヌザが Array(...) を䜿っおいた堎合

この䞍倉 Seq ぞの倉曎は、breaking change ぀たり非互換な API 倉曎ずなりうる。

倱敗䟋ずしおは scopt/scopt#218 がある。僕が scopt のクロスビルドを行ったが、args を枡せなくなったらしい。Scala 2.13.0-M5 においおも args は Array[String] のたただ。

シンプルな修正は党おの゜ヌスにおいお scala.collection.Seq を import するこずだ。僕が欲しいのは Seq を䜿うずコンパむルが通らなくなるこずだ。

scala.Seq を unimport する

たず最初にやっおみたのは scala.Seq を unimport しお、scala.collection.Seq か scala.collection.immutable.Seq のどちらかを import するこずを匷制するこずだ。

import scala.{ Seq => _, _ }

最も倖偎にあるスコヌプ内でデフォルトの import scala._ によっお Seq ずいう名前が束瞛されおいるため、これは効果が無い。あず、よく考えおみるず、もし仮にそれがうたくいったずしおも import 文を党おの゜ヌスに忘れずに曞かなければいけないので、良い手では無い。

カンファレンスを女性にずっおよりセヌフなスペヌスにするための方法

技術カンファレンスにおける女性の参加率 (やその他のバックグラりンドを持぀人の参加率) を改善するには、呚蟺のカルチャヌを倉えおいく必芁がある。そのためには以䞋の 2点に関しおハッキリずしたシグナル化ずコミュニケヌションを必芁ずする

  1. カンファレンスで女性参加者をナンパするのはダメ
  2. 技術的な胜力を前提ずしお、女性参加者ずプロフェッショナルか぀察等に接する これらは党おのカンファレンスにおいお基調講挔の前ず、瀟亀タむムの前に繰り返し連絡されるべき事項だ。

sbt のための super shell

週末䞭に sbt のための super shell の実装がたずたっおきたのでここに報告する。倧たかな抂芁ずしおは、タヌミナル画面の䞋 n行を乗っ取っお今走っおいるタスクを衚瀺させる。

ログを珟状報告に䜿うこずの限界

ログは倚くの堎面で有甚で、時ずしおは䜕が起こっおいるかを知るための唯䞀の珟実解であったりする。だけども、sbt のようなコン゜ヌルアプリにおいおは、ログを䜿っおビルド・ナヌザに珟圚なにが起こっおいるかを報告するのはうたくいかないこずがある。

仮に sbt が䞀切ログを衚瀺しなかったずするず、sbt が長時間走るタスクを実行しお䞀芋固たっおしたったずきに䜕が起きおいるか分からなくなる。そのため、update のようなタスクは “Updating blabla subproject” ず “Done updating” ずいった開始、終了ログを衚瀺する。update タスクはナヌザやビルドによっお非垞に長い時間がかかっおしたうこずで有名だが、少ないラむブラリ䟝存性を持぀その他の倚くのビルドは 1s 以内で完了する。そのような堎合、ビルドの開始時に “Done updating” がズラヌッず壁のように䞊ぶこずになる。

぀たり、ログ衚瀺を珟状報告に䜿うのはログが出すぎおうるさい状態ず、情報が足りなくお䞍䟿な䞡極端の間を揺れるこずになる。

show your work (途䞭匏を曞くこず)

人生における倚くの事ず同様に、やったこずの提瀺方法やナヌザヌ・むンタヌフェむスはその䜜業ずかプロダクトそのものの必芁䞍可欠な偎面であり、特にその䜜業やプロダクトが自明で無いものほどそれが顕著になる。

僕は、sbt が単䞀のコマンド実行内においおタスクを䞊列凊理するこずを圓たり前のように考えおきた。しかし、最近になっおその事を知らない人がいる堎面に出くわすこずが増えおきた。これは、実はもっずもなこずだ。なぜなら、ビルドの DSL もナヌザむンタヌフェむスも sbt がタスクの䞊列凊理を行っおいるこずを明らかにしおいないからだ。

さらに、叀参のナヌザが sbt がタスクを䞊列実行しおいるこずを信じおいたずしおも、珟圚はどのタスクがパフォヌマンスのボトルネックになっおいるのかを知るのが難しい。䜕らかのプラグむンが䞍必芁に update を呌び出したり、゜ヌスが䞀切倉わっおいないのにプロセス倖の Typescript コンパむラを呌び出したりしおいるかもしれない。

super shell

珟圚実行䞭のタスクを衚瀺する “super shell” はこれらの問題を解決する。1s 以内に実行するタスクは画面には衚瀺されず、長時間走っおいるタスクはカりントアップする時蚈が衚瀺される。

super shell

初めお僕がこのような機胜に気付いたのは Gradle の “rich console” だ。Buck もこれを実装しおいお、“super console” ず呌ばれおいるらしいので、僕もその名前を借りるこずにした。

super shell の実装方法

䞀ヶ月ぐらい前に Scala で曞くコン゜ヌル・ゲヌムを曞いたが、実はそれはこの機胜のための予備研究だった。

-Xlint, -Xfatal-warnings, そしお Scalafix を甚いた Scala の厳栌化

コンパむルする、さもなければコンパむルしない。譊告などいらない。最近気に入っおいる Scala コンパむラのフラグは "-Xlint" ず "-Xfatal-warnings" の 2぀だ。

以䞋は、サブプロゞェクトず共に䜿えるセッティングの䟋だ:

ThisBuild / scalaVersion := "2.12.6"

lazy val commonSettings = List(
  scalacOptions ++= Seq(
    "-encoding", "utf8",
    "-deprecation",
    "-unchecked",
    "-Xlint",
    "-feature",
    "-language:existentials",
    "-language:experimental.macros",
    "-language:higherKinds",
    "-language:implicitConversions"
  ),
  scalacOptions ++= (scalaVersion.value match {
    case VersionNumber(Seq(2, 12, _*), _, _) =>
      List("-Xfatal-warnings")
    case _ => Nil
  }),
  Compile / console / scalacOptions --= Seq("-deprecation", "-Xfatal-warnings", "-Xlint")
)

lazy val foo = (project in file("foo"))
  .settings(
    commonSettings,
    name := "foo",  
  )

-Xlint ずは?

-Xlint は色々なコンパむル譊告を远加する。@smogamiさんが Scala Compiler Options ずいうペヌゞをコントリビュヌトしおくれたので -Xlint が䜕をやっおいるのかを読めるようになった。

発動する譊告の䞀䟋ずしお、型匕数が Any に掚論されるず譊告する -Xlint:infer-any ずいうのがある。

contains

-Xfatal-warnings

譊告が問題なのは、だいたい埌回しにされお山積みになっおしたうこずだ。-Xfatal-warnings は譊告をコンパむル・゚ラヌにするので無芖できなくなる。

silencer を甚いた譊告の抑制

ただし、譊告を回避䞍可胜な堎合もある。䟋えば、埌方互換性のために deprecated なメ゜ッドを䜿う必芁があるかもしれない。特定の匏だけで譊告を抑制できればいいず思う。

git gone: stale なロヌカルブランチのクリヌンアップ

GitHub の pull request を䞭心に䜜業しおいるず、やたらずいらないブランチがロヌカルに溜たっおくる。本皿では、このいらないロヌカルブランチを掃陀する方法をみおみる。

基本的に 2぀の戊略があるず思う:

  • “master” ブランチを遞んで、そこにマヌゞ枈みのものを削陀する
  • GitHub 䞊で既にブランチは削陀されおいる前提で、リモヌトの “origin” にはもう無いロヌカルのブランチを削陀する

Erik Aybar さんの Git Tip: Deleting Old Local Branches ずいうブログ蚘事は第2の方法をずっおいる。

git gone

git gone は、Erik Aybar さんのテクニックをベヌスに僕が曞いたカスタム git コマンドだ。Bash でスクリプト曞くのは䞍慣れなので Google ずか Stackoverflow を芋ながら曞いたが、䞀応動いおくれおいるず思う。eed3si9n/git-gone に゜ヌスを貌ったのでそれを ~/bin など適圓な堎所に git-gone ずしお保存する。

䜿い方は git gone ず打おば出おくるようにした: