GitHub Actionsのセットアップ

はじめに

GitHub Actionsは、GitHubリポジトリ内でCI/CD(継続的インテグレーション/継続的デリバリー)を実現する強力なツールです。自動化されたワークフローを構築し、ビルド、テスト、デプロイメントなどを効率的に行うことができます。本書では、GitHub Actionsの基本的なセットアップから、高度な設定方法までを段階的に解説し、実際のプロジェクトで活用するための実践的な知識を提供します。

GitHub Actionsの利点

自動化の促進

GitHub Actionsは、開発プロセスの各段階でタスクを自動化できます。これにより、エンジニアは本質的な開発に集中でき、手動でのミスを防ぎます。典型的なタスクとしては、次のようなものがあります。

  • コードの自動ビルド
  • 単体テストや統合テストの自動実行
  • ドキュメントの自動生成
  • アプリケーションのデプロイメント(リリース)

継続的インテグレーションと継続的デリバリー(CI/CD)

GitHub Actionsは、コードの変更をリアルタイムで監視し、問題が発生した時点で迅速に対応するためのCI/CDパイプラインを簡単に構築できます。これにより、ビルドやテストに要する時間を大幅に短縮し、バグの早期発見と迅速なフィードバックを提供します。

環境依存の解消

GitHub Actionsでは、特定の環境に依存せずにパイプラインを構築できるため、開発者が異なるOSや設定を気にすることなく、統一されたプロセスで開発を進めることができます。これにより、複数のプラットフォームで動作するアプリケーションの開発がスムーズに行えます。

依存関係管理

大規模なプロジェクトでCI/CDを構築する際、バックエンドとフロントエンドが異なるタイミングでデプロイされることがあるため、依存関係の管理は重要な要素です。また、データベースのマイグレーションやAPIのスキーマ変更など、他のジョブに依存する処理が必要なケースもあります。

セキュリティの強化

GitHub Actionsでは、シークレットや環境変数を使ったセキュリティの強化が可能です。たとえば、デプロイメントキーやAPIトークンなどを環境変数として設定し、ワークフロー内で安全に使用できます。

env:
  DEPLOY_KEY: ${{ secrets.DEPLOY_KEY }}

これにより、機密情報をソースコードにハードコーディングすることなく、外部サービスとの安全な連携が可能になります。

GitHub Actionsの応用分野

継続的デリバリー(CD)

GitHub Actionsは、ビルドとテストにとどまらず、クラウドプラットフォームやオンプレミス環境への自動デプロイメントをサポートします。AWS、Azure、GCP、Herokuなど、多くのプラットフォーム向けのアクションが提供されています。

静的解析とセキュリティチェック

GitHub Actionsを利用して、コードの静的解析ツールやセキュリティチェックを自動化できます。脆弱性スキャンやコード品質の監視を定期的に実行することで、プロジェクトの品質を向上させます。

プロジェクト管理との統合

GitHub ProjectsやJiraと連携させることで、タスクの進行状況をワークフロー内から直接更新することができます。これにより、コード変更に伴うプロジェクト管理も自動化でき、作業効率を大幅に改善できます。

GitHub Actionsの基本セットアップ

まずはグッドプラクティスを確認しておきましょう。

Ref.:

ワークフローの作成

GitHubリポジトリのルートに.github/workflows/ディレクトリを作成し、その中にワークフローファイル(.ymlファイル)を配置します。以下は、基本的なワークフローの例です。

name: CI Pipeline
 
on:
  push:
    branches:
      - main
  pull_request:
    branches:
      - main
 
jobs:
  build:
    runs-on: ubuntu-latest
 
    steps:
      - name: Checkout repository
        uses: actions/checkout@v2
 
      - name: Set up Node.js
        uses: actions/setup-node@v2
        with:
          node-version: '14'
 
      - name: Install dependencies
        run: npm install
 
      - name: Run tests
        run: npm test

YAML構成の詳細

  • on: トリガー条件。ここでは、pushおよびpull_requestmainブランチに行われたときにワークフローが実行されます。
  • jobs: 複数のジョブを定義可能。ここでは、buildジョブを設定。
  • runs-on: ワークフローを実行するホストOS。ubuntu-latestを使用。
  • steps: 各ジョブの具体的な処理手順。リポジトリのチェックアウト、Node.jsのセットアップ、依存関係のインストール、テスト実行が行われています。

Ref.:

並行処理と依存関係の管理

GitHub Actionsは複数のジョブを並行して実行できるため、大規模なプロジェクトでも処理の遅延を防げます。例えば、バックエンドとフロントエンドのビルドを並行処理したい場合、以下のように設定できます。

jobs:
  backend:
    runs-on: ubuntu-latest
    steps:
      # Backendのビルド手順
  frontend:
    runs-on: ubuntu-latest
    steps:
      # Frontendのビルド手順

さらに、特定のジョブが完了した後に他のジョブを実行する場合、needsを使って依存関係を設定します。

