Skip to content

GitHub Actions CI Build Matrix Guide

Using the .github/workflows/docker-build-matrix.yml workflow (docker-build-matrix.yml), automatically build and test the four Docker build modes (source/wheel/cython/nuitka).

Table of Contents

  1. Workflow Overview
  2. Workflow Structure
  3. Trigger Conditions
  4. Matrix Configuration
  5. Step Details
  6. Local Execution
  7. Troubleshooting
  8. Customization

Workflow Overview

This workflow executes the following:

  1. Matrix Build: Build four modes (source/wheel/cython/nuitka) in parallel
  2. Post-Build Test: Proper validation for each mode
  3. Success Notification: Report once all builds complete
Trigger (PR/Push) 
        ↓
        ├─→ Build mode: source   → Test source imports
        ├─→ Build mode: wheel    → Test wheel imports
        ├─→ Build mode: cython   → Test cython imports
        └─→ Build mode: nuitka   → Test binary existence

All complete -> ✅ Success / ❌ Failure

Runtime

  • Cold full run: 60-80 minutes (15-50 min per mode)
  • With caching: 30-40 minutes (utilizing Docker layer cache)
  • Parallel execution: Matrix runs 4 jobs concurrently

Resource Usage

  • CPU Cores: 4 parallel (GitHub Actions runners)
  • Disk Space: ~50GB required per job
  • Timeout: 360 minutes/job (GitHub Actions default)

Workflow Structure

File Location

.github/
├── workflows/
│   └── docker-build-matrix.yml   ← このワークフロー

ワークフロー定義(概要)

name: Docker Build Matrix

on:
  push:
    branches: [main, develop]
    paths:
      - Dockerfile
      - scripts/protect_with_cython.py
      - scripts/build_nuitka_api_binary.py
      - README.md
      - README.ja.md
      - pyproject.toml
      - .github/workflows/docker-build-matrix.yml
  pull_request:
    branches: [main]

jobs:
  build-matrix:
    runs-on: ubuntu-latest
    strategy:
      matrix:
        mode: [source, wheel, cython, nuitka]
      fail-fast: false  # 1つのモード失敗でも他のモードは継続

    steps:
      # ... 各ステップは以下で詳述

Trigger Conditions

アクティベーション条件

このワークフローは以下の場合に実行されます:

トリガー 対象 実行条件
push main/develop ブランチ Dockerfile など関連ファイル変更時
pull_request main ブランチ PR 作成・更新時
manual 任意 GitHub Actions UI から手動実行

パス指定(自動フィルタ)

