Skip to content

docs: extend CONTRIBUTING.md with code guidelines#4202

Open
jlaportebot wants to merge 3 commits into
google:masterfrom
jlaportebot:docs/extend-contributing-guidelines
Open

docs: extend CONTRIBUTING.md with code guidelines#4202
jlaportebot wants to merge 3 commits into
google:masterfrom
jlaportebot:docs/extend-contributing-guidelines

Conversation

@jlaportebot
Copy link
Copy Markdown

Summary

This PR extends CONTRIBUTING.md with a comprehensive section on code guidelines and conventions, addressing issue #4023.

Changes

Added a new "Code Guidelines" section that documents:

  1. Naming Conventions

    • File names ({service}_{api}.go pattern)
    • Receiver names (consistently use 's')
    • Request option types
    • Request body types
    • Response types
    • Method and variable naming
    • Common variable names (owner, repo, org, user, team, project)
    • Enterprise and organization scoped methods
    • Common structs (ListOptions, ListCursorOptions, UploadOptions, Response)
  2. JSON Tags for Request Bodies

    • Required fields: non-pointer types without omitempty
    • Optional fields: pointer types with omitempty
    • Use omitzero for structs and slices
  3. URL Tags for Query Parameters

    • All fields should be non-pointer types with url tags
    • Use omitempty to omit zero values
  4. Pagination

    • Offset-based pagination (ListOptions)
    • Cursor-based pagination (ListCursorOptions)
    • Pagination best practices (embedding options, handling nil, using iterators)
  5. Common Types

    • ID fields: always int64
    • Node ID fields: always string
    • Timestamp fields: use Timestamp type
    • Boolean fields: always *bool
  6. Generation Patterns

    • Generated accessors
    • Generated iterators
    • Generated documentation
    • Linter rules (sliceofpointers, structfield)

Benefits

  • Helps new contributors understand the codebase better
  • Reduces review burden by making expectations explicit
  • Improves code consistency across the project
  • Documents patterns that are frequently discussed in reviews

Testing

This is a documentation-only change. No code changes or tests needed.

Closes #4023

Add comprehensive section documenting common code patterns and conventions:
- Naming conventions (files, receivers, types, methods, variables)
- JSON tags for request bodies (required vs optional fields, omitzero)
- URL tags for query parameters (non-pointer fields with omitempty)
- Pagination patterns (ListOptions, ListCursorOptions, best practices)
- Common types (ID, NodeID, Timestamp, boolean fields)
- Generation patterns (accessors, iterators, documentation, linter rules)

This addresses issue google#4023 and helps new contributors understand the codebase
better, reducing review burden and improving code consistency.
Copy link
Copy Markdown
Collaborator

@gmlewis gmlewis left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thank you, @jlaportebot.
LGTM.

cc: @alexandear

@codecov
Copy link
Copy Markdown

codecov Bot commented May 8, 2026

Codecov Report

✅ All modified and coverable lines are covered by tests.
✅ Project coverage is 93.34%. Comparing base (6c58592) to head (dfe7486).
⚠️ Report is 13 commits behind head on master.

Additional details and impacted files
@@            Coverage Diff             @@
##           master    #4202      +/-   ##
==========================================
- Coverage   93.71%   93.34%   -0.37%     
==========================================
  Files         209      209              
  Lines       19772    19998     +226     
==========================================
+ Hits        18529    18667     +138     
- Misses       1046     1114      +68     
- Partials      197      217      +20     

☔ View full report in Codecov by Sentry.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.

Copy link
Copy Markdown
Contributor

@alexandear alexandear left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@jlaportebot Thank you. I left a few comments regarding excessive formatting and redundant information. Could you also review the entire CONTRIBUTING.md document and consolidate duplicated content?

Also, I think this PR should be reviewed by everyone listed in the REVIEWERS file.

Comment thread CONTRIBUTING.md Outdated

[Go Doc Comments]: https://go.dev/doc/comment

## Code Guidelines
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think the "Code Comments" section above should be under "Code Guidelines".

Comment thread CONTRIBUTING.md
Comment on lines +540 to +543
#### Generated Documentation

