Skip to content

feat: 定義ファイルに無いリモート変数を削除する prune 機能を追加#40

Merged
polidog merged 2 commits into
mainfrom
feat/prune-undefined-vars
Jul 2, 2026
Merged

feat: 定義ファイルに無いリモート変数を削除する prune 機能を追加#40
polidog merged 2 commits into
mainfrom
feat/prune-undefined-vars

Conversation

@polidog

@polidog polidog commented Jul 2, 2026

Copy link
Copy Markdown
Member

概要

env-sync.yaml に定義されていないリモートの変数を同期時に削除する prune 機能を追加します。

使い方

# env-sync.yaml
prune: true
prune_exclude:
  - BLOB_*        # 例: Vercel Blob Store が発行するトークンを保持
  - SENTRY_DSN

variables:
  DATABASE_URL: { secret: true }

CLI の --prune フラグでも有効化できます(フラグ or yaml のどちらかが true なら実行)。

仕様

保持ルール

  • variables に宣言されたキーは .env に値が無くても削除しない
  • prune_exclude の glob パターンに一致するキーは保持(大文字小文字非区別、不正パターンは起動時エラー)

安全確認

  • 削除対象を - KEY [削除] 形式で一覧表示し、削除がある場合は必ず y/N 確認--yes でスキップ、--dry-run は表示のみ)
  • 既存一覧の取得に失敗した場合は削除をスキップして警告(誤削除防止の安全側フォールバック)

プロバイダーごとの挙動

