0
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

【C言語×GitHub Actions CI#1】組込みC言語プロジェクトにCIを導入する:概要・構成編

0
Posted at

はじめに

組み込みソフトウェア開発では、C言語プロジェクトへのCI導入は「やりたいけど設定が面倒」と後回しになりがちです。
今回、GitHub Actionsを使ってC言語プロジェクトのCI環境をゼロから構築してみました。

自動化した内容は以下の4つです。

  • ビルド(make)
  • 単体テスト(GoogleTest)
  • 静的コード解析(cppcheck)
  • カバレッジ計測(gcovr / lcov)

また、構築にあたってGitHub Copilotも活用しました。設定ファイルや定型コードの生成に役立った点や、ハマりどころについては#4でまとめています。

サンプルコードはこちらで公開しています。
https://github.com/YusukeHarada/c-sample

本記事は全5部構成のシリーズです。

  • #1(本記事):概要・構成編 ← いまここ
  • #2:ビルド・単体テスト編
  • #3:静的解析・カバレッジ編
  • #4:ハマりどころ編
  • #5:GitLab経験者向けワークフロー構文解説

作ったものの全体像

リポジトリ構成

c-sample/
├── main.c               # プログラム本体(add / multiply / run_program)
├── main.h               # ヘッダファイル(extern "C" ガード付き)
├── test_main.cc         # GoogleTestによる単体テスト(C++)
├── makefile             # ビルド・テスト・解析・カバレッジをまとめて管理
└── .github/
    └── workflows/
        └── ci.yml       # GitHub Actions ワークフロー定義

プログラム本体は addmultiply という2つの関数と、それらを呼び出す run_program で構成されたシンプルなサンプルです。CI環境の構築方法を示すことが目的なので、コード自体はシンプルに保っています。

CIで自動化している内容

ステップ ツール 内容
ビルド gcc / make メインプログラムのビルド確認
単体テスト GoogleTest 関数レベルのテスト実行
静的解析 cppcheck コード品質チェック
警告チェック gcc (-Wall -Wextra -Werror) 厳密なコンパイル確認
カバレッジ計測 gcovr / lcov C0カバレッジ計測・HTMLレポート生成

スクリーンショット 2026-04-22 20.52.12.png


GitHub Actionsワークフローの概要

.github/workflows/ci.yml の全体像です。

name: CI Build

on:
  push:
    branches: [ main ]
  pull_request:
    branches: [ main ]

jobs:
  build:
    runs-on: ubuntu-latest

    steps:
    - uses: actions/checkout@v4

    - name: Install dependencies
      run: |
        sudo apt-get update
        sudo apt-get install -y build-essential pkg-config libgtest-dev cppcheck gcovr lcov

    - name: Build with make
      run: make

    - name: Run unit tests
      id: test
      run: make test

    - name: Static code analysis with cppcheck
      id: cppcheck
      run: cppcheck --enable=all --suppress=missingIncludeSystem --error-exitcode=1 main.c main.h

    - name: Build check with strict warnings
      id: build_check
      run: gcc -Wall -Wextra -Werror -c main.c -o /tmp/main_check.o

    - name: Run coverage measurement
      id: coverage
      run: make coverage
      continue-on-error: true

    - name: Generate HTML coverage report
      id: coverage_html
      run: make coverage-html
      continue-on-error: true

    - name: Check coverage directory
      run: ls -la out/ || echo "out directory does not exist"
      continue-on-error: true

    - name: Upload coverage reports
      uses: actions/upload-artifact@v4
      if: always() && hashFiles('out/coverage/**') != ''
      with:
        name: coverage-report
        path: out/coverage/
        if-no-files-found: warn

    - name: Final status check
      if: always()
      run: |
        if [[ "${{ steps.test.outcome }}" == "success" && "${{ steps.cppcheck.outcome }}" == "success" && "${{ steps.build_check.outcome }}" == "success" ]]; then
          echo "🎉 All CI checks passed successfully!"
          echo "✅ Build: OK"
          echo "✅ Tests: OK"
          echo "✅ Static Analysis: OK"
          echo "✅ Warnings Check: OK"
          echo "✅ Coverage: Generated (check artifacts)"
          exit 0
        else
          echo "❌ Some CI checks failed!"
          echo "Build: ${{ steps.test.outcome == 'success' && '✅ OK' || '❌ FAILED' }}"
          echo "Tests: ${{ steps.cppcheck.outcome == 'success' && '✅ OK' || '❌ FAILED' }}"
          echo "Static Analysis: ${{ steps.build_check.outcome == 'success' && '✅ OK' || '❌ FAILED' }}"
          echo "Warnings Check: ${{ steps.coverage.outcome == 'success' && '✅ OK' || '⚠️  SKIPPED' }}"
          echo "Coverage: ${{ steps.coverage_html.outcome == 'success' && '✅ OK' || '⚠️  SKIPPED' }}"
          exit 1
        fi

    - name: Clean up
      if: always()
      run: make clean

トリガー条件

main ブランチへのpushおよびpull requestをトリガーとしています。

on:
  push:
    branches: [ main ]
  pull_request:
    branches: [ main ]

依存ライブラリのインストール

必要なツールをまとめて1ステップでインストールしています。

- name: Install dependencies
  run: |
    sudo apt-get update
    sudo apt-get install -y build-essential pkg-config libgtest-dev cppcheck gcovr lcov

CI結果のサマリー表示(Final status check)

各ステップに id を付与し、最終ステップで全体の成否をまとめて表示するようにしています。

- name: Final status check
  if: always()
  run: |
    if [[ "${{ steps.test.outcome }}" == "success" && ... ]]; then
      echo "🎉 All CI checks passed successfully!"
      echo "✅ Build: OK"
      echo "✅ Tests: OK"
      ...
    else
      echo "❌ Some CI checks failed!"
      ...
      exit 1
    fi

成功時・失敗時の表示イメージはこのようになります。

成功時:

🎉 All CI checks passed successfully!
✅ Build: OK
✅ Tests: OK
✅ Static Analysis: OK
✅ Warnings Check: OK
✅ Coverage: Generated (check artifacts)

スクリーンショット 2026-04-22 20.54.17.png

失敗時:

❌ Some CI checks failed!

ビルドやテストが通ってもカバレッジが取れなかった場合は ⚠️ SKIPPED として扱い、CIを失敗扱いにしない設計にしています(カバレッジステップには continue-on-error: true を指定)。


まとめ

本記事では、CI環境の全体像とワークフローの概要を紹介しました。
次回以降で各ステップの詳細を解説していきます。

0
1
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?