Documentation links are automatically generated from `openapi_operations.yaml`.
Run `script/generate.sh` to update these links.
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

These lines are not needed.

They are already in "Submitting a patch", "Metadata", and "Scripts".

Can be removed.

Comment thread CONTRIBUTING.md Outdated
Comment on lines +545 to +549
#### Linter Rules

The repository uses custom linter rules to enforce consistency:
- `sliceofpointers` - Ensures slice fields use pointers
- `structfield` - Ensures struct fields follow naming conventions
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We have more linters. Let's simply remove this section.

Comment thread CONTRIBUTING.md Outdated
Comment on lines +332 to +333
State string `json:"state"` // Required field
// ...
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please use TABs instead of spaces for all examples:

Suggested change
State string `json:"state"` // Required field
// ...
State string `json:"state"` // Required field
// ...

Comment thread CONTRIBUTING.md Outdated

### Naming Conventions

#### File Names
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Should we remove the "Other notes on code organization" section?

Comment thread CONTRIBUTING.md Outdated
Comment on lines +303 to +314
#### Enterprise and Organization Scoped Methods

Methods that operate on enterprise or organization resources include the scope
in their name:

```go
// Enterprise-scoped methods
func (s *EnterpriseService) GetLicenseInfo(ctx context.Context) (*LicenseInfo, *Response, error)

// Organization-scoped methods
func (s *OrganizationsService) ListMembers(ctx context.Context, org string, opts *OrganizationListMembersOptions) ([]*User, *Response, error)
```
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actually, I think this subsection may be incorrect - see #3761.

Comment thread CONTRIBUTING.md Outdated

When defining structs that represent a request body (sent via POST/PUT/PATCH):

1. **Required fields** should be non-pointer types without `omitempty`:
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please do not use excessive LLM-like formatting:

Suggested change
1. **Required fields** should be non-pointer types without `omitempty`:
1. Required fields should be non-pointer types without `omitempty`:

Comment thread CONTRIBUTING.md Outdated
Comment on lines +448 to +457
2. **Handle nil options** in your methods:

```go
func (s *RepositoriesService) List(ctx context.Context, user string, opts *RepositoryListOptions) ([]*Repository, *Response, error) {
if opts == nil {
opts = &RepositoryListOptions{}
}
// ...
}
```
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This can be removed. We have the addOptions to handle nil options.

@alexandear
Copy link
Copy Markdown
Contributor

@stevehipwell @zyfy29 @Not-Dhananjay-Mishra @munlicode please review when you have time

@stevehipwell
Copy link
Copy Markdown
Contributor

@alexandear did you not want your review comments addressing before someone else weighs in?

Comment thread CONTRIBUTING.md Outdated

### Naming Conventions

#### File Names
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Maybe remove "Other notes on code organization" as @alexandear suggested, and put this:

Files are organized by service and API endpoint, following the pattern
`{service}_{api}.go`. For example:
- `repos_contents.go` - Repository contents API methods
- `users_ssh_signing_keys.go` - User SSH signing keys API methods
- `orgs_rules.go` - Organization rules API methods

Test files follow the pattern `{service}_{api}_test.go`.


