github.com/argoproj/argo-cd/v2@v2.10.9/applicationset/services/scm_provider/github_test.go (about) 1 package scm_provider 2 3 import ( 4 "context" 5 "io" 6 "net/http" 7 "net/http/httptest" 8 "testing" 9 10 "github.com/stretchr/testify/assert" 11 12 "github.com/argoproj/argo-cd/v2/pkg/apis/application/v1alpha1" 13 ) 14 15 func githubMockHandler(t *testing.T) func(http.ResponseWriter, *http.Request) { 16 return func(w http.ResponseWriter, r *http.Request) { 17 w.Header().Set("Content-Type", "application/json") 18 switch r.RequestURI { 19 case "/api/v3/orgs/argoproj/repos?per_page=100": 20 _, err := io.WriteString(w, `[ 21 { 22 "id": 1296269, 23 "node_id": "MDEwOlJlcG9zaXRvcnkxMjk2MjY5", 24 "name": "argo-cd", 25 "full_name": "argoproj/argo-cd", 26 "owner": { 27 "login": "argoproj", 28 "id": 1, 29 "node_id": "MDQ6VXNlcjE=", 30 "avatar_url": "https://github.com/images/error/argoproj_happy.gif", 31 "gravatar_id": "", 32 "url": "https://api.github.com/users/argoproj", 33 "html_url": "https://github.com/argoproj", 34 "followers_url": "https://api.github.com/users/argoproj/followers", 35 "following_url": "https://api.github.com/users/argoproj/following{/other_user}", 36 "gists_url": "https://api.github.com/users/argoproj/gists{/gist_id}", 37 "starred_url": "https://api.github.com/users/argoproj/starred{/owner}{/repo}", 38 "subscriptions_url": "https://api.github.com/users/argoproj/subscriptions", 39 "organizations_url": "https://api.github.com/users/argoproj/orgs", 40 "repos_url": "https://api.github.com/users/argoproj/repos", 41 "events_url": "https://api.github.com/users/argoproj/events{/privacy}", 42 "received_events_url": "https://api.github.com/users/argoproj/received_events", 43 "type": "User", 44 "site_admin": false 45 }, 46 "private": false, 47 "html_url": "https://github.com/argoproj/argo-cd", 48 "description": "This your first repo!", 49 "fork": false, 50 "url": "https://api.github.com/repos/argoproj/argo-cd", 51 "archive_url": "https://api.github.com/repos/argoproj/argo-cd/{archive_format}{/ref}", 52 "assignees_url": "https://api.github.com/repos/argoproj/argo-cd/assignees{/user}", 53 "blobs_url": "https://api.github.com/repos/argoproj/argo-cd/git/blobs{/sha}", 54 "branches_url": "https://api.github.com/repos/argoproj/argo-cd/branches{/branch}", 55 "collaborators_url": "https://api.github.com/repos/argoproj/argo-cd/collaborators{/collaborator}", 56 "comments_url": "https://api.github.com/repos/argoproj/argo-cd/comments{/number}", 57 "commits_url": "https://api.github.com/repos/argoproj/argo-cd/commits{/sha}", 58 "compare_url": "https://api.github.com/repos/argoproj/argo-cd/compare/{base}...{head}", 59 "contents_url": "https://api.github.com/repos/argoproj/argo-cd/contents/{path}", 60 "contributors_url": "https://api.github.com/repos/argoproj/argo-cd/contributors", 61 "deployments_url": "https://api.github.com/repos/argoproj/argo-cd/deployments", 62 "downloads_url": "https://api.github.com/repos/argoproj/argo-cd/downloads", 63 "events_url": "https://api.github.com/repos/argoproj/argo-cd/events", 64 "forks_url": "https://api.github.com/repos/argoproj/argo-cd/forks", 65 "git_commits_url": "https://api.github.com/repos/argoproj/argo-cd/git/commits{/sha}", 66 "git_refs_url": "https://api.github.com/repos/argoproj/argo-cd/git/refs{/sha}", 67 "git_tags_url": "https://api.github.com/repos/argoproj/argo-cd/git/tags{/sha}", 68 "git_url": "git:github.com/argoproj/argo-cd.git", 69 "issue_comment_url": "https://api.github.com/repos/argoproj/argo-cd/issues/comments{/number}", 70 "issue_events_url": "https://api.github.com/repos/argoproj/argo-cd/issues/events{/number}", 71 "issues_url": "https://api.github.com/repos/argoproj/argo-cd/issues{/number}", 72 "keys_url": "https://api.github.com/repos/argoproj/argo-cd/keys{/key_id}", 73 "labels_url": "https://api.github.com/repos/argoproj/argo-cd/labels{/name}", 74 "languages_url": "https://api.github.com/repos/argoproj/argo-cd/languages", 75 "merges_url": "https://api.github.com/repos/argoproj/argo-cd/merges", 76 "milestones_url": "https://api.github.com/repos/argoproj/argo-cd/milestones{/number}", 77 "notifications_url": "https://api.github.com/repos/argoproj/argo-cd/notifications{?since,all,participating}", 78 "pulls_url": "https://api.github.com/repos/argoproj/argo-cd/pulls{/number}", 79 "releases_url": "https://api.github.com/repos/argoproj/argo-cd/releases{/id}", 80 "ssh_url": "git@github.com:argoproj/argo-cd.git", 81 "stargazers_url": "https://api.github.com/repos/argoproj/argo-cd/stargazers", 82 "statuses_url": "https://api.github.com/repos/argoproj/argo-cd/statuses/{sha}", 83 "subscribers_url": "https://api.github.com/repos/argoproj/argo-cd/subscribers", 84 "subscription_url": "https://api.github.com/repos/argoproj/argo-cd/subscription", 85 "tags_url": "https://api.github.com/repos/argoproj/argo-cd/tags", 86 "teams_url": "https://api.github.com/repos/argoproj/argo-cd/teams", 87 "trees_url": "https://api.github.com/repos/argoproj/argo-cd/git/trees{/sha}", 88 "clone_url": "https://github.com/argoproj/argo-cd.git", 89 "mirror_url": "git:git.example.com/argoproj/argo-cd", 90 "hooks_url": "https://api.github.com/repos/argoproj/argo-cd/hooks", 91 "svn_url": "https://svn.github.com/argoproj/argo-cd", 92 "homepage": "https://github.com", 93 "language": null, 94 "forks_count": 9, 95 "stargazers_count": 80, 96 "watchers_count": 80, 97 "size": 108, 98 "default_branch": "master", 99 "open_issues_count": 0, 100 "is_template": false, 101 "topics": [ 102 "argoproj", 103 "atom", 104 "electron", 105 "api" 106 ], 107 "has_issues": true, 108 "has_projects": true, 109 "has_wiki": true, 110 "has_pages": false, 111 "has_downloads": true, 112 "archived": false, 113 "disabled": false, 114 "visibility": "public", 115 "pushed_at": "2011-01-26T19:06:43Z", 116 "created_at": "2011-01-26T19:01:12Z", 117 "updated_at": "2011-01-26T19:14:43Z", 118 "permissions": { 119 "admin": false, 120 "push": false, 121 "pull": true 122 }, 123 "template_repository": null 124 } 125 ]`) 126 if err != nil { 127 t.Fail() 128 } 129 case "/api/v3/repos/argoproj/argo-cd/branches?per_page=100": 130 _, err := io.WriteString(w, `[ 131 { 132 "name": "master", 133 "commit": { 134 "sha": "c5b97d5ae6c19d5c5df71a34c7fbeeda2479ccbc", 135 "url": "https://api.github.com/repos/argoproj/argo-cd/commits/c5b97d5ae6c19d5c5df71a34c7fbeeda2479ccbc" 136 }, 137 "protected": true, 138 "protection": { 139 "required_status_checks": { 140 "enforcement_level": "non_admins", 141 "contexts": [ 142 "ci-test", 143 "linter" 144 ] 145 } 146 }, 147 "protection_url": "https://api.github.com/repos/argoproj/hello-world/branches/master/protection" 148 } 149 ] 150 `) 151 if err != nil { 152 t.Fail() 153 } 154 case "/api/v3/repos/argoproj/argo-cd/contents/pkg?ref=master": 155 _, err := io.WriteString(w, `{ 156 "type": "file", 157 "encoding": "base64", 158 "size": 5362, 159 "name": "pkg/", 160 "path": "pkg/", 161 "content": "encoded content ...", 162 "sha": "3d21ec53a331a6f037a91c368710b99387d012c1", 163 "url": "https://api.github.com/repos/octokit/octokit.rb/contents/README.md", 164 "git_url": "https://api.github.com/repos/octokit/octokit.rb/git/blobs/3d21ec53a331a6f037a91c368710b99387d012c1", 165 "html_url": "https://github.com/octokit/octokit.rb/blob/master/README.md", 166 "download_url": "https://raw.githubusercontent.com/octokit/octokit.rb/master/README.md", 167 "_links": { 168 "git": "https://api.github.com/repos/octokit/octokit.rb/git/blobs/3d21ec53a331a6f037a91c368710b99387d012c1", 169 "self": "https://api.github.com/repos/octokit/octokit.rb/contents/README.md", 170 "html": "https://github.com/octokit/octokit.rb/blob/master/README.md" 171 } 172 }`) 173 if err != nil { 174 t.Fail() 175 } 176 case "/api/v3/repos/argoproj/argo-cd/branches/master": 177 _, err := io.WriteString(w, `{ 178 "name": "master", 179 "commit": { 180 "sha": "c5b97d5ae6c19d5c5df71a34c7fbeeda2479ccbc", 181 "url": "https://api.github.com/repos/octocat/Hello-World/commits/c5b97d5ae6c19d5c5df71a34c7fbeeda2479ccbc" 182 }, 183 "protected": true, 184 "protection": { 185 "required_status_checks": { 186 "enforcement_level": "non_admins", 187 "contexts": [ 188 "ci-test", 189 "linter" 190 ] 191 } 192 }, 193 "protection_url": "https://api.github.com/repos/octocat/hello-world/branches/master/protection" 194 }`) 195 if err != nil { 196 t.Fail() 197 } 198 default: 199 w.WriteHeader(http.StatusNotFound) 200 } 201 } 202 } 203 204 func TestGithubListRepos(t *testing.T) { 205 cases := []struct { 206 name, proto, url string 207 hasError, allBranches bool 208 branches []string 209 filters []v1alpha1.SCMProviderGeneratorFilter 210 }{ 211 { 212 name: "blank protocol", 213 url: "git@github.com:argoproj/argo-cd.git", 214 branches: []string{"master"}, 215 }, 216 { 217 name: "ssh protocol", 218 proto: "ssh", 219 url: "git@github.com:argoproj/argo-cd.git", 220 }, 221 { 222 name: "https protocol", 223 proto: "https", 224 url: "https://github.com/argoproj/argo-cd.git", 225 }, 226 { 227 name: "other protocol", 228 proto: "other", 229 hasError: true, 230 }, 231 { 232 name: "all branches", 233 allBranches: true, 234 url: "git@github.com:argoproj/argo-cd.git", 235 branches: []string{"master"}, 236 }, 237 } 238 ts := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { 239 githubMockHandler(t)(w, r) 240 })) 241 defer ts.Close() 242 for _, c := range cases { 243 t.Run(c.name, func(t *testing.T) { 244 provider, _ := NewGithubProvider(context.Background(), "argoproj", "", ts.URL, c.allBranches) 245 rawRepos, err := ListRepos(context.Background(), provider, c.filters, c.proto) 246 if c.hasError { 247 assert.Error(t, err) 248 } else { 249 assert.NoError(t, err) 250 // Just check that this one project shows up. Not a great test but better thing nothing? 251 repos := []*Repository{} 252 branches := []string{} 253 for _, r := range rawRepos { 254 if r.Repository == "argo-cd" { 255 repos = append(repos, r) 256 branches = append(branches, r.Branch) 257 } 258 } 259 assert.NotEmpty(t, repos) 260 assert.Equal(t, c.url, repos[0].URL) 261 for _, b := range c.branches { 262 assert.Contains(t, branches, b) 263 } 264 } 265 }) 266 } 267 } 268 269 func TestGithubHasPath(t *testing.T) { 270 ts := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { 271 githubMockHandler(t)(w, r) 272 })) 273 defer ts.Close() 274 host, _ := NewGithubProvider(context.Background(), "argoproj", "", ts.URL, false) 275 repo := &Repository{ 276 Organization: "argoproj", 277 Repository: "argo-cd", 278 Branch: "master", 279 } 280 ok, err := host.RepoHasPath(context.Background(), repo, "pkg/") 281 assert.Nil(t, err) 282 assert.True(t, ok) 283 284 ok, err = host.RepoHasPath(context.Background(), repo, "notathing/") 285 assert.Nil(t, err) 286 assert.False(t, ok) 287 } 288 289 func TestGithubGetBranches(t *testing.T) { 290 ts := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { 291 githubMockHandler(t)(w, r) 292 })) 293 defer ts.Close() 294 host, _ := NewGithubProvider(context.Background(), "argoproj", "", ts.URL, false) 295 repo := &Repository{ 296 Organization: "argoproj", 297 Repository: "argo-cd", 298 Branch: "master", 299 } 300 repos, err := host.GetBranches(context.Background(), repo) 301 if err != nil { 302 assert.NoError(t, err) 303 } else { 304 assert.Equal(t, repos[0].Branch, "master") 305 } 306 //Branch Doesn't exists instead of error will return no error 307 repo2 := &Repository{ 308 Organization: "argoproj", 309 Repository: "applicationset", 310 Branch: "main", 311 } 312 _, err = host.GetBranches(context.Background(), repo2) 313 assert.NoError(t, err) 314 315 // Get all branches 316 host.allBranches = true 317 repos, err = host.GetBranches(context.Background(), repo) 318 if err != nil { 319 assert.NoError(t, err) 320 } else { 321 // considering master branch to exist. 322 assert.Equal(t, len(repos), 1) 323 } 324 }