【Common Lisp】cl-base + rove + GitHub Actions でテストする

以前「cl-base + rove + Travis CI でテストする」という記事を書きましたが、その s/Travis CI/GitHub Actions/ 版です。

eshamster.hatenablog.com

下記が作成したアクションのリポジトリです。

github.com



使い方

ひとまず使い方です。次の条件に合致する場合、プロジェクトに下記のような内容の .github/workflows/xxx.yml (xxx は任意) を配置するだけです。

on: [push]

jobs:
  test:
    runs-on: ubuntu-latest
    strategy:
      matrix:
        lisp: [sbcl-bin, ccl-bin]
    name: A job to test Common Lisp project
    steps:
    - name: Checkout
      uses: actions/checkout@v2
    - name: Test step
      id: test
      uses: eshamster/try-cl-test-on-gh-actions@v0.3.1
      with:
        # 利用する処理系: 今のところ sbcl-bin or ccl-bin
        lisp: '${{ matrix.lisp }}'
        # [optional] テスト前に ros install したいものがあればカンマ区切りで指定する
        installTargets: 'eshamster/ps-experiment,eshamster/cl-ps-ecs'

テスト環境の /github/workspace にテスト対象のコードがあることを前提にしているので、先に actions/checkout アクションでリポジトリをチェックアウトします。

ちなみに、リポジトリ内でも動作確認していますが、(GitHub Actions 初触りなため)他プロジェクトから使えるのか不安だったので、次のリポジトリでお試し利用しています。

github.com

中身

アクションのリポジトリを再掲します。

github.com

このうち、アクションに関係するのは以下の4ファイルです。

├── action.yml
└── test-docker
     ├── Dockerfile
     └── test.sh

Travis CI 版と比べると、docker run 部分を GitHub Actions 側でやってくれるので、test-docker/run.sh にあたるファイルがありません。

action.yml

アクション定義の本体です。

name: 'Test Common Lisp'
description: 'Run test of Common Lisp project using rove on Docker'
inputs:
  lisp:
    description: 'Name of Common Lisp implementation'
    required: true
    default: 'sbcl-bin'
  installTargets:
    description: 'Comma separated installation targets that can be installed by "ros install"'
    required: false
runs:
  using: 'docker'
  image: 'test-docker/Dockerfile'
  args:
    - ${{ inputs.lisp }}
    - ${{ inputs.installTargets }}

特筆するところもないですが、runs.usingdocker を指定することで、テストを Docker コンテナ上で走らせることを指示しています。

このアクションでは2つの引数(inputs)を取ります。

  • lisp: 利用する処理系の指定で今のところ下記のいずれか
    • sbcl-bin
    • ccl-bin
  • installTargets: [optional] テスト前に ros install したいものがあればカンマ区切りで指定する ((処理系を ros use する手前で ros install を実行しているので別の処理系の追加も可能ではあります。とはいえ、テスト実行のたびにインストールすることになるので Dockerfile 側を修正して追加するのが正道ですね))
    • 例. 'eshamster/ps-experiment,eshamster/cl-ps-ecs'

test-docker/Dockerfile

テスト実行環境を定義する Dockerfile です。

FROM eshamster/cl-base:2.4.2

ADD ./test.sh /root
RUN ros install ccl-bin && \
    ros install rove

ENTRYPOINT ["/root/test.sh"]

Travis CI 版と比べると CMD -> ENTRYPOINT になったぐらいであとは見ての通りです。Common Lisp 処理系は(デフォルトの sbcl-bin に加えて)ccl-bin を入れています。他の処理系を入れる場合はここに追加するのが良さそうです。

test-docker/test.sh

ENTRYPOINT としてコンテナ内部で起動されるスクリプトです。

#!/bin/sh

set -eux

lisp=$1
install_targets="${2:-}"

if [ "${install_targets}" != "" ]; then
    echo "${install_targets}" | tr ',' '\n'| while read target; do
        ros install ${target}
    done
    ros -e '(ql:register-local-projects)' -q
fi

ros use ${lisp}

# Note: Assume that repository is checkout to workspace folder in previous step
dir=/root/.roswell/local-projects/target
cp -R /github/workspace ${dir} # (*1)
cd ${dir}
rove *.asd 2>&1 | tee /tmp/test.log
# Note: In Clozure CL, terminating debug console finishes in errcode 0,
# so grep message to check if the test has actually run.
grep "tests? passed" /tmp/test.log # (*2)

2つの引数を取ります。

  • 第1引数: 利用する Common Lisp 実装
  • 第2引数: 追加で ros install するもの

下記のような微妙なハックがあります。

  • (*1): 最初 ln -sシンボリックリンクを作ろうとしていたのですが、Clozure CL ではうまく認識(ql:quickload)できなかったっため、コピーを作成しています
  • (*2): システムが見つからなかったなどでデバッガに入った場合即座に死んでくれる...のは良いのですが、Clozure CL ではエラーコード 0 で終了してテスト成功扱いになってしまったので、テストログを grep してテスト成功を示すメッセージがあるかを確認しています
    • 追記:複数のテストが走る場合メッセージが test passed ではなく test"s" passed になることに気付いたので v0.3.1 で修正

参考にしたもの

今回のものをつくる上では、公式のドキュメントを見れば事足りる感じでした。基本的には「Docker コンテナのアクションを作成する」に沿っていけば良かった感じです。

設定の細かい部分に関しては適宜下記を参照しました。