github.com/nektos/act@v0.2.83/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(_ *testing.T, _ string) {}, 112 Assert: func(t *testing.T, _ 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 t.Run(name, func(t *testing.T) { 169 dir := filepath.Join(basedir, name) 170 require.NoError(t, os.MkdirAll(dir, 0o755)) 171 require.NoError(t, gitCmd("-C", dir, "init", "--initial-branch=master")) 172 require.NoError(t, cleanGitHooks(dir)) 173 tt.Prepare(t, dir) 174 ref, err := FindGitRef(context.Background(), dir) 175 tt.Assert(t, ref, err) 176 }) 177 } 178 } 179 180 func TestGitCloneExecutor(t *testing.T) { 181 for name, tt := range map[string]struct { 182 Err error 183 URL, Ref string 184 }{ 185 "tag": { 186 Err: nil, 187 URL: "https://github.com/actions/checkout", 188 Ref: "v2", 189 }, 190 "branch": { 191 Err: nil, 192 URL: "https://github.com/anchore/scan-action", 193 Ref: "act-fails", 194 }, 195 "sha": { 196 Err: nil, 197 URL: "https://github.com/actions/checkout", 198 Ref: "5a4ac9002d0be2fb38bd78e4b4dbde5606d7042f", // v2 199 }, 200 "short-sha": { 201 Err: &Error{ErrShortRef, "5a4ac9002d0be2fb38bd78e4b4dbde5606d7042f"}, 202 URL: "https://github.com/actions/checkout", 203 Ref: "5a4ac90", // v2 204 }, 205 } { 206 t.Run(name, func(t *testing.T) { 207 clone := NewGitCloneExecutor(NewGitCloneExecutorInput{ 208 URL: tt.URL, 209 Ref: tt.Ref, 210 Dir: testDir(t), 211 }) 212 213 err := clone(context.Background()) 214 if tt.Err != nil { 215 assert.Error(t, err) 216 assert.Equal(t, tt.Err, err) 217 } else { 218 assert.Empty(t, err) 219 } 220 }) 221 } 222 } 223 224 func gitConfig() { 225 if os.Getenv("GITHUB_ACTIONS") == "true" { 226 var err error 227 if err = gitCmd("config", "--global", "user.email", "test@test.com"); err != nil { 228 log.Error(err) 229 } 230 if err = gitCmd("config", "--global", "user.name", "Unit Test"); err != nil { 231 log.Error(err) 232 } 233 } 234 } 235 236 func gitCmd(args ...string) error { 237 cmd := exec.Command("git", args...) 238 cmd.Stdout = os.Stdout 239 cmd.Stderr = os.Stderr 240 241 err := cmd.Run() 242 if exitError, ok := err.(*exec.ExitError); ok { 243 if waitStatus, ok := exitError.Sys().(syscall.WaitStatus); ok { 244 return fmt.Errorf("Exit error %d", waitStatus.ExitStatus()) 245 } 246 return exitError 247 } 248 return nil 249 } 250 251 func TestCloneIfRequired(t *testing.T) { 252 tempDir := t.TempDir() 253 ctx := context.Background() 254 255 t.Run("clone", func(t *testing.T) { 256 repo, err := CloneIfRequired(ctx, "refs/heads/main", NewGitCloneExecutorInput{ 257 URL: "https://github.com/actions/checkout", 258 Dir: tempDir, 259 }, common.Logger(ctx)) 260 assert.NoError(t, err) 261 assert.NotNil(t, repo) 262 }) 263 264 t.Run("clone different remote", func(t *testing.T) { 265 repo, err := CloneIfRequired(ctx, "refs/heads/main", NewGitCloneExecutorInput{ 266 URL: "https://github.com/actions/setup-go", 267 Dir: tempDir, 268 }, common.Logger(ctx)) 269 require.NoError(t, err) 270 require.NotNil(t, repo) 271 272 remote, err := repo.Remote("origin") 273 require.NoError(t, err) 274 require.Len(t, remote.Config().URLs, 1) 275 assert.Equal(t, "https://github.com/actions/setup-go", remote.Config().URLs[0]) 276 }) 277 }