github.com/GoogleContainerTools/skaffold@v1.39.18/pkg/skaffold/git/gitutil_test.go (about) 1 /* 2 Copyright 2021 The Skaffold Authors 3 4 Licensed under the Apache License, Version 2.0 (the "License"); 5 you may not use this file except in compliance with the License. 6 You may obtain a copy of the License at 7 8 http://www.apache.org/licenses/LICENSE-2.0 9 10 Unless required by applicable law or agreed to in writing, software 11 distributed under the License is distributed on an "AS IS" BASIS, 12 WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 See the License for the specific language governing permissions and 14 limitations under the License. 15 */ 16 17 package git 18 19 import ( 20 "context" 21 "errors" 22 "path/filepath" 23 "testing" 24 25 "github.com/GoogleContainerTools/skaffold/pkg/skaffold/config" 26 "github.com/GoogleContainerTools/skaffold/pkg/skaffold/schema/latest" 27 "github.com/GoogleContainerTools/skaffold/pkg/skaffold/util" 28 "github.com/GoogleContainerTools/skaffold/testutil" 29 ) 30 31 func TestDefaultRef(t *testing.T) { 32 tests := []struct { 33 description string 34 masterExists bool 35 mainExists bool 36 expected string 37 err error 38 }{ 39 { 40 description: "master branch exists", 41 masterExists: true, 42 mainExists: true, 43 expected: "master", 44 }, 45 { 46 description: "master branch does not exist; main branch exists", 47 mainExists: true, 48 expected: "main", 49 }, 50 { 51 description: "master and main don't exist", 52 err: errors.New("failed to get default branch for repo http://github.com/foo.git"), 53 }, 54 } 55 for _, test := range tests { 56 testutil.Run(t, test.description, func(t *testutil.T) { 57 var f *testutil.FakeCmd 58 if test.masterExists { 59 f = testutil.CmdRunOut("git ls-remote --heads https://github.com/foo.git master", "8be3f718c015a5fe190bebf356079a25afe0ca57 refs/heads/master") 60 } else { 61 f = testutil.CmdRunOut("git ls-remote --heads https://github.com/foo.git master", "") 62 } 63 if test.mainExists { 64 f = f.AndRunOut("git ls-remote --heads https://github.com/foo.git main", "8be3f718c015a5fe190bebf356079a25afe0ca58 refs/heads/main") 65 } else { 66 f = f.AndRunOut("git ls-remote --heads https://github.com/foo.git main", "") 67 } 68 t.Override(&findGit, func() (string, error) { return "git", nil }) 69 t.Override(&util.DefaultExecCommand, f) 70 ref, err := defaultRef(context.Background(), "https://github.com/foo.git") 71 t.CheckErrorAndDeepEqual(test.err != nil, err, test.expected, ref) 72 }) 73 } 74 } 75 76 func TestSyncRepo(t *testing.T) { 77 tests := []struct { 78 description string 79 g latest.GitInfo 80 cmds []cmdResponse 81 syncFlag string 82 existing bool 83 shouldErr bool 84 expected string 85 }{ 86 { 87 description: "first time repo clone succeeds", 88 g: latest.GitInfo{Repo: "http://github.com/foo.git", Path: "bar/skaffold.yaml", Ref: "master"}, 89 cmds: []cmdResponse{ 90 {cmd: "git clone http://github.com/foo.git ./iSEL5rQfK5EJ2yLhnW8tUgcVOvDC8Wjl --branch master --depth 1"}, 91 }, 92 syncFlag: "always", 93 expected: "iSEL5rQfK5EJ2yLhnW8tUgcVOvDC8Wjl", 94 }, 95 { 96 description: "first time repo clone fails", 97 g: latest.GitInfo{Repo: "http://github.com/foo.git", Path: "bar/skaffold.yaml", Ref: "master"}, 98 cmds: []cmdResponse{ 99 {cmd: "git clone http://github.com/foo.git ./iSEL5rQfK5EJ2yLhnW8tUgcVOvDC8Wjl --branch master --depth 1", err: errors.New("error")}, 100 }, 101 syncFlag: "always", 102 shouldErr: true, 103 }, 104 { 105 description: "first time repo clone with sync off via flag fails", 106 g: latest.GitInfo{Repo: "http://github.com/foo.git", Path: "bar/skaffold.yaml", Ref: "master"}, 107 syncFlag: "never", 108 shouldErr: true, 109 }, 110 { 111 description: "existing repo update succeeds", 112 g: latest.GitInfo{Repo: "http://github.com/foo.git", Path: "bar/skaffold.yaml", Ref: "master"}, 113 existing: true, 114 cmds: []cmdResponse{ 115 {cmd: "git remote -v", out: "origin git@github.com/foo.git"}, 116 {cmd: "git fetch origin master"}, 117 {cmd: "git reset --hard origin/master"}, 118 }, 119 syncFlag: "always", 120 expected: "iSEL5rQfK5EJ2yLhnW8tUgcVOvDC8Wjl", 121 }, 122 { 123 description: "existing repo update fails on remote check", 124 g: latest.GitInfo{Repo: "http://github.com/foo.git", Path: "bar/skaffold.yaml", Ref: "master"}, 125 existing: true, 126 cmds: []cmdResponse{ 127 {cmd: "git remote -v", err: errors.New("error")}, 128 }, 129 syncFlag: "always", 130 shouldErr: true, 131 }, 132 { 133 description: "existing repo with no remotes fails", 134 g: latest.GitInfo{Repo: "http://github.com/foo.git", Path: "bar/skaffold.yaml", Ref: "master"}, 135 existing: true, 136 cmds: []cmdResponse{ 137 {cmd: "git remote -v"}, 138 }, 139 syncFlag: "always", 140 shouldErr: true, 141 }, 142 { 143 description: "existing dirty repo with sync off succeeds", 144 g: latest.GitInfo{Repo: "http://github.com/foo.git", Path: "bar/skaffold.yaml", Ref: "master", Sync: util.BoolPtr(false)}, 145 existing: true, 146 cmds: []cmdResponse{ 147 {cmd: "git remote -v", out: "origin git@github.com/foo.git"}, 148 }, 149 syncFlag: "always", 150 expected: "iSEL5rQfK5EJ2yLhnW8tUgcVOvDC8Wjl", 151 }, 152 { 153 description: "existing dirty repo with sync off via flag succeeds", 154 g: latest.GitInfo{Repo: "http://github.com/foo.git", Path: "bar/skaffold.yaml", Ref: "master"}, 155 existing: true, 156 cmds: []cmdResponse{ 157 {cmd: "git remote -v", out: "origin git@github.com/foo.git"}, 158 }, 159 syncFlag: "missing", 160 expected: "iSEL5rQfK5EJ2yLhnW8tUgcVOvDC8Wjl", 161 }, 162 { 163 description: "existing repo with uncommitted changes and sync on resets", 164 g: latest.GitInfo{Repo: "http://github.com/foo.git", Path: "bar/skaffold.yaml", Ref: "master", Sync: util.BoolPtr(true)}, 165 existing: true, 166 cmds: []cmdResponse{ 167 {cmd: "git remote -v", out: "origin git@github.com/foo.git"}, 168 {cmd: "git fetch origin master"}, 169 {cmd: "git reset --hard origin/master"}, 170 }, 171 syncFlag: "always", 172 expected: "iSEL5rQfK5EJ2yLhnW8tUgcVOvDC8Wjl", 173 }, 174 { 175 description: "existing repo with unpushed commits and sync on resets", 176 g: latest.GitInfo{Repo: "http://github.com/foo.git", Path: "bar/skaffold.yaml", Ref: "master", Sync: util.BoolPtr(true)}, 177 existing: true, 178 cmds: []cmdResponse{ 179 {cmd: "git remote -v", out: "origin git@github.com/foo.git"}, 180 {cmd: "git fetch origin master"}, 181 {cmd: "git reset --hard origin/master"}, 182 }, 183 syncFlag: "always", 184 expected: "iSEL5rQfK5EJ2yLhnW8tUgcVOvDC8Wjl", 185 }, 186 { 187 description: "existing repo update fails on fetch", 188 g: latest.GitInfo{Repo: "http://github.com/foo.git", Path: "bar/skaffold.yaml", Ref: "master"}, 189 existing: true, 190 cmds: []cmdResponse{ 191 {cmd: "git remote -v", out: "origin git@github.com/foo.git"}, 192 {cmd: "git fetch origin master", err: errors.New("error")}, 193 }, 194 syncFlag: "always", 195 shouldErr: true, 196 }, 197 { 198 description: "existing repo update fails on reset", 199 g: latest.GitInfo{Repo: "http://github.com/foo.git", Path: "bar/skaffold.yaml", Ref: "master"}, 200 existing: true, 201 cmds: []cmdResponse{ 202 {cmd: "git remote -v", out: "origin git@github.com/foo.git"}, 203 {cmd: "git fetch origin master"}, 204 {cmd: "git reset --hard origin/master", err: errors.New("error")}, 205 }, 206 syncFlag: "always", 207 shouldErr: true, 208 }, 209 } 210 211 for _, test := range tests { 212 testutil.Run(t, test.description, func(t *testutil.T) { 213 td := t.NewTempDir() 214 if test.existing { 215 td.Touch("iSEL5rQfK5EJ2yLhnW8tUgcVOvDC8Wjl/.git/") 216 } 217 syncRemote := &config.SyncRemoteCacheOption{} 218 _ = syncRemote.Set(test.syncFlag) 219 opts := config.SkaffoldOptions{RepoCacheDir: td.Root(), SyncRemoteCache: *syncRemote} 220 var f *testutil.FakeCmd 221 for _, v := range test.cmds { 222 if f == nil { 223 f = testutil.CmdRunOutErr(v.cmd, v.out, v.err) 224 } else { 225 f = f.AndRunOutErr(v.cmd, v.out, v.err) 226 } 227 } 228 t.Override(&findGit, func() (string, error) { return "git", nil }) 229 t.Override(&util.DefaultExecCommand, f) 230 path, err := syncRepo(context.Background(), test.g, opts) 231 var expected string 232 if !test.shouldErr { 233 expected = filepath.Join(td.Root(), test.expected) 234 } 235 t.CheckErrorAndDeepEqual(test.shouldErr, err, expected, path) 236 }) 237 } 238 } 239 240 type cmdResponse struct { 241 cmd string 242 out string 243 err error 244 }