CircleCIのスケジュール実行でcronから乗り換える

概要

最近、CircleCI2.0ではtoriggerという機能でスケジュール実行ができるということを知った。

CircleCI公式ドキュメント

まんまこちらの方の記事の通り。
Circle-CI 2.0のcron triggerを使って、定期実行をする

私が実現したかったのは、個人のアプリケーションでサーバーでcronで定期実行させてSlackに通知させているやつを、このtorrigerで実現できないかなと思ったことだった。
今までだとherokuとかのPaaSを使ったり、AWS Lambda、Google App Scriptとかを使うのがよくある方法だと思うのだけど、簡易的なバッチならCircleCIのみでいけないかな?と思い、やってみることにした。

CicleCIへのプロジェクト追加

まず、いつもどおりにCircleCIにログインして、「Add Project」からプロジェクトを追加する。※今回はすでに追加済みだが、tw4-html-parserというリポジトリを例にあげる。

次に「start building」しておく。

このままではCIはなにも実行されずにエラーになるので、下記をリポジトリに追加する。
追加先は、リポジトリ直下に .circleci/config.yml というのを作成して、runの部分に実行させたいコマンドを記載する。

---
version: 2
jobs:
  build:
    docker:
      - image: ruby:2.4
    working_directory: ~/repo
    steps:
      - checkout
      - run: bundle install
      - run: bundle exec ruby htmlparser.rb
workflows:
  version: 2
  normal_workflow:
    jobs:
      - build
  schedule_workflow:
    triggers:
      - schedule:
          cron: "1 11 * * *" # UTCで記述。-9
          filters:
            branches:
              only:
                - master
    jobs:
      - build

ポイントはworkflowという箇所。
通常CIをまわす際にはworkflowはなくても良いが、ここでいろいろ設定できる。
今回はtoriggerにscheduleを指定。これで指定した時間に実行される。
※時間はUTCなので日本時間から-9しておく。20時実行なら11時。

また、CIで実行するにあたり、.envで管理していたslackのwebuhookのURLをCircleCIの環境変数にセットした。

結果無事に通知されてきた。

※これは誰かのツイッターで知ったウェブマンガのリンクをパースした簡単なスクリプト通知。

やってみて

CircleCIは基本CIなので、CIを目的に使うのが普通なのかもしれないが、2.0から自分で作ったDockerイメージを指定できるし、1コンテナまでは実行が無料で、toriggerでバッチ実行できるようになっててまじで最高に便利だと思う。
待受はできないけど、簡単なバッチみたいなスクリプトであれば、まさにサーバーを管理しないという意味のサーバーレス化ができたかと思う。
開発やっている人とかだったら結構普通にやっているのかもしれないが、私はCIは疎いので今回も学びが多かった。
これでこんなことやっていたcronを削除できる!

00 19 * * * root /usr/local/bin/docker-compose -f /path/to/docker-compose-orgapps.yaml exec -T ruby-24 sh -c "cd /var/www/html/github/tw4-html-parser && /usr/local/bin/bundle exec ruby htmlparser.rb"

ちなみに通知が来なくて、toriggerの制限にかかっているのかなーって思ってたが、ちゃんとcircleciコマンドでvalidateしたら、普通にタイポしてて泣いた。