Salesforce CI/CDをマスターする:開発者のためのGitHub Actionsガイド


執筆者:Salesforce 開発者


背景と適用シナリオ

Salesforceプラットフォームでの開発は、もはや単なるメタデータの変更や手動での変更セットのデプロイにとどまりません。現代の開発プロセスでは、品質、速度、信頼性を確保するために、DevOps(デブオプス)の文化と実践が不可欠となっています。その中核をなすのが、CI/CD (Continuous Integration/Continuous Delivery - 継続的インテグレーション/継続的デリバリー) です。

CI/CDは、コードの変更をリポジトリにプッシュすると、ビルド、テスト、デプロイといった一連のプロセスが自動的に実行される仕組みです。これにより、開発者はバグを早期に発見し、手動作業によるヒューマンエラーを削減し、より迅速かつ確実に価値を顧客に届けることができます。

この自動化を実現するための強力なツールが GitHub Actions です。GitHub Actionsは、GitHubリポジトリにネイティブに統合されたCI/CDプラットフォームであり、コードのプッシュ、プルリクエストの作成、特定の時間スケジュールなど、様々なイベントをトリガーとしてワークフローを自動実行できます。Salesforce開発者にとって、GitHub Actionsは以下のような多くのシナリオで強力な味方となります。

主な適用シナリオ

  • コード品質の自動チェック:プルリクエストが作成されるたびに、Apexの単体テストを自動実行し、コードカバレッジが基準を満たしているかを確認します。
  • 静的コード解析:Apex PMDなどのツールをワークフローに組み込み、コーディング規約違反や潜在的なバグを自動的に検出します。
  • デプロイの検証:開発ブランチへのマージ前に、変更内容がターゲットのSandbox(サンドボックス)環境へ問題なくデプロイ可能か(Validate)を自動で検証します。
  • 環境への自動デプロイ:メインブランチへのマージをトリガーとして、UAT(ユーザー受け入れテスト)環境やステージング環境へ自動的にデプロイします。
  • スクラッチ組織の自動作成:プルリクエストごとに独立したスクラッチ組織(Scratch Org)を作成し、そこでテストを実行することで、クリーンな環境での動作を保証します。

この記事では、Salesforce開発者として、GitHub Actionsを活用してSalesforceのCI/CDパイプラインを構築するための基本的な原理、具体的な設定方法、そしてベストプラクティスについて詳しく解説します。

原理の説明

GitHub ActionsがSalesforceと連携する仕組みを理解するには、いくつかのコアコンセプトを把握する必要があります。ワークフローは、リポジトリの .github/workflows/ ディレクトリに配置されたYAML形式のファイルによって定義されます。

GitHub Actionsの主要な構成要素

  • Workflow(ワークフロー):CI/CDプロセス全体を定義したものです。1つ以上のJobから構成されます。
  • Event(イベント):ワークフローを開始するきっかけとなるトリガーです。pushpull_requestscheduleなどが代表的です。
  • Job(ジョブ):特定のRunner(ランナー)上で実行される一連のStep(ステップ)の集まりです。複数のJobはデフォルトで並行して実行できますが、依存関係を定義することも可能です。
  • Step(ステップ):Job内の個々のタスクです。シェルコマンドを実行したり、特定のアクション(Action)を呼び出したりします。
  • Action(アクション):ワークフロー内で再利用可能なコードの単位です。例えば、リポジトリのコードをチェックアウトするactions/checkout@v3や、Salesforce CLI(SFDX)をセットアップするsfdx-actions/setup-sfdx@v1など、コミュニティやSalesforce公式が提供する多くのアクションが存在します。
  • Runner(ランナー):ワークフローを実行するサーバーです。GitHubがホストする仮想マシン(GitHub-hosted runner)または、自前で用意するサーバー(Self-hosted runner)を利用できます。

SalesforceのCI/CDにおけるGitHub Actionsの動作フローは、一般的に以下のようになります。

1. 認証情報の安全な保管:CI/CDプロセスでは、Salesforce組織に自動でログインする必要があります。この認証には、サーバー間の認証に適した JWT (JSON Web Token) Bearer Flow を使用するのが一般的です。Salesforceで「接続アプリケーション(Connected App)」を作成し、生成されたコンシューマーキー(Consumer Key)と、自己署名証明書から生成したサーバーキー(Server Key)を、GitHubリポジトリのSecrets機能に安全に保管します。Secretsに登録された情報は暗号化され、ワークフロー実行時のみ参照可能になるため、認証情報をコードに直接ハードコーディングする危険を避けられます。

2. ワークフローの実行:開発者がコードをリポジトリにプッシュすると、定義されたEventが発火し、Workflowが開始されます。

3. 環境のセットアップ:Runner上で、まずsfdx-actions/setup-sfdxアクションが実行され、Salesforce CLI (SFDX)がインストールされます。

