Skip to content

Conversation

@nithish-95
Copy link

Description

Implements enterprise GitHub App installation repository management endpoints for issue #3829.

This PR adds the following endpoints:

  • GET /enterprises/{enterprise}/apps/organizations/{org}/installations/{installation_id}/repositories
  • PATCH /enterprises/{enterprise}/apps/organizations/{org}/installations/{installation_id}/repositories
  • PATCH /enterprises/{enterprise}/apps/organizations/{org}/installations/{installation_id}/repositories/add
  • PATCH /enterprises/{enterprise}/apps/organizations/{org}/installations/{installation_id}/repositories/remove

Changes

  • Added ListRepositoriesForOrgInstallation method to list repositories accessible to an app installation
  • Added ToggleInstallationRepositories method to update repository selection
  • Added AddRepositoriesToInstallation method to add repositories to an installation
  • Added RemoveRepositoriesFromInstallation method to remove repositories from an installation
  • Added corresponding test cases for all methods
  • Added necessary request/response types

Testing

  • All unit tests pass
  • Linter checks pass
  • Follows existing code patterns in the repository

cc @gmlewis @Not-Dhananjay-Mishra

@codecov
Copy link

codecov bot commented Nov 16, 2025

Codecov Report

✅ All modified and coverable lines are covered by tests.
✅ Project coverage is 92.44%. Comparing base (903265b) to head (1a69bbf).

Additional details and impacted files
@@            Coverage Diff             @@
##           master    #3831      +/-   ##
==========================================
+ Coverage   92.41%   92.44%   +0.02%     
==========================================
  Files         197      198       +1     
  Lines       14152    14195      +43     
==========================================
+ Hits        13079    13122      +43     
  Misses        884      884              
  Partials      189      189              

☔ 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
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, @nithish-95!
One minor tweak, please, then we should be ready to merge after a second LGTM+Approval from any other contributor to this repo.

cc: @stevehipwell - @alexandear - @zyfy29

@gmlewis gmlewis added the NeedsReview PR is awaiting a review before merging. label Nov 17, 2025
@stevehipwell
Copy link
Contributor

How does this PR relate to #3830? They look related to me, which means we likely want to align the implementation including naming. Would it not make sense to wait for #3830 to be merged before reviewing this PR?

