くりにっき

フルスタックキュアエンジニアです

GitLabのリポジトリでRenovateを使い始めた

DependabotからRenovateしたモチベーション

http://gitlab.com/sue445 にあるリポジトリではライブラリのバージョンアップにGitLab版のDependabotである https://dependabot-gitlab.gitlab.io/dependabot/ (Standalone mode)を使っていました。

これといって不満はなかったんですが、gitlab.com/gitlab-org/api/client-go/v3 のようにGo moduleのパス名にメジャーバージョン含まれる場合にDependabotだと追従できないという問題がありました。

GitHubだとnativeで使えるDendanbotがなんやかんやで便利なのでメインではそっちを使いつつパス名にメジャーバージョン含まれるGo moduleのみRenovateを使っているのですが、GitLabだとそういう優位性がないので全面的にRenovateに移行しました。

使ったもの

GitHub Actionsのmarketplaceに対応するものとしてGitLabには CI/CD Catalog というのがあります

今回Renovateを使うために https://gitlab.com/explore/catalog/to-be-continuous/renovate を使いました。

ハマったこと

v1.14.1を使ったので以降のバージョンだと挙動が変わってる可能性があります。

gitlab-ci-renovateのjobがtest stageとbuild stageに依存している

具体的にはこの辺

gitlab-ci-renovateを導入したリポジトリだと .gitlab-ci.yml に

stages:
  - test
  - publish

のように書いていたのですが、build stageが無いせいでgitlab-ci-renovateが依存してるjobが定義できずにシンタックスエラーになりました。

解決方法

ちょっと汚いですが下記のようにstageを追加して回避しました

stages:
  - build # renovate-validator job requires build stage
  - test
  - publish

gitlab-ci-renovateのjobが勝手に追加されるせいでRenovateを使わないワークフローで意図しない挙動になる

GitLabだとGitLab CIのSchedulerを使ってRenovateを動かします。

https://gitlab.com/sue445/tanuki_reminder はSlackなどに投稿する通知ツールなのでRenovate以外にも通知系のSchedulerを登録してます。

Slack通知を行いたいだけなのにgitlab-ci-renovateのjobも実行されて通知が遅くなったり、GitLab CIのQuotaを消費するという問題がありました。

解決方法

Renovate以外のワークフローで $RENOVARE_TOKEN をセットしなければrenovate-depcheck(実際にRenovateを実行するjob)は作られません。*1

そのため下記のようにして $RENOVARE_TOKEN がある時のみcomponentをincludeするようにしました。

include:
  - component: $CI_SERVER_FQDN/to-be-continuous/renovate/gitlab-ci-renovate@~latest
    rules:
      - if: "$RENOVATE_TOKEN"

RenovateのScheduleにのみVariableで $RENOVARE_TOKEN をセットすることで、Renovate以外では $CI_SERVER_FQDN/to-be-continuous/renovate/gitlab-ci-renovate のincludeそのものを抑制しました。

実際にRenovateを導入したリポジトリ

rbpackerを作った

これ何?

複数のrbファイルを連結(bundling)してminifyするためのツールです。

github.com

名前の由来

名前の由来はruby + webpackです。(Ruby版のwebpackを意識して作った)

Rubyのgemならerをつけた方がいいかな *1 と思ってrbpackerにしました。

なぜ作ったの?

https://github.com/sue445/rb-wasm-vdom ではruby.wasmやPicoRuby.wasmで使うrbファイルをCDNで配布しています。

CDNから配信するのでminifyしたファイルの方がいいかなと思い作りました。

技術的な面白ポイント

require_relativeにモンキーパッチを当てた

当初は rbpacker --src-file a.rb b.rb ... にように羅列することも考えたのですが、それだとダサいのでrbファイル内の require_relative を解析してbundlingできるようにしました。

幸い(?) にもrb-wasm-vdomで require_relative をモンキーパッチして挙動を変える術を知っていました。*2

その時にやったことを応用してrequire_relative をモンキーパッチしてbundlingするようにしました。

https://github.com/sue445/rbpacker/blob/v0.1.1/lib/rbpacker/source_bundler.rb#L78-L89

Rubyのminify

minify部分は id:koic 作の https://github.com/koic/minifyrb を使ったのでだいぶ楽をできました。

koic.hatenablog.com

2年前にminifyrbを見た時は正直使い道が思いつかなかったんですが、こんなところでユースケースを見つけるとは思いませんでした。

ruby.wasmとPicoRuby.wasmの両方で動く仮想DOMライブラリを作った

モチベーション