4. Salesforce組織への認証:次に、GitHub Secretsに保管された認証情報を使って、sfdx-actions/auth-jwtのようなアクションが実行されます。これにより、SFDXがターゲットのSalesforce組織(開発者Sandbox、UAT環境など)にヘッドレスで(UIを介さずに)ログインします。

5. SFDXコマンドの実行:認証が完了すると、ワークフローはrunステップを通じて任意のSFDXコマンドを実行できるようになります。例えば、sfdx force:source:deploy --checkonlyでデプロイを検証したり、sfdx force:apex:test:runでApexテストを実行したりします。

6. 結果のフィードバック:各ステップの実行結果(成功または失敗)は、GitHubのUI上でリアルタイムに確認できます。プルリクエストのチェック機能と連携させれば、CI/CDが失敗した場合にマージをブロックすることも可能です。

示例代码

ここでは、プルリクエストが作成または更新された際に、変更内容を開発者Sandboxにデプロイ検証し、全てのApexテストを実行する基本的なワークフローのサンプルを紹介します。このコードはSalesforce公式の `sfdx-actions` のドキュメントに基づいています。

まず、このワークフローを実行する前に、Salesforce側で接続アプリケーションを設定し、必要なキーを生成してGitHubリポジトリの Secrets に以下の3つを登録する必要があります。

  • SALESFORCE_HUB_URL: 認証に使用する組織のSFDX認証URL。JWT認証の場合、これはログインユーザー名、クライアントID、JWTキーファイル、インスタンスURLなどの情報を含みます。 `sfdx force:org:display --verbose -u ` で取得できます。
  • SF_CONSUMER_KEY: 接続アプリケーションのコンシューマーキー。
  • SF_JWT_KEY: サーバー証明書の秘密鍵(.keyファイルの内容)。
  • SF_USERNAME: 認証に使用するSalesforceユーザーのユーザー名。

ファイルパス: .github/workflows/validate-and-test.yml

# ワークフローの名前
name: Validate and Run Apex Tests

# ワークフローのトリガーを定義
# この場合、mainブランチに対するプルリクエストが作成・同期されたときに実行
on:
  pull_request:
    branches:
      - main
    types: [opened, synchronize]

# ワークフローで実行されるジョブを定義
jobs:
  validate-and-test:
    # ジョブの名前
    name: Validate Deploy and Run Apex Tests
    # ジョブを実行するRunnerを指定(GitHubが提供する最新のUbuntu環境)
    runs-on: ubuntu-latest
    
    # ジョブ内のステップを定義
    steps:
      # 1. リポジトリのコードをRunnerにチェックアウトする
      - name: 'Checkout source code'
        uses: actions/checkout@v3

      # 2. Salesforce CLI (SFDX) をセットアップする
      # Salesforce公式のアクションを使用
      - name: 'Install Salesforce CLI'
        uses: sfdx-actions/setup-sfdx@v1

      # 3. 秘密鍵をファイルとして保存する
      # GitHub SecretsからJWTの秘密鍵を読み取り、Runner上のファイルに書き出す
      - name: 'Populate auth file with SFDX_URL secret'
        shell: bash
        run: echo ${{ secrets.SF_JWT_KEY }} > server.key

      # 4. JWTを使用してSalesforce組織に認証する
      # sfdx force:auth:jwt:grant コマンドを実行
      # --clientid: 接続アプリケーションのコンシューマーキー
      # --jwtkeyfile: 秘密鍵ファイルのパス
      # --username: Salesforceユーザー名
      # --instanceurl: ログイン先のURL (本番ならlogin.salesforce.com, Sandboxならtest.salesforce.com)
      # --setalias: この認証情報に別名(エイリアス)を付ける
      - name: 'Authenticate to Salesforce Org'
        run: |
          sfdx force:auth:jwt:grant \
            --clientid ${{ secrets.SF_CONSUMER_KEY }} \
            --jwtkeyfile server.key \
            --username ${{ secrets.SF_USERNAME }} \
            --instanceurl https://test.salesforce.com \
            --setalias DevSandbox

      # 5. デプロイの検証(チェックオンリー)を実行
      # force-appディレクトリ以下のメタデータをDevSandboxに対してデプロイ検証
      # --checkonly: 実際にはデプロイせず、成功するかどうかだけをテストする
      # --testlevel RunLocalTests: 管理パッケージ以外の全てのApexテストを実行する
      # --wait 20: デプロイ完了まで最大20分待機する
      - name: 'Validate deployment to Dev Sandbox'
        run: |
          sfdx force:source:deploy \
            --targetusername DevSandbox \
            --sourcepath force-app \
            --checkonly \
            --testlevel RunLocalTests \
            --wait 20

