とことんDevOps | 日本仮想化技術のDevOps技術情報メディア

DevOpsに関連する技術情報を幅広く提供していきます。

日本仮想化技術がお届けする「とことんDevOps」では、DevOpsに関する技術情報や、日々のDevOps業務の中での検証結果、TipsなどDevOpsのお役立ち情報をお届けします。
主なテーマ: DevOps、CI/CD、コンテナ開発、IaCなど
読者登録と各種SNSのフォローもよろしくお願いいたします。

CircleCI CLIを活用してローカルでテストを行う方法

CircleCIを使えば、VCSにコードをPushするだけで自動的にCIを行えます。非常にお手軽ですが、テストの内容に間違いがって正しくテストが行えなかったり、YAMLの文法エラーによってそもそもジョブが起動しなかったり、といったことがよくあります。つまりCIのコードそのもののテストも必要となるわけです。

今回紹介するCircleCI CLIを利用すると、ローカルマシン上のDockerを使い、CircleCIのジョブをテストすることができます。

Dockerのインストール

それではCircleCI CLIを実行する環境を作りましょう。今回はUbuntu 22.04 LTSの仮想マシンを利用しました。

CircleCI CLIでジョブを実行するには、Dockerが必要です。UbuntuにDockerをインストールする方法はいくつかありますが、今回はUbuntuのリポジトリにあるDebパッケージ版をAPTでインストールしました。以下のコマンドを実行してください。

$ sudo apt install -y docker.io

dockerコマンドを利用するには、デフォルトではroot権限が必要となります。しかしsudoをつけてCircleCI CLIを実行すると、デフォルトではホームディレクトリ以下にある設定ファイルが読めず、実行に失敗するという問題があります。そこで今回は一般ユーザーでdockerコマンドを利用できるよう、dockerグループにユーザーを追加します*1

$ sudo gpasswd -a ユーザー名 docker

グループへの追加が完了したら、ログインし直すか、newgrpコマンドを実行してください。docker versionコマンドなどを実行して、Dockerデーモンと通信できているか確認するとよいでしょう。

CircleCI CLIのインストール

続いてCircleCI CLIをインストールします。今回はインストールスクリプトをダウンロードして実行しました*2

$ curl -fLSs https://raw.githubusercontent.com/CircleCI-Public/circleci-cli/master/install.sh | sudo bash

ドキュメントによると、Docker/CircleCI CLI双方ともに、snapパッケージからのインストールが可能となっています。しかし筆者が試したところ、snap版のDockerは/tmp/local_build_config.ymlが読み込めずエラーとなってしまいました*3。またDockerをDebパッケージからインストールしていても、CircleCI CLIがsnap版だと、CLIがDockerデーモンと通信できず、ジョブを起動することができませんでした。そのため現時点では、Docker/CircleCI CLI双方ともにsnap版は使用しない方が、余計なトラブルを回避できるのではないかと思います。

コマンド補完の設定

これでcircleciコマンドを実行する準備は整いました。circleciコマンドは、他の様々なコマンドと同じく、複数のサブコマンドと引数を必要とします。これらをいちいち手で入力するのは面倒ですから、シェルの補完を有効にしておきましょう。以下のコマンドを実行すると、シェルの補完に必要な設定が出力されます。

$ circleci completion bash   ← bashの場合
$ circleci completion zsh     ← zshの場合

シェルの起動時にこの設定を読み込むには、プロファイルに記述してしまうとよいでしょう。例えばBashであれば、~/.bashrcの末尾あたりに、以下の内容を追記します。

eval "$(circleci completion bash)"

シェルを再起動すれば、自動的に補完が有効になっているはずです。circleciコマンドに続いて、Tabキーを何度か押してみましょう。

設定ファイルのバリデーション

.circleciがあるディレクトリ内で、以下のコマンドを実行すると、設定ファイルのバリデーションが行えます。

$ circleci config validate 

YAMLの文法エラーはこれで検出できますので、GitのPre-Commitフックに登録するなどして、機械的にチェックしてしまうと間違いを防止できるかもしれませんね。

ジョブの実行

同様に.circleciがあるディレクトリ内で、以下のコマンドを実行すると、特定のジョブをDockerコンテナ内で実行できます。

$ circleci local execute  --job 実行したいジョブ名

例えば、以下のようなconfig.ymlがあったとしましょう。echoコマンドを実行するだけで、具体的なことは何もしないジョブの例です。

version: 2.1

jobs:
  test:
    docker:
      - image: cimg/base:2022.03
    steps:
      - checkout
      - run:
          name: echo message 
          command: echo hello

workflows:
  my_workflow:
    jobs:
      - test
$ circleci local execute  --job test
Docker image digest: sha256:e2ea2900aaeaf36ef6d2519b60496cc095464018e16b68286abf6eb758577a46
====>> Spin up environment
(...略...)

====>> Preparing environment variables
Using build environment variables:
  BASH_ENV=/tmp/.bash_env-localbuild-1649226755
(...略...)

====>> echo message
  #!/bin/bash -eo pipefail
echo hello
hello
Success!

このように、自動的に必要なDockerイメージがPullされ、内部でジョブの内容が実行されました。

いちいちコードをPushし、クラウド上でジョブを起動してトライ&エラーするPushデバッグは、VCSのコミット履歴を汚しますし、何より効率が悪いですよね。CircleCI CLIを活用して、コードをPushする前に手元でもチェックを行ってみてください。

*1:非rootでdockerコマンドを実行できるようにするのは、セキュリティ面で細心の注意を払う必要がありますが、今回は考慮しないこととします。なおかわりに、ユーザーのホームディレクトリに第三者への読み込みパーミッションをつけ、circleciコマンドをsudoつきで実行しても構いません。

*2:本来、インターネットからダウンロードしたスクリプトを、このようにノーケアで実行するのはよろしくないのですが、本題から外れるためここでは無視します。

*3:おそらくsnap版のDockerは、基本的にホームディレクトリ以下のファイルしか読めないためかと思われます。