くりにっき

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

gitlabci-bundle-update-mr v0.3.0をリリースした

gitlab.com

changelog

https://gitlab.com/sue445/gitlabci-bundle-update-mr/blob/master/CHANGELOG.md#v030

v0.3.0の新機能

GitLab CIが他のCIと比べて優れてる機能の1つにMerge when pipeline succeeds(CIが通ったら自動でMergeRequestをマージする)があるのですが、gitlabci-bundle-update-mrでも対応しました

f:id:sue445:20190504202355p:plain

bundle updateのMRは作りたいけど各gemのchangelogを読むまでもないような雑なアプリの場合だといちいちAcceptボタンをポチるのも面倒だと思うので、API経由でMerge when pipeline succeedsを有効にするようにしました

gitlabci-bundle-update-mr --merge-when-pipeline-succeeds

のように --merge-when-pipeline-succeeds を渡すことで有効になります。(デフォルトだとOFF)

rubicure APIを止めた

あけましておめ令和(挨拶)

https://rubicure.herokuapp.com/ で動いていたrubicure APIですが、3月くらいから毎分のようにDDosがきていてFree Dyno hoursを圧迫してたので止めました。

リポジトリは残してるので使いたい人はDeploy to Herokuで自分のアカウントで動かしてください https://github.com/sue445/rubicure_api

あと、プリキュア誕生日icalだけGitHub Pagesに作り直した(といっても https://sue445.github.io/pretty-all-friends-birthday-calendar/ のほぼコピペだけど)のでicalがほしい人はこちらをお使いください。

sue445.github.io

Rails 5.2.2.1にしたらErrno::ENOENT: No such file or directoryのエラーになった

Railsのsecurity fixが出ました

weblog.rubyonrails.org

個人アプリ2つアップデートしたんですが、どっちもRails 5.2.2だし余裕だろうと思ったら片方だけ下記のようなエラーになってちょっとハマったのでメモ。

+ ./bin/rails db:create

(snip)

Errno::ENOENT: No such file or directory @ rb_sysopen - /home/circleci/app/tmp/development_secret.txt
/home/circleci/app/vendor/bundle/ruby/2.6.0/gems/railties-5.2.2.1/lib/rails/application.rb:597:in `binwrite'
/home/circleci/app/vendor/bundle/ruby/2.6.0/gems/railties-5.2.2.1/lib/rails/application.rb:597:in `generate_development_secret'
/home/circleci/app/vendor/bundle/ruby/2.6.0/gems/railties-5.2.2.1/lib/rails/application.rb:430:in `secret_key_base'
/home/circleci/app/vendor/bundle/ruby/2.6.0/gems/devise-4.6.1/lib/devise/secret_key_finder.rb:24:in `key_exists?'
/home/circleci/app/vendor/bundle/ruby/2.6.0/gems/devise-4.6.1/lib/devise/secret_key_finder.rb:16:in `find'
/home/circleci/app/vendor/bundle/ruby/2.6.0/gems/devise-4.6.1/lib/devise/rails.rb:37:in `block in <class:Engine>'
/home/circleci/app/vendor/bundle/ruby/2.6.0/gems/railties-5.2.2.1/lib/rails/initializable.rb:32:in `instance_exec'
/home/circleci/app/vendor/bundle/ruby/2.6.0/gems/railties-5.2.2.1/lib/rails/initializable.rb:32:in `run'
/home/circleci/app/vendor/bundle/ruby/2.6.0/gems/railties-5.2.2.1/lib/rails/initializable.rb:61:in `block in run_initializers'
/home/circleci/app/vendor/bundle/ruby/2.6.0/gems/railties-5.2.2.1/lib/rails/initializable.rb:60:in `run_initializers'
/home/circleci/app/vendor/bundle/ruby/2.6.0/gems/railties-5.2.2.1/lib/rails/application.rb:361:in `initialize!'
/home/circleci/app/config/environment.rb:5:in `<top (required)>'

原因

tmp/ がコミットされていなくて tmp/development_secret.txt の作成に失敗してた

今回CIがコケたアプリはRails 4.1系からupdateしてたので tmp/.keep の追従忘れてたんだろうなあと納得

対応内容

tmp/ を作ってコミットしただけ

mkdir -p tmp
touch tmp/.keep
git add -f tmp/.keep
git commit -am "Add tmp/"

Dependabotの設定ファイルを置くようにした

なにげなくDependabotを見てたらリポジトリ.dependabot/config.yml を置けることを気づいたので置いてみた

https://dependabot.com/docs/config-file/

ちなみに .dependabot/config.yml をコミットしてると設定画面でこんな表示になります

f:id:sue445:20190310145727p:plain

設定ファイルを置くメリット

  • 新しくリポジトリを作ってDependabotを導入する時にボタンをポチらずに済む
    • リポジトリから設定ファイルをコピーしてくればいつもの設定が導入できる
  • 設定をgitで履歴管理

いつも使ってる設定晒し

Rubyだとこれでだいたいいいはずですが他言語だと微妙に変えた方がいいかもしれないです。

# c.f. https://dependabot.com/docs/config-file/
version: 1

update_configs:
  - package_manager: "ruby:bundler"

    directory: "/"

    update_schedule: "daily"

    default_assignees:
      - sue445

    allowed_updates:
      - match:
          # Disable. Only top-level dependencies (and security patches for subdependencies)
          update_type: "all"

    automerged_updates:
      - match:
          dependency_type: "development"
          update_type: "all"
      - match:
          dependency_type: "production"
          update_type: "semver:patch"

    # Enable. Only lockfile updates (ignore updates that require Gemfile changes)
    version_requirement_updates: "off"

解説

default_assignees

PRが作られた時に誰をassignさせるか。

PRを見た後にchangelogを見に行ったりしてると実際にマージするのをちょいちょい忘れるので自分をassignしておくと便利

allowed_updates

設定画面の「Only top-level dependencies (and security patches for subdependencies)」に相当。

f:id:sue445:20190310150258p:plain

デフォルトだとこれに入っているんですが、そうするとGemfileに直接書かれてるgemしかbundle updateの対象にならなくて、gemの依存の依存のgemがupdateされないのでいつもこのチェックを外すようにしてます。

設定ファイルだと update_type: "all" を書けば同じ効果になります

automerged_updates

設定画面のAutomatic PR mergingに相当

f:id:sue445:20190310150517p:plain

個々の好みが分かれるところですが、僕は普段development dependencyのアップデートは全部自動マージして、runtime dependencyはパッチバージョンのアップデートのみ自動マージ(マイナーバージョンアップは手動)にしてます

version_requirement_updates

設定画面の「Only lockfile updates (ignore updates that require Gemfile changes)」に相当

f:id:sue445:20190310150832p:plain

デフォルトだとチェックが外れているんですが、そうすると Gemfile でバージョン固定していた場合にGemfileを書き換えてbundle updateするので、これにチェック入れとくことで Gemfile.lock のみ更新かけるようにしてます。

Gemfile でバージョン固定しているのはだいたいなんらかの理由があるはずなので書き換えられるのは困る)