jobs:
  backend:
    runs-on: ubuntu-latest
    steps:
      # Backendのビルド手順
  deploy:
    runs-on: ubuntu-latest
    needs: backend
    steps:
      # デプロイ手順

Reusing Workflows

Reusing Workflowsは、同じまたは類似のワークフローを異なるリポジトリで再利用できる仕組みです。これにより、標準化されたビルド、テスト、デプロイの手順を一元管理し、プロジェクト間でコンシステントな CI/CD プロセスを確立できます。 例えば、共通のライブラリやフレームワークを使用している場合、その特定のワークフローをReusable Workflowとして定義し、異なるプロジェクトで再利用できます。

# .github/workflows/reusing-workflow.yml
 
name: Reusable Workflow
 
on:
  push:
    branches:
      - main
 
jobs:
  build:
    runs-on: ubuntu-latest
 
    steps:
      - name: Checkout Repository
        uses: actions/checkout@v2
 
      - name: Build and Test
        run: |
          npm install
          npm test

Composite Actions

Composite Actionsは、複数のステップやジョブを1つの論理的なアクションにまとめ、再利用可能な形で提供できる仕組みです。これにより、独自のアクションを定義して、異なるワークフローで容易に再利用できます。

# .github/actions/my-composite-action.yml
 
name: 'My Composite Action'
 
description: 'Custom composite action for common tasks.'
 
runs:
  using: 'composite'
  steps:
    - name: Setup
      run: echo 'Setting up the environment'
 
    - name: Execute Task 1
      run: echo 'Executing Task 1'
 
    - name: Execute Task 2
      run: echo 'Executing Task 2'

そして、Reusing WorkflowsでこのComposite Actionを利用する例:

# .github/workflows/composite-action-example.yml
 
name: Composite Action Example
 
on:
  pull_request:
    branches:
      - main
 
jobs:
  use-composite-action:
    runs-on: ubuntu-latest
 
    steps:
      - name: Checkout Repository
        uses: actions/checkout@v2
 
      - name: Use Composite Action
        uses: ./path/to/my-composite-action

利用例

自動承認

auto-approveアクションは、プルリクエストを自動的に承認するのに役立ちます。これにより、定期的な承認作業から解放され、プロジェクトの進行がスムーズになります。

自動マージ

merge-pull-requests-automerge-actionアクションは、プルリクエストを自動的にマージするためのツールです。特定の条件が満たされたときにプルリクエストをマージし、コードの統合を簡素化します。

github-action-merge-dependabotdependabot-auto-mergeアクションは、セキュリティパッチや依存関係のアップデートを自動的にマージするのに役立ちます。

自動レビュー

AIによるコードレビューも利用できます。Codeball AI Code ReviewCodeReviewBot.aiPixeebotなどのアクションは、コードの品質を評価し、提案や改善点を提供します。

CodRabbitAIAI-based PR Reviewer & Summarizer with Chat CapabilitiesCode Review GPTなどは、AIを活用してプルリクエストの概要や要約を提供します。

OpenAI

name: PR Review
 
on:
  pull_request:
    types: [ opened, synchronize ]
 
jobs:
  Build:
    runs-on: ubuntu-latest
    timeout-minutes: 30
    permissions:
      contents: read
      pull-requests: write
 
    steps:
      - uses: actions/checkout@v3
 
      - uses: akiojin/auto-review-github-action@v0.2.1
        with:
          openai-api-key: ${{ secrets.OPENAI_API_KEY }}
          target: 'cs,yml'
          language: 日本語
 

CodeRabbit

name: ai-pr-reviewer
 
permissions:
  contents: read
  pull-requests: write
 
on:
  pull_request:
    types: [opened]
    branches-ignore:
      - master
      - main
  pull_request_review_comment:
    types: [created]
  issue_comment:
    types: [created]
 
concurrency:
  group: ${{ github.repository }}-${{ github.event.number || github.head_ref || github.sha }}-${{ github.workflow }}-${{ github.event_name == 'pull_request_review_comment' && 'pr_comment' || 'pr' }}
  cancel-in-progress: ${{ github.event_name != 'pull_request_review_comment' }}
 