プロバイダー 削除対象 自動除外
Vercel 環境変数(レコード単位、DELETE /v9/projects/:id/env/:envId システム変数、インテグレーション由来の変数(configurationId 付き、Blob Store / Marketplace 等)
GitHub Actions Secrets / Variables(repo レベル + 定義に現れる named environment、ページング対応)
GCP managed-by=env-sync ラベル付き Secret のみ ラベルの無い(env-sync 以外が作成した)Secret

GCP の付随変更

  • 同期時に managed-by: env-sync ラベルを常時付与(prune の対象識別用)
  • 既存 Secret のラベルはマージで更新し、無関係なラベルは保持。差分が無ければ更新 API をスキップ

テスト

  • 各プロバイダーの純粋関数(削除対象計算・除外判定)と API 呼び出し(httptest / モック)のテストを追加
  • go test ./... / go vet / gofmt すべて通過

🤖 Generated with Claude Code

env-sync.yaml トップレベルの prune: true または --prune フラグで有効化し、
variables に宣言されていないリモートの変数を同期時に削除する。

- 保持ルール: variables 宣言済みキーは .env に値が無くても削除しない。
  prune_exclude(glob パターン・大文字小文字非区別)で任意キーを除外可能
- 安全確認: 削除対象を一覧表示し、削除がある場合は必ず y/N 確認
  (--yes でスキップ、--dry-run は表示のみ)。既存一覧の取得失敗時は
  削除をスキップして警告
- Vercel: レコード単位で DELETE (/v9/projects/:id/env/:envId)。
  システム変数とインテグレーション由来の変数(configurationId 付き、
  Blob Store / Marketplace 等)は自動除外
- GitHub: Actions Secrets / Variables を repo レベル + 定義に現れる
  named environment スコープで削除(ページング対応)
- GCP: 同期時に managed-by=env-sync ラベルを自動付与し、prune は
  このラベル付き Secret のみ対象(既存の無関係なラベルはマージで保持)

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

env-sync.yaml に定義されていないリモート変数を同期時に削除する prune 機能を追加し、Vercel/GitHub/GCP 各プロバイダーで安全確認付きの削除フローとテストを整備する PR です。

Changes:

  • 定義ファイル(prune, prune_exclude)と CLI(--prune)から prune を有効化できるようにし、保持ルール(定義済みキー + 除外 glob)を共通化
  • Vercel/GitHub/GCP で削除対象の収集・一覧表示・確認・削除処理を追加(取得失敗時は安全側でスキップ)
  • i18n・README・サンプル YAML・テストを追加し、GCP では managed-by=env-sync ラベルの付与/マージ/差分更新も実装

Reviewed changes

Copilot reviewed 20 out of 20 changed files in this pull request and generated 2 comments.

Show a summary per file
File Description
README.md prune/prune_exclude と --prune の仕様・使い方を追記
README.ja.md prune/prune_exclude と --prune の仕様・使い方を追記(日本語)
internal/provider/vercel/vercel.go Vercel の既存 env 取得・prune 対象算出・削除 API 呼び出しを追加
internal/provider/vercel/prune_test.go Vercel prune(対象算出・削除 API)テストを追加
internal/provider/vercel/classify_test.go 既存取得関数名変更(fetch keys→fetch envs)に追従
internal/provider/prune_test.go Options.PruneKeepValidatePrunePatterns のテストを追加
internal/provider/provider.go prune 用のオプション(Prune/DefinedKeys/PruneExclude)と保持判定・パターン検証を追加
internal/provider/github/prune_test.go GitHub prune(スコープ収集・一覧取得・削除)テストを追加
internal/provider/github/github.go GitHub の prune 対象収集・一覧表示・確認・削除処理を追加
internal/provider/gcp/prune_test.go GCP prune(対象算出・Sync フロー)テストを追加
internal/provider/gcp/gcp.go GCP の prune(managed-by ラベルで限定)とラベルマージ更新を追加
internal/provider/gcp/gcp_test.go buildLabels の仕様変更とラベルマージ/更新スキップのテストを追加
internal/i18n/keys.go prune 関連メッセージキーを追加
internal/i18n/catalog_ja.go prune 関連メッセージ(日本語)を追加
internal/i18n/catalog_en.go prune 関連メッセージ(英語)を追加
internal/config/prune_test.go 定義ファイルの prune/prune_exclude パースと --prune のテストを追加
internal/config/config.go Definition に prune/prune_exclude を追加し --prune をパース
go.mod GCP の iterator 利用に伴う依存を direct に調整
env-sync.yaml prune/prune_exclude のコメント(仕様)を追記
cmd/env-sync/main.go prune 有効化解決・glob 検証・DefinedKeys/PruneExclude を provider に伝播

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment on lines +454 to +461
var prune []vercelEnv
for _, e := range envs {
if e.System || e.Type == "system" || e.ConfigurationID != "" || keep(e.Key) {
continue
}
prune = append(prune, e)
}
return prune

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

d379072 で対応しました。ID が空のレコードは computeVercelPrune で prune 対象から除外するようにしています(テスト追加済み)。

Comment on lines +203 to +223
Variables []struct {
Name string `json:"name"`
} `json:"variables"`
}
err = json.NewDecoder(res.Body).Decode(&resp)
res.Body.Close()
if err != nil {
return nil, fmt.Errorf("%s: %w", i18n.T(i18n.MsgRequestFail), err)
}

count := 0
for _, s := range resp.Secrets {
names = append(names, s.Name)
count++
}
for _, v := range resp.Variables {
names = append(names, v.Name)
count++
}
if count < perPage {
return names, nil

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

d379072 で対応しました。total_count に達したら終了するようにし、total_count が取得できない場合は従来の count < per_page で終了するフォールバックを残しています(100 件ちょうどで追加リクエストが飛ばないテストを追加済み)。

- Vercel: ID が空の env レコードは削除 URL を組み立てられないため
  prune 対象から安全側に除外する
- GitHub: 一覧取得のページング終了判定に total_count を利用し、
  件数が per_page の倍数のときの余分な空ページ取得を回避する
  (total_count が取得できない場合は従来の count < per_page で終了)

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
@polidog polidog merged commit 8cd5f50 into main Jul 2, 2026
1 check passed
@polidog polidog deleted the feat/prune-undefined-vars branch July 2, 2026 07:20
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants