くりにっき

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

プリキュアボットを支える技術

これは プリキュア Advent Calendar 2018 の16日目です。

adventar.org

はじめに

今日はキュアピースの中の人の金元寿子さんのお誕生日です。おめでとうございます!!!!

嫁集合写真

キュアスタ!とは

Mastodonプリキュアインスタンスです precure.ml

キュアスタ!ではサーバに負荷をかけない程度であればボットの作成は容認されています。*1

いくつかボットを作ってるのでその紹介です

プリキュアこのあとすぐボット

プリキュアが始まる直前にトゥートするボットです。

https://precure.ml/@precure_onair_bot

f:id:sue445:20181130202050p:plain

元ネタ

最初作った時は開始10分前だけの通知でしたが、1日1回まとめて通知できた方が便利そうだったので0時にその日に放送される番組をまとめて通知するようにもしました。便利

f:id:sue445:20181130202141p:plain

今まで作った中ではこれが一番のお気に入りです

使っている技術

プリキュア誕生日ボット

プリキュアの誕生日の日にトゥートするボットです

f:id:sue445:20181130202239p:plain

https://precure.ml/@precure_birthday_bot

使っている技術

プリキュア つながるぱずるん」非公式

キュアぱず公式アカウント のツイートをきゅあったーに流すボットです。

f:id:sue445:20181130202644p:plain

https://precure.ml/@precure_app

使ってる技術

拙作の twittodon で流しています

詳しいこと

sue445.hatenablog.com

CIマニアから見た各種CIツールの使い所

社内外でちょいちょい聞かれるのでメモ。

前置き

  • 100%自分の主観なので偏ってます
    • SaaSかオンプレならSaaS派。(自分でサーバの面倒身たくない)
  • 自分が使ったことがないものは紹介していません
    • 今回紹介してるTravis CI, CircleCI, Wercker, GitLab CI, Jenkinsに関しては仕事や趣味で各3〜4年くらいは使ってるはず

GitHubを使ってる場合

ライブラリを作ってる場合

紛らわしいですが https://travis-ci.org/ は無料版で https://travis-ci.com/ が有料版。

今は両方 https://travis-ci.com/ に統一されてるとのこと *1

OSSであれば基本的にはTravis CIを使っていればいいと思います。

Travis CIを選択する理由

Travis CIを選択しない理由

アプリを作ってる場合

アプリの場合

  1. テスト
  2. テストが成功したもののみ開発環境にデプロイ
  3. 開発環境で確認して問題がなかったらステージング環境にデプロイ
  4. ステージング環境にデプロイして問題なかったら本番環境にデプロイ

というワークフローがよくあると思いますが、Travis CIだと複雑なワークフローを組むのが大変なので CircleCIWercker を使うのがいいと思っています。

CircleCIとWerckerの共通点

  • 任意のDockerイメージが使える
  • ワークフローが組める
  • 設定ファイルがymlファイル
  • 無料プランでもプライベートリポジトリがビルドできる

CircleCIとWerckerの機能差異

CircleCI 1.0時代はWerckerの方が機能面で優秀でしたが、現時点ではCircleCIの方が全体的に使い勝手がいいと思っています。(今後変わるかも)

理由

  • Werckerは1リポジトリ1 Dockerイメージだが、CircleCIはジョブ単位で利用するDockerイメージを変えられる
  • CircleCIはスケジューラ(cronのようにジョブを定期実行)をサポートしているが、Werckerは非サポート
    • WerckerのAPIをcrontabから定期的に叩けばいけるんだけど、CIサービスだけで完結しないのが難点
    • 【宣伝】Werckerでジョブを定期実行しやすくするツールは昔作りました
  • CircleCIはほぼ全ての設定がymlに集約されているが、Werckerの場合ワークフローの定義部分は管理画面で設定する必要がある
    • リポジトリの管理者しかワークフローの設定をいじれないので、第三者がワークフローの設定変更のPRを送りづらい
  • CircleCIとWerckerではCircleCIの方が複雑なワークフローを組める
  • CircleCIだと自動実行だけでなく、人間が承認することによってワークフローの先のステップに進めるということができる(Manual Approval)

GitLabを使ってる場合

リポジトリ(GitLab本体)と一体化していて連携が楽なのでGitLab CI一択。

設定ファイルの書き方に細かい違いはあるものの、基本的にCircrleCI 2.1相当の機能があるので普通に使う分にはまず機能面で困ることは無いと思います。