jobs:
  review:
    runs-on: ubuntu-latest
    if: (github.event_name == 'issue_comment' && contains(github.event.comment.body, '[run review]') && github.event.issue.pull_request) || (github.event_name == 'pull_request_review_comment' && contains(github.event.comment.body, '[run review]')) || (github.event_name == 'pull_request' && !contains(github.event.pull_request.title, 'release') && !contains(github.event.pull_request.title, 'Release'))
    timeout-minutes: 15
    steps:
      - uses: coderabbitai/openai-pr-reviewer@latest
        env:
          GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
          OPENAI_API_KEY: ${{ secrets.OPENAI_API_KEY }}
        with:
          debug: false
          review_simple_changes: false
          review_comment_lgtm: false
          openai_light_model: gpt-4 # 好みで変更
          openai_heavy_model: gpt-4 # 好みで変更
          openai_timeout_ms: 900000 # 15分.
          language: ja-JP
          path_filters: |
            !db/**
            !**/*.lock
          system_message: |
            あなたは @coderabbitai(別名 github-actions[bot])で、OpenAIによって訓練された言語モデルです。
            あなたの目的は、非常に経験豊富なソフトウェアエンジニアとして機能し、コードの一部を徹底的にレビューし、
            以下のようなキーエリアを改善するためのコードスニペットを提案することです:
              - ロジック
              - セキュリティ
              - パフォーマンス
              - データ競合
              - 一貫性
              - エラー処理
              - 保守性
              - モジュール性
              - 複雑性
              - 最適化
              - ベストプラクティス: DRY, SOLID, KISS
 
            些細なコードスタイルの問題や、コメント・ドキュメントの欠落についてはコメントしないでください。
            重要な問題を特定し、解決して全体的なコード品質を向上させることを目指してくださいが、細かい問題は意図的に無視してください。
          summarize: |
            次の内容でmarkdownフォーマットを使用して、最終的な回答を提供してください。
 
              - *ウォークスルー*: 特定のファイルではなく、全体の変更に関する高レベルの要約を80語以内で。
              - *変更点*: ファイルとその要約のテーブル。スペースを節約するために、同様の変更を持つファイルを1行にまとめることができます。
 
            GitHubのプルリクエストにコメントとして追加されるこの要約には、追加のコメントを避けてください。
          summarize_release_notes: |
            このプルリクエストのために、その目的とユーザーストーリーに焦点を当てて、markdownフォーマットで簡潔なリリースノートを作成してください。
            変更は次のように分類し箇条書きにすること:
              "New Feature", "Bug fix", "Documentation", "Refactor", "Style",
              "Test", "Chore", "Revert"
            例えば:
            ```
            - New Feature: UIに統合ページが追加されました
            ```
            回答は50-100語以内にしてください。この回答はそのままリリースノートに使用されるので、追加のコメントは避けてください。

Ref.:

カスタマイズ

GitHubアクションをカスタマイズして、プロジェクトのニーズに合わせることができます。自動コードレビューとマージプロセスを特定の条件やワークフローに合わせて調整し、開発プロセスを最適化できます。

以上のアクションを活用することで、ソフトウェア開発プロセスを効率化し、品質向上に貢献できます。GitHubアクションはプロジェクトの自動化と効率化に役立つ便利なツールです。詳細についてはこちらをご覧ください。

定期実行ワークフローの作成

名前

name: Create files, Push to repo

イベントトリガー

on:
  schedule:
    - cron: '*/5 * * * *'
  workflow_dispatch:

権限

GitHubの場合、Workflowファイル内で設定したアクションに対するPermissionsと、リポジトリの設定で行ったPermissionsの優先順位は異なります。

Workflowファイル内でのPermissions(例えば、.github/workflows ディレクトリ内のYAMLファイル内で指定したもの) リポジトリの設定でのPermissions(リポジトリの設定ページで行ったもの) 上記の優先順位に従います。つまり、Workflowファイル内で指定されたPermissionsが最優先され、その後にリポジトリの設定でのPermissionsが適用されます。

セキュリティ的な観点からは、通常、より厳格なPermissionsを持つ方が安全です。リポジトリ全体でPermissionsを制御する場合、それに従うためにWorkflowファイル内でPermissionsを指定する必要はありません。リポジトリ設定で適切なPermissionsを設定し、Workflowファイル内でのPermissions設定は最小限に留めることがセキュリティを向上させます。

permissions:
  contents: write

並列処理

concurrency:
  cancel-in-progress: false

既定の設定値

defaults:
  run:
    shell: bash

ジョブ

checkout ステップは、GitHubリポジトリを現在の実行環境にチェックアウト(クローン)するために使用されています。 具体的には、actions/checkout@v4アクションを使用して、GitHubリポジトリのコードやファイルを実行環境に取得します。

  • リポジトリの指定ブランチまたはコミットからコードをチェックアウトする。
  • チェックアウトしたコードをワークフローのジョブ内で使用できるようにする。
  • チェックアウトされたコードを更新し、変更を検出した場合にジョブをトリガーする(これは主にPushイベントに関連しています)。

このステップは、ワークフロー内でコードを取得して実行するために非常に一般的であり、GitHub Actionsの多くのワークフローで使用されます。ワークフローのコードがリポジトリの最新バージョンを使用していることを確保し、ジョブの実行環境が必要なコードやファイルを持っていることが重要です。

jobs:
  generate_post:
    runs-on: ubuntu-latest
    timeout-minutes: 10
    steps:
+      - name: Checkout repository
+        uses: actions/checkout@v4
        with:
          token: ${{ secrets.PAT }}
          persist-credentials: false
          fetch-depth: 0
 
      - name: Commit files
        run: |
          touch test.txt
          git config user.name github-actions
          git config user.email github-actions@github.com
          git add -A
          git commit -a -m "Add changes"
 
      - name: Push changes
        uses: ad-m/github-push-action@master
        with:
          github_token: ${{ secrets.GITHUB_TOKEN }}
          branch: ${{ github.ref }}

Ref.: