🐉

Artifact RegistryにおいたGoモジュールをGithub Actionsでダウンロードさせる手順について

2024/07/04に公開

はじめに

  • 記事の目的と背景

ある案件でフロントエンドがTypeScript、バックエンドがGoのアプリケーションを作成しましたOpenAPIを使用して型情報を共通化して管理するため、OpenAPIから生成したそれぞれの型をパッケージ化して管理することになりました

GitHubのPrivate Repositoryを使用する選択肢もありましたが、PAT (Personal Access Token) を個別に管理するのが面倒で、組織内でしか使わないパッケージのため、今回はArtifact Registryを選択しました

Go モジュールをArtifact Registryに置き、Goのプロジェクトでinstallすることはできましたが、GitHub Actionsで認証させてdownloadさせる際に苦労したので、備忘録として書きます
調べても情報が少なかったので、これが誰かの助けになれば幸いです


1. 前提条件と準備

以下の設定は済んでいる前提で進めます

  • 必要なアカウントとツール
  • Go言語のインストール
  • gcloud sdkのインストール
  • Artifact Registryのセットアップ
  • GCPプロジェクトの作成
  • Artifact Registryの有効化
  • 認証情報の設定
    • 作成したサービスアカウントにArtifact Registryの権限の付与
  • Workload Identity の設定
    • 指定したGithub Repositoryからのみ認証ができるようにするattributeの付与

2. Go モジュールのパブリッシュ

  1. Goモジュールのrepositoryを作成します
gcloud artifacts repositories create {module_name} \
--repository-format=go \
--location={asia-northeast1} \
--description="description for module" \
--project={gcp_project_name}

module_nameは任意です
locationは日本の場合asia-northeast1またはasia-northeast2が適当です
descriptionは省略可能
projectにはGCPプロジェクトのIDを入れてください

  1. Go モジュールのupload
gcloud artifacts go upload  \
--repository={repository_name} \
--location={asia-northeast1} \
--module-path={module_path} \
--version="v0.0.1" \
--source=.

repositoryにはmodule_name
locationは上記と同じ
module-pathにはgo mod initした名称を
versionには適宜更新してください
sourceにはカレントディレクトリ.を指定するのが一般的です

これでartifact registry上にgoモジュールがアップロードされます


3. ローカルでのGoモジュールのダウンロード

  1. 認証
    以下のコマンドを実行してgcloud認証を済ませます
gcloud auth application-default login
  1. Goモジュールの認証
GOPROXY=proxy.golang.org \
go run github.com/GoogleCloudPlatform/artifact-registry-go-tools/cmd/auth@latest add-locations \
--locations=asia-northeast1
GOPROXY=proxy.golang.org \
go run github.com/GoogleCloudPlatform/artifact-registry-go-tools/cmd/auth@latest refresh
  1. Goモジュールのダウンロード
    go.modがある場所に移動してから以下コマンドを実行してモジュールをダウンロードします
go get {module_path}@latest

これでローカルでのGoモジュールの使用ができるようになります

4. Github Actionsの設定

以下はGithub ActionsでGoモジュールをダウンロードさせる流れです

name: Go build, test
on:
  pull_request:
    types:
      - synchronize
      - opened
      - reopened

jobs:
  build_test:
    runs-on: ubuntu-latest
    permissions:
      contents: write
      id-token: write

    steps:
      - name: Check out
        uses: actions/checkout@v4

      - name: Set up
        uses: actions/setup-go@v5
        with:
          go-version-file: 'src/go.mod'

      - id: auth
        name: Authenticate to Google Cloud
        uses: google-github-actions/auth@v2
        with:
          create_credentials_file: true
          workload_identity_provider: {projects/{project_id}/locations/global/workloadIdentityPools/{workload_identity_pools_name}/providers/{provider_name}}
          service_account: {serviceaccount_name}
          access_token_lifetime: 1200s

      - name: Assign GONOPROXY & GOPROXY
        run: |
          go env -w GONOPROXY=github.com/GoogleCloudPlatform/artifact-registry-go-tools
          go env -w GOPROXY=https://proxy.golang.org

      - name: Add location and refresh
        run: |
          go run github.com/GoogleCloudPlatform/artifact-registry-go-tools/cmd/auth@latest add-locations --locations=asia-northeast1
          go run github.com/GoogleCloudPlatform/artifact-registry-go-tools/cmd/auth@latest refresh

      - name: Re-assign GOPROXY & Assign GONOSUMDB
        run: |
          go env -w GONOSUMDB={module_path}
          go env -w GOPROXY=https://{module_path},https://proxy.golang.org,direct

      - name: go mod tidy & download
        run: |
          cd src
          go mod tidy
          go mod download

      - name: Cache
        uses: actions/cache@v4
        with:
          path: ~/go/pkg/mod
          key: ${{ runner.os }}-go-${{ hashFiles('**/go.sum') }}
          restore-keys: |
            ${{ runner.os }}-go-

      - name: Build
        run: cd src && go build

      - name: Test
        run: cd src && MODE=test go test ./... -v
  • 各セクションの詳しい説明
  1. checkout
    checkoutして最新のブランチの状態を取得します

  2. setup-go
    goのsetupをします
    versionはgo.modファイルを指定することでgo.modに書いてあるバージョンが自動で反映されます

  3. auth
    ローカルと同じように認証をします
    ここでハマり、ずっと--json_keyを指定して、${{ steps.auth.outputs.credentials_file_path }}を指定していたのが良くなくて、ずっと401になってしまっていました
    原因はよくわかっていませんが、authの部分でGOOGLE_APPLICATION_CREDENTIALSに値が入り、--json_keyで指定しなくても、add-locationsもrefreshもそれでrefreshができているのかなと思いました

  4. Assign GONOPROXY & GOPROXY
    こちらで、無視するauthするモジュールのパスをGONOPROXYに指定しておきます

  5. Add location and refresh
    ローカルと同じようにします

  6. GONOSUMDBの指定と、GOPROXYの再指定
    checksumの確認をしないように、今回作成したArtifact registryのgoモジュールのモジュールパスをGONOSUMDBに追加し、GOPROXYにArtifact registryのパスを追加します

go env -w GONOSUMDB={module_path}
go env -w GOPROXY=https://{module_path},https://proxy.golang.org,direct

go mod initしたときのmodule_pathが入ります
以下のような形になるはずです

go env -w GONOSUMDB=asia-northeast1-go.pkg.dev/gcp_project_name/module_name
go env -w GOPROXY=https://asia-northeast1-go.pkg.dev/gcp_project_name/module_name,https://proxy.golang.org,direct
  1. go mod tidy & download
    go mod tidyで依存関係の整理をしてから、go downloadします
    上記でGOPROXYを変えてから認証しているので、これで依存関係をエラーなしでdownloadできます

  2. cache
    依存関係のキャッシングを行います
    go.sum ファイルのハッシュをキーにして、キャッシュの復元や保存を行います

  3. Build
    ソースコードのビルドを行います

  4. Test
    テストします

9番以降は任意で追加してください


5. 参考文献とリンク

Discussion