-
Notifications
You must be signed in to change notification settings - Fork 98
/
Copy pathapi.go
174 lines (150 loc) · 6.03 KB
/
api.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
// Copyright 2018 The WPT Dashboard Project. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
//go:generate mockgen -destination mock_checks/api_mock.go github.com/web-platform-tests/wpt.fyi/api/checks API
package checks
import (
"context"
"fmt"
"net/url"
"time"
"github.com/google/go-github/v47/github"
"github.com/web-platform-tests/wpt.fyi/api/checks/summaries"
"github.com/web-platform-tests/wpt.fyi/shared"
)
const (
wptfyiCheckAppID = int64(23318) // https://github.com/apps/wpt-fyi-status-check
wptfyiStagingCheckAppID = int64(19965) // https://github.com/apps/staging-wpt-fyi-status-check
wptRepoInstallationID = int64(577173)
wptRepoStagingInstallationID = int64(449270)
wptRepoID = int64(3618133)
checksForAllUsersFeature = "checksAllUsers"
)
// API abstracts all the API calls used externally.
type API interface {
shared.AppEngineAPI
ScheduleResultsProcessing(sha string, browser shared.ProductSpec) error
GetSuitesForSHA(sha string) ([]shared.CheckSuite, error)
IgnoreFailure(sender, owner, repo string, run *github.CheckRun, installation *github.Installation) error
CancelRun(sender, owner, repo string, run *github.CheckRun, installation *github.Installation) error
CreateWPTCheckSuite(appID, installationID int64, sha string, prNumbers ...int) (bool, error)
GetWPTRepoAppInstallationIDs() (appID, installationID int64)
}
type checksAPIImpl struct {
shared.AppEngineAPI
queue string
}
// NewAPI returns a real implementation of the API
func NewAPI(ctx context.Context) API {
return checksAPIImpl{
AppEngineAPI: shared.NewAppEngineAPI(ctx),
queue: CheckProcessingQueue,
}
}
// ScheduleResultsProcessing adds a URL for callback to TaskQueue for the given sha and
// product, which will actually interpret the results and summarize the outcome.
func (s checksAPIImpl) ScheduleResultsProcessing(sha string, product shared.ProductSpec) error {
log := shared.GetLogger(s.Context())
target := fmt.Sprintf("/api/checks/%s", sha)
q := url.Values{}
q.Set("product", product.String())
_, err := s.ScheduleTask(s.queue, "", target, q)
if err != nil {
log.Warningf("Failed to queue %s @ %s: %s", product.String(), sha[:7], err.Error())
} else {
log.Infof("Added %s @ %s to checks processing queue", product.String(), sha[:7])
}
return err
}
// GetSuitesForSHA gets all existing check suites for the given Head SHA
func (s checksAPIImpl) GetSuitesForSHA(sha string) ([]shared.CheckSuite, error) {
var suites []shared.CheckSuite
store := shared.NewAppEngineDatastore(s.Context(), false)
_, err := store.GetAll(store.NewQuery("CheckSuite").Filter("SHA =", sha), &suites)
return suites, err
}
// IgnoreFailure updates the given CheckRun's outcome to success, even if it failed.
func (s checksAPIImpl) IgnoreFailure(sender, owner, repo string, run *github.CheckRun, installation *github.Installation) error {
client, err := getGitHubClient(s.Context(), run.GetApp().GetID(), installation.GetID())
if err != nil {
return err
}
// Keep the previous output, if applicable, but prefix it with an indication that
// somebody ignored the failure.
output := run.GetOutput()
if output == nil {
output = &github.CheckRunOutput{}
}
prepend := fmt.Sprintf("This check was marked as a success by @%s via the _Ignore_ action.\n\n", sender)
summary := prepend + output.GetSummary()
output.Summary = &summary
success := "success"
opts := github.UpdateCheckRunOptions{
Name: run.GetName(),
Output: output,
Conclusion: &success,
CompletedAt: &github.Timestamp{Time: time.Now()},
Actions: []*github.CheckRunAction{
summaries.RecomputeAction(),
},
}
_, _, err = client.Checks.UpdateCheckRun(s.Context(), owner, repo, run.GetID(), opts)
return err
}
// CancelRun updates the given CheckRun's outcome to cancelled, even if it failed.
func (s checksAPIImpl) CancelRun(sender, owner, repo string, run *github.CheckRun, installation *github.Installation) error {
client, err := getGitHubClient(s.Context(), run.GetApp().GetID(), installation.GetID())
if err != nil {
return err
}
// Keep the previous output, if applicable, but prefix it with an indication that
// somebody ignored the failure.
summary := fmt.Sprintf("This check was cancelled by @%s via the _Cancel_ action.", sender)
title := run.GetOutput().GetTitle()
output := &github.CheckRunOutput{
Title: &title,
Summary: &summary,
}
cancelled := "cancelled"
opts := github.UpdateCheckRunOptions{
Name: run.GetName(),
Output: output,
Conclusion: &cancelled,
CompletedAt: &github.Timestamp{Time: time.Now()},
Actions: []*github.CheckRunAction{
summaries.RecomputeAction(),
summaries.IgnoreAction(),
},
}
_, _, err = client.Checks.UpdateCheckRun(s.Context(), owner, repo, run.GetID(), opts)
return err
}
// CreateWPTCheckSuite creates a check_suite on the main wpt repo for the given
// SHA. This is needed when a PR comes from a different fork of the repo.
func (s checksAPIImpl) CreateWPTCheckSuite(appID, installationID int64, sha string, prNumbers ...int) (bool, error) {
log := shared.GetLogger(s.Context())
log.Debugf("Creating check_suite for web-platform-tests/wpt @ %s", sha)
client, err := getGitHubClient(s.Context(), appID, installationID)
if err != nil {
return false, err
}
opts := github.CreateCheckSuiteOptions{
HeadSHA: sha,
}
suite, _, err := client.Checks.CreateCheckSuite(s.Context(), shared.WPTRepoOwner, shared.WPTRepoName, opts)
if err != nil {
log.Errorf("Failed to create GitHub check suite: %s", err.Error())
} else if suite != nil {
log.Infof("check_suite %v created", suite.GetID())
getOrCreateCheckSuite(s.Context(), sha, shared.WPTRepoOwner, shared.WPTRepoName, appID, installationID, prNumbers...)
}
return suite != nil, err
}
func (s checksAPIImpl) GetWPTRepoAppInstallationIDs() (appID, installationID int64) {
// Production
if s.GetOrigin().Hostname() == "wpt.fyi" {
return wptfyiCheckAppID, wptRepoInstallationID
}
// Default to staging
return wptfyiStagingCheckAppID, wptRepoStagingInstallationID
}