5
2

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

【初心者仕様】GitHubActionsでCI/CDを試してみた話

Posted at

はじめに

この記事はGitHubActionsについて、名前は知っているけどその実態は何も知らない成人男性がGitHubActionsでコードをテスト~デプロイを行うワークフローを作ってみた話です。

GitHubActionsってなんだ

GitHubActionsはGitHubの提供するCI/CDプラットフォームです。
プルリクエストが作成されたタイミングでテストコードを実行したり、mainブランチへマージされたタイミングでビルドやデプロイを行うワークフローを実行できるほか、イシューを作成したタイミングでラベルを付けるといったこともできるそうです。

GitHub Actions は、DevOps であるだけでなく、リポジトリで他のイベントが発生したときにワークフローを実行できます。 たとえば、リポジトリで新しい issue が作成されるたびに、適切なラベルを自動的に追加するワークフローを実行できます。

GitHubActions Words

出てくるワードが分からんのでまとめてみました。

ワークフロー

1つ以上のジョブを実行する自動化プロセス。
.github/workflows/配下のYAMLファイルで定義する。

ジョブ

ワークフローを構成する各スクリプトやアクション。

イベント

プッシュやフォーク、イシューの作成といったGitHub上のアクションのことで、イベントをトリガーにワークフローが実行される。

使ってみよう

なんとな~く概要を知ったつもりになったところで今回は以下の2つのワークフローを作ってみます。

  • プルリクエストが作成されたらテストコードを実行する
  • mainブランチへマージされたらビルドしてGitHubPagesに静的サイトをデプロイする

プロジェクトの準備

viteでReactプロジェクトを作成して必要なパッケージをインストールします。

npm create vite@latest

npm install -D vitest @vitest/coverage-v8

適当にvitestの設定をします。

vitest.config.ts
const defaultExclude = ["coverage/**",
    "dist/**",
    "**\/[.]**",
    "packages/*\/test?(s)/**",
    "**\/*.d.ts",
    "**\/virtual:*",
    "**\/__x00__*",
    "**\/\x00*",
    "cypress/**",
    "test?(s)/**",
    "test?(-*).?(c|m)[jt]s?(x)",
    "**\/*{.,-}{test,spec}?(-d).?(c|m)[jt]s?(x)",
    "**\/__tests__/**",
    "**\/{karma,rollup,webpack,vite,vitest,jest,ava,babel,nyc,cypress,tsup,build}.config.*",
    "**\/vitest.{workspace,projects}.[jt]s?(on)",
    "**\/.{eslint,mocha,prettier}rc.{?(c|m)js,yml}"
];

export default defineConfig({
    plugins: [react()],
    test: {
        globals: true,
        environment: "jsdom",
        include: ["test/**/*.test.{js,ts,jsx,tsx}"],
        coverage: {
            provider: "v8",
            exclude: [...defaultExclude, "src/main.tsx"],
            thresholds: {
                statements: 100,
                branches: 100,
                functions: 100,
                lines: 100
            }
        },
        alias: { "@": path.resolve(__dirname, "./test"), }
    }
});

適当にテストコードを書きます。

test/App.test.tsx
import { describe, test, expect } from "vitest";
import React from "react";
import { render, screen } from "@testing-library/react";
import App from "../src/App";

describe("App Test", () => {

    test("render check", () => {
        render(<App />);
        expect(screen.getByText("Vite + React")).toBeTruthy();
    });
});

プルリクエストの作成時にテストコードを実行するワークフロー

.github/workflows/配下にワークフローの設定ファイルを作成します。

.github/workflows/test.yml
name: Run Vitest And Check Coverage
run-name: test coverage

# プルリクエストの作成時に実行する
on: [pull_request]

# ワークフローで実行するジョブ定義
jobs:
  test:
    # ジョブを実行するOS
    runs-on: ubuntu-latest

    steps:
      # リポジトリをチェックアウトする
      - name: Checkout repository
        uses: actions/checkout@v4

      # Node.jsを使用する
      - name: Setup Node.js
        uses: actions/setup-node@v4
        with:
          node-version: '20.x'

      # 依存関係をインストール
      - name: Install dependencies
        run: npm install

      # Vitestを実行
      - name: Run vitest
        run: npm run test

