@@ -18,15 +18,133 @@ package framework
1818
1919import (
2020 "cmp"
21+ "context"
2122 "fmt"
2223 "os"
2324 "strings"
25+ "time"
2426
2527 . "github.com/onsi/gomega"
2628
2729 "github.com/go-git/go-git/v5"
30+ "github.com/go-git/go-git/v5/plumbing/object"
31+ "github.com/go-git/go-git/v5/plumbing/transport/http"
2832)
2933
34+ // GitCloneRepoInput is the input to GitCloneRepo.
35+ type GitCloneRepoInput struct {
36+ // Address is the URL of the repository to clone.
37+ Address string
38+
39+ // CloneLocation is the directory where the repository will be cloned.
40+ CloneLocation string
41+
42+ // Username is the username for authentication (optional).
43+ Username string `env:"GITEA_USER_NAME"`
44+
45+ // Password is the password for authentication (optional).
46+ Password string `env:"GITEA_USER_PWD"`
47+ }
48+
49+ // GitCloneRepo will clone a repo to a given location.
50+ func GitCloneRepo (ctx context.Context , input GitCloneRepoInput ) string {
51+ Expect (Parse (& input )).To (Succeed (), "Failed to parse environment variables" )
52+
53+ Expect (ctx ).NotTo (BeNil (), "ctx is required for GitCloneRepo" )
54+ Expect (input .Address ).ToNot (BeEmpty (), "Invalid argument. input.Address can't be empty when calling GitCloneRepo" )
55+
56+ cloneDir := input .CloneLocation
57+
58+ if input .CloneLocation == "" {
59+ dir , err := os .MkdirTemp ("" , "turtles-clone" )
60+ Expect (err ).ShouldNot (HaveOccurred (), "Failed creating temporary clone directory" )
61+ cloneDir = dir
62+ }
63+
64+ opts := & git.CloneOptions {
65+ URL : input .Address ,
66+ Progress : os .Stdout ,
67+ }
68+ if input .Username != "" {
69+ opts .Auth = & http.BasicAuth {
70+ Username : input .Username ,
71+ Password : input .Password ,
72+ }
73+ }
74+
75+ _ , err := git .PlainClone (cloneDir , false , opts )
76+ Expect (err ).ShouldNot (HaveOccurred (), "Failed cloning repo" )
77+
78+ return cloneDir
79+ }
80+
81+ // GitCommitAndPushInput is the input to GitCommitAndPush.
82+ type GitCommitAndPushInput struct {
83+ // CloneLocation is the directory where the repository is cloned.
84+ CloneLocation string
85+
86+ // Username is the username for authentication (optional).
87+ Username string `env:"GITEA_USER_NAME"`
88+
89+ // Password is the password for authentication (optional).
90+ Password string `env:"GITEA_USER_PWD"`
91+
92+ // CommitMessage is the message for the commit.
93+ CommitMessage string
94+
95+ // GitPushWait is the wait time for the git push operation.
96+ GitPushWait []interface {} `envDefault:"3m,10s"`
97+ }
98+
99+ // GitCommitAndPush will commit the files for a repo and push the changes to the origin.
100+ func GitCommitAndPush (ctx context.Context , input GitCommitAndPushInput ) {
101+ Expect (Parse (& input )).To (Succeed (), "Failed to parse environment variables" )
102+
103+ Expect (ctx ).NotTo (BeNil (), "ctx is required for GitCommitAndPush" )
104+ Expect (input .CloneLocation ).ToNot (BeEmpty (), "Invalid argument. input.CloneLoaction can't be empty when calling GitCommitAndPush" )
105+ Expect (input .CommitMessage ).ToNot (BeEmpty (), "Invalid argument. input.CommitMessage can't be empty when calling GitCommitAndPush" )
106+
107+ repo , err := git .PlainOpen (input .CloneLocation )
108+ Expect (err ).ShouldNot (HaveOccurred (), "Failed opening the repo" )
109+
110+ tree , err := repo .Worktree ()
111+ Expect (err ).ShouldNot (HaveOccurred (), "Failed getting work tree for repo" )
112+
113+ err = tree .AddWithOptions (& git.AddOptions {
114+ All : true ,
115+ })
116+ Expect (err ).ShouldNot (HaveOccurred (), "Failed adding all files" )
117+
118+ commitOptions := & git.CommitOptions {
119+ Author : & object.Signature {
120+ Name : "Rancher Turtles Tests" ,
121+ 122+ When : time .Now (),
123+ },
124+ }
125+
126+ _ , err = tree .Commit (input .CommitMessage , commitOptions )
127+ Expect (err ).ShouldNot (HaveOccurred (), "Failed to commit files" )
128+
129+ pushOptions := & git.PushOptions {}
130+ if input .Username != "" {
131+ pushOptions .Auth = & http.BasicAuth {
132+ Username : input .Username ,
133+ Password : input .Password ,
134+ }
135+ }
136+ err = repo .Push (pushOptions )
137+ Expect (err ).ShouldNot (HaveOccurred (), "Failed pushing changes" )
138+
139+ Eventually (func () error {
140+ err := repo .Push (pushOptions )
141+ if err .Error () == "already up-to-date" {
142+ return nil
143+ }
144+ return err
145+ }, input .GitPushWait ... ).Should (Succeed (), "Failed to connect to workload cluster using CAPI kubeconfig" )
146+ }
147+
30148// defaultToCurrentGitRepo retrieves the repository URL and the current branch
31149func defaultToCurrentGitRepo (input * FleetCreateGitRepoInput ) {
32150 if input .Repo != "" {
0 commit comments