- Use EnterpriseService instead of creating new service
- Add EnterpriseInstallationRepositoriesOptions for consistency
- Update method signatures to Required
…orOrgInstallation` to return a slice of it
…tead of ListRepositories and adjust its test expectations.
@nithish-95
Copy link
Author

I've rebased on master to use the existing AccessibleRepository struct and removed the duplicate definition from this PR.
I also updated ListRepositoriesForOrgInstallation to return []*AccessibleRepository and fixed ToggleInstallationRepositories to return *Installation as requested.

I feel sorry for the way I use Git!!

cc: @gmlewis - @Not-Dhananjay-Mishra - @stevehipwell

Copy link
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, @nithish-95!
LGTM.
Awaiting second LGTM+Approval from any other contributor to this repo before merging.

cc: @stevehipwell - @alexandear - @zyfy29 - @Not-Dhananjay-Mishra

// GitHub API docs: https://docs.github.com/enterprise-cloud@latest/rest/enterprise-admin/organization-installations#grant-repository-access-to-an-organization-installation
//
//meta:operation PATCH /enterprises/{enterprise}/apps/organizations/{org}/installations/{installation_id}/repositories/add
func (s *EnterpriseService) AddRepositoriesToInstallation(ctx context.Context, enterprise, org string, installationID int64, opts EnterpriseInstallationRepositoriesOptions) (*ListRepositories, *Response, error) {
Copy link
Contributor

Choose a reason for hiding this comment

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

Suggested change
func (s *EnterpriseService) AddRepositoriesToInstallation(ctx context.Context, enterprise, org string, installationID int64, opts EnterpriseInstallationRepositoriesOptions) (*ListRepositories, *Response, error) {
func (s *EnterpriseService) AddRepositoriesToInstallation(ctx context.Context, enterprise, org string, installationID int64, opts EnterpriseInstallationRepositoriesOptions) ([]*AccessibleRepository, *Response, error) {

/enterprises/{enterprise}/apps/organizations/{org}/installations/{installation_id}/repositories/add
This endpoint has this response schema

{
  "type": "array",
  "items": {
    "title": "Accessible Repository",
    "description": "A repository that may be made accessible to a GitHub App.",
    "type": "object",
    "properties": {
      "id": {
        "description": "Unique identifier of the repository",
        "type": "integer",
        "format": "int64",
        "examples": [
          1
        ]
      },
      "name": {
        "description": "The name of the repository.",
        "type": "string",
        "examples": [
          "Team Environment"
        ]
      },
      "full_name": {
        "type": "string",
        "examples": [
          "octocat/Hello-World"
        ]
      }
    },
    "required": [
      "full_name",
      "id",
      "name"
    ]
  }
}

It should retrun []*AccessibleRepository not *ListRepositories

type AccessibleRepository struct {
	ID       int64  `json:"id"`
	Name     string `json:"name"`
	FullName string `json:"full_name"`
}

// GitHub API docs: https://docs.github.com/enterprise-cloud@latest/rest/enterprise-admin/organization-installations#remove-repository-access-from-an-organization-installation
//
//meta:operation PATCH /enterprises/{enterprise}/apps/organizations/{org}/installations/{installation_id}/repositories/remove
func (s *EnterpriseService) RemoveRepositoriesFromInstallation(ctx context.Context, enterprise, org string, installationID int64, opts EnterpriseInstallationRepositoriesOptions) (*ListRepositories, *Response, error) {
Copy link
Contributor

Choose a reason for hiding this comment

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

Suggested change
func (s *EnterpriseService) RemoveRepositoriesFromInstallation(ctx context.Context, enterprise, org string, installationID int64, opts EnterpriseInstallationRepositoriesOptions) (*ListRepositories, *Response, error) {
func (s *EnterpriseService) RemoveRepositoriesFromInstallation(ctx context.Context, enterprise, org string, installationID int64, opts EnterpriseInstallationRepositoriesOptions) ([]*AccessibleRepository, *Response, error) {

same here

Copy link
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.

I've added some naming suggestions, happy to discuss the "why".

Comment on lines +13 to +25
// EnterpriseInstallationRepositoriesOptions specifies the parameters for
// EnterpriseService.AddRepositoriesToInstallation and
// EnterpriseService.RemoveRepositoriesFromInstallation.
type EnterpriseInstallationRepositoriesOptions struct {
SelectedRepositoryIDs []int64 `json:"selected_repository_ids"`
}

// EnterpriseInstallationRepositoriesToggleOptions specifies the parameters for
// EnterpriseService.ToggleInstallationRepositories.
type EnterpriseInstallationRepositoriesToggleOptions struct {
RepositorySelection *string `json:"repository_selection,omitempty"` // Can be "all" or "selected"
SelectedRepositoryIDs []int64 `json:"selected_repository_ids,omitempty"`
}
Copy link
Contributor

Choose a reason for hiding this comment

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

Do these types need to be scoped to the enterprise, they look pretty generic? And should they not use AppInstallation instead of just Installation?

// GitHub API docs: https://docs.github.com/enterprise-cloud@latest/rest/enterprise-admin/organization-installations#get-the-repositories-accessible-to-a-given-github-app-installation
//
//meta:operation GET /enterprises/{enterprise}/apps/organizations/{org}/installations/{installation_id}/repositories
func (s *EnterpriseService) ListRepositoriesForOrgInstallation(ctx context.Context, enterprise, org string, installationID int64, opts *ListOptions) ([]*AccessibleRepository, *Response, error) {
Copy link
Contributor

Choose a reason for hiding this comment

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

Suggested change
func (s *EnterpriseService) ListRepositoriesForOrgInstallation(ctx context.Context, enterprise, org string, installationID int64, opts *ListOptions) ([]*AccessibleRepository, *Response, error) {
func (s *EnterpriseService) ListRepositoriesForOrgAppInstallation(ctx context.Context, enterprise, org string, installationID int64, opts *ListOptions) ([]*AccessibleRepository, *Response, error) {

// GitHub API docs: https://docs.github.com/enterprise-cloud@latest/rest/enterprise-admin/organization-installations#toggle-installation-repository-access-between-selected-and-all-repositories
//
//meta:operation PATCH /enterprises/{enterprise}/apps/organizations/{org}/installations/{installation_id}/repositories
func (s *EnterpriseService) ToggleInstallationRepositories(ctx context.Context, enterprise, org string, installationID int64, opts EnterpriseInstallationRepositoriesToggleOptions) (*Installation, *Response, error) {
Copy link
Contributor

Choose a reason for hiding this comment

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

I think this would make more sense and be more consistent if it was named UpdateAppInstallationRepositories?

// GitHub API docs: https://docs.github.com/enterprise-cloud@latest/rest/enterprise-admin/organization-installations#grant-repository-access-to-an-organization-installation
//
//meta:operation PATCH /enterprises/{enterprise}/apps/organizations/{org}/installations/{installation_id}/repositories/add
func (s *EnterpriseService) AddRepositoriesToInstallation(ctx context.Context, enterprise, org string, installationID int64, opts EnterpriseInstallationRepositoriesOptions) (*ListRepositories, *Response, error) {
Copy link
Contributor

Choose a reason for hiding this comment

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

Suggested change
func (s *EnterpriseService) AddRepositoriesToInstallation(ctx context.Context, enterprise, org string, installationID int64, opts EnterpriseInstallationRepositoriesOptions) (*ListRepositories, *Response, error) {
func (s *EnterpriseService) AddRepositoriesToAppInstallation(ctx context.Context, enterprise, org string, installationID int64, opts EnterpriseInstallationRepositoriesOptions) (*ListRepositories, *Response, error) {

// GitHub API docs: https://docs.github.com/enterprise-cloud@latest/rest/enterprise-admin/organization-installations#remove-repository-access-from-an-organization-installation
//
//meta:operation PATCH /enterprises/{enterprise}/apps/organizations/{org}/installations/{installation_id}/repositories/remove
func (s *EnterpriseService) RemoveRepositoriesFromInstallation(ctx context.Context, enterprise, org string, installationID int64, opts EnterpriseInstallationRepositoriesOptions) (*ListRepositories, *Response, error) {
Copy link
Contributor

Choose a reason for hiding this comment

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

Suggested change
func (s *EnterpriseService) RemoveRepositoriesFromInstallation(ctx context.Context, enterprise, org string, installationID int64, opts EnterpriseInstallationRepositoriesOptions) (*ListRepositories, *Response, error) {
func (s *EnterpriseService) RemoveRepositoriesFromAppInstallation(ctx context.Context, enterprise, org string, installationID int64, opts EnterpriseInstallationRepositoriesOptions) (*ListRepositories, *Response, error) {

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

Labels

NeedsReview PR is awaiting a review before merging.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants