GitHub Actions と GitLab CI/CD の両方を使ったことがある人なら、きっと一度はこう思ったことがあるはずです。
「似ているようで、全然違う」
どちらも YAML で CI/CD を定義し、同じようなトリガーで処理が動きます。
それでも実務では、設計の考え始め方や処理の組み立て方の違いによって、拡張性や再利用のしやすさ、運用の感覚に差が出てきます。
この記事では、機能の優劣を比べるのではなく設計の寄りどころの違いという視点から、GitHub Actions と GitLab CI/CD を実務向けに整理します。
1. 設計の考え始めが違うと、処理の流れ方も変わる
まず大前提として、GitHub Actions も GitLab CI/CD も
push / PR(MR) / schedule / manual / API などのトリガー条件で実行が始まる点は同じです。
違いが出てくるのは、トリガーが発生したあとどう組み立てていくかという部分です。
GitHub Actions の場合
GitHub Actions では、発生したイベントを起点に処理を考えていく形になりやすいです。
- push されたら何をするか
- PR が作られたら何をするか
- 手動実行されたら何をするか
といったようにイベントごとに実行したい処理を整理し、それぞれに workflow を割り当てるという構成になりがちです。
そのため処理は「イベント単位」で分かれ、後から if や context を使って細かく条件分岐を足していくケースが増えます。
GitLab CI/CD の場合
GitLab CI/CD では、プロジェクト全体の CI の流れを先に決めてから設計する形になりやすいです。
- build
- test
- deploy
といった処理の順序をまず定義し、その流れの中で「この job はどの条件のときに実行するか」を調整していきます。
そのため 1 本のパイプラインの中を条件によって通したり止めたりする構成になりやすく、全体像を把握しやすい形に落ち着きます。
比較
この設計の考え始めの違いが、結果としてトリガー後の処理の流れ方の違いとして表れます。
| 観点 | GitHub Actions | GitLab CI/CD |
|---|---|---|
| 実行のきっかけ |
on(push / PR / schedule / dispatch など) |
push / MR / schedule / manual / API など |
| トリガー後の処理の流れ | イベントごとに workflow を組み立てる |
パイプラインの流れに job を配置する |
| 設計で意識しやすいポイント | イベントと処理の対応関係 | 処理全体の順序と通過条件 |
どちらが優れているという話ではなく、設計の組み立て方が違うだけです。
2. 再利用・共通化の方向性
| 観点 | GitHub Actions | GitLab CI/CD |
|---|---|---|
| jobの再利用 | reusable workflows (workflow_call) |
extends / include
|
| stepの再利用 | Composite Actions | YAMLテンプレ + anchor / include |
| 再利用の文化 | Marketplace文化が強い | テンプレ構造化文化が強い |
GitHub Actions も GitLab CI/CD も、どちらも CI を分割・再利用できます。
一見すると「どちらも部品化して呼び出しているだけ」に見えますが、部品として切り出す“粒度”と“レイヤー” に違いがあります。
GitHub Actions の再利用イメージ
GitHub Actions では、共通化したい処理の粒度によって切り出し先が自然に分かれます。
-
stepレベルの共通処理
→Composite Action
(lint、build コマンド、共通セットアップなど関数のようなもの) -
job(またはjob群)レベルの共通処理
→ reusable workflow
(test job 一式、deploy job 一式などサブルーチンのようなもの)
workflow はそれらを 組み合わせる側 に立ち、「どの job を持ち、どの step を呼ぶか」は各リポジトリが決める構成になります。
結果として、
- 再利用されるのは 処理そのもの
- CI 全体の構成は リポジトリごとに保持される
という形になりやすく、柔軟で組み替えやすい反面、構造を揃えるには工夫が必要になります。
GitLab CI/CD の再利用イメージ
GitLab CI/CD では、stages や job 構成を含んだCI テンプレートを用意し、各リポジトリはそれを include / extends して使います。
この構成では、テンプレート側で CI の基本構造を揃えつつ、
各リポジトリ側で変数の上書きや job の有効/無効を調整できます。
たとえば、
- 変数を上書きして挙動を切り替える
- 特定の job を無効化する
- job の一部だけ設定を差し替える
といったことを、テンプレートを壊さずに行えます。
そのため全体としては、
- 再利用されるのは 処理だけでなく CI の構造全体
- CI の流れは テンプレート側で一元管理
- 各リポジトリは 差分(変数・有効化設定など)だけを書く
という形になり、CI の構造を揃えつつ、リポジトリごとの違いも吸収しやすい構成になります。
この違いが効いてくる場面
小規模なうちは、両者の違いはほとんど表に出ません。
しかし、
- リポジトリ数が増えた
- CI の構成を全体で揃えたくなった
- デプロイフローを一括で変更したくなった
といった段階になると、差がはっきりします。
-
GitHub Actions
→step/job単位で部品をどう組み合わせるか を調整する -
GitLab CI/CD
→ 構造テンプレを直すだけで全体に反映できる
という違いになります。
3. 並列実行(matrix)の考え方
GitHub Actions と GitLab CI/CD の matrix(並列実行)は、単一軸の並列化であれば、実質的にほぼ同じことができます。
# GitHub Actions
matrix:
node: [16, 18, 20]
# GitLab CI/CD
parallel:
matrix:
- NODE_VERSION: ["16", "18", "20"]
どちらも「Node.js 16 / 18 / 20 で同じ job を並列実行する」という意味では差はありません。
違いが見えてくるのは、
- 並列化の軸が複数になったとき
- 実行したくない組み合わせを除外したいとき
- 特定の組み合わせだけを追加したいとき
といった少し複雑な条件を扱い始めた場面です。
matrix の考え方を整理すると、次のような違いになります。
| 観点 | GitHub Actions | GitLab CI/CD |
|---|---|---|
| 単一軸の並列化 | ほぼ同じ | ほぼ同じ |
| 複数軸の展開 | 直積として自動展開される | 組み合わせを定義する感覚 |
| 除外・例外の扱い |
matrix 機能として用意されている |
組み合わせの書き方で調整する |
| 読み取りやすさ | 軸の意図が分かりやすい | 実行パターンが明示的 |
GitHub Actions の場合
GitHub Actions の matrix は、軸を増やすと自動的に直積で job が展開される 仕組みです。
strategy:
matrix:
node: [16, 18]
os: [ubuntu-latest, windows-latest]
この例では、
- node × os
- 2 × 2 = 4 job
が自動的に生成されます。
さらに GitHub Actions では、exclude や include を使って展開後の組み合わせを調整できます。
strategy:
matrix:
node: [16, 18]
os: [ubuntu-latest, windows-latest]
exclude:
- node: 16
os: windows-latest
include:
- node: 20
os: ubuntu-latest
このように、
- まず軸を並べて全体を展開
- そのあとで不要な組み合わせを除外・追加
という 「展開 → 調整」 の流れで考えるのが GitHub Actions の matrix です。
並列条件がシンプルなうちは非常に書きやすい一方で、軸や例外が増えると「最終的にどの job が動くのか」を把握しづらくなることがあります。
GitLab CI/CD の場合
GitLab CI/CD でも parallel:matrix: を使えば複数軸を扱えますが、発想はやや異なります。
test:
script:
- npm test
parallel:
matrix:
- NODE: ["16", "18"]
OS: ["ubuntu", "windows"]
結果として実行される job は GitHub と同じですが、GitLab では 「どの変数の組み合わせで job を複製するか」 を定義している感覚に近くなります。
除外や例外を扱う場合は、GitHub のような専用構文を使うというより、実行したい組み合わせを明示的に書く 方向に寄りがちです。
parallel:
matrix:
- NODE: "16"
OS: "ubuntu"
- NODE: "18"
OS: "ubuntu"
- NODE: "18"
OS: "windows"
このように、
- 実行したいパターンだけを列挙する
- 不要な組み合わせは最初から書かない
という形になりやすく、「どの job が動くか」を YAML から読み取りやすい という特徴があります。
4. 変数・コンテキストの扱い方
まず結論:YAML で「どう参照するか」が違う
変数の扱い方の違い
| 使いたい値 | GitHub Actions | GitLab CI/CD |
|---|---|---|
| 通常の環境変数 | ${{ env.VAR }} |
$VAR |
| 手動実行の入力値 | ${{ github.event.inputs.VAR }} |
$VAR |
| secrets | ${{ secrets.VAR }} |
$VAR |
| job 間で渡した値 | ${{ needs.job.outputs.VAR }} |
$VAR(dotenv artifacts) |
| 参照方法の数 | 用途ごとに異なる | ほぼ $VAR に統一 |
GitHub Actions は、値の出どころごとに参照方法が分かれており、「この値はどこから来たのか」を意識して書く設計になっています。
一方 GitLab CI/CD は、UI 変数・secrets・artifacts 由来の値まで含めてほとんどを $VAR として扱えるため、参照方法が統一されています。
GitHub Actions の場合
GitHub Actions では、値の種類ごとに参照する context が分かれています。
- run: |
echo "${{ env.ENV_NAME }}"
echo "${{ secrets.API_KEY }}"
echo "${{ github.event.inputs.target }}"
echo "${{ needs.build.outputs.image_tag }}"
この例が示しているのは、
- 環境変数 →
env - secrets →
secrets - 手動入力 →
github.event.inputs - job 間の値 →
needs.*.outputs
というように、同じ「変数っぽい値」でも値を取得する context がそれぞれ異なるという点です。
また GitHub Actions では、
artifacts は基本的に ファイルとして受け渡すものであり、
次の job で使うには、
-
outputsに変換する - 環境変数として再定義する
といった一手間が必要になります。
GitLab CI/CD の場合
GitLab CI/CD では、多くの値がCI/CD variables として扱われます。
script:
- echo "$DEPLOY_ENV"
- echo "$API_KEY"
- echo "$IMAGE_TAG"
この $VAR は、
- UI から指定した変数
- .gitlab-ci.yml の
variables -
protected variables(secrets) - 前 job の
artifacts(dotenv)
の いずれであっても同じ書き方 です。
特に job 間の値受け渡しでは、dotenv artifacts を使うことで「artifacts なのに変数としてそのまま使える」 のが特徴です。
build:
script:
- echo "IMAGE_TAG=v1.0.0" >> build.env
artifacts:
reports:
dotenv: build.env
deploy:
script:
- echo "$IMAGE_TAG"
5. どんなときにどちらを選ぶと良いか
ここまでの違いを踏まえると、次のように整理できます。
GitHub Actions が向いているケース
- GitHub リポジトリに CI をすぐ追加したい
- push / PR / 手動などイベントごとに処理を組み立てたい
- Marketplace の Action を活用して CI を構築したい
GitLab CI/CD が向いているケース
- 複数リポジトリで同じ CI 構造を共有したい
- 複雑な条件で動くパイプラインを見通し良く管理したい
- CI テンプレートを使ってパイプラインを一元管理したい
6. まとめ
本記事では、GitHub Actions と GitLab CI/CD を「何ができるか」ではなく、どう設計し、どう運用していくかという視点で整理してきました。
両者の違いをあらためてまとめると、次のようになります。
| 観点 | GitHub Actions | GitLab CI/CD |
|---|---|---|
| 設計の考え始め | イベントから処理を考える | パイプラインの流れから考える |
| 再利用の方向性 | 処理を部品として切り出す | 構造をテンプレ化して揃える |
| 並列実行 | 少ない軸を手軽に広げる | 条件が増えても整理しやすい |
| 変数の扱い | 出どころごとに参照方法が分かれる | ほぼ $VAR に統一される |
| 運用時の印象 | 柔軟でスピーディ | 一貫性がありスケールしやすい |
どちらが優れている/劣っているという話ではありません。
CI/CD をどこから設計したいか、何を揃えて運用したいかによって、自然に向いている方が変わります。
GitHub Actions:
- イベント起点で柔軟に組み立てたい
- 処理を部品として素早く組み合わせたい
GitLab CI/CD:
- CI の構造やルールを揃えたい
- 規模が大きくなっても見通しを保ちたい
両方を触るようになると、
CI/CD はツール選定よりも設計の置きどころで安定性が決まる
という感覚が掴めてきて、結果として CI/CD の運用がかなり楽になります。

