CircleCIがパスしない時にローカルでデバッグする方法


問題

  • CircleCIがパスしない
  • ログを見ても原因がよくわからない

解決策

  • circleci buildでCIをローカル上のDockerコンテナで実行する
  • CIが終わってもコンテナを破棄しないよう.circleci/config.ymlを変更する
  • Dockerコンテナに接続してデバッグする

Docker Desktopのインストール

手順略

circleciコマンドのインストール

Macの場合はHomebrewでインストールします。

brew install circleci

circleci build

以下のコマンドによりCircleCIのタスクをローカルのDockerコンテナで実行します。

circleci build

このままだとCIが成功しても失敗しても終わったらコンテナは終了するため、デバッグすることができません。

CIが終わってもコンテナを破棄しないようにする

正確にはCIプロセスが終わらないようにします。

まず、失敗するstep以降をコメントアウトします。

次に、以下の設定を.circleci/config.ymlのjobs/build/stepsの最後に追加します。

      - run:
          name: for debug
          no_output_timeout: 120m
          command: |
            tail -f /dev/null

.circleci/config.ymlの全体は例えば以下のようになります。

version: 2
jobs:
  build:
    docker:
      - image: circleci/node

    steps:
      - checkout
      - run:
          name: install npm packages
          command: |
            npm install --verbose
      ...
#      - run:
#          name: unit test
#          command: |
#            npm run test
      - run:
          name: for debug
          no_output_timeout: 120m
          command: |
            tail -f /dev/null

Dockerコンテナに接続する

上記設定を加えた後にcircleci buildを実行すると、CIの実行コンテナが残り続けます。

docker psコマンドでコンテナ名を確認し、コンテナに接続します。

$ docker ps
$ docker exec -it [container] bash

以降、リモート実行時に失敗したコマンドを手動で実行するなどしてデバッグします。

タイムアウトを設定する

上記の設定ではno_output_timeoutの指定により120分後にコンテナは自動停止します。
デバッグに必要な時間を余裕を持って設定しましょう。

別の方法

リモートのCircleCIにはRun job with SSHボタンにより、
SSHを有効にした状態でビルドを走らせることができます。
こちらの方法もデバッグに使えますが、SSH接続中は実行時間が消費される点に注意しましょう。