Skip to content

Commit

Permalink
Merge pull request #516 from chmouel/update-existing-check-run
Browse files Browse the repository at this point in the history
  • Loading branch information
chmouel authored Apr 4, 2022
2 parents 990c7c9 + 311e665 commit da52f50
Show file tree
Hide file tree
Showing 5 changed files with 141 additions and 20 deletions.
2 changes: 0 additions & 2 deletions .tekton/push.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -156,8 +156,6 @@ spec:
workspaces:
- name: source
volumeClaimTemplate:
metadata:
creationTimestamp: null
spec:
accessModes:
- ReadWriteOnce
Expand Down
1 change: 1 addition & 0 deletions pkg/provider/github/events.go
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,7 @@ func (v *Provider) getAppToken(ctx context.Context, kube kubernetes.Interface, g
if err != nil {
return "", fmt.Errorf("could not parse the github application_id number from secret: %w", err)
}
v.ApplicationID = &applicationID

privateKey := secret.Data["github-private-key"]

Expand Down
1 change: 1 addition & 0 deletions pkg/provider/github/github.go
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ const apiPublicURL = "https://api.github.com/"
type Provider struct {
Client *github.Client
Token, APIURL *string
ApplicationID *int64
}

func (v *Provider) Validate(ctx context.Context, cs *params.Run, event *info.Event) error {
Expand Down
62 changes: 45 additions & 17 deletions pkg/provider/github/status.go
Original file line number Diff line number Diff line change
Expand Up @@ -35,25 +35,53 @@ func getCheckName(status provider.StatusOpts, pacopts *info.PacOpts) string {
return status.OriginalPipelineRunName
}

// createCheckRunStatus create a status via the checkRun API, which is only
func (v *Provider) getExistingCheckRunID(ctx context.Context, runevent *info.Event) (*int64, error) {
res, _, err := v.Client.Checks.ListCheckRunsForRef(ctx, runevent.Organization, runevent.Repository,
runevent.SHA, &github.ListCheckRunsOptions{
AppID: v.ApplicationID,
})
if err != nil {
return nil, err
}
if *res.Total > 0 {
// Their should be only one, since we CRUD it.. maybe one day we
// will offer the ability to do multiple pipelineruns per commit then
// things will get more complicated here.
return res.CheckRuns[0].ID, nil
}
return nil, nil
}

func (v *Provider) createCheckRunStatus(ctx context.Context, runevent *info.Event, pacopts *info.PacOpts, status provider.StatusOpts) (*int64, error) {
now := github.Timestamp{Time: time.Now()}
checkrunoption := github.CreateCheckRunOptions{
Name: getCheckName(status, pacopts),
HeadSHA: runevent.SHA,
Status: github.String("in_progress"),
DetailsURL: github.String(pacopts.LogURL),
StartedAt: &now,
}

checkRun, _, err := v.Client.Checks.CreateCheckRun(ctx, runevent.Organization, runevent.Repository, checkrunoption)
if err != nil {
return nil, err
}
return checkRun.ID, nil
}

// getOrUpdateCheckRunStatus create a status via the checkRun API, which is only
// available with Github apps tokens.
func (v *Provider) createCheckRunStatus(ctx context.Context, runevent *info.Event, pacopts *info.PacOpts, status provider.StatusOpts) error {
func (v *Provider) getOrUpdateCheckRunStatus(ctx context.Context, runevent *info.Event, pacopts *info.PacOpts, status provider.StatusOpts) error {
var err error

now := github.Timestamp{Time: time.Now()}
if runevent.CheckRunID == nil {
now := github.Timestamp{Time: time.Now()}
checkrunoption := github.CreateCheckRunOptions{
Name: getCheckName(status, pacopts),
HeadSHA: runevent.SHA,
Status: github.String("in_progress"),
DetailsURL: github.String(pacopts.LogURL),
StartedAt: &now,
}

checkRun, _, err := v.Client.Checks.CreateCheckRun(ctx, runevent.Organization, runevent.Repository, checkrunoption)
if err != nil {
return err
if runevent.CheckRunID, _ = v.getExistingCheckRunID(ctx, runevent); runevent.CheckRunID == nil {
runevent.CheckRunID, err = v.createCheckRunStatus(ctx, runevent, pacopts, status)
if err != nil {
return err
}
}
runevent.CheckRunID = checkRun.ID
}

checkRunOutput := &github.CheckRunOutput{
Expand All @@ -78,7 +106,7 @@ func (v *Provider) createCheckRunStatus(ctx context.Context, runevent *info.Even
opts.Conclusion = &status.Conclusion
}

_, _, err := v.Client.Checks.UpdateCheckRun(ctx, runevent.Organization, runevent.Repository, *runevent.CheckRunID, opts)
_, _, err = v.Client.Checks.UpdateCheckRun(ctx, runevent.Organization, runevent.Repository, *runevent.CheckRunID, opts)
return err
}

Expand Down Expand Up @@ -156,5 +184,5 @@ func (v *Provider) CreateStatus(ctx context.Context, runevent *info.Event, pacop
if runevent.Provider.InfoFromRepo {
return v.createStatusCommit(ctx, runevent, pacopts, status)
}
return v.createCheckRunStatus(ctx, runevent, pacopts, status)
return v.getOrUpdateCheckRunStatus(ctx, runevent, pacopts, status)
}
95 changes: 94 additions & 1 deletion pkg/provider/github/status_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import (
"fmt"
"io/ioutil"
"net/http"
"reflect"
"strings"
"testing"

Expand All @@ -23,13 +24,45 @@ func TestGithubProviderCreateCheckRun(t *testing.T) {
event := &info.Event{
Organization: "check",
Repository: "info",
SHA: "createCheckRunSHA",
}

err := gcvs.createCheckRunStatus(ctx, event, &info.PacOpts{LogURL: "http://nowhere"}, provider.StatusOpts{Status: "hello moto"})
err := gcvs.getOrUpdateCheckRunStatus(ctx, event, &info.PacOpts{LogURL: "http://nowhere"}, provider.StatusOpts{Status: "hello moto"})
assert.NilError(t, err)
assert.Equal(t, *event.CheckRunID, int64(555))
}

func TestGetExistingCheckRunID(t *testing.T) {
ctx, _ := rtesting.SetupFakeContext(t)
client, mux, _, teardown := ghtesthelper.SetupGH()
defer teardown()

gvcs := &Provider{
Client: client,
}
event := &info.Event{
Organization: "owner",
Repository: "repository",
SHA: "sha",
}

checkRunID := int64(55555)
mux.HandleFunc(fmt.Sprintf("/repos/%v/%v/commits/%v/check-runs", event.Organization, event.Repository, event.SHA), func(w http.ResponseWriter, r *http.Request) {
_, _ = fmt.Fprintf(w, `{
"total_count": 1,
"check_runs": [
{
"id": %v
}
]
}`, checkRunID)
})

id, err := gvcs.getExistingCheckRunID(ctx, event)
assert.NilError(t, err)
assert.Equal(t, *id, checkRunID)
}

func TestGithubProviderCreateStatus(t *testing.T) {
checkrunid := int64(2026)
resultid := int64(666)
Expand Down Expand Up @@ -310,3 +343,63 @@ func TestGetCheckName(t *testing.T) {
})
}
}

func TestProviderGetExistingCheckRunID(t *testing.T) {
tests := []struct {
name string
jsonret string
expectedID *int64
wantErr bool
}{
{
name: "has check runs",
jsonret: `{
"total_count": 1,
"check_runs": [
{
"id": 55555
}
]
}`,
expectedID: github.Int64(55555),
},
{
name: "no check runs",
jsonret: `{"total_count": 0,"check_runs": []}`,
expectedID: nil,
},
{
name: "error it",
jsonret: `BLAHALALACLCALWA`,
expectedID: nil,
wantErr: true,
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
ctx, _ := rtesting.SetupFakeContext(t)
client, mux, _, teardown := ghtesthelper.SetupGH()
defer teardown()
event := &info.Event{
Organization: "owner",
Repository: "repository",
SHA: "sha",
}
v := &Provider{
Client: client,
}
mux.HandleFunc(fmt.Sprintf("/repos/%v/%v/commits/%v/check-runs", event.Organization, event.Repository, event.SHA), func(w http.ResponseWriter, r *http.Request) {
_, _ = fmt.Fprintf(w, tt.jsonret)
})

got, err := v.getExistingCheckRunID(ctx, event)
if (err != nil) != tt.wantErr {
t.Errorf("getExistingCheckRunID() error = %v, wantErr %v", err, tt.wantErr)
return
}
if !reflect.DeepEqual(got, tt.expectedID) {
t.Errorf("getExistingCheckRunID() got = %v, want %v", got, tt.expectedID)
}
})
}
}

0 comments on commit da52f50

Please sign in to comment.