Skip to content

Commit 8cb0e74

Browse files
yashrtalelekswadipasha-codefresh
authored
feat: Add GitHub Check Run Support (#344)
* feat: Add Support for GitHub Check Runs Signed-off-by: Yash Talele <[email protected]> * Added test cases for github check run Signed-off-by: Yash Talele <[email protected]> * docs: add check run options for github Signed-off-by: kswadi <[email protected]> --------- Signed-off-by: Yash Talele <[email protected]> Signed-off-by: kswadi <[email protected]> Co-authored-by: kswadi <[email protected]> Co-authored-by: Pasha Kostohrys <[email protected]>
1 parent 4fb0fb3 commit 8cb0e74

File tree

3 files changed

+224
-0
lines changed

3 files changed

+224
-0
lines changed

docs/services/github.md

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -84,6 +84,19 @@ template.app-deployed: |
8484
content: |
8585
Application {{.app.metadata.name}} is now running new version of deployments manifests.
8686
See more here: {{.context.argocdUrl}}/applications/{{.app.metadata.name}}?operation=true
87+
checkRun:
88+
name: "continuous-delivery/{{.app.metadata.name}}"
89+
details_url: "{{.context.argocdUrl}}/applications/{{.app.metadata.name}}?operation=true"
90+
status: completed
91+
conclusion: success
92+
started_at: "YYYY-MM-DDTHH:MM:SSZ"
93+
completed_at: "YYYY-MM-DDTHH:MM:SSZ"
94+
output:
95+
title: "Deployment of {{.app.metadata.name}} on ArgoCD"
96+
summary: "Application {{.app.metadata.name}} is now running new version of deployments manifests."
97+
text: |
98+
Application {{.app.metadata.name}} is now running new version of deployments manifests.
99+
See more here: {{.context.argocdUrl}}/applications/{{.app.metadata.name}}?operation=true
87100
```
88101
89102
**Notes**:

pkg/services/github.go

Lines changed: 158 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@ import (
88
"regexp"
99
"strings"
1010
texttemplate "text/template"
11+
"time"
1112
"unicode/utf8"
1213

1314
"github.com/bradleyfalzon/ghinstallation/v2"
@@ -39,6 +40,7 @@ type GitHubNotification struct {
3940
PullRequestComment *GitHubPullRequestComment `json:"pullRequestComment,omitempty"`
4041
RepoURLPath string `json:"repoURLPath,omitempty"`
4142
RevisionPath string `json:"revisionPath,omitempty"`
43+
CheckRun *GitHubCheckRun `json:"checkRun,omitempty"`
4244
}
4345

4446
type GitHubStatus struct {
@@ -47,6 +49,23 @@ type GitHubStatus struct {
4749
TargetURL string `json:"targetURL,omitempty"`
4850
}
4951

52+
type GitHubCheckRun struct {
53+
// head_sha - this will be the revision path
54+
// external_id - this should have the details of argocd server
55+
Name string `json:"name,omitempty"`
56+
DetailsURL string `json:"details_url,omitempty"`
57+
Status string `json:"status,omitempty"`
58+
Conclusion string `json:"conclusion,omitempty"`
59+
StartedAt string `json:"started_at,omitempty"`
60+
CompletedAt string `json:"completed_at,omitempty"`
61+
Output *GitHubCheckRunOutput `json:"output,omitempty"`
62+
}
63+
type GitHubCheckRunOutput struct {
64+
Title string `json:"title,omitempty"`
65+
Summary string `json:"summary,omitempty"`
66+
Text string `json:"text,omitempty"`
67+
}
68+
5069
type GitHubDeployment struct {
5170
State string `json:"state,omitempty"`
5271
Environment string `json:"environment,omitempty"`
@@ -139,6 +158,49 @@ func (g *GitHubNotification) GetTemplater(name string, f texttemplate.FuncMap) (
139158
}
140159
}
141160

161+
var checkRunName, detailsURL, status, conclusion, startedAt, completedAt *texttemplate.Template
162+
if g.CheckRun != nil {
163+
checkRunName, err = texttemplate.New(name).Funcs(f).Parse(g.CheckRun.Name)
164+
if err != nil {
165+
return nil, err
166+
}
167+
detailsURL, err = texttemplate.New(name).Funcs(f).Parse(g.CheckRun.DetailsURL)
168+
if err != nil {
169+
return nil, err
170+
}
171+
status, err = texttemplate.New(name).Funcs(f).Parse(g.CheckRun.Status)
172+
if err != nil {
173+
return nil, err
174+
}
175+
conclusion, err = texttemplate.New(name).Funcs(f).Parse(g.CheckRun.Conclusion)
176+
if err != nil {
177+
return nil, err
178+
}
179+
startedAt, err = texttemplate.New(name).Funcs(f).Parse(g.CheckRun.StartedAt)
180+
if err != nil {
181+
return nil, err
182+
}
183+
completedAt, err = texttemplate.New(name).Funcs(f).Parse(g.CheckRun.CompletedAt)
184+
if err != nil {
185+
return nil, err
186+
}
187+
}
188+
var checkRunTitle, summary, text *texttemplate.Template
189+
if g.CheckRun != nil && g.CheckRun.Output != nil {
190+
checkRunTitle, err = texttemplate.New(name).Funcs(f).Parse(g.CheckRun.Output.Title)
191+
if err != nil {
192+
return nil, err
193+
}
194+
summary, err = texttemplate.New(name).Funcs(f).Parse(g.CheckRun.Output.Summary)
195+
if err != nil {
196+
return nil, err
197+
}
198+
text, err = texttemplate.New(name).Funcs(f).Parse(g.CheckRun.Output.Text)
199+
if err != nil {
200+
return nil, err
201+
}
202+
}
203+
142204
return func(notification *Notification, vars map[string]interface{}) error {
143205
if notification.GitHub == nil {
144206
notification.GitHub = &GitHubNotification{
@@ -246,6 +308,63 @@ func (g *GitHubNotification) GetTemplater(name string, f texttemplate.FuncMap) (
246308
notification.GitHub.PullRequestComment.Content = contentData.String()
247309
}
248310

311+
if g.CheckRun != nil {
312+
if notification.GitHub.CheckRun == nil {
313+
notification.GitHub.CheckRun = &GitHubCheckRun{}
314+
}
315+
var checkRunNameData bytes.Buffer
316+
if err := checkRunName.Execute(&checkRunNameData, vars); err != nil {
317+
return err
318+
}
319+
notification.GitHub.CheckRun.Name = checkRunNameData.String()
320+
var detailsURLData bytes.Buffer
321+
if err := detailsURL.Execute(&detailsURLData, vars); err != nil {
322+
return err
323+
}
324+
notification.GitHub.CheckRun.DetailsURL = detailsURLData.String()
325+
326+
var statusData bytes.Buffer
327+
if err := status.Execute(&statusData, vars); err != nil {
328+
return err
329+
}
330+
notification.GitHub.CheckRun.Status = statusData.String()
331+
var conclusionData bytes.Buffer
332+
if err := conclusion.Execute(&conclusionData, vars); err != nil {
333+
return err
334+
}
335+
notification.GitHub.CheckRun.Conclusion = conclusionData.String()
336+
var startedAtData bytes.Buffer
337+
if err := startedAt.Execute(&startedAtData, vars); err != nil {
338+
return err
339+
}
340+
notification.GitHub.CheckRun.StartedAt = startedAtData.String()
341+
var completedAtData bytes.Buffer
342+
if err := completedAt.Execute(&completedAtData, vars); err != nil {
343+
return err
344+
}
345+
notification.GitHub.CheckRun.CompletedAt = completedAtData.String()
346+
}
347+
if g.CheckRun != nil && g.CheckRun.Output != nil {
348+
if notification.GitHub.CheckRun.Output == nil {
349+
notification.GitHub.CheckRun.Output = &GitHubCheckRunOutput{}
350+
}
351+
var checkRunTitleData bytes.Buffer
352+
if err := checkRunTitle.Execute(&checkRunTitleData, vars); err != nil {
353+
return err
354+
}
355+
notification.GitHub.CheckRun.Output.Title = checkRunTitleData.String()
356+
var summaryData bytes.Buffer
357+
if err := summary.Execute(&summaryData, vars); err != nil {
358+
return err
359+
}
360+
notification.GitHub.CheckRun.Output.Summary = summaryData.String()
361+
var textData bytes.Buffer
362+
if err := text.Execute(&textData, vars); err != nil {
363+
return err
364+
}
365+
notification.GitHub.CheckRun.Output.Text = textData.String()
366+
}
367+
249368
return nil
250369
}, nil
251370
}
@@ -438,5 +557,44 @@ func (g gitHubService) Send(notification Notification, _ Destination) error {
438557
}
439558
}
440559

560+
if notification.GitHub.CheckRun != nil {
561+
startedTime, err := time.Parse("YYYY-MM-DDTHH:MM:SSZ", notification.GitHub.CheckRun.StartedAt)
562+
if err != nil {
563+
return err
564+
}
565+
completedTime, err := time.Parse("YYYY-MM-DDTHH:MM:SSZ", notification.GitHub.CheckRun.CompletedAt)
566+
if err != nil {
567+
return err
568+
}
569+
externalID := "argocd-notifications"
570+
checkRunOutput := &github.CheckRunOutput{}
571+
if notification.GitHub.CheckRun.Output != nil {
572+
checkRunOutput = &github.CheckRunOutput{
573+
Title: &notification.GitHub.CheckRun.Output.Title,
574+
Text: &notification.GitHub.CheckRun.Output.Text,
575+
Summary: &notification.GitHub.CheckRun.Output.Summary,
576+
}
577+
}
578+
579+
_, _, err = g.client.Checks.CreateCheckRun(
580+
context.Background(),
581+
u[0],
582+
u[1],
583+
github.CreateCheckRunOptions{
584+
HeadSHA: notification.GitHub.revision,
585+
ExternalID: &externalID,
586+
Name: notification.GitHub.CheckRun.Name,
587+
DetailsURL: &notification.GitHub.CheckRun.DetailsURL,
588+
StartedAt: &github.Timestamp{Time: startedTime},
589+
CompletedAt: &github.Timestamp{Time: completedTime},
590+
Output: checkRunOutput,
591+
},
592+
)
593+
594+
if err != nil {
595+
return err
596+
}
597+
}
598+
441599
return nil
442600
}

pkg/services/github_test.go

Lines changed: 53 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@ package services
33
import (
44
"testing"
55
"text/template"
6+
"time"
67

78
"github.com/stretchr/testify/assert"
89
)
@@ -261,3 +262,55 @@ func TestGetTemplater_Github_PullRequestComment(t *testing.T) {
261262
assert.Equal(t, "0123456789", notification.GitHub.revision)
262263
assert.Equal(t, "This is a comment", notification.GitHub.PullRequestComment.Content)
263264
}
265+
266+
func TestGitHubCheckRunNotification(t *testing.T) {
267+
checkRun := &GitHubCheckRun{
268+
Name: "ArgoCD GitHub Check Run",
269+
DetailsURL: "http://example.com/build/status",
270+
Status: "completed",
271+
Conclusion: "success",
272+
StartedAt: time.Now().Format(time.RFC3339),
273+
CompletedAt: time.Now().Add(5 * time.Minute).Format(time.RFC3339),
274+
Output: &GitHubCheckRunOutput{
275+
Title: "Test Check Run",
276+
Summary: "All tests passed.",
277+
Text: "All unit tests and integration tests passed successfully.",
278+
},
279+
}
280+
281+
githubNotification := &GitHubNotification{
282+
CheckRun: checkRun,
283+
}
284+
285+
vars := map[string]interface{}{
286+
"app": map[string]interface{}{
287+
"spec": map[string]interface{}{
288+
"source": map[string]interface{}{
289+
"repoURL": "https://github.com/argoproj/argo-cd.git",
290+
},
291+
},
292+
"status": map[string]interface{}{
293+
"operationState": map[string]interface{}{
294+
"syncResult": map[string]interface{}{
295+
"revision": "abc123",
296+
},
297+
},
298+
},
299+
},
300+
}
301+
302+
templater, err := githubNotification.GetTemplater("checkRun", nil)
303+
assert.NoError(t, err)
304+
305+
notification := &Notification{}
306+
307+
err = templater(notification, vars)
308+
assert.NoError(t, err)
309+
310+
assert.NotNil(t, notification.GitHub)
311+
assert.NotNil(t, notification.GitHub.CheckRun)
312+
assert.Equal(t, "ArgoCD GitHub Check Run", notification.GitHub.CheckRun.Name)
313+
assert.Equal(t, "completed", notification.GitHub.CheckRun.Status)
314+
assert.Equal(t, "success", notification.GitHub.CheckRun.Conclusion)
315+
assert.Equal(t, "All tests passed.", notification.GitHub.CheckRun.Output.Summary)
316+
}

0 commit comments

Comments
 (0)