Skip to content

Commit 8657c38

Browse files
fix!: Fix field selection and bugs in ProjectsV2 GET endpoints (#3809)
BREAKING CHANGE: `UpdateProjectItemOptions.Field` is now `[]*ProjectV2FieldUpdate`.
1 parent 3959138 commit 8657c38

File tree

5 files changed

+367
-73
lines changed

5 files changed

+367
-73
lines changed

github/event_types.go

Lines changed: 34 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -1148,20 +1148,42 @@ type FieldValue struct {
11481148
To json.RawMessage `json:"to,omitempty"`
11491149
}
11501150

1151+
// ProjectV2ItemFieldValue represents a field value of a project item.
1152+
type ProjectV2ItemFieldValue struct {
1153+
ID *int64 `json:"id,omitempty"`
1154+
Name string `json:"name,omitempty"`
1155+
DataType string `json:"data_type,omitempty"`
1156+
// Value set for the field. The type depends on the field type:
1157+
// - text: string
1158+
// - number: float64
1159+
// - date: string (ISO 8601 date format, e.g. "2023-06-23") or null
1160+
// - single_select: object with "id", "name", "color", "description" fields or null
1161+
// - iteration: object with "id", "title", "start_date", "duration" fields or null
1162+
// - title: object with "text" field (read-only, reflects the item's title) or null
1163+
// - assignees: array of user objects with "login", "id", etc. or null
1164+
// - labels: array of label objects with "id", "name", "color", etc. or null
1165+
// - linked_pull_requests: array of pull request objects or null
1166+
// - milestone: milestone object with "id", "title", "description", etc. or null
1167+
// - repository: repository object with "id", "name", "full_name", etc. or null
1168+
// - reviewers: array of user objects or null
1169+
// - status: object with "id", "name", "color", "description" fields (same structure as single_select) or null
1170+
Value any `json:"value,omitempty"`
1171+
}
1172+
11511173
// ProjectV2Item represents an item belonging to a project.
11521174
type ProjectV2Item struct {
1153-
ID *int64 `json:"id,omitempty"`
1154-
NodeID *string `json:"node_id,omitempty"`
1155-
ProjectNodeID *string `json:"project_node_id,omitempty"`
1156-
ContentNodeID *string `json:"content_node_id,omitempty"`
1157-
ProjectURL *string `json:"project_url,omitempty"`
1158-
ContentType *string `json:"content_type,omitempty"`
1159-
Creator *User `json:"creator,omitempty"`
1160-
CreatedAt *Timestamp `json:"created_at,omitempty"`
1161-
UpdatedAt *Timestamp `json:"updated_at,omitempty"`
1162-
ArchivedAt *Timestamp `json:"archived_at,omitempty"`
1163-
ItemURL *string `json:"item_url,omitempty"`
1164-
Fields []*ProjectV2Field `json:"fields,omitempty"`
1175+
ID *int64 `json:"id,omitempty"`
1176+
NodeID *string `json:"node_id,omitempty"`
1177+
ProjectNodeID *string `json:"project_node_id,omitempty"`
1178+
ContentNodeID *string `json:"content_node_id,omitempty"`
1179+
ProjectURL *string `json:"project_url,omitempty"`
1180+
ContentType *string `json:"content_type,omitempty"`
1181+
Creator *User `json:"creator,omitempty"`
1182+
CreatedAt *Timestamp `json:"created_at,omitempty"`
1183+
UpdatedAt *Timestamp `json:"updated_at,omitempty"`
1184+
ArchivedAt *Timestamp `json:"archived_at,omitempty"`
1185+
ItemURL *string `json:"item_url,omitempty"`
1186+
Fields []*ProjectV2ItemFieldValue `json:"fields,omitempty"`
11651187
}
11661188

11671189
// PublicEvent is triggered when a private repository is open sourced.

github/github-accessors.go

Lines changed: 39 additions & 15 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

github/github-accessors_test.go

Lines changed: 36 additions & 12 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

github/projects.go

Lines changed: 48 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -74,26 +74,35 @@ type ListProjectsOptions struct {
7474
Query *string `url:"q,omitempty"`
7575
}
7676

77+
// ProjectV2TextContent represents text content in a project field option or iteration.
78+
// It includes both HTML and raw text representations.
79+
//
80+
// GitHub API docs: https://docs.github.com/rest/projects/fields
81+
type ProjectV2TextContent struct {
82+
HTML *string `json:"html,omitempty"`
83+
Raw *string `json:"raw,omitempty"`
84+
}
85+
7786
// ProjectV2FieldOption represents an option for a project field of type single_select or multi_select.
7887
// It defines the available choices that can be selected for dropdown-style fields.
7988
//
8089
// GitHub API docs: https://docs.github.com/rest/projects/fields
8190
type ProjectV2FieldOption struct {
82-
ID *string `json:"id,omitempty"` // The unique identifier for this option.
83-
Name *string `json:"name,omitempty"` // The display name of the option.
84-
Color *string `json:"color,omitempty"` // The color associated with this option (e.g., "blue", "red").
85-
Description *string `json:"description,omitempty"` // An optional description for this option.
91+
ID *string `json:"id,omitempty"` // The unique identifier for this option.
92+
Color *string `json:"color,omitempty"` // The color associated with this option (e.g., "blue", "red").
93+
Description *ProjectV2TextContent `json:"description,omitempty"` // An optional description for this option.
94+
Name *ProjectV2TextContent `json:"name,omitempty"` // The display name of the option.
8695
}
8796

8897
// ProjectV2FieldIteration represents an iteration within a project field of type iteration.
8998
// It defines a specific time-bound period that can be associated with project items.
9099
//
91100
// GitHub API docs: https://docs.github.com/rest/projects/fields
92101
type ProjectV2FieldIteration struct {
93-
ID *string `json:"id,omitempty"` // The unique identifier for the iteration.
94-
Title *string `json:"title,omitempty"` // The title of the iteration.
95-
StartDate *string `json:"start_date,omitempty"` // The start date of the iteration in ISO 8601 format.
96-
Duration *int `json:"duration,omitempty"` // The duration of the iteration in seconds.
102+
ID *string `json:"id,omitempty"` // The unique identifier for the iteration.
103+
Title *ProjectV2TextContent `json:"title,omitempty"` // The title of the iteration.
104+
StartDate *string `json:"start_date,omitempty"` // The start date of the iteration in ISO 8601 format.
105+
Duration *int `json:"duration,omitempty"` // The duration of the iteration in seconds.
97106
}
98107

99108
// ProjectV2FieldConfiguration represents the configuration for a project field of type iteration.
@@ -325,14 +334,31 @@ type AddProjectItemOptions struct {
325334
ID int64 `json:"id,omitempty"`
326335
}
327336

337+
// UpdateProjectV2Field represents a field update for a project item.
338+
//
339+
// GitHub API docs: https://docs.github.com/rest/projects/items#update-project-item-for-organization
340+
type UpdateProjectV2Field struct {
341+
// ID is the field ID to update.
342+
ID int64 `json:"id"`
343+
// Value is the new value to set for the field. The type depends on the field type.
344+
// For text fields: string
345+
// For number fields: float64 or int
346+
// For single_select fields: string (option ID)
347+
// For date fields: string (ISO 8601 date)
348+
// For iteration fields: string (iteration ID)
349+
// Note: Some field types (title, assignees, labels, etc.) are read-only or managed through other API endpoints.
350+
Value any `json:"value"`
351+
}
352+
328353
// UpdateProjectItemOptions represents fields that can be modified for a project item.
329-
// Currently the REST API allows archiving/unarchiving an item (archived boolean).
330-
// This struct can be expanded in the future as the API grows.
354+
// The GitHub API expects either archived status updates or field value updates.
331355
type UpdateProjectItemOptions struct {
332356
// Archived indicates whether the item should be archived (true) or unarchived (false).
357+
// This is used for archive/unarchive operations.
333358
Archived *bool `json:"archived,omitempty"`
334-
// Fields allows updating field values for the item. Each entry supplies a field ID and a value.
335-
Fields []*ProjectV2Field `json:"fields,omitempty"`
359+
// Fields contains field updates to apply to the project item.
360+
// Each entry specifies a field ID and its new value.
361+
Fields []*UpdateProjectV2Field `json:"fields,omitempty"`
336362
}
337363

338364
// ListOrganizationProjectItems lists items for an organization owned project.
@@ -387,7 +413,11 @@ func (s *ProjectsService) AddOrganizationProjectItem(ctx context.Context, org st
387413
//meta:operation GET /orgs/{org}/projectsV2/{project_number}/items/{item_id}
388414
func (s *ProjectsService) GetOrganizationProjectItem(ctx context.Context, org string, projectNumber int, itemID int64, opts *GetProjectItemOptions) (*ProjectV2Item, *Response, error) {
389415
u := fmt.Sprintf("orgs/%v/projectsV2/%v/items/%v", org, projectNumber, itemID)
390-
req, err := s.client.NewRequest("GET", u, opts)
416+
u, err := addOptions(u, opts)
417+
if err != nil {
418+
return nil, nil, err
419+
}
420+
req, err := s.client.NewRequest("GET", u, nil)
391421
if err != nil {
392422
return nil, nil, err
393423
}
@@ -481,7 +511,11 @@ func (s *ProjectsService) AddUserProjectItem(ctx context.Context, username strin
481511
//meta:operation GET /users/{username}/projectsV2/{project_number}/items/{item_id}
482512
func (s *ProjectsService) GetUserProjectItem(ctx context.Context, username string, projectNumber int, itemID int64, opts *GetProjectItemOptions) (*ProjectV2Item, *Response, error) {
483513
u := fmt.Sprintf("users/%v/projectsV2/%v/items/%v", username, projectNumber, itemID)
484-
req, err := s.client.NewRequest("GET", u, opts)
514+
u, err := addOptions(u, opts)
515+
if err != nil {
516+
return nil, nil, err
517+
}
518+
req, err := s.client.NewRequest("GET", u, nil)
485519
if err != nil {
486520
return nil, nil, err
487521
}

0 commit comments

Comments
 (0)