@@ -199,6 +199,355 @@ description.
199199
200200[ Go Doc Comments ] : https://go.dev/doc/comment
201201
202+ ## Code Guidelines
203+
204+ This section documents common code patterns and conventions used throughout
205+ the go-github repository. Following these guidelines helps maintain consistency
206+ and makes the codebase easier to understand and maintain.
207+
208+ ### Naming Conventions
209+
210+ #### File Names
211+
212+ Files are organized by service and API endpoint, following the pattern
213+ ` {service}_{api}.go ` . For example:
214+ - ` repos_contents.go ` - Repository contents API methods
215+ - ` users_ssh_signing_keys.go ` - User SSH signing keys API methods
216+ - ` orgs_rules.go ` - Organization rules API methods
217+
218+ Test files follow the pattern ` {service}_{api}_test.go ` .
219+
220+ #### Receiver Names
221+
222+ Service method receivers consistently use the single letter ` s ` :
223+
224+ ``` go
225+ func (s *RepositoriesService ) Get (ctx context .Context , owner , repo string ) (*Repository , *Response , error ) {
226+ // ...
227+ }
228+ ```
229+
230+ #### Request Option Types
231+
232+ Request option types (for query parameters) are named after the method they
233+ modify, with the suffix ` Options ` :
234+
235+ ``` go
236+ type RepositoryListOptions struct {
237+ Type string ` url:"type,omitempty"`
238+ Sort string ` url:"sort,omitempty"`
239+ Direction string ` url:"direction,omitempty"`
240+ ListOptions
241+ }
242+ ```
243+
244+ #### Request Body Types
245+
246+ Request body types (for POST/PUT/PATCH requests) are named after the method
247+ they modify, with the suffix ` Options ` :
248+
249+ ``` go
250+ type RepositoryContentFileOptions struct {
251+ Message *string ` json:"message,omitempty"`
252+ Content []byte ` json:"content"`
253+ SHA *string ` json:"sha,omitempty"`
254+ Branch *string ` json:"branch,omitempty"`
255+ Author *CommitAuthor ` json:"author,omitempty"`
256+ Committer *CommitAuthor ` json:"committer,omitempty"`
257+ }
258+ ```
259+
260+ #### Response Types
261+
262+ Response types are named after the resource they represent, typically without
263+ any suffix:
264+
265+ ``` go
266+ type Repository struct {
267+ ID *int64 ` json:"id,omitempty"`
268+ Name *string ` json:"name,omitempty"`
269+ FullName *string ` json:"full_name,omitempty"`
270+ Description *string ` json:"description,omitempty"`
271+ // ...
272+ }
273+ ```
274+
275+ #### Method and Variable Naming
276+
277+ Methods use descriptive names that clearly indicate their action:
278+ - ` Get ` - Retrieve a single resource
279+ - ` List ` - Retrieve multiple resources (supports pagination)
280+ - ` Create ` - Create a new resource
281+ - ` Update ` - Update an existing resource
282+ - ` Delete ` - Delete a resource
283+ - ` Edit ` - Edit an existing resource (alternative to Update)
284+
285+ Common local variable names:
286+ - ` ctx ` - Context
287+ - ` u ` - URL string
288+ - ` req ` - HTTP request
289+ - ` resp ` - HTTP response
290+ - ` result ` - Result from API call
291+ - ` err ` - Error
292+
293+ #### Common Variable Names
294+
295+ These variable names are used consistently throughout the codebase:
296+ - ` owner ` - Repository owner (username or organization)
297+ - ` repo ` - Repository name
298+ - ` org ` - Organization name
299+ - ` user ` - Username
300+ - ` team ` - Team name or slug
301+ - ` project ` - Project name or number
302+
303+ #### Enterprise and Organization Scoped Methods
304+
305+ Methods that operate on enterprise or organization resources include the scope
306+ in their name:
307+
308+ ``` go
309+ // Enterprise-scoped methods
310+ func (s *EnterpriseService ) GetLicenseInfo (ctx context .Context ) (*LicenseInfo , *Response , error )
311+
312+ // Organization-scoped methods
313+ func (s *OrganizationsService) ListMembers(ctx context.Context, org string, opts *OrganizationListMembersOptions) ([]*User, *Response, error)
314+ ```
315+
316+ #### Common Structs
317+
318+ These common structs are used throughout the codebase:
319+ - `ListOptions` - For offset-based pagination (page/per_page)
320+ - `ListCursorOptions` - For cursor-based pagination
321+ - `UploadOptions` - For file uploads
322+ - `Response` - Wraps the HTTP response
323+
324+ ### JSON Tags for Request Bodies
325+
326+ When defining structs that represent a request body (sent via POST/PUT/PATCH):
327+
328+ 1. **Required fields** should be non-pointer types without `omitempty`:
329+
330+ ```go
331+ type SecretScanningAlertUpdateOptions struct {
332+ State string ` json:"state"` // Required field
333+ // ...
334+ }
335+ ```
336+
337+ 2 . ** Optional fields** should be pointer types with ` omitempty ` :
338+
339+ ``` go
340+ type SecretScanningAlertUpdateOptions struct {
341+ State string ` json:"state"`
342+ Resolution *string ` json:"resolution,omitempty"`
343+ ResolutionComment *string ` json:"resolution_comment,omitempty"`
344+ }
345+ ```
346+
347+ 3 . ** Use ` omitzero ` for structs and slices** where you want to omit empty values
348+ (not just nil):
349+
350+ ``` go
351+ type ActivityNotificationOptions struct {
352+ SubjectType string ` json:"subject_type,omitempty"`
353+ Subject *string ` json:"subject,omitempty"`
354+ LastReadAt Timestamp ` json:"last_read_at,omitzero"`
355+ }
356+ ```
357+
358+ ### URL Tags for Query Parameters
359+
360+ When defining structs that represent query parameters (sent via URL):
361+
362+ 1 . ** All fields should be non-pointer types** with ` url ` tags:
363+
364+ ``` go
365+ type RepositoryContentGetOptions struct {
366+ Ref string ` url:"ref,omitempty"`
367+ }
368+
369+ type ListOptions struct {
370+ Page int ` url:"page,omitempty"`
371+ PerPage int ` url:"per_page,omitempty"`
372+ }
373+ ```
374+
375+ 2 . ** Use ` omitempty ` to omit zero values** from the query string:
376+
377+ ``` go
378+ type RepositoryListOptions struct {
379+ Type string ` url:"type,omitempty"`
380+ Sort string ` url:"sort,omitempty"`
381+ Direction string ` url:"direction,omitempty"`
382+ ListOptions
383+ }
384+ ```
385+
386+ ### Pagination
387+
388+ The go-github library supports two types of pagination:
389+
390+ #### Offset-based Pagination
391+
392+ Use ` ListOptions ` for APIs that use page/per_page parameters:
393+
394+ ``` go
395+ type ListOptions struct {
396+ // For paginated result sets, page of results to retrieve.
397+ Page int ` url:"page,omitempty"`
398+
399+ // For paginated result sets, the number of results to include per page.
400+ PerPage int ` url:"per_page,omitempty"`
401+ }
402+ ```
403+
404+ #### Cursor-based Pagination
405+
406+ Use ` ListCursorOptions ` for APIs that use cursor-based pagination:
407+
408+ ``` go
409+ type ListCursorOptions struct {
410+ // For paginated result sets, page of results to retrieve.
411+ Page string ` url:"page,omitempty"`
412+
413+ // For paginated result sets, the number of results to include per page.
414+ PerPage int ` url:"per_page,omitempty"`
415+
416+ // For paginated result sets, the number of results per page (max 100), starting from the first matching result.
417+ // This parameter must not be used in combination with last.
418+ First int ` url:"first,omitempty"`
419+
420+ // For paginated result sets, the number of results per page (max 100), starting from the last matching result.
421+ // This parameter must not be used in combination with first.
422+ Last int ` url:"last,omitempty"`
423+
424+ // A cursor, as given in the Link header. If specified, the query only searches for events after this cursor.
425+ After string ` url:"after,omitempty"`
426+
427+ // A cursor, as given in the Link header. If specified, the query only searches for events before this cursor.
428+ Before string ` url:"before,omitempty"`
429+
430+ // A cursor, as given in the Link header. If specified, the query continues the search using this cursor.
431+ Cursor string ` url:"cursor,omitempty"`
432+ }
433+ ```
434+
435+ #### Pagination Best Practices
436+
437+ 1 . ** Embed pagination options** in your option structs:
438+
439+ ``` go
440+ type RepositoryListOptions struct {
441+ Type string ` url:"type,omitempty"`
442+ Sort string ` url:"sort,omitempty"`
443+ Direction string ` url:"direction,omitempty"`
444+ ListOptions // Embed for pagination
445+ }
446+ ```
447+
448+ 2 . ** Handle nil options** in your methods:
449+
450+ ``` go
451+ func (s *RepositoriesService ) List (ctx context .Context , user string , opts *RepositoryListOptions ) ([]*Repository , *Response , error ) {
452+ if opts == nil {
453+ opts = &RepositoryListOptions{}
454+ }
455+ // ...
456+ }
457+ ```
458+
459+ 3 . ** Use iterators** for list methods that support pagination. The library
460+ automatically generates iterator methods (e.g., ` ListIter ` ) for methods
461+ that start with ` List ` and return a slice.
462+
463+ ### Common Types
464+
465+ These types are used consistently throughout the codebase:
466+
467+ #### ID Fields
468+
469+ GitHub API IDs are always ` int64 ` :
470+
471+ ``` go
472+ type Repository struct {
473+ ID *int64 ` json:"id,omitempty"`
474+ // ...
475+ }
476+
477+ type User struct {
478+ ID *int64 ` json:"id,omitempty"`
479+ // ...
480+ }
481+ ```
482+
483+ #### Node ID Fields
484+
485+ Node IDs are always ` string ` :
486+
487+ ``` go
488+ type Repository struct {
489+ ID *int64 ` json:"id,omitempty"`
490+ NodeID *string ` json:"node_id,omitempty"`
491+ // ...
492+ }
493+ ```
494+
495+ #### Timestamp Fields
496+
497+ Use the ` Timestamp ` type for all date/time fields:
498+
499+ ``` go
500+ type Repository struct {
501+ CreatedAt *Timestamp ` json:"created_at,omitempty"`
502+ UpdatedAt *Timestamp ` json:"updated_at,omitempty"`
503+ PushedAt *Timestamp ` json:"pushed_at,omitempty"`
504+ // ...
505+ }
506+ ```
507+
508+ #### Boolean Fields
509+
510+ Boolean fields are always ` *bool ` (pointer to bool) to distinguish between
511+ ` false ` and ` not set ` :
512+
513+ ``` go
514+ type Repository struct {
515+ Private *bool ` json:"private,omitempty"`
516+ Fork *bool ` json:"fork,omitempty"`
517+ // ...
518+ }
519+ ```
520+
521+ ### Generation Patterns
522+
523+ The go-github repository uses code generation for several purposes:
524+
525+ #### Generated Accessors
526+
527+ The ` github-accessors.go ` file contains generated getter and setter methods
528+ for struct fields. These are generated automatically and should not be edited
529+ manually.
530+
531+ #### Generated Iterators
532+
533+ Iterator methods are automatically generated for list methods that:
534+ 1 . Start with ` List `
535+ 2 . Return a slice
536+ 3 . Accept pagination options
537+
538+ For example, ` RepositoriesService.List ` automatically gets a ` ListIter ` method.
539+
540+ #### Generated Documentation
541+
542+ Documentation links are automatically generated from ` openapi_operations.yaml ` .
543+ Run ` script/generate.sh ` to update these links.
544+
545+ #### Linter Rules
546+
547+ The repository uses custom linter rules to enforce consistency:
548+ - ` sliceofpointers ` - Ensures slice fields use pointers
549+ - ` structfield ` - Ensures struct fields follow naming conventions
550+
202551## Metadata
203552
204553GitHub publishes [ OpenAPI descriptions of their API] [ ] . We use these
0 commit comments