From 94469a8e7c5a705414bad32dae35f0ea471e04d7 Mon Sep 17 00:00:00 2001 From: Andrea Frittoli Date: Mon, 9 Mar 2020 17:54:01 +0000 Subject: [PATCH] Handle the case of multiple versions of a status The GitHub API keeps old versions of a status for historical reasons. The statuses are returned in reverse chronological order. This patch pulls-in a version of go-scm that handles this behaviour and only returns the latest status. Fixes #2188 Signed-off-by: Andrea Frittoli (cherry picked from commit a5794f2d5c93a600f48213958777aba5e339f0ec) --- go.mod | 2 +- go.sum | 4 +- .../github.com/hashicorp/errwrap/go.mod | 2 - .../github.com/hashicorp/go-multierror/go.mod | 2 - .../jenkins-x/go-scm/{scm => }/LICENSE | 0 .../{scm/driver/internal => pkg}/hmac/hmac.go | 0 .../github.com/jenkins-x/go-scm/scm/client.go | 5 +- .../jenkins-x/go-scm/scm/content.go | 2 +- .../github.com/jenkins-x/go-scm/scm/deploy.go | 93 ++++++++ .../jenkins-x/go-scm/scm/driver/fake/data.go | 5 + .../jenkins-x/go-scm/scm/driver/fake/fake.go | 5 +- .../jenkins-x/go-scm/scm/driver/fake/repo.go | 96 +++++--- .../jenkins-x/go-scm/scm/driver/fake/user.go | 29 +++ .../go-scm/scm/driver/github/deploy.go | 207 ++++++++++++++++++ .../go-scm/scm/driver/github/github.go | 1 + .../go-scm/scm/driver/github/repo.go | 36 ++- .../go-scm/scm/driver/github/user.go | 3 + .../go-scm/scm/driver/github/webhook.go | 6 +- .../go-scm/scm/driver/gitlab/repo.go | 4 + .../github.com/jenkins-x/go-scm/scm/repo.go | 13 ++ vendor/modules.txt | 4 +- 21 files changed, 474 insertions(+), 45 deletions(-) rename third_party/github.com/jenkins-x/go-scm/{scm => }/LICENSE (100%) rename vendor/github.com/jenkins-x/go-scm/{scm/driver/internal => pkg}/hmac/hmac.go (100%) create mode 100644 vendor/github.com/jenkins-x/go-scm/scm/deploy.go create mode 100644 vendor/github.com/jenkins-x/go-scm/scm/driver/fake/user.go create mode 100644 vendor/github.com/jenkins-x/go-scm/scm/driver/github/deploy.go diff --git a/go.mod b/go.mod index bff22a7ca31..b60d758a71b 100644 --- a/go.mod +++ b/go.mod @@ -19,7 +19,7 @@ require ( github.com/hashicorp/go-multierror v1.0.0 github.com/hashicorp/golang-lru v0.5.3 github.com/imdario/mergo v0.3.8 // indirect - github.com/jenkins-x/go-scm v1.5.73 + github.com/jenkins-x/go-scm v1.5.79 github.com/json-iterator/go v1.1.8 // indirect github.com/markbates/inflect v1.0.4 // indirect github.com/mattbaird/jsonpatch v0.0.0-20171005235357-81af80346b1a // indirect diff --git a/go.sum b/go.sum index 409e2cb6295..53fa99333c9 100644 --- a/go.sum +++ b/go.sum @@ -305,8 +305,8 @@ github.com/jbenet/go-context v0.0.0-20150711004518-d14ea06fba99 h1:BQSFePA1RWJOl github.com/jbenet/go-context v0.0.0-20150711004518-d14ea06fba99/go.mod h1:1lJo3i6rXxKeerYnT8Nvf0QmHCRC1n8sfWVwXF2Frvo= github.com/jcmturner/gofork v0.0.0-20190328161633-dc7c13fece03/go.mod h1:MK8+TM0La+2rjBD4jE12Kj1pCCxK7d2LK/UM3ncEo0o= github.com/jcmturner/gofork v1.0.0/go.mod h1:MK8+TM0La+2rjBD4jE12Kj1pCCxK7d2LK/UM3ncEo0o= -github.com/jenkins-x/go-scm v1.5.73 h1:ThyFuUdrKivXDHWStSmpQ/M7tJ331l7lzHtR5k5/RhY= -github.com/jenkins-x/go-scm v1.5.73/go.mod h1:PCT338UhP/pQ0IeEeMEf/hoLTYKcH7qjGEKd7jPkeYg= +github.com/jenkins-x/go-scm v1.5.79 h1:+HIEkc/Dzdq0buJF8q0Keip2wexW40BfkrDXKx88T78= +github.com/jenkins-x/go-scm v1.5.79/go.mod h1:PCT338UhP/pQ0IeEeMEf/hoLTYKcH7qjGEKd7jPkeYg= github.com/jessevdk/go-flags v1.4.0/go.mod h1:4FA24M0QyGHXBuZZK/XkWh8h0e1EYbRYJSGM75WSRxI= github.com/jmespath/go-jmespath v0.0.0-20180206201540-c2b33e8439af h1:pmfjZENx5imkbgOkpRUYLnmbU7UEFbjtDA2hxJ1ichM= github.com/jmespath/go-jmespath v0.0.0-20180206201540-c2b33e8439af/go.mod h1:Nht3zPeWKUH0NzdCt2Blrr5ys8VGpn0CEB0cQHVjt7k= diff --git a/third_party/github.com/hashicorp/errwrap/go.mod b/third_party/github.com/hashicorp/errwrap/go.mod index d7ed369809b..c9b84022cf7 100644 --- a/third_party/github.com/hashicorp/errwrap/go.mod +++ b/third_party/github.com/hashicorp/errwrap/go.mod @@ -1,3 +1 @@ module github.com/hashicorp/errwrap - -go 1.13 diff --git a/third_party/github.com/hashicorp/go-multierror/go.mod b/third_party/github.com/hashicorp/go-multierror/go.mod index 8c91af65b26..2534331d5f9 100644 --- a/third_party/github.com/hashicorp/go-multierror/go.mod +++ b/third_party/github.com/hashicorp/go-multierror/go.mod @@ -1,5 +1,3 @@ module github.com/hashicorp/go-multierror require github.com/hashicorp/errwrap v1.0.0 - -go 1.13 diff --git a/third_party/github.com/jenkins-x/go-scm/scm/LICENSE b/third_party/github.com/jenkins-x/go-scm/LICENSE similarity index 100% rename from third_party/github.com/jenkins-x/go-scm/scm/LICENSE rename to third_party/github.com/jenkins-x/go-scm/LICENSE diff --git a/vendor/github.com/jenkins-x/go-scm/scm/driver/internal/hmac/hmac.go b/vendor/github.com/jenkins-x/go-scm/pkg/hmac/hmac.go similarity index 100% rename from vendor/github.com/jenkins-x/go-scm/scm/driver/internal/hmac/hmac.go rename to vendor/github.com/jenkins-x/go-scm/pkg/hmac/hmac.go diff --git a/vendor/github.com/jenkins-x/go-scm/scm/client.go b/vendor/github.com/jenkins-x/go-scm/scm/client.go index 8ac0b2e867a..d1b1ea6ec4f 100644 --- a/vendor/github.com/jenkins-x/go-scm/scm/client.go +++ b/vendor/github.com/jenkins-x/go-scm/scm/client.go @@ -94,8 +94,11 @@ type ( // Services used for communicating with the API. Driver Driver + Apps AppService Contents ContentService + Deployments DeploymentService Git GitService + GraphQL GraphQLService Organizations OrganizationService Issues IssueService PullRequests PullRequestService @@ -103,8 +106,6 @@ type ( Reviews ReviewService Users UserService Webhooks WebhookService - GraphQL GraphQLService - Apps AppService // DumpResponse optionally specifies a function to // dump the the response body for debugging purposes. diff --git a/vendor/github.com/jenkins-x/go-scm/scm/content.go b/vendor/github.com/jenkins-x/go-scm/scm/content.go index 7d4a567e387..b3f9cc9df7c 100644 --- a/vendor/github.com/jenkins-x/go-scm/scm/content.go +++ b/vendor/github.com/jenkins-x/go-scm/scm/content.go @@ -40,7 +40,7 @@ type ( // Lists the files or directories at the given path List(ctx context.Context, repo, path, ref string) ([]*FileEntry, *Response, error) - // Create creates a new repositroy file. + // Create creates a new repository file. Create(ctx context.Context, repo, path string, params *ContentParams) (*Response, error) // Update updates a repository file. diff --git a/vendor/github.com/jenkins-x/go-scm/scm/deploy.go b/vendor/github.com/jenkins-x/go-scm/scm/deploy.go new file mode 100644 index 00000000000..212b3a2f9b8 --- /dev/null +++ b/vendor/github.com/jenkins-x/go-scm/scm/deploy.go @@ -0,0 +1,93 @@ +package scm + +import ( + "context" + "time" +) + +type ( + // Deployment represents a request to deploy a version/ref/sha in some environment + Deployment struct { + ID string + Namespace string + Name string + Link string + Sha string + Ref string + FullName string + Description string + OriginalEnvironment string + Environment string + RepositoryLink string + StatusLink string + Author *User + Created time.Time + Updated time.Time + TransientEnvironment bool + ProductionEnvironment bool + } + + // DeploymentInput the input to create a new deployment + DeploymentInput struct { + Ref string + Task string + Payload string + Environment string + Description string + RequiredContexts []string + AutoMerge bool + TransientEnvironment bool + ProductionEnvironment bool + } + + // DeploymentStatus represents the status of a deployment + DeploymentStatus struct { + ID string + State string + Author *User + Description string + Environment string + DeploymentLink string + EnvironmentLink string + LogLink string + RepositoryLink string + TargetLink string + Created time.Time + Updated time.Time + } + + // DeploymentStatusInput the input to creating a status of a deployment + DeploymentStatusInput struct { + State string + TargetLink string + LogLink string + Description string + Environment string + EnvironmentLink string + AutoInactive bool + } + + // DeploymentService a service for working with deployments and deployment services + DeploymentService interface { + // Find find a deployment by id. + Find(ctx context.Context, repoFullName string, deploymentID string) (*Deployment, *Response, error) + + // List returns a list of deployments. + List(ctx context.Context, repoFullName string, opts ListOptions) ([]*Deployment, *Response, error) + + // Create creates a new deployment. + Create(ctx context.Context, repoFullName string, deployment *DeploymentInput) (*Deployment, *Response, error) + + // Delete deletes a deployment. + Delete(ctx context.Context, repoFullName string, deploymentID string) (*Response, error) + + // FindStatus find a deployment status by id. + FindStatus(ctx context.Context, repoFullName string, deploymentID string, statusID string) (*DeploymentStatus, *Response, error) + + // List returns a list of deployments. + ListStatus(ctx context.Context, repoFullName string, deploymentID string, options ListOptions) ([]*DeploymentStatus, *Response, error) + + // Create creates a new deployment. + CreateStatus(ctx context.Context, repoFullName string, deploymentID string, deployment *DeploymentStatusInput) (*DeploymentStatus, *Response, error) + } +) diff --git a/vendor/github.com/jenkins-x/go-scm/scm/driver/fake/data.go b/vendor/github.com/jenkins-x/go-scm/scm/driver/fake/data.go index 23d90114d8f..246f8fcf58c 100644 --- a/vendor/github.com/jenkins-x/go-scm/scm/driver/fake/data.go +++ b/vendor/github.com/jenkins-x/go-scm/scm/driver/fake/data.go @@ -24,6 +24,11 @@ type Data struct { TestRef string PullRequestsCreated map[int]*scm.PullRequestInput PullRequestID int + CreateRepositories []*scm.RepositoryInput + Repositories []*scm.Repository + CurrentUser scm.User + Users []*scm.User + Hooks map[string][]*scm.Hook //All Labels That Exist In The Repo RepoLabelsExisting []string diff --git a/vendor/github.com/jenkins-x/go-scm/scm/driver/fake/fake.go b/vendor/github.com/jenkins-x/go-scm/scm/driver/fake/fake.go index ac1c7f6ce05..f44d3f262a6 100644 --- a/vendor/github.com/jenkins-x/go-scm/scm/driver/fake/fake.go +++ b/vendor/github.com/jenkins-x/go-scm/scm/driver/fake/fake.go @@ -11,6 +11,9 @@ import ( // scm operations have been performed func NewDefault() (*scm.Client, *Data) { data := NewData() + data.CurrentUser.Login = "dummy" + data.CurrentUser.Name = "dummy" + client := &wrapper{new(scm.Client)} client.BaseURL = &url.URL{ Host: "fake.com", @@ -25,11 +28,11 @@ func NewDefault() (*scm.Client, *Data) { client.PullRequests = &pullService{client: client, data: data} client.Repositories = &repositoryService{client: client, data: data} client.Reviews = &reviewService{client: client, data: data} + client.Users = &userService{client: client, data: data} // TODO /* client.Contents = &contentService{client} - client.Users = &userService{client} client.Webhooks = &webhookService{client} */ return client.Client, data diff --git a/vendor/github.com/jenkins-x/go-scm/scm/driver/fake/repo.go b/vendor/github.com/jenkins-x/go-scm/scm/driver/fake/repo.go index c00da0be570..ad105bee95a 100644 --- a/vendor/github.com/jenkins-x/go-scm/scm/driver/fake/repo.go +++ b/vendor/github.com/jenkins-x/go-scm/scm/driver/fake/repo.go @@ -2,7 +2,9 @@ package fake import ( "context" + "fmt" "strings" + "time" "github.com/jenkins-x/go-scm/scm" ) @@ -36,6 +38,22 @@ func (s *repositoryService) FindUserPermission(ctx context.Context, repo string, // NormLogin normalizes login strings var NormLogin = strings.ToLower +func (s *repositoryService) FindHook(context.Context, string, string) (*scm.Hook, *scm.Response, error) { + panic("implement me") +} + +func (s *repositoryService) FindPerms(context.Context, string) (*scm.Perm, *scm.Response, error) { + panic("implement me") +} + +func (s *repositoryService) ListOrganisation(context.Context, string, scm.ListOptions) ([]*scm.Repository, *scm.Response, error) { + panic("implement me") +} + +func (s *repositoryService) ListUser(context.Context, string, scm.ListOptions) ([]*scm.Repository, *scm.Response, error) { + panic("implement me") +} + func (s *repositoryService) IsCollaborator(ctx context.Context, repo, login string) (bool, *scm.Response, error) { f := s.data normed := NormLogin(login) @@ -56,28 +74,17 @@ func (s *repositoryService) ListCollaborators(ctx context.Context, repo string) return result, nil, nil } -func (s *repositoryService) Find(context.Context, string) (*scm.Repository, *scm.Response, error) { - panic("implement me") -} - -func (s *repositoryService) FindHook(context.Context, string, string) (*scm.Hook, *scm.Response, error) { - panic("implement me") -} - -func (s *repositoryService) FindPerms(context.Context, string) (*scm.Perm, *scm.Response, error) { - panic("implement me") -} - -func (s *repositoryService) List(context.Context, scm.ListOptions) ([]*scm.Repository, *scm.Response, error) { - panic("implement me") +func (s *repositoryService) Find(ctx context.Context, fullName string) (*scm.Repository, *scm.Response, error) { + for _, repo := range s.data.Repositories { + if repo.FullName == fullName { + return repo, nil, nil + } + } + return nil, nil, scm.ErrNotFound } -func (s *repositoryService) ListOrganisation(context.Context, string, scm.ListOptions) ([]*scm.Repository, *scm.Response, error) { - panic("implement me") -} - -func (s *repositoryService) ListUser(context.Context, string, scm.ListOptions) ([]*scm.Repository, *scm.Response, error) { - panic("implement me") +func (s *repositoryService) List(ctx context.Context, opts scm.ListOptions) ([]*scm.Repository, *scm.Response, error) { + return s.data.Repositories, nil, nil } func (s *repositoryService) ListLabels(context.Context, string, scm.ListOptions) ([]*scm.Label, *scm.Response, error) { @@ -89,10 +96,6 @@ func (s *repositoryService) ListLabels(context.Context, string, scm.ListOptions) return la, nil, nil } -func (s *repositoryService) ListHooks(context.Context, string, scm.ListOptions) ([]*scm.Hook, *scm.Response, error) { - panic("implement me") -} - func (s *repositoryService) ListStatus(ctx context.Context, repo string, ref string, opt scm.ListOptions) ([]*scm.Status, *scm.Response, error) { f := s.data result := make([]*scm.Status, 0, len(f.Statuses)) @@ -102,8 +105,45 @@ func (s *repositoryService) ListStatus(ctx context.Context, repo string, ref str return result, nil, nil } -func (s *repositoryService) CreateHook(context.Context, string, *scm.HookInput) (*scm.Hook, *scm.Response, error) { - panic("implement me") +func (s *repositoryService) Create(ctx context.Context, input *scm.RepositoryInput) (*scm.Repository, *scm.Response, error) { + s.data.CreateRepositories = append(s.data.CreateRepositories, input) + fullName := scm.Join(input.Namespace, input.Name) + repo := &scm.Repository{ + Namespace: input.Namespace, + Name: input.Name, + FullName: fullName, + Link: fmt.Sprintf("https://fake.com/%s.git", fullName), + Created: time.Now(), + } + s.data.Repositories = append(s.data.Repositories, repo) + return repo, nil, nil +} + +func (s *repositoryService) ListHooks(ctx context.Context, fullName string, opts scm.ListOptions) ([]*scm.Hook, *scm.Response, error) { + return s.data.Hooks[fullName], nil, nil +} + +func (s *repositoryService) CreateHook(ctx context.Context, fullName string, input *scm.HookInput) (*scm.Hook, *scm.Response, error) { + hook := &scm.Hook{ + ID: "dummy", + Name: input.Name, + Target: input.Target, + Active: true, + } + s.data.Hooks[fullName] = append(s.data.Hooks[fullName], hook) + return hook, nil, nil +} + +func (s *repositoryService) DeleteHook(ctx context.Context, fullName string, hookName string) (*scm.Response, error) { + hooks := s.data.Hooks[fullName] + for i, h := range hooks { + if h.Name == hookName { + hooks = append(hooks[0:i], hooks[i+1:]...) + s.data.Hooks[fullName] = hooks + break + } + } + return nil, nil } func (s *repositoryService) CreateStatus(ctx context.Context, repo string, ref string, in *scm.StatusInput) (*scm.Status, *scm.Response, error) { @@ -122,7 +162,3 @@ func (s *repositoryService) CreateStatus(ctx context.Context, repo string, ref s s.data.Statuses[ref] = statuses return status, nil, nil } - -func (s *repositoryService) DeleteHook(context.Context, string, string) (*scm.Response, error) { - panic("implement me") -} diff --git a/vendor/github.com/jenkins-x/go-scm/scm/driver/fake/user.go b/vendor/github.com/jenkins-x/go-scm/scm/driver/fake/user.go new file mode 100644 index 00000000000..6bad084d659 --- /dev/null +++ b/vendor/github.com/jenkins-x/go-scm/scm/driver/fake/user.go @@ -0,0 +1,29 @@ +package fake + +import ( + "context" + + "github.com/jenkins-x/go-scm/scm" +) + +type userService struct { + client *wrapper + data *Data +} + +func (u *userService) Find(ctx context.Context) (*scm.User, *scm.Response, error) { + return &u.data.CurrentUser, nil, nil +} + +func (u *userService) FindEmail(ctx context.Context) (string, *scm.Response, error) { + return u.data.CurrentUser.Email, nil, nil +} + +func (u *userService) FindLogin(ctx context.Context, login string) (*scm.User, *scm.Response, error) { + for _, user := range u.data.Users { + if user.Login == login { + return user, nil, nil + } + } + return nil, nil, nil +} diff --git a/vendor/github.com/jenkins-x/go-scm/scm/driver/github/deploy.go b/vendor/github.com/jenkins-x/go-scm/scm/driver/github/deploy.go new file mode 100644 index 00000000000..81050901135 --- /dev/null +++ b/vendor/github.com/jenkins-x/go-scm/scm/driver/github/deploy.go @@ -0,0 +1,207 @@ +package github + +import ( + "context" + "fmt" + "strconv" + "strings" + "time" + + "github.com/jenkins-x/go-scm/scm" +) + +type deploymentService struct { + client *wrapper +} + +type deployment struct { + Namespace string + Name string + FullName string + ID int `json:"id"` + Link string `json:"url"` + Sha string `json:"sha"` + Ref string `json:"ref"` + Description string `json:"description"` + OriginalEnvironment string `json:"original_environment"` + Environment string `json:"environment"` + RepositoryLink string `json:"repository_url"` + StatusLink string `json:"statuses_url"` + Author *user `json:"creator"` + Created time.Time `json:"created_at"` + Updated time.Time `json:"updated_at"` + TransientEnvironment bool `json:"transient_environment"` + ProductionEnvironment bool `json:"production_environment"` +} + +type deploymentInput struct { + Ref string `json:"ref"` + Task string `json:"task"` + Payload string `json:"payload"` + Environment string `json:"environment"` + Description string `json:"description"` + RequiredContexts []string `json:"required_contexts"` + AutoMerge bool `json:"auto_merge"` + TransientEnvironment bool `json:"transient_environment"` + ProductionEnvironment bool `json:"production_environment"` +} + +type deploymentStatus struct { + ID int `json:"id"` + State string `json:"state"` + Author *user `json:"creator"` + Description string `json:"description"` + Environment string `json:"environment"` + DeploymentLink string `json:"deployment_url"` + EnvironmentLink string `json:"environment_url"` + LogLink string `json:"log_url"` + RepositoryLink string `json:"repository_url"` + TargetLink string `json:"target_url"` + Created time.Time `json:"created_at"` + Updated time.Time `json:"updated_at"` +} + +type deploymentStatusInput struct { + State string `json:"state"` + TargetLink string `json:"target_url"` + LogLink string `json:"log_url"` + Description string `json:"description"` + Environment string `json:"environment"` + EnvironmentLink string `json:"environment_url"` + AutoInactive bool `json:"auto_inactive"` +} + +func (s *deploymentService) Find(ctx context.Context, repoFullName string, deploymentID string) (*scm.Deployment, *scm.Response, error) { + path := fmt.Sprintf("repos/%s/deployments/%s", repoFullName, deploymentID) + out := new(deployment) + res, err := s.client.do(ctx, "GET", path, nil, out) + return convertDeployment(out, repoFullName), res, err +} + +func (s *deploymentService) List(ctx context.Context, repoFullName string, opts scm.ListOptions) ([]*scm.Deployment, *scm.Response, error) { + path := fmt.Sprintf("repos/%s/deployments?%s", repoFullName, encodeListOptions(opts)) + out := []*deployment{} + res, err := s.client.do(ctx, "GET", path, nil, &out) + return convertDeploymentList(out, repoFullName), res, err +} + +func (s *deploymentService) Create(ctx context.Context, repoFullName string, deploymentInput *scm.DeploymentInput) (*scm.Deployment, *scm.Response, error) { + path := fmt.Sprintf("repos/%s/deployments", repoFullName) + in := convertToDeploymentInput(deploymentInput) + out := new(deployment) + res, err := s.client.do(ctx, "POST", path, in, out) + return convertDeployment(out, repoFullName), res, err +} + +func (s *deploymentService) Delete(ctx context.Context, repoFullName string, deploymentID string) (*scm.Response, error) { + path := fmt.Sprintf("repos/%s/deployments/%s", repoFullName, deploymentID) + return s.client.do(ctx, "DELETE", path, nil, nil) +} + +func (s *deploymentService) FindStatus(ctx context.Context, repoFullName string, deploymentID string, statusID string) (*scm.DeploymentStatus, *scm.Response, error) { + path := fmt.Sprintf("repos/%s/deployments/%s/statuses/%s", repoFullName, deploymentID, statusID) + out := new(deploymentStatus) + res, err := s.client.do(ctx, "GET", path, nil, out) + return convertDeploymentStatus(out), res, err +} + +func (s *deploymentService) ListStatus(ctx context.Context, repoFullName string, deploymentID string, opts scm.ListOptions) ([]*scm.DeploymentStatus, *scm.Response, error) { + path := fmt.Sprintf("repos/%s/deployments/%s/statuses?%s", repoFullName, deploymentID, encodeListOptions(opts)) + out := []*deploymentStatus{} + res, err := s.client.do(ctx, "GET", path, nil, &out) + return convertDeploymentStatusList(out), res, err +} + +func (s *deploymentService) CreateStatus(ctx context.Context, repoFullName string, deploymentID string, deploymentStatusInput *scm.DeploymentStatusInput) (*scm.DeploymentStatus, *scm.Response, error) { + path := fmt.Sprintf("repos/%s/deployments/%s/statuses", repoFullName, deploymentID) + in := convertToDeploymentStatusInput(deploymentStatusInput) + out := new(deploymentStatus) + res, err := s.client.do(ctx, "POST", path, in, out) + return convertDeploymentStatus(out), res, err +} + +func convertDeploymentList(out []*deployment, fullName string) []*scm.Deployment { + answer := []*scm.Deployment{} + for _, o := range out { + answer = append(answer, convertDeployment(o, fullName)) + } + return answer +} + +func convertDeploymentStatusList(out []*deploymentStatus) []*scm.DeploymentStatus { + answer := []*scm.DeploymentStatus{} + for _, o := range out { + answer = append(answer, convertDeploymentStatus(o)) + } + return answer + +} + +func convertToDeploymentInput(from *scm.DeploymentInput) *deploymentInput { + return &deploymentInput{ + Ref: from.Ref, + Task: from.Task, + Payload: from.Payload, + Environment: from.Environment, + Description: from.Description, + RequiredContexts: from.RequiredContexts, + AutoMerge: from.AutoMerge, + TransientEnvironment: from.TransientEnvironment, + ProductionEnvironment: from.ProductionEnvironment, + } +} + +func convertDeployment(from *deployment, fullName string) *scm.Deployment { + dst := &scm.Deployment{ + ID: strconv.Itoa(from.ID), + Link: from.Link, + Sha: from.Sha, + Ref: from.Ref, + FullName: fullName, + Description: from.Description, + OriginalEnvironment: from.OriginalEnvironment, + Environment: from.Environment, + RepositoryLink: from.RepositoryLink, + StatusLink: from.StatusLink, + Author: convertUser(from.Author), + Created: from.Created, + Updated: from.Updated, + TransientEnvironment: from.TransientEnvironment, + ProductionEnvironment: from.ProductionEnvironment, + } + names := strings.Split(fullName, "/") + if len(names) > 1 { + dst.Namespace = names[0] + dst.Name = names[1] + } + return dst +} + +func convertDeploymentStatus(from *deploymentStatus) *scm.DeploymentStatus { + return &scm.DeploymentStatus{ + ID: strconv.Itoa(from.ID), + State: from.State, + Author: convertUser(from.Author), + Description: from.Description, + Environment: from.Environment, + DeploymentLink: from.DeploymentLink, + EnvironmentLink: from.EnvironmentLink, + LogLink: from.LogLink, + RepositoryLink: from.RepositoryLink, + TargetLink: from.TargetLink, + Created: from.Created, + Updated: from.Updated, + } +} + +func convertToDeploymentStatusInput(from *scm.DeploymentStatusInput) *deploymentStatusInput { + return &deploymentStatusInput{ + State: from.State, + TargetLink: from.TargetLink, + LogLink: from.LogLink, + Description: from.Description, + Environment: from.Environment, + EnvironmentLink: from.EnvironmentLink, + AutoInactive: from.AutoInactive, + } +} diff --git a/vendor/github.com/jenkins-x/go-scm/scm/driver/github/github.go b/vendor/github.com/jenkins-x/go-scm/scm/driver/github/github.go index 42953980988..3e51c719934 100644 --- a/vendor/github.com/jenkins-x/go-scm/scm/driver/github/github.go +++ b/vendor/github.com/jenkins-x/go-scm/scm/driver/github/github.go @@ -39,6 +39,7 @@ func New(uri string) (*scm.Client, error) { // initialize services client.Driver = scm.DriverGithub client.Contents = &contentService{client} + client.Deployments = &deploymentService{client} client.Git = &gitService{client} client.Issues = &issueService{client} client.Organizations = &organizationService{client} diff --git a/vendor/github.com/jenkins-x/go-scm/scm/driver/github/repo.go b/vendor/github.com/jenkins-x/go-scm/scm/driver/github/repo.go index 2c6014a8d03..093ace11d90 100644 --- a/vendor/github.com/jenkins-x/go-scm/scm/driver/github/repo.go +++ b/vendor/github.com/jenkins-x/go-scm/scm/driver/github/repo.go @@ -38,6 +38,13 @@ type repository struct { } `json:"permissions"` } +type repositoryInput struct { + Name string `json:"name"` + Description string `json:"description"` + Homepage string `json:"homepage"` + Private bool `json:"private"` +} + type hook struct { ID int `json:"id,omitempty"` Name string `json:"name"` @@ -199,6 +206,23 @@ func (s *repositoryService) ListLabels(ctx context.Context, repo string, opts sc return convertLabelObjects(out), res, err } +// Create creates a new repository +func (s *repositoryService) Create(ctx context.Context, input *scm.RepositoryInput) (*scm.Repository, *scm.Response, error) { + path := "/user/repos" + if input.Namespace != "" { + path = fmt.Sprintf("/orgs/%s/repos", input.Namespace) + + } + in := new(repositoryInput) + in.Name = input.Name + in.Description = input.Description + in.Homepage = input.Homepage + in.Private = input.Private + out := new(repository) + res, err := s.client.do(ctx, "POST", path, in, out) + return convertRepository(out), res, err +} + // CreateHook creates a new repository webhook. func (s *repositoryService) CreateHook(ctx context.Context, repo string, input *scm.HookInput) (*scm.Hook, *scm.Response, error) { path := fmt.Sprintf("repos/%s/hooks", repo) @@ -335,9 +359,19 @@ func convertCombinedStatus(from *combinedStatus) *scm.CombinedStatus { } func convertStatusList(from []*status) []*scm.Status { + // The GitHub API may return multiple statuses with the same Context, in + // reverse chronological order: + // https://developer.github.com/v3/repos/statuses/#list-statuses-for-a-specific-ref. + // We only expose the most recent one to consumers. to := []*scm.Status{} + unique := make(map[string]interface{}) for _, v := range from { - to = append(to, convertStatus(v)) + convertedStatus := convertStatus(v) + if _, ok := unique[convertedStatus.Label]; ok { + continue + } + to = append(to, convertedStatus) + unique[convertedStatus.Label] = nil } return to } diff --git a/vendor/github.com/jenkins-x/go-scm/scm/driver/github/user.go b/vendor/github.com/jenkins-x/go-scm/scm/driver/github/user.go index 9c3e823236f..8bac3f52c09 100644 --- a/vendor/github.com/jenkins-x/go-scm/scm/driver/github/user.go +++ b/vendor/github.com/jenkins-x/go-scm/scm/driver/github/user.go @@ -47,6 +47,9 @@ type user 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/vendor/github.com/jenkins-x/go-scm/scm/driver/github/webhook.go b/vendor/github.com/jenkins-x/go-scm/scm/driver/github/webhook.go index a565dea94e1..4ed8524bf5b 100644 --- a/vendor/github.com/jenkins-x/go-scm/scm/driver/github/webhook.go +++ b/vendor/github.com/jenkins-x/go-scm/scm/driver/github/webhook.go @@ -14,8 +14,8 @@ import ( "regexp" "time" + "github.com/jenkins-x/go-scm/pkg/hmac" "github.com/jenkins-x/go-scm/scm" - "github.com/jenkins-x/go-scm/scm/driver/internal/hmac" "github.com/jenkins-x/go-scm/scm/driver/internal/null" "github.com/sirupsen/logrus" ) @@ -106,6 +106,10 @@ func (s *webhookService) Parse(req *http.Request, fn scm.SecretFunc) (scm.Webhoo return hook, nil } + if logWebHooks { + log.Infof("Webhook HMAC token: %s", key) + } + sig := req.Header.Get("X-Hub-Signature") if !hmac.ValidatePrefix(data, []byte(key), sig) { return hook, scm.ErrSignatureInvalid diff --git a/vendor/github.com/jenkins-x/go-scm/scm/driver/gitlab/repo.go b/vendor/github.com/jenkins-x/go-scm/scm/driver/gitlab/repo.go index 83cd93110d2..ae52a8fbcfb 100644 --- a/vendor/github.com/jenkins-x/go-scm/scm/driver/gitlab/repo.go +++ b/vendor/github.com/jenkins-x/go-scm/scm/driver/gitlab/repo.go @@ -71,6 +71,10 @@ type repositoryService struct { client *wrapper } +func (s *repositoryService) Create(context.Context, *scm.RepositoryInput) (*scm.Repository, *scm.Response, error) { + panic("implement me") +} + func (s *repositoryService) FindCombinedStatus(ctx context.Context, repo, ref string) (*scm.CombinedStatus, *scm.Response, error) { panic("implement me") } diff --git a/vendor/github.com/jenkins-x/go-scm/scm/repo.go b/vendor/github.com/jenkins-x/go-scm/scm/repo.go index 791ae3b747e..606b1becc3c 100644 --- a/vendor/github.com/jenkins-x/go-scm/scm/repo.go +++ b/vendor/github.com/jenkins-x/go-scm/scm/repo.go @@ -26,6 +26,16 @@ type ( Updated time.Time } + // RepositoryInput provides the input fields required for + // creating a new repository. + RepositoryInput struct { + Namespace string + Name string + Description string + Homepage string + Private bool + } + // Perm represents a user's repository permissions. Perm struct { Pull bool @@ -126,6 +136,9 @@ type ( // FindCombinedStatus returns the combined status for a ref FindCombinedStatus(ctx context.Context, repo, ref string) (*CombinedStatus, *Response, error) + // Create creates a new repository . + Create(context.Context, *RepositoryInput) (*Repository, *Response, error) + // CreateHook creates a new repository webhook. CreateHook(context.Context, string, *HookInput) (*Hook, *Response, error) diff --git a/vendor/modules.txt b/vendor/modules.txt index af7d4301efd..6930682929d 100644 --- a/vendor/modules.txt +++ b/vendor/modules.txt @@ -206,12 +206,12 @@ github.com/hashicorp/golang-lru github.com/hashicorp/golang-lru/simplelru # github.com/imdario/mergo v0.3.8 github.com/imdario/mergo -# github.com/jenkins-x/go-scm v1.5.73 +# github.com/jenkins-x/go-scm v1.5.79 +github.com/jenkins-x/go-scm/pkg/hmac github.com/jenkins-x/go-scm/scm github.com/jenkins-x/go-scm/scm/driver/fake github.com/jenkins-x/go-scm/scm/driver/github github.com/jenkins-x/go-scm/scm/driver/gitlab -github.com/jenkins-x/go-scm/scm/driver/internal/hmac github.com/jenkins-x/go-scm/scm/driver/internal/null # github.com/jmespath/go-jmespath v0.0.0-20180206201540-c2b33e8439af github.com/jmespath/go-jmespath