on

ワークフローを実行するイベントを記述します。
プルリクエストの作成時(pull_request)やプッシュ時(push)のほかにも指定できるイベントはかなり多いです。
以下の形式で特定のブランチのみワークフローを実行することも可能です。

# mainブランチへプッシュされたときにワークフローを実行する
on: 
  push:
    branches:
      - "main"

jobs

ワークフローで実施するジョブを記述します。
ジョブ自体は並列で実行されますが、needsを指定することで特定のジョブが完了してから実行する、といった制御も可能です。

runs-on

ジョブを実行するOS(ランナー)を設定します。
GitHubホステッドランナー(Ubuntu、Windows、macOS)のほか、独自で設定するセルフホステッドランナーを設定できます。

uses

GitHubやユーザの作成したアクションをワークフロー内から実行することが出来ます。
上記コードで使用しているactions/checkout@v4actions/setup-node@v4はGitHubが作成して公開しているアクションです。

テストコードの自動実行

ワークフローの設定ができたところで、適当にブランチを切ってmainブランチへのプルリクエストを作成します。
その際、vitestのコードカバレッジが100%にならないように変更を加えておきます。

プルリクエストを作ったらGithubActionsが実行されています。
このまま実行が完了するまで待ってみましょう。
image.png

カバレッジが100%未満なのでエラーが出ていますが、
このままでもマージはできてしまうので、リポジトリの設定を弄ってテストでエラーが出た場合はマージできないようにしてみましょう。
image.png

リポジトリのルールセットから、mainブランチに対するルール設定を追加します。
image.png

今回はRequire status checks to pass before mergingを有効化することでマージ前のステータスチェック通過を必須条件とし、必要なステータスチェックとしてGitHubActionsのtestワークフローを追加しています。
image.png

これでテストコードのカバレッジを100%にしないとマージできないようになりました。
image.png

コードのカバレッジが100%になるよう修正してプッシュしてみると
ステータスチェックが正常に完了し、マージできるようになりました。
image.png

mainブランチへマージされたらGitHubPagesにデプロイするワークフロー

.github/workflows/配下にtestとは別のワークフローファイルを作成します。

.github/workflows/build-deploy.yml
name: Build Application
run-name: build and deploy
on: 
  push:
    branches:
      - "main"

jobs:
  build:
    runs-on: ubuntu-latest

    steps:
      # リポジトリをチェックアウトする
      - name: Checkout repository
        uses: actions/checkout@v4

      # Node.jsを使用する
      - name: Setup Node.js
        uses: actions/setup-node@v4
        with:
          node-version: '20.x'

      # 依存関係をインストール
      - name: Install dependencies
        run: npm install

      # ビルドを実行
      - name: Run build
        run: npm run build

      # ビルドしたアーティファクトをアップロード
      - name: Upload artifact files
        uses: actions/upload-pages-artifact@v2
        with:
          path: ./dist

  deploy:
    runs-on: ubuntu-latest

    # GitHub Pagesのデプロイ権限を設定
    permissions:
      contents: read
      pages: write
      id-token: write

    # buildが完了してから実行する
    needs: build

    steps:
      # GitHub Pagesにデプロイ
      - name: Deploy to GitHub Pages
        id: deployment
        uses: actions/deploy-pages@v3

ワークフローを作成したところで適当なブランチへプッシュしてmainブランチへマージします。
マージのタイミングでデプロイ用ワークフローが動いていることが確認できます。
image.png

ワークフローがちゃんと完了し、GitHubPagesに静的サイトがデプロイされていました。
image.png

おわりに

GithubActionsを使って簡単な仕様のCI/CDを試してみましたが、かなり簡単に実装できるものでしたね。
GitHubは個人で適当に遊ぶ用のリポジトリを用意する程度にしか使ってきませんでしたが、もう少しGitHubの可能性に目を向けるべきだったのかもしれません。

気が向いたらもう少し凝ったワークフローを作って記事を書いてみたいですね。

参考記事

5
2
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
5
2

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?