設定ファイルだと version_requirement_updates: "off" に相当。

まとめ

ローカルで bundle update した時と同じ挙動にしたければ allowed_updatesversion_requirement_updates を書いとけばいいかと。

gitlabci-bundle-update-mrを作った

gitlab.com

rubygems.org

経緯

試験勉強を始めるとついつい部屋の掃除をしちゃいますよね?

(訳:RubyKaigiの資料の現実逃避で全く関係ないgemを作った)

どんなgem ?

名前からピンときた人もいるかもしれませんが、CircleCIで bundle update のPRを作る circleci-bundle-update-pr のGitLab版です。

f:id:sue445:20190307230836p:plain

使い方

0. 事前準備

READMEを参考に GITLAB_API_ENDPOINTGITLAB_API_PRIVATE_TOKENOCTOKIT_ACCESS_TOKEN をEnvironment variablesに設定します

f:id:sue445:20190307231509p:plain

1-A. .gitlab-ci.ymlに直接書く

.gitlab-ci.yml に下記のようなものを書きます

stages:
  - build

continuous_bundle_update:
  stage: build

  image: ruby

  cache:
    key: "$CI_BUILD_NAME"
    paths:
      - vendor/bundle/

  before_script:
    # Set timezone to Asia/Tokyo
    - cp /usr/share/zoneinfo/Asia/Tokyo /etc/localtime

  script:
    - bundle install --path vendor/bundle
    - bundle clean
    - gem install --no-doc gitlabci-bundle-update-mr
    - gitlabci-bundle-update-mr --user="GitLab CI" --email="gitlabci@example.com" --labels="bundle update"

  only:
    - schedules

1-B

