ラクスAdvent Calendar 2021 の2日目は、スプリットキーボードならぬデュアルキーボード歴2ヶ月の @oohira が、左手に Magic Keyboard、右手に REALFORCE というごった煮環境からお送りします。
昨日は「初日取ったった!」してくれた @Y-Kanoh さんの「GASでカユいところに手が届いたTips3選」でした。勢い、大事ですね。
はじめに
これまで定期実行したいちょっとしたスクリプトは、個人PCやプロジェクト共用サーバー、Jenkins などを使って実行していましたが、ここ数年で GitLab CI を使って実行する方法に完全に落ち着きました。この記事では、社内のメンバーも読者に想定しつつ、GitLab CI のよさと簡単な始め方を紹介したいと思います。
背景と前提
GitLab CI(や GitHub Actions)が登場する前の世界では、Linux の cron や、Windows のタスクスケジューラー、Jenkins などを使ってスクリプトを定期実行することが多かったのではないかと思います。いずれの方法でも目的は果たせますが、次のような課題もありました。
- 実行マシンを用意するのが面倒
- 個人PCなのか共用サーバーなのかは別として、スクリプトを実行するためのマシンを用意し、デプロイする仕組みを考えなければならない
- 実行マシンのミドルウェアを管理するのが面倒
- スクリプトで使用するプログラミング言語を実行できる環境を整備したり、実行マシン自体のOSやミドルウェアを定期的にアップデートしなければならない
- 引き継ぎするのが面倒
- 別の人にスクリプトを引き継いでメンテしてもらう必要が出たときに、実行マシンの構成や手順などを文書化して伝えなければならない
GitLab CI を使うと、これらの問題を解決したスクリプト実行環境を簡単に構築することができます。GitHub Actions でも同じことが実現できると思いますが、弊社ではソースコード管理システムとして GitLab を採用しているため、ここでは GitLab CI を前提として話を進めます。執筆時点で確認したバージョンは次の通りです。
- GitLab v14.0.5
- GitLab v14.6.0-pre
はじめの一歩
まずは、GitLab CI でスクリプトが実行できるミニマムの環境を作ります。
-
GitLab プロジェクトを新規作成する
-
GitLab Runner を登録する(GitLab.comの場合は不要)
- 自社でサーバーを立てている&Shared runner が有効になっていない場合は、
Settings > CI/CD > Runners
から、GitLab CI を実行するためのサーバーを登録する必要があります。-
弊社メンバーの皆さまは、↓にある個別 Runner を使ってもらってOKですよ。これ、一部の人にしか見えていないっぽいことが発覚してしまいました 1
-
- 自社でサーバーを立てている&Shared runner が有効になっていない場合は、
-
.gitlab-ci.yml
を作成する- プロジェクトルートにビルド設定を記載したファイルを作成します。リポジトリをチェックアウトしなくても、GitLab の Web 画面から作成・編集するとお手軽です
.gitlab-ci.ymlimage: alpine awesome-job: stage: build script: - echo "Hello, World!"
-
.gitlab-ci.yml
をコミット&push する
簡単ですね
POINT: 実行環境の準備が楽
GitLab CI は、GitLab に統合されているため、実行マシンを別に用意2したり、スクリプトを実行サーバーにデプロイしたりする手間がありません。.gitlab-ci.yml に実行したいスクリプトを書くだけで、あとは GitLab CI がいい感じに実行してくれます。
ミドルウェアを変更する
ここで、もう少し本格的なスクリプトを作りたくなったとしましょう。シェルスクリプトでは心もとないので、Node.js に切り替えるとします(Go でも Ruby でも好きな言語をどうぞ)。
-
.gitlab-ci.yml
を変更する- Node.js がセットアップ済みの軽量イメージとして node:14-alpine を使ってみます 3
.gitlab-ci.ymlimage: node:14-alpine awesome-job: stage: build script: - npm xmas
POINT: ミドルウェアの管理や更新が楽
GitLab CI は、コンテナベースの実行環境なので、スクリプトを実行するOSやプログラミング言語を変更しても、新たにミドルウェアをセットアップする手間がありません。.gitlab-ci.yml に必要なバージョンのミドルウェアを指定するだけで準備が完了します。
定期実行する
このままでは(CIの本来の期待通りではありますが)コミットするたびに実行されてしまうので、スケジュール登録して定期実行できるようにします。
-
スケジュール実行のときだけビルドするよう
.gitlab-ci.yml
を変更する.gitlab-ci.ymlimage: alpine awesome-job: stage: build rules: - if: $CI_PIPELINE_SOURCE == "schedule" script: - echo "Hello, World!"
-
スケジュール設定を登録する
-
CI/CD > Schedules > New schedule
からスケジュール設定を登録します。cron と同じ書式で実行間隔を指定できます
- 登録が完了すると、次回実行予定日時が確認できます。オンプレの場合は、GitLab の設定によって実行間隔が期待通りにならないことがある ので注意してください
-
-
スケジュール設定した日時に自動実行されるのを待つ
-
手動で即時実行する
外部システムと連携する
スクリプトを実行する仕組みは整いましたが、このままでは GitLab CI のログでしか出力を確認することができません。多くの場合は、Slack や Mattermost のようなチャットツールに結果を投稿したり、Git にコードをコミットしたり、別のシステムとの連携が期待されます。
ここでは、Mattermost に投稿する bot を作ってみます。
-
Webhook URL を取得する
- Mattermost 側で Incoming Webhook を実行するためのURLを発行します
-
.gitlab-ci.yml
を修正する- Mattermost にメッセージを投稿するようスクリプトを変更します。curl コマンドを追加でインストールしている点や、URLをハードコーディングせずに環境変数としている点に注意してください(説明の都合上、インラインでコマンドを書いていますが、エスケープがつらいので実際は別ファイルに切り出すとよいでしょう)
.gitlab-ci.ymlimage: alpine awesome-job: stage: build rules: - if: $CI_PIPELINE_SOURCE == "schedule" script: - apk add curl - 'curl -k -X POST -H "Content-Type: application/json" -d "{\"icon_emoji\": \"santa\", \"username\": \"santa_bot\", \"text\": \"Hello, Mattermost. :tada:\"}" "${MATTERMOST_URL}"'
-
スケジュール設定に環境変数を登録する
-
定期実行されるのを待つ or 手動実行する
- GitLab CI で実行されたスクリプトから Mattermost への投稿 4 が成功します
- GitLab CI で実行されたスクリプトから Mattermost への投稿 4 が成功します
好きな言語で書いたスクリプトからチャットへ投稿ができるようになったので、あとはスクリプトで何を投稿するか、アイデア次第です。
POINT: 引き継ぎが楽
スクリプトだけでなく、ミドルウェアまで含めた前提条件が .gitlab-ci.yml にコード化されるため、スクリプトの実行に何が必要かを把握しやすくなります。また、スケジュール設定や環境変数の値も含めてすべて GitLab 上に一元化されるため、引き継ぎはリポジトリを伝えれば何とかなります(多分)。
成果物を保存する
スクリプトの出力を二次利用する別の方法として、生成したファイルを GitLab に保存しておき、後から参照できるようにすることもできます。
-
.gitlab-ci.yml
を修正する- 外部サービスから取得したネコ画像を
artifacts
として保存するよう指定します
.gitlab-ci.ymlimage: alpine awesome-job: stage: build rules: - if: $CI_PIPELINE_SOURCE == "schedule" script: - apk add curl # Powered by Cat as a service (CATAAS) - curl -s "https://cataas.com/cat/gif" -o cat.gif artifacts: paths: - cat.gif
- 外部サービスから取得したネコ画像を
Tips
最後に雑多な Tips を紹介します。
-
一時的に無効にする
- スクリプトのデバッグ時など、一時的に定期実行を無効にしたい場合は、スケジュール設定の
Active
フラグで切り替えることができます
- スクリプトのデバッグ時など、一時的に定期実行を無効にしたい場合は、スケジュール設定の
-
エラーメールはスケジュール設定のオーナーだけに届く
- ビルドが失敗した場合の通知メールは、スケジュール設定を登録したユーザー(オーナー)だけにしか送信されません
- 監視スクリプトなど、ビルド失敗をチームとしてウォッチする必要がある場合は、別途チャットに通知するようにしておくなり、メールを自動転送するようにしておくなり、何かしらの対処が必要です
-
複数のスクリプトを管理する
- 1つのリポジトリでスケジュールが異なる複数のスクリプトを管理したい場合は、スケジュール設定の環境変数をうまく組み合わせることで対応することができます
.gitlab-ci.ymlimage: alpine awesome-job: stage: build rules: - if: '$CI_PIPELINE_SOURCE == "schedule" && $AWESOME_JOB_SCHEDULE == "1"' script: - echo "Awesome job" great-job: stage: build rules: - if: '$CI_PIPELINE_SOURCE == "schedule" && $GREAT_JOB_SCHEDULE == "1"' script: - echo "Great job"
さらに学ぶには
- Get started with GitLab CI/CD | GitLab
- Pipeline schedules | GitLab
- Keyword reference for the .gitlab-ci.yml file | GitLab
まとめ
この記事では、GitLab CI を使って定期実行スクリプトを管理・実行する方法を紹介しました。ソースコードの管理と実行環境の管理を一元化することができ、とてもオススメです。
GitLab CI、イイよ!
-
プロジェクトロックしていない Specific runner を社内メンバーに自由に使ってもらって、 GitLab CI を手軽に試してもらおうというのがそもそも今回の記事の目的だったのに、ここにきてまさかとはこのこと。やはり管理者にお試し用の Shared runner を用意してもらうしかないか。とり急ぎ Specific runner の候補が1つも出ない場合は、
Show Runner installation instructions
の手順に従って… (ry ↩ -
厳密には、GitLab CI の実行に使う GitLab Runner を誰かが用意する必要があります。そのため、GitLab CI を使ったからといって完全に実行マシンの管理が不要になるわけではありませんが、GitLab Runner さえ用意すれば他の大多数の人はその恩恵を受けるだけで済みます。 ↩
-
npm xmas
がとうとう削除されたっぽいので、意図的に少し古めの Node.js を使用しています。 ↩ -
当たり前と言えば当たり前ですが、GiLab CI が実行するコンテナから Mattermost へアクセスできる必要があります。GitLab.com を使っているけど Mattermost は社内ネットワークで稼働している、と言った場合は面倒かもしれません ↩