fix: merge all bootstrap migrations

This commit is contained in:
eding 2026-09-09 21:21:27 +02:00
parent 32734dafff
commit 3ea55e34e0
4 changed files with 40 additions and 24 deletions

View file

@ -121,8 +121,16 @@ func runBootstrap(cmd *cobra.Command, args []string) error {
return err return err
} }
manager := forgejo.NewRepoManager(cfg.Git.BaseURL, cfg.Git.Token, cfg.Git.Owner, cfg.Git.Username, "", "", cfg.Flux.Branch, "") manager := forgejo.NewRepoManager(cfg.Git.BaseURL, cfg.Git.Token, cfg.Git.Owner, cfg.Git.Username, "", "", cfg.Flux.Branch, "")
if err := manager.MergePullRequest(cfg.Flux.RepoName, "maidn/bootstrap-"+cfg.ClusterID); err != nil { for _, repository := range []string{cfg.Flux.ManifestsRepo, cfg.Flux.RepoName} {
return err open, err := manager.HasOpenPullRequest(repository, "maidn/bootstrap-"+cfg.ClusterID)
if err != nil {
return err
}
if open {
if err := manager.MergePullRequest(repository, "maidn/bootstrap-"+cfg.ClusterID); err != nil {
return err
}
}
} }
} }
if bootstrapConfigPath != "" { if bootstrapConfigPath != "" {

View file

@ -343,14 +343,16 @@ func (r Runner) Run() error {
} }
func (r Runner) reconcileBootstrapMigration(manager *forgejo.RepoManager) error { func (r Runner) reconcileBootstrapMigration(manager *forgejo.RepoManager) error {
if !manager.MigrationPending { if len(manager.MigrationRepositories) == 0 {
return nil return nil
} }
if !r.AutoMergeBootstrapMigration { if !r.AutoMergeBootstrapMigration {
return errors.New("existing repository migration PR created; merge and rerun bootstrap before infrastructure changes") return fmt.Errorf("repository migration PRs created for %s; merge and rerun bootstrap before infrastructure changes", strings.Join(manager.MigrationRepositories, ", "))
} }
if err := manager.MergePullRequest(r.Config.Flux.RepoName, manager.MigrationBranch); err != nil { for _, repository := range manager.MigrationRepositories {
return fmt.Errorf("merge bootstrap migration PR: %w", err) if err := manager.MergePullRequest(repository, manager.MigrationBranch); err != nil {
return fmt.Errorf("merge bootstrap migration PR for %s: %w", repository, err)
}
} }
return nil return nil
} }

View file

@ -908,15 +908,16 @@ func TestRunnerEnableDeliveryAppliesDefaults(t *testing.T) {
func TestRunnerAutoMergesBootstrapMigration(t *testing.T) { func TestRunnerAutoMergesBootstrapMigration(t *testing.T) {
server := httptest.NewServer(http.HandlerFunc(func(writer http.ResponseWriter, request *http.Request) { server := httptest.NewServer(http.HandlerFunc(func(writer http.ResponseWriter, request *http.Request) {
switch request.Method + " " + request.URL.Path { if request.Method == http.MethodGet && (request.URL.Path == "/api/v1/repos/test-org/manifests/pulls" || request.URL.Path == "/api/v1/repos/test-org/cluster/pulls") {
case http.MethodGet + " /api/v1/repos/test-org/cluster/pulls":
if request.URL.Query().Get("state") != "open" || request.URL.Query().Get("head") != "maidn/bootstrap-test-cluster" { if request.URL.Query().Get("state") != "open" || request.URL.Query().Get("head") != "maidn/bootstrap-test-cluster" {
t.Fatalf("unexpected migration lookup query: %q", request.URL.RawQuery) t.Fatalf("unexpected migration lookup query: %q", request.URL.RawQuery)
} }
_ = json.NewEncoder(writer).Encode([]struct { _ = json.NewEncoder(writer).Encode([]struct {
Number int `json:"number"` Number int `json:"number"`
}{{Number: 4}}) }{{Number: 4}})
case http.MethodPost + " /api/v1/repos/test-org/cluster/pulls/4/merge": return
}
if request.Method == http.MethodPost && (request.URL.Path == "/api/v1/repos/test-org/manifests/pulls/4/merge" || request.URL.Path == "/api/v1/repos/test-org/cluster/pulls/4/merge") {
var body struct { var body struct {
Do string `json:"Do"` Do string `json:"Do"`
} }
@ -924,15 +925,15 @@ func TestRunnerAutoMergesBootstrapMigration(t *testing.T) {
t.Fatalf("unexpected migration merge request: %#v, %v", body, err) t.Fatalf("unexpected migration merge request: %#v, %v", body, err)
} }
writer.WriteHeader(http.StatusOK) writer.WriteHeader(http.StatusOK)
default: return
t.Fatalf("unexpected Forgejo request %s %s", request.Method, request.URL.Path)
} }
t.Fatalf("unexpected Forgejo request %s %s", request.Method, request.URL.Path)
})) }))
defer server.Close() defer server.Close()
manager := forgejo.NewRepoManager(server.URL, "test-token", "test-org", "bot", "manifests", "cluster", "main", "maidn/bootstrap-test-cluster") manager := forgejo.NewRepoManager(server.URL, "test-token", "test-org", "bot", "manifests", "cluster", "main", "maidn/bootstrap-test-cluster")
manager.HTTPClient = server.Client() manager.HTTPClient = server.Client()
manager.MigrationPending = true manager.MigrationRepositories = []string{"manifests", "cluster"}
if err := (Runner{Config: config.Config{Flux: config.FluxConfig{RepoName: "cluster"}}, AutoMergeBootstrapMigration: true}).reconcileBootstrapMigration(manager); err != nil { if err := (Runner{Config: config.Config{Flux: config.FluxConfig{RepoName: "cluster"}}, AutoMergeBootstrapMigration: true}).reconcileBootstrapMigration(manager); err != nil {
t.Fatal(err) t.Fatal(err)
} }
@ -946,7 +947,7 @@ func TestRunnerRetainsMigrationApprovalGate(t *testing.T) {
manager := forgejo.NewRepoManager(server.URL, "test-token", "test-org", "bot", "manifests", "cluster", "main", "maidn/bootstrap-test-cluster") manager := forgejo.NewRepoManager(server.URL, "test-token", "test-org", "bot", "manifests", "cluster", "main", "maidn/bootstrap-test-cluster")
manager.HTTPClient = server.Client() manager.HTTPClient = server.Client()
manager.MigrationPending = true manager.MigrationRepositories = []string{"manifests"}
if err := (Runner{Config: config.Config{Flux: config.FluxConfig{RepoName: "cluster"}}}).reconcileBootstrapMigration(manager); err == nil || !strings.Contains(err.Error(), "merge and rerun bootstrap") { if err := (Runner{Config: config.Config{Flux: config.FluxConfig{RepoName: "cluster"}}}).reconcileBootstrapMigration(manager); err == nil || !strings.Contains(err.Error(), "merge and rerun bootstrap") {
t.Fatalf("normal bootstrap migration gate = %v", err) t.Fatalf("normal bootstrap migration gate = %v", err)
} }

View file

@ -16,16 +16,16 @@ import (
) )
type RepoManager struct { type RepoManager struct {
BaseURL string BaseURL string
Token string Token string
Owner string Owner string
Username string Username string
ManifestsRepoName string ManifestsRepoName string
FluxRepoName string FluxRepoName string
Branch string Branch string
MigrationBranch string MigrationBranch string
MigrationPending bool MigrationRepositories []string
HTTPClient *http.Client HTTPClient *http.Client
} }
type createRepoRequest struct { type createRepoRequest struct {
@ -379,7 +379,12 @@ func (rm *RepoManager) setupRepository(repoURL, repoName string, existing bool,
if err != nil || !changed || !existing { if err != nil || !changed || !existing {
return err return err
} }
rm.MigrationPending = true for _, repository := range rm.MigrationRepositories {
if repository == repoName {
return rm.createMigrationPullRequest(repoName, targetBranch)
}
}
rm.MigrationRepositories = append(rm.MigrationRepositories, repoName)
return rm.createMigrationPullRequest(repoName, targetBranch) return rm.createMigrationPullRequest(repoName, targetBranch)
} }