github.com/google/go-github/v49@v49.1.0/github/repos.go (about) 1 // Copyright 2013 The go-github AUTHORS. All rights reserved. 2 // 3 // Use of this source code is governed by a BSD-style 4 // license that can be found in the LICENSE file. 5 6 package github 7 8 import ( 9 "context" 10 "encoding/json" 11 "errors" 12 "fmt" 13 "net/http" 14 "strings" 15 ) 16 17 const githubBranchNotProtected string = "Branch not protected" 18 19 var ErrBranchNotProtected = errors.New("branch is not protected") 20 21 // RepositoriesService handles communication with the repository related 22 // methods of the GitHub API. 23 // 24 // GitHub API docs: https://docs.github.com/en/rest/repos/ 25 type RepositoriesService service 26 27 // Repository represents a GitHub repository. 28 type Repository struct { 29 ID *int64 `json:"id,omitempty"` 30 NodeID *string `json:"node_id,omitempty"` 31 Owner *User `json:"owner,omitempty"` 32 Name *string `json:"name,omitempty"` 33 FullName *string `json:"full_name,omitempty"` 34 Description *string `json:"description,omitempty"` 35 Homepage *string `json:"homepage,omitempty"` 36 CodeOfConduct *CodeOfConduct `json:"code_of_conduct,omitempty"` 37 DefaultBranch *string `json:"default_branch,omitempty"` 38 MasterBranch *string `json:"master_branch,omitempty"` 39 CreatedAt *Timestamp `json:"created_at,omitempty"` 40 PushedAt *Timestamp `json:"pushed_at,omitempty"` 41 UpdatedAt *Timestamp `json:"updated_at,omitempty"` 42 HTMLURL *string `json:"html_url,omitempty"` 43 CloneURL *string `json:"clone_url,omitempty"` 44 GitURL *string `json:"git_url,omitempty"` 45 MirrorURL *string `json:"mirror_url,omitempty"` 46 SSHURL *string `json:"ssh_url,omitempty"` 47 SVNURL *string `json:"svn_url,omitempty"` 48 Language *string `json:"language,omitempty"` 49 Fork *bool `json:"fork,omitempty"` 50 ForksCount *int `json:"forks_count,omitempty"` 51 NetworkCount *int `json:"network_count,omitempty"` 52 OpenIssuesCount *int `json:"open_issues_count,omitempty"` 53 OpenIssues *int `json:"open_issues,omitempty"` // Deprecated: Replaced by OpenIssuesCount. For backward compatibility OpenIssues is still populated. 54 StargazersCount *int `json:"stargazers_count,omitempty"` 55 SubscribersCount *int `json:"subscribers_count,omitempty"` 56 WatchersCount *int `json:"watchers_count,omitempty"` // Deprecated: Replaced by StargazersCount. For backward compatibility WatchersCount is still populated. 57 Watchers *int `json:"watchers,omitempty"` // Deprecated: Replaced by StargazersCount. For backward compatibility Watchers is still populated. 58 Size *int `json:"size,omitempty"` 59 AutoInit *bool `json:"auto_init,omitempty"` 60 Parent *Repository `json:"parent,omitempty"` 61 Source *Repository `json:"source,omitempty"` 62 TemplateRepository *Repository `json:"template_repository,omitempty"` 63 Organization *Organization `json:"organization,omitempty"` 64 Permissions map[string]bool `json:"permissions,omitempty"` 65 AllowRebaseMerge *bool `json:"allow_rebase_merge,omitempty"` 66 AllowUpdateBranch *bool `json:"allow_update_branch,omitempty"` 67 AllowSquashMerge *bool `json:"allow_squash_merge,omitempty"` 68 AllowMergeCommit *bool `json:"allow_merge_commit,omitempty"` 69 AllowAutoMerge *bool `json:"allow_auto_merge,omitempty"` 70 AllowForking *bool `json:"allow_forking,omitempty"` 71 DeleteBranchOnMerge *bool `json:"delete_branch_on_merge,omitempty"` 72 UseSquashPRTitleAsDefault *bool `json:"use_squash_pr_title_as_default,omitempty"` 73 SquashMergeCommitTitle *string `json:"squash_merge_commit_title,omitempty"` // Can be one of: "PR_TITLE", "COMMIT_OR_PR_TITLE" 74 SquashMergeCommitMessage *string `json:"squash_merge_commit_message,omitempty"` // Can be one of: "PR_BODY", "COMMIT_MESSAGES", "BLANK" 75 MergeCommitTitle *string `json:"merge_commit_title,omitempty"` // Can be one of: "PR_TITLE", "MERGE_MESSAGE" 76 MergeCommitMessage *string `json:"merge_commit_message,omitempty"` // Can be one of: "PR_BODY", "PR_TITLE", "BLANK" 77 Topics []string `json:"topics,omitempty"` 78 Archived *bool `json:"archived,omitempty"` 79 Disabled *bool `json:"disabled,omitempty"` 80 81 // Only provided when using RepositoriesService.Get while in preview 82 License *License `json:"license,omitempty"` 83 84 // Additional mutable fields when creating and editing a repository 85 Private *bool `json:"private,omitempty"` 86 HasIssues *bool `json:"has_issues,omitempty"` 87 HasWiki *bool `json:"has_wiki,omitempty"` 88 HasPages *bool `json:"has_pages,omitempty"` 89 HasProjects *bool `json:"has_projects,omitempty"` 90 HasDownloads *bool `json:"has_downloads,omitempty"` 91 HasDiscussions *bool `json:"has_discussions,omitempty"` 92 IsTemplate *bool `json:"is_template,omitempty"` 93 LicenseTemplate *string `json:"license_template,omitempty"` 94 GitignoreTemplate *string `json:"gitignore_template,omitempty"` 95 96 // Options for configuring Advanced Security and Secret Scanning 97 SecurityAndAnalysis *SecurityAndAnalysis `json:"security_and_analysis,omitempty"` 98 99 // Creating an organization repository. Required for non-owners. 100 TeamID *int64 `json:"team_id,omitempty"` 101 102 // API URLs 103 URL *string `json:"url,omitempty"` 104 ArchiveURL *string `json:"archive_url,omitempty"` 105 AssigneesURL *string `json:"assignees_url,omitempty"` 106 BlobsURL *string `json:"blobs_url,omitempty"` 107 BranchesURL *string `json:"branches_url,omitempty"` 108 CollaboratorsURL *string `json:"collaborators_url,omitempty"` 109 CommentsURL *string `json:"comments_url,omitempty"` 110 CommitsURL *string `json:"commits_url,omitempty"` 111 CompareURL *string `json:"compare_url,omitempty"` 112 ContentsURL *string `json:"contents_url,omitempty"` 113 ContributorsURL *string `json:"contributors_url,omitempty"` 114 DeploymentsURL *string `json:"deployments_url,omitempty"` 115 DownloadsURL *string `json:"downloads_url,omitempty"` 116 EventsURL *string `json:"events_url,omitempty"` 117 ForksURL *string `json:"forks_url,omitempty"` 118 GitCommitsURL *string `json:"git_commits_url,omitempty"` 119 GitRefsURL *string `json:"git_refs_url,omitempty"` 120 GitTagsURL *string `json:"git_tags_url,omitempty"` 121 HooksURL *string `json:"hooks_url,omitempty"` 122 IssueCommentURL *string `json:"issue_comment_url,omitempty"` 123 IssueEventsURL *string `json:"issue_events_url,omitempty"` 124 IssuesURL *string `json:"issues_url,omitempty"` 125 KeysURL *string `json:"keys_url,omitempty"` 126 LabelsURL *string `json:"labels_url,omitempty"` 127 LanguagesURL *string `json:"languages_url,omitempty"` 128 MergesURL *string `json:"merges_url,omitempty"` 129 MilestonesURL *string `json:"milestones_url,omitempty"` 130 NotificationsURL *string `json:"notifications_url,omitempty"` 131 PullsURL *string `json:"pulls_url,omitempty"` 132 ReleasesURL *string `json:"releases_url,omitempty"` 133 StargazersURL *string `json:"stargazers_url,omitempty"` 134 StatusesURL *string `json:"statuses_url,omitempty"` 135 SubscribersURL *string `json:"subscribers_url,omitempty"` 136 SubscriptionURL *string `json:"subscription_url,omitempty"` 137 TagsURL *string `json:"tags_url,omitempty"` 138 TreesURL *string `json:"trees_url,omitempty"` 139 TeamsURL *string `json:"teams_url,omitempty"` 140 141 // TextMatches is only populated from search results that request text matches 142 // See: search.go and https://docs.github.com/en/rest/search/#text-match-metadata 143 TextMatches []*TextMatch `json:"text_matches,omitempty"` 144 145 // Visibility is only used for Create and Edit endpoints. The visibility field 146 // overrides the field parameter when both are used. 147 // Can be one of public, private or internal. 148 Visibility *string `json:"visibility,omitempty"` 149 150 // RoleName is only returned by the API 'check team permissions for a repository'. 151 // See: teams.go (IsTeamRepoByID) https://docs.github.com/en/rest/teams/teams#check-team-permissions-for-a-repository 152 RoleName *string `json:"role_name,omitempty"` 153 } 154 155 func (r Repository) String() string { 156 return Stringify(r) 157 } 158 159 // BranchListOptions specifies the optional parameters to the 160 // RepositoriesService.ListBranches method. 161 type BranchListOptions struct { 162 // Setting to true returns only protected branches. 163 // When set to false, only unprotected branches are returned. 164 // Omitting this parameter returns all branches. 165 // Default: nil 166 Protected *bool `url:"protected,omitempty"` 167 168 ListOptions 169 } 170 171 // RepositoryListOptions specifies the optional parameters to the 172 // RepositoriesService.List method. 173 type RepositoryListOptions struct { 174 // Visibility of repositories to list. Can be one of all, public, or private. 175 // Default: all 176 Visibility string `url:"visibility,omitempty"` 177 178 // List repos of given affiliation[s]. 179 // Comma-separated list of values. Can include: 180 // * owner: Repositories that are owned by the authenticated user. 181 // * collaborator: Repositories that the user has been added to as a 182 // collaborator. 183 // * organization_member: Repositories that the user has access to through 184 // being a member of an organization. This includes every repository on 185 // every team that the user is on. 186 // Default: owner,collaborator,organization_member 187 Affiliation string `url:"affiliation,omitempty"` 188 189 // Type of repositories to list. 190 // Can be one of all, owner, public, private, member. Default: all 191 // Will cause a 422 error if used in the same request as visibility or 192 // affiliation. 193 Type string `url:"type,omitempty"` 194 195 // How to sort the repository list. Can be one of created, updated, pushed, 196 // full_name. Default: full_name 197 Sort string `url:"sort,omitempty"` 198 199 // Direction in which to sort repositories. Can be one of asc or desc. 200 // Default: when using full_name: asc; otherwise desc 201 Direction string `url:"direction,omitempty"` 202 203 ListOptions 204 } 205 206 // SecurityAndAnalysis specifies the optional advanced security features 207 // that are enabled on a given repository. 208 type SecurityAndAnalysis struct { 209 AdvancedSecurity *AdvancedSecurity `json:"advanced_security,omitempty"` 210 SecretScanning *SecretScanning `json:"secret_scanning,omitempty"` 211 SecretScanningPushProtection *SecretScanningPushProtection `json:"secret_scanning_push_protection,omitempty"` 212 } 213 214 func (s SecurityAndAnalysis) String() string { 215 return Stringify(s) 216 } 217 218 // AdvancedSecurity specifies the state of advanced security on a repository. 219 // 220 // GitHub API docs: https://docs.github.com/en/github/getting-started-with-github/learning-about-github/about-github-advanced-security 221 type AdvancedSecurity struct { 222 Status *string `json:"status,omitempty"` 223 } 224 225 func (a AdvancedSecurity) String() string { 226 return Stringify(a) 227 } 228 229 // SecretScanning specifies the state of secret scanning on a repository. 230 // 231 // GitHub API docs: https://docs.github.com/en/code-security/secret-security/about-secret-scanning 232 type SecretScanning struct { 233 Status *string `json:"status,omitempty"` 234 } 235 236 func (s SecretScanning) String() string { 237 return Stringify(s) 238 } 239 240 // SecretScanningPushProtection specifies the state of secret scanning push protection on a repository. 241 // 242 // GitHub API docs: https://docs.github.com/en/code-security/secret-scanning/about-secret-scanning#about-secret-scanning-for-partner-patterns 243 type SecretScanningPushProtection struct { 244 Status *string `json:"status,omitempty"` 245 } 246 247 // List the repositories for a user. Passing the empty string will list 248 // repositories for the authenticated user. 249 // 250 // GitHub API docs: https://docs.github.com/en/rest/repos/repos#list-repositories-for-the-authenticated-user 251 // GitHub API docs: https://docs.github.com/en/rest/repos/repos#list-repositories-for-a-user 252 func (s *RepositoriesService) List(ctx context.Context, user string, opts *RepositoryListOptions) ([]*Repository, *Response, error) { 253 var u string 254 if user != "" { 255 u = fmt.Sprintf("users/%v/repos", user) 256 } else { 257 u = "user/repos" 258 } 259 u, err := addOptions(u, opts) 260 if err != nil { 261 return nil, nil, err 262 } 263 264 req, err := s.client.NewRequest("GET", u, nil) 265 if err != nil { 266 return nil, nil, err 267 } 268 269 // TODO: remove custom Accept headers when APIs fully launch. 270 acceptHeaders := []string{mediaTypeTopicsPreview, mediaTypeRepositoryVisibilityPreview} 271 req.Header.Set("Accept", strings.Join(acceptHeaders, ", ")) 272 273 var repos []*Repository 274 resp, err := s.client.Do(ctx, req, &repos) 275 if err != nil { 276 return nil, resp, err 277 } 278 279 return repos, resp, nil 280 } 281 282 // RepositoryListByOrgOptions specifies the optional parameters to the 283 // RepositoriesService.ListByOrg method. 284 type RepositoryListByOrgOptions struct { 285 // Type of repositories to list. Possible values are: all, public, private, 286 // forks, sources, member. Default is "all". 287 Type string `url:"type,omitempty"` 288 289 // How to sort the repository list. Can be one of created, updated, pushed, 290 // full_name. Default is "created". 291 Sort string `url:"sort,omitempty"` 292 293 // Direction in which to sort repositories. Can be one of asc or desc. 294 // Default when using full_name: asc; otherwise desc. 295 Direction string `url:"direction,omitempty"` 296 297 ListOptions 298 } 299 300 // ListByOrg lists the repositories for an organization. 301 // 302 // GitHub API docs: https://docs.github.com/en/rest/repos/repos#list-organization-repositories 303 func (s *RepositoriesService) ListByOrg(ctx context.Context, org string, opts *RepositoryListByOrgOptions) ([]*Repository, *Response, error) { 304 u := fmt.Sprintf("orgs/%v/repos", org) 305 u, err := addOptions(u, opts) 306 if err != nil { 307 return nil, nil, err 308 } 309 310 req, err := s.client.NewRequest("GET", u, nil) 311 if err != nil { 312 return nil, nil, err 313 } 314 315 // TODO: remove custom Accept headers when APIs fully launch. 316 acceptHeaders := []string{mediaTypeTopicsPreview, mediaTypeRepositoryVisibilityPreview} 317 req.Header.Set("Accept", strings.Join(acceptHeaders, ", ")) 318 319 var repos []*Repository 320 resp, err := s.client.Do(ctx, req, &repos) 321 if err != nil { 322 return nil, resp, err 323 } 324 325 return repos, resp, nil 326 } 327 328 // RepositoryListAllOptions specifies the optional parameters to the 329 // RepositoriesService.ListAll method. 330 type RepositoryListAllOptions struct { 331 // ID of the last repository seen 332 Since int64 `url:"since,omitempty"` 333 } 334 335 // ListAll lists all GitHub repositories in the order that they were created. 336 // 337 // GitHub API docs: https://docs.github.com/en/rest/repos/repos#list-public-repositories 338 func (s *RepositoriesService) ListAll(ctx context.Context, opts *RepositoryListAllOptions) ([]*Repository, *Response, error) { 339 u, err := addOptions("repositories", opts) 340 if err != nil { 341 return nil, nil, err 342 } 343 344 req, err := s.client.NewRequest("GET", u, nil) 345 if err != nil { 346 return nil, nil, err 347 } 348 349 var repos []*Repository 350 resp, err := s.client.Do(ctx, req, &repos) 351 if err != nil { 352 return nil, resp, err 353 } 354 355 return repos, resp, nil 356 } 357 358 // createRepoRequest is a subset of Repository and is used internally 359 // by Create to pass only the known fields for the endpoint. 360 // 361 // See https://github.com/google/go-github/issues/1014 for more 362 // information. 363 type createRepoRequest struct { 364 // Name is required when creating a repo. 365 Name *string `json:"name,omitempty"` 366 Description *string `json:"description,omitempty"` 367 Homepage *string `json:"homepage,omitempty"` 368 369 Private *bool `json:"private,omitempty"` 370 Visibility *string `json:"visibility,omitempty"` 371 HasIssues *bool `json:"has_issues,omitempty"` 372 HasProjects *bool `json:"has_projects,omitempty"` 373 HasWiki *bool `json:"has_wiki,omitempty"` 374 HasDiscussions *bool `json:"has_discussions,omitempty"` 375 IsTemplate *bool `json:"is_template,omitempty"` 376 377 // Creating an organization repository. Required for non-owners. 378 TeamID *int64 `json:"team_id,omitempty"` 379 380 AutoInit *bool `json:"auto_init,omitempty"` 381 GitignoreTemplate *string `json:"gitignore_template,omitempty"` 382 LicenseTemplate *string `json:"license_template,omitempty"` 383 AllowSquashMerge *bool `json:"allow_squash_merge,omitempty"` 384 AllowMergeCommit *bool `json:"allow_merge_commit,omitempty"` 385 AllowRebaseMerge *bool `json:"allow_rebase_merge,omitempty"` 386 AllowUpdateBranch *bool `json:"allow_update_branch,omitempty"` 387 AllowAutoMerge *bool `json:"allow_auto_merge,omitempty"` 388 AllowForking *bool `json:"allow_forking,omitempty"` 389 DeleteBranchOnMerge *bool `json:"delete_branch_on_merge,omitempty"` 390 UseSquashPRTitleAsDefault *bool `json:"use_squash_pr_title_as_default,omitempty"` 391 SquashMergeCommitTitle *string `json:"squash_merge_commit_title,omitempty"` 392 SquashMergeCommitMessage *string `json:"squash_merge_commit_message,omitempty"` 393 MergeCommitTitle *string `json:"merge_commit_title,omitempty"` 394 MergeCommitMessage *string `json:"merge_commit_message,omitempty"` 395 } 396 397 // Create a new repository. If an organization is specified, the new 398 // repository will be created under that org. If the empty string is 399 // specified, it will be created for the authenticated user. 400 // 401 // Note that only a subset of the repo fields are used and repo must 402 // not be nil. 403 // 404 // Also note that this method will return the response without actually 405 // waiting for GitHub to finish creating the repository and letting the 406 // changes propagate throughout its servers. You may set up a loop with 407 // exponential back-off to verify repository's creation. 408 // 409 // GitHub API docs: https://docs.github.com/en/rest/repos/repos#create-a-repository-for-the-authenticated-user 410 // GitHub API docs: https://docs.github.com/en/rest/repos/repos#create-an-organization-repository 411 func (s *RepositoriesService) Create(ctx context.Context, org string, repo *Repository) (*Repository, *Response, error) { 412 var u string 413 if org != "" { 414 u = fmt.Sprintf("orgs/%v/repos", org) 415 } else { 416 u = "user/repos" 417 } 418 419 repoReq := &createRepoRequest{ 420 Name: repo.Name, 421 Description: repo.Description, 422 Homepage: repo.Homepage, 423 Private: repo.Private, 424 Visibility: repo.Visibility, 425 HasIssues: repo.HasIssues, 426 HasProjects: repo.HasProjects, 427 HasWiki: repo.HasWiki, 428 HasDiscussions: repo.HasDiscussions, 429 IsTemplate: repo.IsTemplate, 430 TeamID: repo.TeamID, 431 AutoInit: repo.AutoInit, 432 GitignoreTemplate: repo.GitignoreTemplate, 433 LicenseTemplate: repo.LicenseTemplate, 434 AllowSquashMerge: repo.AllowSquashMerge, 435 AllowMergeCommit: repo.AllowMergeCommit, 436 AllowRebaseMerge: repo.AllowRebaseMerge, 437 AllowUpdateBranch: repo.AllowUpdateBranch, 438 AllowAutoMerge: repo.AllowAutoMerge, 439 AllowForking: repo.AllowForking, 440 DeleteBranchOnMerge: repo.DeleteBranchOnMerge, 441 UseSquashPRTitleAsDefault: repo.UseSquashPRTitleAsDefault, 442 SquashMergeCommitTitle: repo.SquashMergeCommitTitle, 443 SquashMergeCommitMessage: repo.SquashMergeCommitMessage, 444 MergeCommitTitle: repo.MergeCommitTitle, 445 MergeCommitMessage: repo.MergeCommitMessage, 446 } 447 448 req, err := s.client.NewRequest("POST", u, repoReq) 449 if err != nil { 450 return nil, nil, err 451 } 452 453 acceptHeaders := []string{mediaTypeRepositoryTemplatePreview, mediaTypeRepositoryVisibilityPreview} 454 req.Header.Set("Accept", strings.Join(acceptHeaders, ", ")) 455 r := new(Repository) 456 resp, err := s.client.Do(ctx, req, r) 457 if err != nil { 458 return nil, resp, err 459 } 460 461 return r, resp, nil 462 } 463 464 // TemplateRepoRequest represents a request to create a repository from a template. 465 type TemplateRepoRequest struct { 466 // Name is required when creating a repo. 467 Name *string `json:"name,omitempty"` 468 Owner *string `json:"owner,omitempty"` 469 Description *string `json:"description,omitempty"` 470 471 IncludeAllBranches *bool `json:"include_all_branches,omitempty"` 472 Private *bool `json:"private,omitempty"` 473 } 474 475 // CreateFromTemplate generates a repository from a template. 476 // 477 // GitHub API docs: https://docs.github.com/en/rest/repos/repos#create-a-repository-using-a-template 478 func (s *RepositoriesService) CreateFromTemplate(ctx context.Context, templateOwner, templateRepo string, templateRepoReq *TemplateRepoRequest) (*Repository, *Response, error) { 479 u := fmt.Sprintf("repos/%v/%v/generate", templateOwner, templateRepo) 480 481 req, err := s.client.NewRequest("POST", u, templateRepoReq) 482 if err != nil { 483 return nil, nil, err 484 } 485 486 req.Header.Set("Accept", mediaTypeRepositoryTemplatePreview) 487 r := new(Repository) 488 resp, err := s.client.Do(ctx, req, r) 489 if err != nil { 490 return nil, resp, err 491 } 492 493 return r, resp, nil 494 } 495 496 // Get fetches a repository. 497 // 498 // GitHub API docs: https://docs.github.com/en/rest/repos/repos#get-a-repository 499 func (s *RepositoriesService) Get(ctx context.Context, owner, repo string) (*Repository, *Response, error) { 500 u := fmt.Sprintf("repos/%v/%v", owner, repo) 501 req, err := s.client.NewRequest("GET", u, nil) 502 if err != nil { 503 return nil, nil, err 504 } 505 506 // TODO: remove custom Accept header when the license support fully launches 507 // https://docs.github.com/en/rest/licenses/#get-a-repositorys-license 508 acceptHeaders := []string{ 509 mediaTypeCodesOfConductPreview, 510 mediaTypeTopicsPreview, 511 mediaTypeRepositoryTemplatePreview, 512 mediaTypeRepositoryVisibilityPreview, 513 } 514 req.Header.Set("Accept", strings.Join(acceptHeaders, ", ")) 515 516 repository := new(Repository) 517 resp, err := s.client.Do(ctx, req, repository) 518 if err != nil { 519 return nil, resp, err 520 } 521 522 return repository, resp, nil 523 } 524 525 // GetCodeOfConduct gets the contents of a repository's code of conduct. 526 // Note that https://docs.github.com/en/rest/codes-of-conduct#about-the-codes-of-conduct-api 527 // says to use the GET /repos/{owner}/{repo} endpoint. 528 // 529 // GitHub API docs: https://docs.github.com/en/rest/repos/repos#update-a-repository 530 func (s *RepositoriesService) GetCodeOfConduct(ctx context.Context, owner, repo string) (*CodeOfConduct, *Response, error) { 531 u := fmt.Sprintf("repos/%v/%v", owner, repo) 532 req, err := s.client.NewRequest("GET", u, nil) 533 if err != nil { 534 return nil, nil, err 535 } 536 537 // TODO: remove custom Accept header when this API fully launches. 538 req.Header.Set("Accept", mediaTypeCodesOfConductPreview) 539 540 r := new(Repository) 541 resp, err := s.client.Do(ctx, req, r) 542 if err != nil { 543 return nil, resp, err 544 } 545 546 return r.GetCodeOfConduct(), resp, nil 547 } 548 549 // GetByID fetches a repository. 550 // 551 // Note: GetByID uses the undocumented GitHub API endpoint /repositories/:id. 552 func (s *RepositoriesService) GetByID(ctx context.Context, id int64) (*Repository, *Response, error) { 553 u := fmt.Sprintf("repositories/%d", id) 554 req, err := s.client.NewRequest("GET", u, nil) 555 if err != nil { 556 return nil, nil, err 557 } 558 559 repository := new(Repository) 560 resp, err := s.client.Do(ctx, req, repository) 561 if err != nil { 562 return nil, resp, err 563 } 564 565 return repository, resp, nil 566 } 567 568 // Edit updates a repository. 569 // 570 // GitHub API docs: https://docs.github.com/en/rest/repos/repos#update-a-repository 571 func (s *RepositoriesService) Edit(ctx context.Context, owner, repo string, repository *Repository) (*Repository, *Response, error) { 572 u := fmt.Sprintf("repos/%v/%v", owner, repo) 573 req, err := s.client.NewRequest("PATCH", u, repository) 574 if err != nil { 575 return nil, nil, err 576 } 577 578 acceptHeaders := []string{mediaTypeRepositoryTemplatePreview, mediaTypeRepositoryVisibilityPreview} 579 req.Header.Set("Accept", strings.Join(acceptHeaders, ", ")) 580 r := new(Repository) 581 resp, err := s.client.Do(ctx, req, r) 582 if err != nil { 583 return nil, resp, err 584 } 585 586 return r, resp, nil 587 } 588 589 // Delete a repository. 590 // 591 // GitHub API docs: https://docs.github.com/en/rest/repos/repos#delete-a-repository 592 func (s *RepositoriesService) Delete(ctx context.Context, owner, repo string) (*Response, error) { 593 u := fmt.Sprintf("repos/%v/%v", owner, repo) 594 req, err := s.client.NewRequest("DELETE", u, nil) 595 if err != nil { 596 return nil, err 597 } 598 599 return s.client.Do(ctx, req, nil) 600 } 601 602 // Contributor represents a repository contributor 603 type Contributor struct { 604 Login *string `json:"login,omitempty"` 605 ID *int64 `json:"id,omitempty"` 606 NodeID *string `json:"node_id,omitempty"` 607 AvatarURL *string `json:"avatar_url,omitempty"` 608 GravatarID *string `json:"gravatar_id,omitempty"` 609 URL *string `json:"url,omitempty"` 610 HTMLURL *string `json:"html_url,omitempty"` 611 FollowersURL *string `json:"followers_url,omitempty"` 612 FollowingURL *string `json:"following_url,omitempty"` 613 GistsURL *string `json:"gists_url,omitempty"` 614 StarredURL *string `json:"starred_url,omitempty"` 615 SubscriptionsURL *string `json:"subscriptions_url,omitempty"` 616 OrganizationsURL *string `json:"organizations_url,omitempty"` 617 ReposURL *string `json:"repos_url,omitempty"` 618 EventsURL *string `json:"events_url,omitempty"` 619 ReceivedEventsURL *string `json:"received_events_url,omitempty"` 620 Type *string `json:"type,omitempty"` 621 SiteAdmin *bool `json:"site_admin,omitempty"` 622 Contributions *int `json:"contributions,omitempty"` 623 Name *string `json:"name,omitempty"` 624 Email *string `json:"email,omitempty"` 625 } 626 627 // ListContributorsOptions specifies the optional parameters to the 628 // RepositoriesService.ListContributors method. 629 type ListContributorsOptions struct { 630 // Include anonymous contributors in results or not 631 Anon string `url:"anon,omitempty"` 632 633 ListOptions 634 } 635 636 // GetVulnerabilityAlerts checks if vulnerability alerts are enabled for a repository. 637 // 638 // GitHub API docs: https://docs.github.com/en/rest/repos/repos#check-if-vulnerability-alerts-are-enabled-for-a-repository 639 func (s *RepositoriesService) GetVulnerabilityAlerts(ctx context.Context, owner, repository string) (bool, *Response, error) { 640 u := fmt.Sprintf("repos/%v/%v/vulnerability-alerts", owner, repository) 641 642 req, err := s.client.NewRequest("GET", u, nil) 643 if err != nil { 644 return false, nil, err 645 } 646 647 // TODO: remove custom Accept header when this API fully launches 648 req.Header.Set("Accept", mediaTypeRequiredVulnerabilityAlertsPreview) 649 650 resp, err := s.client.Do(ctx, req, nil) 651 vulnerabilityAlertsEnabled, err := parseBoolResponse(err) 652 return vulnerabilityAlertsEnabled, resp, err 653 } 654 655 // EnableVulnerabilityAlerts enables vulnerability alerts and the dependency graph for a repository. 656 // 657 // GitHub API docs: https://docs.github.com/en/rest/repos/repos#enable-vulnerability-alerts 658 func (s *RepositoriesService) EnableVulnerabilityAlerts(ctx context.Context, owner, repository string) (*Response, error) { 659 u := fmt.Sprintf("repos/%v/%v/vulnerability-alerts", owner, repository) 660 661 req, err := s.client.NewRequest("PUT", u, nil) 662 if err != nil { 663 return nil, err 664 } 665 666 // TODO: remove custom Accept header when this API fully launches 667 req.Header.Set("Accept", mediaTypeRequiredVulnerabilityAlertsPreview) 668 669 return s.client.Do(ctx, req, nil) 670 } 671 672 // DisableVulnerabilityAlerts disables vulnerability alerts and the dependency graph for a repository. 673 // 674 // GitHub API docs: https://docs.github.com/en/rest/repos/repos#disable-vulnerability-alerts 675 func (s *RepositoriesService) DisableVulnerabilityAlerts(ctx context.Context, owner, repository string) (*Response, error) { 676 u := fmt.Sprintf("repos/%v/%v/vulnerability-alerts", owner, repository) 677 678 req, err := s.client.NewRequest("DELETE", u, nil) 679 if err != nil { 680 return nil, err 681 } 682 683 // TODO: remove custom Accept header when this API fully launches 684 req.Header.Set("Accept", mediaTypeRequiredVulnerabilityAlertsPreview) 685 686 return s.client.Do(ctx, req, nil) 687 } 688 689 // EnableAutomatedSecurityFixes enables the automated security fixes for a repository. 690 // 691 // GitHub API docs: https://docs.github.com/en/rest/repos/repos#enable-automated-security-fixes 692 func (s *RepositoriesService) EnableAutomatedSecurityFixes(ctx context.Context, owner, repository string) (*Response, error) { 693 u := fmt.Sprintf("repos/%v/%v/automated-security-fixes", owner, repository) 694 695 req, err := s.client.NewRequest("PUT", u, nil) 696 if err != nil { 697 return nil, err 698 } 699 700 // TODO: remove custom Accept header when this API fully launches 701 req.Header.Set("Accept", mediaTypeRequiredAutomatedSecurityFixesPreview) 702 703 return s.client.Do(ctx, req, nil) 704 } 705 706 // DisableAutomatedSecurityFixes disables vulnerability alerts and the dependency graph for a repository. 707 // 708 // GitHub API docs: https://docs.github.com/en/rest/repos/repos#disable-automated-security-fixes 709 func (s *RepositoriesService) DisableAutomatedSecurityFixes(ctx context.Context, owner, repository string) (*Response, error) { 710 u := fmt.Sprintf("repos/%v/%v/automated-security-fixes", owner, repository) 711 712 req, err := s.client.NewRequest("DELETE", u, nil) 713 if err != nil { 714 return nil, err 715 } 716 717 // TODO: remove custom Accept header when this API fully launches 718 req.Header.Set("Accept", mediaTypeRequiredAutomatedSecurityFixesPreview) 719 720 return s.client.Do(ctx, req, nil) 721 } 722 723 // ListContributors lists contributors for a repository. 724 // 725 // GitHub API docs: https://docs.github.com/en/rest/repos/repos#list-repository-contributors 726 func (s *RepositoriesService) ListContributors(ctx context.Context, owner string, repository string, opts *ListContributorsOptions) ([]*Contributor, *Response, error) { 727 u := fmt.Sprintf("repos/%v/%v/contributors", owner, repository) 728 u, err := addOptions(u, opts) 729 if err != nil { 730 return nil, nil, err 731 } 732 733 req, err := s.client.NewRequest("GET", u, nil) 734 if err != nil { 735 return nil, nil, err 736 } 737 738 var contributor []*Contributor 739 resp, err := s.client.Do(ctx, req, &contributor) 740 if err != nil { 741 return nil, resp, err 742 } 743 744 return contributor, resp, nil 745 } 746 747 // ListLanguages lists languages for the specified repository. The returned map 748 // specifies the languages and the number of bytes of code written in that 749 // language. For example: 750 // 751 // { 752 // "C": 78769, 753 // "Python": 7769 754 // } 755 // 756 // GitHub API docs: https://docs.github.com/en/rest/repos/repos#list-repository-languages 757 func (s *RepositoriesService) ListLanguages(ctx context.Context, owner string, repo string) (map[string]int, *Response, error) { 758 u := fmt.Sprintf("repos/%v/%v/languages", owner, repo) 759 req, err := s.client.NewRequest("GET", u, nil) 760 if err != nil { 761 return nil, nil, err 762 } 763 764 languages := make(map[string]int) 765 resp, err := s.client.Do(ctx, req, &languages) 766 if err != nil { 767 return nil, resp, err 768 } 769 770 return languages, resp, nil 771 } 772 773 // ListTeams lists the teams for the specified repository. 774 // 775 // GitHub API docs: https://docs.github.com/en/rest/repos/repos#list-repository-teams 776 func (s *RepositoriesService) ListTeams(ctx context.Context, owner string, repo string, opts *ListOptions) ([]*Team, *Response, error) { 777 u := fmt.Sprintf("repos/%v/%v/teams", owner, repo) 778 u, err := addOptions(u, opts) 779 if err != nil { 780 return nil, nil, err 781 } 782 783 req, err := s.client.NewRequest("GET", u, nil) 784 if err != nil { 785 return nil, nil, err 786 } 787 788 var teams []*Team 789 resp, err := s.client.Do(ctx, req, &teams) 790 if err != nil { 791 return nil, resp, err 792 } 793 794 return teams, resp, nil 795 } 796 797 // RepositoryTag represents a repository tag. 798 type RepositoryTag struct { 799 Name *string `json:"name,omitempty"` 800 Commit *Commit `json:"commit,omitempty"` 801 ZipballURL *string `json:"zipball_url,omitempty"` 802 TarballURL *string `json:"tarball_url,omitempty"` 803 } 804 805 // ListTags lists tags for the specified repository. 806 // 807 // GitHub API docs: https://docs.github.com/en/rest/repos/repos#list-repository-tags 808 func (s *RepositoriesService) ListTags(ctx context.Context, owner string, repo string, opts *ListOptions) ([]*RepositoryTag, *Response, error) { 809 u := fmt.Sprintf("repos/%v/%v/tags", owner, repo) 810 u, err := addOptions(u, opts) 811 if err != nil { 812 return nil, nil, err 813 } 814 815 req, err := s.client.NewRequest("GET", u, nil) 816 if err != nil { 817 return nil, nil, err 818 } 819 820 var tags []*RepositoryTag 821 resp, err := s.client.Do(ctx, req, &tags) 822 if err != nil { 823 return nil, resp, err 824 } 825 826 return tags, resp, nil 827 } 828 829 // Branch represents a repository branch 830 type Branch struct { 831 Name *string `json:"name,omitempty"` 832 Commit *RepositoryCommit `json:"commit,omitempty"` 833 Protected *bool `json:"protected,omitempty"` 834 } 835 836 // Protection represents a repository branch's protection. 837 type Protection struct { 838 RequiredStatusChecks *RequiredStatusChecks `json:"required_status_checks"` 839 RequiredPullRequestReviews *PullRequestReviewsEnforcement `json:"required_pull_request_reviews"` 840 EnforceAdmins *AdminEnforcement `json:"enforce_admins"` 841 Restrictions *BranchRestrictions `json:"restrictions"` 842 RequireLinearHistory *RequireLinearHistory `json:"required_linear_history"` 843 AllowForcePushes *AllowForcePushes `json:"allow_force_pushes"` 844 AllowDeletions *AllowDeletions `json:"allow_deletions"` 845 RequiredConversationResolution *RequiredConversationResolution `json:"required_conversation_resolution"` 846 LockBranch *LockBranch `json:"lock_branch,omitempty"` 847 AllowForkSyncing *AllowForkSyncing `json:"allow_fork_syncing,omitempty"` 848 } 849 850 // LockBranch represents if the branch is marked as read-only. If this is true, users will not be able to push to the branch. 851 type LockBranch struct { 852 Enabled *bool `json:"enabled,omitempty"` 853 } 854 855 // AllowForkSyncing represents whether users can pull changes from upstream when the branch is locked. 856 type AllowForkSyncing struct { 857 Enabled *bool `json:"enabled,omitempty"` 858 } 859 860 // BranchProtectionRule represents the rule applied to a repositories branch. 861 type BranchProtectionRule struct { 862 ID *int64 `json:"id,omitempty"` 863 RepositoryID *int64 `json:"repository_id,omitempty"` 864 Name *string `json:"name,omitempty"` 865 CreatedAt *Timestamp `json:"created_at,omitempty"` 866 UpdatedAt *Timestamp `json:"updated_at,omitempty"` 867 PullRequestReviewsEnforcementLevel *string `json:"pull_request_reviews_enforcement_level,omitempty"` 868 RequiredApprovingReviewCount *int `json:"required_approving_review_count,omitempty"` 869 DismissStaleReviewsOnPush *bool `json:"dismiss_stale_reviews_on_push,omitempty"` 870 AuthorizedDismissalActorsOnly *bool `json:"authorized_dismissal_actors_only,omitempty"` 871 IgnoreApprovalsFromContributors *bool `json:"ignore_approvals_from_contributors,omitempty"` 872 RequireCodeOwnerReview *bool `json:"require_code_owner_review,omitempty"` 873 RequiredStatusChecks []string `json:"required_status_checks,omitempty"` 874 RequiredStatusChecksEnforcementLevel *string `json:"required_status_checks_enforcement_level,omitempty"` 875 StrictRequiredStatusChecksPolicy *bool `json:"strict_required_status_checks_policy,omitempty"` 876 SignatureRequirementEnforcementLevel *string `json:"signature_requirement_enforcement_level,omitempty"` 877 LinearHistoryRequirementEnforcementLevel *string `json:"linear_history_requirement_enforcement_level,omitempty"` 878 AdminEnforced *bool `json:"admin_enforced,omitempty"` 879 AllowForcePushesEnforcementLevel *string `json:"allow_force_pushes_enforcement_level,omitempty"` 880 AllowDeletionsEnforcementLevel *string `json:"allow_deletions_enforcement_level,omitempty"` 881 MergeQueueEnforcementLevel *string `json:"merge_queue_enforcement_level,omitempty"` 882 RequiredDeploymentsEnforcementLevel *string `json:"required_deployments_enforcement_level,omitempty"` 883 RequiredConversationResolutionLevel *string `json:"required_conversation_resolution_level,omitempty"` 884 AuthorizedActorsOnly *bool `json:"authorized_actors_only,omitempty"` 885 AuthorizedActorNames []string `json:"authorized_actor_names,omitempty"` 886 } 887 888 // ProtectionChanges represents the changes to the rule if the BranchProtection was edited. 889 type ProtectionChanges struct { 890 AdminEnforced *AdminEnforcedChanges `json:"admin_enforced,omitempty"` 891 AllowDeletionsEnforcementLevel *AllowDeletionsEnforcementLevelChanges `json:"allow_deletions_enforcement_level,omitempty"` 892 AuthorizedActorNames *AuthorizedActorNames `json:"authorized_actor_names,omitempty"` 893 AuthorizedActorsOnly *AuthorizedActorsOnly `json:"authorized_actors_only,omitempty"` 894 AuthorizedDismissalActorsOnly *AuthorizedDismissalActorsOnlyChanges `json:"authorized_dismissal_actors_only,omitempty"` 895 CreateProtected *CreateProtectedChanges `json:"create_protected,omitempty"` 896 DismissStaleReviewsOnPush *DismissStaleReviewsOnPushChanges `json:"dismiss_stale_reviews_on_push,omitempty"` 897 LinearHistoryRequirementEnforcementLevel *LinearHistoryRequirementEnforcementLevelChanges `json:"linear_history_requirement_enforcement_level,omitempty"` 898 PullRequestReviewsEnforcementLevel *PullRequestReviewsEnforcementLevelChanges `json:"pull_request_reviews_enforcement_level,omitempty"` 899 RequireCodeOwnerReview *RequireCodeOwnerReviewChanges `json:"require_code_owner_review,omitempty"` 900 RequiredConversationResolutionLevel *RequiredConversationResolutionLevelChanges `json:"required_conversation_resolution_level,omitempty"` 901 RequiredDeploymentsEnforcementLevel *RequiredDeploymentsEnforcementLevelChanges `json:"required_deployments_enforcement_level,omitempty"` 902 RequiredStatusChecks *RequiredStatusChecksChanges `json:"required_status_checks,omitempty"` 903 RequiredStatusChecksEnforcementLevel *RequiredStatusChecksEnforcementLevelChanges `json:"required_status_checks_enforcement_level,omitempty"` 904 SignatureRequirementEnforcementLevel *SignatureRequirementEnforcementLevelChanges `json:"signature_requirement_enforcement_level,omitempty"` 905 } 906 907 // AdminEnforcedChanges represents the changes made to the AdminEnforced policy. 908 type AdminEnforcedChanges struct { 909 From *bool `json:"from,omitempty"` 910 } 911 912 // AllowDeletionsEnforcementLevelChanges represents the changes made to the AllowDeletionsEnforcementLevel policy. 913 type AllowDeletionsEnforcementLevelChanges struct { 914 From *string `json:"from,omitempty"` 915 } 916 917 // AuthorizedActorNames represents who are authorized to edit the branch protection rules. 918 type AuthorizedActorNames struct { 919 From []string `json:"from,omitempty"` 920 } 921 922 // AuthorizedActorsOnly represents if the branch rule can be edited by authorized actors only. 923 type AuthorizedActorsOnly struct { 924 From *bool `json:"from,omitempty"` 925 } 926 927 // AuthorizedDismissalActorsOnlyChanges represents the changes made to the AuthorizedDismissalActorsOnly policy. 928 type AuthorizedDismissalActorsOnlyChanges struct { 929 From *bool `json:"from,omitempty"` 930 } 931 932 // CreateProtectedChanges represents the changes made to the CreateProtected policy. 933 type CreateProtectedChanges struct { 934 From *bool `json:"from,omitempty"` 935 } 936 937 // DismissStaleReviewsOnPushChanges represents the changes made to the DismissStaleReviewsOnPushChanges policy. 938 type DismissStaleReviewsOnPushChanges struct { 939 From *bool `json:"from,omitempty"` 940 } 941 942 // LinearHistoryRequirementEnforcementLevelChanges represents the changes made to the LinearHistoryRequirementEnforcementLevel policy. 943 type LinearHistoryRequirementEnforcementLevelChanges struct { 944 From *string `json:"from,omitempty"` 945 } 946 947 // PullRequestReviewsEnforcementLevelChanges represents the changes made to the PullRequestReviewsEnforcementLevel policy. 948 type PullRequestReviewsEnforcementLevelChanges struct { 949 From *string `json:"from,omitempty"` 950 } 951 952 // RequireCodeOwnerReviewChanges represents the changes made to the RequireCodeOwnerReview policy. 953 type RequireCodeOwnerReviewChanges struct { 954 From *bool `json:"from,omitempty"` 955 } 956 957 // RequiredConversationResolutionLevelChanges represents the changes made to the RequiredConversationResolutionLevel policy. 958 type RequiredConversationResolutionLevelChanges struct { 959 From *string `json:"from,omitempty"` 960 } 961 962 // RequiredDeploymentsEnforcementLevelChanges represents the changes made to the RequiredDeploymentsEnforcementLevel policy. 963 type RequiredDeploymentsEnforcementLevelChanges struct { 964 From *string `json:"from,omitempty"` 965 } 966 967 // RequiredStatusChecksChanges represents the changes made to the RequiredStatusChecks policy. 968 type RequiredStatusChecksChanges struct { 969 From []string `json:"from,omitempty"` 970 } 971 972 // RequiredStatusChecksEnforcementLevelChanges represents the changes made to the RequiredStatusChecksEnforcementLevel policy. 973 type RequiredStatusChecksEnforcementLevelChanges struct { 974 From *string `json:"from,omitempty"` 975 } 976 977 // SignatureRequirementEnforcementLevelChanges represents the changes made to the SignatureRequirementEnforcementLevel policy. 978 type SignatureRequirementEnforcementLevelChanges struct { 979 From *string `json:"from,omitempty"` 980 } 981 982 // ProtectionRequest represents a request to create/edit a branch's protection. 983 type ProtectionRequest struct { 984 RequiredStatusChecks *RequiredStatusChecks `json:"required_status_checks"` 985 RequiredPullRequestReviews *PullRequestReviewsEnforcementRequest `json:"required_pull_request_reviews"` 986 EnforceAdmins bool `json:"enforce_admins"` 987 Restrictions *BranchRestrictionsRequest `json:"restrictions"` 988 // Enforces a linear commit Git history, which prevents anyone from pushing merge commits to a branch. 989 RequireLinearHistory *bool `json:"required_linear_history,omitempty"` 990 // Permits force pushes to the protected branch by anyone with write access to the repository. 991 AllowForcePushes *bool `json:"allow_force_pushes,omitempty"` 992 // Allows deletion of the protected branch by anyone with write access to the repository. 993 AllowDeletions *bool `json:"allow_deletions,omitempty"` 994 // RequiredConversationResolution, if set to true, requires all comments 995 // on the pull request to be resolved before it can be merged to a protected branch. 996 RequiredConversationResolution *bool `json:"required_conversation_resolution,omitempty"` 997 } 998 999 // RequiredStatusChecks represents the protection status of a individual branch. 1000 type RequiredStatusChecks struct { 1001 // Require branches to be up to date before merging. (Required.) 1002 Strict bool `json:"strict"` 1003 // The list of status checks to require in order to merge into this 1004 // branch. (Deprecated. Note: only one of Contexts/Checks can be populated, 1005 // but at least one must be populated). 1006 Contexts []string `json:"contexts,omitempty"` 1007 // The list of status checks to require in order to merge into this 1008 // branch. 1009 Checks []*RequiredStatusCheck `json:"checks"` 1010 } 1011 1012 // RequiredStatusChecksRequest represents a request to edit a protected branch's status checks. 1013 type RequiredStatusChecksRequest struct { 1014 Strict *bool `json:"strict,omitempty"` 1015 // Note: if both Contexts and Checks are populated, 1016 // the GitHub API will only use Checks. 1017 Contexts []string `json:"contexts,omitempty"` 1018 Checks []*RequiredStatusCheck `json:"checks,omitempty"` 1019 } 1020 1021 // RequiredStatusCheck represents a status check of a protected branch. 1022 type RequiredStatusCheck struct { 1023 // The name of the required check. 1024 Context string `json:"context"` 1025 // The ID of the GitHub App that must provide this check. 1026 // Omit this field to automatically select the GitHub App 1027 // that has recently provided this check, 1028 // or any app if it was not set by a GitHub App. 1029 // Pass -1 to explicitly allow any app to set the status. 1030 AppID *int64 `json:"app_id,omitempty"` 1031 } 1032 1033 // PullRequestReviewsEnforcement represents the pull request reviews enforcement of a protected branch. 1034 type PullRequestReviewsEnforcement struct { 1035 // Allow specific users, teams, or apps to bypass pull request requirements. 1036 BypassPullRequestAllowances *BypassPullRequestAllowances `json:"bypass_pull_request_allowances,omitempty"` 1037 // Specifies which users, teams and apps can dismiss pull request reviews. 1038 DismissalRestrictions *DismissalRestrictions `json:"dismissal_restrictions,omitempty"` 1039 // Specifies if approved reviews are dismissed automatically, when a new commit is pushed. 1040 DismissStaleReviews bool `json:"dismiss_stale_reviews"` 1041 // RequireCodeOwnerReviews specifies if an approved review is required in pull requests including files with a designated code owner. 1042 RequireCodeOwnerReviews bool `json:"require_code_owner_reviews"` 1043 // RequiredApprovingReviewCount specifies the number of approvals required before the pull request can be merged. 1044 // Valid values are 1-6. 1045 RequiredApprovingReviewCount int `json:"required_approving_review_count"` 1046 // RequireLastPushApproval specifies whether the last pusher to a pull request branch can approve it. 1047 RequireLastPushApproval bool `json:"require_last_push_approval"` 1048 } 1049 1050 // PullRequestReviewsEnforcementRequest represents request to set the pull request review 1051 // enforcement of a protected branch. It is separate from PullRequestReviewsEnforcement above 1052 // because the request structure is different from the response structure. 1053 type PullRequestReviewsEnforcementRequest struct { 1054 // Allow specific users, teams, or apps to bypass pull request requirements. 1055 BypassPullRequestAllowancesRequest *BypassPullRequestAllowancesRequest `json:"bypass_pull_request_allowances,omitempty"` 1056 // Specifies which users, teams and apps should be allowed to dismiss pull request reviews. 1057 // User, team and app dismissal restrictions are only available for 1058 // organization-owned repositories. Must be nil for personal repositories. 1059 DismissalRestrictionsRequest *DismissalRestrictionsRequest `json:"dismissal_restrictions,omitempty"` 1060 // Specifies if approved reviews can be dismissed automatically, when a new commit is pushed. (Required) 1061 DismissStaleReviews bool `json:"dismiss_stale_reviews"` 1062 // RequireCodeOwnerReviews specifies if an approved review is required in pull requests including files with a designated code owner. 1063 RequireCodeOwnerReviews bool `json:"require_code_owner_reviews"` 1064 // RequiredApprovingReviewCount specifies the number of approvals required before the pull request can be merged. 1065 // Valid values are 1-6. 1066 RequiredApprovingReviewCount int `json:"required_approving_review_count"` 1067 } 1068 1069 // PullRequestReviewsEnforcementUpdate represents request to patch the pull request review 1070 // enforcement of a protected branch. It is separate from PullRequestReviewsEnforcementRequest above 1071 // because the patch request does not require all fields to be initialized. 1072 type PullRequestReviewsEnforcementUpdate struct { 1073 // Allow specific users, teams, or apps to bypass pull request requirements. 1074 BypassPullRequestAllowancesRequest *BypassPullRequestAllowancesRequest `json:"bypass_pull_request_allowances,omitempty"` 1075 // Specifies which users, teams and apps can dismiss pull request reviews. Can be omitted. 1076 DismissalRestrictionsRequest *DismissalRestrictionsRequest `json:"dismissal_restrictions,omitempty"` 1077 // Specifies if approved reviews can be dismissed automatically, when a new commit is pushed. Can be omitted. 1078 DismissStaleReviews *bool `json:"dismiss_stale_reviews,omitempty"` 1079 // RequireCodeOwnerReviews specifies if merging pull requests is blocked until code owners have reviewed. 1080 RequireCodeOwnerReviews *bool `json:"require_code_owner_reviews,omitempty"` 1081 // RequiredApprovingReviewCount specifies the number of approvals required before the pull request can be merged. 1082 // Valid values are 1 - 6 or 0 to not require reviewers. 1083 RequiredApprovingReviewCount int `json:"required_approving_review_count"` 1084 // RequireLastPushApproval specifies whether the last pusher to a pull request branch can approve it. 1085 RequireLastPushApproval *bool `json:"require_last_push_approval,omitempty"` 1086 } 1087 1088 // RequireLinearHistory represents the configuration to enforce branches with no merge commit. 1089 type RequireLinearHistory struct { 1090 Enabled bool `json:"enabled"` 1091 } 1092 1093 // AllowDeletions represents the configuration to accept deletion of protected branches. 1094 type AllowDeletions struct { 1095 Enabled bool `json:"enabled"` 1096 } 1097 1098 // AllowForcePushes represents the configuration to accept forced pushes on protected branches. 1099 type AllowForcePushes struct { 1100 Enabled bool `json:"enabled"` 1101 } 1102 1103 // RequiredConversationResolution, if enabled, requires all comments on the pull request to be resolved before it can be merged to a protected branch. 1104 type RequiredConversationResolution struct { 1105 Enabled bool `json:"enabled"` 1106 } 1107 1108 // AdminEnforcement represents the configuration to enforce required status checks for repository administrators. 1109 type AdminEnforcement struct { 1110 URL *string `json:"url,omitempty"` 1111 Enabled bool `json:"enabled"` 1112 } 1113 1114 // BranchRestrictions represents the restriction that only certain users or 1115 // teams may push to a branch. 1116 type BranchRestrictions struct { 1117 // The list of user logins with push access. 1118 Users []*User `json:"users"` 1119 // The list of team slugs with push access. 1120 Teams []*Team `json:"teams"` 1121 // The list of app slugs with push access. 1122 Apps []*App `json:"apps"` 1123 } 1124 1125 // BranchRestrictionsRequest represents the request to create/edit the 1126 // restriction that only certain users or teams may push to a branch. It is 1127 // separate from BranchRestrictions above because the request structure is 1128 // different from the response structure. 1129 type BranchRestrictionsRequest struct { 1130 // The list of user logins with push access. (Required; use []string{} instead of nil for empty list.) 1131 Users []string `json:"users"` 1132 // The list of team slugs with push access. (Required; use []string{} instead of nil for empty list.) 1133 Teams []string `json:"teams"` 1134 // The list of app slugs with push access. 1135 Apps []string `json:"apps"` 1136 } 1137 1138 // BypassPullRequestAllowances represents the people, teams, or apps who are allowed to bypass required pull requests. 1139 type BypassPullRequestAllowances struct { 1140 // The list of users allowed to bypass pull request requirements. 1141 Users []*User `json:"users"` 1142 // The list of teams allowed to bypass pull request requirements. 1143 Teams []*Team `json:"teams"` 1144 // The list of apps allowed to bypass pull request requirements. 1145 Apps []*App `json:"apps"` 1146 } 1147 1148 // BypassPullRequestAllowancesRequest represents the people, teams, or apps who are 1149 // allowed to bypass required pull requests. 1150 // It is separate from BypassPullRequestAllowances above because the request structure is 1151 // different from the response structure. 1152 type BypassPullRequestAllowancesRequest struct { 1153 // The list of user logins allowed to bypass pull request requirements. 1154 Users []string `json:"users"` 1155 // The list of team slugs allowed to bypass pull request requirements. 1156 Teams []string `json:"teams"` 1157 // The list of app slugs allowed to bypass pull request requirements. 1158 Apps []string `json:"apps"` 1159 } 1160 1161 // DismissalRestrictions specifies which users and teams can dismiss pull request reviews. 1162 type DismissalRestrictions struct { 1163 // The list of users who can dimiss pull request reviews. 1164 Users []*User `json:"users"` 1165 // The list of teams which can dismiss pull request reviews. 1166 Teams []*Team `json:"teams"` 1167 // The list of apps which can dismiss pull request reviews. 1168 Apps []*App `json:"apps"` 1169 } 1170 1171 // DismissalRestrictionsRequest represents the request to create/edit the 1172 // restriction to allows only specific users, teams or apps to dimiss pull request reviews. It is 1173 // separate from DismissalRestrictions above because the request structure is 1174 // different from the response structure. 1175 // Note: Both Users and Teams must be nil, or both must be non-nil. 1176 type DismissalRestrictionsRequest struct { 1177 // The list of user logins who can dismiss pull request reviews. (Required; use nil to disable dismissal_restrictions or &[]string{} otherwise.) 1178 Users *[]string `json:"users,omitempty"` 1179 // The list of team slugs which can dismiss pull request reviews. (Required; use nil to disable dismissal_restrictions or &[]string{} otherwise.) 1180 Teams *[]string `json:"teams,omitempty"` 1181 // The list of apps which can dismiss pull request reviews. (Required; use nil to disable dismissal_restrictions or &[]string{} otherwise.) 1182 Apps *[]string `json:"apps,omitempty"` 1183 } 1184 1185 // SignaturesProtectedBranch represents the protection status of an individual branch. 1186 type SignaturesProtectedBranch struct { 1187 URL *string `json:"url,omitempty"` 1188 // Commits pushed to matching branches must have verified signatures. 1189 Enabled *bool `json:"enabled,omitempty"` 1190 } 1191 1192 // ListBranches lists branches for the specified repository. 1193 // 1194 // GitHub API docs: https://docs.github.com/en/rest/branches/branches#list-branches 1195 func (s *RepositoriesService) ListBranches(ctx context.Context, owner string, repo string, opts *BranchListOptions) ([]*Branch, *Response, error) { 1196 u := fmt.Sprintf("repos/%v/%v/branches", owner, repo) 1197 u, err := addOptions(u, opts) 1198 if err != nil { 1199 return nil, nil, err 1200 } 1201 1202 req, err := s.client.NewRequest("GET", u, nil) 1203 if err != nil { 1204 return nil, nil, err 1205 } 1206 1207 var branches []*Branch 1208 resp, err := s.client.Do(ctx, req, &branches) 1209 if err != nil { 1210 return nil, resp, err 1211 } 1212 1213 return branches, resp, nil 1214 } 1215 1216 // GetBranch gets the specified branch for a repository. 1217 // 1218 // GitHub API docs: https://docs.github.com/en/rest/branches/branches#get-a-branch 1219 func (s *RepositoriesService) GetBranch(ctx context.Context, owner, repo, branch string, followRedirects bool) (*Branch, *Response, error) { 1220 u := fmt.Sprintf("repos/%v/%v/branches/%v", owner, repo, branch) 1221 1222 resp, err := s.client.roundTripWithOptionalFollowRedirect(ctx, u, followRedirects) 1223 if err != nil { 1224 return nil, nil, err 1225 } 1226 defer resp.Body.Close() 1227 1228 if resp.StatusCode != http.StatusOK { 1229 return nil, newResponse(resp), fmt.Errorf("unexpected status code: %s", resp.Status) 1230 } 1231 1232 b := new(Branch) 1233 err = json.NewDecoder(resp.Body).Decode(b) 1234 return b, newResponse(resp), err 1235 } 1236 1237 // renameBranchRequest represents a request to rename a branch. 1238 type renameBranchRequest struct { 1239 NewName string `json:"new_name"` 1240 } 1241 1242 // RenameBranch renames a branch in a repository. 1243 // 1244 // To rename a non-default branch: Users must have push access. GitHub Apps must have the `contents:write` repository permission. 1245 // To rename the default branch: Users must have admin or owner permissions. GitHub Apps must have the `administration:write` repository permission. 1246 // 1247 // GitHub API docs: https://docs.github.com/en/rest/branches/branches#rename-a-branch 1248 func (s *RepositoriesService) RenameBranch(ctx context.Context, owner, repo, branch, newName string) (*Branch, *Response, error) { 1249 u := fmt.Sprintf("repos/%v/%v/branches/%v/rename", owner, repo, branch) 1250 r := &renameBranchRequest{NewName: newName} 1251 req, err := s.client.NewRequest("POST", u, r) 1252 if err != nil { 1253 return nil, nil, err 1254 } 1255 1256 b := new(Branch) 1257 resp, err := s.client.Do(ctx, req, b) 1258 if err != nil { 1259 return nil, resp, err 1260 } 1261 1262 return b, resp, nil 1263 } 1264 1265 // GetBranchProtection gets the protection of a given branch. 1266 // 1267 // GitHub API docs: https://docs.github.com/en/rest/branches/branch-protection#get-branch-protection 1268 func (s *RepositoriesService) GetBranchProtection(ctx context.Context, owner, repo, branch string) (*Protection, *Response, error) { 1269 u := fmt.Sprintf("repos/%v/%v/branches/%v/protection", owner, repo, branch) 1270 req, err := s.client.NewRequest("GET", u, nil) 1271 if err != nil { 1272 return nil, nil, err 1273 } 1274 1275 // TODO: remove custom Accept header when this API fully launches 1276 req.Header.Set("Accept", mediaTypeRequiredApprovingReviewsPreview) 1277 1278 p := new(Protection) 1279 resp, err := s.client.Do(ctx, req, p) 1280 if err != nil { 1281 if isBranchNotProtected(err) { 1282 err = ErrBranchNotProtected 1283 } 1284 return nil, resp, err 1285 } 1286 1287 return p, resp, nil 1288 } 1289 1290 // GetRequiredStatusChecks gets the required status checks for a given protected branch. 1291 // 1292 // GitHub API docs: https://docs.github.com/en/rest/branches/branch-protection#get-status-checks-protection 1293 func (s *RepositoriesService) GetRequiredStatusChecks(ctx context.Context, owner, repo, branch string) (*RequiredStatusChecks, *Response, error) { 1294 u := fmt.Sprintf("repos/%v/%v/branches/%v/protection/required_status_checks", owner, repo, branch) 1295 req, err := s.client.NewRequest("GET", u, nil) 1296 if err != nil { 1297 return nil, nil, err 1298 } 1299 1300 p := new(RequiredStatusChecks) 1301 resp, err := s.client.Do(ctx, req, p) 1302 if err != nil { 1303 if isBranchNotProtected(err) { 1304 err = ErrBranchNotProtected 1305 } 1306 return nil, resp, err 1307 } 1308 1309 return p, resp, nil 1310 } 1311 1312 // ListRequiredStatusChecksContexts lists the required status checks contexts for a given protected branch. 1313 // 1314 // GitHub API docs: https://docs.github.com/en/rest/branches/branch-protection#get-all-status-check-contexts 1315 func (s *RepositoriesService) ListRequiredStatusChecksContexts(ctx context.Context, owner, repo, branch string) (contexts []string, resp *Response, err error) { 1316 u := fmt.Sprintf("repos/%v/%v/branches/%v/protection/required_status_checks/contexts", owner, repo, branch) 1317 req, err := s.client.NewRequest("GET", u, nil) 1318 if err != nil { 1319 return nil, nil, err 1320 } 1321 1322 resp, err = s.client.Do(ctx, req, &contexts) 1323 if err != nil { 1324 if isBranchNotProtected(err) { 1325 err = ErrBranchNotProtected 1326 } 1327 return nil, resp, err 1328 } 1329 1330 return contexts, resp, nil 1331 } 1332 1333 // UpdateBranchProtection updates the protection of a given branch. 1334 // 1335 // GitHub API docs: https://docs.github.com/en/rest/branches/branch-protection#update-branch-protection 1336 func (s *RepositoriesService) UpdateBranchProtection(ctx context.Context, owner, repo, branch string, preq *ProtectionRequest) (*Protection, *Response, error) { 1337 u := fmt.Sprintf("repos/%v/%v/branches/%v/protection", owner, repo, branch) 1338 req, err := s.client.NewRequest("PUT", u, preq) 1339 if err != nil { 1340 return nil, nil, err 1341 } 1342 1343 // TODO: remove custom Accept header when this API fully launches 1344 req.Header.Set("Accept", mediaTypeRequiredApprovingReviewsPreview) 1345 1346 p := new(Protection) 1347 resp, err := s.client.Do(ctx, req, p) 1348 if err != nil { 1349 return nil, resp, err 1350 } 1351 1352 return p, resp, nil 1353 } 1354 1355 // RemoveBranchProtection removes the protection of a given branch. 1356 // 1357 // GitHub API docs: https://docs.github.com/en/rest/branches/branch-protection#delete-branch-protection 1358 func (s *RepositoriesService) RemoveBranchProtection(ctx context.Context, owner, repo, branch string) (*Response, error) { 1359 u := fmt.Sprintf("repos/%v/%v/branches/%v/protection", owner, repo, branch) 1360 req, err := s.client.NewRequest("DELETE", u, nil) 1361 if err != nil { 1362 return nil, err 1363 } 1364 1365 return s.client.Do(ctx, req, nil) 1366 } 1367 1368 // GetSignaturesProtectedBranch gets required signatures of protected branch. 1369 // 1370 // GitHub API docs: https://docs.github.com/en/rest/branches/branch-protection#get-commit-signature-protection 1371 func (s *RepositoriesService) GetSignaturesProtectedBranch(ctx context.Context, owner, repo, branch string) (*SignaturesProtectedBranch, *Response, error) { 1372 u := fmt.Sprintf("repos/%v/%v/branches/%v/protection/required_signatures", owner, repo, branch) 1373 req, err := s.client.NewRequest("GET", u, nil) 1374 if err != nil { 1375 return nil, nil, err 1376 } 1377 1378 // TODO: remove custom Accept header when this API fully launches 1379 req.Header.Set("Accept", mediaTypeSignaturePreview) 1380 1381 p := new(SignaturesProtectedBranch) 1382 resp, err := s.client.Do(ctx, req, p) 1383 if err != nil { 1384 return nil, resp, err 1385 } 1386 1387 return p, resp, nil 1388 } 1389 1390 // RequireSignaturesOnProtectedBranch makes signed commits required on a protected branch. 1391 // It requires admin access and branch protection to be enabled. 1392 // 1393 // GitHub API docs: https://docs.github.com/en/rest/branches/branch-protection#create-commit-signature-protection 1394 func (s *RepositoriesService) RequireSignaturesOnProtectedBranch(ctx context.Context, owner, repo, branch string) (*SignaturesProtectedBranch, *Response, error) { 1395 u := fmt.Sprintf("repos/%v/%v/branches/%v/protection/required_signatures", owner, repo, branch) 1396 req, err := s.client.NewRequest("POST", u, nil) 1397 if err != nil { 1398 return nil, nil, err 1399 } 1400 1401 // TODO: remove custom Accept header when this API fully launches 1402 req.Header.Set("Accept", mediaTypeSignaturePreview) 1403 1404 r := new(SignaturesProtectedBranch) 1405 resp, err := s.client.Do(ctx, req, r) 1406 if err != nil { 1407 return nil, resp, err 1408 } 1409 1410 return r, resp, nil 1411 } 1412 1413 // OptionalSignaturesOnProtectedBranch removes required signed commits on a given branch. 1414 // 1415 // GitHub API docs: https://docs.github.com/en/rest/branches/branch-protection#delete-commit-signature-protection 1416 func (s *RepositoriesService) OptionalSignaturesOnProtectedBranch(ctx context.Context, owner, repo, branch string) (*Response, error) { 1417 u := fmt.Sprintf("repos/%v/%v/branches/%v/protection/required_signatures", owner, repo, branch) 1418 req, err := s.client.NewRequest("DELETE", u, nil) 1419 if err != nil { 1420 return nil, err 1421 } 1422 1423 // TODO: remove custom Accept header when this API fully launches 1424 req.Header.Set("Accept", mediaTypeSignaturePreview) 1425 1426 return s.client.Do(ctx, req, nil) 1427 } 1428 1429 // UpdateRequiredStatusChecks updates the required status checks for a given protected branch. 1430 // 1431 // GitHub API docs: https://docs.github.com/en/rest/branches/branch-protection#update-status-check-protection 1432 func (s *RepositoriesService) UpdateRequiredStatusChecks(ctx context.Context, owner, repo, branch string, sreq *RequiredStatusChecksRequest) (*RequiredStatusChecks, *Response, error) { 1433 u := fmt.Sprintf("repos/%v/%v/branches/%v/protection/required_status_checks", owner, repo, branch) 1434 req, err := s.client.NewRequest("PATCH", u, sreq) 1435 if err != nil { 1436 return nil, nil, err 1437 } 1438 1439 sc := new(RequiredStatusChecks) 1440 resp, err := s.client.Do(ctx, req, sc) 1441 if err != nil { 1442 return nil, resp, err 1443 } 1444 1445 return sc, resp, nil 1446 } 1447 1448 // RemoveRequiredStatusChecks removes the required status checks for a given protected branch. 1449 // 1450 // GitHub API docs: https://docs.github.com/en/rest/branches/branch-protection#remove-status-check-protection 1451 func (s *RepositoriesService) RemoveRequiredStatusChecks(ctx context.Context, owner, repo, branch string) (*Response, error) { 1452 u := fmt.Sprintf("repos/%v/%v/branches/%v/protection/required_status_checks", owner, repo, branch) 1453 req, err := s.client.NewRequest("DELETE", u, nil) 1454 if err != nil { 1455 return nil, err 1456 } 1457 1458 return s.client.Do(ctx, req, nil) 1459 } 1460 1461 // License gets the contents of a repository's license if one is detected. 1462 // 1463 // GitHub API docs: https://docs.github.com/en/rest/licenses#get-the-license-for-a-repository 1464 func (s *RepositoriesService) License(ctx context.Context, owner, repo string) (*RepositoryLicense, *Response, error) { 1465 u := fmt.Sprintf("repos/%v/%v/license", owner, repo) 1466 req, err := s.client.NewRequest("GET", u, nil) 1467 if err != nil { 1468 return nil, nil, err 1469 } 1470 1471 r := &RepositoryLicense{} 1472 resp, err := s.client.Do(ctx, req, r) 1473 if err != nil { 1474 return nil, resp, err 1475 } 1476 1477 return r, resp, nil 1478 } 1479 1480 // GetPullRequestReviewEnforcement gets pull request review enforcement of a protected branch. 1481 // 1482 // GitHub API docs: https://docs.github.com/en/rest/branches/branch-protection#get-pull-request-review-protection 1483 func (s *RepositoriesService) GetPullRequestReviewEnforcement(ctx context.Context, owner, repo, branch string) (*PullRequestReviewsEnforcement, *Response, error) { 1484 u := fmt.Sprintf("repos/%v/%v/branches/%v/protection/required_pull_request_reviews", owner, repo, branch) 1485 req, err := s.client.NewRequest("GET", u, nil) 1486 if err != nil { 1487 return nil, nil, err 1488 } 1489 1490 // TODO: remove custom Accept header when this API fully launches 1491 req.Header.Set("Accept", mediaTypeRequiredApprovingReviewsPreview) 1492 1493 r := new(PullRequestReviewsEnforcement) 1494 resp, err := s.client.Do(ctx, req, r) 1495 if err != nil { 1496 return nil, resp, err 1497 } 1498 1499 return r, resp, nil 1500 } 1501 1502 // UpdatePullRequestReviewEnforcement patches pull request review enforcement of a protected branch. 1503 // It requires admin access and branch protection to be enabled. 1504 // 1505 // GitHub API docs: https://docs.github.com/en/rest/branches/branch-protection#update-pull-request-review-protection 1506 func (s *RepositoriesService) UpdatePullRequestReviewEnforcement(ctx context.Context, owner, repo, branch string, patch *PullRequestReviewsEnforcementUpdate) (*PullRequestReviewsEnforcement, *Response, error) { 1507 u := fmt.Sprintf("repos/%v/%v/branches/%v/protection/required_pull_request_reviews", owner, repo, branch) 1508 req, err := s.client.NewRequest("PATCH", u, patch) 1509 if err != nil { 1510 return nil, nil, err 1511 } 1512 1513 // TODO: remove custom Accept header when this API fully launches 1514 req.Header.Set("Accept", mediaTypeRequiredApprovingReviewsPreview) 1515 1516 r := new(PullRequestReviewsEnforcement) 1517 resp, err := s.client.Do(ctx, req, r) 1518 if err != nil { 1519 return nil, resp, err 1520 } 1521 1522 return r, resp, nil 1523 } 1524 1525 // DisableDismissalRestrictions disables dismissal restrictions of a protected branch. 1526 // It requires admin access and branch protection to be enabled. 1527 // 1528 // GitHub API docs: https://docs.github.com/en/rest/branches/branch-protection#update-pull-request-review-protection 1529 func (s *RepositoriesService) DisableDismissalRestrictions(ctx context.Context, owner, repo, branch string) (*PullRequestReviewsEnforcement, *Response, error) { 1530 u := fmt.Sprintf("repos/%v/%v/branches/%v/protection/required_pull_request_reviews", owner, repo, branch) 1531 1532 data := new(struct { 1533 DismissalRestrictionsRequest `json:"dismissal_restrictions"` 1534 }) 1535 1536 req, err := s.client.NewRequest("PATCH", u, data) 1537 if err != nil { 1538 return nil, nil, err 1539 } 1540 1541 // TODO: remove custom Accept header when this API fully launches 1542 req.Header.Set("Accept", mediaTypeRequiredApprovingReviewsPreview) 1543 1544 r := new(PullRequestReviewsEnforcement) 1545 resp, err := s.client.Do(ctx, req, r) 1546 if err != nil { 1547 return nil, resp, err 1548 } 1549 1550 return r, resp, nil 1551 } 1552 1553 // RemovePullRequestReviewEnforcement removes pull request enforcement of a protected branch. 1554 // 1555 // GitHub API docs: https://docs.github.com/en/rest/branches/branch-protection#delete-pull-request-review-protection 1556 func (s *RepositoriesService) RemovePullRequestReviewEnforcement(ctx context.Context, owner, repo, branch string) (*Response, error) { 1557 u := fmt.Sprintf("repos/%v/%v/branches/%v/protection/required_pull_request_reviews", owner, repo, branch) 1558 req, err := s.client.NewRequest("DELETE", u, nil) 1559 if err != nil { 1560 return nil, err 1561 } 1562 1563 return s.client.Do(ctx, req, nil) 1564 } 1565 1566 // GetAdminEnforcement gets admin enforcement information of a protected branch. 1567 // 1568 // GitHub API docs: https://docs.github.com/en/rest/branches/branch-protection#get-admin-branch-protection 1569 func (s *RepositoriesService) GetAdminEnforcement(ctx context.Context, owner, repo, branch string) (*AdminEnforcement, *Response, error) { 1570 u := fmt.Sprintf("repos/%v/%v/branches/%v/protection/enforce_admins", owner, repo, branch) 1571 req, err := s.client.NewRequest("GET", u, nil) 1572 if err != nil { 1573 return nil, nil, err 1574 } 1575 1576 r := new(AdminEnforcement) 1577 resp, err := s.client.Do(ctx, req, r) 1578 if err != nil { 1579 return nil, resp, err 1580 } 1581 1582 return r, resp, nil 1583 } 1584 1585 // AddAdminEnforcement adds admin enforcement to a protected branch. 1586 // It requires admin access and branch protection to be enabled. 1587 // 1588 // GitHub API docs: https://docs.github.com/en/rest/branches/branch-protection#set-admin-branch-protection 1589 func (s *RepositoriesService) AddAdminEnforcement(ctx context.Context, owner, repo, branch string) (*AdminEnforcement, *Response, error) { 1590 u := fmt.Sprintf("repos/%v/%v/branches/%v/protection/enforce_admins", owner, repo, branch) 1591 req, err := s.client.NewRequest("POST", u, nil) 1592 if err != nil { 1593 return nil, nil, err 1594 } 1595 1596 r := new(AdminEnforcement) 1597 resp, err := s.client.Do(ctx, req, r) 1598 if err != nil { 1599 return nil, resp, err 1600 } 1601 1602 return r, resp, nil 1603 } 1604 1605 // RemoveAdminEnforcement removes admin enforcement from a protected branch. 1606 // 1607 // GitHub API docs: https://docs.github.com/en/rest/branches/branch-protection#delete-admin-branch-protection 1608 func (s *RepositoriesService) RemoveAdminEnforcement(ctx context.Context, owner, repo, branch string) (*Response, error) { 1609 u := fmt.Sprintf("repos/%v/%v/branches/%v/protection/enforce_admins", owner, repo, branch) 1610 req, err := s.client.NewRequest("DELETE", u, nil) 1611 if err != nil { 1612 return nil, err 1613 } 1614 1615 return s.client.Do(ctx, req, nil) 1616 } 1617 1618 // repositoryTopics represents a collection of repository topics. 1619 type repositoryTopics struct { 1620 Names []string `json:"names"` 1621 } 1622 1623 // ListAllTopics lists topics for a repository. 1624 // 1625 // GitHub API docs: https://docs.github.com/en/rest/repos/repos#get-all-repository-topics 1626 func (s *RepositoriesService) ListAllTopics(ctx context.Context, owner, repo string) ([]string, *Response, error) { 1627 u := fmt.Sprintf("repos/%v/%v/topics", owner, repo) 1628 req, err := s.client.NewRequest("GET", u, nil) 1629 if err != nil { 1630 return nil, nil, err 1631 } 1632 1633 // TODO: remove custom Accept header when this API fully launches. 1634 req.Header.Set("Accept", mediaTypeTopicsPreview) 1635 1636 topics := new(repositoryTopics) 1637 resp, err := s.client.Do(ctx, req, topics) 1638 if err != nil { 1639 return nil, resp, err 1640 } 1641 1642 return topics.Names, resp, nil 1643 } 1644 1645 // ReplaceAllTopics replaces all repository topics. 1646 // 1647 // GitHub API docs: https://docs.github.com/en/rest/repos/repos#replace-all-repository-topics 1648 func (s *RepositoriesService) ReplaceAllTopics(ctx context.Context, owner, repo string, topics []string) ([]string, *Response, error) { 1649 u := fmt.Sprintf("repos/%v/%v/topics", owner, repo) 1650 t := &repositoryTopics{ 1651 Names: topics, 1652 } 1653 if t.Names == nil { 1654 t.Names = []string{} 1655 } 1656 req, err := s.client.NewRequest("PUT", u, t) 1657 if err != nil { 1658 return nil, nil, err 1659 } 1660 1661 // TODO: remove custom Accept header when this API fully launches. 1662 req.Header.Set("Accept", mediaTypeTopicsPreview) 1663 1664 t = new(repositoryTopics) 1665 resp, err := s.client.Do(ctx, req, t) 1666 if err != nil { 1667 return nil, resp, err 1668 } 1669 1670 return t.Names, resp, nil 1671 } 1672 1673 // ListApps lists the GitHub apps that have push access to a given protected branch. 1674 // It requires the GitHub apps to have `write` access to the `content` permission. 1675 // 1676 // GitHub API docs: https://docs.github.com/en/rest/branches/branch-protection#get-apps-with-access-to-the-protected-branch 1677 func (s *RepositoriesService) ListApps(ctx context.Context, owner, repo, branch string) ([]*App, *Response, error) { 1678 u := fmt.Sprintf("repos/%v/%v/branches/%v/protection/restrictions/apps", owner, repo, branch) 1679 req, err := s.client.NewRequest("GET", u, nil) 1680 if err != nil { 1681 return nil, nil, err 1682 } 1683 1684 var apps []*App 1685 resp, err := s.client.Do(ctx, req, &apps) 1686 if err != nil { 1687 return nil, resp, err 1688 } 1689 1690 return apps, resp, nil 1691 } 1692 1693 // ReplaceAppRestrictions replaces the apps that have push access to a given protected branch. 1694 // It removes all apps that previously had push access and grants push access to the new list of apps. 1695 // It requires the GitHub apps to have `write` access to the `content` permission. 1696 // 1697 // Note: The list of users, apps, and teams in total is limited to 100 items. 1698 // 1699 // GitHub API docs: https://docs.github.com/en/rest/branches/branch-protection#set-app-access-restrictions 1700 func (s *RepositoriesService) ReplaceAppRestrictions(ctx context.Context, owner, repo, branch string, slug []string) ([]*App, *Response, error) { 1701 u := fmt.Sprintf("repos/%v/%v/branches/%v/protection/restrictions/apps", owner, repo, branch) 1702 req, err := s.client.NewRequest("PUT", u, slug) 1703 if err != nil { 1704 return nil, nil, err 1705 } 1706 1707 var apps []*App 1708 resp, err := s.client.Do(ctx, req, &apps) 1709 if err != nil { 1710 return nil, resp, err 1711 } 1712 1713 return apps, resp, nil 1714 } 1715 1716 // AddAppRestrictions grants the specified apps push access to a given protected branch. 1717 // It requires the GitHub apps to have `write` access to the `content` permission. 1718 // 1719 // Note: The list of users, apps, and teams in total is limited to 100 items. 1720 // 1721 // GitHub API docs: https://docs.github.com/en/rest/branches/branch-protection#add-app-access-restrictions 1722 func (s *RepositoriesService) AddAppRestrictions(ctx context.Context, owner, repo, branch string, slug []string) ([]*App, *Response, error) { 1723 u := fmt.Sprintf("repos/%v/%v/branches/%v/protection/restrictions/apps", owner, repo, branch) 1724 req, err := s.client.NewRequest("POST", u, slug) 1725 if err != nil { 1726 return nil, nil, err 1727 } 1728 1729 var apps []*App 1730 resp, err := s.client.Do(ctx, req, &apps) 1731 if err != nil { 1732 return nil, resp, err 1733 } 1734 1735 return apps, resp, nil 1736 } 1737 1738 // RemoveAppRestrictions removes the ability of an app to push to this branch. 1739 // It requires the GitHub apps to have `write` access to the `content` permission. 1740 // 1741 // Note: The list of users, apps, and teams in total is limited to 100 items. 1742 // 1743 // GitHub API docs: https://docs.github.com/en/rest/branches/branch-protection#remove-app-access-restrictions 1744 func (s *RepositoriesService) RemoveAppRestrictions(ctx context.Context, owner, repo, branch string, slug []string) ([]*App, *Response, error) { 1745 u := fmt.Sprintf("repos/%v/%v/branches/%v/protection/restrictions/apps", owner, repo, branch) 1746 req, err := s.client.NewRequest("DELETE", u, slug) 1747 if err != nil { 1748 return nil, nil, err 1749 } 1750 1751 var apps []*App 1752 resp, err := s.client.Do(ctx, req, &apps) 1753 if err != nil { 1754 return nil, resp, err 1755 } 1756 1757 return apps, resp, nil 1758 } 1759 1760 // TransferRequest represents a request to transfer a repository. 1761 type TransferRequest struct { 1762 NewOwner string `json:"new_owner"` 1763 TeamID []int64 `json:"team_ids,omitempty"` 1764 } 1765 1766 // Transfer transfers a repository from one account or organization to another. 1767 // 1768 // This method might return an *AcceptedError and a status code of 1769 // 202. This is because this is the status that GitHub returns to signify that 1770 // it has now scheduled the transfer of the repository in a background task. 1771 // A follow up request, after a delay of a second or so, should result 1772 // in a successful request. 1773 // 1774 // GitHub API docs: https://docs.github.com/en/rest/repos/repos#transfer-a-repository 1775 func (s *RepositoriesService) Transfer(ctx context.Context, owner, repo string, transfer TransferRequest) (*Repository, *Response, error) { 1776 u := fmt.Sprintf("repos/%v/%v/transfer", owner, repo) 1777 1778 req, err := s.client.NewRequest("POST", u, &transfer) 1779 if err != nil { 1780 return nil, nil, err 1781 } 1782 1783 r := new(Repository) 1784 resp, err := s.client.Do(ctx, req, r) 1785 if err != nil { 1786 return nil, resp, err 1787 } 1788 1789 return r, resp, nil 1790 } 1791 1792 // DispatchRequestOptions represents a request to trigger a repository_dispatch event. 1793 type DispatchRequestOptions struct { 1794 // EventType is a custom webhook event name. (Required.) 1795 EventType string `json:"event_type"` 1796 // ClientPayload is a custom JSON payload with extra information about the webhook event. 1797 // Defaults to an empty JSON object. 1798 ClientPayload *json.RawMessage `json:"client_payload,omitempty"` 1799 } 1800 1801 // Dispatch triggers a repository_dispatch event in a GitHub Actions workflow. 1802 // 1803 // GitHub API docs: https://docs.github.com/en/rest/repos/repos#create-a-repository-dispatch-event 1804 func (s *RepositoriesService) Dispatch(ctx context.Context, owner, repo string, opts DispatchRequestOptions) (*Repository, *Response, error) { 1805 u := fmt.Sprintf("repos/%v/%v/dispatches", owner, repo) 1806 1807 req, err := s.client.NewRequest("POST", u, &opts) 1808 if err != nil { 1809 return nil, nil, err 1810 } 1811 1812 r := new(Repository) 1813 resp, err := s.client.Do(ctx, req, r) 1814 if err != nil { 1815 return nil, resp, err 1816 } 1817 1818 return r, resp, nil 1819 } 1820 1821 // isBranchNotProtected determines whether a branch is not protected 1822 // based on the error message returned by GitHub API. 1823 func isBranchNotProtected(err error) bool { 1824 errorResponse, ok := err.(*ErrorResponse) 1825 return ok && errorResponse.Message == githubBranchNotProtected 1826 }