元々は今年のRubyKaigiのLTネタで作ろうと思ってたのですが、本編のタイムテーブル見てたら内容が被ってそうだったので作るのを断念しました。

rubykaigi.org

RubyKaigiのpartyかなんかで id:hasumikin にそのことを話した時に「両方あっていいんじゃない?(意訳)」みたいなことを言われたので作りました。 *1

作ったもの

これ。

github.com

人生初npmです。

https://www.npmjs.com/package/@sue445/rb-wasm-vdom

Example

リポジトリのREADMEからのコピペですがこんな感じ。

<!-- Using ruby.wasm -->
<script src="https://cdn.jsdelivr.net/npm/@ruby/head-wasm-wasi/dist/browser.script.iife.min.js"></script>

<!--
or using PicoRuby.wasm
<script src="https://cdn.jsdelivr.net/npm/@picoruby/wasm-wasi@latest/dist/init.iife.js"></script>
-->

<script type="text/ruby" src="https://cdn.jsdelivr.net/npm/@sue445/rb-wasm-vdom@latest/dist/rb-wasm-vdom.rb"></script>

<!--
or specific version
<script type="text/ruby" src="https://cdn.jsdelivr.net/npm/@sue445/rb-wasm-vdom@X.Y.Z/dist/rb-wasm-vdom.rb"></script>
-->

<div id="app"></div>

<script type="text/ruby">
  # Define the template with variable interpolation and event bindings
  template = <<~HTML
    <div class="app-container">
      <h2 style="margin-top: 0; color: #cc342d;">{{ title }}</h2>

      <div style="margin-bottom: 15px;">
        <label>Step value: </label>
        <input type="number" class="input-box" value="{{ step }}" @input="update_step">
      </div>

      <p style="font-size: 1.2rem;">Current Count: <strong>{{ count }}</strong></p>

      <button class="btn" @click="increment">+ Increment</button>
      <button class="btn" @click="decrement">- Decrement</button>
      <button class="btn" style="background: #666;" @click="reset">Reset</button>
    </div>
  HTML

  # Define the reactive state
  state = {
    title: "Ruby Reactivity App",
    count: 0,
    step: 1
  }

  # Define the methods to handle events and mutate the state
  methods = {
    increment:   ->(e, s) { s[:count] += s[:step] },
    decrement:   ->(e, s) { s[:count] -= s[:step] },
    reset:       ->(e, s) { s[:count] = 0 },
    update_step: ->(e, s) { s[:step] = e[:target][:value].to_i }
  }

  # Initialize and mount the application
  RbWasmVdom.create_app("#app", template: template, state: state, methods: methods)
</script>

Vue.js や https://github.com/getty104/ruby-wasm-vdom をよく使ってたのでその辺の影響を結構受けてると思います。

https://github.com/picoruby/funicular との違い

  • ruby.wasmとPicoRuby.wasmを両方サポートしてること
    • リポジトリには書いてないけどPicoRuby.wasmの方が機能が少ないのでPicoRuby.wasmで動けばruby.wasmでも普通に動きそうではある
  • templateに直接HTMLを書ける