These services map directly to how the [GitHub API documentation](https://docs.github.com/en/rest) is organized, so use that as your guide for where to put new methods.

For example, methods defined at <https://docs.github.com/en/rest/webhooks/repos> live in [repos_hooks.go][https://github.com/google/go-github/blob/master/github/repos_hooks.go].

@alexandear
Copy link
Copy Markdown
Contributor

@alexandear did you not want your review comments addressing before someone else weighs in?

@stevehipwell I prefer that all reviewers contribute to the guidelines regardless of my comments, since my feedback is ultimately opinionated as well.

Copy link
Copy Markdown
Contributor

@stevehipwell stevehipwell left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is looking like a really useful resource for contributions. I've added some comments/suggestions.

Comment thread CONTRIBUTING.md Outdated
Comment on lines +246 to +247
Request body types (for POST/PUT/PATCH requests) are named after the method
they modify, with the suffix `Options`:
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Should request body types not use the Request suffix? The use of Options here is overloaded and it looks to me like the current usage is split roughly even across the wtwo patterns.

Comment thread CONTRIBUTING.md Outdated
- `Create` - Create a new resource
- `Update` - Update an existing resource
- `Delete` - Delete a resource
- `Edit` - Edit an existing resource (alternative to Update)
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't think we should have Edit as an "alternative", the GitHub API isn't consistent but that doesn't mean we can't make this SDK consistent (as far as is supported by the API).

Comment thread CONTRIBUTING.md Outdated
Comment on lines +305 to +306
Methods that operate on enterprise or organization resources include the scope
in their name:
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This comment doesn't line up with the example below it and also doesn't match the last agreed practice of NOT including the scope in the name where the scope is already defined by the service.

Comment thread CONTRIBUTING.md
Comment on lines +319 to +320
- `ListOptions` - For offset-based pagination (page/per_page)
- `ListCursorOptions` - For cursor-based pagination
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Do we want to move away from the use of some of the common structs that don't directly map to the API surface and instead start to add specific structs?

Comment thread CONTRIBUTING.md Outdated
Comment on lines +347 to +356
3. **Use `omitzero` for structs and slices** where you want to omit empty values
(not just nil):

```go
type ActivityNotificationOptions struct {
SubjectType string `json:"subject_type,omitempty"`
Subject *string `json:"subject,omitempty"`
LastReadAt Timestamp `json:"last_read_at,omitzero"`
}
```
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't think this comment is correct, for structs and time.Time using omitzero will omit the value from the payload; but for slices and maps it does the opposite and keeps empty ones and only omits them if they're nil. See the use in RepositoryRuleset.

Comment thread CONTRIBUTING.md

### Pagination

The go-github library supports two types of pagination:
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is this still correct, I thought it was fuzzier?

Comment thread CONTRIBUTING.md Outdated
}
```

3. **Use iterators** for list methods that support pagination. The library
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We probably out to mention the custom pagination configuration for non-standard pagination (e.g. commit files).

Comment thread CONTRIBUTING.md Outdated
Comment on lines +472 to +480
type Repository struct {
ID *int64 `json:"id,omitempty"`
// ...
}

type User struct {
ID *int64 `json:"id,omitempty"`
// ...
}
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It might be better to choose an example where the ID isn't a pointer.

Comment thread CONTRIBUTING.md Outdated
Comment on lines +501 to +503
CreatedAt *Timestamp `json:"created_at,omitempty"`
UpdatedAt *Timestamp `json:"updated_at,omitempty"`
PushedAt *Timestamp `json:"pushed_at,omitempty"`
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Do these still need to be pointers or can we use omitzero? If so should we?

Comment thread CONTRIBUTING.md Outdated
Comment on lines +510 to +511
Boolean fields are always `*bool` (pointer to bool) to distinguish between
`false` and `not set`:
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If the boolean is required I'm not sure I see the value in this?

Comment thread CONTRIBUTING.md Outdated
- `Delete` - Delete a resource
- `Edit` - Edit an existing resource (alternative to Update)

Common local variable names:
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We can add opts in this list too.
As opts is more commonly used throughout the repository #3887

Comment thread CONTRIBUTING.md
Committer *CommitAuthor `json:"committer,omitempty"`
}
```

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

In my opinion it is worth mentioning about the use of value parameters instead of pointers where appropriate #3644

Comment thread CONTRIBUTING.md Outdated
Comment on lines +324 to +326
### JSON Tags for Request Bodies

When defining structs that represent a request body (sent via POST/PUT/PATCH):
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We have similar kind of rules around pointer usage and omitempty/omitzero for response bodies as well, so I think it would be worth mentioning them too.
Maybe we can combine the request and response body sections into a single section or should we make separate section?

@alexandear
Copy link
Copy Markdown
Contributor

@jlaportebot, are you planning to continue working on this?

@jlaportebot
Copy link
Copy Markdown
Author

@alexandear Yes, I'm planning to continue working on this. I'll address the requested changes around excessive formatting, redundant information, and duplicated content shortly. Thanks for the patience.

