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  }