🕰️

GitHub ActionsでROS 2のビルド・テストを自動化する

2023/07/26に公開

海洋ロボコンをやってた人です。

今回はGitHub Actionsを触ってROS 2のパッケージのcolcon buildcolcon testを自動化してみたので、その備忘録として記載していきます。

GitHub Actionsは、GitHub上で利用可能なCI/CDツール※1, 2です。GitHub Actionsを使用すると、ソフトウェア開発プロジェクトのビルド、テスト、デプロイなどの一連のタスクを自動化することができます。

※1 CI: Continuous Integration(継続的インテグレーション)
※2 CD: Continuous Deployment(継続的デプロイメント)

記事を書いた理由は以下です。

  • CI/CDを触りながら学びたいため
  • 後から使い方を自分で見直せるようにするため


初学者なので、何かコメントあれば積極的に募集します。
では、早速記載していきますね。


※ 2023/8 GitHub ActionsとJenkinsどっちを使用するのが良いのか?という疑問に対しては、使用する際の環境と以下の相違点を踏まえて判断していただければと思います。

https://www.enterprisenetworkingplanet.com/management/github-actions-vs-jenkins/

ROS 2のテストとは

ビルド・テスト・デプロイメントなどのプロセス自動化での、ビルドはcolcon buildなどで馴染みがあると思いますが、テストとデプロイはあまりイメージがなかったので、以下にメモを記載しておきます。

ROS 2 でソースコードのテストを行うには以下を実行します。

terminal
colcon test --packages-select package_name

実行後にxxx_ws下のlogファイルを見てみると、様々なテストが行われているのが分かります。

