@@ -2,7 +2,9 @@ package main
2
2
3
3
import (
4
4
"context"
5
+ "errors"
5
6
"fmt"
7
+ "net/url"
6
8
"os"
7
9
"path/filepath"
8
10
"strings"
@@ -11,107 +13,142 @@ import (
11
13
"github.com/databrickslabs/sandbox/acceptance/boilerplate"
12
14
"github.com/databrickslabs/sandbox/acceptance/ecosystem"
13
15
"github.com/databrickslabs/sandbox/acceptance/notify"
16
+ "github.com/databrickslabs/sandbox/acceptance/redaction"
14
17
"github.com/databrickslabs/sandbox/acceptance/testenv"
15
18
"github.com/databrickslabs/sandbox/go-libs/env"
16
19
"github.com/databrickslabs/sandbox/go-libs/github"
20
+ "github.com/databrickslabs/sandbox/go-libs/slack"
17
21
"github.com/sethvargo/go-githubactions"
18
22
)
19
23
24
+ func main () {
25
+ err := run (context .Background ())
26
+ if err != nil {
27
+ githubactions .Fatalf ("failed: %s" , err )
28
+ }
29
+ }
30
+
20
31
func run (ctx context.Context , opts ... githubactions.Option ) error {
21
- b , err := boilerplate .New (ctx )
32
+ b , err := boilerplate .New (ctx , opts ... )
22
33
if err != nil {
23
34
return fmt .Errorf ("boilerplate: %w" , err )
24
35
}
25
- timeoutRaw := b .Action .GetInput ("timeout" )
26
- if timeoutRaw == "" {
27
- timeoutRaw = "1h"
28
- }
29
- timeout , err := time .ParseDuration (timeoutRaw )
36
+ a := & acceptance {Boilerplate : b }
37
+ alert , err := a .trigger (ctx )
30
38
if err != nil {
31
- return fmt .Errorf ("timeout : %w" , err )
39
+ return fmt .Errorf ("trigger : %w" , err )
32
40
}
33
- ctx , cancel := context .WithTimeout (ctx , timeout )
34
- defer cancel ()
35
- vaultURI := b .Action .GetInput ("vault_uri" )
36
- directory := b .Action .GetInput ("directory" )
37
- project := b .Action .GetInput ("project" )
38
- if project == "" {
39
- abs , err := filepath .Abs (directory )
40
- if err != nil {
41
- return fmt .Errorf ("absolute path: %w" , err )
42
- }
43
- project = filepath .Base (abs )
41
+ return a .notifyIfNeeded (ctx , alert )
42
+ }
43
+
44
+ type acceptance struct {
45
+ * boilerplate.Boilerplate
46
+ }
47
+
48
+ func (a * acceptance ) trigger (ctx context.Context ) (* notify.Notification , error ) {
49
+ vaultURI := a .Action .GetInput ("vault_uri" )
50
+ directory , project , err := a .getProject ()
51
+ if err != nil {
52
+ return nil , fmt .Errorf ("project: %w" , err )
44
53
}
45
- artifactDir , err := b .PrepareArtifacts ()
54
+ artifactDir , err := a .PrepareArtifacts ()
46
55
if err != nil {
47
- return fmt .Errorf ("prepare artifacts: %w" , err )
56
+ return nil , fmt .Errorf ("prepare artifacts: %w" , err )
48
57
}
49
58
defer os .RemoveAll (artifactDir )
50
- testEnv := testenv .NewWithGitHubOIDC (b .Action , vaultURI )
59
+ testEnv := testenv .NewWithGitHubOIDC (a .Action , vaultURI )
51
60
loaded , err := testEnv .Load (ctx )
52
61
if err != nil {
53
- return fmt .Errorf ("load: %w" , err )
62
+ return nil , fmt .Errorf ("load: %w" , err )
54
63
}
55
64
ctx , stop , err := loaded .Start (ctx )
56
65
if err != nil {
57
- return fmt .Errorf ("start: %w" , err )
66
+ return nil , fmt .Errorf ("start: %w" , err )
58
67
}
59
68
defer stop ()
60
69
// make sure that test logs leave their artifacts somewhere we can pickup
61
70
ctx = env .Set (ctx , ecosystem .LogDirEnv , artifactDir )
62
71
redact := loaded .Redaction ()
63
- // detect and run all tests
64
- report , err := ecosystem .RunAll (ctx , redact , directory )
72
+ report , err := a .runWithTimeout (ctx , redact , directory )
65
73
if err != nil {
66
- return fmt .Errorf ("unknown : %w" , err )
74
+ return nil , fmt .Errorf ("run : %w" , err )
67
75
}
68
76
err = report .WriteReport (project , filepath .Join (artifactDir , "test-report.json" ))
69
77
if err != nil {
70
- return fmt .Errorf ("report: %w" , err )
78
+ return nil , fmt .Errorf ("report: %w" , err )
71
79
}
72
80
// better be redacting twice, right?
73
81
summary := redact .ReplaceAll (report .StepSummary ())
74
- b .Action .AddStepSummary (summary )
75
- err = b .Comment (ctx , summary )
82
+ a .Action .AddStepSummary (summary )
83
+ err = a .AddOrUpdateComment (ctx , summary )
84
+ if err != nil {
85
+ return nil , fmt .Errorf ("comment: %w" , err )
86
+ }
87
+ err = a .Upload (ctx , artifactDir )
88
+ if err != nil {
89
+ return nil , fmt .Errorf ("upload artifact: %w" , err )
90
+ }
91
+ runUrl , err := a .RunURL (ctx )
92
+ if err != nil {
93
+ return nil , fmt .Errorf ("run url: %w" , err )
94
+ }
95
+ kvStoreURL , err := url .Parse (vaultURI )
76
96
if err != nil {
77
- return fmt .Errorf ("comment: %w" , err )
97
+ return nil , fmt .Errorf ("vault uri: %w" , err )
98
+ }
99
+ runName := strings .TrimSuffix (kvStoreURL .Host , ".vault.azure.net" )
100
+ return & notify.Notification {
101
+ Project : project ,
102
+ Report : report ,
103
+ Cloud : loaded .Cloud (),
104
+ RunName : runName ,
105
+ RunURL : runUrl ,
106
+ }, nil
107
+ }
108
+
109
+ func (a * acceptance ) runWithTimeout (
110
+ ctx context.Context , redact redaction.Redaction , directory string ,
111
+ ) (ecosystem.TestReport , error ) {
112
+ timeoutRaw := a .Action .GetInput ("timeout" )
113
+ if timeoutRaw == "" {
114
+ timeoutRaw = "50m"
78
115
}
79
- err = b . Upload ( ctx , artifactDir )
116
+ timeout , err := time . ParseDuration ( timeoutRaw )
80
117
if err != nil {
81
- return fmt .Errorf ("upload artifact : %w" , err )
118
+ return nil , fmt .Errorf ("timeout : %w" , err )
82
119
}
83
- slackWebhook := b .Action .GetInput ("slack_webhook" )
84
- createIssues := strings .ToLower (b .Action .GetInput ("create_issues" ))
120
+ ctx , cancel := context .WithTimeout (ctx , timeout )
121
+ defer cancel ()
122
+ // detect and run all tests
123
+ report , err := ecosystem .RunAll (ctx , redact , directory )
124
+ if err == nil || errors .Is (err , context .DeadlineExceeded ) {
125
+ return report , nil
126
+ }
127
+ return nil , fmt .Errorf ("unknown: %w" , err )
128
+ }
129
+
130
+ func (a * acceptance ) notifyIfNeeded (ctx context.Context , alert * notify.Notification ) error {
131
+ slackWebhook := a .Action .GetInput ("slack_webhook" )
132
+ createIssues := strings .ToLower (a .Action .GetInput ("create_issues" ))
85
133
needsSlack := slackWebhook != ""
86
134
needsIssues := createIssues == "true" || createIssues == "yes"
87
135
needsNotification := needsSlack || needsIssues
88
- if ! report .Pass () && needsNotification {
89
- runUrl , err := b .RunURL (ctx )
90
- if err != nil {
91
- return fmt .Errorf ("run url: %w" , err )
92
- }
93
- alert := notify.Notification {
94
- Project : project ,
95
- Report : report ,
96
- Cloud : loaded .Cloud (),
97
- RunName : b .WorkflowRunName (),
98
- WebHook : slackWebhook ,
99
- RunURL : runUrl ,
100
- }
136
+ if ! alert .Report .Pass () && needsNotification {
101
137
if needsSlack {
102
- err = alert .ToSlack ()
138
+ hook := slack .Webhook (slackWebhook )
139
+ err := alert .ToSlack (hook )
103
140
if err != nil {
104
141
return fmt .Errorf ("slack: %w" , err )
105
142
}
106
143
}
107
144
if needsIssues {
108
- for _ , v := range report {
145
+ for _ , v := range alert . Report {
109
146
if ! v .Failed () {
110
147
continue
111
148
}
112
- err = b . CreateIssueIfNotOpen (ctx , github.NewIssue {
113
- Title : fmt .Sprintf ("Test failure: `%s`" , v .Name ),
114
- Body : v .Summary (),
149
+ err := a . CreateOrCommentOnIssue (ctx , github.NewIssue {
150
+ Title : fmt .Sprintf ("Test failure: `%s`" , v .Name ),
151
+ Body : v .Summary (),
115
152
Labels : []string {"bug" },
116
153
})
117
154
if err != nil {
@@ -120,12 +157,18 @@ func run(ctx context.Context, opts ...githubactions.Option) error {
120
157
}
121
158
}
122
159
}
123
- return report .Failed ()
160
+ return alert . Report .Failed ()
124
161
}
125
162
126
- func main () {
127
- err := run (context .Background ())
128
- if err != nil {
129
- githubactions .Fatalf ("failed: %s" , err )
163
+ func (a * acceptance ) getProject () (string , string , error ) {
164
+ directory := a .Action .GetInput ("directory" )
165
+ project := a .Action .GetInput ("project" )
166
+ if project == "" {
167
+ abs , err := filepath .Abs (directory )
168
+ if err != nil {
169
+ return "" , "" , fmt .Errorf ("absolute path: %w" , err )
170
+ }
171
+ project = filepath .Base (abs )
130
172
}
173
+ return directory , project , nil
131
174
}
0 commit comments