GitLab CIの優位点

Jenkinsなどを使った方がいい場合

下記のユースケースに関してはJenkinsや他のツールを使った方がいいと思います

  • 複数のリポジトリにまたがるジョブを構築したい時
    • Travis CI・CircleCI・GitLab CI・Wercker、いずれにせよ複数リポジトリで連携させるジョブを作るのは難しい
  • Parameterized Trigger Plugin のように、ジョブ実行時にパラメータを選択したい時
  • ビルド環境がハードウェア依存の場合
    • 一番分かりやすいのはiOS/Android/Unityアプリなどのビルド
      • ただしCircleCIはiOSビルドをサポートしているし*4、GitLab CIでもMacをRunnerにすることでiOSアプリをビルドすることもできるので、「ハードウェア依存のビルドだからJenkins必須」とは一概には言えない
  • イントラ環境でのビルドが必要な場合
    • SaaSを使いたくない(使えない)という大人の事情以外にも、イントラ内じゃないとライブラリやパッケージがダウンロードできないというのはある
      • ただしそういう時でもCircleCIのEnterpriseを利用するとか、GitLab CIのRunnerをオンプレに置くという方法はある*5

追記:2018/12/8

from id:tnir

CIマニアから見た各種CIツールの使い所 - くりにっき

GitHub\.comを使ってる場合、GitLab CI/CD for GitHub (SaaS)の選択肢はないのかどうか。

2018/12/08 00:01
b.hatena.ne.jp

なるほど。これは知らなかったです

about.gitlab.com

アリかナシかで言えばアリで、GitHubだけどイントラ内でCIをしたい(が自前でJenkinsをホスティングしたくもない)ような場合にはGitLab CIに軍配が上がりそうです。(Runnerをホスティングする手間はあるけど)

*1: https://twitter.com/ndxbn/status/1071045198145191943

*2:TravisだとOracleのインストールだけで10分くらいかかった

*3: https://travis-ci.com/plans

*4:https://circleci.com/docs/2.0/ios-tutorial/

*5:GitLabはそもそもオンプレやんというツッコミはありそうですが、SaaSのGitLab.comとオンプレのRunnerを連携できます

Pixelaでesaのkusaを生やす

esaとkusa(草)の語感が似ていたのでやってみました (\( ⁰⊖⁰)/)

やり方

Pixela の設定

以下は拙作の pixela gemを使っていますが、他言語の場合は適当に置き換えてください

require "pixela"

client = Pixela::Client.new(username: "YOUR_NAME", token: "YOUR_TOKEN")

# Pixelaにユーザ登録していないなら登録する
client.create_user(agree_terms_of_service: true, not_minor: true)

# グラフを作成する
# colorはshibafu, momiji, sora, ichou, ajisai, kuroのいずれかを選択
# c.f. https://docs.pixe.la/#/post-graph
client.create_graph(graph_id: "esa", name: "esa activity", unit: "kusa", type: "int", color: "shibafu", timezone: "Asia/Tokyo")

# webhookを作成
client.create_webhook(graph_id: "esa", type: "increment")
#=> #<Hashie::Mash isSuccess=true message="Success." webhookHash="XXXXXXXXXXXXXXXX">

create_webhook の戻り値で返ってくる webhookHash は後で使うので忘れないようにしてください

esa の設定

Ownerアカウントで「チーム情報 -> Webhook・アプリ連携」よりGeneric Webhookを登録

f:id:sue445:20181206001624p:plain

URLは https://pixe.la/v1/users/【ユーザ名】/webhooks/【webhookHash】 の形式

チェックボックスはお好みで。

実際のグラフ

https://pixe.la/v1/users/【ユーザ名】/graphs/【グラフID】svghttps://pixe.la/v1/users/【ユーザ名】/graphs/【グラフID】.html がhtmlのURLです。

esaに埋め込む方法

こんな感じ

