Skip to content

Commit

Permalink
Support configuring the targetBranch with yaml (#20)
Browse files Browse the repository at this point in the history
Signed-off-by: Paul Farver <[email protected]>
  • Loading branch information
PaulFarver authored Feb 2, 2021
1 parent 06a84f6 commit 1e90681
Show file tree
Hide file tree
Showing 3 changed files with 97 additions and 22 deletions.
1 change: 1 addition & 0 deletions go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -15,4 +15,5 @@ require (
github.com/spf13/viper v1.7.1
gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15 // indirect
gopkg.in/gookit/color.v1 v1.1.6
gopkg.in/yaml.v2 v2.2.8
)
26 changes: 20 additions & 6 deletions pkg/githubclient.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ package pkg
import (
"context"
"fmt"
"io"
"net/http"
"regexp"
"strconv"
Expand All @@ -20,8 +21,9 @@ var (
)

type Client interface {
HandlePushEvent(*github.PushEvent) (interface{}, error)
HandleReleaseEvent(*github.ReleaseEvent) (interface{}, error)
HandlePushEvent(*github.PushEvent, Config) (interface{}, error)
HandleReleaseEvent(*github.ReleaseEvent, Config) (interface{}, error)
GetFile(repo Repo, ref, file string) (io.ReadCloser, error)
}

type ClientImpl struct {
Expand All @@ -44,11 +46,14 @@ func init() {
candidateRx = regexp.MustCompile("^rc.(?P<candidate>[0-9]+)$")
}

func (c *ClientImpl) HandlePushEvent(ev *github.PushEvent) (interface{}, error) {
func (c *ClientImpl) HandlePushEvent(ev *github.PushEvent, config Config) (interface{}, error) {
owner := ev.GetRepo().GetOwner().GetLogin()
repo := ev.GetRepo().GetName()
pushed := strings.TrimPrefix(ev.GetRef(), "refs/heads/")
master := ev.GetRepo().GetMasterBranch()
if config.TargetBranch != "" {
master = config.TargetBranch
}

if pushed != master {
return nil, nil
Expand All @@ -63,7 +68,7 @@ func (c *ClientImpl) HandlePushEvent(ev *github.PushEvent) (interface{}, error)
return c.ReleaseCandidate(owner, repo, release.GetTagName(), master)
}

func (c *ClientImpl) HandleReleaseEvent(ev *github.ReleaseEvent) (interface{}, error) {
func (c *ClientImpl) HandleReleaseEvent(ev *github.ReleaseEvent, config Config) (interface{}, error) {
owner := ev.GetRepo().GetOwner().GetLogin()
repo := ev.GetRepo().GetName()
release := ev.GetRelease()
Expand All @@ -87,10 +92,13 @@ func (c *ClientImpl) HandleReleaseEvent(ev *github.ReleaseEvent) (interface{}, e
}

curr := release.GetTagName()
next := ev.GetRepo().GetDefaultBranch()
next := ev.GetRepo().GetMasterBranch()
if config.TargetBranch != "" {
next = config.TargetBranch
}
comparison, _, err := c.client.Repositories.CompareCommits(context.TODO(), owner, repo, curr, next)
if comparison.GetTotalCommits() != 0 {
return c.ReleaseCandidate(ev.GetRepo().GetOwner().GetLogin(), ev.GetRepo().GetName(), ev.GetRelease().GetTagName(), ev.GetRepo().GetDefaultBranch())
return c.ReleaseCandidate(ev.GetRepo().GetOwner().GetLogin(), ev.GetRepo().GetName(), ev.GetRelease().GetTagName(), next)
}

return nil, nil
Expand Down Expand Up @@ -363,3 +371,9 @@ func (c *ClientImpl) getRefs(owner, repo, prefix string) ([]*github.Reference, e
}
return references, nil
}

func (c *ClientImpl) GetFile(repo Repo, ref, file string) (io.ReadCloser, error) {
return c.client.Repositories.DownloadContents(context.TODO(), repo.GetOwner().GetLogin(), repo.GetName(), file, &github.RepositoryContentGetOptions{
Ref: ref,
})
}
92 changes: 76 additions & 16 deletions pkg/githubhandler.go
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,8 @@ import (
"github.com/bradleyfalzon/ghinstallation"
"github.com/google/go-github/v32/github"
"github.com/labstack/echo/v4"
"github.com/pkg/errors"
"gopkg.in/yaml.v2"
)

type WebhookHandler struct {
Expand All @@ -21,6 +23,23 @@ func NewHandler(atr *ghinstallation.AppsTransport, secret []byte) *WebhookHandle
}
}

type HandledEvent interface {
GetInstallation() *github.Installation
}

type Repo interface {
GetOwner() *github.User
GetName() string
}

func (h *WebhookHandler) initClient(c echo.Context, ev HandledEvent, prefix string) (echo.Logger, *ClientImpl) {
k := ghinstallation.NewFromAppsTransport(h.AppsTransport, ev.GetInstallation().GetID())
l := c.Logger()
l.SetPrefix(prefix)
client := NewClient(&http.Client{Transport: k, Timeout: time.Minute}, l)
return l, client
}

func (h *WebhookHandler) HandleGithub(c echo.Context) error {
payload, err := github.ValidatePayload(c.Request(), h.Secret)
if err != nil {
Expand All @@ -33,16 +52,12 @@ func (h *WebhookHandler) HandleGithub(c echo.Context) error {

switch event := event.(type) {
case *github.PushEvent:
k := ghinstallation.NewFromAppsTransport(h.AppsTransport, event.Installation.GetID())
c.Logger().SetPrefix(event.GetRepo().GetFullName())
client := NewClient(&http.Client{Transport: k, Timeout: time.Minute}, c.Logger())
go handlePushEvent(c, client, event)
logger, client := h.initClient(c, event, event.GetRepo().GetFullName())
go handlePushEvent(logger, client, event)
return c.String(http.StatusAccepted, "Handling push event")
case *github.ReleaseEvent:
k := ghinstallation.NewFromAppsTransport(h.AppsTransport, event.Installation.GetID())
c.Logger().SetPrefix(event.GetRepo().GetFullName())
client := NewClient(&http.Client{Transport: k, Timeout: time.Minute}, c.Logger())
go handleReleaseEvent(c, client, event)
logger, client := h.initClient(c, event, event.GetRepo().GetFullName())
go handleReleaseEvent(logger, client, event)
return c.String(http.StatusAccepted, "Handling release event")
case *github.PingEvent:
return c.String(http.StatusOK, "Got ping event")
Expand All @@ -51,18 +66,63 @@ func (h *WebhookHandler) HandleGithub(c echo.Context) error {
}
}

func handleReleaseEvent(c echo.Context, client Client, ev *github.ReleaseEvent) {
c.Logger().Debug("Handling release event")
_, err := client.HandleReleaseEvent(ev)
func handleReleaseEvent(l echo.Logger, client Client, ev *github.ReleaseEvent) {
l.Debug("Handling release event")
config, err := getConfig(l, client, ev.GetRepo(), ev.GetRelease().GetTargetCommitish())
if err != nil {
l.Error("Could not instantiate repository config ", err)
return
}
if config == nil {
l.Error("Config is nil")
return
}
if _, err := client.HandleReleaseEvent(ev, *config); err != nil {
l.Error("Error handling release event", err)
}
}

func handlePushEvent(l echo.Logger, client Client, ev *github.PushEvent) {
l.Debug("Handling push event")
config, err := getConfig(l, client, ev.GetRepo(), ev.GetAfter())
if err != nil {
c.Logger().Error("Error handling release event", err)
l.Error("Could not instantiate repository config ", err)
return
}
if config == nil {
l.Error("Config is nil")
return
}

if _, err := client.HandlePushEvent(ev, *config); err != nil {
l.Error("Error handling push event", err)
}
}

func handlePushEvent(c echo.Context, client Client, ev *github.PushEvent) {
c.Logger().Debug("Handling push event")
_, err := client.HandlePushEvent(ev)
type Config struct {
TargetBranch string `yaml:"targetBranch,omitempty"`
}

func getConfig(l echo.Logger, client Client, repo Repo, ref string) (*Config, error) {
config := &Config{
TargetBranch: "",
}
reader, err := client.GetFile(repo, ref, ".ship-it")
if err != nil {
c.Logger().Error("Error handling push event", err)
l.Debug("Error getting config from github, using defaults ", err)
return config, nil
}
defer reader.Close()
decoder := yaml.NewDecoder(reader)
if err := decoder.Decode(config); err != nil {
return nil, errors.Wrap(err, "Error decoding config file")
}
if err := config.validate(); err != nil {
return nil, errors.Wrap(err, "Failed to validate config file")
}
return config, nil
}

func (c *Config) validate() error {
return nil
}

0 comments on commit 1e90681

Please sign in to comment.