GitHub Actions でリークテスト:)
要約
Docker コンテナと Makefile を使ってローカルで行なっていた Valgrind と Sanitizers を用いたリークテストを,Github Actions を用いて,GitHub 上でも行えるようにした.このことにより,リークテストが容易になり,開発スピードが向上した.
序論
42Tokyo では,日々ピアラーニングと課題解決型学習を通して学習に励んでいます.何かを教えてくれる教師やメンターがいないので,自分たちで課題を理解し,問題点を見つけ,解決し,評価しています.評価を行うときには,評価項目に沿って,相手の課題を評価します.その際には,自分が今まで得た知識やテクを生かし,相手のコードのミステイクを見つけたり,コードがより良くなるためのアドバイスをしたり,されたり,議論したり,課題で問われている内容をきちんと理解し,自分で実装できているかを確認したりします.ここで,評価者が発見したフィックスできる,実装者が意図していない挙動,ランタイムエラー,リーク,セグフォは絶対に許容されません.これが曲者で,時間が経ってくると 42Tokyo 内で課題に対する知見が溜まっていき,コードを見る目がどんどん高度になり,課題をサクセスさせることが難しくなっていきます.知識が浅いままで実装をしていると,直ぐにエラーになってしまいますが,もう知り得たエラーパターンの漏れ発見などは煩わしくなってきます.
そこで,ローカルで Docker コンテナと Makefile を用いて行なっていた Valgrind と Sanitizer のリークテストを GitHub Actions を用いて,リポジトリにプッシュしたら自動で走るようにしました.
42 では,Build your own X の精神で,車輪の再発明をどんどん行なっているので,自分でリークチェッカー[1]などを実装できたら良かったのですが,今回は巨人の肩にたくさん乗らせてもらいオンラインでのリークテストを行うようにしました.
ローカルでのリークテスト
Docker コンテナ上で Makefile で設定したコマンドを実行し,リークテストを行なっています.
Valgrind リークテスト
- Valgrind をインストールした Dockerfile を書く.Dockerfile
FROM ubuntu:20.04 RUN apt-get update && \ apt-get upgrade -y && \ apt-get install -y build-essential valgrind && \ rm -fr /var/lib/apt/lists/* WORKDIR /code CMD /bin/bash
-
make valgrind
を実行すると Valgrind テストが実行されるように Makefile を書く.Makefile.PHONY: valgrind valgrind: re valgrind --leak-check=full --show-leak-kinds=all --track-fds=yes ./$(NAME)
- 以下のコマンドを実行して,コンテナ上で Valgrind テストを実行する.Terminal
docker build -t 42docker . docker run -it --rm -v $PWD:/code 42docker make valgrind
Sanitizer リークテスト
- gcc または clang をインストールした Dockerfile を書く.Dockerfile
FROM ubuntu:20.04 RUN apt-get update && \ apt-get upgrade -y && \ apt-get install -y build-essential clang && \ rm -fr /var/lib/apt/lists/* WORKDIR /code CMD /bin/bash
-
make leak
,make address
,make thread
,make memory
を実行するとそれぞれの Sanitizer テストが実行されるように Makefile を書く.MakefileCFLAGS := -Wall -Wextra -Werror .PHONY: leak leak: CFLAGS += -g -fsanitize=leak leak: test .PHONY: address address: CFLAGS += -g -fsanitize=address address: test .PHONY: thread thread: CFLAGS += -g -fsanitize=thread thread: test .PHONY: memory memory: CFLAGS += -g -fsanitize=memory memory: test .PHONY: test test: re ./$(NAME)
- 以下のコマンドを実行して,コンテナ上で Sanitizer テストを実行する.Terminal
docker build -t 42docker . docker run -it --rm -v $PWD:/code 42docker make leak docker run -it --rm -v $PWD:/code 42docker make address docker run -it --rm -v $PWD:/code 42docker make thread docker run -it --rm -v $PWD:/code 42docker make memory
オンラインでのリークテスト
Github Actions を用いて同様のリークテストができるようにします.ローカルで使用していた Makefile と同様のものを使って.
Valgrind リークテスト
CI 環境に直接 Valgrind をインストールする方法
- CI 環境に Valgrind をインストールする GitHub Action を書く..github/workflows/valgrind.yml
name: Valgrind on: [ push, pull_request ] jobs: Valgrind: runs-on: ubuntu-latest steps: - uses: actions/checkout@v2 - name: install valgrind run: | sudo apt update sudo apt install -y valgrind - name: Run Valgrind run: make valgrind
Docker containe action を用いる方法
- Github Actions 用の Valgrind をインストールした Dockerfile を書いて,dockerhub か ghcr に置く.Dockerfile
FROM ubuntu:20.04 RUN apt-get update && \ apt-get upgrade -y && \ apt-get install -y build-essential valgrind clang && \ rm -fr /var/lib/apt/lists/* WORKDIR /code ENTRYPOINT ["valgrind --leak-check=full --show-leak-kinds=all ./a.out"]
- 上記を実行する Docker container action を書いて,マーケットプレイスに公開する.action.yml
name: '42valgrind Leak checker' description: 'Run valgrind on ubuntu-latest' branding: icon: 'play-circle' color: 'green' inputs: flags: description: 'Flags passed to valgrind' required: true default: '.' runs: using: 'docker' image: 'docker://solareenlo/42valgrind:latest' entrypoint: /bin/bash args: - -c - ${{ inputs.flags }}
- 上記を実行する GitHub action を書く..github/workflows/valgrind.yml
name: Valgrind on: [ push, pull_request ] jobs: valgrind: runs-on: ubuntu-latest name: 42valgrind steps: - uses: actions/checkout@v2 - name: 42valgrind Leak checker uses: solareenlo/42valgrind-action@v1.0.3 with: flags: 'make valgrind'
Sanitizer リークテスト
- CI 環境に Sanitizers を実行する GitHub Action を書く..github/workflows/sanitizers.yml
name: Sanitizers on: [ push, pull_request ] jobs: Sanitizers: runs-on: ubuntu-latest steps: - uses: actions/checkout@v2 - name: Run Sanitizers run: | make leak make address make thread make memory
これでリポジトリにプッシュすると,Valgrind, Sanitizers のリークテストが自動で走るようになりました.(これらを使用したリポジトリ例:42ft_containers, 42CPP_Module_08_2021).
結論
- オンラインでもリークテストができるようになり,便利かつ時短になって,大変満足だが,評価環境とリークテスト環境とに若干の差異があるので気を付ける.
- reviewdog でリークテストのエラーが自動でプルリクされるようにする.
- 他のテストもどんどん追加する.
- こんな感じでいろんなことを自動化する.
- もっと早くにやっておけば良かったです orz.
製作物
謝辞
オープンソースで,いろんな便利なツールが公開されていて,本当に感謝です.
42Tokyo では,個々人のペースで自由にいろんなことが勉強できて,本当に感謝です.
42Tokyo に関わる皆さんには,いろんなことを優しく教えてくださり,本当に感謝です.
Discussion