[![esa activity](https://pixe.la/v1/users/【ユーザ名】/graphs/【グラフID】)](https://pixe.la/v1/users/【ユーザ名】/graphs/【グラフID】.html)

サンプル

## esa activity
[![esa activity](https://pixe.la/v1/users/sue445/graphs/esa)](https://pixe.la/v1/users/sue445/graphs/esa.html)

で埋め込んだ図が下記です。READMEに埋め込んでおくと分かりやすいでしょう。

f:id:sue445:20181206000114p:plain

注意点

esaはログインしないと見れませんが、Pixelaのグラフ(草)はログイン無しで見れてしまいます。

そのため、もしPixelaのグラフを作る場合はURLを第三者に知られないようにし、リスク(esaのactivityがpublicになる)を認識して利用してください。

rubocop_auto_correctorを作った

はじめに

これはアドベントカレンダーとは全く関係ないいつもの技術エントリです

github.com

モチベーション

僕は普段rubocopでauto correctする時はコミットの可読性の観点から下記のように各cop単位でauto correctしてコミットするようにしています。

sue445.hatenablog.com

このスクリプトは非常に便利なのですが、個人dotfilesにあるため他の人に使ってもらいにくいという難点がありました。

先日のOSSパッチ会 でrubocopコミッタの id:koic に「こういうスクリプトってrubocop本体にあるとどうっすかね?」みたいな感じで雑に相談したら、「本体よりも別のツールとしてあった方がよさそう」という返事をもらったのでgem化したのが今回の rubocop_auto_corrector になります

使い方

bundle exec rubocop_auto_corrector で実行するだけです

実行結果のサンプル

https://github.com/sue445/rubocop_auto_corrector/pull/3/commits

f:id:sue445:20181130235925p:plain

gem化するにあたって気をつけたこと

ユニット(?)テストの整備

gemの性質上実際にgit commitするところまでテストで検証する必要があったので、rspecの中で

  1. ダミーアプリをgit init
  2. rubocop_auto_correctorを動かして rubocop --auto-correct && git commit
  3. gitのコミットメッセージが意図通りか検証

のようなことを行っています

詳しくはこの辺のソースを読んでください

auto correctできないcopはスキップするようにした

今まではrubocopの実行結果に出てきたcop全部 rubocop --auto-correct してたので割と無駄が多かったのですが、それは無駄なので実際にauto correctできるcopのみrubocop --auto-correct するようにしました。

しかし「言うは易く行うは難し」というやつで、cop名からcopのクラス名とgem名(プラグインの場合)を取り出す方法が色々と面倒くさかったです。。。(特にrubocop-rspec

https://github.com/sue445/rubocop_auto_corrector/blob/v0.1.0/lib/rubocop_auto_corrector/cop_finder.rb#L41-L54

Itamae v1.10.1をリリースした

リリースノート

https://github.com/itamae-kitchen/itamae/blob/master/CHANGELOG.md#v1101

Fail --ohai option when using ohai v13.0.1 or higher

github.com

古いPRなのですが入れても問題なさそうだったのでマージしました。

ただこのPRがTravisCI移行前のPRでビルドステータスが落ちてる状態だったので、手元で最新のmasterをマージした上で別PRでマージしています。

github.com

circleci-bundle-update-prをCircleCIのorbにした

circleci-bundle-update-prとは

CircleCIでbundle updateしてPRを作るgemです。(id:masutaka26 氏製作)

github.com

モチベーション

コアの処理はgemになっていてCircleCIから呼ぶ部分は実質ワンライナーなのでorb化不要な気もしましたが、あるとそれなりに便利そうなので作ってみました

使い方

だいたいこれで動きます。

version: 2.1

orbs:
  ruby-orbs: sue445/ruby-orbs@1.3.0

workflows:
  version: 2

  nightly:
    triggers:
      - schedule:
          cron: "00 10 * * 5"
          filters:
            branches:
              only: master

    jobs:
      - ruby-orbs/bundle-update-pr:
          image: "circleci/ruby:2.5.3"
          pre-bundle-update-pr:
            - run:
                name: "Set timezone to Asia/Tokyo"
                command: "sudo cp /usr/share/zoneinfo/Asia/Tokyo /etc/localtime"
          git_user_name: "yourname"
          git_user_email: "you@example.com"
          github_access_token: "$GITHUB_ACCESS_TOKEN"

パラメータの一覧や詳しい説明はREADMEを御覧ください。

https://github.com/sue445/circleci-ruby-orbs#bundle-update-pr

実際に動いた画面

f:id:sue445:20181118151141p:plain

合わせて読みたい

sue445.hatenablog.com

sue445.hatenablog.com

CircleCI orb Perfect Testing

sue445.hatenablog.com

で書いてた

今回作ったorbのインテグレーションテストも頑張ってるのですが、長くなるので別の機会に書こうと思います

の件です。

https://github.com/sue445/circleci-ruby-orbs/blob/1.2.0/.circleci/config.yml の解説をします

注)タイトルは半分釣りです

tl;dr;

  • 何をテストしたいかによって難易度が変わる

orbのテストについて

https://github.com/CircleCI-Public/config-preview-sdk/blob/master/docs/orbs-testing.md より抜粋

You can think of orb testing at 4 levels, in increasing levels of complexity and scope.

  1. Schema Validation - this can be done with a single CLI command and checks if the orb is well-formed YAML and conforms to the orb schema.
  2. Expansion Testing - this can be done by scripting the CircleCI CLI and tests whether the elements of the orb generate the configuration you intended when processing configuration containing those elements.
  3. Runtime Testing - this requires setting up separate tests and running them inside a CircleCI build.
  4. Integration Testing - this is likely only needed for fairly advanced orbs or orbs designed specifically as public, stable interfaces to 3rd-party services. Doing orb integration tests requires a custom build and your own external testing environments for whatever systems you are integration with.

英語は苦手なので 今回は和訳することが目的ではないので具体的にどんなテスト手法があるのかを紹介します

YAMLシンタックスチェック

実際のソース

https://github.com/sue445/circleci-ruby-orbs/blob/1.2.0/.circleci/config.yml#L7-L14

一番お手軽ですが、ymlファイルの検証だけで実際にジョブを動かさないためテストとしては不十分です

ローカルテスト

CircleCI Orbs 入門 | tsub's blog の「Orb のテスト実行」が詳しいです

実際のソース

だいたいの場合はこれでいいのですが、orb実行のために他にファイルが必要な場合( ruby-orbs/bundle-install の場合Gemfile)には不向きです

理由

インテグレーションテスト

https://github.com/CircleCI-Public/artifactory-orb ではスモークテストのためのリポジトリhttps://github.com/eddiewebb/artifactory-orb-test )を作っていました。

それを参考にruby-orbsでも https://github.com/sue445/circleci-ruby-orbs-test のようなリポジトリとCircleCIのプロジェクトを作っています

circleci-ruby-orbs(メインのリポジトリ)とcircleci-ruby-orbs-test(スモークテスト用のリポジトリ)を連携させて下図のようなインテグレーションテストを実現しています。(文字が小さくなってすいません。。。)

f:id:sue445:20181116014650p:plain

仕組み

  1. 【ローカル】トピックブランチをpush
  2. 【circleci-ruby-orbs】sue445/ruby-orbs@dev:${CIRCLE_SHA1} (CIRCLE_SHA1はビルド実行時のgitのリビジョン)でorbをリリース
  3. 【circleci-ruby-orbs】smoke_testジョブでcircleci-ruby-orbs-testのリポジトリをcloneする
  4. 【circleci-ruby-orbs】cloneしたcircleci-ruby-orbs-testで smoke_test/{CIRCLE_SHA1} のようなブランチを作る
  5. 【circleci-ruby-orbs】circleci-ruby-orbs-testが sue445/ruby-orbs@dev:${CIRCLE_SHA1} を使ってビルドするようなコミットを作る
  6. 【circleci-ruby-orbs】circleci-ruby-orbs-testにpush
  7. 【circleci-ruby-orbs-test】circleci-ruby-orbsのCircleCIから下記画像のようなコミットがpushされてくるので、circleci-ruby-ops-test側のCircleCIがビルドを実行する
    • f:id:sue445:20181112013800p:plain
  8. 【circleci-ruby-orbs】circleci-ruby-orbs-testのビルドをポーリングして、ビルドが終了するまで待つ

【おまけ】スモークテスト用のブランチを自動で削除する

circleci-ruby-orbs-testには smoke_test/xxxxx のようなブランチが大量に作られるので、それを定期的に削除するCircleCIのジョブを作ってます

今の設定だと12時間に1回、12時間以上前に作られたブランチを自動で削除するようにしています

【おまけ】orbリリース時に自動でgitのtagをpushしたい

orb-tools/increment を使えばorbの自動リリースは簡単にできるのですが、リポジトリ的にはリリースごとにtagが打たれていた方が後からバージョン間の差分が取りやすいので嬉しいことが多いです。

increment後に自動でgitのtagをpushする方法がないかissueで聞いたところ、

github.com

You could run circleci orb info to get the latest in an additional step in your flow

というレスをもらったのでそれをCIで実装したのが下記です

circleci orb info をたたいてLatestで返ってきたバージョンのtagを作ってpushしています

*1

*1:余談ですがここだけrubyを使っているのはシェルで標準出力を正規表現のparseするのが難しかったためです