diff --git a/scm/apps.go b/scm/apps.go new file mode 100644 index 00000000..293f07d2 --- /dev/null +++ b/scm/apps.go @@ -0,0 +1,156 @@ +// Copyright 2017 Drone.IO Inc. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package scm + +import ( + "context" + "time" +) + +type ( + // App represents an SCM App. + App struct { + ID int64 + Slug string + NodeID string + Owner *User + Name string + Description string + ExternalURL string + HTMLURL string + CreatedAt time.Time + UpdatedAt time.Time + Permissions *InstallationPermissions + Events []string + } + + // Installation represents an Apps installation. + Installation struct { + ID int64 + NodeID string + AppID int64 + AppSlug string + TargetID int64 + Account *User + AccessTokensURL string + RepositoriesURL string + HTMLURL string + TargetType string + SingleFileName string + RepositorySelection string + Events []string + SingleFilePaths []string + Permissions *InstallationPermissions + CreatedAt time.Time + UpdatedAt time.Time + HasMultipleSingleFiles bool + SuspendedBy *User + SuspendedAt *time.Time + } + + // InstallationToken represents an installation token. + InstallationToken struct { + Token string + ExpiresAt time.Time + Permissions *InstallationPermissions + Repositories []*Repository + } + + // InstallationTokenOptions allow restricting a token's access to specific repositories. + InstallationTokenOptions struct { + // The IDs of the repositories that the installation token can access. + // Providing repository IDs restricts the access of an installation token to specific repositories. + RepositoryIDs []int64 `json:"repository_ids,omitempty"` + + // The names of the repositories that the installation token can access. + // Providing repository names restricts the access of an installation token to specific repositories. + Repositories []string `json:"repositories,omitempty"` + + // The permissions granted to the access token. + // The permissions object includes the permission names and their access type. + Permissions *InstallationPermissions `json:"permissions,omitempty"` + } + + // InstallationPermissions lists the repository and organization permissions for an installation. + InstallationPermissions struct { + Actions string `json:"actions,omitempty"` + Administration string `json:"administration,omitempty"` + Blocking string `json:"blocking,omitempty"` + Checks string `json:"checks,omitempty"` + Contents string `json:"contents,omitempty"` + ContentReferences string `json:"content_references,omitempty"` + Deployments string `json:"deployments,omitempty"` + Emails string `json:"emails,omitempty"` + Environments string `json:"environments,omitempty"` + Followers string `json:"followers,omitempty"` + Issues string `json:"issues,omitempty"` + Metadata string `json:"metadata,omitempty"` + Members string `json:"members,omitempty"` + OrganizationAdministration string `json:"organization_administration,omitempty"` + OrganizationCustomRoles string `json:"organization_custom_roles,omitempty"` + OrganizationHooks string `json:"organization_hooks,omitempty"` + OrganizationPackages string `json:"organization_packages,omitempty"` + OrganizationPlan string `json:"organization_plan,omitempty"` + OrganizationPreReceiveHooks string `json:"organization_pre_receive_hooks,omitempty"` + OrganizationProjects string `json:"organization_projects,omitempty"` + OrganizationSecrets string `json:"organization_secrets,omitempty"` + OrganizationSelfHostedRunners string `json:"organization_self_hosted_runners,omitempty"` + OrganizationUserBlocking string `json:"organization_user_blocking,omitempty"` + Packages string `json:"packages,omitempty"` + Pages string `json:"pages,omitempty"` + PullRequests string `json:"pull_requests,omitempty"` + RepositoryHooks string `json:"repository_hooks,omitempty"` + RepositoryProjects string `json:"repository_projects,omitempty"` + RepositoryPreReceiveHooks string `json:"repository_pre_receive_hooks,omitempty"` + Secrets string `json:"secrets,omitempty"` + SecretScanningAlerts string `json:"secret_scanning_alerts,omitempty"` + SecurityEvents string `json:"security_events,omitempty"` + SingleFile string `json:"single_file,omitempty"` + Statuses string `json:"statuses,omitempty"` + TeamDiscussions string `json:"team_discussions,omitempty"` + VulnerabilityAlerts string `json:"vulnerability_alerts,omitempty"` + Workflows string `json:"workflows,omitempty"` + } + + // AppsService provides access to Apps-related functions. + AppsService interface { + // Get returns a single App. Passing the empty string will get + // the authenticated App. + Get(ctx context.Context, appSlug string) (*App, *Response, error) + + // ListInstallations lists the installations that the current App has. + ListInstallations(ctx context.Context, opts ListOptions) ([]*Installation, *Response, error) + + // GetInstallation returns the specified installation. + GetInstallation(ctx context.Context, id int64) (*Installation, *Response, error) + + // ListUserInstallations lists installations that are accessible to the authenticated user. + ListUserInstallations(ctx context.Context, opts ListOptions) ([]*Installation, *Response, error) + + // SuspendInstallation suspends the specified installation. + SuspendInstallation(ctx context.Context, id int64) (*Response, error) + + // UnsuspendInstallation unsuspends the specified installation. + UnsuspendInstallation(ctx context.Context, id int64) (*Response, error) + + // DeleteInstallation deletes the specified installation. + DeleteInstallation(ctx context.Context, id int64) (*Response, error) + + // CreateInstallationToken creates a new installation token. + CreateInstallationToken(ctx context.Context, id int64, opts *InstallationTokenOptions) (*InstallationToken, *Response, error) + + // FindOrganizationInstallation finds the organization's installation information. + FindOrganizationInstallation(ctx context.Context, org string) (*Installation, *Response, error) + + // FindRepositoryInstallation finds the repository's installation information. + FindRepositoryInstallation(ctx context.Context, owner, repo string) (*Installation, *Response, error) + + // FindRepositoryInstallationByID finds the repository's installation information by repository ID. + FindRepositoryInstallationByID(ctx context.Context, id int64) (*Installation, *Response, error) + + // FindUserInstallation finds the user's installation information. + FindUserInstallation(ctx context.Context, user string) (*Installation, *Response, error) + } +) diff --git a/scm/client.go b/scm/client.go index fba635ba..1453943e 100644 --- a/scm/client.go +++ b/scm/client.go @@ -110,6 +110,7 @@ type ( // Services used for communicating with the API. Driver Driver Linker Linker + Apps AppsService Contents ContentService Git GitService Organizations OrganizationService @@ -230,7 +231,7 @@ func (c *Client) Do(ctx context.Context, in *Request) (*Response, error) { return newResponse(res), nil } -//requestDetails checks if RequestContextKey exits in the context +// requestDetails checks if RequestContextKey exits in the context func (c *Client) requestDetails(ctx context.Context) (*RequestDetails, error) { requestDetails, _ := ctx.Value(RequestContextKey{}).(*RequestDetails) return requestDetails, nil diff --git a/scm/driver/azure/apps.go b/scm/driver/azure/apps.go new file mode 100644 index 00000000..321b22f4 --- /dev/null +++ b/scm/driver/azure/apps.go @@ -0,0 +1,63 @@ +// Copyright 2017 Drone.IO Inc. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package azure + +import ( + "context" + + "github.com/drone/go-scm/scm" +) + +type appsService struct { + client *wrapper +} + +func (s *appsService) Get(ctx context.Context, appSlug string) (*scm.App, *scm.Response, error) { + return nil, nil, scm.ErrNotSupported +} + +func (s *appsService) ListInstallations(ctx context.Context, opts scm.ListOptions) ([]*scm.Installation, *scm.Response, error) { + return nil, nil, scm.ErrNotSupported +} + +func (s *appsService) GetInstallation(ctx context.Context, id int64) (*scm.Installation, *scm.Response, error) { + return nil, nil, scm.ErrNotSupported +} + +func (s *appsService) ListUserInstallations(ctx context.Context, opts scm.ListOptions) ([]*scm.Installation, *scm.Response, error) { + return nil, nil, scm.ErrNotSupported +} + +func (s *appsService) SuspendInstallation(ctx context.Context, id int64) (*scm.Response, error) { + return nil, scm.ErrNotSupported +} + +func (s *appsService) UnsuspendInstallation(ctx context.Context, id int64) (*scm.Response, error) { + return nil, scm.ErrNotSupported +} + +func (s *appsService) DeleteInstallation(ctx context.Context, id int64) (*scm.Response, error) { + return nil, scm.ErrNotSupported +} + +func (s *appsService) CreateInstallationToken(ctx context.Context, id int64, opts *scm.InstallationTokenOptions) (*scm.InstallationToken, *scm.Response, error) { + return nil, nil, scm.ErrNotSupported +} + +func (s *appsService) FindOrganizationInstallation(ctx context.Context, org string) (*scm.Installation, *scm.Response, error) { + return nil, nil, scm.ErrNotSupported +} + +func (s *appsService) FindRepositoryInstallation(ctx context.Context, owner, repo string) (*scm.Installation, *scm.Response, error) { + return nil, nil, scm.ErrNotSupported +} + +func (s *appsService) FindRepositoryInstallationByID(ctx context.Context, id int64) (*scm.Installation, *scm.Response, error) { + return nil, nil, scm.ErrNotSupported +} + +func (s *appsService) FindUserInstallation(ctx context.Context, user string) (*scm.Installation, *scm.Response, error) { + return nil, nil, scm.ErrNotSupported +} diff --git a/scm/driver/azure/azure.go b/scm/driver/azure/azure.go index e762a6db..047798be 100644 --- a/scm/driver/azure/azure.go +++ b/scm/driver/azure/azure.go @@ -38,6 +38,7 @@ func New(uri, owner, project string) (*scm.Client, error) { // initialize services client.Driver = scm.DriverAzure client.Linker = &linker{base.String()} + client.Apps = &appsService{client} client.Contents = &contentService{client} client.Git = &gitService{client} client.Issues = &issueService{client} diff --git a/scm/driver/bitbucket/apps.go b/scm/driver/bitbucket/apps.go new file mode 100644 index 00000000..66b1706c --- /dev/null +++ b/scm/driver/bitbucket/apps.go @@ -0,0 +1,63 @@ +// Copyright 2017 Drone.IO Inc. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package bitbucket + +import ( + "context" + + "github.com/drone/go-scm/scm" +) + +type appsService struct { + client *wrapper +} + +func (s *appsService) Get(ctx context.Context, appSlug string) (*scm.App, *scm.Response, error) { + return nil, nil, scm.ErrNotSupported +} + +func (s *appsService) ListInstallations(ctx context.Context, opts scm.ListOptions) ([]*scm.Installation, *scm.Response, error) { + return nil, nil, scm.ErrNotSupported +} + +func (s *appsService) GetInstallation(ctx context.Context, id int64) (*scm.Installation, *scm.Response, error) { + return nil, nil, scm.ErrNotSupported +} + +func (s *appsService) ListUserInstallations(ctx context.Context, opts scm.ListOptions) ([]*scm.Installation, *scm.Response, error) { + return nil, nil, scm.ErrNotSupported +} + +func (s *appsService) SuspendInstallation(ctx context.Context, id int64) (*scm.Response, error) { + return nil, scm.ErrNotSupported +} + +func (s *appsService) UnsuspendInstallation(ctx context.Context, id int64) (*scm.Response, error) { + return nil, scm.ErrNotSupported +} + +func (s *appsService) DeleteInstallation(ctx context.Context, id int64) (*scm.Response, error) { + return nil, scm.ErrNotSupported +} + +func (s *appsService) CreateInstallationToken(ctx context.Context, id int64, opts *scm.InstallationTokenOptions) (*scm.InstallationToken, *scm.Response, error) { + return nil, nil, scm.ErrNotSupported +} + +func (s *appsService) FindOrganizationInstallation(ctx context.Context, org string) (*scm.Installation, *scm.Response, error) { + return nil, nil, scm.ErrNotSupported +} + +func (s *appsService) FindRepositoryInstallation(ctx context.Context, owner, repo string) (*scm.Installation, *scm.Response, error) { + return nil, nil, scm.ErrNotSupported +} + +func (s *appsService) FindRepositoryInstallationByID(ctx context.Context, id int64) (*scm.Installation, *scm.Response, error) { + return nil, nil, scm.ErrNotSupported +} + +func (s *appsService) FindUserInstallation(ctx context.Context, user string) (*scm.Installation, *scm.Response, error) { + return nil, nil, scm.ErrNotSupported +} diff --git a/scm/driver/bitbucket/bitbucket.go b/scm/driver/bitbucket/bitbucket.go index f05ab670..bab32cee 100644 --- a/scm/driver/bitbucket/bitbucket.go +++ b/scm/driver/bitbucket/bitbucket.go @@ -31,6 +31,7 @@ func New(uri string) (*scm.Client, error) { // initialize services client.Driver = scm.DriverBitbucket client.Linker = &linker{"https://bitbucket.org/"} + client.Apps = &appsService{client} client.Contents = &contentService{client} client.Git = &gitService{client} client.Issues = &issueService{client} diff --git a/scm/driver/gitea/apps.go b/scm/driver/gitea/apps.go new file mode 100644 index 00000000..a5db8a10 --- /dev/null +++ b/scm/driver/gitea/apps.go @@ -0,0 +1,63 @@ +// Copyright 2017 Drone.IO Inc. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package gitea + +import ( + "context" + + "github.com/drone/go-scm/scm" +) + +type appsService struct { + client *wrapper +} + +func (s *appsService) Get(ctx context.Context, appSlug string) (*scm.App, *scm.Response, error) { + return nil, nil, scm.ErrNotSupported +} + +func (s *appsService) ListInstallations(ctx context.Context, opts scm.ListOptions) ([]*scm.Installation, *scm.Response, error) { + return nil, nil, scm.ErrNotSupported +} + +func (s *appsService) GetInstallation(ctx context.Context, id int64) (*scm.Installation, *scm.Response, error) { + return nil, nil, scm.ErrNotSupported +} + +func (s *appsService) ListUserInstallations(ctx context.Context, opts scm.ListOptions) ([]*scm.Installation, *scm.Response, error) { + return nil, nil, scm.ErrNotSupported +} + +func (s *appsService) SuspendInstallation(ctx context.Context, id int64) (*scm.Response, error) { + return nil, scm.ErrNotSupported +} + +func (s *appsService) UnsuspendInstallation(ctx context.Context, id int64) (*scm.Response, error) { + return nil, scm.ErrNotSupported +} + +func (s *appsService) DeleteInstallation(ctx context.Context, id int64) (*scm.Response, error) { + return nil, scm.ErrNotSupported +} + +func (s *appsService) CreateInstallationToken(ctx context.Context, id int64, opts *scm.InstallationTokenOptions) (*scm.InstallationToken, *scm.Response, error) { + return nil, nil, scm.ErrNotSupported +} + +func (s *appsService) FindOrganizationInstallation(ctx context.Context, org string) (*scm.Installation, *scm.Response, error) { + return nil, nil, scm.ErrNotSupported +} + +func (s *appsService) FindRepositoryInstallation(ctx context.Context, owner, repo string) (*scm.Installation, *scm.Response, error) { + return nil, nil, scm.ErrNotSupported +} + +func (s *appsService) FindRepositoryInstallationByID(ctx context.Context, id int64) (*scm.Installation, *scm.Response, error) { + return nil, nil, scm.ErrNotSupported +} + +func (s *appsService) FindUserInstallation(ctx context.Context, user string) (*scm.Installation, *scm.Response, error) { + return nil, nil, scm.ErrNotSupported +} diff --git a/scm/driver/gitea/gitea.go b/scm/driver/gitea/gitea.go index 3e8031cb..51c77c38 100644 --- a/scm/driver/gitea/gitea.go +++ b/scm/driver/gitea/gitea.go @@ -32,10 +32,11 @@ func New(uri string) (*scm.Client, error) { // initialize services client.Driver = scm.DriverGitea client.Linker = &linker{base.String()} + client.Apps = &appsService{client} client.Contents = &contentService{client} client.Git = &gitService{client} client.Issues = &issueService{client} - client.Milestones = & milestoneService{client} + client.Milestones = &milestoneService{client} client.Organizations = &organizationService{client} client.PullRequests = &pullService{client} client.Repositories = &repositoryService{client} diff --git a/scm/driver/gitee/apps.go b/scm/driver/gitee/apps.go new file mode 100644 index 00000000..11e9a6ac --- /dev/null +++ b/scm/driver/gitee/apps.go @@ -0,0 +1,63 @@ +// Copyright 2017 Drone.IO Inc. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package gitee + +import ( + "context" + + "github.com/drone/go-scm/scm" +) + +type appsService struct { + client *wrapper +} + +func (s *appsService) Get(ctx context.Context, appSlug string) (*scm.App, *scm.Response, error) { + return nil, nil, scm.ErrNotSupported +} + +func (s *appsService) ListInstallations(ctx context.Context, opts scm.ListOptions) ([]*scm.Installation, *scm.Response, error) { + return nil, nil, scm.ErrNotSupported +} + +func (s *appsService) GetInstallation(ctx context.Context, id int64) (*scm.Installation, *scm.Response, error) { + return nil, nil, scm.ErrNotSupported +} + +func (s *appsService) ListUserInstallations(ctx context.Context, opts scm.ListOptions) ([]*scm.Installation, *scm.Response, error) { + return nil, nil, scm.ErrNotSupported +} + +func (s *appsService) SuspendInstallation(ctx context.Context, id int64) (*scm.Response, error) { + return nil, scm.ErrNotSupported +} + +func (s *appsService) UnsuspendInstallation(ctx context.Context, id int64) (*scm.Response, error) { + return nil, scm.ErrNotSupported +} + +func (s *appsService) DeleteInstallation(ctx context.Context, id int64) (*scm.Response, error) { + return nil, scm.ErrNotSupported +} + +func (s *appsService) CreateInstallationToken(ctx context.Context, id int64, opts *scm.InstallationTokenOptions) (*scm.InstallationToken, *scm.Response, error) { + return nil, nil, scm.ErrNotSupported +} + +func (s *appsService) FindOrganizationInstallation(ctx context.Context, org string) (*scm.Installation, *scm.Response, error) { + return nil, nil, scm.ErrNotSupported +} + +func (s *appsService) FindRepositoryInstallation(ctx context.Context, owner, repo string) (*scm.Installation, *scm.Response, error) { + return nil, nil, scm.ErrNotSupported +} + +func (s *appsService) FindRepositoryInstallationByID(ctx context.Context, id int64) (*scm.Installation, *scm.Response, error) { + return nil, nil, scm.ErrNotSupported +} + +func (s *appsService) FindUserInstallation(ctx context.Context, user string) (*scm.Installation, *scm.Response, error) { + return nil, nil, scm.ErrNotSupported +} diff --git a/scm/driver/gitee/gitee.go b/scm/driver/gitee/gitee.go index 9bf40fd2..59d5c679 100644 --- a/scm/driver/gitee/gitee.go +++ b/scm/driver/gitee/gitee.go @@ -30,6 +30,7 @@ func New(uri string) (*scm.Client, error) { // initialize services client.Driver = scm.DriverGitee client.Linker = &linker{websiteAddress(base)} + client.Apps = &appsService{client} client.Contents = &contentService{client} client.Git = &gitService{client} client.Issues = &issueService{client} diff --git a/scm/driver/github/apps.go b/scm/driver/github/apps.go new file mode 100644 index 00000000..f476181a --- /dev/null +++ b/scm/driver/github/apps.go @@ -0,0 +1,308 @@ +// Copyright 2017 Drone.IO Inc. 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" + "time" + + "github.com/drone/go-scm/scm" +) + +type appsService struct { + client *wrapper +} + +type app struct { + ID int64 `json:"id,omitempty"` + Slug string `json:"slug,omitempty"` + NodeID string `json:"node_id,omitempty"` + Owner *user `json:"owner,omitempty"` + Name string `json:"name,omitempty"` + Description string `json:"description,omitempty"` + ExternalURL string `json:"external_url,omitempty"` + HTMLURL string `json:"html_url,omitempty"` + CreatedAt time.Time `json:"created_at,omitempty"` + UpdatedAt time.Time `json:"updated_at,omitempty"` + Permissions *installationPermissions `json:"permissions,omitempty"` + Events []string `json:"events,omitempty"` +} + +type installation struct { + ID int64 `json:"id,omitempty"` + NodeID string `json:"node_id,omitempty"` + AppID int64 `json:"app_id,omitempty"` + AppSlug string `json:"app_slug,omitempty"` + TargetID int64 `json:"target_id,omitempty"` + Account *user `json:"account,omitempty"` + AccessTokensURL string `json:"access_tokens_url,omitempty"` + RepositoriesURL string `json:"repositories_url,omitempty"` + HTMLURL string `json:"html_url,omitempty"` + TargetType string `json:"target_type,omitempty"` + SingleFileName string `json:"single_file_name,omitempty"` + RepositorySelection string `json:"repository_selection,omitempty"` + Events []string `json:"events,omitempty"` + SingleFilePaths []string `json:"single_file_paths,omitempty"` + Permissions *installationPermissions `json:"permissions,omitempty"` + CreatedAt time.Time `json:"created_at,omitempty"` + UpdatedAt time.Time `json:"updated_at,omitempty"` + HasMultipleSingleFiles *bool `json:"has_multiple_single_files,omitempty"` + SuspendedBy *user `json:"suspended_by,omitempty"` + SuspendedAt *time.Time `json:"suspended_at,omitempty"` +} + +type installationToken struct { + Token string `json:"token,omitempty"` + ExpiresAt time.Time `json:"expires_at,omitempty"` + Permissions *installationPermissions `json:"permissions,omitempty"` + Repositories []*repository `json:"repositories,omitempty"` +} + +type installationPermissions struct { + Actions string `json:"actions,omitempty"` + Administration string `json:"administration,omitempty"` + Blocking string `json:"blocking,omitempty"` + Checks string `json:"checks,omitempty"` + Contents string `json:"contents,omitempty"` + ContentReferences string `json:"content_references,omitempty"` + Deployments string `json:"deployments,omitempty"` + Emails string `json:"emails,omitempty"` + Environments string `json:"environments,omitempty"` + Followers string `json:"followers,omitempty"` + Issues string `json:"issues,omitempty"` + Metadata string `json:"metadata,omitempty"` + Members string `json:"members,omitempty"` + OrganizationAdministration string `json:"organization_administration,omitempty"` + OrganizationCustomRoles string `json:"organization_custom_roles,omitempty"` + OrganizationHooks string `json:"organization_hooks,omitempty"` + OrganizationPackages string `json:"organization_packages,omitempty"` + OrganizationPlan string `json:"organization_plan,omitempty"` + OrganizationPreReceiveHooks string `json:"organization_pre_receive_hooks,omitempty"` + OrganizationProjects string `json:"organization_projects,omitempty"` + OrganizationSecrets string `json:"organization_secrets,omitempty"` + OrganizationSelfHostedRunners string `json:"organization_self_hosted_runners,omitempty"` + OrganizationUserBlocking string `json:"organization_user_blocking,omitempty"` + Packages string `json:"packages,omitempty"` + Pages string `json:"pages,omitempty"` + PullRequests string `json:"pull_requests,omitempty"` + RepositoryHooks string `json:"repository_hooks,omitempty"` + RepositoryProjects string `json:"repository_projects,omitempty"` + RepositoryPreReceiveHooks string `json:"repository_pre_receive_hooks,omitempty"` + Secrets string `json:"secrets,omitempty"` + SecretScanningAlerts string `json:"secret_scanning_alerts,omitempty"` + SecurityEvents string `json:"security_events,omitempty"` + SingleFile string `json:"single_file,omitempty"` + Statuses string `json:"statuses,omitempty"` + TeamDiscussions string `json:"team_discussions,omitempty"` + VulnerabilityAlerts string `json:"vulnerability_alerts,omitempty"` + Workflows string `json:"workflows,omitempty"` +} + +func (s *appsService) Get(ctx context.Context, appSlug string) (*scm.App, *scm.Response, error) { + var path string + if appSlug != "" { + path = fmt.Sprintf("apps/%s", appSlug) + } else { + path = "app" + } + + out := new(app) + res, err := s.client.do(ctx, "GET", path, nil, out) + return convertApp(out), res, err +} + +func (s *appsService) ListInstallations(ctx context.Context, opts scm.ListOptions) ([]*scm.Installation, *scm.Response, error) { + path := fmt.Sprintf("app/installations?%s", encodeListOptions(opts)) + out := []*installation{} + res, err := s.client.do(ctx, "GET", path, nil, &out) + return convertInstallationList(out), res, err +} + +func (s *appsService) GetInstallation(ctx context.Context, id int64) (*scm.Installation, *scm.Response, error) { + path := fmt.Sprintf("app/installations/%d", id) + out := new(installation) + res, err := s.client.do(ctx, "GET", path, nil, out) + return convertInstallation(out), res, err +} + +func (s *appsService) ListUserInstallations(ctx context.Context, opts scm.ListOptions) ([]*scm.Installation, *scm.Response, error) { + path := fmt.Sprintf("user/installations?%s", encodeListOptions(opts)) + var result struct { + Installations []*installation `json:"installations"` + } + res, err := s.client.do(ctx, "GET", path, nil, &result) + return convertInstallationList(result.Installations), res, err +} + +func (s *appsService) SuspendInstallation(ctx context.Context, id int64) (*scm.Response, error) { + path := fmt.Sprintf("app/installations/%d/suspended", id) + res, err := s.client.do(ctx, "PUT", path, nil, nil) + return res, err +} + +func (s *appsService) UnsuspendInstallation(ctx context.Context, id int64) (*scm.Response, error) { + path := fmt.Sprintf("app/installations/%d/suspended", id) + res, err := s.client.do(ctx, "DELETE", path, nil, nil) + return res, err +} + +func (s *appsService) DeleteInstallation(ctx context.Context, id int64) (*scm.Response, error) { + path := fmt.Sprintf("app/installations/%d", id) + res, err := s.client.do(ctx, "DELETE", path, nil, nil) + return res, err +} + +func (s *appsService) CreateInstallationToken(ctx context.Context, id int64, opts *scm.InstallationTokenOptions) (*scm.InstallationToken, *scm.Response, error) { + path := fmt.Sprintf("app/installations/%d/access_tokens", id) + out := new(installationToken) + res, err := s.client.do(ctx, "POST", path, opts, out) + return convertInstallationToken(out), res, err +} + +func (s *appsService) FindOrganizationInstallation(ctx context.Context, org string) (*scm.Installation, *scm.Response, error) { + path := fmt.Sprintf("orgs/%s/installation", org) + out := new(installation) + res, err := s.client.do(ctx, "GET", path, nil, out) + return convertInstallation(out), res, err +} + +func (s *appsService) FindRepositoryInstallation(ctx context.Context, owner, repo string) (*scm.Installation, *scm.Response, error) { + path := fmt.Sprintf("repos/%s/%s/installation", owner, repo) + out := new(installation) + res, err := s.client.do(ctx, "GET", path, nil, out) + return convertInstallation(out), res, err +} + +func (s *appsService) FindRepositoryInstallationByID(ctx context.Context, id int64) (*scm.Installation, *scm.Response, error) { + path := fmt.Sprintf("repositories/%d/installation", id) + out := new(installation) + res, err := s.client.do(ctx, "GET", path, nil, out) + return convertInstallation(out), res, err +} + +func (s *appsService) FindUserInstallation(ctx context.Context, user string) (*scm.Installation, *scm.Response, error) { + path := fmt.Sprintf("users/%s/installation", user) + out := new(installation) + res, err := s.client.do(ctx, "GET", path, nil, out) + return convertInstallation(out), res, err +} + +func convertApp(from *app) *scm.App { + if from == nil { + return nil + } + return &scm.App{ + ID: from.ID, + Slug: from.Slug, + NodeID: from.NodeID, + Owner: convertUser(from.Owner), + Name: from.Name, + Description: from.Description, + ExternalURL: from.ExternalURL, + HTMLURL: from.HTMLURL, + CreatedAt: from.CreatedAt, + UpdatedAt: from.UpdatedAt, + Permissions: convertInstallationPermissions(from.Permissions), + Events: from.Events, + } +} + +func convertInstallation(from *installation) *scm.Installation { + if from == nil { + return nil + } + hasMultipleSingleFiles := false + if from.HasMultipleSingleFiles != nil { + hasMultipleSingleFiles = *from.HasMultipleSingleFiles + } + return &scm.Installation{ + ID: from.ID, + NodeID: from.NodeID, + AppID: from.AppID, + AppSlug: from.AppSlug, + TargetID: from.TargetID, + Account: convertUser(from.Account), + AccessTokensURL: from.AccessTokensURL, + RepositoriesURL: from.RepositoriesURL, + HTMLURL: from.HTMLURL, + TargetType: from.TargetType, + SingleFileName: from.SingleFileName, + RepositorySelection: from.RepositorySelection, + Events: from.Events, + SingleFilePaths: from.SingleFilePaths, + Permissions: convertInstallationPermissions(from.Permissions), + CreatedAt: from.CreatedAt, + UpdatedAt: from.UpdatedAt, + HasMultipleSingleFiles: hasMultipleSingleFiles, + SuspendedBy: convertUser(from.SuspendedBy), + SuspendedAt: from.SuspendedAt, + } +} + +func convertInstallationList(from []*installation) []*scm.Installation { + to := []*scm.Installation{} + for _, v := range from { + to = append(to, convertInstallation(v)) + } + return to +} + +func convertInstallationToken(from *installationToken) *scm.InstallationToken { + if from == nil { + return nil + } + return &scm.InstallationToken{ + Token: from.Token, + ExpiresAt: from.ExpiresAt, + Permissions: convertInstallationPermissions(from.Permissions), + Repositories: convertRepositoryList(from.Repositories), + } +} + +func convertInstallationPermissions(from *installationPermissions) *scm.InstallationPermissions { + if from == nil { + return nil + } + return &scm.InstallationPermissions{ + Actions: from.Actions, + Administration: from.Administration, + Blocking: from.Blocking, + Checks: from.Checks, + Contents: from.Contents, + ContentReferences: from.ContentReferences, + Deployments: from.Deployments, + Emails: from.Emails, + Environments: from.Environments, + Followers: from.Followers, + Issues: from.Issues, + Metadata: from.Metadata, + Members: from.Members, + OrganizationAdministration: from.OrganizationAdministration, + OrganizationCustomRoles: from.OrganizationCustomRoles, + OrganizationHooks: from.OrganizationHooks, + OrganizationPackages: from.OrganizationPackages, + OrganizationPlan: from.OrganizationPlan, + OrganizationPreReceiveHooks: from.OrganizationPreReceiveHooks, + OrganizationProjects: from.OrganizationProjects, + OrganizationSecrets: from.OrganizationSecrets, + OrganizationSelfHostedRunners: from.OrganizationSelfHostedRunners, + OrganizationUserBlocking: from.OrganizationUserBlocking, + Packages: from.Packages, + Pages: from.Pages, + PullRequests: from.PullRequests, + RepositoryHooks: from.RepositoryHooks, + RepositoryProjects: from.RepositoryProjects, + RepositoryPreReceiveHooks: from.RepositoryPreReceiveHooks, + Secrets: from.Secrets, + SecretScanningAlerts: from.SecretScanningAlerts, + SecurityEvents: from.SecurityEvents, + SingleFile: from.SingleFile, + Statuses: from.Statuses, + TeamDiscussions: from.TeamDiscussions, + VulnerabilityAlerts: from.VulnerabilityAlerts, + Workflows: from.Workflows, + } +} diff --git a/scm/driver/github/apps_test.go b/scm/driver/github/apps_test.go new file mode 100644 index 00000000..82a454d4 --- /dev/null +++ b/scm/driver/github/apps_test.go @@ -0,0 +1,167 @@ +// Copyright 2017 Drone.IO Inc. 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" + "testing" + + "github.com/drone/go-scm/scm" + "github.com/h2non/gock" +) + +func TestAppsCreateInstallationToken(t *testing.T) { + defer gock.Off() + + gock.New("https://api.github.com"). + Post("/app/installations/123/access_tokens"). + Reply(201). + Type("application/json"). + File("testdata/installation_token.json") + + client := NewDefault() + opts := &scm.InstallationTokenOptions{ + RepositoryIDs: []int64{123456}, + Repositories: []string{"owner/repo"}, + Permissions: &scm.InstallationPermissions{ + Contents: "read", + Issues: "write", + }, + } + + token, res, err := client.Apps.CreateInstallationToken(context.Background(), 123, opts) + if err != nil { + t.Error(err) + return + } + + if got, want := res.Status, 201; got != want { + t.Errorf("Want response status %d, got %d", want, got) + } + + if got, want := token.Token, "ghs_16C7e42F292c6912E7710c838347Ae178B4a"; got != want { + t.Errorf("Want token %s, got %s", want, got) + } + + if got, want := len(token.Repositories), 1; got != want { + t.Errorf("Want %d repositories, got %d", want, got) + } + + if got, want := token.Repositories[0].Name, "Hello-World"; got != want { + t.Errorf("Want repository name %s, got %s", want, got) + } +} + +func TestAppsGet(t *testing.T) { + defer gock.Off() + + gock.New("https://api.github.com"). + Get("/app"). + Reply(200). + Type("application/json"). + File("testdata/app.json") + + client := NewDefault() + app, res, err := client.Apps.Get(context.Background(), "") + if err != nil { + t.Error(err) + return + } + + if got, want := res.Status, 200; got != want { + t.Errorf("Want response status %d, got %d", want, got) + } + + if got, want := app.ID, int64(1); got != want { + t.Errorf("Want app ID %d, got %d", want, got) + } + + if got, want := app.Name, "octocat-app"; got != want { + t.Errorf("Want app name %s, got %s", want, got) + } +} + +func TestAppsGetInstallation(t *testing.T) { + defer gock.Off() + + gock.New("https://api.github.com"). + Get("/app/installations/123"). + Reply(200). + Type("application/json"). + File("testdata/installation.json") + + client := NewDefault() + installation, res, err := client.Apps.GetInstallation(context.Background(), 123) + if err != nil { + t.Error(err) + return + } + + if got, want := res.Status, 200; got != want { + t.Errorf("Want response status %d, got %d", want, got) + } + + if got, want := installation.ID, int64(123); got != want { + t.Errorf("Want installation ID %d, got %d", want, got) + } + + if got, want := installation.AppID, int64(1); got != want { + t.Errorf("Want app ID %d, got %d", want, got) + } +} + +func TestAppsListInstallations(t *testing.T) { + defer gock.Off() + + gock.New("https://api.github.com"). + Get("/app/installations"). + Reply(200). + Type("application/json"). + File("testdata/installations.json") + + client := NewDefault() + installations, res, err := client.Apps.ListInstallations(context.Background(), scm.ListOptions{}) + if err != nil { + t.Error(err) + return + } + + if got, want := res.Status, 200; got != want { + t.Errorf("Want response status %d, got %d", want, got) + } + + if got, want := len(installations), 1; got != want { + t.Errorf("Want %d installations, got %d", want, got) + } + + if got, want := installations[0].ID, int64(123); got != want { + t.Errorf("Want installation ID %d, got %d", want, got) + } +} + +func TestAppsFindRepositoryInstallation(t *testing.T) { + defer gock.Off() + + gock.New("https://api.github.com"). + Get("/repos/octocat/Hello-World/installation"). + Reply(200). + Type("application/json"). + File("testdata/installation.json") + + client := NewDefault() + installation, res, err := client.Apps.FindRepositoryInstallation(context.Background(), "octocat", "Hello-World") + if err != nil { + t.Error(err) + return + } + + if got, want := res.Status, 200; got != want { + t.Errorf("Want response status %d, got %d", want, got) + } + + if got, want := installation.ID, int64(123); got != want { + t.Errorf("Want installation ID %d, got %d", want, got) + } +} diff --git a/scm/driver/github/github.go b/scm/driver/github/github.go index 8464b3e2..4530e155 100644 --- a/scm/driver/github/github.go +++ b/scm/driver/github/github.go @@ -35,6 +35,7 @@ func New(uri string) (*scm.Client, error) { // initialize services client.Driver = scm.DriverGithub client.Linker = &linker{websiteAddress(base)} + client.Apps = &appsService{client} client.Contents = &contentService{client} client.Git = &gitService{client} client.Issues = &issueService{client} diff --git a/scm/driver/github/testdata/app.json b/scm/driver/github/testdata/app.json new file mode 100644 index 00000000..02c9ac41 --- /dev/null +++ b/scm/driver/github/testdata/app.json @@ -0,0 +1,39 @@ +{ + "id": 1, + "slug": "octocat-app", + "node_id": "MDExOkludGVncmF0aW9uMQ==", + "owner": { + "login": "octocat", + "id": 1, + "node_id": "MDQ6VXNlcjE=", + "avatar_url": "https://github.com/images/error/octocat_happy.gif", + "gravatar_id": "", + "url": "https://api.github.com/users/octocat", + "html_url": "https://github.com/octocat", + "followers_url": "https://api.github.com/users/octocat/followers", + "following_url": "https://api.github.com/users/octocat/following{/other_user}", + "gists_url": "https://api.github.com/users/octocat/gists{/gist_id}", + "starred_url": "https://api.github.com/users/octocat/starred{/owner}{/repo}", + "subscriptions_url": "https://api.github.com/users/octocat/subscriptions", + "organizations_url": "https://api.github.com/users/octocat/orgs", + "repos_url": "https://api.github.com/users/octocat/repos", + "events_url": "https://api.github.com/users/octocat/events{/privacy}", + "received_events_url": "https://api.github.com/users/octocat/received_events", + "type": "User", + "site_admin": false + }, + "name": "octocat-app", + "description": "A GitHub App", + "external_url": "https://example.com", + "html_url": "https://github.com/apps/octocat-app", + "created_at": "2017-07-08T16:18:44-04:00", + "updated_at": "2017-07-08T16:18:44-04:00", + "permissions": { + "contents": "read", + "issues": "write" + }, + "events": [ + "push", + "pull_request" + ] +} \ No newline at end of file diff --git a/scm/driver/github/testdata/installation.json b/scm/driver/github/testdata/installation.json new file mode 100644 index 00000000..0f380599 --- /dev/null +++ b/scm/driver/github/testdata/installation.json @@ -0,0 +1,47 @@ +{ + "id": 123, + "node_id": "MDExOkludGVncmF0aW9uMTIz", + "app_id": 1, + "app_slug": "octocat-app", + "target_id": 1, + "account": { + "login": "octocat", + "id": 1, + "node_id": "MDQ6VXNlcjE=", + "avatar_url": "https://github.com/images/error/octocat_happy.gif", + "gravatar_id": "", + "url": "https://api.github.com/users/octocat", + "html_url": "https://github.com/octocat", + "followers_url": "https://api.github.com/users/octocat/followers", + "following_url": "https://api.github.com/users/octocat/following{/other_user}", + "gists_url": "https://api.github.com/users/octocat/gists{/gist_id}", + "starred_url": "https://api.github.com/users/octocat/starred{/owner}{/repo}", + "subscriptions_url": "https://api.github.com/users/octocat/subscriptions", + "organizations_url": "https://api.github.com/users/octocat/orgs", + "repos_url": "https://api.github.com/users/octocat/repos", + "events_url": "https://api.github.com/users/octocat/events{/privacy}", + "received_events_url": "https://api.github.com/users/octocat/received_events", + "type": "User", + "site_admin": false + }, + "access_tokens_url": "https://api.github.com/app/installations/123/access_tokens", + "repositories_url": "https://api.github.com/installation/repositories", + "html_url": "https://github.com/settings/installations/123", + "target_type": "User", + "single_file_name": null, + "repository_selection": "all", + "events": [ + "push", + "pull_request" + ], + "single_file_paths": [], + "permissions": { + "contents": "read", + "issues": "write" + }, + "created_at": "2017-07-08T16:18:44-04:00", + "updated_at": "2017-07-08T16:18:44-04:00", + "has_multiple_single_files": false, + "suspended_by": null, + "suspended_at": null +} \ No newline at end of file diff --git a/scm/driver/github/testdata/installation_token.json b/scm/driver/github/testdata/installation_token.json new file mode 100644 index 00000000..aff884ac --- /dev/null +++ b/scm/driver/github/testdata/installation_token.json @@ -0,0 +1,115 @@ +{ + "token": "ghs_16C7e42F292c6912E7710c838347Ae178B4a", + "expires_at": "2016-07-11T22:14:10Z", + "permissions": { + "contents": "read", + "issues": "write" + }, + "repositories": [ + { + "id": 1296269, + "node_id": "MDEwOlJlcG9zaXRvcnkxMjk2MjY5", + "name": "Hello-World", + "full_name": "octocat/Hello-World", + "private": false, + "owner": { + "login": "octocat", + "id": 1, + "node_id": "MDQ6VXNlcjE=", + "avatar_url": "https://github.com/images/error/octocat_happy.gif", + "gravatar_id": "", + "url": "https://api.github.com/users/octocat", + "html_url": "https://github.com/octocat", + "followers_url": "https://api.github.com/users/octocat/followers", + "following_url": "https://api.github.com/users/octocat/following{/other_user}", + "gists_url": "https://api.github.com/users/octocat/gists{/gist_id}", + "starred_url": "https://api.github.com/users/octocat/starred{/owner}{/repo}", + "subscriptions_url": "https://api.github.com/users/octocat/subscriptions", + "organizations_url": "https://api.github.com/users/octocat/orgs", + "repos_url": "https://api.github.com/users/octocat/repos", + "events_url": "https://api.github.com/users/octocat/events{/privacy}", + "received_events_url": "https://api.github.com/users/octocat/received_events", + "type": "User", + "site_admin": false + }, + "html_url": "https://github.com/octocat/Hello-World", + "description": "My first repository on GitHub!", + "fork": false, + "url": "https://api.github.com/repos/octocat/Hello-World", + "archive_url": "https://api.github.com/repos/octocat/Hello-World/{archive_format}{/ref}", + "assignees_url": "https://api.github.com/repos/octocat/Hello-World/assignees{/user}", + "blobs_url": "https://api.github.com/repos/octocat/Hello-World/git/blobs{/sha}", + "branches_url": "https://api.github.com/repos/octocat/Hello-World/branches{/branch}", + "collaborators_url": "https://api.github.com/repos/octocat/Hello-World/collaborators{/collaborator}", + "comments_url": "https://api.github.com/repos/octocat/Hello-World/comments{/number}", + "commits_url": "https://api.github.com/repos/octocat/Hello-World/commits{/sha}", + "compare_url": "https://api.github.com/repos/octocat/Hello-World/compare/{base}...{head}", + "contents_url": "https://api.github.com/repos/octocat/Hello-World/contents/{+path}", + "contributors_url": "https://api.github.com/repos/octocat/Hello-World/contributors", + "deployments_url": "https://api.github.com/repos/octocat/Hello-World/deployments", + "downloads_url": "https://api.github.com/repos/octocat/Hello-World/downloads", + "events_url": "https://api.github.com/repos/octocat/Hello-World/events", + "forks_url": "https://api.github.com/repos/octocat/Hello-World/forks", + "git_commits_url": "https://api.github.com/repos/octocat/Hello-World/git/commits{/sha}", + "git_refs_url": "https://api.github.com/repos/octocat/Hello-World/git/refs{/sha}", + "git_tags_url": "https://api.github.com/repos/octocat/Hello-World/git/tags{/sha}", + "git_url": "git:github.com/octocat/Hello-World.git", + "issue_comment_url": "https://api.github.com/repos/octocat/Hello-World/issues/comments{/number}", + "issue_events_url": "https://api.github.com/repos/octocat/Hello-World/issues/events{/number}", + "issues_url": "https://api.github.com/repos/octocat/Hello-World/issues{/number}", + "keys_url": "https://api.github.com/repos/octocat/Hello-World/keys{/key_id}", + "labels_url": "https://api.github.com/repos/octocat/Hello-World/labels{/name}", + "languages_url": "https://api.github.com/repos/octocat/Hello-World/languages", + "merges_url": "https://api.github.com/repos/octocat/Hello-World/merges", + "milestones_url": "https://api.github.com/repos/octocat/Hello-World/milestones{/number}", + "notifications_url": "https://api.github.com/repos/octocat/Hello-World/notifications{?since,all,participating}", + "pulls_url": "https://api.github.com/repos/octocat/Hello-World/pulls{/number}", + "releases_url": "https://api.github.com/repos/octocat/Hello-World/releases{/id}", + "ssh_url": "git@github.com:octocat/Hello-World.git", + "stargazers_url": "https://api.github.com/repos/octocat/Hello-World/stargazers", + "statuses_url": "https://api.github.com/repos/octocat/Hello-World/statuses/{sha}", + "subscribers_url": "https://api.github.com/repos/octocat/Hello-World/subscribers", + "subscription_url": "https://api.github.com/repos/octocat/Hello-World/subscription", + "tags_url": "https://api.github.com/repos/octocat/Hello-World/tags", + "teams_url": "https://api.github.com/repos/octocat/Hello-World/teams", + "trees_url": "https://api.github.com/repos/octocat/Hello-World/git/trees{/sha}", + "clone_url": "https://github.com/octocat/Hello-World.git", + "mirror_url": "git:git.example.com/octocat/Hello-World", + "hooks_url": "https://api.github.com/repos/octocat/Hello-World/hooks", + "svn_url": "https://svn.github.com/octocat/Hello-World", + "homepage": "https://github.com", + "language": null, + "forks_count": 9, + "stargazers_count": 80, + "watchers_count": 80, + "size": 108, + "default_branch": "master", + "open_issues_count": 2, + "topics": [ + "octocat", + "atom", + "electron", + "api" + ], + "has_issues": true, + "has_projects": true, + "has_wiki": true, + "has_pages": false, + "has_downloads": true, + "archived": false, + "disabled": false, + "license": { + "key": "mit", + "name": "MIT License", + "url": "https://api.github.com/licenses/mit", + "spdx_id": "MIT", + "node_id": "MDc6TGljZW5zZW1pdA==" + }, + "permissions": { + "admin": false, + "push": false, + "pull": true + } + } + ] +} \ No newline at end of file diff --git a/scm/driver/github/testdata/installations.json b/scm/driver/github/testdata/installations.json new file mode 100644 index 00000000..3012defd --- /dev/null +++ b/scm/driver/github/testdata/installations.json @@ -0,0 +1,49 @@ +[ + { + "id": 123, + "node_id": "MDExOkludGVncmF0aW9uMTIz", + "app_id": 1, + "app_slug": "octocat-app", + "target_id": 1, + "account": { + "login": "octocat", + "id": 1, + "node_id": "MDQ6VXNlcjE=", + "avatar_url": "https://github.com/images/error/octocat_happy.gif", + "gravatar_id": "", + "url": "https://api.github.com/users/octocat", + "html_url": "https://github.com/octocat", + "followers_url": "https://api.github.com/users/octocat/followers", + "following_url": "https://api.github.com/users/octocat/following{/other_user}", + "gists_url": "https://api.github.com/users/octocat/gists{/gist_id}", + "starred_url": "https://api.github.com/users/octocat/starred{/owner}{/repo}", + "subscriptions_url": "https://api.github.com/users/octocat/subscriptions", + "organizations_url": "https://api.github.com/users/octocat/orgs", + "repos_url": "https://api.github.com/users/octocat/repos", + "events_url": "https://api.github.com/users/octocat/events{/privacy}", + "received_events_url": "https://api.github.com/users/octocat/received_events", + "type": "User", + "site_admin": false + }, + "access_tokens_url": "https://api.github.com/app/installations/123/access_tokens", + "repositories_url": "https://api.github.com/installation/repositories", + "html_url": "https://github.com/settings/installations/123", + "target_type": "User", + "single_file_name": null, + "repository_selection": "all", + "events": [ + "push", + "pull_request" + ], + "single_file_paths": [], + "permissions": { + "contents": "read", + "issues": "write" + }, + "created_at": "2017-07-08T16:18:44-04:00", + "updated_at": "2017-07-08T16:18:44-04:00", + "has_multiple_single_files": false, + "suspended_by": null, + "suspended_at": null + } +] \ No newline at end of file diff --git a/scm/driver/github/user.go b/scm/driver/github/user.go index db34ade7..a254887a 100644 --- a/scm/driver/github/user.go +++ b/scm/driver/github/user.go @@ -60,6 +60,9 @@ type email struct { } func convertUser(from *user) *scm.User { + if from == nil { + return nil + } return &scm.User{ Avatar: from.Avatar, Email: from.Email.String, diff --git a/scm/driver/gitlab/apps.go b/scm/driver/gitlab/apps.go new file mode 100644 index 00000000..fd014208 --- /dev/null +++ b/scm/driver/gitlab/apps.go @@ -0,0 +1,63 @@ +// Copyright 2017 Drone.IO Inc. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package gitlab + +import ( + "context" + + "github.com/drone/go-scm/scm" +) + +type appsService struct { + client *wrapper +} + +func (s *appsService) Get(ctx context.Context, appSlug string) (*scm.App, *scm.Response, error) { + return nil, nil, scm.ErrNotSupported +} + +func (s *appsService) ListInstallations(ctx context.Context, opts scm.ListOptions) ([]*scm.Installation, *scm.Response, error) { + return nil, nil, scm.ErrNotSupported +} + +func (s *appsService) GetInstallation(ctx context.Context, id int64) (*scm.Installation, *scm.Response, error) { + return nil, nil, scm.ErrNotSupported +} + +func (s *appsService) ListUserInstallations(ctx context.Context, opts scm.ListOptions) ([]*scm.Installation, *scm.Response, error) { + return nil, nil, scm.ErrNotSupported +} + +func (s *appsService) SuspendInstallation(ctx context.Context, id int64) (*scm.Response, error) { + return nil, scm.ErrNotSupported +} + +func (s *appsService) UnsuspendInstallation(ctx context.Context, id int64) (*scm.Response, error) { + return nil, scm.ErrNotSupported +} + +func (s *appsService) DeleteInstallation(ctx context.Context, id int64) (*scm.Response, error) { + return nil, scm.ErrNotSupported +} + +func (s *appsService) CreateInstallationToken(ctx context.Context, id int64, opts *scm.InstallationTokenOptions) (*scm.InstallationToken, *scm.Response, error) { + return nil, nil, scm.ErrNotSupported +} + +func (s *appsService) FindOrganizationInstallation(ctx context.Context, org string) (*scm.Installation, *scm.Response, error) { + return nil, nil, scm.ErrNotSupported +} + +func (s *appsService) FindRepositoryInstallation(ctx context.Context, owner, repo string) (*scm.Installation, *scm.Response, error) { + return nil, nil, scm.ErrNotSupported +} + +func (s *appsService) FindRepositoryInstallationByID(ctx context.Context, id int64) (*scm.Installation, *scm.Response, error) { + return nil, nil, scm.ErrNotSupported +} + +func (s *appsService) FindUserInstallation(ctx context.Context, user string) (*scm.Installation, *scm.Response, error) { + return nil, nil, scm.ErrNotSupported +} diff --git a/scm/driver/gitlab/gitlab.go b/scm/driver/gitlab/gitlab.go index 4d92016c..cadb67cc 100644 --- a/scm/driver/gitlab/gitlab.go +++ b/scm/driver/gitlab/gitlab.go @@ -30,6 +30,7 @@ func New(uri string) (*scm.Client, error) { // initialize services client.Driver = scm.DriverGitlab client.Linker = &linker{base.String()} + client.Apps = &appsService{client} client.Contents = &contentService{client} client.Git = &gitService{client} client.Issues = &issueService{client} diff --git a/scm/driver/gogs/apps.go b/scm/driver/gogs/apps.go new file mode 100644 index 00000000..33ddbc1b --- /dev/null +++ b/scm/driver/gogs/apps.go @@ -0,0 +1,63 @@ +// Copyright 2017 Drone.IO Inc. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package gogs + +import ( + "context" + + "github.com/drone/go-scm/scm" +) + +type appsService struct { + client *wrapper +} + +func (s *appsService) Get(ctx context.Context, appSlug string) (*scm.App, *scm.Response, error) { + return nil, nil, scm.ErrNotSupported +} + +func (s *appsService) ListInstallations(ctx context.Context, opts scm.ListOptions) ([]*scm.Installation, *scm.Response, error) { + return nil, nil, scm.ErrNotSupported +} + +func (s *appsService) GetInstallation(ctx context.Context, id int64) (*scm.Installation, *scm.Response, error) { + return nil, nil, scm.ErrNotSupported +} + +func (s *appsService) ListUserInstallations(ctx context.Context, opts scm.ListOptions) ([]*scm.Installation, *scm.Response, error) { + return nil, nil, scm.ErrNotSupported +} + +func (s *appsService) SuspendInstallation(ctx context.Context, id int64) (*scm.Response, error) { + return nil, scm.ErrNotSupported +} + +func (s *appsService) UnsuspendInstallation(ctx context.Context, id int64) (*scm.Response, error) { + return nil, scm.ErrNotSupported +} + +func (s *appsService) DeleteInstallation(ctx context.Context, id int64) (*scm.Response, error) { + return nil, scm.ErrNotSupported +} + +func (s *appsService) CreateInstallationToken(ctx context.Context, id int64, opts *scm.InstallationTokenOptions) (*scm.InstallationToken, *scm.Response, error) { + return nil, nil, scm.ErrNotSupported +} + +func (s *appsService) FindOrganizationInstallation(ctx context.Context, org string) (*scm.Installation, *scm.Response, error) { + return nil, nil, scm.ErrNotSupported +} + +func (s *appsService) FindRepositoryInstallation(ctx context.Context, owner, repo string) (*scm.Installation, *scm.Response, error) { + return nil, nil, scm.ErrNotSupported +} + +func (s *appsService) FindRepositoryInstallationByID(ctx context.Context, id int64) (*scm.Installation, *scm.Response, error) { + return nil, nil, scm.ErrNotSupported +} + +func (s *appsService) FindUserInstallation(ctx context.Context, user string) (*scm.Installation, *scm.Response, error) { + return nil, nil, scm.ErrNotSupported +} diff --git a/scm/driver/gogs/gogs.go b/scm/driver/gogs/gogs.go index 41e3f429..96f294bc 100644 --- a/scm/driver/gogs/gogs.go +++ b/scm/driver/gogs/gogs.go @@ -32,6 +32,7 @@ func New(uri string) (*scm.Client, error) { // initialize services client.Driver = scm.DriverGogs client.Linker = &linker{base.String()} + client.Apps = &appsService{client} client.Contents = &contentService{client} client.Git = &gitService{client} client.Issues = &issueService{client} diff --git a/scm/driver/harness/apps.go b/scm/driver/harness/apps.go new file mode 100644 index 00000000..7a47d6da --- /dev/null +++ b/scm/driver/harness/apps.go @@ -0,0 +1,63 @@ +// Copyright 2017 Drone.IO Inc. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package harness + +import ( + "context" + + "github.com/drone/go-scm/scm" +) + +type appsService struct { + client *wrapper +} + +func (s *appsService) Get(ctx context.Context, appSlug string) (*scm.App, *scm.Response, error) { + return nil, nil, scm.ErrNotSupported +} + +func (s *appsService) ListInstallations(ctx context.Context, opts scm.ListOptions) ([]*scm.Installation, *scm.Response, error) { + return nil, nil, scm.ErrNotSupported +} + +func (s *appsService) GetInstallation(ctx context.Context, id int64) (*scm.Installation, *scm.Response, error) { + return nil, nil, scm.ErrNotSupported +} + +func (s *appsService) ListUserInstallations(ctx context.Context, opts scm.ListOptions) ([]*scm.Installation, *scm.Response, error) { + return nil, nil, scm.ErrNotSupported +} + +func (s *appsService) SuspendInstallation(ctx context.Context, id int64) (*scm.Response, error) { + return nil, scm.ErrNotSupported +} + +func (s *appsService) UnsuspendInstallation(ctx context.Context, id int64) (*scm.Response, error) { + return nil, scm.ErrNotSupported +} + +func (s *appsService) DeleteInstallation(ctx context.Context, id int64) (*scm.Response, error) { + return nil, scm.ErrNotSupported +} + +func (s *appsService) CreateInstallationToken(ctx context.Context, id int64, opts *scm.InstallationTokenOptions) (*scm.InstallationToken, *scm.Response, error) { + return nil, nil, scm.ErrNotSupported +} + +func (s *appsService) FindOrganizationInstallation(ctx context.Context, org string) (*scm.Installation, *scm.Response, error) { + return nil, nil, scm.ErrNotSupported +} + +func (s *appsService) FindRepositoryInstallation(ctx context.Context, owner, repo string) (*scm.Installation, *scm.Response, error) { + return nil, nil, scm.ErrNotSupported +} + +func (s *appsService) FindRepositoryInstallationByID(ctx context.Context, id int64) (*scm.Installation, *scm.Response, error) { + return nil, nil, scm.ErrNotSupported +} + +func (s *appsService) FindUserInstallation(ctx context.Context, user string) (*scm.Installation, *scm.Response, error) { + return nil, nil, scm.ErrNotSupported +} diff --git a/scm/driver/harness/harness.go b/scm/driver/harness/harness.go index cf71dd7f..37e5bcd4 100644 --- a/scm/driver/harness/harness.go +++ b/scm/driver/harness/harness.go @@ -29,6 +29,7 @@ func New(uri, account, organization, project string) (*scm.Client, error) { // initialize services client.Driver = scm.DriverHarness client.Linker = &linker{base.String()} + client.Apps = &appsService{client} client.Contents = &contentService{client} client.Git = &gitService{client} client.Issues = &issueService{client} diff --git a/scm/driver/stash/apps.go b/scm/driver/stash/apps.go new file mode 100644 index 00000000..6c4a4808 --- /dev/null +++ b/scm/driver/stash/apps.go @@ -0,0 +1,63 @@ +// Copyright 2017 Drone.IO Inc. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package stash + +import ( + "context" + + "github.com/drone/go-scm/scm" +) + +type appsService struct { + client *wrapper +} + +func (s *appsService) Get(ctx context.Context, appSlug string) (*scm.App, *scm.Response, error) { + return nil, nil, scm.ErrNotSupported +} + +func (s *appsService) ListInstallations(ctx context.Context, opts scm.ListOptions) ([]*scm.Installation, *scm.Response, error) { + return nil, nil, scm.ErrNotSupported +} + +func (s *appsService) GetInstallation(ctx context.Context, id int64) (*scm.Installation, *scm.Response, error) { + return nil, nil, scm.ErrNotSupported +} + +func (s *appsService) ListUserInstallations(ctx context.Context, opts scm.ListOptions) ([]*scm.Installation, *scm.Response, error) { + return nil, nil, scm.ErrNotSupported +} + +func (s *appsService) SuspendInstallation(ctx context.Context, id int64) (*scm.Response, error) { + return nil, scm.ErrNotSupported +} + +func (s *appsService) UnsuspendInstallation(ctx context.Context, id int64) (*scm.Response, error) { + return nil, scm.ErrNotSupported +} + +func (s *appsService) DeleteInstallation(ctx context.Context, id int64) (*scm.Response, error) { + return nil, scm.ErrNotSupported +} + +func (s *appsService) CreateInstallationToken(ctx context.Context, id int64, opts *scm.InstallationTokenOptions) (*scm.InstallationToken, *scm.Response, error) { + return nil, nil, scm.ErrNotSupported +} + +func (s *appsService) FindOrganizationInstallation(ctx context.Context, org string) (*scm.Installation, *scm.Response, error) { + return nil, nil, scm.ErrNotSupported +} + +func (s *appsService) FindRepositoryInstallation(ctx context.Context, owner, repo string) (*scm.Installation, *scm.Response, error) { + return nil, nil, scm.ErrNotSupported +} + +func (s *appsService) FindRepositoryInstallationByID(ctx context.Context, id int64) (*scm.Installation, *scm.Response, error) { + return nil, nil, scm.ErrNotSupported +} + +func (s *appsService) FindUserInstallation(ctx context.Context, user string) (*scm.Installation, *scm.Response, error) { + return nil, nil, scm.ErrNotSupported +} diff --git a/scm/driver/stash/stash.go b/scm/driver/stash/stash.go index 62db1c7f..84b507bf 100644 --- a/scm/driver/stash/stash.go +++ b/scm/driver/stash/stash.go @@ -36,6 +36,7 @@ func New(uri string) (*scm.Client, error) { // initialize services client.Driver = scm.DriverStash client.Linker = &linker{base.String()} + client.Apps = &appsService{client} client.Contents = &contentService{client} client.Git = &gitService{client} client.Issues = &issueService{client}