11package cmd
22
33import (
4- "errors"
54 "fmt"
6- "log"
7- "os"
8- "path/filepath"
9- "time"
105
116 "github.com/go-git/go-git/v5"
12- "github.com/go-git/go-git/v5/config "
13- "github.com/go-git/go-git/v5/plumbing "
14- "github.com/go-git/go-git/v5/plumbing/object "
7+ deploymentrepo "github.com/openmcp-project/bootstrapper/internal/deployment-repo "
8+ "github.com/openmcp-project/bootstrapper/internal/log "
9+ "github.com/openmcp-project/bootstrapper/internal/util "
1510 "github.com/spf13/cobra"
1611
1712 gitconfig "github.com/openmcp-project/bootstrapper/internal/git-config"
18- "github.com/openmcp-project/bootstrapper/internal/template"
1913)
2014
2115const (
@@ -25,34 +19,34 @@ const (
2519type LogWriter struct {}
2620
2721func (w LogWriter ) Write (p []byte ) (n int , err error ) {
28- log .Print (string (p ))
22+ logger := log .GetLogger ()
23+ logger .Debugf ("Git progress: %s" , string (p ))
2924 return len (p ), nil
3025}
3126
3227// manageDeploymentRepoCmd represents the manageDeploymentRepo command
3328var manageDeploymentRepoCmd = & cobra.Command {
3429 Use : "manageDeploymentRepo" ,
35- Short : "A brief description of your command" ,
36- Long : `A longer description that spans multiple lines and likely contains examples
37- and usage of using your command. For example:
38-
39- Cobra is a CLI library for Go that empowers applications.
40- This application is a tool to generate the needed files
41- to quickly create a Cobra application.` ,
30+ Short : "Updates the openMCP deployment specification in the specified Git repository" ,
31+ Long : `Updates the openMCP deployment specification in the specified Git repository.
32+ The update is based on the specified component version.
33+ openmcp-bootstrapper manageDeploymentRepo <componentLocation> <templateDirectory> <deploymentRepository> <deploymentRepositoryBranch>` ,
4234 Args : cobra .ExactArgs (4 ),
4335 ArgAliases : []string {
4436 "componentLocation" ,
4537 "templateDirectory" ,
4638 "deploymentRepository" ,
4739 "deploymentRepositoryBranch" ,
4840 },
41+ Example : ` openmcp-bootstrapper manageDeploymentRepo "ghcr.io/openmcp-project/components//github.com/openmcp-project/openmcp:${OPENMCP_VERSION}" ./templates "https://github.com/${GITHUB_USER}/deployment-repo.git" incoming-branch` ,
4942 RunE : func (cmd * cobra.Command , args []string ) error {
5043 //componentLocation := args[0]
5144 templateDirectory := args [1 ]
5245 deploymentRepository := args [2 ]
5346 deploymentRepositoryBranch := args [3 ]
5447
55- log .Println ("parsing git config file from flag:" , cmd .Flag (FlagGitConfig ).Value .String ())
48+ logger := log .GetLogger ()
49+ logger .Debug ("parsing git config file from flag:" , cmd .Flag (FlagGitConfig ).Value .String ())
5650
5751 gitConfig , err := gitconfig .ParseConfig (cmd .Flag (FlagGitConfig ).Value .String ())
5852 if err != nil {
@@ -70,164 +64,40 @@ to quickly create a Cobra application.`,
7064 return err
7165 }
7266
73- tmpDir , err := os .MkdirTemp ("" , "deployment-repo-" )
74- if err != nil {
75- return fmt .Errorf ("failed to create temp dir: %w" , err )
76- }
77-
78- repo , err := CloneRepo (deploymentRepository , tmpDir , gitConfig )
79- log .Println ("Cloned repository to temporary directory: " , tmpDir )
67+ tempDir , err := util .CreateTempDir ("deployment-repo-" )
68+ logger .Tracef ("Created temp dir: %s" , tempDir )
8069 if err != nil {
81- return fmt .Errorf ("failed to clone repository: %w" , err )
70+ return fmt .Errorf ("failed to create temporary directory for deployment repository: %w" , err )
8271 }
83- defer func (path string ) {
84- err := os .RemoveAll (path )
85- if err != nil {
86- _ , _ = fmt .Fprintf (os .Stderr , "failed to remove temporary directory %s: %v\n " , path , err )
72+ defer func () {
73+ if err := util .DeleteTempDir (tempDir ); err != nil {
74+ logger .Errorf ("failed to delete temporary directory %s: %v" , tempDir , err )
8775 }
88- }(tmpDir )
76+ }()
8977
90- // Check if branch exists (local or remote)
91- branchExists := false
92- references , err := repo .References ()
78+ repo , err := deploymentrepo .CloneRepo (deploymentRepository , tempDir , gitConfig )
9379 if err != nil {
94- return fmt .Errorf ("failed to list references: %w" , err )
95- }
96- localRef := plumbing .NewBranchReferenceName (deploymentRepositoryBranch )
97- remoteRef := plumbing .NewRemoteReferenceName ("origin" , deploymentRepositoryBranch )
98- err = references .ForEach (func (ref * plumbing.Reference ) error {
99- log .Printf ("Found reference: %s" , ref .Name ())
100- if ref .Name () == localRef || ref .Name () == remoteRef {
101- branchExists = true
102- log .Printf ("Branch %s exists as %s" , deploymentRepositoryBranch , ref .Name ())
103- }
104- return nil
105- })
106- if err != nil {
107- return err
80+ return fmt .Errorf ("failed to clone deployment repository: %w" , err )
10881 }
10982
110- workTree , err := repo . Worktree ( )
83+ err = deploymentrepo . CheckoutAndCreateBranchIfNotExists ( repo , deploymentRepositoryBranch , gitConfig )
11184 if err != nil {
112- return fmt .Errorf ("failed to get worktree: %w" , err )
113- }
114-
115- if ! branchExists {
116- // Create and checkout new branch
117- log .Printf ("Branch %s does not exist. Creating...\n " , deploymentRepositoryBranch )
118- err = workTree .Checkout (& git.CheckoutOptions {
119- Branch : localRef ,
120- Create : true ,
121- })
122- if err != nil {
123- return fmt .Errorf ("failed to create branch: %w" , err )
124- }
125-
126- pushOptions := & git.PushOptions {
127- RefSpecs : []config.RefSpec {
128- config .RefSpec (localRef + ":" + localRef ),
129- },
130- Progress : LogWriter {},
131- }
132-
133- if err := gitConfig .ConfigurePushOptions (pushOptions ); err != nil {
134- return fmt .Errorf ("failed to configure push options: %w" , err )
135- }
136-
137- // Push new branch to remote
138- err = repo .Push (pushOptions )
139- if err != nil && ! errors .Is (err , git .NoErrAlreadyUpToDate ) {
140- return fmt .Errorf ("failed to push new branch: %w" , err )
141- }
142- } else {
143- // Checkout existing branch
144- err = workTree .Checkout (& git.CheckoutOptions {
145- Branch : remoteRef ,
146- })
147- if err != nil {
148- return fmt .Errorf ("failed to checkout branch: %w" , err )
149- }
85+ return fmt .Errorf ("failed to checkout or create branch %s: %w" , deploymentRepositoryBranch , err )
15086 }
15187
152- // open the template directory
153- templateDir , err := os .Open (templateDirectory )
88+ err = deploymentrepo .TemplateDir (templateDirectory , repo )
15489 if err != nil {
155- return fmt .Errorf ("failed to open template directory: %w" , err )
90+ return fmt .Errorf ("failed to apply templates from directory %s : %w" , templateDirectory , err )
15691 }
157- defer func () {
158- if err := templateDir .Close (); err != nil {
159- fmt .Fprintf (os .Stderr , "failed to close template directory: %v\n " , err )
160- }
161- }()
162-
163- te := template .NewTemplateExecution ()
164- templateInput := make (map [string ]interface {})
165-
166- // Recursively walk through all files in the template directory
167- err = filepath .WalkDir (templateDirectory , func (path string , d os.DirEntry , err error ) error {
168- if err != nil {
169- return err
170- }
171- if ! d .IsDir () {
172- // Process the file (path)
173- log .Printf ("Found file: %s\n " , path )
174- template , err := os .ReadFile (path )
175- if err != nil {
176- return fmt .Errorf ("failed to read template file %s: %w" , path , err )
177- }
178-
179- templateResult , err := te .Execute (path , string (template ), templateInput )
180- if err != nil {
181- return fmt .Errorf ("failed to execute template %s: %w" , path , err )
182- }
18392
184- pathInRepo , err := filepath .Rel (templateDirectory , path )
185- fileInWt , err := workTree .Filesystem .OpenFile (pathInRepo , os .O_WRONLY | os .O_CREATE , 0644 )
186- if err != nil {
187- return fmt .Errorf ("failed to open file in worktree %s: %w" , path , err )
188- }
189- defer fileInWt .Close ()
190- _ , err = fileInWt .Write (templateResult )
191- if err != nil {
192- return fmt .Errorf ("failed to write to file in worktree %s: %w" , path , err )
193- }
194- // Add the file to the git index
195- if _ , err := workTree .Add (pathInRepo ); err != nil {
196- return fmt .Errorf ("failed to add file to git index: %w" , err )
197- }
198- }
199- return nil
200- })
93+ err = deploymentrepo .
CommitChanges (
repo ,
"apply templates" ,
"openmcp" ,
"[email protected] " )
20194 if err != nil {
202- return fmt .Errorf ("failed to walk template directory : %w" , err )
95+ return fmt .Errorf ("failed to commit changes : %w" , err )
20396 }
20497
205- // Commit the changes
206- commitMsg := "Update deployment repo with template files"
207- _ , err = workTree .Commit (commitMsg , & git.CommitOptions {
208- Author : & object.Signature {
209- Name : "openmcp-bootstrapper" ,
210- 211- When : time .Now (),
212- },
213- })
98+ err = deploymentrepo .PushRepo (repo , gitConfig )
21499 if err != nil {
215- if ! errors .Is (err , git .ErrEmptyCommit ) {
216- return fmt .Errorf ("failed to commit changes: %w" , err )
217- }
218- }
219-
220- // Push the changes
221- pushOptions := & git.PushOptions {}
222- if err := gitConfig .ConfigurePushOptions (pushOptions ); err != nil {
223- return fmt .Errorf ("failed to configure push options: %w" , err )
224- }
225- pushOptions .Progress = LogWriter {}
226- err = repo .Push (pushOptions )
227- if err != nil {
228- if ! errors .Is (err , git .NoErrAlreadyUpToDate ) {
229- return fmt .Errorf ("failed to push changes: %w" , err )
230- }
100+ return fmt .Errorf ("failed to push changes to deployment repository: %w" , err )
231101 }
232102
233103 return nil
@@ -237,6 +107,8 @@ to quickly create a Cobra application.`,
237107func init () {
238108 RootCmd .AddCommand (manageDeploymentRepoCmd )
239109
110+ manageDeploymentRepoCmd .Flags ().SortFlags = false
111+
240112 manageDeploymentRepoCmd .Flags ().StringArray ("cluster-providers" , nil , "List of cluster providers to manage" )
241113 manageDeploymentRepoCmd .Flags ().StringArray ("serviceProviders" , nil , "List of service providers to manage" )
242114 manageDeploymentRepoCmd .Flags ().StringArray ("platformServices" , nil , "List of platform services to manage" )
@@ -248,21 +120,3 @@ func init() {
248120 panic (err )
249121 }
250122}
251-
252- func CloneRepo (repoURL , path string , config * gitconfig.Config ) (* git.Repository , error ) {
253- cloneOptions := & git.CloneOptions {
254- URL : repoURL ,
255- SingleBranch : false ,
256- }
257-
258- if err := config .ConfigureCloneOptions (cloneOptions ); err != nil {
259- return nil , err
260- }
261-
262- repo , err := git .PlainClone (path , false , cloneOptions )
263- if err != nil {
264- return nil , fmt .Errorf ("failed to clone repository: %w" , err )
265- }
266-
267- return repo , nil
268- }
0 commit comments