このYAMLファイルは、プルリクエストが作成されるたびに、Salesforce組織への認証、ソースコードのデプロイ検証、そしてApexテストの実行までを全自動で行います。もしテストの失敗やデプロイエラーがあれば、ジョブは失敗し、プルリクエストのUI上にその結果が表示されるため、問題のあるコードが `main` ブランチにマージされるのを防ぐことができます。

注意事項

GitHub ActionsをSalesforceのCI/CDに導入する際には、いくつかの重要な点に注意する必要があります。

権限 (Permissions)

CI/CDプロセスで使用するSalesforceのインテグレーションユーザーには、適切な権限が必要です。最低限、以下の権限を持つプロファイルまたは権限セットを割り当ててください。

  • APIの有効化 (API Enabled):API経由でのアクセスを許可するために必須です。
  • すべてのデータの編集 (Modify All Data):デプロイするメタデータの種類によっては、非常に広範なオブジェクトや設定へのアクセス権が必要になるため、この権限を付与するのが最も簡単です。セキュリティ要件が厳しい場合は、デプロイ対象のメタデータコンポーネントごとに必要な権限を細かく設定することも可能ですが、管理が複雑になります。
  • Apex RESTサービスへのアクセス (Apex REST Services):Tooling APIなどを利用する場合に必要です。

また、接続アプリケーションの設定では、許可されたユーザーを「管理者が承認したユーザは事前承認済み」に設定し、関連プロファイルまたは権限セットを割り当てておく必要があります。

API制限 (API Limits)

Salesforce組織には、24時間あたりのAPIコール数に制限があります。CI/CDプロセスは、認証、メタデータの取得、デプロイ、テスト実行など、多くのAPIコールを消費します。特に大規模なプロジェクトや、頻繁にワークフローが実行される環境では、このAPI制限に達してしまう可能性があります。

対策として、以下のような工夫が考えられます。

  • ワークフローのトリガーを限定する(例:特定のブランチへのpushのみ、手動実行のみ)。
  • 差分デプロイの仕組みを導入し、変更があったコンポーネントのみをデプロイ対象とすることで、処理時間とAPIコール数を削減する。
  • APIコール数の消費を監視し、必要に応じてSalesforceに追加のAPIコール数を購入する。

エラー処理 (Error Handling)

ワークフローが失敗した場合(例:Apexテストの失敗、デプロイ検証エラー)、GitHub Actionsはそのジョブを停止し、失敗としてマークします。プルリクエストのチェック機能と連携している場合、マージがブロックされるため、開発者はすぐに問題に気づくことができます。

GitHub ActionsのUIでは、各ステップのログを詳細に確認できるため、エラーの原因特定が容易です。sfdxコマンドが出力するエラーメッセージがそのままログに表示されます。また、if: failure()のような条件式を使うことで、ジョブが失敗した際にのみ実行されるステップ(例:Slackへの通知)を追加することも可能です。

まとめとベストプラクティス

GitHub Actionsは、Salesforce開発プロセスにCI/CDを導入するための非常に強力で柔軟なツールです。YAMLファイルでパイプラインを「コードとして」管理できるため、バージョン管理が可能で、プロセスの透明性も向上します。

Salesforce開発者としてGitHub Actionsを最大限に活用するためのベストプラクティスを以下にまとめます。

  1. 小さく始める:最初から複雑なパイプラインを構築しようとせず、まずはApexテストの自動実行など、単一のタスクから始め、徐々にステップを追加していくのが成功の鍵です。
  2. 環境ごとに認証情報を分離する:開発、ステージング、本番といった各環境に対して、それぞれ別のインテグレーションユーザーと接続アプリケーションを用意します。認証情報は、GitHubの Environments 機能を使って環境ごとにSecretsを管理すると、より安全で管理しやすくなります。
  3. .forceignore を活用する:リポジトリに含まれるが、Salesforce組織にデプロイすべきでないファイル(例:ローカル設定ファイル、テストデータCSV)は、.forceignore ファイルに記述して、デプロイ対象から除外します。これにより、不要なエラーを防ぎ、デプロイ時間を短縮できます。
  4. 静的コード解析を組み込む:sfdx-scanner などをワークフローに組み込むことで、コードがリポジトリにマージされる前に品質をチェックし、技術的負債の蓄積を防ぎます。
  5. 差分デプロイを検討する:プロジェクトが大きくなるにつれて、毎回すべてのメタデータをデプロイするのは非効率になります。Gitの差分を検出し、変更されたファイルのみをデプロイするスクリプトを導入することで、CI/CDの実行時間を大幅に短縮できます。

GitHub ActionsとSalesforce DXを組み合わせることで、開発チームはより高品質なアプリケーションを、より速く、より確実にリリースできるようになります。ぜひ、あなたのプロジェクトでも導入を検討してみてください。

コメント