xxx_ws/log/latest_test/package_name/stdout_stderr.log
The following tests FAILED:
	[0;31m  1 - copyright (Failed)[0;0m
	[0;31m  2 - cppcheck (Failed)[0;0m
	[0;31m  3 - cpplint (Failed)[0;0m
	[0;31m  4 - lint_cmake (Failed)[0;0m
	[0;31m  5 - uncrustify (Failed)[0;0m
	[0;31m  6 - xmllint (Failed)[0;0m

上記ですが、cppcheckcpplintなど必要なパッケージをインストールしていないと上記のように全項目Failedが表示されるので、以下もインストールしました。

terminal
sudo apt install ros-humble-ament-cppcheck
sudo apt install ros-humble-ament-cpplint
sudo apt install ros-humble-ament-lint-cmake
sudo apt install ros-humble-ament-uncrustify
sudo apt install ros-humble-ament-xmllint

あとはlogファイルに書いてあるエラーを見ながら、テスト項目をクリアできるようにプログラムを修正していけば良さそうです。

参考までに、自分が引っかかったエラー項目に対しての対策一覧を記載しておきます。

  • copyrightが先頭にあること
  • a < bと演算子の両端にスペースが入っていること
  • Tabでなくspace推奨
  • ファイル末尾に改行文字があること
  • 空白行にインデントが入っていないこと
  • コードブロック開始部分(関数の始め)の余分な空白行を削除すること
  • void function()で改行し { は次行に書くこと


デプロイでは、Gitを使用して特定のバージョンやブランチのコードを本番環境(アプリケーションやウェブサイト)に展開させます。

思いつく案としては、GitでROS 2 パッケージをpush後、GitHub Actionsでビルド、テストが実行され、ssh等でロボット側へアクセス&pullでデプロイする形でしょうか。

このあたりは、あくまで私の想定ですので各自調べてくださいね。

GitHub ActionsでROS 2のビルドとテストをする

GitHub ActionsではGitHub Actions の課金についてによると、パブリックリポジトリは無料、プライベートリポジトリでは制限範囲内(使用時間 (分) とストレージ)であれば無料という形になっています。

なので、上記で説明したtestなどをGitHub Actionsで試すためのROS 2パッケージサンプルを以下のように準備しました。

https://github.com/tasada038/ros2_topic_sample

以降、こちらを利用して説明していきます。

Actions用のymlを作成する

まずはpublicリポジトリに移動し、Actionsから.github/workflows/xxx.ymlへGitHub Actions用の設定ファイルを作成します。

デフォルトで準備してあるものを使用しない場合は、Skip this and set up a workflow yourselfを選択してymlを直書きします。

ros2_ci.yml
name: build and test

on:
  push:
    branches: [ master ]
  pull_request:
    branches: [ master ]
  workflow_dispatch:
  schedule:
    - cron: '0 0 * * *'
  release:
    types: [published]

jobs:
  build_and_test:
    strategy:
      matrix:
        os:
          - ubuntu-22.04
        rosdistro:
          - humble

    runs-on: ubuntu-latest

    container:
      image: ros:${{ matrix.rosdistro }}-ros-base

    steps:
      - name: Setup directories
        run: mkdir -p ros2_ws/src
        
      - name: Check out repository
        uses: actions/checkout@v3
        with:
          path: ros2_ws/src/ros2_topic_sample

      - name: Install dependencies
        run: |
          rosdep update && 
          apt-get update && 
          rosdep install --from-path . -i -y --rosdistro ${{ matrix.rosdistro }}

      - name: Install diagnostic-updater
        run: apt-get install ros-${{ matrix.rosdistro }}-diagnostic-updater

      - name: Build tests
        id: build_test
        run: |
          . /opt/ros/${{ matrix.rosdistro }}/setup.sh && 
          colcon build
        continue-on-error: true

      - name: build_test command success
        if: steps.build_test.outcome == 'success'
        run: echo "result - success"

      - name: build_test command failure
        if: steps.build_test.outcome == 'failure'
        run: echo "result - failure" && exit 1

      - name: Run tests
        id: run_test
        run: |
          . /opt/ros/${{ matrix.rosdistro }}/setup.sh &&
          colcon test && 
          colcon test-result
        continue-on-error: true

      - name: run_test command success
        if: steps.run_test.outcome == 'success'
        run: echo "result - success"

      - name: run_test command failure
        if: steps.run_test.outcome == 'failure'
        run: echo "result - failure" && exit 1

GitHub Actionsのワークフロー構文

上記の中身について、備忘録も兼ねて記載します。
GitHub Actionsのワークフロー構文についてはGitHub Docs: GitHub Actions のワークフロー構文もご参照ください。

name要素

name: build and testでは、GitHub Actionsのワークフロー名を指定しています。ここではbuild and testが該当します。

on要素

onでは、どのようなイベントに対してGitHub Actionsのワークフローをトリガーするかを設定します。トリガーにできるイベントは複数個や時間スケジュールも可能です。

push: branches: [master]と記述することで、masterブランチに対してpushイベントが生じたときにワークフローが実行されます。

pull_requestも原理は同様です。

workflow_dispatch: schedule:では定期的に実行する設定をします。

cron: '0 0 * * *'は順に分、時、日、月、曜日なので、毎日0時(UTC: Coordinated Universal Time 協定世界時)に実行されます。

UTCとJST:日本標準時ではおよそ9時間の時差があることを覚えておくとスケジュール設定しやすいと思います。

release: types: [published]はReleaseがPublishされた時にIssueをクローズするために使用します。

jobs要素

jobs: build_and_test:では、ジョブの名前を定義しています。

strategy: matrix: ではジョブ内で使用する変数要素を宣言します。
上記ではos:でubuntu-22.04を、rosdistro:でディストリビューションを宣言しています。

runs-on:はジョブの実行環境を指定し、ubuntu-latestでUbuntuの最新バージョンを指定しています。

container: imageではジョブが実行されるコンテナイメージを指定しており、ros:${{ matrix.rosdistro }}-ros-baseとすることで、ROSのコンテナイメージを宣言しています。

steps:ではジョブ個々のステップを定義し、上から順に実行されます。
-name: はステップ名、run: は実行するコマンドやスクリプトを表します。

continue-on-error: trueを追記することで、コマンドやスクリプトでエラーが発生した場合でも、以降のワークフロー実行を継続します。

if: steps.build_test.outcome == 'success'では、build_testというIDをもつステップが成功した場合に実行されることを意味します。
IDを付与し、outcomeでステップの結果を判断することで、コマンドの成功/失敗によって以降の処理を分岐できる利点があります。

exit 1はGitHub Actionsにおいて、ステップがエラーを示すために使用されるコマンドです。
エラーが発生すると、ジョブもfailureとなりますね。

GitHub ActionsでROS 2ビルドとテストを確認する

変更を加えて、.github/workflow/xxx.yamlのあるリポジトリにpushしてみましょう。

このような形で、successになっていればOKですね。

右上の「・・・」ボタンからCreate status badge > Copy status badge MarkdownでCIのバッチをREADME.mdに貼り付けるとCIでテストしてあることを示せるので良いと思います。

Reference

  • ROS 2 CI

Running Tests in ROS 2 from the Command Line

GitHub: ros2-build-and-test-action

GitHub: ROS 2 CI Infrastructure

GitHub: YumaMatsumura/ros_ci_test

GitHub: ros-tooling/action-ros-ci-template

gitコマンド一覧

GitHub Actionsの記事を書いたので、手元にあるgitコマンド一覧のメモもこちらにまとめておきました。

GitHub Actionsで遊ぶときの参考にしてください。

terminal
# ローカルからリモートへpushするまでの一連の操作
mkdir package_name
cd ./package_name
## Gitリポジトリの初期化
git init

## Gitリポジトリ内の変更されたファイルをステージングエリアへ追加
git add *
git add repo_name

## Gitリポジトリ内での変更一覧を表示
git status

## Gitリポジトリ内の変更をコミット
git commit -m "Initial commit"

## originというリモート名のリモートリポジトリを作成
git remote add origin [remote URL]

## ローカルのGitリポジトリをリモートリポジトリに送信
git push origin master


# その他よく使うgitコマンドたち
## リモートリポジトリの更新をローカルリポジトリに取り込む
## git pull <リモート名> <リモートブランチ名>
git pull origin master

## humble-develブランチをmasterブランチにマージする
git checkout master
git merge humble-devel
git push origin master  # リモートリポジトリにマージをプッシュする

## ブランチの表示
git branch

## 新しいブランチの作成
git branch humble-devel

## ブランチの切り替え stashとか使うのが良い
git checkout humble-devel

## 新しいブランチを作成し、ブランチを切り替える
git checkout -b humble-devel

## 直前のコミットをなかった事にする
git reset --soft HEAD^

## .gitconfigの設定
git config --global user.email "you@example.com"
git config --global user.name "Your Name"

Discussion