paths:
  - Dockerfile              # メイン Dockerfile 変更時
  - scripts/protect_*       # Cython/Nuitka スクリプト変更時
  - README.md              # README ドキュメント変更時
  - pyproject.toml         # パッケージ定義変更時
  - .github/workflows/*    # ワークフロー定義自体の変更時

手動実行

GitHub UI から手動トリガー:

Actions → Docker Build Matrix → Run workflow → Branch: main → Run

Matrix Configuration

4つのビルドモード定義

strategy:
  matrix:
    mode: [source, wheel, cython, nuitka]
    include:
      - mode: source
        target: runtime
        tag_suffix: latest
      - mode: wheel
        target: runtime-wheel
        tag_suffix: wheel
      - mode: cython
        target: runtime-cython
        tag_suffix: cython
      - mode: nuitka
        target: runtime-nuitka
        tag_suffix: nuitka
モード Docker ターゲット イメージタグ 用途
source runtime latest 開発・デバッグ
wheel runtime-wheel wheel ステージング
cython runtime-cython cython プリプロ
nuitka runtime-nuitka nuitka 本番

並列実行と失敗処理

fail-fast: false  # 1つのモード失敗でも他のモードは継続(推奨)
  • fail-fast: true の場合、1つのモードが失敗するとマトリックス全体が停止
  • fail-fast: false の場合、すべてのモードが独立して実行(推奨)

Step Details

Step 1: コード取得

- uses: actions/checkout@v4
  with:
    fetch-depth: 0

目的: リポジトリコード取得、タグ情報も含める

出力: - ${{ github.workspace }} = /home/runner/work/EvoSpikeNet-Core/EvoSpikeNet-Core - Dockerfile, scripts/, README.md など全ファイル利用可能


Step 2: Docker Buildx セットアップ

- name: Set up Docker Buildx
  uses: docker/setup-buildx-action@v3

目的: マルチプラットフォーム(linux/amd64, linux/arm64)対応ビルダーの設定

機能: - マルチステージビルドサポート(必須) - Docker レイヤーキャッシュ(gha キャッシュ) - イメージ署名サポート(オプション)


Step 3: メタデータ抽出

- name: Extract metadata
  id: meta
  uses: docker/metadata-action@v5
  with:
    images: ghcr.io/${{ github.repository }}/evospikenet
    tags: |
      type=ref,event=branch,suffix=-${{ matrix.tag_suffix }}
      type=semver,pattern={{version}},suffix=-${{ matrix.tag_suffix }}
      type=sha,suffix=-${{ matrix.tag_suffix }}

目的: イメージタグルールを定義

生成されるタグ例:

トリガー 生成タグ
push to main ghcr.io/.../evospikenet:main-latest
push tag v1.0.0 ghcr.io/.../evospikenet:1.0.0-latest
push to PR ghcr.io/.../evospikenet:pr-123-latest
git sha ghcr.io/.../evospikenet:abc1234-latest

Step 4: Docker イメージビルド

- name: Build and push Docker image
  uses: docker/build-push-action@v5
  with:
    context: ./EvoSpikeNet-Core
    target: ${{ matrix.target }}
    build-args: |
      APP_IMAGE_MODE=${{ matrix.mode }}
      BASE_IMAGE=ubuntu:22.04
      ENABLE_GPU=false
    push: false  # PR 時はプッシュなし
    tags: ${{ steps.meta.outputs.tags }}
    labels: ${{ steps.meta.outputs.labels }}
    cache-from: type=gha
    cache-to: type=gha,mode=max

パラメータ説明:

パラメータ 説明
context ./EvoSpikeNet-Core ビルドコンテキスト(Dockerfile の場所)
target runtime など Dockerfile の FROM ターゲット
build-args APP_IMAGE_MODE=source など ビルド引数(--build-arg 相当)
push false (PR) / true (main push) レジストリにプッシュするか
cache-from/to type=gha GitHub Actions キャッシュを使用

ビルド時間(初回):

source:  2-3 分
wheel:   5-8 分
cython:  15-20 分
nuitka:  40-50 分
-------
合計:    60-80 分

Step 5: ポストビルドテスト

5a. source/wheel/cython: Python モジュールテスト

- name: Test module imports
  run: |
    docker run --rm ${{ steps.build.outputs.imageid }} python -c \
      "import evospikenet.api; print('✓ API import OK')"

テスト内容: - evospikenet.api モジュールのインポート - 基本的な関数定義確認

失敗時の対応:

# ステップが失敗するとワークフロー全体が ❌ 状態に
echo "❌ Module import failed"
exit 1

5b. nuitka: バイナリ存在確認

- name: Test Nuitka binary
  run: |
    docker run --rm ${{ steps.build.outputs.imageid }} \
      test -x /tmp/nuitka-dist/evospikenet-api && \
      echo "✓ Nuitka binary OK" || exit 1

テスト内容: - /tmp/nuitka-dist/evospikenet-api ファイルが存在 - 実行可能(-x)


Step 6: 結果レポート

- name: Report build result
  if: always()  # 成功/失敗に関わらず実行
  run: |
    echo "Build Status: ${{ job.status }}"
    echo "Mode: ${{ matrix.mode }}"
    echo "Image: ${{ steps.meta.outputs.tags }}"

Local Execution

GitHub Actions を手元で実行(act ツール)

# act をインストール(Ubuntu)
curl https://raw.githubusercontent.com/nektos/act/master/install.sh | bash

# ワークフロー実行
cd /path/to/EvoSpikeNet-Core
act --job build-matrix -l

# 特定のモードのみ実行
act --job build-matrix -e events.json  # events.json で matrix 指定

マトリックス実行の Docker コマンド例

ワークフロー内の docker build コマンドをローカルで再現:

# source モード
docker build \
  --build-arg APP_IMAGE_MODE=source \
  --target runtime \
  -t evospikenet:test-source \
  ./EvoSpikeNet-Core

# wheel モード
docker build \
  --build-arg APP_IMAGE_MODE=wheel \
  --target runtime-wheel \
  -t evospikenet:test-wheel \
  ./EvoSpikeNet-Core

# cython モード
docker build \
  --build-arg APP_IMAGE_MODE=cython \
  --target runtime-cython \
  -t evospikenet:test-cython \
  ./EvoSpikeNet-Core

# nuitka モード(時間がかかる)
docker build \
  --build-arg APP_IMAGE_MODE=nuitka \
  --target runtime-nuitka \
  -t evospikenet:test-nuitka \
  ./EvoSpikeNet-Core

テストスクリプト

scripts/test-all-docker-modes.sh:

#!/bin/bash
set -e

echo "Testing all Docker build modes..."

MODES=(source wheel cython nuitka)
TARGETS=(runtime runtime-wheel runtime-cython runtime-nuitka)

for i in "${!MODES[@]}"; do
  mode=${MODES[$i]}
  target=${TARGETS[$i]}

  echo ""
  echo "=== Building $mode mode (target: $target) ==="

  docker build \
    --build-arg APP_IMAGE_MODE=$mode \
    --target $target \
    -t evospikenet:test-$mode \
    ./EvoSpikeNet-Core

  # テスト実行
  echo "Testing $mode mode..."
  if [[ "$mode" == "nuitka" ]]; then
    docker run --rm evospikenet:test-$mode \
      test -x /tmp/nuitka-dist/evospikenet-api && \
      echo "✓ $mode mode OK" || (echo "❌ $mode mode FAILED"; exit 1)
  else
    docker run --rm evospikenet:test-$mode python -c \
      "import evospikenet.api; print('✓ $mode mode OK')" || \
      (echo "❌ $mode mode FAILED"; exit 1)
  fi
done

echo ""
echo "✅ All modes passed!"

実行:

chmod +x scripts/test-all-docker-modes.sh
./scripts/test-all-docker-modes.sh

Troubleshooting

エラー: "Out of disk space"

GitHub Actions ランナーのディスク容量不足。

# 対策: キャッシュクリーンアップ
- name: Clean up Docker build cache
  run: docker builder prune -a --force

エラー: "Nuitka compilation timeout"

Nuitka バイナリ化に時間がかかりすぎた。

# 対策: タイムアウト増加
timeout-minutes: 120  # デフォルト 360 分から明示的に指定

エラー: "Matrix job failed"

特定のモードのビルルが失敗。ワークフロー実行ログを確認:

Actions → [ワークフロー実行] → [失敗したジョブ] → ログを展開

イメージが大きすぎる

# イメージサイズ確認
docker images evospikenet:test-*
docker inspect --format='{{.VirtualSize}}' evospikenet:test-nuitka

キャッシュが効かない

# 対策: キャッシュキーをリセット(すべてのレイヤーを再ビルド)
cache-from: type=gha,scope=${{ github.ref }}
cache-to: type=gha,mode=max,scope=${{ github.ref }}

Customization

モード追加(例: wheel+GPU)

strategy:
  matrix:
    mode: [source, wheel, cython, nuitka, wheel-gpu]
    include:
      # ... 既存のモード ...
      - mode: wheel-gpu
        target: runtime-wheel
        tag_suffix: wheel-gpu
        build_args: |
          APP_IMAGE_MODE=wheel
          BASE_IMAGE=nvidia/cuda:12.4.1
          ENABLE_GPU=true

特定のブランチのみビルド

on:
  push:
    branches:
      - main
      - develop
      - release/*  # release/* ブランチも対象

スケジュール実行(定期ビルド)

on:
  schedule:
    - cron: '0 2 * * 0'  # 毎週日曜 2:00 UTC

手動実行パラメータ

on:
  workflow_dispatch:
    inputs:
      build_mode:
        description: 'Build mode'
        required: true
        default: 'all'
        type: choice
        options:
          - all
          - source
          - wheel
          - cython
          - nuitka

使用方法:

jobs:
  build-matrix:
    runs-on: ubuntu-latest
    strategy:
      matrix:
        mode: ${{ github.event.inputs.build_mode == 'all' && 
                  fromJson('["source","wheel","cython","nuitka"]') || 
                  fromJson(format('["{0}"]', github.event.inputs.build_mode)) }}

パフォーマンス最適化

1. キャッシュ戦略

cache-from: type=gha,scope=${{ github.workflow }}-${{ github.ref }}
cache-to: type=gha,mode=max,scope=${{ github.workflow }}-${{ github.ref }}

効果: 2 回目以降のビルドが 50% 以上高速化

2. 不要なモードをスキップ

strategy:
  matrix:
    mode: [source, wheel, cython, nuitka]
    exclude:
      - mode: nuitka
        # PR ではnuitka をスキップ(時間節約)
        if: ${{ github.event_name == 'pull_request' }}

3. 並列ジョブ数制限

concurrency:
  group: docker-build-${{ github.ref }}
  cancel-in-progress: true

効果: 同じブランチで複数実行を防ぐ


関連ドキュメント