- CI(GitHub Actions)って何?一言でいうと「プッシュした瞬間に“自動でテストしてくれるロボット”」
- まずは「最小のPython用CI」をイメージで掴む
- GitHub Actions のワークフローを具体的に見てみる
- 重要ポイント1:CIは「ローカルでやっていることを、他人のマシンで再現する」もの
- 重要ポイント2:テスト・型チェック・Lint を「分けて」考える
- 重要ポイント3:Pull Request と CI をセットで考える
- 重要ポイント4:フォルダ構成標準化とCIはセットで効いてくる
- 初心者が「最初のCI」を入れるときのステップ
- まとめ(CI × GitHub Actions は「未来の自分を守る自動テスト係」)
CI(GitHub Actions)って何?一言でいうと「プッシュした瞬間に“自動でテストしてくれるロボット”」
CI(Continuous Integration)は、「コードを少し変更するたびに、自動でテストやチェックを回して、壊れていないかを常に確認し続ける仕組み」です。
GitHub Actions は、その CI を GitHub 上で簡単に動かせる“自動実行ロボット”だと思ってください。
あなたが git push した瞬間に、
テストを実行する
型チェック(mypy)を回す
Lint(ruff, flake8 など)を回す
といったことを、GitHub が勝手にやってくれます。
「人間がうっかり壊したコードを main に混ぜない」ための安全装置です。
まずは「最小のPython用CI」をイメージで掴む
どんなことが自動で行われるのか
例えば、こんな Python プロジェクトを想像してください。
src/ にアプリ本体tests/ にテスト
普段はローカルでこうやってテストを回しているとします。
pytest
これを「GitHub に push したときにも自動でやってほしい」のが CI です。
GitHub Actions では、リポジトリの中に
.github/
workflows/
ci.yml
というファイルを置いて、「こういう手順でテストしてね」と書きます。
GitHub Actions のワークフローを具体的に見てみる
一番シンプルな Python CI の例
例えば、こんな ci.yml を置きます。
name: CI
on:
push:
branches: [ main ]
pull_request:
branches: [ main ]
jobs:
test:
runs-on: ubuntu-latest
steps:
- name: Checkout
uses: actions/checkout@v4
- name: Set up Python
uses: actions/setup-python@v5
with:
python-version: "3.12"
- name: Install dependencies
run: |
pip install -U pip
pip install -e .[dev]
- name: Run tests
run: |
pytest
YAMLこれを噛み砕いて説明します。
on:
いつ動かすか。ここでは main ブランチへの push と、main に向けた Pull Request のとき。
jobs:
実行する「仕事」の定義。ここでは test というジョブが一つ。
runs-on:
どんな環境で動かすか。ubuntu-latest は「GitHub が用意してくれる Ubuntu マシン」。
steps:
そのジョブの中で、何を順番にやるか。
actions/checkout でリポジトリのコードを取ってくるactions/setup-python で Python のバージョンを指定するpip install で依存関係を入れるpytest を実行する
これだけで、「push したら自動で pytest が走る」状態になります。
重要ポイント1:CIは「ローカルでやっていることを、他人のマシンで再現する」もの
ローカルでできていないことは、CIでもできない
CI を考えるときの大事な視点は、
「ローカルで手動でやっている一連の作業を、そのまま YAML に書く」
ということです。
普段あなたが、
仮想環境を作る
依存をインストールする
テストを実行する
という流れで開発しているなら、
それをそのまま GitHub Actions の steps に落とし込めばいい。
逆に言うと、
ローカルでテストがまともに回っていない状態で CI を入れても、
ただ「失敗する自動化」ができるだけです。
だから順番としては、
ローカルで pytest や mypy を安定して回せるようにする
そのコマンドを GitHub Actions に書く
という流れが自然です。
重要ポイント2:テスト・型チェック・Lint を「分けて」考える
1つのCIで複数のチェックを回す
Python の品質チェックは、だいたい次の3つに分かれます。
テスト(pytest)
型チェック(mypy)
Lint(ruff, flake8 など)
これらを CI で全部回すのが理想です。
例えば、こういう構成にできます。
jobs:
test:
runs-on: ubuntu-latest
steps:
... # さっきと同じ
- name: Run tests
run: pytest
lint:
runs-on: ubuntu-latest
steps:
...
- name: Run ruff
run: ruff check .
typecheck:
runs-on: ubuntu-latest
steps:
...
- name: Run mypy
run: mypy src tests
YAMLポイントは、「ジョブを分けると、どこで落ちたかが一目で分かる」ことです。
テストが落ちたのか
型チェックが落ちたのか
Lint が落ちたのか
これが分かるだけで、修正のストレスがかなり減ります。
重要ポイント3:Pull Request と CI をセットで考える
「CIが通らないとマージできない」状態を作る
GitHub では、ブランチ保護ルールを使って、
「CI が成功していない Pull Request は main にマージできない」
という設定ができます。
これを有効にすると、
テストが落ちているコード
型チェックが通っていないコード
Lint がボロボロなコード
が main に混ざるのを防げます。
つまり、CI は「レビュー前の最低ラインチェック」を自動でやってくれる存在になります。
人間のレビューは「設計・命名・仕様」などに集中できるようになり、
テスト落ち・フォーマット崩れのような機械的な指摘は CI に任せられます。
重要ポイント4:フォルダ構成標準化とCIはセットで効いてくる
src/ と tests/ を前提にしたCIを書く
フォルダ構成を標準化しておくと、CI の設定もテンプレート化しやすくなります。
例えば、
ソースコードは src/
テストは tests/
という前提なら、mypy や pytest のコマンドはだいたいこうなります。
pytest
mypy src tests
ruff check src tests
これを GitHub Actions にそのまま書けばいい。
プロジェクトごとに「どこにコードがあるか」を考え直さなくて済むので、
CI の導入コストが一気に下がります。
初心者が「最初のCI」を入れるときのステップ
ステップ1:ローカルで pytest を安定して回せるようにする
まずは、ローカルで
pytest
が普通に通る状態にしておきます。
ここがぐらついていると、CI も当然ぐらつきます。
ステップ2:最小の ci.yml を置いてみる
さきほどの「テストだけ回す」CI を、そのまま .github/workflows/ci.yml に置いてみます。
push して、GitHub の「Actions」タブを開くと、
実際に CI が動いている様子が見られます。
ここで一度、「自分のテストが他人のマシンでも再現できている」感覚を掴むのが大事です。
ステップ3:慣れてきたら mypy や ruff を足していく
テストが安定してきたら、
次は型チェック(mypy)や Lint(ruff)を CI に追加していきます。
いきなり全部を完璧にしようとしなくてよくて、
まずはテストだけ
次に Lint
最後に型チェック
のように、少しずつ育てていくイメージで十分です。
まとめ(CI × GitHub Actions は「未来の自分を守る自動テスト係」)
初心者目線で整理すると、CI(GitHub Actions)はこういう存在です。
GitHub に push / PR したタイミングで、自動でテスト・型チェック・Lint を回して、「壊れたコードが main に混ざる」のを防ぐ仕組み。
やっていることの本質は「ローカルで手動でやっている一連のコマンドを、YAML に書いて他人のマシン(GitHub)で再現している」だけで、難しい魔法ではない。
フォルダ構成(src / tests)やツール(pytest / mypy / ruff)を標準化しておくと、CI の設定もテンプレート化できて、新しいプロジェクトでもすぐに「自動テスト係」を雇えるようになる。