GitLab v11.4でinclude *1がCoreに入ったので、せっかくの機会なのでincludeに対応しました。

その場合は下記のような書き方です。

include:
  - remote: "https://gitlab.com/sue445/gitlabci-bundle-update-mr/blob/master/gitlabci-templates/continuous_bundle_update.yml"

continuous_bundle_update:
  stage: build

  variables:
    # override variables (followings are defailts)
    CACHE_VERSION: "v1"
    GIT_EMAIL:     "gitlabci@example.com"
    GIT_USER:      "GitLab CI"
    LABELS:        "bundle update"
    OPTIONS:       ""

  before_script:
    # Set timezone to Asia/Tokyo
    - cp /usr/share/zoneinfo/Asia/Tokyo /etc/localtime

さっきと違って変数の上書きを除けばちょっと短くなるのがポイントです。

2. スケジューラに登録する

GitLab CIでscheduler(cronのように定期実行する機能)を使うにはymlではなくリポジトリの設定から登録する必要があります

f:id:sue445:20190307231334p:plain

今回のgemを作るにあたって

アップデートされたgemのcompareリンクを生成する部分は前述のcircleci-bundle-update-pr同様 compare_linker を使っているので、circleci-bundle-update-prと同じ内容のMRが作れます。

gitlabci-bundle-update-mrで作ったMR

f:id:sue445:20190307230836p:plain

circleci-bundle-update-prで作ったPR

f:id:sue445:20190308134328p:plain

ただしgitlabci-bundle-update-mrから使おうとすると一部使いづらい部分があったので、汎用的に使えるように一部ロジックをpublicメソッドに切り出すPRを投げました。

github.com

*1:CircleCIのorbのように外部のymlを取り込めるようにする機能

pixiv TECH SALONで「スペックを上げてクラウドで殴るCI」という発表をしました #pixivTECHSALON

昨日 pixiv TECH SALON という完全招待制のイベントで「スペックを上げてクラウドで殴るCI」で発表したので、その時のスライドを公開します。

他の人たちのスライドも別途まとめて公開される予定ですが、いったん自分の分だけ先に出します。

おまけ:発表中の様子

togetter.com

git-updateがクソ便利

git-syncインスパイヤされて作りました

qiita.com

ソースコード

gist.github.com

モチベーション

例えばトピックブランチで作業してて、リポジトリのmasterが更新されたから最新のmasterを取り込んでrebaseするってことよくやると思うのですが、その時にいちいち

git checkout master
git pull --ff
git checkout topic_branch
git rebase master

みたいなことをやるのが大変なのでサブコマンドにしました。 *1

3ヶ月くらい使ってるけど割と開発が捗ってます。

~/.gitconfig のaliasにも up = update で登録してるので、1時間に1回くらいは g up 叩いてるんじゃないかなw

https://github.com/sue445/dotfiles/blob/65468baf32e391a78216018942bc4a158024e7af/_gitconfig#L57

おまけ:dotfilesでオレオレgitサブコマンドを運用する方法

自分のdotfilesに bin/ を置いて、そこにPATHを通して使っています

設定はこんな感じ

https://github.com/sue445/dotfiles/blob/65468baf32e391a78216018942bc4a158024e7af/_bashrc#L113-L114

2019/3/4追記

ブコメで色々突っ込まれてたので追記

id:manaten

git pull --rebase origin master でよさそうな気がするのだけど、違いはどこだろ

id:ramen31

git pull --rebase origin masterでいいのでは?

普段 pull --rebase は使ってないから完全に頭から抜けてたw

挙動的にはこれでいいんだけど、ローカルのmasterやorigin/masterが更新されなくてどこからブランチ伸びてるか分かりづらかったので使うのを以前やめた記憶。

それを気にしなければ git pull --rebase origin master で全然いいと思います。

id:tofu-kun

俺は“rebase origin/master”派だな

id:PEEE

自分もorigin/master派

自分は怠惰なので rebase origin/master の前に fetch すら叩きたくない派でした。

fetch && rebase くらいなら ~/.gitconfigaliasワンライナーで書けるのでできないことはないけど、master以外がデフォルトブランチに設定されてた場合(よくあるのはdevelopブランチ)に途端に複雑度が増すのがアレ。

一応自分の git-update に関してはmaster以外がデフォルトブランチになってた場合に自動判別してます。

*1:fetchしてrebase origin/masterでもいいんだけど、masterからトピックブランチ作ることが多いので僕はこっちの方が好きです