🐈‍⬛

CI/CDパイプラインへのGithub App導入

2024/05/14に公開

概要

元々、筆者が現在管理しているCI/CDフローにおいては、GitのPrivateリポジトリにアクセスする必要があり、その際には個人(筆者)に紐づく認証情報を使っていました。
要件としては過不足なく満たしていたものの、他方で、万一筆者が現職を辞した場合には、CI/CDフローが機能不全に陥るという状況がありました。端的に言って、あまり気持ちのいいものではなく、どうしたものかなと思っていたのですが、Github Appを利用することによって、この状況を改善できましたため、あらましを共有します。

Before

まず、従来の(Github App導入前の)github actionsや、Dockerfileのつくりが以下の通り(一部抜粋)です。なお、Dockerfileについては、同僚のkaito2氏が公開している記事の内容がベースになっております。

      - name: set up ssh
        run: |
          mkdir -p ~/.ssh
          echo "${GIT_PRIVATE_KEY}" > ~/.ssh/id_rsa
          chmod 700 ~/.ssh/id_rsa
          eval "$(ssh-agent)"
          ssh-add ~/.ssh/id_rsa
          ssh-keyscan -H github.com >> ~/.ssh/known_hosts
          git config --global url.git@github.com:.insteadOf https://github.com/
        env:
          GIT_PRIVATE_KEY: ${{ secrets.GIT_PRIVATE_KEY }}
#
# Build
#
FROM golang:1.19.5 as builder

ENV CGO_ENABLED=0
ENV GOOS=linux
ENV GOARCH=amd64
ENV GOPRIVATE=github.com/fivot/go-lib
WORKDIR /build

RUN mkdir -p -m 0700 ~/.ssh && \
    ssh-keyscan github.com >> ~/.ssh/known_hosts && \
    git config --global url.git@github.com:.insteadOf https://github.com/

COPY . .

RUN --mount=type=ssh go mod download
RUN go build -buildvcs=false -o /build/main ./cmd/...

上の通り、github actions において(筆者のアカウントに紐づく)githubのPRIVATE_KEYを、~/.ssh/id_rsaに配置。その後、Dockerfile内において --mount=type=ssh go mod download することで、Privateリポジトリの依存を解決していました。

Github Appの設定方法

Afterに筆を進める前に、個人的に結構ひっかかったので、Github Appの設定方法について記述しておきます。Organization単位でGithub Appを導入する場合、Github右上のアカウント設定から「Your organizations」へ進み、対象のOrganizationsについて「Setting」を選択。その後、画面左側の「Developper settings」から「Github Apps」を選択することで設定が可能です。

After

さて、Github App導入後のgithub actionsや、Dockerfileのつくりが以下の通り(一部抜粋)です。

      - name: Generate token
        id: generate_token
        uses: tibdex/github-app-token@3beb63f4bd073e61482598c45c71c1019b59b73a # v2.1.0
        with:
          app_id: ${{ secrets.GH_APP_ID }}
          private_key: ${{ secrets.GH_PRIVATE_KEY }}
          repositories: >-
            ["go-lib"]
          permissions: >-
            {
              "contents": "read"
            }

#
# Build
#
FROM golang:1.22.3 as builder

ARG TOKEN

ENV CGO_ENABLED=0
ENV GOOS=linux
ENV GOARCH=amd64
ENV GOPRIVATE=github.com/fivot/go-lib
WORKDIR /build

# トークンが提供されていればトークンを使用し、提供されていなければSSHを使用
RUN if [ -z "$TOKEN" ] ; then \
        # SSHを使用する設定
        mkdir -p -m 0700 ~/.ssh && \
        ssh-keyscan github.com >> ~/.ssh/known_hosts && \
        git config --global url.git@github.com:.insteadOf https://github.com/ ; \
    else \
        # トークンを使用する設定
        git config --global url."https://x-access-token:${TOKEN}@github.com/".insteadOf "https://github.com/" ; \
    fi

COPY . .

# トークンが提供されていれば通常のgo mod downloadを使用し、提供されていなければSSHを使用
RUN if [ -z "$TOKEN" ] ; then \
        # SSHを使用してモジュールをダウンロード
        --mount=type=ssh go mod download; \
    else \
        # 通常のHTTP経由でモジュールをダウンロード
        go mod download; \
    fi
RUN go build -buildvcs=false -o /build/main ./cmd/...

ローカルでの docker build 時にはトークンなしで実行可能なようにしているため、多少冗長な記述になっています。が、CI/CDパイプライン上ではGithub Appから払い出されたトークンを使って、そうでない場合、即ち各開発者のローカル環境においてビルドする場合には、通常通りに開発者が保有しているだろうsshの秘密鍵を使って、それぞれ依存を解決するように設定しました。
また、弊社のCI/CDパイプラインには suzuki-shunsuke氏ghalintを利用させていただいているため、lintで怒られてしまわないよう( the input permissions is required が出ないよう)、actions内では明示的にpermission, repositoriesを指定しています。

まとめ

以上の通り、Github Appを導入することによって、筆者個人に紐づく認証情報を、CI/CDパイプラインから切除することができました。これでいつでも退職ができるという寸法です!!
......というのは冗談ですが、組織全体のCI/CDパイプラインが、組織内の一個人の在職如何というか、秘密鍵の有効状況に左右されるというのは、どう考えても健全な状況ではありませんので、もし(そうそうないとは思いますが)皆さまが似たような状況にありましたら、これを機会に、Github Appを導入してみるのはいかがでしょうか。

Fivot Tech Blog

Discussion