- Move Code Comments section under Code Guidelines
- Remove 'Other notes on code organization' (merged into File Names)
- Remove Linter Rules subsection (duplicates other sections)
- Add Request suffix as alternative for request body types
- Remove Edit from method naming (SDK should be consistent with Update)
- Fix Enterprise/Org scoped methods description (scope from service type)
- Correct omitzero behavior for slices vs structs
- Add response body JSON tag guidance
- Mention custom pagination for non-standard APIs
- Add opts to common variable names
- Add value parameters guidance
- Use tabs in Go code examples
- Remove excessive bold formatting
@jlaportebot
Copy link
Copy Markdown
Author

Addressed all review feedback in a new commit (6dc10b8):

  1. Moved Code Comments section under Code Guidelines per @alexandear
  2. Removed 'Other notes on code organization' section — merged the GitHub API docs link into the File Names subsection per @alexandear and @munlicode
  3. Removed Linter Rules subsection per @alexandear
  4. Added Request suffix as an alternative naming pattern for request body types per @stevehipwell
  5. Removed Edit from method naming — the SDK should be consistent with Update per @stevehipwell
  6. Rewrote the Enterprise/Organization scoped methods section — methods don't need scope in the name since the service type already defines it per @stevehipwell
  7. Corrected the omitzero description: for structs and time.Time, omitzero omits empty values; for slices and maps, omitzero keeps empty (non-nil) values and only omits nil per @stevehipwell. Added reference to RepositoryRuleset for examples.
  8. Added response body JSON tag guidance per @Not-Dhananjay-Mishra
  9. Added custom pagination configuration note for non-standard APIs (e.g., commit files) per @stevehipwell
  10. Added opts to the common local variable names list per @Not-Dhananjay-Mishra
  11. Added value parameters guidance (prefer value types over pointers where appropriate) per @Not-Dhananjay-Mishra (Refactor codebase to use value parameters instead of pointers where appropriate #3644)
  12. Used tabs in Go code examples per @alexandear
  13. Removed excessive bold formatting throughout the Code Guidelines section per @alexandear
  14. Added non-pointer int64 example for ID fields in request bodies per @stevehipwell
  15. Added boolean field guidance: non-pointer bool for required fields, *bool with omitempty for optional, *bool with omitzero when distinguishing false from not set per @stevehipwell
  16. Noted that addOptions handles nil options so explicit nil checks are unnecessary per @alexandear

Please take another look — happy to make further adjustments.

- Move Code Comments under Code Guidelines section
- Remove duplicated content (Code Organization, Linters)
- Use TABs instead of spaces in code examples
- Remove excessive numbered list formatting
- Fix omitzero description for slices/maps per stevehipwell
- Use non-pointer ID in example per stevehipwell
- Add opts to common variable names per Not-Dhananjay-Mishra
- Add Value vs Pointer Parameters section per google#3644
- Fix method naming section to match scoped method convention
- Add custom pagination note per stevehipwell
- Consolidate request/response body JSON tag guidelines
- Fix boolean field guidance (use omitzero for optional bools)
- Remove Edit from method name list, keep consistent with API
@jlaportebot
Copy link
Copy Markdown
Author

Thanks for the detailed reviews! I've pushed a comprehensive update addressing the feedback:

@alexandear:

  • Moved Code Comments under Code Guidelines section
  • Removed duplicated content (Other notes on code organization section, linters section)
  • Used TABs instead of spaces in all code examples
  • Removed excessive numbered list formatting

@stevehipwell:

  • Fixed omitzero description: clarified that for slices/maps it keeps empty (non-nil) values and only omits nil values, with reference to RepositoryRuleset
  • Used non-pointer int64 for ID field in request body example
  • Added note about custom pagination for non-standard APIs (e.g., commit files)
  • Fixed boolean field guidance: use *bool with omitzero for optional fields where you need to distinguish between false and "not set"
  • Removed Edit from method name list to keep SDK consistent
  • Fixed method naming section to match the scoped method convention (method name should not repeat scope)

@Not-Dhananjay-Mishra:

Other improvements:

  • Consolidated request/response body JSON tag guidelines
  • Removed redundant number formatting throughout
  • Streamlined the overall structure

I'd appreciate another round of review. Happy to make further adjustments.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Extend CONTRIBUTING.md with common code guidelines

6 participants