gitbucket-commitgraphs-plugin を修正しようとしたらハマった話
概要
GitBucket のプラグイン gitbucket-commitgraphs-plugin は、開発者のコミット状況をグラフで表示するプラグインです。
グラフの描画には、Google Charts を利用しているため、インターネットに接続できないクローズド環境では、使用できません。
あまり需要はないかもしれませんが、個人的にクローズド環境に対応させたく、修正を試みたのですが、謎の依存関係にハマってしまったというお話です。
前回の記事
最終的な成果
本当は、本家にコントリビュートできるようにしたかったのですが、後述の事情により、GitBucket Commit Graphs Chart.js Plugin という別のリポジトリを作成しました。
バージョン v0.1.0 としてリリースしましたのでお試しいただけますと幸いです。
Google Charts の代わりに chart.js を同梱し、利用するようにしました。
オリジナル版では、以下のように表示されていました。

改造版では、以下のように表示されます。

なお、日付の表示は、ブラウザの言語設定により変わります。
謎の依存関係
gitbucket-commitgraphs-plugin を Fork し、clone してビルドしようとしたら、以下のエラーに遭遇しました。
[warn] Note: Unresolved dependencies path:
[error] sbt.librarymanagement.ResolveException: Error downloading com.github.bkromhout:java-diff-utils:2.1.1
[error] Not found
[error] Not found
[error] not found: C:\Users\username\.ivy2\local\com.github.bkromhout\java-diff-utils\2.1.1\ivys\ivy.xml
[error] not found: https://jcenter.bintray.com/com/github/bkromhout/java-diff-utils/2.1.1/java-diff-utils-2.1.1.pom
[error] not found: https://repo1.maven.org/maven2/com/github/bkromhout/java-diff-utils/2.1.1/java-diff-utils-2.1.1.pom
[error] not found: https://dl.bintray.com/bkromhout/maven/com/github/bkromhout/java-diff-utils/2.1.1/java-diff-utils-2.1.1.pom
[error] at lmcoursier.CoursierDependencyResolution.unresolvedWarningOrThrow(CoursierDependencyResolution.scala:258)
[error] at lmcoursier.CoursierDependencyResolution.$anonfun$update$38(CoursierDependencyResolution.scala:227)
[error] at scala.util.Either$LeftProjection.map(Either.scala:573)
[error] at lmcoursier.CoursierDependencyResolution.update(CoursierDependencyResolution.scala:227)
[error] at sbt.librarymanagement.DependencyResolution.update(DependencyResolution.scala:60)
[error] at sbt.internal.LibraryManagement$.resolve$1(LibraryManagement.scala:53)
[error] at sbt.internal.LibraryManagement$.$anonfun$cachedUpdate$12(LibraryManagement.scala:103)
[error] at sbt.util.Tracked$.$anonfun$lastOutput$1(Tracked.scala:73)
[error] at sbt.internal.LibraryManagement$.$anonfun$cachedUpdate$20(LibraryManagement.scala:116)
[error] at scala.util.control.Exception$Catch.apply(Exception.scala:228)
[error] at sbt.internal.LibraryManagement$.$anonfun$cachedUpdate$11(LibraryManagement.scala:116)
[error] at sbt.internal.LibraryManagement$.$anonfun$cachedUpdate$11$adapted(LibraryManagement.scala:97)
[error] at sbt.util.Tracked$.$anonfun$inputChangedW$1(Tracked.scala:219)
[error] at sbt.internal.LibraryManagement$.cachedUpdate(LibraryManagement.scala:130)
[error] at sbt.Classpaths$.$anonfun$updateTask0$5(Defaults.scala:3485)
[error] at scala.Function1.$anonfun$compose$1(Function1.scala:49)
[error] at sbt.internal.util.$tilde$greater.$anonfun$$u2219$1(TypeFunctions.scala:62)
[error] at sbt.std.Transform$$anon$4.work(Transform.scala:68)
[error] at sbt.Execute.$anonfun$submit$2(Execute.scala:282)
[error] at sbt.internal.util.ErrorHandling$.wideConvert(ErrorHandling.scala:23)
[error] at sbt.Execute.work(Execute.scala:291)
[error] at sbt.Execute.$anonfun$submit$1(Execute.scala:282)
[error] at sbt.ConcurrentRestrictions$$anon$4.$anonfun$submitValid$1(ConcurrentRestrictions.scala:265)
[error] at sbt.CompletionService$$anon$2.call(CompletionService.scala:64)
[error] at java.base/java.util.concurrent.FutureTask.run(FutureTask.java:264)
[error] at java.base/java.util.concurrent.Executors$RunnableAdapter.call(Executors.java:539)
[error] at java.base/java.util.concurrent.FutureTask.run(FutureTask.java:264)
[error] at java.base/java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1136)
[error] at java.base/java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:635)
[error] at java.base/java.lang.Thread.run(Thread.java:840)
[error] (update) sbt.librarymanagement.ResolveException: Error downloading com.github.bkromhout:java-diff-utils:2.1.1
[error] Not found
[error] Not found
[error] not found: C:\Users\username\.ivy2\local\com.github.bkromhout\java-diff-utils\2.1.1\ivys\ivy.xml
[error] not found: https://jcenter.bintray.com/com/github/bkromhout/java-diff-utils/2.1.1/java-diff-utils-2.1.1.pom
[error] not found: https://repo1.maven.org/maven2/com/github/bkromhout/java-diff-utils/2.1.1/java-diff-utils-2.1.1.pom
[error] not found: https://dl.bintray.com/bkromhout/maven/com/github/bkromhout/java-diff-utils/2.1.1/java-diff-utils-2.1.1.pom
java-diff-utils の groupId が変わってしまったのでダウンロードできないのだと思いますが、そもそもなぜ java-diff-utils への依存を拾ってくるのから、見当がつきません。
java-diff-utils という文字列でプロジェクトないを検索してみましたが、当該ログが引っかかるのみです。
依存関係ツリーを表示してみる
sbt dependencyTree で依存関係を調べてみました。
>sbt dependencyTree
WARNING: A terminally deprecated method in java.lang.System has been called
WARNING: System::setSecurityManager has been called by sbt.TrapExit$ (file:/C:/Users/username/.sbt/boot/scala-2.12.12/org.scala-sbt/sbt/1.4.4/run_2.12-1.4.4.jar)
WARNING: Please consider reporting this to the maintainers of sbt.TrapExit$
WARNING: System::setSecurityManager will be removed in a future release
[info] welcome to sbt 1.4.4 (Eclipse Adoptium Java 17.0.15)
[info] loading settings for project gitbucket-commitgraphs-plugin-build from plugins.sbt ...
[info] loading project definition from C:\Users\username\gitbucket-commitgraphs-plugin\project
[info] loading settings for project root from build.sbt ...
[info] set current project to gitbucket-commitgraphs-plugin (in build file:/C:/Users/username/gitbucket-commitgraphs-plugin/)
[info] me.huzi.gitbucket:gitbucket-commitgraphs-plugin_2.13:4.35.0 [S]
[info] +-com.typesafe.play:twirl-api_2.13:1.4.2 [S]
[info] +-org.scala-lang.modules:scala-xml_2.13:1.2.0 [S]
[info]
[success] Total time: 13 s, completed 2025/12/30 9:07:09
やはり、java-diff-utils は見つかりません。
スコープを変えて sbt runtime:dependencyTree を実行してみます。
>sbt runtime:dependencyTree
WARNING: A terminally deprecated method in java.lang.System has been called
WARNING: System::setSecurityManager has been called by sbt.TrapExit$ (file:/C:/Users/username/.sbt/boot/scala-2.12.12/org.scala-sbt/sbt/1.4.4/run_2.12-1.4.4.jar)
WARNING: Please consider reporting this to the maintainers of sbt.TrapExit$
WARNING: System::setSecurityManager will be removed in a future release
[info] welcome to sbt 1.4.4 (Eclipse Adoptium Java 17.0.15)
[info] loading settings for project gitbucket-commitgraphs-plugin-build from plugins.sbt ...
[info] loading project definition from C:\Users\username\gitbucket-commitgraphs-plugin\project
[info] loading settings for project root from build.sbt ...
[info] set current project to gitbucket-commitgraphs-plugin (in build file:/C:/Users/username/gitbucket-commitgraphs-plugin/)
[info] me.huzi.gitbucket:gitbucket-commitgraphs-plugin_2.13:4.35.0 [S]
[info] +-com.typesafe.play:twirl-api_2.13:1.4.2 [S]
[info] +-org.scala-lang.modules:scala-xml_2.13:1.2.0 [S]
[info]
[success] Total time: 0 s, completed 2025/12/30 9:08:05
さらに sbt test:dependencyTree を実行してみます。
>sbt test:dependencyTree
WARNING: A terminally deprecated method in java.lang.System has been called
WARNING: System::setSecurityManager has been called by sbt.TrapExit$ (file:/C:/Users/username/.sbt/boot/scala-2.12.12/org.scala-sbt/sbt/1.4.4/run_2.12-1.4.4.jar)
WARNING: Please consider reporting this to the maintainers of sbt.TrapExit$
WARNING: System::setSecurityManager will be removed in a future release
[info] welcome to sbt 1.4.4 (Eclipse Adoptium Java 17.0.15)
[info] loading settings for project gitbucket-commitgraphs-plugin-build from plugins.sbt ...
[info] loading project definition from C:\Users\username\gitbucket-commitgraphs-plugin\project
[info] loading settings for project root from build.sbt ...
[info] set current project to gitbucket-commitgraphs-plugin (in build file:/C:/Users/username/gitbucket-commitgraphs-plugin/)
[info] me.huzi.gitbucket:gitbucket-commitgraphs-plugin_2.13:4.35.0 [S]
[info] +-com.typesafe.play:twirl-api_2.13:1.4.2 [S]
[info] +-org.scala-lang.modules:scala-xml_2.13:1.2.0 [S]
[info]
[success] Total time: 0 s, completed 2025/12/30 9:08:38
sbt compile:dependencyTree でも状況は変わりません。
>sbt compile:dependencyTree
WARNING: A terminally deprecated method in java.lang.System has been called
WARNING: System::setSecurityManager has been called by sbt.TrapExit$ (file:/C:/Users/username/.sbt/boot/scala-2.12.12/org.scala-sbt/sbt/1.4.4/run_2.12-1.4.4.jar)
WARNING: Please consider reporting this to the maintainers of sbt.TrapExit$
WARNING: System::setSecurityManager will be removed in a future release
[info] welcome to sbt 1.4.4 (Eclipse Adoptium Java 17.0.15)
[info] loading settings for project gitbucket-commitgraphs-plugin-build from plugins.sbt ...
[info] loading project definition from C:\Users\username\gitbucket-commitgraphs-plugin\project
[info] loading settings for project root from build.sbt ...
[info] set current project to gitbucket-commitgraphs-plugin (in build file:/C:/Users/username/gitbucket-commitgraphs-plugin/)
[info] me.huzi.gitbucket:gitbucket-commitgraphs-plugin_2.13:4.35.0 [S]
[info] +-com.typesafe.play:twirl-api_2.13:1.4.2 [S]
[info] +-org.scala-lang.modules:scala-xml_2.13:1.2.0 [S]
[info]
[success] Total time: 0 s, completed 2025/12/30 9:12:17
以下のバージョンを変えてみたり、キャッシュを削除したりしてみましたが、現象は変わりませんでした。
- scala
- sbt
- sbt-twirl
- sbt-gitbucket-plugin
- jvm
解決できないので新規 sbt プロジェクトを作成し src 以下を移植してみる
gitbucket-commitgraphs-chartjs-plugin というディレクトリを作成し、以下のファイルを作成しました。
name := "gitbucket-commitgraphs-chartjs-plugin"
organization := "io.github.gitbucket"
version := "0.1.0"
scalaVersion := "2.13.16"
gitbucketVersion := "4.36.2"
lazy val root = (project in file(".")).enablePlugins(SbtTwirl)
addSbtPlugin("io.github.gitbucket" % "sbt-gitbucket-plugin" % "1.6.0")
addSbtPlugin("org.scalameta" % "sbt-scalafmt" % "2.5.6")
addSbtPlugin("org.playframework.twirl" % "sbt-twirl" % "2.0.9")
gitbucket-commitgraphs-plugin から src をそくっりもらってきます。
それから、sbt compile を実行しました。
>sbt compile
[info] welcome to sbt 1.11.3 (Eclipse Adoptium Java 17.0.15)
[info] loading settings for project gitbucket-commitgraphs-chartjs-plugin-build from plugins.sbt...
[info] loading project definition from C:\Users\y_aka\projects\gitbucket-commitgraphs-chartjs-plugin\project
[info] loading settings for project root from build.sbt...
[info] set current project to gitbucket-commitgraphs-chartjs-plugin (in build file:/C:/Users/y_aka/projects/gitbucket-commitgraphs-chartjs-plugin/)
[info] Executing in batch mode. For better performance use sbt's shell
[info] compiling 7 Scala sources to C:\Users\y_aka\projects\gitbucket-commitgraphs-chartjs-plugin\target\scala-2.13\classes ...
[warn] 3 deprecations
[warn] 5 deprecations (since 4.36.0)
[warn] 8 deprecations in total; re-run with -deprecation for details
[warn] three warnings found
[success] Total time: 8 s, completed 2025/12/30 9:19:54
deprecations の警告は出るもののすんなりコンパイルが通りました。なんでやねん!
Google Charts の処理部分を調査する
手始めに src/main/twirl/me/huzi/gitbucket/commitgraphs/list.scala.html の28行目 から始まる以下の処理が、グラフの描画を担っています。
google.setOnLoadCallback(function() {
var data = new google.visualization.DataTable();
data.addColumn('date',"Date");
data.addColumn('number',"Commits");
data.addRows([
@cg.dailys.map { d =>
@{"[new Date(%4d,%2d,%2d,0,0,0), %d],".format(d.date.getYear()+1900,d.date.getMonth(),d.date.getDate(),d.commits)}
}
]);
var options = {
legend: {position: "none"},
vAxis: {minValue: 0}
};
var chart = new google.visualization.AreaChart(document.getElementById('chart_div_@i'));
chart.draw(data, options);
});
クライアントに渡される際には、以下のように展開されます。
google.setOnLoadCallback(function() {
var data = new google.visualization.DataTable();
data.addColumn('date',"Date");
data.addColumn('number',"Commits");
data.addRows([
[new Date(2025, 6, 7,0,0,0), 2],
[new Date(2025, 7, 2,0,0,0), 16],
[new Date(2025,10,15,0,0,0), 5],
[new Date(2025,10,29,0,0,0), 1],
[new Date(2025,11, 3,0,0,0), 2],
[new Date(2025,11, 4,0,0,0), 1],
[new Date(2025,11, 5,0,0,0), 1],
[new Date(2025,11, 7,0,0,0), 6],
[new Date(2025,11, 8,0,0,0), 2],
[new Date(2025,11, 9,0,0,0), 2],
[new Date(2025,11,10,0,0,0), 9],
[new Date(2025,11,11,0,0,0), 1],
[new Date(2025,11,15,0,0,0), 10],
[new Date(2025,11,16,0,0,0), 4],
[new Date(2025,11,17,0,0,0), 1],
[new Date(2025,11,22,0,0,0), 2],
[new Date(2025,11,23,0,0,0), 2],
[new Date(2025,11,24,0,0,0), 2],
]);
var options = {
legend: {position: "none"},
vAxis: {minValue: 0}
};
var chart = new google.visualization.AreaChart(document.getElementById('chart_div_0'));
chart.draw(data, options);
});
chart.js など必要なファイルを同梱するディレクトリを作成
ディレクトリ src/main/resources/commitgraphs-chartjs/assets を掘り、以下のファイルを配置しました。
chartjs-adapter-luxon は、luxonにより、X軸に表示する日付をブラウザのローケルに合わせて表示するための Date Adapters です。
assetsMappings を設定
src/main/scala/Plugin.scala で assetsMappings を override し、同梱したファイルを使えるようにします。
override val assetsMappings = Seq("/commitgraphs-chartjs" -> "/commitgraphs-chartjs/assets")
chart.js を使用してグラフを描画するように修正
src/main/twirl/me/huzi/gitbucket/commitgraphs/list.scala.html を修正しました。
まず、同梱した JavaScript を読み込むようにします。
<script src="@context.path/plugin-assets/commitgraphs-chartjs/chart.umd.min.js"></script>
<script src="@context.path/plugin-assets/commitgraphs-chartjs/luxon.js"></script>
<script src="@context.path/plugin-assets/commitgraphs-chartjs/chartjs-adapter-luxon.js"></script>
Google Charts では X軸の値とY軸の値が対になっていましたが、 chart.js では、X軸とY軸を別の配列で定義する必要があります。
まずは、X軸の値を定義します。
var dateLabels@i = [
@cg.dailys.map { d =>
@{"new Date(%4d,%2d,%2d,0,0,0),".format(d.date.getYear()+1900,d.date.getMonth(),d.date.getDate()) }
}
];
実はこの部分、Scala というか Java 的には、deprecations なコードが入っています。(java.util.Date の getYearなど)
次にY軸の値を定義するとともに先ほど定義したX軸を関連付けます。オリジナルに合わせて、グラフを塗りつぶすように fill を true にしています。
var data@i = {
labels: dateLabels@i,
datasets: [{
label: 'Commits',
data: [
@cg.dailys.map { d =>
@{"%d,".format(d.commits)}
}
],
fill: true
}]
};
グラフの設定を定義します。
var lineConfig@i = {
type: 'line',
data: data@i,
options: {
responsive: true,
locale: navigator.language,
scales: {
x: {
type: 'time',
time: {
unit: 'day'
}
},
y: {
beginAtZero: true
}
},
plugins: {
legend: {
position: 'top',
},
title: {
display: true,
text: 'Commits over Time'
}
}
},
};
ポイントは以下の通り。
-
localeをnavigator.languageから取得 - X軸の
typeをtimeにすることで日付間隔を調整
Copilot からサジェストされた plugins はなくても良かったかな…
以上から、グラフを描画します。
var myChart@i = new Chart(
document.getElementById('chart_div_@i'),
lineConfig@i
);
オリジナルのまま、タグの id をそのまま使ってますが、div から canvas に変えたので合わせた方が良かったかな…
CommitGraphsSettingsService の deprecations な記述を修正
src\main\scala\me\huzi\gitbucket\commitgraphs\service\CommitGraphsSettingsService.scala に deprecations な記述があると警告が出ました。
例えば、以下の部分の2行目にある defining という記述です。元々、GitBucket に用意されていたシンタックスシュガーのようです。
def saveCommitGraphsSettings(settings: CommitGraphsSettings): Unit =
defining(new java.util.Properties()) { props =>
props.setProperty(CommitGraphsGitCommand, settings.CommitGraphsGitCommand)
Using.resource(new java.io.FileOutputStream(CommitGraphsConf)) { out =>
props.store(out, null)
}
}
改造版 では、以下のように修正しています。
def saveCommitGraphsSettings(settings: CommitGraphsSettings): Unit = {
val props = new java.util.Properties()
props.setProperty(CommitGraphsGitCommand, settings.CommitGraphsGitCommand)
Using.resource(new java.io.FileOutputStream(CommitGraphsConf)) { out =>
props.store(out, null)
}
}
Discussion
com.github.bkromhoutのjava-diff-utilsは昔のgitbucketが依存していたけれどjcenterという、もう今となっては閉鎖した場所に置かれていたものです。以下のようにいくつかupdateしたら手元では依存解決成功しました。変なcacheが効いていたか、sbtのreload忘れた、とかだと思います
情報ありがとうございます。勉強になりました。
gitbucketVersion の更新忘れが原因だったみたいです…。修正したら、あっさりコンパイル通りました。
JCenter の記述も気になっておりました。