Sansan Tech Blog

Sansanのものづくりを支えるメンバーの技術やデザイン、プロダクトマネジメントの情報を発信

GitHub Enterprise移行のために研究開発部でやったこと

本記事はSansan Advent Calendar 2025、1日目の記事です。

こんにちは、技術本部研究開発部の高橋寛治です。

会社としてGitHubからGitHub Enterpriseへの移行が行われました。 会社として移行ガイドの用意があり、GitHub Enterprise Importerのドキュメントもありましたが、研究開発部の事情に合わせて確認や工夫をすることがありました。 研究開発部では、100以上のリポジトリを管理しており、GitOpsの利用や共通化されたCI/CDパイプラインを利用しています。 サービスの提供に影響無く移行するための検証が必要でした。

研究開発部の移行作業について、いくつか紹介できればと思います。

プラットフォームCircuitの移行前確認

Circuitの概要

研究開発部では、アプリケーション実行基盤CircuitをEKS中心にプラットフォームとして構築して提供しています。

GitHubに依存している箇所は、大きく2つです。

  • Argo CDによるGitOpsを採用し、GitHubのmainブランチを信頼できる唯一の情報源としている
  • コンテナイメージのビルドとプッシュは、GitHub Actionsにより行う

移行前確認でやること

Production環境でサービス停止なく切り替えられることを確認するのが目的です。 Development環境を対象に検証し、動作確認と、移行作業手順のドキュメント化を行いました。

動作確認は、次の動作を行えるかを確認しました。

確認項目 内容
mainブランチの同期 ArgoCDにてGitHubのmainブランチと同期が取れているか
アプリケーションのデプロイ 問題なく動作するか
GitHub Actionsによるビルド コンテナイメージが正しくプッシュされるか

実際の作業

GitHubはGitHub Enterpriseの検証用Organization、CircuitはDevelopment環境で作業しました。

検証用Organizationでは、リポジトリの作成とGitHub Appのinstallを行いました。 GitHub Appの名前は一意になる必要があるため、suffixにdevなどを追加するといいです。 リポジトリは、GitOps用のリポジトリとアプリケーションリポジトリ、共通GitHub Actionsリポジトリを作成しました。 検証に必要なコードは、対象リポジトリにPushします。 ArgoCDで利用するGitHub AppのInstallを行いました。

実際に検証する際には、ArgoCDの対象環境のSelf healをOffにしてから作業します。 あとは対象環境の設定ファイル上のGitHub AppIDやOrganizationを機械的に置換します。

その後、Self healをOnにして、動作確認を行います。

動作確認後は、設定を元に戻して完了です。

リポジトリに設定されているSecretsの収集

Secretsの収集設定の方針

Secretsは移行されないため、設定値を収集するか更新する必要があります。

管理方法の改善余地はありますが、当時の状況では迅速な再設定を優先しました。 本来は、そもそもSecretsを利用しない方式に移行したり、発行方法を把握しやすいようにしたりと改善していくべきですが、数が多く時間を要するため、設定値を取得して再設定することにしました。

GitHub Actionsを使って設定値を取得

GPGキーを用意し、GitHub Actionsで暗号化した設定値を出力します。 その値を手元で復号することにより設定値を取得しました。

次に、Secretsを暗号化して出力するためのYAMLサンプルを紹介します。 Environment secretsは指定したEnvironmentが対応します。 キー名は自分で指定します。

name: export-picked-secrets
on:
  workflow_dispatch:
    inputs:
      environment:
        description: "Environment name to export secrets for"
        required: true
        type: choice
        options:
          - dev
          - stg
          - prod
      armored_public_gpg_key:
        required: true
        description: "-----BEGIN PGP PUBLIC KEY BLOCK----- …"

jobs:
  export:
    runs-on: ubuntu-latest
    environment: ${{ github.event.inputs.environment }}
    steps:
      # 1. 公開鍵のインポート & fingerprint を出力
      - id: gpg
        shell: bash
        run: |
          printf '%s\n' "${{ github.event.inputs.armored_public_gpg_key }}" \
            | gpg --batch --import
          fp=$(gpg --list-keys --with-colons \
                   | awk -F: '$1=="fpr"{print $10;exit}')
          echo "fp=$fp" >> "$GITHUB_OUTPUT"

      # 2. 必要なシークレットを列挙して暗号化
      - id: dump
        env:
          GPG_FP            : ${{ steps.gpg.outputs.fp }}
          XXXXXX           : ${{ secrets.XXXXXX }}
        shell: bash
        run: |
          set -euo pipefail
          [[ -n "$GPG_FP" ]] || { echo "Empty GPG_FP"; exit 1; }

          jq -n \
            --arg xxx "$(printf '%s' "$XXXXXX"  \
                        | gpg --batch --yes --trust-model always -a -e -r "$GPG_FP")" 
            '{
              XXXXXX:$xxx
            }' > chosen_secrets.json

      # 3. アーティファクトに保存
      - uses: actions/upload-artifact@v4
        with:
          name: encrypted-secrets-${{ github.event.inputs.environment }}
          path: chosen_secrets.json

次のようにworkflowを実行します。

gh workflow run export-secrets.yml --ref export-secrets-temp -f armored_public_gpg_key="$(cat ~/pub_key.key)" -f environment="dev"

復号はPythonなどで適当にコードを書いて行いました。

一括設定

取得したSecretsは暗号化されたJSONファイルとして手元にあるため、次にGitHub APIを使って一括設定を行いました。 GitHub APIでは設定や更新の操作が提供されています。

一括プルリクエスト

Organization名の変更に対応するため、一括置換しプルリクエストを一括で出しました。 次のようなbashファイルを対象リポジトリにPull Requestを出す権限を持つ人が実行します。

#!/bin/sh -eu

REPO_LIST_FILE="repositories.txt"
mapfile -t repositories < "$REPO_LIST_FILE"

for repo in "${repositories[@]}"; do
  echo "Cloning $repo..."
  gh repo clone "$repo"

  repo_dir=$(basename "$repo")
  echo "Changing references in $repo_dir..."
  cd "$repo_dir"

  # デフォルトブランチ名の取得
  default_branch=$(gh repo view "$repo" --json defaultBranchRef -q ".defaultBranchRef.name")
  echo "Default branch is: $default_branch"

  # 参照の書き換え
  find . -path ./.git -prune -o -type f -print0 | xargs -0 sed -i -e "s/repo:before-organization/repo:new-organization/g"
  find . -path ./.git -prune -o -type f -print0 | xargs -0 sed -i -e "s/github.com\/before-organization/github.com\/new-organization/g"
  find . -path ./.git -prune -o -type f -print0 | xargs -0 sed -i -e "s/repos\/before-organization/repos\/new-organization/g"
  find . -path ./.git -prune -o -type f -print0 | xargs -0 sed -i -e "s/before-organization/new-organization/g"

  echo "Creating a pull request..."
  gh pr create --base "$default_branch" --head new-organization:"$default_branch" \
    --title "Change organization name"
  cd ..
done

このスクリプトにより、100を超えるリポジトリへの変更を安全かつ効率的に反映できました。

おわりに

GitHubのOrganization移行は初めての経験でした。 どの設定を変更すべきか一つひとつ確認し事前に検証しておくことで、大きなトラブルなく移行できました。

Sansan Advent Calendar 2025では、他のメンバーからもさまざまな取り組みが紹介されます。 ぜひ明日以降もご覧ください。

研究開発部ではPlatform Engineerを募集しています! 本記事では移行の話でしたが、Platform自体を改善し研究開発部の生産性を高めていくポジションです。 カジュアル面談もお待ちしています。

© Sansan, Inc.