Conversation
env-sync.yaml の variables 各エントリと defaults に provider フィールドを追加。 provider: vercel / github / [vercel, github] を許可し、1 回の実行で複数プロバイダーへ 振り分け同期できるようにした。解決優先順位は varConf > defaults > CLI --provider。 - ProviderVal 型を追加(YAML で string / []string 両対応) - Entry.Providers フィールドを追加してプロバイダー情報を保持 - resolveEntries に cliProvider 引数を追加しプロバイダー解決・検証を実装 - run() で dry-run 時に統合一覧(key -> provider)を表示して早期終了 - run() でプロバイダーごとにエントリを振り分け Sync() を呼び出すよう変更 - 不正な provider 値はエラーで中止 - README と env-sync.yaml にドキュメントを追記 Co-Authored-By: Claude Sonnet 4.6 (1M context) <noreply@anthropic.com>
Closed
There was a problem hiding this comment.
Pull request overview
env-sync.yaml の各変数ごとに同期先プロバイダー(Vercel / GitHub / 両方)を指定できるようにし、1 回の実行で複数プロバイダーへ振り分けて同期できるようにする PR です。CLI の --provider から YAML 設定(変数個別 / defaults)へ解決優先順位を拡張しています。
Changes:
- YAML スキーマに
provider(string / []string)を追加し、優先順位(var > defaults > CLI)で解決 run()で Entry を provider ごとに振り分けて、登録順に各 Provider へ Sync- README / env-sync.yaml コメントに provider 混在指定の例と説明を追記、関連テストを追加
Reviewed changes
Copilot reviewed 8 out of 8 changed files in this pull request and generated 3 comments.
Show a summary per file
| File | Description |
|---|---|
| README.md | provider フィールドの説明と混在指定例を追記 |
| main.go | provider ごとに振り分けて同期、dry-run 出力の変更 |
| init_test.go | resolveEntries の新シグネチャに追従 |
| env-sync.yaml | provider フィールドの説明コメントと例を追記 |
| entry.go | provider 解決・検証ロジックを resolveEntries に追加し Entry.Providers を導入 |
| entry_test.go | provider 解決ロジックのユニットテストを追加 |
| config.go | YAML の provider を string / []string で扱う ProviderVal を追加 |
| config_test.go | ProviderVal の YAML パーステストを追加 |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
Comment on lines
+58
to
+76
| // provider の解決: varConf.Provider → defaults.Provider → CLI フラグ | ||
| var providers []string | ||
| if def.Defaults.Provider != nil { | ||
| providers = def.Defaults.Provider.Values | ||
| } | ||
| if conf.Provider != nil { | ||
| providers = conf.Provider.Values | ||
| } | ||
| if len(providers) == 0 { | ||
| providers = []string{cliProvider} | ||
| } | ||
|
|
||
| // provider 値の検証 | ||
| for _, p := range providers { | ||
| if !isRegisteredProvider(p) { | ||
| names := strings.Join(registeredProviderNames(), " / ") | ||
| return nil, fmt.Errorf("%s: 不正な provider 値 %q(%s のいずれかを指定してください)", key, p, names) | ||
| } | ||
| } |
Comment on lines
+122
to
+134
| // ---- dry-run: 統合一覧表示して終了 ---- | ||
| if opts.dryRun { | ||
| if len(entries) == 0 { | ||
| fmt.Println("登録対象がありません") | ||
| } else { | ||
| fmt.Printf("同期対象 %d 件:\n", len(entries)) | ||
| for _, e := range entries { | ||
| fmt.Printf(" %s -> %s\n", e.Key, strings.Join(e.Providers, ", ")) | ||
| } | ||
| } | ||
| fmt.Println("\n[dry-run] 送信しません") | ||
| return nil | ||
| } |
Comment on lines
+245
to
+293
| // provider に両方指定できる | ||
| func TestResolveEntries_ProviderBoth(t *testing.T) { | ||
| pv := &ProviderVal{Values: []string{"vercel", "github"}} | ||
| def := definition{ | ||
| Variables: map[string]varConf{ | ||
| "FOO": {Provider: pv}, | ||
| }, | ||
| } | ||
| envVars := map[string]string{"FOO": "bar"} | ||
| entries, err := resolveEntries(def, envVars, []string{"FOO"}, "vercel") | ||
| if err != nil { | ||
| t.Fatalf("resolveEntries エラー: %v", err) | ||
| } | ||
| if len(entries[0].Providers) != 2 { | ||
| t.Fatalf("Providers len = %d, want 2", len(entries[0].Providers)) | ||
| } | ||
| } | ||
|
|
||
| // 不正な provider 値はエラーを返す | ||
| func TestResolveEntries_ProviderInvalid(t *testing.T) { | ||
| pv := &ProviderVal{Values: []string{"gitlab"}} | ||
| def := definition{ | ||
| Variables: map[string]varConf{ | ||
| "FOO": {Provider: pv}, | ||
| }, | ||
| } | ||
| envVars := map[string]string{"FOO": "bar"} | ||
| _, err := resolveEntries(def, envVars, []string{"FOO"}, "vercel") | ||
| if err == nil { | ||
| t.Error("不正な provider 値でエラーが返らなかった") | ||
| } | ||
| } | ||
|
|
||
| // provider が YAML に無ければ CLI フラグのデフォルトが使われる | ||
| func TestResolveEntries_ProviderFallbackToCLI(t *testing.T) { | ||
| def := definition{ | ||
| Variables: map[string]varConf{ | ||
| "FOO": {}, | ||
| }, | ||
| } | ||
| envVars := map[string]string{"FOO": "bar"} | ||
| entries, err := resolveEntries(def, envVars, []string{"FOO"}, "github") | ||
| if err != nil { | ||
| t.Fatalf("resolveEntries エラー: %v", err) | ||
| } | ||
| if len(entries[0].Providers) != 1 || entries[0].Providers[0] != "github" { | ||
| t.Errorf("Providers = %v, want [github]", entries[0].Providers) | ||
| } | ||
| } |
Copilot レビューの指摘に対応: - entry.go: [vercel, vercel] のような重複 provider を deduplicateProviders で排除し二重 Sync を防止 - entry.go: provider: [] の明示的空配列はフォールバックせずエラーを返すよう変更 - main.go: --dry-run の出力に secret と environments 情報を追加(key のみだった表示を拡充) - entry_test.go: 重複 provider 排除・空配列エラーのテストを追加 Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Comment on lines
+58
to
+76
| // provider の解決: varConf.Provider → defaults.Provider → CLI フラグ | ||
| var providers []string | ||
| if def.Defaults.Provider != nil { | ||
| providers = def.Defaults.Provider.Values | ||
| } | ||
| if conf.Provider != nil { | ||
| providers = conf.Provider.Values | ||
| } | ||
| if len(providers) == 0 { | ||
| providers = []string{cliProvider} | ||
| } | ||
|
|
||
| // provider 値の検証 | ||
| for _, p := range providers { | ||
| if !isRegisteredProvider(p) { | ||
| names := strings.Join(registeredProviderNames(), " / ") | ||
| return nil, fmt.Errorf("%s: 不正な provider 値 %q(%s のいずれかを指定してください)", key, p, names) | ||
| } | ||
| } |
Comment on lines
+136
to
+137
| // ---- プロバイダーへ同期(登録順) ---- | ||
| for _, pname := range registeredProviderNames() { |
Comment on lines
+278
to
+293
| // provider が YAML に無ければ CLI フラグのデフォルトが使われる | ||
| func TestResolveEntries_ProviderFallbackToCLI(t *testing.T) { | ||
| def := definition{ | ||
| Variables: map[string]varConf{ | ||
| "FOO": {}, | ||
| }, | ||
| } | ||
| envVars := map[string]string{"FOO": "bar"} | ||
| entries, err := resolveEntries(def, envVars, []string{"FOO"}, "github") | ||
| if err != nil { | ||
| t.Fatalf("resolveEntries エラー: %v", err) | ||
| } | ||
| if len(entries[0].Providers) != 1 || entries[0].Providers[0] != "github" { | ||
| t.Errorf("Providers = %v, want [github]", entries[0].Providers) | ||
| } | ||
| } |
Copilot ラウンド 2 の指摘に対応: - 同期対象が 0 件の場合、dry-run 以外の通常実行でも何も出力されずに正常終了していた - 0 件チェックを dry-run 分岐の前に統合し、明示的なメッセージを出して早期 return Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Comment on lines
+74
to
+78
| if len(providers) == 0 { | ||
| providers = []string{cliProvider} | ||
| } | ||
| // [vercel, vercel] のような重複指定で二重 Sync にならないよう排除する | ||
| providers = deduplicateProviders(providers) |
Comment on lines
+60
to
+66
| if def.Defaults.Provider != nil { | ||
| if len(def.Defaults.Provider.Values) == 0 { | ||
| names := strings.Join(registeredProviderNames(), " / ") | ||
| return nil, fmt.Errorf("defaults.provider に空配列が指定されています(%s のいずれかを指定してください)", names) | ||
| } | ||
| providers = def.Defaults.Provider.Values | ||
| } |
Comment on lines
+74
to
+78
| if len(providers) == 0 { | ||
| providers = []string{cliProvider} | ||
| } | ||
| // [vercel, vercel] のような重複指定で二重 Sync にならないよう排除する | ||
| providers = deduplicateProviders(providers) |
- provider: " " など空白のみの指定が deduplicateProviders() 後に空になった場合、 静かに落ちずエラーを返すよう修正 - defaults.provider の不正値を、varConf による上書きの有無にかかわらず resolveEntries の先頭で事前検証するよう修正(不正値は即エラー) - 各ケースのユニットテストを追加 Co-Authored-By: Claude Sonnet 4.6 (1M context) <noreply@anthropic.com>
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.
タスク
背景
現状の
--provider vercel|githubは CLI フラグで全変数に一律適用され、変数ごとに同期先を選べない。1 つのenv-sync.yaml内で「この変数は Vercel、この変数は GitHub」と混在指定できるようにした。変更内容
env-sync.yamlのvariables各エントリとdefaultsにproviderフィールドを追加vercel/github、または両方へ送る配列[vercel, github]を許可provider→defaults.provider→ CLI--providerフラグ--dry-runの一覧出力に各 key の同期先プロバイダーを表示env-sync.yamlのコメントにproviderフィールドの説明と混在指定の例を追記完了条件
env-sync.yamlの各変数およびdefaultsでprovider: vercel/provider: github/provider: [vercel, github]が宣言できる。--providerの優先順位で同期先が解決される。providerをどこにも書かない既存のenv-sync.yamlは従来どおり--providerフラグ(デフォルト vercel)で動作する(後方互換)。provider値を指定するとエラーメッセージを出して中止する。--dry-runで各 key の同期先プロバイダーが確認できる。env-sync.yamlコメントにproviderフィールドの説明・例が追記されている。go test ./...が通る。動作確認
go test ./...)主な実装ポイント
ProviderVal型: YAML でstring/[]stringを透過的に扱うカスタム UnmarshalYAMLEntry.Providers []string: 解決済みプロバイダーリストを保持resolveEntriesにcliProvider string引数を追加しプロバイダー解決・検証を実装run()で dry-run 時に統合一覧(KEY -> vercel, github)を表示して早期終了run()でproviderEntriesマップに振り分け、登録順で各 Sync() を呼び出し