https://github.com/getty104/ruby-wasm-vdom との違い

  • ruby-wasm-vdomはPicoRuby.wasmでは動かなかった(実践済)
  • ruby-wasm-vdomだとRubyのStringをそのままDOMに変換する *2 ためstateの値によってはXSSが起きる。そのため https://github.com/sue445/annict-vod-search/blob/a016c719701de32e8d9be71d6c934fb5886be707/docs/src/app.rb#L8-L14 のようなヘルパメソッドなどを作って自分で対策をする必要がある。しかしそれは普通に面倒なのでライブラリ側でXSSが起きないつくりにした
  • ruby-wasm-vdomはGitHub Pagesを直接参照するためバージョニングとかがされておらずmainブランチでbreaking changeが起きると死ぬ
    • 実はGitHub PagesにはRateLimitがある *3 のでちゃんとしたCDNが使えるならそっちの方がいい
    • 拙作のrb-wasm-vdomでは https://npmjs.com に公開してるので https://www.jsdelivr.com/ のCDNから使えるようにしてる。(jsdelivr経由で使えるようにするのはruby.wasmやPicoRuby.wasmも同じ)
  • Vue.jsの v-for や v-if みたいなレンダリングを実装( #each *4 と #if *5)

苦労点

  • 普通にRubyでプログラムを書く場合はclassやmoduleごとにファイルを分割するが、複数ファイルあるとhtmlのscriptタグで読み込む時に不便なので1つのファイルにしたい。jsであればwebpackでbundlingできるがRubyだとそうはいかないので自前でbundlingする必要があった
  • ruby.wasmとPicoRuby.wasmの微妙な実装差異によりruby.wasmだとテストが通るがPicoRuby.wasmだとテストがコケる事例が結構あった
    • PicoRuby.wasmの方にメソッドが無いことが多かった
  • ruby.wasmとPicoRuby.wasmの両方で動くテストコードを書くのが大変だった

その他近況

個人アプリでVue.jsやruby-wasm-vdom を使ってたところは全部PicoRuby.wasm + rb-wasm-vdomに移行しました。

ruby-wasm-startup-benchmarkを作った

これなに?

ruby.wasmとPicoRuby.wasmの起動時間を雑に計測するためのベンチマークツール。

PicoRuby.wasmはバイナリが小さいからruby.wasmよりも起動が早いってのはよく聞くけど実際どれくらい違うのか比較したくなったので作った。

sue445.github.io

github.com

計測結果

10回計測した時の平均と中央値は下記

ブラウザのキャッシュが効いてる状態

  • @ruby/head-wasm-wasi@latest (Ruby 4.1.0) : 平均661.8ms、中央値654.4ms
  • @picoruby/wasm-wasi@latest (Ruby 3.4) : 平均127.05ms, 中央値126.2ms

ブラウザのキャッシュが効いてない状態

  • @ruby/head-wasm-wasi@latest (Ruby 4.1.0) : 平均863.12ms、中央値890.7ms
  • @picoruby/wasm-wasi@latest (Ruby 3.4) : 平均157.46ms, 中央値155.9ms

#RubyKaigi 2026に参加した

rubykaigi.org

前置き

今年はプロポーザル落ちたので一般参加です

印象深かったトーク

The Journey of Box Building

むっちゃテックトークだったのに最後の方にえもくなってさすがキーノートだと思った

From Live Code to Sound: Building a Ruby Live Coding Engine

アリーナ映えしてよかったw

Building a Standalone Ruby Programming Environment

社内リハで発表一度聞いてはいたんだけど、まさか最後にゲームがくるとは思わなくてびっくりした。

A Faster FFI

Native extensionで関数ポインタにZJITのためのヒントを含めるテクがすごかった...

Ruby Releases Ruby

自動化話すごかった。

あとbundler v4の紹介で僕が作った機能が一瞬映って勝手にテンション上がってた

その他印象深かったエピソード

  • 僕は https://github.com/yhara/simple_twitter のメンテナもしてるんだけど、作者のyharaさんに初めて挨拶できたのがよかった。(去年もyharaさん来てたんだけど挨拶しそびれてた)
  • 他の人のトークを聞いて気持ちが高まりすぎて YAPC::Tokyo 2026 のプロポーザルを2本書いた(KaigiEffect)

terraform-version-updaterをcooldown対応した&ghrcooldownを作った

背景

昨今サプライチェーンアタックが流行っており、その対策の1つとしてcooldown(ライブラリなどで新しいバージョンが出てもすぐにバージョンアップせずに一定期間待つ)が挙げられています

拙作の https://github.com/sue445/terraform-version-updater はTerraformを最新バージョンに上げるためのツールですが、Terraformがサプライチェーンの被害に合うこともゼロではないのでcooldown対応しました。

# Update terraform to latest version with cooldown days
terraform-version-updater --cooldown-days 7

github.com

ghrcooldownについて

ghrcooldownはGitHubのReleaseからcooldownを考慮した最新バージョンを取得するためのライブラリです。(例えばRelease上ではv1.2.3が最新でも、それが自分が指定したcooldownの期間を経過していなければその1つ前のv1.2.2が返ってくる)

github.com

cooldown系の機能はterraform-version-updater内で実装しようとも考えたんですがこの手のcooldown機能はみんな実装したくなりそうなのでライブラリとして切り出しました。

使い方などはREADMEのexampleを参照

RubyKaigi 2026 Mapを作った #rubykaigi

今年も自分用にまとめました

備考

  • アイコンは各日付ごとに色分けしつつ、イベントの種類ごとにそれっぽい絵柄にしています(例:Drinkupは🍺など)
  • 日付ごとにレイヤーを分けているので、特定の日付のみ見たい場合は見たい日付以外のレイヤーを非表示にしてください
  • たまに https://rubykaigi.org/2026/events/ や https://scrapbox.io/ruby-jp/RubyKaigi_2026 を見に行って新しいイベントが登録されてたら追加するつもり。

Past Maps

sue445.hatenablog.com

sue445.hatenablog.com