github.com/nektos/act@v0.2.63/pkg/common/git/git_test.go (about) 1 package git 2 3 import ( 4 "context" 5 "fmt" 6 "os" 7 "os/exec" 8 "path/filepath" 9 "syscall" 10 "testing" 11 12 log "github.com/sirupsen/logrus" 13 "github.com/stretchr/testify/assert" 14 "github.com/stretchr/testify/require" 15 16 "github.com/nektos/act/pkg/common" 17 ) 18 19 func TestFindGitSlug(t *testing.T) { 20 assert := assert.New(t) 21 22 var slugTests = []struct { 23 url string // input 24 provider string // expected result 25 slug string // expected result 26 }{ 27 {"https://git-codecommit.us-east-1.amazonaws.com/v1/repos/my-repo-name", "CodeCommit", "my-repo-name"}, 28 {"ssh://git-codecommit.us-west-2.amazonaws.com/v1/repos/my-repo", "CodeCommit", "my-repo"}, 29 {"git@github.com:nektos/act.git", "GitHub", "nektos/act"}, 30 {"git@github.com:nektos/act", "GitHub", "nektos/act"}, 31 {"https://github.com/nektos/act.git", "GitHub", "nektos/act"}, 32 {"http://github.com/nektos/act.git", "GitHub", "nektos/act"}, 33 {"https://github.com/nektos/act", "GitHub", "nektos/act"}, 34 {"http://github.com/nektos/act", "GitHub", "nektos/act"}, 35 {"git+ssh://git@github.com/owner/repo.git", "GitHub", "owner/repo"}, 36 {"http://myotherrepo.com/act.git", "", "http://myotherrepo.com/act.git"}, 37 } 38 39 for _, tt := range slugTests { 40 provider, slug, err := findGitSlug(tt.url, "github.com") 41 42 assert.NoError(err) 43 assert.Equal(tt.provider, provider) 44 assert.Equal(tt.slug, slug) 45 } 46 } 47 48 func testDir(t *testing.T) string { 49 basedir, err := os.MkdirTemp("", "act-test") 50 require.NoError(t, err) 51 t.Cleanup(func() { _ = os.RemoveAll(basedir) }) 52 return basedir 53 } 54 55 func cleanGitHooks(dir string) error { 56 hooksDir := filepath.Join(dir, ".git", "hooks") 57 files, err := os.ReadDir(hooksDir) 58 if err != nil { 59 if os.IsNotExist(err) { 60 return nil 61 } 62 return err 63 } 64 for _, f := range files { 65 if f.IsDir() { 66 continue 67 } 68 relName := filepath.Join(hooksDir, f.Name()) 69 if err := os.Remove(relName); err != nil { 70 return err 71 } 72 } 73 return nil 74 } 75 76 func TestFindGitRemoteURL(t *testing.T) { 77 assert := assert.New(t) 78 79 basedir := testDir(t) 80 gitConfig() 81 err := gitCmd("init", basedir) 82 assert.NoError(err) 83 err = cleanGitHooks(basedir) 84 assert.NoError(err) 85 86 remoteURL := "https://git-codecommit.us-east-1.amazonaws.com/v1/repos/my-repo-name" 87 err = gitCmd("-C", basedir, "remote", "add", "origin", remoteURL) 88 assert.NoError(err) 89 90 u, err := findGitRemoteURL(context.Background(), basedir, "origin") 91 assert.NoError(err) 92 assert.Equal(remoteURL, u) 93 94 remoteURL = "git@github.com/AwesomeOwner/MyAwesomeRepo.git" 95 err = gitCmd("-C", basedir, "remote", "add", "upstream", remoteURL) 96 assert.NoError(err) 97 u, err = findGitRemoteURL(context.Background(), basedir, "upstream") 98 assert.NoError(err) 99 assert.Equal(remoteURL, u) 100 } 101 102 func TestGitFindRef(t *testing.T) { 103 basedir := testDir(t) 104 gitConfig() 105 106 for name, tt := range map[string]struct { 107 Prepare func(t *testing.T, dir string) 108 Assert func(t *testing.T, ref string, err error) 109 }{ 110 "new_repo": { 111 Prepare: func(t *testing.T, dir string) {}, 112 Assert: func(t *testing.T, ref string, err error) { 113 require.Error(t, err) 114 }, 115 }, 116 "new_repo_with_commit": { 117 Prepare: func(t *testing.T, dir string) { 118 require.NoError(t, gitCmd("-C", dir, "commit", "--allow-empty", "-m", "msg")) 119 }, 120 Assert: func(t *testing.T, ref string, err error) { 121 require.NoError(t, err) 122 require.Equal(t, "refs/heads/master", ref) 123 }, 124 }, 125 "current_head_is_tag": { 126 Prepare: func(t *testing.T, dir string) { 127 require.NoError(t, gitCmd("-C", dir, "commit", "--allow-empty", "-m", "commit msg")) 128 require.NoError(t, gitCmd("-C", dir, "tag", "v1.2.3")) 129 require.NoError(t, gitCmd("-C", dir, "checkout", "v1.2.3")) 130 }, 131 Assert: func(t *testing.T, ref string, err error) { 132 require.NoError(t, err) 133 require.Equal(t, "refs/tags/v1.2.3", ref) 134 }, 135 }, 136 "current_head_is_same_as_tag": { 137 Prepare: func(t *testing.T, dir string) { 138 require.NoError(t, gitCmd("-C", dir, "commit", "--allow-empty", "-m", "1.4.2 release")) 139 require.NoError(t, gitCmd("-C", dir, "tag", "v1.4.2")) 140 }, 141 Assert: func(t *testing.T, ref string, err error) { 142 require.NoError(t, err) 143 require.Equal(t, "refs/tags/v1.4.2", ref) 144 }, 145 }, 146 "current_head_is_not_tag": { 147 Prepare: func(t *testing.T, dir string) { 148 require.NoError(t, gitCmd("-C", dir, "commit", "--allow-empty", "-m", "msg")) 149 require.NoError(t, gitCmd("-C", dir, "tag", "v1.4.2")) 150 require.NoError(t, gitCmd("-C", dir, "commit", "--allow-empty", "-m", "msg2")) 151 }, 152 Assert: func(t *testing.T, ref string, err error) { 153 require.NoError(t, err) 154 require.Equal(t, "refs/heads/master", ref) 155 }, 156 }, 157 "current_head_is_another_branch": { 158 Prepare: func(t *testing.T, dir string) { 159 require.NoError(t, gitCmd("-C", dir, "checkout", "-b", "mybranch")) 160 require.NoError(t, gitCmd("-C", dir, "commit", "--allow-empty", "-m", "msg")) 161 }, 162 Assert: func(t *testing.T, ref string, err error) { 163 require.NoError(t, err) 164 require.Equal(t, "refs/heads/mybranch", ref) 165 }, 166 }, 167 } { 168 tt := tt 169 name := name 170 t.Run(name, func(t *testing.T) { 171 dir := filepath.Join(basedir, name) 172 require.NoError(t, os.MkdirAll(dir, 0o755)) 173 require.NoError(t, gitCmd("-C", dir, "init", "--initial-branch=master")) 174 require.NoError(t, cleanGitHooks(dir)) 175 tt.Prepare(t, dir) 176 ref, err := FindGitRef(context.Background(), dir) 177 tt.Assert(t, ref, err) 178 }) 179 } 180 } 181 182 func TestGitCloneExecutor(t *testing.T) { 183 for name, tt := range map[string]struct { 184 Err error 185 URL, Ref string 186 }{ 187 "tag": { 188 Err: nil, 189 URL: "https://github.com/actions/checkout", 190 Ref: "v2", 191 }, 192 "branch": { 193 Err: nil, 194 URL: "https://github.com/anchore/scan-action", 195 Ref: "act-fails", 196 }, 197 "sha": { 198 Err: nil, 199 URL: "https://github.com/actions/checkout", 200 Ref: "5a4ac9002d0be2fb38bd78e4b4dbde5606d7042f", // v2 201 }, 202 "short-sha": { 203 Err: &Error{ErrShortRef, "5a4ac9002d0be2fb38bd78e4b4dbde5606d7042f"}, 204 URL: "https://github.com/actions/checkout", 205 Ref: "5a4ac90", // v2 206 }, 207 } { 208 t.Run(name, func(t *testing.T) { 209 clone := NewGitCloneExecutor(NewGitCloneExecutorInput{ 210 URL: tt.URL, 211 Ref: tt.Ref, 212 Dir: testDir(t), 213 }) 214 215 err := clone(context.Background()) 216 if tt.Err != nil { 217 assert.Error(t, err) 218 assert.Equal(t, tt.Err, err) 219 } else { 220 assert.Empty(t, err) 221 } 222 }) 223 } 224 } 225 226 func gitConfig() { 227 if os.Getenv("GITHUB_ACTIONS") == "true" { 228 var err error 229 if err = gitCmd("config", "--global", "user.email", "test@test.com"); err != nil { 230 log.Error(err) 231 } 232 if err = gitCmd("config", "--global", "user.name", "Unit Test"); err != nil { 233 log.Error(err) 234 } 235 } 236 } 237 238 func gitCmd(args ...string) error { 239 cmd := exec.Command("git", args...) 240 cmd.Stdout = os.Stdout 241 cmd.Stderr = os.Stderr 242 243 err := cmd.Run() 244 if exitError, ok := err.(*exec.ExitError); ok { 245 if waitStatus, ok := exitError.Sys().(syscall.WaitStatus); ok { 246 return fmt.Errorf("Exit error %d", waitStatus.ExitStatus()) 247 } 248 return exitError 249 } 250 return nil 251 } 252 253 func TestCloneIfRequired(t *testing.T) { 254 tempDir := t.TempDir() 255 ctx := context.Background() 256 257 t.Run("clone", func(t *testing.T) { 258 repo, err := CloneIfRequired(ctx, "refs/heads/main", NewGitCloneExecutorInput{ 259 URL: "https://github.com/actions/checkout", 260 Dir: tempDir, 261 }, common.Logger(ctx)) 262 assert.NoError(t, err) 263 assert.NotNil(t, repo) 264 }) 265 266 t.Run("clone different remote", func(t *testing.T) { 267 repo, err := CloneIfRequired(ctx, "refs/heads/main", NewGitCloneExecutorInput{ 268 URL: "https://github.com/actions/setup-go", 269 Dir: tempDir, 270 }, common.Logger(ctx)) 271 require.NoError(t, err) 272 require.NotNil(t, repo) 273 274 remote, err := repo.Remote("origin") 275 require.NoError(t, err) 276 require.Len(t, remote.Config().URLs, 1) 277 assert.Equal(t, "https://github.com/actions/setup-go", remote.Config().URLs[0]) 278 }) 279 }