github.com/google/go-github/v64@v64.0.0/github/projects.go (about)

     1  // Copyright 2016 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  	"fmt"
    11  )
    12  
    13  // ProjectsService provides access to the projects functions in the
    14  // GitHub API.
    15  //
    16  // GitHub API docs: https://docs.github.com/rest/projects
    17  type ProjectsService service
    18  
    19  // Project represents a GitHub Project.
    20  type Project struct {
    21  	ID                     *int64     `json:"id,omitempty"`
    22  	URL                    *string    `json:"url,omitempty"`
    23  	HTMLURL                *string    `json:"html_url,omitempty"`
    24  	ColumnsURL             *string    `json:"columns_url,omitempty"`
    25  	OwnerURL               *string    `json:"owner_url,omitempty"`
    26  	Name                   *string    `json:"name,omitempty"`
    27  	Body                   *string    `json:"body,omitempty"`
    28  	Number                 *int       `json:"number,omitempty"`
    29  	State                  *string    `json:"state,omitempty"`
    30  	CreatedAt              *Timestamp `json:"created_at,omitempty"`
    31  	UpdatedAt              *Timestamp `json:"updated_at,omitempty"`
    32  	NodeID                 *string    `json:"node_id,omitempty"`
    33  	OrganizationPermission *string    `json:"organization_permission,omitempty"`
    34  	Private                *bool      `json:"private,omitempty"`
    35  
    36  	// The User object that generated the project.
    37  	Creator *User `json:"creator,omitempty"`
    38  }
    39  
    40  func (p Project) String() string {
    41  	return Stringify(p)
    42  }
    43  
    44  // GetProject gets a GitHub Project for a repo.
    45  //
    46  // GitHub API docs: https://docs.github.com/rest/projects/projects#get-a-project
    47  //
    48  //meta:operation GET /projects/{project_id}
    49  func (s *ProjectsService) GetProject(ctx context.Context, id int64) (*Project, *Response, error) {
    50  	u := fmt.Sprintf("projects/%v", id)
    51  	req, err := s.client.NewRequest("GET", u, nil)
    52  	if err != nil {
    53  		return nil, nil, err
    54  	}
    55  
    56  	// TODO: remove custom Accept headers when APIs fully launch.
    57  	req.Header.Set("Accept", mediaTypeProjectsPreview)
    58  
    59  	project := &Project{}
    60  	resp, err := s.client.Do(ctx, req, project)
    61  	if err != nil {
    62  		return nil, resp, err
    63  	}
    64  
    65  	return project, resp, nil
    66  }
    67  
    68  // ProjectOptions specifies the parameters to the
    69  // RepositoriesService.CreateProject and
    70  // ProjectsService.UpdateProject methods.
    71  type ProjectOptions struct {
    72  	// The name of the project. (Required for creation; optional for update.)
    73  	Name *string `json:"name,omitempty"`
    74  	// The body of the project. (Optional.)
    75  	Body *string `json:"body,omitempty"`
    76  
    77  	// The following field(s) are only applicable for update.
    78  	// They should be left with zero values for creation.
    79  
    80  	// State of the project. Either "open" or "closed". (Optional.)
    81  	State *string `json:"state,omitempty"`
    82  	// The permission level that all members of the project's organization
    83  	// will have on this project.
    84  	// Setting the organization permission is only available
    85  	// for organization projects. (Optional.)
    86  	OrganizationPermission *string `json:"organization_permission,omitempty"`
    87  	// Sets visibility of the project within the organization.
    88  	// Setting visibility is only available
    89  	// for organization projects.(Optional.)
    90  	Private *bool `json:"private,omitempty"`
    91  }
    92  
    93  // UpdateProject updates a repository project.
    94  //
    95  // GitHub API docs: https://docs.github.com/rest/projects/projects#update-a-project
    96  //
    97  //meta:operation PATCH /projects/{project_id}
    98  func (s *ProjectsService) UpdateProject(ctx context.Context, id int64, opts *ProjectOptions) (*Project, *Response, error) {
    99  	u := fmt.Sprintf("projects/%v", id)
   100  	req, err := s.client.NewRequest("PATCH", u, opts)
   101  	if err != nil {
   102  		return nil, nil, err
   103  	}
   104  
   105  	// TODO: remove custom Accept headers when APIs fully launch.
   106  	req.Header.Set("Accept", mediaTypeProjectsPreview)
   107  
   108  	project := &Project{}
   109  	resp, err := s.client.Do(ctx, req, project)
   110  	if err != nil {
   111  		return nil, resp, err
   112  	}
   113  
   114  	return project, resp, nil
   115  }
   116  
   117  // DeleteProject deletes a GitHub Project from a repository.
   118  //
   119  // GitHub API docs: https://docs.github.com/rest/projects/projects#delete-a-project
   120  //
   121  //meta:operation DELETE /projects/{project_id}
   122  func (s *ProjectsService) DeleteProject(ctx context.Context, id int64) (*Response, error) {
   123  	u := fmt.Sprintf("projects/%v", id)
   124  	req, err := s.client.NewRequest("DELETE", u, nil)
   125  	if err != nil {
   126  		return nil, err
   127  	}
   128  
   129  	// TODO: remove custom Accept header when this API fully launches.
   130  	req.Header.Set("Accept", mediaTypeProjectsPreview)
   131  
   132  	return s.client.Do(ctx, req, nil)
   133  }
   134  
   135  // ProjectColumn represents a column of a GitHub Project.
   136  //
   137  // GitHub API docs: https://docs.github.com/rest/repos/projects/
   138  type ProjectColumn struct {
   139  	ID         *int64     `json:"id,omitempty"`
   140  	Name       *string    `json:"name,omitempty"`
   141  	URL        *string    `json:"url,omitempty"`
   142  	ProjectURL *string    `json:"project_url,omitempty"`
   143  	CardsURL   *string    `json:"cards_url,omitempty"`
   144  	CreatedAt  *Timestamp `json:"created_at,omitempty"`
   145  	UpdatedAt  *Timestamp `json:"updated_at,omitempty"`
   146  	NodeID     *string    `json:"node_id,omitempty"`
   147  }
   148  
   149  // ListProjectColumns lists the columns of a GitHub Project for a repo.
   150  //
   151  // GitHub API docs: https://docs.github.com/rest/projects/columns#list-project-columns
   152  //
   153  //meta:operation GET /projects/{project_id}/columns
   154  func (s *ProjectsService) ListProjectColumns(ctx context.Context, projectID int64, opts *ListOptions) ([]*ProjectColumn, *Response, error) {
   155  	u := fmt.Sprintf("projects/%v/columns", projectID)
   156  	u, err := addOptions(u, opts)
   157  	if err != nil {
   158  		return nil, nil, err
   159  	}
   160  
   161  	req, err := s.client.NewRequest("GET", u, nil)
   162  	if err != nil {
   163  		return nil, nil, err
   164  	}
   165  
   166  	// TODO: remove custom Accept headers when APIs fully launch.
   167  	req.Header.Set("Accept", mediaTypeProjectsPreview)
   168  
   169  	columns := []*ProjectColumn{}
   170  	resp, err := s.client.Do(ctx, req, &columns)
   171  	if err != nil {
   172  		return nil, resp, err
   173  	}
   174  
   175  	return columns, resp, nil
   176  }
   177  
   178  // GetProjectColumn gets a column of a GitHub Project for a repo.
   179  //
   180  // GitHub API docs: https://docs.github.com/rest/projects/columns#get-a-project-column
   181  //
   182  //meta:operation GET /projects/columns/{column_id}
   183  func (s *ProjectsService) GetProjectColumn(ctx context.Context, id int64) (*ProjectColumn, *Response, error) {
   184  	u := fmt.Sprintf("projects/columns/%v", id)
   185  	req, err := s.client.NewRequest("GET", u, nil)
   186  	if err != nil {
   187  		return nil, nil, err
   188  	}
   189  
   190  	// TODO: remove custom Accept headers when APIs fully launch.
   191  	req.Header.Set("Accept", mediaTypeProjectsPreview)
   192  
   193  	column := &ProjectColumn{}
   194  	resp, err := s.client.Do(ctx, req, column)
   195  	if err != nil {
   196  		return nil, resp, err
   197  	}
   198  
   199  	return column, resp, nil
   200  }
   201  
   202  // ProjectColumnOptions specifies the parameters to the
   203  // ProjectsService.CreateProjectColumn and
   204  // ProjectsService.UpdateProjectColumn methods.
   205  type ProjectColumnOptions struct {
   206  	// The name of the project column. (Required for creation and update.)
   207  	Name string `json:"name"`
   208  }
   209  
   210  // CreateProjectColumn creates a column for the specified (by number) project.
   211  //
   212  // GitHub API docs: https://docs.github.com/rest/projects/columns#create-a-project-column
   213  //
   214  //meta:operation POST /projects/{project_id}/columns
   215  func (s *ProjectsService) CreateProjectColumn(ctx context.Context, projectID int64, opts *ProjectColumnOptions) (*ProjectColumn, *Response, error) {
   216  	u := fmt.Sprintf("projects/%v/columns", projectID)
   217  	req, err := s.client.NewRequest("POST", u, opts)
   218  	if err != nil {
   219  		return nil, nil, err
   220  	}
   221  
   222  	// TODO: remove custom Accept headers when APIs fully launch.
   223  	req.Header.Set("Accept", mediaTypeProjectsPreview)
   224  
   225  	column := &ProjectColumn{}
   226  	resp, err := s.client.Do(ctx, req, column)
   227  	if err != nil {
   228  		return nil, resp, err
   229  	}
   230  
   231  	return column, resp, nil
   232  }
   233  
   234  // UpdateProjectColumn updates a column of a GitHub Project.
   235  //
   236  // GitHub API docs: https://docs.github.com/rest/projects/columns#update-an-existing-project-column
   237  //
   238  //meta:operation PATCH /projects/columns/{column_id}
   239  func (s *ProjectsService) UpdateProjectColumn(ctx context.Context, columnID int64, opts *ProjectColumnOptions) (*ProjectColumn, *Response, error) {
   240  	u := fmt.Sprintf("projects/columns/%v", columnID)
   241  	req, err := s.client.NewRequest("PATCH", u, opts)
   242  	if err != nil {
   243  		return nil, nil, err
   244  	}
   245  
   246  	// TODO: remove custom Accept headers when APIs fully launch.
   247  	req.Header.Set("Accept", mediaTypeProjectsPreview)
   248  
   249  	column := &ProjectColumn{}
   250  	resp, err := s.client.Do(ctx, req, column)
   251  	if err != nil {
   252  		return nil, resp, err
   253  	}
   254  
   255  	return column, resp, nil
   256  }
   257  
   258  // DeleteProjectColumn deletes a column from a GitHub Project.
   259  //
   260  // GitHub API docs: https://docs.github.com/rest/projects/columns#delete-a-project-column
   261  //
   262  //meta:operation DELETE /projects/columns/{column_id}
   263  func (s *ProjectsService) DeleteProjectColumn(ctx context.Context, columnID int64) (*Response, error) {
   264  	u := fmt.Sprintf("projects/columns/%v", columnID)
   265  	req, err := s.client.NewRequest("DELETE", u, nil)
   266  	if err != nil {
   267  		return nil, err
   268  	}
   269  
   270  	// TODO: remove custom Accept header when this API fully launches.
   271  	req.Header.Set("Accept", mediaTypeProjectsPreview)
   272  
   273  	return s.client.Do(ctx, req, nil)
   274  }
   275  
   276  // ProjectColumnMoveOptions specifies the parameters to the
   277  // ProjectsService.MoveProjectColumn method.
   278  type ProjectColumnMoveOptions struct {
   279  	// Position can be one of "first", "last", or "after:<column-id>", where
   280  	// <column-id> is the ID of a column in the same project. (Required.)
   281  	Position string `json:"position"`
   282  }
   283  
   284  // MoveProjectColumn moves a column within a GitHub Project.
   285  //
   286  // GitHub API docs: https://docs.github.com/rest/projects/columns#move-a-project-column
   287  //
   288  //meta:operation POST /projects/columns/{column_id}/moves
   289  func (s *ProjectsService) MoveProjectColumn(ctx context.Context, columnID int64, opts *ProjectColumnMoveOptions) (*Response, error) {
   290  	u := fmt.Sprintf("projects/columns/%v/moves", columnID)
   291  	req, err := s.client.NewRequest("POST", u, opts)
   292  	if err != nil {
   293  		return nil, err
   294  	}
   295  
   296  	// TODO: remove custom Accept header when this API fully launches.
   297  	req.Header.Set("Accept", mediaTypeProjectsPreview)
   298  
   299  	return s.client.Do(ctx, req, nil)
   300  }
   301  
   302  // ProjectCard represents a card in a column of a GitHub Project.
   303  //
   304  // GitHub API docs: https://docs.github.com/rest/projects/cards/#get-a-project-card
   305  type ProjectCard struct {
   306  	URL        *string    `json:"url,omitempty"`
   307  	ColumnURL  *string    `json:"column_url,omitempty"`
   308  	ContentURL *string    `json:"content_url,omitempty"`
   309  	ID         *int64     `json:"id,omitempty"`
   310  	Note       *string    `json:"note,omitempty"`
   311  	Creator    *User      `json:"creator,omitempty"`
   312  	CreatedAt  *Timestamp `json:"created_at,omitempty"`
   313  	UpdatedAt  *Timestamp `json:"updated_at,omitempty"`
   314  	NodeID     *string    `json:"node_id,omitempty"`
   315  	Archived   *bool      `json:"archived,omitempty"`
   316  
   317  	// The following fields are only populated by Webhook events.
   318  	ColumnID *int64 `json:"column_id,omitempty"`
   319  
   320  	// The following fields are only populated by Events API.
   321  	ProjectID          *int64  `json:"project_id,omitempty"`
   322  	ProjectURL         *string `json:"project_url,omitempty"`
   323  	ColumnName         *string `json:"column_name,omitempty"`
   324  	PreviousColumnName *string `json:"previous_column_name,omitempty"` // Populated in "moved_columns_in_project" event deliveries.
   325  }
   326  
   327  // ProjectCardListOptions specifies the optional parameters to the
   328  // ProjectsService.ListProjectCards method.
   329  type ProjectCardListOptions struct {
   330  	// ArchivedState is used to list all, archived, or not_archived project cards.
   331  	// Defaults to not_archived when you omit this parameter.
   332  	ArchivedState *string `url:"archived_state,omitempty"`
   333  
   334  	ListOptions
   335  }
   336  
   337  // ListProjectCards lists the cards in a column of a GitHub Project.
   338  //
   339  // GitHub API docs: https://docs.github.com/rest/projects/cards#list-project-cards
   340  //
   341  //meta:operation GET /projects/columns/{column_id}/cards
   342  func (s *ProjectsService) ListProjectCards(ctx context.Context, columnID int64, opts *ProjectCardListOptions) ([]*ProjectCard, *Response, error) {
   343  	u := fmt.Sprintf("projects/columns/%v/cards", columnID)
   344  	u, err := addOptions(u, opts)
   345  	if err != nil {
   346  		return nil, nil, err
   347  	}
   348  
   349  	req, err := s.client.NewRequest("GET", u, nil)
   350  	if err != nil {
   351  		return nil, nil, err
   352  	}
   353  
   354  	// TODO: remove custom Accept headers when APIs fully launch.
   355  	req.Header.Set("Accept", mediaTypeProjectsPreview)
   356  
   357  	cards := []*ProjectCard{}
   358  	resp, err := s.client.Do(ctx, req, &cards)
   359  	if err != nil {
   360  		return nil, resp, err
   361  	}
   362  
   363  	return cards, resp, nil
   364  }
   365  
   366  // GetProjectCard gets a card in a column of a GitHub Project.
   367  //
   368  // GitHub API docs: https://docs.github.com/rest/projects/cards#get-a-project-card
   369  //
   370  //meta:operation GET /projects/columns/cards/{card_id}
   371  func (s *ProjectsService) GetProjectCard(ctx context.Context, cardID int64) (*ProjectCard, *Response, error) {
   372  	u := fmt.Sprintf("projects/columns/cards/%v", cardID)
   373  	req, err := s.client.NewRequest("GET", u, nil)
   374  	if err != nil {
   375  		return nil, nil, err
   376  	}
   377  
   378  	// TODO: remove custom Accept headers when APIs fully launch.
   379  	req.Header.Set("Accept", mediaTypeProjectsPreview)
   380  
   381  	card := &ProjectCard{}
   382  	resp, err := s.client.Do(ctx, req, card)
   383  	if err != nil {
   384  		return nil, resp, err
   385  	}
   386  
   387  	return card, resp, nil
   388  }
   389  
   390  // ProjectCardOptions specifies the parameters to the
   391  // ProjectsService.CreateProjectCard and
   392  // ProjectsService.UpdateProjectCard methods.
   393  type ProjectCardOptions struct {
   394  	// The note of the card. Note and ContentID are mutually exclusive.
   395  	Note string `json:"note,omitempty"`
   396  	// The ID (not Number) of the Issue to associate with this card.
   397  	// Note and ContentID are mutually exclusive.
   398  	ContentID int64 `json:"content_id,omitempty"`
   399  	// The type of content to associate with this card. Possible values are: "Issue" and "PullRequest".
   400  	ContentType string `json:"content_type,omitempty"`
   401  	// Use true to archive a project card.
   402  	// Specify false if you need to restore a previously archived project card.
   403  	Archived *bool `json:"archived,omitempty"`
   404  }
   405  
   406  // CreateProjectCard creates a card in the specified column of a GitHub Project.
   407  //
   408  // GitHub API docs: https://docs.github.com/rest/projects/cards#create-a-project-card
   409  //
   410  //meta:operation POST /projects/columns/{column_id}/cards
   411  func (s *ProjectsService) CreateProjectCard(ctx context.Context, columnID int64, opts *ProjectCardOptions) (*ProjectCard, *Response, error) {
   412  	u := fmt.Sprintf("projects/columns/%v/cards", columnID)
   413  	req, err := s.client.NewRequest("POST", u, opts)
   414  	if err != nil {
   415  		return nil, nil, err
   416  	}
   417  
   418  	// TODO: remove custom Accept headers when APIs fully launch.
   419  	req.Header.Set("Accept", mediaTypeProjectsPreview)
   420  
   421  	card := &ProjectCard{}
   422  	resp, err := s.client.Do(ctx, req, card)
   423  	if err != nil {
   424  		return nil, resp, err
   425  	}
   426  
   427  	return card, resp, nil
   428  }
   429  
   430  // UpdateProjectCard updates a card of a GitHub Project.
   431  //
   432  // GitHub API docs: https://docs.github.com/rest/projects/cards#update-an-existing-project-card
   433  //
   434  //meta:operation PATCH /projects/columns/cards/{card_id}
   435  func (s *ProjectsService) UpdateProjectCard(ctx context.Context, cardID int64, opts *ProjectCardOptions) (*ProjectCard, *Response, error) {
   436  	u := fmt.Sprintf("projects/columns/cards/%v", cardID)
   437  	req, err := s.client.NewRequest("PATCH", u, opts)
   438  	if err != nil {
   439  		return nil, nil, err
   440  	}
   441  
   442  	// TODO: remove custom Accept headers when APIs fully launch.
   443  	req.Header.Set("Accept", mediaTypeProjectsPreview)
   444  
   445  	card := &ProjectCard{}
   446  	resp, err := s.client.Do(ctx, req, card)
   447  	if err != nil {
   448  		return nil, resp, err
   449  	}
   450  
   451  	return card, resp, nil
   452  }
   453  
   454  // DeleteProjectCard deletes a card from a GitHub Project.
   455  //
   456  // GitHub API docs: https://docs.github.com/rest/projects/cards#delete-a-project-card
   457  //
   458  //meta:operation DELETE /projects/columns/cards/{card_id}
   459  func (s *ProjectsService) DeleteProjectCard(ctx context.Context, cardID int64) (*Response, error) {
   460  	u := fmt.Sprintf("projects/columns/cards/%v", cardID)
   461  	req, err := s.client.NewRequest("DELETE", u, nil)
   462  	if err != nil {
   463  		return nil, err
   464  	}
   465  
   466  	// TODO: remove custom Accept header when this API fully launches.
   467  	req.Header.Set("Accept", mediaTypeProjectsPreview)
   468  
   469  	return s.client.Do(ctx, req, nil)
   470  }
   471  
   472  // ProjectCardMoveOptions specifies the parameters to the
   473  // ProjectsService.MoveProjectCard method.
   474  type ProjectCardMoveOptions struct {
   475  	// Position can be one of "top", "bottom", or "after:<card-id>", where
   476  	// <card-id> is the ID of a card in the same project.
   477  	Position string `json:"position"`
   478  	// ColumnID is the ID of a column in the same project. Note that ColumnID
   479  	// is required when using Position "after:<card-id>" when that card is in
   480  	// another column; otherwise it is optional.
   481  	ColumnID int64 `json:"column_id,omitempty"`
   482  }
   483  
   484  // MoveProjectCard moves a card within a GitHub Project.
   485  //
   486  // GitHub API docs: https://docs.github.com/rest/projects/cards#move-a-project-card
   487  //
   488  //meta:operation POST /projects/columns/cards/{card_id}/moves
   489  func (s *ProjectsService) MoveProjectCard(ctx context.Context, cardID int64, opts *ProjectCardMoveOptions) (*Response, error) {
   490  	u := fmt.Sprintf("projects/columns/cards/%v/moves", cardID)
   491  	req, err := s.client.NewRequest("POST", u, opts)
   492  	if err != nil {
   493  		return nil, err
   494  	}
   495  
   496  	// TODO: remove custom Accept header when this API fully launches.
   497  	req.Header.Set("Accept", mediaTypeProjectsPreview)
   498  
   499  	return s.client.Do(ctx, req, nil)
   500  }
   501  
   502  // ProjectCollaboratorOptions specifies the optional parameters to the
   503  // ProjectsService.AddProjectCollaborator method.
   504  type ProjectCollaboratorOptions struct {
   505  	// Permission specifies the permission to grant to the collaborator.
   506  	// Possible values are:
   507  	//     "read" - can read, but not write to or administer this project.
   508  	//     "write" - can read and write, but not administer this project.
   509  	//     "admin" - can read, write and administer this project.
   510  	//
   511  	// Default value is "write"
   512  	Permission *string `json:"permission,omitempty"`
   513  }
   514  
   515  // AddProjectCollaborator adds a collaborator to an organization project and sets
   516  // their permission level. You must be an organization owner or a project admin to add a collaborator.
   517  //
   518  // GitHub API docs: https://docs.github.com/rest/projects/collaborators#add-project-collaborator
   519  //
   520  //meta:operation PUT /projects/{project_id}/collaborators/{username}
   521  func (s *ProjectsService) AddProjectCollaborator(ctx context.Context, id int64, username string, opts *ProjectCollaboratorOptions) (*Response, error) {
   522  	u := fmt.Sprintf("projects/%v/collaborators/%v", id, username)
   523  	req, err := s.client.NewRequest("PUT", u, opts)
   524  	if err != nil {
   525  		return nil, err
   526  	}
   527  
   528  	// TODO: remove custom Accept header when this API fully launches.
   529  	req.Header.Set("Accept", mediaTypeProjectsPreview)
   530  
   531  	return s.client.Do(ctx, req, nil)
   532  }
   533  
   534  // RemoveProjectCollaborator removes a collaborator from an organization project.
   535  // You must be an organization owner or a project admin to remove a collaborator.
   536  //
   537  // GitHub API docs: https://docs.github.com/rest/projects/collaborators#remove-user-as-a-collaborator
   538  //
   539  //meta:operation DELETE /projects/{project_id}/collaborators/{username}
   540  func (s *ProjectsService) RemoveProjectCollaborator(ctx context.Context, id int64, username string) (*Response, error) {
   541  	u := fmt.Sprintf("projects/%v/collaborators/%v", id, username)
   542  	req, err := s.client.NewRequest("DELETE", u, nil)
   543  	if err != nil {
   544  		return nil, err
   545  	}
   546  
   547  	// TODO: remove custom Accept header when this API fully launches.
   548  	req.Header.Set("Accept", mediaTypeProjectsPreview)
   549  
   550  	return s.client.Do(ctx, req, nil)
   551  }
   552  
   553  // ListCollaboratorOptions specifies the optional parameters to the
   554  // ProjectsService.ListProjectCollaborators method.
   555  type ListCollaboratorOptions struct {
   556  	// Affiliation specifies how collaborators should be filtered by their affiliation.
   557  	// Possible values are:
   558  	//     "outside" - All outside collaborators of an organization-owned repository
   559  	//     "direct" - All collaborators with permissions to an organization-owned repository,
   560  	//              regardless of organization membership status
   561  	//     "all" - All collaborators the authenticated user can see
   562  	//
   563  	// Default value is "all".
   564  	Affiliation *string `url:"affiliation,omitempty"`
   565  
   566  	ListOptions
   567  }
   568  
   569  // ListProjectCollaborators lists the collaborators for an organization project. For a project,
   570  // the list of collaborators includes outside collaborators, organization members that are direct
   571  // collaborators, organization members with access through team memberships, organization members
   572  // with access through default organization permissions, and organization owners. You must be an
   573  // organization owner or a project admin to list collaborators.
   574  //
   575  // GitHub API docs: https://docs.github.com/rest/projects/collaborators#list-project-collaborators
   576  //
   577  //meta:operation GET /projects/{project_id}/collaborators
   578  func (s *ProjectsService) ListProjectCollaborators(ctx context.Context, id int64, opts *ListCollaboratorOptions) ([]*User, *Response, error) {
   579  	u := fmt.Sprintf("projects/%v/collaborators", id)
   580  	u, err := addOptions(u, opts)
   581  	if err != nil {
   582  		return nil, nil, err
   583  	}
   584  
   585  	req, err := s.client.NewRequest("GET", u, nil)
   586  	if err != nil {
   587  		return nil, nil, err
   588  	}
   589  
   590  	// TODO: remove custom Accept header when this API fully launches.
   591  	req.Header.Set("Accept", mediaTypeProjectsPreview)
   592  
   593  	var users []*User
   594  	resp, err := s.client.Do(ctx, req, &users)
   595  	if err != nil {
   596  		return nil, resp, err
   597  	}
   598  
   599  	return users, resp, nil
   600  }
   601  
   602  // ProjectPermissionLevel represents the permission level an organization
   603  // member has for a given project.
   604  type ProjectPermissionLevel struct {
   605  	// Possible values: "admin", "write", "read", "none"
   606  	Permission *string `json:"permission,omitempty"`
   607  
   608  	User *User `json:"user,omitempty"`
   609  }
   610  
   611  // ReviewProjectCollaboratorPermission returns the collaborator's permission level for an organization
   612  // project. Possible values for the permission key: "admin", "write", "read", "none".
   613  // You must be an organization owner or a project admin to review a user's permission level.
   614  //
   615  // GitHub API docs: https://docs.github.com/rest/projects/collaborators#get-project-permission-for-a-user
   616  //
   617  //meta:operation GET /projects/{project_id}/collaborators/{username}/permission
   618  func (s *ProjectsService) ReviewProjectCollaboratorPermission(ctx context.Context, id int64, username string) (*ProjectPermissionLevel, *Response, error) {
   619  	u := fmt.Sprintf("projects/%v/collaborators/%v/permission", id, username)
   620  	req, err := s.client.NewRequest("GET", u, nil)
   621  	if err != nil {
   622  		return nil, nil, err
   623  	}
   624  
   625  	// TODO: remove custom Accept header when this API fully launches.
   626  	req.Header.Set("Accept", mediaTypeProjectsPreview)
   627  
   628  	ppl := new(ProjectPermissionLevel)
   629  	resp, err := s.client.Do(ctx, req, ppl)
   630  	if err != nil {
   631  		return nil, resp, err
   632  	}
   633  	return ppl, resp, nil
   634  }