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