Conversation
- internal/provider/gcp/gcp.go: gcpProvider を実装し Provider interface を満たす
- init() で RegisterProvider("gcp", ...) を呼び自己登録する
- 認証: Application Default Credentials (ADC) を使用
- 必須環境変数: GCP_PROJECT_ID
- Entry.Secret == false のエントリはスキップしてログ出力
- Entry.Environments が指定された場合、labels {"environment": "<env>"} を付与
- opts.DryRun == true の場合は API 呼び出しをスキップしてログのみ出力
- cmd/env-sync/main.go に blank import を追加
- go.mod / go.sum に cloud.google.com/go/secretmanager 依存を追加
- env-sync.yaml サンプルに provider: gcp の使用例を追記
Co-Authored-By: Claude Sonnet 4.6 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01MUNfaHdh77j6ZEA2v8oieH
There was a problem hiding this comment.
Pull request overview
GCP Secret Manager へ .env の値を同期できるようにするため、新しい gcp provider を追加し、registry 登録・依存追加・サンプル設定を更新する PR です。
Changes:
internal/provider/gcpに Secret Manager 同期ロジック(作成/ラベル更新/バージョン追加)を実装し、自動登録を追加- GCP provider のユニット/結合テストを追加し、依存関係(Secret Manager SDK など)を
go.mod/go.sumに追加 cmd/env-syncで gcp provider を blank import し、env-sync.yamlサンプルに使用例を追記
Reviewed changes
Copilot reviewed 6 out of 7 changed files in this pull request and generated 5 comments.
Show a summary per file
| File | Description |
|---|---|
| internal/provider/gcp/gcp.go | GCP Secret Manager への同期処理(secret の作成/更新、labels、バージョン追加)を追加 |
| internal/provider/gcp/gcp_test.go | buildLabels / syncSecret / Sync のテストを追加 |
| internal/provider/gcp/export_test.go | テスト用の差し替え・エクスポート補助を追加 |
| cmd/env-sync/main.go | gcp provider を registry 登録するための blank import を追加 |
| env-sync.yaml | provider: gcp の利用例と説明を追記 |
| go.mod | Secret Manager SDK 等の依存を追加 |
| go.sum | 依存追加に伴うチェックサム更新 |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
| return nil | ||
| } | ||
|
|
||
| ctx := context.Background() |
Comment on lines
+163
to
+174
| } else if len(labels) > 0 { | ||
| // 既存 secret の labels を更新する | ||
| if _, err = client.UpdateSecret(ctx, &secretmanagerpb.UpdateSecretRequest{ | ||
| Secret: &secretmanagerpb.Secret{ | ||
| Name: secretName, | ||
| Labels: labels, | ||
| }, | ||
| UpdateMask: &fieldmaskpb.FieldMask{Paths: []string{"labels"}}, | ||
| }); err != nil { | ||
| return fmt.Errorf("Secret のラベル更新に失敗: %s", err) | ||
| } | ||
| } |
| # ※ GitHub の named environment は事前に作成が必要 | ||
| # | ||
| # provider: vercel|github|[vercel, github] | ||
| # provider: vercel|github|gcp|[vercel, gcp] |
| # 必須環境変数: GCP_PROJECT_ID(対象 GCP プロジェクト ID) | ||
| # 認証: Application Default Credentials(GOOGLE_APPLICATION_CREDENTIALS または ADC 自動解決) | ||
| # secret: true のエントリのみ同期(false はスキップ) | ||
| # environments に値を設定すると、Secret に labels {"environment": "<env>"} が付与される |
Comment on lines
+45
to
47
| _ "github.com/ptyhard/env-sync/internal/provider/gcp" | ||
| _ "github.com/ptyhard/env-sync/internal/provider/github" | ||
| _ "github.com/ptyhard/env-sync/internal/provider/vercel" |
- GCP provider に確認プロンプト(--yes フラグ未指定時)を追加し、vercel/github と挙動を統一 - env-sync.yaml のコメントに複数 provider 指定例([vercel, github])と environments 複数時の挙動を追記 - cmd/env-sync/main.go の usage に GCP_PROJECT_ID / ADC 認証説明を追加 Co-Authored-By: Claude Sonnet 4.6 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01MUNfaHdh77j6ZEA2v8oieH
| if !config.IsTTY(os.Stdin) { | ||
| return fmt.Errorf("対話できない環境です。確認をスキップするには --yes を付けてください") | ||
| } | ||
| fmt.Print("上記を GCP Secret Manager に登録します(既存は上書き)。続行しますか? (y/N) ") |
Comment on lines
+173
to
+179
| if _, err = client.CreateSecret(ctx, &secretmanagerpb.CreateSecretRequest{ | ||
| Parent: parent, | ||
| SecretId: e.Key, | ||
| Secret: secret, | ||
| }); err != nil { | ||
| return fmt.Errorf("Secret の作成に失敗: %s", err) | ||
| } |
- 確認プロンプトの文言を「既存は上書き」から「新しいバージョンとして追加」に修正 (Secret Manager はバージョン追加であり上書きではないため) - CreateSecret の AlreadyExists エラーを吸収し、並行実行・再実行時の競合を安全に処理 Co-Authored-By: Claude Sonnet 4.6 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01MUNfaHdh77j6ZEA2v8oieH
Comment on lines
+185
to
+196
| } else if len(labels) > 0 { | ||
| // 既存 secret の labels を更新する | ||
| if _, err = client.UpdateSecret(ctx, &secretmanagerpb.UpdateSecretRequest{ | ||
| Secret: &secretmanagerpb.Secret{ | ||
| Name: secretName, | ||
| Labels: labels, | ||
| }, | ||
| UpdateMask: &fieldmaskpb.FieldMask{Paths: []string{"labels"}}, | ||
| }); err != nil { | ||
| return fmt.Errorf("Secret のラベル更新に失敗: %s", err) | ||
| } | ||
| } |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
タスク
internal/provider/gcp/gcp.goにgcpProviderstruct を実装し、Provider interface(Name() string,Sync(opts Options, entries []Entry) error)を満たすinit()関数内でRegisterProvider("gcp", ...)を呼び出し自己登録cmd/env-sync/main.goで_ "github.com/ptyhard/env-sync/internal/provider/gcp"を blank import して registry に登録GCP_PROJECT_ID(Secret Manager の対象 GCP プロジェクト ID)Entry.Secret == trueの場合は Secret Manager に secret として作成・更新(バージョン追加)Entry.Secret == falseのエントリはスキップしてログ出力Entry.Environmentsが指定された場合、labels{"environment": "<env>"}を secret に付与opts.DryRun == trueの場合は API 呼び出しをスキップしてログのみ出力go.mod/go.sumにcloud.google.com/go/secretmanager依存を追加env-sync.yamlサンプルにprovider: gcpの使用例を追記完了条件
env-sync.yamlでprovider: gcpまたはprovider: [vercel, gcp]と設定したとき、GCP Secret Manager に環境変数が同期されるGCP_PROJECT_IDが未設定の場合、明示的なエラーメッセージが表示されるEntry.Secret == falseのエントリはスキップされ、警告ログが出力される--dry-runフラグ使用時は API 呼び出しなしで対象キー一覧がログ出力されるgo test ./...がすべてパスする(internal/provider/gcp/gcp_test.goを含む)go build ./...がエラーなしで通る動作確認
go build ./...)go test ./...全 7 パッケージ PASS)品質チェック結果
特記事項なし
テスト内容
internal/provider/gcp/gcp_test.goに以下のテストを追加:TestBuildLabels_*: labels 組み立てロジックのユニットテスト(空・1件・複数)TestSyncSecret_*: secret の新規作成・既存更新・エラーハンドリングのテストTestSync_MissingProjectID: GCP_PROJECT_ID 未設定時のエラー確認TestSync_DryRun: dry-run 時の API 非呼び出し確認TestSync_SkipsNonSecretEntries: secret=false エントリのスキップ確認TestSync_SecretCreatedAndVersionAdded: 正常系 E2E テストTestGCPProvider_Registered: registry への自動登録確認実装方針
secretManagerClientインターフェースを定義してテスタビリティを確保(export_test.goでSwapClientFuncを公開)realClientラッパーが本物の*secretmanager.Clientを wrap してインターフェースに適合させるnewClientFunc変数でクライアント生成をテストで差し替え可能にするCreateSecret(labels 付き)→AddSecretVersionUpdateSecret(environments ある時のみ)→AddSecretVersion