📚
CI/CDとは?【テスト・デプロイ】
0. はじめに
この記事は、駆け出しバックエンドエンジニアによる学習記録です。
初学で調べたことをまとめたものなので、多少間違った説明もあるかもしれません。ご了承くださいmm
1. CIとは?
CI(Continuous Integration、継続的インテグレーション)は、「ソフトウェア開発における自動化されたビルド・テスト・統合の仕組み」を指す。
概要
- 目的:開発チームが頻繁にコードを統合し、早期にバグを発見するための仕組み
- 基本の流れ:
- 開発者がコードをGitなどのリポジトリにプッシュ
- CIツール(例:GitHub Actions, Jenkins, GitLab CI)が自動でビルドを実行
- 単体テストや統合テストを自動実行
- 結果(成功/失敗)を開発者に通知
これにより、コードが常に動作する状態(“緑の状態”)に保たれる。
メリット
- 早期バグ検出:小さい変更ごとにテストするので、不具合の原因が特定しやすい
- 品質向上:テストが自動で走るため、人為的ミスを減らせる
- 開発スピード向上:統合時のコンフリクトやビルド失敗を事前に防げる
- リリースの安定:常に動く状態が維持されるため、本番リリースが安心
CIツール
- GitHub Actions(GitHubリポジトリと連携しやすい)
- Jenkins(自前サーバーで運用可能、柔軟性が高い)
- GitLab CI/CD(GitLabと統合済み)
2. CDとは?
CI(Continuous Integration)とセットでよく出てくるCDは、文脈によって2通りの意味がある:
CDの2つの意味
- Continuous Delivery(継続的デリバリー)
- 本番リリース直前までを自動化(ビルド・テスト・ステージング環境へのデプロイ)
- 使われ方: 「レビューOKならボタン1つで本番リリースできる状態」
- Continuous Deployment(継続的デプロイ)
- 本番リリースまで完全自動化
- 使われ方: 「テストが通ったら自動で本番へリリース」
ポイント
- まずは、CIを導入 → テストが常にグリーンになる環境を作る
- その後、CDを導入 → デプロイも自動化するとチーム全体が早く動ける
3. CIの実践
0) 前提
- リポジトリがGitHub上にある
-
gradlew
とgradle/wrapper/*
がコミット済み(ローカルで./gradlew test
が通っている)
1) ワークフローを作る
リポジトリ直下に以下のパスでファイルを新規作成:
.github/workflows/ci.yml
ci.yml
の中身(例)
name: CI
on:
push:
branches: [ "**" ]
pull_request:
concurrency:
group: ci-${{ github.ref }}
cancel-in-progress: true
jobs:
build-and-test:
runs-on: ubuntu-latest
permissions:
contents: read
defaults:
run:
working-directory: backend # gradlewがbackend/に配置されている
steps:
- name: Checkout
uses: actions/checkout@v4
- name: Validate Gradle Wrapper
uses: gradle/actions/wrapper-validation@v3
- name: Set up JDK 21
uses: actions/setup-java@v4
with:
distribution: temurin
java-version: "21"
cache: gradle # Gradle依存キャッシュ
# (任意)環境変数をここで渡す。必要ならSecretsに入れて参照
# - name: Set env
# run: echo "JWT_SECRET=local-test-secret" >> $GITHUB_ENV
- name: Grant execute permission for gradlew
run: chmod +x gradlew
- name: Build & Test
run: ./gradlew clean build test --no-daemon
# 失敗時にテストレポートを見れるようアーティファクト収集
- name: Upload test reports (always)
if: always()
uses: actions/upload-artifact@v4
with:
name: test-reports
path: |
**/build/reports/tests/test
**/build/test-results/test
**/build/reports/jacoco/**
if-no-files-found: ignore
これでpush/prのたびに./gradlew clean build test
が走る。
Testcontainersを使っていても追加設定は不要(Ubuntu runnerにDockerデーモンが入っているため)。
2) build.gradleに設定追加
build.gradle
(Groovy)にJaCoCoを追加。まずは可視化→後で閾値を上げる方針が実務的。
plugins {
id 'jacoco'
}
jacoco {
toolVersion = "0.8.10"
}
test {
useJUnitPlatform()
finalizedBy jacocoTestReport
}
jacocoTestReport {
dependsOn test
reports {
xml.required = true
html.required = true
}
}
// 閾値(最初は緩めでOK。CIで赤にしたければ有効化)
jacocoTestCoverageVerification {
violationRules {
rule {
limit {
counter = 'LINE'
value = 'COVEREDRATIO'
minimum = 0.80 // line coverage 80%
}
}
}
}
// check.dependsOn jacocoTestCoverageVerification
CIのアーティファクトにHTMLレポートが入るので、失敗時でも詳細をDLして確認できる。
4. 感想
今回初めてCIを実装するにあたってCI/CDについて調べてまとめてみた。
実際に手を動かして実践したことで、ざっくり概要は掴めたと思う。
実務ではもっとやることがあると思うが、今回はとりあえずここまでやってみた感じ。
ここではGitHub Actionsを使ったが、新卒の会社ではJenkinsを使っていたことを思い出した。
個人開発ではCDまでは必要ないと思うけど、概要くらいは知っとくべきだと思った。よく頑張った。
Discussion