From 4d5f9f46da511907a761a82b2f94a7ce7f14eda9 Mon Sep 17 00:00:00 2001 From: eding Date: Sun, 26 Jul 2026 20:46:11 +0200 Subject: [PATCH] feat: initialize configured app repository --- cmd/bootstrap.go | 9 +++++++++ internal/forgejo/repo.go | 23 +++++++++++++++++++---- internal/forgejo/repo_test.go | 27 +++++++++++++++++++++++++++ 3 files changed, 55 insertions(+), 4 deletions(-) diff --git a/cmd/bootstrap.go b/cmd/bootstrap.go index 538a8f7..c7d6691 100644 --- a/cmd/bootstrap.go +++ b/cmd/bootstrap.go @@ -58,6 +58,15 @@ func runBootstrap(cmd *cobra.Command, args []string) error { return err } manager := forgejo.NewRepoManager(cfg.Git.BaseURL, cfg.Git.Token, owner, cfg.Git.Username, "", "", cfg.Delivery.AppRepoRef, "") + created, err := manager.EnsureRepository(repo, "Application source for Maidn CI/CD delivery") + if err != nil { + return err + } + if created { + if err := manager.PushRef(bootstrapPublishAppFrom, cfg.Delivery.AppRepoURL, cfg.Delivery.AppRepoRef, cfg.Delivery.AppRepoRef); err != nil { + return err + } + } if err := manager.PushBranch(bootstrapPublishAppFrom, cfg.Delivery.AppRepoURL, branch); err != nil { return err } diff --git a/internal/forgejo/repo.go b/internal/forgejo/repo.go index 1c42d86..408bcdb 100644 --- a/internal/forgejo/repo.go +++ b/internal/forgejo/repo.go @@ -90,7 +90,7 @@ func (rm *RepoManager) ensureRepo(name, description string, createStructure func return err } if !exists { - if err := rm.createRepo(name, description); err != nil { + if err := rm.createRepo(name, description, true); err != nil { return err } } @@ -112,12 +112,12 @@ func (rm *RepoManager) repoExists(name string) (bool, error) { } } -func (rm *RepoManager) createRepo(name, description string) error { +func (rm *RepoManager) createRepo(name, description string, autoInit bool) error { createURL := fmt.Sprintf("%s/api/v1/orgs/%s/repos", rm.BaseURL, rm.Owner) if rm.Owner == rm.Username { createURL = fmt.Sprintf("%s/api/v1/user/repos", rm.BaseURL) } - body, err := json.Marshal(createRepoRequest{Name: name, Description: description, Private: true, AutoInit: true, DefaultBranch: rm.Branch}) + body, err := json.Marshal(createRepoRequest{Name: name, Description: description, Private: true, AutoInit: autoInit, DefaultBranch: rm.Branch}) if err != nil { return err } @@ -131,6 +131,17 @@ func (rm *RepoManager) createRepo(name, description string) error { return nil } +func (rm *RepoManager) EnsureRepository(name, description string) (bool, error) { + exists, err := rm.repoExists(name) + if err != nil { + return false, err + } + if exists { + return false, nil + } + return true, rm.createRepo(name, description, false) +} + func (rm *RepoManager) setupRepository(repoURL, repoName string, existing bool, createStructure func(string) error) error { tempDir, err := os.MkdirTemp("", "repo-setup-*") if err != nil { @@ -183,12 +194,16 @@ func (rm *RepoManager) CreatePullRequest(repo, title, head, base string) error { } func (rm *RepoManager) PushBranch(dir, repoURL, branch string) error { + return rm.PushRef(dir, repoURL, "HEAD", branch) +} + +func (rm *RepoManager) PushRef(dir, repoURL, sourceRef, targetBranch string) error { cleanupAskPass, environment, err := rm.gitEnvironment(dir) if err != nil { return err } defer cleanupAskPass() - return runGit(dir, environment, "push", repoURL, "HEAD:refs/heads/"+branch) + return runGit(dir, environment, "push", repoURL, sourceRef+":refs/heads/"+targetBranch) } func CurrentBranch(dir string) (string, error) { diff --git a/internal/forgejo/repo_test.go b/internal/forgejo/repo_test.go index 443bbf5..735952e 100644 --- a/internal/forgejo/repo_test.go +++ b/internal/forgejo/repo_test.go @@ -89,6 +89,33 @@ func TestRepositoryFromURL(t *testing.T) { } } +func TestEnsureRepositoryCreatesWithoutInitialization(t *testing.T) { + server := httptest.NewServer(http.HandlerFunc(func(writer http.ResponseWriter, request *http.Request) { + switch request.Method { + case http.MethodGet: + writer.WriteHeader(http.StatusNotFound) + case http.MethodPost: + var body createRepoRequest + if err := json.NewDecoder(request.Body).Decode(&body); err != nil { + t.Fatal(err) + } + if body.AutoInit { + t.Fatal("application repository must be created without an initial commit") + } + writer.WriteHeader(http.StatusCreated) + default: + t.Fatalf("unexpected method %q", request.Method) + } + })) + defer server.Close() + manager := NewRepoManager(server.URL, "token", "owner", "user", "manifests", "cluster", "main", "maidn/bootstrap-test") + manager.HTTPClient = server.Client() + created, err := manager.EnsureRepository("app", "description") + if err != nil || !created { + t.Fatalf("EnsureRepository() = (%t, %v)", created, err) + } +} + func TestRepoExistsReturnsFalseOnNotFound(t *testing.T) { server := httptest.NewServer(http.HandlerFunc(func(writer http.ResponseWriter, request *http.Request) { writer.WriteHeader(http.StatusNotFound)