1
0
mirror of https://github.com/woodpecker-ci/woodpecker.git synced 2024-12-24 10:07:21 +02:00

Status line for each pipeline on Github

This commit is contained in:
Laszlo Fogas 2019-06-17 10:48:40 +02:00
parent a433591afa
commit 1d47ba8a32
16 changed files with 78 additions and 41 deletions

View File

@ -214,7 +214,7 @@ func (c *config) Dir(u *model.User, r *model.Repo, b *model.Build, f string) ([]
}
// Status creates a build status for the Bitbucket commit.
func (c *config) Status(u *model.User, r *model.Repo, b *model.Build, link string) error {
func (c *config) Status(u *model.User, r *model.Repo, b *model.Build, link string, proc *model.Proc) error {
status := internal.BuildStatus{
State: convertStatus(b.Status),
Desc: convertDesc(b.Status),

View File

@ -283,7 +283,7 @@ func Test_bitbucket(t *testing.T) {
})
g.It("Should update the status", func() {
err := c.Status(fakeUser, fakeRepo, fakeBuild, "http://127.0.0.1")
err := c.Status(fakeUser, fakeRepo, fakeBuild, "http://127.0.0.1", nil)
g.Assert(err == nil).IsTrue()
})

View File

@ -184,7 +184,7 @@ func (c *Config) Dir(u *model.User, r *model.Repo, b *model.Build, f string) ([]
}
// Status is not supported by the bitbucketserver driver.
func (c *Config) Status(u *model.User, r *model.Repo, b *model.Build, link string) error {
func (c *Config) Status(u *model.User, r *model.Repo, b *model.Build, link string, proc *model.Proc) error {
status := internal.BuildStatus{
State: convertStatus(b.Status),
Desc: convertDesc(b.Status),

View File

@ -243,7 +243,7 @@ func (c *Coding) Dir(u *model.User, r *model.Repo, b *model.Build, f string) ([]
}
// Status sends the commit status to the remote system.
func (c *Coding) Status(u *model.User, r *model.Repo, b *model.Build, link string) error {
func (c *Coding) Status(u *model.User, r *model.Repo, b *model.Build, link string, proc *model.Proc) error {
// EMPTY: not implemented in Coding OAuth API
return nil
}

View File

@ -108,7 +108,7 @@ func (c *client) Dir(u *model.User, r *model.Repo, b *model.Build, f string) ([]
}
// Status is not supported by the Gogs driver.
func (c *client) Status(u *model.User, r *model.Repo, b *model.Build, link string) error {
func (c *client) Status(u *model.User, r *model.Repo, b *model.Build, link string, proc *model.Proc) error {
return nil
}

View File

@ -254,7 +254,7 @@ func (c *client) Dir(u *model.User, r *model.Repo, b *model.Build, f string) ([]
}
// Status is supported by the Gitea driver.
func (c *client) Status(u *model.User, r *model.Repo, b *model.Build, link string) error {
func (c *client) Status(u *model.User, r *model.Repo, b *model.Build, link string, proc *model.Proc) error {
client := c.newClientToken(u.Token)
status := getStatus(b.Status)

View File

@ -18,10 +18,10 @@ import (
"net/http/httptest"
"testing"
"github.com/laszlocph/drone-oss-08/model"
"github.com/laszlocph/drone-oss-08/remote/gitea/fixtures"
"github.com/franela/goblin"
"github.com/gin-gonic/gin"
"github.com/laszlocph/drone-oss-08/model"
"github.com/laszlocph/drone-oss-08/remote/gitea/fixtures"
)
func Test_gitea(t *testing.T) {
@ -149,7 +149,7 @@ func Test_gitea(t *testing.T) {
})
g.It("Should return nil from send build status", func() {
err := c.Status(fakeUser, fakeRepo, fakeBuild, "http://gitea.io")
err := c.Status(fakeUser, fakeRepo, fakeBuild, "http://gitea.io", nil)
g.Assert(err == nil).IsTrue()
})

View File

@ -430,17 +430,17 @@ func matchingHooks(hooks []github.Hook, rawurl string) *github.Hook {
// Status sends the commit status to the remote system.
// An example would be the GitHub pull request status.
func (c *client) Status(u *model.User, r *model.Repo, b *model.Build, link string) error {
func (c *client) Status(u *model.User, r *model.Repo, b *model.Build, link string, proc *model.Proc) error {
client := c.newClientToken(u.Token)
switch b.Event {
case "deployment":
return deploymentStatus(client, r, b, link)
default:
return repoStatus(client, r, b, link, c.Context)
return repoStatus(client, r, b, link, c.Context, proc)
}
}
func repoStatus(client *github.Client, r *model.Repo, b *model.Build, link, ctx string) error {
func repoStatus(client *github.Client, r *model.Repo, b *model.Build, link, ctx string, proc *model.Proc) error {
context := ctx
switch b.Event {
case model.EventPull:
@ -451,10 +451,19 @@ func repoStatus(client *github.Client, r *model.Repo, b *model.Build, link, ctx
}
}
status := github.String(convertStatus(b.Status))
desc := github.String(convertDesc(b.Status))
if proc != nil {
context += "/" + proc.Name
status = github.String(convertStatus(proc.State))
desc = github.String(convertDesc(proc.State))
}
data := github.RepoStatus{
Context: github.String(context),
State: github.String(convertStatus(b.Status)),
Description: github.String(convertDesc(b.Status)),
State: status,
Description: desc,
TargetURL: github.String(link),
}
_, _, err := client.Repositories.CreateStatus(r.Owner, r.Name, b.Commit, &data)

View File

@ -345,7 +345,7 @@ func (c *Gitlab) Dir(u *model.User, r *model.Repo, b *model.Build, f string) ([]
// NOTE Currently gitlab doesn't support status for commits and events,
// also if we want get MR status in gitlab we need implement a special plugin for gitlab,
// gitlab uses API to fetch build status on client side. But for now we skip this.
func (g *Gitlab) Status(u *model.User, repo *model.Repo, b *model.Build, link string) error {
func (g *Gitlab) Status(u *model.User, repo *model.Repo, b *model.Build, link string, proc *model.Proc) error {
client := NewClient(g.URL, u.Token, g.SkipVerify)
status := getStatus(b.Status)

View File

@ -345,7 +345,7 @@ func (c *Gitlab) Dir(u *model.User, r *model.Repo, b *model.Build, f string) ([]
// NOTE Currently gitlab doesn't support status for commits and events,
// also if we want get MR status in gitlab we need implement a special plugin for gitlab,
// gitlab uses API to fetch build status on client side. But for now we skip this.
func (g *Gitlab) Status(u *model.User, repo *model.Repo, b *model.Build, link string) error {
func (g *Gitlab) Status(u *model.User, repo *model.Repo, b *model.Build, link string, proc *model.Proc) error {
client := NewClient(g.URL, u.Token, g.SkipVerify)
status := getStatus(b.Status)

View File

@ -207,7 +207,7 @@ func (c *client) Dir(u *model.User, r *model.Repo, b *model.Build, f string) ([]
}
// Status is not supported by the Gogs driver.
func (c *client) Status(u *model.User, r *model.Repo, b *model.Build, link string) error {
func (c *client) Status(u *model.User, r *model.Repo, b *model.Build, link string, proc *model.Proc) error {
return nil
}

View File

@ -163,7 +163,7 @@ func Test_gogs(t *testing.T) {
g.It("Should return no-op for usupporeted features", func() {
_, err1 := c.Auth("octocat", "4vyW6b49Z")
err2 := c.Status(nil, nil, nil, "")
err2 := c.Status(nil, nil, nil, "", nil)
err3 := c.Deactivate(nil, nil, "")
g.Assert(err1 != nil).IsTrue()
g.Assert(err2 == nil).IsTrue()

View File

@ -55,7 +55,7 @@ type Remote interface {
// Status sends the commit status to the remote system.
// An example would be the GitHub pull request status.
Status(u *model.User, r *model.Repo, b *model.Build, link string) error
Status(u *model.User, r *model.Repo, b *model.Build, link string, proc *model.Proc) error
// Netrc returns a .netrc file that can be used to clone
// private repositories from a remote system.
@ -127,8 +127,8 @@ func Perm(c context.Context, u *model.User, owner, repo string) (*model.Perm, er
// Status sends the commit status to the remote system.
// An example would be the GitHub pull request status.
func Status(c context.Context, u *model.User, r *model.Repo, b *model.Build, link string) error {
return FromContext(c).Status(u, r, b, link)
func Status(c context.Context, u *model.User, r *model.Repo, b *model.Build, link string, proc *model.Proc) error {
return FromContext(c).Status(u, r, b, link, proc)
}
// Netrc returns a .netrc file that can be used to clone

View File

@ -307,14 +307,6 @@ func PostApproval(c *gin.Context) {
}
}
defer func() {
uri := fmt.Sprintf("%s/%s/%d", httputil.GetURL(c.Request), repo.FullName, build.Number)
err = remote_.Status(user, repo, build, uri)
if err != nil {
logrus.Errorf("error setting commit status for %s/%d: %v", repo.FullName, build.Number, err)
}
}()
var yamls []*remote.FileMeta
for _, y := range configs {
yamls = append(yamls, &remote.FileMeta{Data: []byte(y.Data), Name: y.Name})
@ -346,6 +338,20 @@ func PostApproval(c *gin.Context) {
logrus.Errorf("error persisting procs %s/%d: %s", repo.FullName, build.Number, err)
}
defer func() {
for _, item := range buildItems {
uri := fmt.Sprintf("%s/%s/%d", httputil.GetURL(c.Request), repo.FullName, build.Number)
if len(buildItems) > 1 {
err = remote_.Status(user, repo, build, uri, item.Proc)
} else {
err = remote_.Status(user, repo, build, uri, nil)
}
if err != nil {
logrus.Errorf("error setting commit status for %s/%d: %v", repo.FullName, build.Number, err)
}
}
}()
publishToTopic(c, build, repo)
queueBuild(build, repo, buildItems)
}
@ -380,7 +386,7 @@ func PostDecline(c *gin.Context) {
}
uri := fmt.Sprintf("%s/%s/%d", httputil.GetURL(c.Request), repo.FullName, build.Number)
err = remote_.Status(user, repo, build, uri)
err = remote_.Status(user, repo, build, uri, nil)
if err != nil {
logrus.Errorf("error setting commit status for %s/%d: %v", repo.FullName, build.Number, err)
}

View File

@ -221,14 +221,6 @@ func PostHook(c *gin.Context) {
// get the previous build so that we can send status change notifications
last, _ := store.GetBuildLastBefore(c, repo, build.Branch, build.ID)
defer func() {
uri := fmt.Sprintf("%s/%s/%d", httputil.GetURL(c.Request), repo.FullName, build.Number)
err = remote_.Status(user, repo, build, uri)
if err != nil {
logrus.Errorf("error setting commit status for %s/%d: %v", repo.FullName, build.Number, err)
}
}()
b := procBuilder{
Repo: repo,
Curr: build,
@ -255,6 +247,20 @@ func PostHook(c *gin.Context) {
logrus.Errorf("error persisting procs %s/%d: %s", repo.FullName, build.Number, err)
}
defer func() {
for _, item := range buildItems {
uri := fmt.Sprintf("%s/%s/%d", httputil.GetURL(c.Request), repo.FullName, build.Number)
if len(buildItems) > 1 {
err = remote_.Status(user, repo, build, uri, item.Proc)
} else {
err = remote_.Status(user, repo, build, uri, nil)
}
if err != nil {
logrus.Errorf("error setting commit status for %s/%d: %v", repo.FullName, build.Number, err)
}
}
}()
publishToTopic(c, build, repo)
queueBuild(build, repo, buildItems)
}

View File

@ -401,7 +401,13 @@ func (s *RPC) Done(c context.Context, id string, state rpc.State) error {
log.Printf("error: done: cannot update build_id %d final state: %s", build.ID, err)
}
s.updateRemoteStatus(repo, build)
if !isMultiPipeline(procs) {
s.updateRemoteStatus(repo, build, nil)
}
}
if isMultiPipeline(procs) {
s.updateRemoteStatus(repo, build, proc)
}
if err := s.logger.Close(c, id); err != nil {
@ -413,6 +419,16 @@ func (s *RPC) Done(c context.Context, id string, state rpc.State) error {
return nil
}
func isMultiPipeline(procs []*model.Proc) bool {
countPPIDZero := 0
for _, proc := range procs {
if proc.PPID == 0 {
countPPIDZero++
}
}
return countPPIDZero > 1
}
// Log implements the rpc.Log function
func (s *RPC) Log(c context.Context, id string, line *rpc.Line) error {
entry := new(logging.Entry)
@ -474,7 +490,7 @@ func buildStatus(procs []*model.Proc) string {
return status
}
func (s *RPC) updateRemoteStatus(repo *model.Repo, build *model.Build) {
func (s *RPC) updateRemoteStatus(repo *model.Repo, build *model.Build, proc *model.Proc) {
user, err := s.store.GetUser(repo.UserID)
if err == nil {
if refresher, ok := s.remote.(remote.Refresher); ok {
@ -484,7 +500,7 @@ func (s *RPC) updateRemoteStatus(repo *model.Repo, build *model.Build) {
}
}
uri := fmt.Sprintf("%s/%s/%d", s.host, repo.FullName, build.Number)
err = s.remote.Status(user, repo, build, uri)
err = s.remote.Status(user, repo, build, uri, proc)
if err != nil {
logrus.Errorf("error setting commit status for %s/%d: %v", repo.FullName, build.Number, err)
}