From b8ff972af9a77eb689d7778d1f6d76d9d3162e8c Mon Sep 17 00:00:00 2001 From: Jacob Valdemar Date: Thu, 13 Aug 2020 15:03:39 +0200 Subject: [PATCH] Add filter: ignore if unmanaged by release-manager (#17) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * Add filter: ignore if unmanaged by release-manager * Update go.mod Co-authored-by: Bjørn Co-authored-by: Bjørn --- go.mod | 2 +- go.sum | 2 + issue_release_status.go | 110 ++++++++++++++++++++-------------------- types.go | 72 ++++++++++++++++++++++++++ 4 files changed, 130 insertions(+), 56 deletions(-) create mode 100644 types.go diff --git a/go.mod b/go.mod index fd5c58c..b212f6b 100644 --- a/go.mod +++ b/go.mod @@ -10,7 +10,7 @@ require ( github.com/pkg/errors v0.9.1 github.com/rs/zerolog v1.19.0 github.com/spf13/pflag v1.0.5 - github.com/stretchr/testify v1.4.0 + github.com/stretchr/testify v1.5.1 goji.io v2.0.2+incompatible gopkg.in/yaml.v2 v2.2.8 ) diff --git a/go.sum b/go.sum index e07b32f..fa3d3f6 100644 --- a/go.sum +++ b/go.sum @@ -69,6 +69,8 @@ github.com/stretchr/objx v0.1.0 h1:4G4v2dO3VZwixGIRoQ5Lfboy6nUhCyYzaqnIAPPhYs4= github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= github.com/stretchr/testify v1.4.0 h1:2E4SXV/wtOkTonXsotYi4li6zVWxYlZuYNCXe9XRJyk= github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4= +github.com/stretchr/testify v1.5.1 h1:nOGnQDM7FYENwehXlg/kFVnos3rEvtKTjRvOWSzb6H4= +github.com/stretchr/testify v1.5.1/go.mod h1:5W2xD1RspED5o8YsWQXVCued0rvSQ+mT+I5cxcmMvtA= github.com/zenazn/goji v0.9.0/go.mod h1:7S9M489iMyHBNxwZnk9/EHS098H4/F6TATF2mIxtB1Q= github.com/zenazn/goji v0.9.1-0.20160507202103-64eb34159fe5/go.mod h1:7S9M489iMyHBNxwZnk9/EHS098H4/F6TATF2mIxtB1Q= goji.io v2.0.0+incompatible h1:QY6NuzeDeRk+8Iby4IfuN/k0d82K+fDFslQF2I2f6AM= diff --git a/issue_release_status.go b/issue_release_status.go index 231a45c..4d02bae 100644 --- a/issue_release_status.go +++ b/issue_release_status.go @@ -15,7 +15,7 @@ import ( ) // Util -func Any(vs []string, f func(string) bool) bool { +func any(vs []string, f func(string) bool) bool { for _, v := range vs { if f(v) { return true @@ -24,6 +24,40 @@ func Any(vs []string, f func(string) bool) bool { return false } +func retrieveFromReleaseManager(endpoint string, authToken string, output interface{}, logger zerolog.Logger) error { + httpClient := &http.Client{} + + req, err := http.NewRequest("GET", endpoint, nil) + if err != nil { + return errors.Wrapf(err, "create GET request for release-manager endpoint '%s'", endpoint) + } + + req.Header.Add("Authorization", "Bearer "+authToken) + + resp, err := httpClient.Do(req) + if err != nil { + return errors.Wrap(err, "sending HTTP request") + } + defer resp.Body.Close() + + body, err := ioutil.ReadAll(resp.Body) + if err != nil { + return errors.Wrap(err, "reading release-manager HTTP response body") + } + + if resp.StatusCode != 200 { + logger.Info().Msgf("Request body: %v", body) + return errors.Errorf("expected status code 200, but recieved " + fmt.Sprintf("%v", resp.StatusCode)) + } + + err = json.Unmarshal(body, output) + if err != nil { + return errors.Wrap(err, "parsing release-manager HTTP response body as json") + } + + return nil +} + // Structs type PRCreateHandler struct { githubapp.ClientCreator @@ -39,24 +73,6 @@ func (handler *PRCreateHandler) Handles() []string { return []string{"pull_request"} } -type AutoReleasePolicy struct { - ID string `json:"id,omitempty"` - Branch string `json:"branch,omitempty"` - Environment string `json:"environment,omitempty"` -} - -type BranchRestrictionPolicy struct { - ID string `json:"id,omitempty"` - Environment string `json:"environment,omitempty"` - BranchRegex string `json:"branchRegex,omitempty"` -} - -type ListPoliciesResponse struct { - Service string `json:"service,omitempty"` - AutoReleases []AutoReleasePolicy `json:"autoReleases,omitempty"` - BranchRestrictions []BranchRestrictionPolicy `json:"branchRestrictions,omitempty"` -} - // Handler func (handler *PRCreateHandler) Handle(ctx context.Context, eventType, deliveryID string, payload []byte) error { zerolog.Ctx(ctx).Info().Msgf("handling delivery ID: '%s', eventtype '%s'", deliveryID, eventType) @@ -74,58 +90,42 @@ func (handler *PRCreateHandler) Handle(ctx context.Context, eventType, deliveryI ctx, logger := githubapp.PreparePRContext(ctx, installationID, repository, prNum) - // Filters - if event.GetAction() != "opened" { - return nil - } - if Any(handler.repoFilters, func(filterRepo string) bool { - return filterRepo == repository.GetName() - }) { - return nil - } - prBase := event.GetPullRequest().GetBase().GetRef() // The branch which the pull request is ending. - - // Retrieve auto-release-policy serviceName := event.GetRepo().GetName() serviceName = strings.TrimSuffix(serviceName, "-service") serviceName = strings.TrimPrefix(serviceName, "lunar-way-") - servicePath := handler.releaseManagerURL + "/policies?service=" + policyPath := handler.releaseManagerURL + "/policies?service=" + describeArtifactPath := handler.releaseManagerURL + "/describe/artifact/" - httpClient := &http.Client{} - - req, err := http.NewRequest("GET", servicePath+serviceName, nil) - if err != nil { - return errors.Wrap(err, "create GET request for release-manager") + // Filters + // - Action type + if event.GetAction() != "opened" { + return nil } - - req.Header.Add("Authorization", "Bearer "+handler.releaseManagerAuthToken) - - resp, err := httpClient.Do(req) + // - Services not managed by release-manager + var describeArtifactResponse DescribeArtifactResponse + err := retrieveFromReleaseManager(describeArtifactPath+serviceName, handler.releaseManagerAuthToken, &describeArtifactResponse, logger) if err != nil { - return errors.Wrap(err, "sending HTTP request") + return errors.Wrap(err, "requesting describeArtifact from release manager") } - defer resp.Body.Close() - - body, err := ioutil.ReadAll(resp.Body) - if err != nil { - return errors.Wrap(err, "reading release-manager HTTP response body") + if len(describeArtifactResponse.Artifacts) == 0 { + return nil } - - if resp.StatusCode != 200 { - logger.Info().Msgf("Request body: %v", body) - return errors.Errorf("expected status code 200, but recieved " + fmt.Sprintf("%v", resp.StatusCode)) + // - Ignored repositories + if any(handler.repoFilters, func(filterRepo string) bool { + return filterRepo == repository.GetName() + }) { + return nil } + // Get policies var policyResponse ListPoliciesResponse - - err = json.Unmarshal(body, &policyResponse) + err = retrieveFromReleaseManager(policyPath+serviceName, handler.releaseManagerAuthToken, &policyResponse, logger) if err != nil { - return errors.Wrap(err, "parsing release-manager HTTP response body as json") + return errors.Wrap(err, "requesting policy from release manager") } var autoReleaseEnvironments []string - for i := 0; i < len(policyResponse.AutoReleases); i++ { if policyResponse.AutoReleases[i].Branch == prBase { autoReleaseEnvironments = append(autoReleaseEnvironments, policyResponse.AutoReleases[i].Environment) diff --git a/types.go b/types.go new file mode 100644 index 0000000..db5db3c --- /dev/null +++ b/types.go @@ -0,0 +1,72 @@ +package main + +import "time" + +// Would be nice to be able to do, instead of this: +// httpinternal "github.com/lunarway/release-manager/internal/http" + +// Policy +type ListPoliciesResponse struct { + Service string `json:"service,omitempty"` + AutoReleases []AutoReleasePolicy `json:"autoReleases,omitempty"` + BranchRestrictions []BranchRestrictionPolicy `json:"branchRestrictions,omitempty"` +} + +type AutoReleasePolicy struct { + ID string `json:"id,omitempty"` + Branch string `json:"branch,omitempty"` + Environment string `json:"environment,omitempty"` +} + +type BranchRestrictionPolicy struct { + ID string `json:"id,omitempty"` + Environment string `json:"environment,omitempty"` + BranchRegex string `json:"branchRegex,omitempty"` +} + +// describeArtifact +type DescribeArtifactResponse struct { + Service string `json:"service,omitempty"` + Artifacts []Spec `json:"artifacts,omitempty"` +} + +type Spec struct { + ID string `json:"id,omitempty"` + Service string `json:"service,omitempty"` + Namespace string `json:"namespace,omitempty"` + Application Repository `json:"application,omitempty"` + CI CI `json:"ci,omitempty"` + Squad string `json:"squad,omitempty"` + Shuttle Shuttle `json:"shuttle,omitempty"` + Stages []Stage `json:"stages,omitempty"` +} + +type Repository struct { + Branch string `json:"branch,omitempty"` + SHA string `json:"sha,omitempty"` + AuthorName string `json:"authorName,omitempty"` + AuthorEmail string `json:"authorEmail,omitempty"` + CommitterName string `json:"committerName,omitempty"` + CommitterEmail string `json:"committerEmail,omitempty"` + Message string `json:"message,omitempty"` + Name string `json:"name,omitempty"` + URL string `json:"url,omitempty"` + Provider string `json:"provider,omitempty"` +} + +type Shuttle struct { + Plan Repository `json:"plan,omitempty"` + ShuttleVersion string `json:"shuttleVersion,omitempty"` +} + +type CI struct { + JobURL string `json:"jobUrl,omitempty"` + Start time.Time `json:"start,omitempty"` + End time.Time `json:"end,omitempty"` +} + +type Stage struct { + ID string `json:"id,omitempty"` + Name string `json:"name,omitempty"` + Data interface{} `json:"data,omitempty"` +}