-
Notifications
You must be signed in to change notification settings - Fork 2.2k
Add ProjectsService #3718
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: master
Are you sure you want to change the base?
Add ProjectsService #3718
Changes from 32 commits
775f0f6
74712bd
3a8cf0c
b754eeb
e93ed36
99852cf
7664215
89016d9
2b94765
a4b0a56
696102b
469e03a
2dbe5b4
478ef5a
c34802d
053a9e1
680a0d1
d8696b4
93dd34f
060aaae
65e64f7
d300550
fc5d3cb
9d6bf4b
9f4c89d
3dd69be
275f930
aca15c0
8ee5bc4
0ca0521
fb6e7a8
6d0637f
5cc797e
c6cfe31
c9feeb2
8c985a9
1625c61
a11a2fa
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.
Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.
Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.
Original file line number | Diff line number | Diff line change | ||||
---|---|---|---|---|---|---|
@@ -0,0 +1,218 @@ | ||||||
// Copyright 2025 The go-github AUTHORS. All rights reserved. | ||||||
// | ||||||
// Use of this source code is governed by a BSD-style | ||||||
// license that can be found in the LICENSE file. | ||||||
|
||||||
package github | ||||||
|
||||||
import ( | ||||||
"context" | ||||||
"fmt" | ||||||
) | ||||||
|
||||||
// ProjectsService handles communication with the project V2 | ||||||
// methods of the GitHub API. | ||||||
// | ||||||
// GitHub API docs: https://docs.github.com/rest/projects/projects | ||||||
type ProjectsService service | ||||||
|
||||||
// ProjectV2 represents a v2 project. | ||||||
type ProjectV2 struct { | ||||||
ID *int64 `json:"id,omitempty"` | ||||||
NodeID *string `json:"node_id,omitempty"` | ||||||
Owner *User `json:"owner,omitempty"` | ||||||
Creator *User `json:"creator,omitempty"` | ||||||
Title *string `json:"title,omitempty"` | ||||||
Description *string `json:"description,omitempty"` | ||||||
Public *bool `json:"public,omitempty"` | ||||||
ClosedAt *Timestamp `json:"closed_at,omitempty"` | ||||||
CreatedAt *Timestamp `json:"created_at,omitempty"` | ||||||
UpdatedAt *Timestamp `json:"updated_at,omitempty"` | ||||||
DeletedAt *Timestamp `json:"deleted_at,omitempty"` | ||||||
Number *int `json:"number,omitempty"` | ||||||
ShortDescription *string `json:"short_description,omitempty"` | ||||||
DeletedBy *User `json:"deleted_by,omitempty"` | ||||||
|
||||||
// Fields migrated from the Project (classic) struct: | ||||||
URL *string `json:"url,omitempty"` | ||||||
HTMLURL *string `json:"html_url,omitempty"` | ||||||
ColumnsURL *string `json:"columns_url,omitempty"` | ||||||
OwnerURL *string `json:"owner_url,omitempty"` | ||||||
Name *string `json:"name,omitempty"` | ||||||
Body *string `json:"body,omitempty"` | ||||||
State *string `json:"state,omitempty"` | ||||||
OrganizationPermission *string `json:"organization_permission,omitempty"` | ||||||
Private *bool `json:"private,omitempty"` | ||||||
} | ||||||
|
||||||
func (p ProjectV2) String() string { return Stringify(p) } | ||||||
|
||||||
// ListProjectsPaginationOptions specifies optional parameters to list projects for user / organization. | ||||||
// | ||||||
// Note: Pagination is powered by before/after cursor-style pagination. After the initial call, | ||||||
// inspect the returned *Response. Use resp.After as the opts.After value to request | ||||||
// the next page, and resp.Before as the opts.Before value to request the previous | ||||||
// page. Set either Before or After for a request; if both are | ||||||
// supplied GitHub API will return an error. PerPage controls the number of items | ||||||
// per page (max 100 per GitHub API docs). | ||||||
type ListProjectsPaginationOptions struct { | ||||||
// A cursor, as given in the Link header. If specified, the query only searches for events before this cursor. | ||||||
Before string `url:"before,omitempty"` | ||||||
|
||||||
// A cursor, as given in the Link header. If specified, the query only searches for events after this cursor. | ||||||
After string `url:"after,omitempty"` | ||||||
|
||||||
// For paginated result sets, the number of results to include per page. | ||||||
PerPage int `url:"per_page,omitempty"` | ||||||
} | ||||||
|
||||||
// ListProjectsOptions specifies optional parameters to list projects for user / organization. | ||||||
type ListProjectsOptions struct { | ||||||
ListProjectsPaginationOptions | ||||||
|
||||||
// Q is an optional query string to limit results to projects of the specified type. | ||||||
Query string `url:"q,omitempty"` | ||||||
} | ||||||
|
||||||
// ProjectV2FieldOption represents an option for a project field of type single_select or multi_select. | ||||||
// It defines the available choices that can be selected for dropdown-style fields. | ||||||
// | ||||||
// GitHub API docs: https://docs.github.com/rest/projects/fields | ||||||
type ProjectV2FieldOption struct { | ||||||
ID string `json:"id,omitempty"` | ||||||
// The display name of the option. | ||||||
Name string `json:"name,omitempty"` | ||||||
// The color associated with this option (e.g., "blue", "red"). | ||||||
Color string `json:"color,omitempty"` | ||||||
// An optional description for this option. | ||||||
Description string `json:"description,omitempty"` | ||||||
} | ||||||
|
||||||
// ProjectV2Field represents a field in a GitHub Projects V2 project. | ||||||
// Fields define the structure and data types for project items. | ||||||
// | ||||||
// GitHub API docs: https://docs.github.com/rest/projects/fields | ||||||
type ProjectV2Field struct { | ||||||
ID *int64 `json:"id,omitempty"` | ||||||
NodeID string `json:"node_id,omitempty"` | ||||||
Name string `json:"name,omitempty"` | ||||||
DataType string `json:"dataType,omitempty"` | ||||||
URL string `json:"url,omitempty"` | ||||||
Options []*any `json:"options,omitempty"` | ||||||
CreatedAt *Timestamp `json:"created_at,omitempty"` | ||||||
UpdatedAt *Timestamp `json:"updated_at,omitempty"` | ||||||
} | ||||||
|
||||||
// ListProjectsForOrg lists Projects V2 for an organization. | ||||||
// | ||||||
// GitHub API docs: https://docs.github.com/rest/projects/projects#list-projects-for-organization | ||||||
// | ||||||
//meta:operation GET /orgs/{org}/projectsV2 | ||||||
func (s *ProjectsService) ListProjectsForOrg(ctx context.Context, org string, opts *ListProjectsOptions) ([]*ProjectV2, *Response, error) { | ||||||
u := fmt.Sprintf("orgs/%v/projectsV2", org) | ||||||
u, err := addOptions(u, opts) | ||||||
if err != nil { | ||||||
return nil, nil, err | ||||||
} | ||||||
|
||||||
req, err := s.client.NewRequest("GET", u, nil) | ||||||
if err != nil { | ||||||
return nil, nil, err | ||||||
} | ||||||
|
||||||
var projects []*ProjectV2 | ||||||
resp, err := s.client.Do(ctx, req, &projects) | ||||||
if err != nil { | ||||||
return nil, resp, err | ||||||
} | ||||||
return projects, resp, nil | ||||||
} | ||||||
|
||||||
// GetProjectForOrg gets a Projects V2 project for an organization by ID. | ||||||
// | ||||||
// GitHub API docs: https://docs.github.com/rest/projects/projects#get-project-for-organization | ||||||
// | ||||||
//meta:operation GET /orgs/{org}/projectsV2/{project_number} | ||||||
func (s *ProjectsService) GetProjectForOrg(ctx context.Context, org string, projectNumber int64) (*ProjectV2, *Response, error) { | ||||||
|
func (s *ProjectsService) GetProjectForOrg(ctx context.Context, org string, projectNumber int64) (*ProjectV2, *Response, error) { | |
func (s *ProjectsService) GetProjectForOrg(ctx context.Context, org string, projectNumber int) (*ProjectV2, *Response, error) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Great catch, @alexandear! This made me curious if the Number
property ever might be as huge as an "id" and as far as I can tell, that is not the case, so I do NOT think both should be int64
, but instead both should be int
as you have suggested.
Thoughts, @JoannaaKL?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
In the GH API project's ID is a number
type and project_number
is an integer type. It can hold int64 actually. number
type can hold any number so yes, I think it should be equal to int 64 as it is now. So I don't think they should be set to int.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
In the GH API project's ID is a
number
type andproject_number
is an integer type. It can hold int64 actually.number
type can hold any number so yes, I think it should be equal to int 64 as it is now. So I don't think they should be set to int.
I think we may have a disconnect here.
The ProjectV2 struct
has these fields (among others):
ID *int64 `json:"id,omitempty"`
Number *int `json:"number,omitempty"`
IDs in this repo are (now) always of type int64
because we empirically discovered IDs from GitHub many years ago that did not fit within an int
, so that is our policy moving forward.
Other integers in this repo that we never expect to overflow an int
remain an int
because that is the natural and familiar integer type for Go programmers.
What we are saying here is that we believe the ProjectV2.Number
field should remain an int
and on line 136 above you currently have projectNumber int64
which does not match its corresponding field in the struct.
Therefore, we would like you to change projectNumber int64
to projectNumber int
to make the two of them match.
Does this make sense, @JoannaaKL?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I was talking about types described in the doc https://docs.github.com/en/rest/projects/fields?apiVersion=2022-11-28
projectNumber
there is described as integer
and that type can hold int64 link (correct me if I am wrong).
Uh oh!
There was an error while loading. Please reload this page.