最近ngx_mrubyを触っていて、RubyのTime#httpdateを使いたかったもののmrubyにはないということがあった。
そもそもmruby自体にも全然慣れていないという課題もあったので、このメソッドを実装することを目標にライブラリを作りながらmrubyに慣れるということをやってみた。
mrubyをビルドする
ビルド手順は非常に簡単で、mrubyのリポジトリをcloneしてmakeするだけで良い。
git clone https://github.com/mruby/mruby.git
cd mruby
make
bin/
ディレクトリ以下にいくつか実行ファイルが作られて試すことが出来て、irbのmruby版であるmirbというものも使うことが出来る。
~/c/s/g/m/mruby ❯❯❯ bin/mirb
mirb - Embeddable Interactive Ruby Shell
> p Time.now
2020-10-20 22:30:13 +0900
=> 2020-10-20 22:30:13 +0900
>
ライブラリの作り方
これで最低限mrubyを使う準備はできたので、次はライブラリを作っていく。
mrubyのライブラリはmrbgem(mgem)と呼ばれており、 mrbgem.rake
や mrblib/
など決まったファイル・ディレクトリ構造に従ってファイルを作成していくというものになっている。
~/c/s/g/c/mruby-time-library ❯❯❯ tree
.
├── LICENSE
├── README.md
├── mrbgem.rake
├── mrblib
│ └── mrb_time_library.rb
└── test
└── mrb_time_library.rb
2 directories, 5 files
実装がある程度できたら動くかどうかテストをする準備をしていく。
テストの実行は少し特殊で、ライブラリのリポジトリではなくmrubyのリポジトリに以下のような build_config.rb
というファイルを作成する。
conf.gemには作成しているライブラリのパスを指定する。
MRuby::Build.new do |conf|
toolchain :gcc
conf.gembox 'default'
conf.gem '../mruby-time-library'
conf.enable_test
end
そしてmrubyのリポジトリで rake test
を実行することでライブラリのテストを走らせることが出来る。
そうすれば「ライブラリの実装とテストを修正し続けて rake test
を実行する」というサイクルで開発をすすめることができる。
GitHub ActionsでCIする
手元環境の準備が整ったので、今度はリポジトリ上でCIできるようにする。
mrubyのライブラリはTravis CIを使っていることも多いけれど、せっかくなのでGitHub Actionsでやれるようにした。
CIでやる場合もmrubyのリポジトリでbuild_config.rbを使って指定するというのは変わらずだけど、手元のパスではなくGitHub上のリポジトリとブランチを指定するのでそこを工夫して書き換える必要がある。
ただし、ActionsのトリガーではブランチへのコミットとPRとでは作業ブランチの取得方法が微妙に異なるのでビルド前にいい感じにブランチ名を取っておくというのも必要。
- name: get branch name
if: github.event_name != 'pull_request'
run: echo "BRANCH_NAME=$(echo ${GITHUB_REF#refs/heads/})" >> $GITHUB_ENV
- name: get pull request branch name
if: github.event_name == 'pull_request'
run: echo "BRANCH_NAME=$(echo $GITHUB_HEAD_REF)" >> $GITHUB_ENV
この BRANCH_NAME
を使ってbuild_config.rbを作ってrake testをしてやれば良い。
- name: Rake test
env:
TEMPLATE: |
MRuby::Build.new do |conf|
toolchain :gcc
enable_debug
conf.enable_bintest
conf.enable_test
conf.gembox 'default'
conf.gem :github => '${{ github.repository }}', :branch => '${BRANCH_NAME}'
end
run: |
printf "${TEMPLATE}" > build_config.rb
cd mruby
env MRUBY_CONFIG=../build_config.rb rake test
そうして完成したワークフローは以下。
https://github.com/cohalz/mruby-time-library/blob/master/.github/workflows/test.yml
ライブラリを作った
以上で、httpdateを含むtimeライブラリの特定のフォーマットの文字列にするメソッド(インスタンスメソッド)を使えるようにするライブラリを作成できた。
github.com
~/c/s/g/m/mruby ❯❯❯ bin/mirb
mirb - Embeddable Interactive Ruby Shell
> Time.now.httpdate
=> "Tue, 20 Oct 2020 14:44:03 GMT"
>
文字列をパースするメソッドに関しては、mrubyにはデフォルトでは正規表現が使えないというのもあり実装を後回しにしているけど、既に欲しくなってきたので近いうちに作りたい。