くりにっき

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

34歳になった&itamaeプラグインを本気でCIする #omotesandorb

自分の誕生日である4/7に表参道.rb #10が開催ということでバースデーLTをしてきました

omotesandorb.connpass.com

例のやつ

www.amazon.co.jp

34歳になりました。もうすぐ定年ですが頑張ります ('A`)

近況

最近はプロビジョニングおじさん業やってます。 itamae, Serverspec, VagrantなどギリギリRubyやってます。

最近送ったPullRequest

vagrant-awsプラグイン(のスポットインスタンス対応版のフォーク)

Fix. Can not used iam_instance_profile options when spot_instance is enabled by sue445 · Pull Request #2 · KariusDx/vagrant-aws · GitHub

スポットインスタンス作成時にIAMロールが適用されなかったので適用されるようにした

vagrant-cloudstackプラグイン(1つ目)

Support multiple network ids by sue445 · Pull Request #148 · schubergphilis/vagrant-cloudstack · GitHub

CloudStackのAPI仕様上は複数network_idを渡せるはずなのにvagrantからだと複数のnetwork_idを渡せないので複数渡せるようにした

vagrant-cloudstackプラグイン(2つ目)

Add ssh_network_id configuration by sue445 · Pull Request #149 · schubergphilis/vagrant-cloudstack · GitHub

複数NICがある場合にeth0以外でsshしたかった

スライド版

LTで発表するためにいろいろ削ったダイジェスト版です

http://sue445.github.io/omotesandorb-10/

https://github.com/sue445/omotesandorb-10/blob/master/slides.md (スライドのソース)

完全版

スライドに書ききれなかった諸々の詳しい説明を含めた完全版です

三行まとめ

itamaeについて

itamaeプラグインについて

レシピ(ミドルウェアのインストール手順など)をgemにしてRubygems.orgで公開することができる

Gemfile

gem "itamae-plugin-recipe-git_now"

recipe.rb

include_recipe "git_now"

git-now がインストールされる

sue445製itamaeプラグイン

暗号化したファイルを転送するプラグイン

sue445.hatenablog.com

tigをビルドするプラグイン

sue445.hatenablog.com

git-nowをビルドするプラグイン

sue445.hatenablog.com

tmuxをビルドするプラグイン

sue445.hatenablog.com

単独にするまでもない雑なレシピ集(今のところdebファイルやrpmファイルをダウンロードしてインストールするレシピだけ)

github.com

itamaeプラグインのテスト事情

https://rubygems.org/search?utf8=%E2%9C%93&query=itamae-plugin

  • 47個中、テストを書いてるgemは18個 *1
    • bundle gem 直後の expect(Itamae::Plugin::Recipe::Hoge::VERSION).not_to be nil しかないやつはノーカン
  • CIしてるgemは5個(全部自分のやつw)
  • itamaeプラグインのIntegration TestのCIの知見を広めたいのが今回の主旨

CIされてることのメリット

  • 複数OSテストしたい時に動作確認が楽(開発者視点)
  • リポジトリのトップにTravis CIとかのバッジが貼ってあれば安心感がある(利用者視点)
    • 常にビルドされているという安心感
    • PR送った時にビルドの結果が出る安心感

f:id:sue445:20160404233427p:plain f:id:sue445:20160404233423p:plain

itamaeプラグインをテストする手順

  1. ローカルでVagrant + VirtualBox環境構築
  2. 自分自身を適用するレシピと、それに対するテストを書く
  3. VirtualBox内でitamaeのレシピ&Serverspec実行
  4. CIでレシピ&Serverspec実行

今回は https://github.com/sue445/itamae-plugin-recipe-git_now で説明

ローカルでVagrant + VirtualBox環境構築

からバイナリをインストール

自分自身を適用するレシピと、それに対するテストを書く

install.rb

include_recipe "git_now"

git_now_spec.rb

describe file("#{node[:git_now][:prefix]}/bin/git-now") do
  it { should be_file }
  it { should be_executable }
end

Serrverspec だとインフラの構成をrspecでテストすることができる

serverspec.org

Serverspecの中でitamaeのnodeを使う方法は下記を参考にしてください

qiita.com

VirtualBox内でitamaeのレシピ&Serverspec実行

itamae実行

f:id:sue445:20160403151948p:plain

Serverspec実行

f:id:sue445:20160403152005p:plain

Vagrantfile

https://github.com/sue445/itamae-plugin-recipe-git_now/blob/v0.1.1/Vagrantfile

Rakefile

itamaeやServerspecの実行はRakefileに集約しておくとCIに落としこむ時に楽です

https://github.com/sue445/itamae-plugin-recipe-git_now/blob/v0.1.1/Rakefile

taskを動的生成してますが rake -T するとこんな感じ

rake itamae:centos70  # Running itamae to centos70
rake itamae:debian8   # Running itamae to debian8
rake spec:centos70    # Run RSpec code examples
rake spec:debian8     # Run RSpec code examples

Rakefile中の

HOSTS = %w(centos70 debian8)

はVagrantfileで使ってるVMに対応しています

https://github.com/sue445/itamae-plugin-recipe-git_now/blob/v0.1.1/Vagrantfile#L25-L41

DigitalOcean

  • 海外の格安VPS
  • 最低プランなら1時間で$0.007から使える
    • 1ドル113円なら0.79円
    • $10のクーポンコードもあるので1428時間は無料で使える
    • https://m.do.co/c/7978f6d6167e から登録してもらえると$10もらえて、$25課金した時に僕も$25もらえます (チラチラッ
  • 全部SSDなので速い
  • ビルドする時だけインスタンスを立ち上げれば費用を抑えることができる

DigitalOceanの設定

Access Tokenの生成

API -> Your Tokens -> Generate New Tokenよりアクセストークンを生成

f:id:sue445:20160331020544p:plain

f:id:sue445:20160331020436p:plain

表示されたトークンは後で使うのでブラウザのタブはそのままにしておく

Wercker

wercker-box-rvm-vagrant-digitalocean

https://github.com/sue445/wercker-box-rvm-vagrant-digitalocean

wercker-box-rvm-vagrant-aws をforkしてrvmとvagrantvagrant-digitaloceanプラグインをインストール済のboxを作った

使い方

wercker.yml

box: sue445/rvm-vagrant-digitalocean@1.0.0

Werckerの設定

Classicにする

Infrastructure stackでClassicを選択 *3

f:id:sue445:20160331020050p:plain

ssh keyの生成

Settings -> SSH keysからDigitalOcean用の鍵を作成 f:id:sue445:20160331015634p:plain

Generateを押すと鍵が生成される f:id:sue445:20160331015818p:plain

Environment variablesの登録

Settings -> Environment variables から環境変数を登録

f:id:sue445:20160331020941p:plain

  • DIGITALOCEAN_ACCESS_TOKEN:さっき作ったDigitalOceanのアクセストークンを入力し、Protectedにチェックを入れる
    • Protectedにチェックが入っていればビルドのコンソールにも出てこなくなる
  • DIGITALOCEAN_KEY:さっき作ったsshの鍵を選択
    • werckerのビルドからは DIGITALOCEAN_KEY_PUBLIC, DIGITALOCEAN_KEY_PRIVATE のような変数で参照できる

wercker.yml(直列実行版)

https://github.com/sue445/itamae-plugin-recipe-git_now/blob/575ef249811ceaeba5d80ecde830c30cea46395c/wercker.yml

wercker.ymlをかいつまんで説明すると

Rubyの設定
        - rvm-use:
            version: 2.3.0

        - script:
            name: install bundler
            code: gem install bundler -v 1.10.6 --no-document

        - bundle-install:
            jobs: 4

bundlerのバージョンが1.10.6なのは、Vagrant *4がbundler 1.11系に対応していないため

https://github.com/mitchellh/vagrant/blob/v1.8.1/vagrant.gemspec#L18

WerckerからDigitalOceanに接続するための設定

上の方で生成した秘密鍵と公開鍵を設置

        - script:
            name: create .ssh directory
            code: mkdir -m 700 -p $HOME/.ssh

        - create-file:
            name: put private key
            filename: $HOME/.ssh/id_rsa.vagrant
            overwrite: true
            hide-from-log: true
            content: $DIGITALOCEAN_KEY_PRIVATE

        - create-file:
            name: put public key
            filename: $HOME/.ssh/id_rsa.vagrant.pub
            overwrite: true
            hide-from-log: true
            content: $DIGITALOCEAN_KEY_PUBLIC

        - script:
            name: chmod 600 id_rsa
            code: chmod 600 $HOME/.ssh/id_rsa.vagrant
ビルド実行
        - script:
            name: test centos70
            code: ./ci/build.sh centos70

        - script:
            name: test debian8
            code: ./ci/build.sh debian8

centos70 -> debian8の順でビルド

build.sh

上の方でRakefileに集約したおかげでビルドスクリプトはシンプルになっています

#!/bin/bash -xe

readonly HOST=$1

vagrant up $HOST --provider=digital_ocean
bundle exec rake itamae:$HOST
bundle exec rake spec:$HOST
vagrant destroy -f $HOST

実はこれだとテストが失敗した時にVMが残り続けるという不具合がありますが後で解決します。(シェルスクリプトの中でエラーハンドリングしてもいいんだけどエラーコードを全部チェックする必要があるのでコードが冗長になる)

ビルドの並列実行

直列実行だと遅い(2つ合わせて5分くらいかかる)ので並列実行できるようにした

Paraduct

  • Paraduct (parallel + parameterize + product)
  • .travis.ymlみたいな感じにいい感じにマトリックステストをするためのgem
  • 2年前に作ったgemなんだけどいろいろ書き直した
    • v0.0.3 -> v1.0.0

詳しい説明

sue445.hatenablog.com

sue445.hatenablog.com

上のエントリだとビルドごとにディレクトリ作ってrsyncするようになってますが、v1.0.0ではrsyncは任意になってます *5

.paraduct.yml

script: |-
  ./ci/build.sh ${HOST}
after_script: |-
  vagrant destroy -f $HOST
variables:
  HOST:
    - debian8
    - centos70
max_threads: 4
  • この例だと ./ci/build.sh debian8./ci/build.sh centos70 が並列に実行される
  • after_script はビルドが失敗時しても必ず実行されるので確実にVMをdestroyしてくれる

その他の特徴

capistranoみたいにホストごとに色がつくのが特徴

f:id:sue445:20160403160203p:plain

https://app.wercker.com/#buildstep/56f46fa951d1ad950a01ad71

CIで使う時

基本的にはビルドスクリプト

gem install paraduct
paraduct test

みたいな処理を書くと思いますが、RubyのプロダクトであればGemfileに

gem "paraduct"

を書いて

bundle exec paraduct test

することでCIサービス側で提供されているbundlerのキャッシュ機能*6を使うことができ、ビルド時間を短縮することができます

小ネタ

参考文献

オライリーのServerspec本にDIgitalOceanやWercker周りの説明が載ってる

www.oreilly.co.jp

itamaeやServerspecの wercker.ymlVagrantfile を熟読した

付録

どうしてTravisCI じゃないのか?

こういうパラメータごとの並列ビルドだとWerckerよりも Travis CIが断然便利なのですが、あえて使わなかった理由は2つあります

  • 有料版の https://travis-ci.com/ だと秘密鍵に対応してるが、無料版の https://travis-ci.org/ だと対応していない *7
    • 管理画面から暗号化したいパラメータを入れる仕組みはあるが、複数行に対応してない
    • 秘密鍵の暗号化してリポジトリに含めつつ(暗号化した時のキーだけ管理画面で保存)暗号化や復号化を自前で頑張ればtravis-ci.org でもたぶんできるんだけど、ビルドスクリプトが複雑になりそうだった
  • Travis CI にはVagrantはインストールされていないのでもし使うとするとビルド中にVagrantVagrantプラグインをインストールする必要があり、その分ビルドに時間がかかる
    • 仮にVagrantのインストールのためにsudoを使おうとすると(.travis.yml で sudo: true を書くと)、コンテナベースの環境を使えないのが痛い。*8
    • 非コンテナは古い形式なので全体的にパフォーマンスが悪い(git pushしてからビルド始まるまでに10分以上かかることもある)
    • 何より非コンテナはbundlerなどのcacheが使えない *9

DigitalOcean vs EC2スポットインスタンス

安いので有名なのはEC2のスポットインスタンスですが、同じくらいの価格帯でスペックを比較してみました *10

DigitalOcean ($ 0.015 / hr) EC2 m1.small ($ 0.01くらい)
Memory 1 GB 1.7 GB
CPU 1 Core 1 Core
Disk 30 GB 160 GB

公式ドキュメント

他のプランだといい感じに値段が同じくらいのがなくて1つずつしか比較できなくて申し訳ないですが、ざっと見た感じ同じくらいの値段ならスポットインスタンスの方がスペックはよかったです

難点は vagrant-awsプラグイン がスポットインスタンスに正式対応してないこと

issueには上がってる

github.com

それでもVagrantからスポットインスタンスを使う方法

さっきのissueで紹介されてるfork版のブランチを使う https://github.com/mitchellh/vagrant-aws/issues/32#issuecomment-163228219

github.com

ググるプラグインを自分でbuildしろみたいなやつが結構ヒットしますが、CIも考慮すると面倒なので自分は素直にGemfileに書いてます

source "https://rubygems.org"

group :development do
  gem "vagrant", github: "mitchellh/vagrant", tag: "v1.8.1"
end

group :plugins do
  # AWSのAPI keyをVagrantfileに環境変数で埋め込んでいるため
  gem "dotenv"
  gem "vagrant-aws", github: "KariusDx/vagrant-aws", branch: "spot"
end

Gemfileに書いてるとvagrantプラグインをforkしてPullRequestする時にも自分のトピックブランチを使えるメリットもあります。(冒頭のPullRequest出してるブランチもGemfileに書いてる)

実行する時

bundle exec vagrant up --provider=aws

最後に

今期のプリキュアRubyがテーマなのでRubyistはみんな見るべき

youtu.be

「魔法つかいプリキュア」なのにRubyスタイルでパワー強化なのはRubyistのマサカリの鋭さの現れか(考えすぎ)

重要なのでもう一度例のやつ

www.amazon.co.jp

*1:2016年4月時点

*2:ただしUnit TestのみCI

*3:wercker-box-rvm-vagrant-digitaloceanはClassicしか対応していないため。Dockerfileでもよかったんだけど強いこだわりはなかったのでサクッといける方を選択(あとitamaeやserverspecがClassic使ってたので準拠)

*4:1.8.1時点

*5:具体的には .paraduct.yml の work_dir を空にすればカレントディレクトリで実行するのでrsyncもしない

*6:TravisCI, Wercker, CircleCIでは使えるのを確認

*7:https://docs.travis-ci.com/user/private-dependencies/ の「Custom SSH keys are currently only available for private repositories on travis-ci.com.」より

*8:https://docs.travis-ci.com/user/workers/container-based-infrastructure/#Routing-your-build-to-container-based-infrastructure

*9:https://docs.travis-ci.com/user/caching/

*10:EC2は東京リージョンでスポットインスタンスの価格は4/7時点のもの

ZusaarがなくなってもAZusaar!!はなくなりません

表題通りです

サービス終了のお知らせ|参加費の決済もできるイベント開催支援サービス「Zusaar」

Zusaarサービス終了の報を受けてなぜか AZusaar!! も心配されていたのでアナウンスさせていただきます

心配の声

5年前に作って大して更新もしてないサービスに対してこんなに心配してくださるなんてありがたいことです

以下ポエム

AZusaar!!は名前で分かる通り元々はイベント登録サイトの二強の「ATND」と「Zusaar」を一緒に検索するために作ったもので、ZusaarがなければAZusaar!!もなかったし、MashupAwardで入賞することもなかったし、ひいては今の会社に転職もできなかったと思うので*1いろいろと感慨深いものがあります。。。

*1:転職活動の時に自作アプリがMashupAwardで入賞したことを結構アピールしたと思うw

「GitHubのPull Requestを簡単にチェックアウトするたった1つの方法」のaliasを作った

元ネタ

sinsoku.hatenablog.com

便利なんですがコマンド長すぎて覚えられないのでaliasにしました

.gitconfig

[alias]
  fpr = "!f() { git fetch origin pull/$1/head:pr/$1; }; f"

コマンド名が気になる人は適宜変えてください

使い方

git fpr <PullRequest ID>

pr/<PullRequest ID> にbranchが作られます

使った図

[sueyoshi_go@YG41-08546.local] ✓ ~/workspace/github.com/sue445/chrome-gitlab-notifier (master)
[sueyoshi_go@YG41-08546.local] [03-31 16:01:18] $ g fpr 83
remote: Counting objects: 14, done.
remote: Compressing objects: 100% (14/14), done.
remote: Total 14 (delta 4), reused 0 (delta 0), pack-reused 0
Unpacking objects: 100% (14/14), done.
From github.com:sue445/chrome-gitlab-notifier
 * [new ref]         refs/pull/83/head -> pr/83

[sueyoshi_go@YG41-08546.local] ✓ ~/workspace/github.com/sue445/chrome-gitlab-notifier (master)
[sueyoshi_go@YG41-08546.local] [03-31 16:02:18] $ g co pr/83
Switched to branch 'pr/83'

[sueyoshi_go@YG41-08546.local] ✓ ~/workspace/github.com/sue445/chrome-gitlab-notifier (pr/83)
[sueyoshi_go@YG41-08546.local] [03-31 16:02:46] $

【おまけ】.gitconfig の aliasで登録したコマンドから引数を取得する方法

直接 $1 って書くとうまく動かなかったので調べたら関数の中に入れる必要があるっぽい

stackoverflow.com

プリキュアオールスターズを見たのでrubicureでキュアエコー対応した

こんにちは、映画プリキュアオールスターズ みんなで歌う♪奇跡の魔法! の映画公開2日目ですが既に2回見てきました。

www.precure-allstars.com

いろいろ思うところがあってキュアエコー対応を行いました

github.com

きっかけ

prehyou2015.hatenablog.com

プリキュアの数字ブログさんの

2016年3月現在では

「44人のプリキュアがいる」

というのが教科書的な答えです。

を読んでrubicureも対応しないといけないような使命感に駆られて対応しました

使い方

Cure.echo

いつものように Cure.echo でキュアエコーのインスタンスを取得できます

echo = Cure.echo

echo.name
# => "坂上あゆみ"

echo.transform!
みんなの思いを守るために
心をひとつに!
思いよ届け!キュアエコー!

# 変身後なので名前が変わる
echo.name
# => "キュアエコー"

echo.attack!
世界に響け、みんなの思い!
プリキュア・ハートフルエコー!

Precure.all_stars

通常はプリキュアオールスターズは43人です

Precure.all_stars.count
# => 43

キュアエコーは特定の映画 *1の中だけに登場するので、Precure.all_stars の引数にその映画の名前を渡せばカウントすることができます

Precure.all_stars(:sing_together_miracle_magic).count
# => 44
Precure.all_stars(:sing_together_miracle_magic).include?(Cure.echo)
# => true

ちなみに :sing_together_miracle_magic は、公式略称のSTMMから推測したものなので間違ってたら直します。。。

他に :new_stage:new_stage3でもキュアエコーは取得できます

Precure.all_stars(:new_stage).count
# => 29
Precure.all_stars(:new_stage).include?(Cure.echo)
# => true

Precure.all_stars(:new_stage3).count
# => 37
Precure.all_stars(:new_stage3).include?(Cure.echo)
# => true

Precure.all_stars の引数に渡せる映画の名称はいろいろエイリアスがあるので詳細はソースを読んでください

https://github.com/sue445/rubicure/blob/v0.4.3/config/movies.yml

映画感想

ネタバレにならない程度に

*1:オールスターズNewStage みらいのともだち、オールスターズNewStage3 永遠のともだち、オールスターズみんなで歌う♪奇跡の魔法!

rubicure v0.4.0をリリースしました

魔法つかいプリキュア! 対応です

github.com

まほプリの仕様上今までとちょっと使い方が変わってるので注意してください

今までのプリキュア

yayoi = Cure.peace

yayoi.name
#=> "黄瀬やよい"

yayoi.cast_name
#=> "金元寿子"

yayoi.attack!
#=> RuntimeError: require transform


yayoi.transform!

(レディ?)
プリキュア・スマイルチャージ!
(ゴー!ゴー!レッツ・ゴー!ピース!!)
ピカピカピカリンジャンケンポン! キュアピース!
5つの光が導く未来!
輝け!スマイルプリキュア!

# 1st transform
yayoi.name
#=> "キュアピース"

yayoi.attack!

プリキュア!ピースサンダー!!

魔法つかいプリキュア

各種スタイルに対応すべく、Rubicure::Girl#transform! に引数を渡せるようになっています

ダイヤスタイルに変身する時

mirai = Cure.miracle

mirai.name
# => "朝日奈みらい"

mirai.cure_up_rapapa! :diamond
# or
mirai.transform! :diamond

キュアップ・ラパパ! ダイヤ!
ミラクル・マジカル・ジュエリーレ!
ふたりの奇跡!キュアミラクル!
魔法つかいプリキュア!!

mirai.name
# => "キュアミラクル(ダイヤスタイル)"

mirai.attack!
リンクルステッキ!
ダイヤ!永遠の輝きを私達の手に!
フルフルリンクル!
プリキュア!ダイヤモンドエターナル!

Ruby ルビースタイルに変身する時

mirai = Cure.miracle

mirai.name
# => "朝日奈みらい"

mirai.cure_up_rapapa! :ruby
# or
mirai.transform! :ruby

キュアップ・ラパパ! ルビー!
ミラクル・マジカル・ジュエリーレ!
ふたりの奇跡!キュアミラクル!
魔法つかいプリキュア!!

mirai.name
# => "キュアミラクル(ルビースタイル)"

mirai.attack!
リンクルステッキ!
ルビー!紅の情熱よ私達の手に!
フルフルリンクル!
プリキュア!ルビーパッショナーレ!

Splash☆Star の Cure.bloomCure.bright みたいにそれぞれのスタイルを別名で定義というのは今までもありましたが、同名で複数のスタイルを対応というのが今回の一番の目玉です!

それではよいキュアエンジニアライフを

追伸

yamlのデータ構造がつらくなってきた・・・

https://github.com/sue445/rubicure/blob/v0.4.0/config/girls/013_maho_girls.yml

heroku-buildpack-rroonga で突然エラーが出た時の対処法

忙しい人のためのまとめ

heroku-buildpack-rroongaの設定が変わってた

経緯

Tachikoma.io を使って Sebastian-badge.info を毎週 bundle update しているのですが、2/21のビルドは問題なかったのに2/28のビルド以降Circle CIの自動デプロイに失敗するという事象がありました。

remote: -----> Fetching set buildpack https://github.com/groonga/heroku-buildpack-rroonga... done
remote: -----> Rroonga app detected
remote: -----> Initializing database
remote: bundle exec ruby groonga/init.rb
remote: /app/vendor/bundle/ruby/2.3.0/gems/bundler-1.9.7/lib/bundler/spec_set.rb:92:in `block in materialize': Could not find rake-10.5.0 in any of the sources (Bundler::GemNotFound)
remote:     from /app/vendor/bundle/ruby/2.3.0/gems/bundler-1.9.7/lib/bundler/spec_set.rb:85:in `map!'
remote:     from /app/vendor/bundle/ruby/2.3.0/gems/bundler-1.9.7/lib/bundler/spec_set.rb:85:in `materialize'
remote:     from /app/vendor/bundle/ruby/2.3.0/gems/bundler-1.9.7/lib/bundler/definition.rb:132:in `specs'
remote:     from /app/vendor/bundle/ruby/2.3.0/gems/bundler-1.9.7/lib/bundler/definition.rb:177:in `specs_for'
remote:     from /app/vendor/bundle/ruby/2.3.0/gems/bundler-1.9.7/lib/bundler/definition.rb:166:in `requested_specs'
remote:     from /app/vendor/bundle/ruby/2.3.0/gems/bundler-1.9.7/lib/bundler/environment.rb:18:in `requested_specs'
remote:     from /app/vendor/bundle/ruby/2.3.0/gems/bundler-1.9.7/lib/bundler/runtime.rb:13:in `setup'
remote:     from /app/vendor/bundle/ruby/2.3.0/gems/bundler-1.9.7/lib/bundler.rb:122:in `setup'
remote:     from /app/vendor/bundle/ruby/2.3.0/gems/bundler-1.9.7/lib/bundler/setup.rb:18:in `<top (required)>'
remote:     from /app/vendor/ruby-2.3.0/lib/ruby/2.3.0/rubygems/core_ext/kernel_require.rb:55:in `require'
remote:     from /app/vendor/ruby-2.3.0/lib/ruby/2.3.0/rubygems/core_ext/kernel_require.rb:55:in `require'
remote: 
remote:  !     Push rejected, failed to compile Rroonga app

https://circleci.com/gh/sue445/sebastian-badge/269

bundle install されてないだと・・・!?

いろいろ調べてたら2/23に入ってた heroku-buildpack-rroonga の変更が原因でした

https://github.com/groonga/heroku-buildpack-rroonga/commit/11af6d1bb0bf83210b7ca9129e171fd04c5b5158

対処法

Circle CIを使ってるので circle.ymlの修正を載せますが他のCIでもやることはだいたい同じだと思います

修正前

deployment:
  production:
    commands:
      - heroku config:add BUILDPACK_URL="https://github.com/groonga/heroku-buildpack-rroonga" --app $HEROKU_APP_NAME

https://github.com/sue445/sebastian-badge/blob/aaf35ea8c02a99d57fbc18fe7ef49097258084d5/circle.yml#L37

修正後

READMEの通りにbuildpackを設定しなおしてやるだけ

deployment:
  production:
    commands:
      - heroku buildpacks:add https://codon-buildpacks.s3.amazonaws.com/buildpacks/groonga/groonga.tgz --app $HEROKU_APP_NAME || true
      - heroku buildpacks:add heroku/ruby --app $HEROKU_APP_NAME || true
      - heroku buildpacks:add https://codon-buildpacks.s3.amazonaws.com/buildpacks/groonga/rroonga.tgz --app $HEROKU_APP_NAME || true

https://github.com/sue445/sebastian-badge/blob/040eb9a298ce06cf2648ccd1d8f2bdeea1ed6ccf/circle.yml#L37-L39

heroku buildpack:add 〜" の後に || trueをつけているのは、既にbuildpack追加済みの状態でbuildpacks:add` するとステータスコード1になりデプロイが途中で止まるのを回避するため。

heroku buildpacks:add https://codon-buildpacks.s3.amazonaws.com/buildpacks/groonga/groonga.tgz --app $HEROKU_APP_NAME
 ▸    The buildpack
 ▸    https://codon-buildpacks.s3.amazonaws.com/buildpacks/groonga/groonga.tgz

heroku buildpacks:add https://codon-buildpacks.s3.amazonaws.com/buildpacks/groonga/groonga.tgz --app $HEROKU_APP_NAME returned exit code 1

▸ is already set on your app. Action failed: heroku buildpacks:add https://codon-buildpacks.s3.amazonaws.com/buildpacks/groonga/groonga.tgz --app $HEROKU_APP_NAME

https://circleci.com/gh/sue445/sebastian-badge/271