@@ -8,19 +8,34 @@ import (
8
8
"sync"
9
9
"time"
10
10
11
+ "github.com/google/uuid"
11
12
"github.com/spf13/cobra"
12
13
"golang.org/x/xerrors"
13
14
14
15
"github.com/coder/coder/coderd/database"
15
16
"github.com/coder/coder/codersdk"
16
17
)
17
18
19
+ func WorkspaceBuild (cmd * cobra.Command , client * codersdk.Client , build uuid.UUID , before time.Time ) error {
20
+ return ProvisionerJob (cmd , ProvisionerJobOptions {
21
+ Fetch : func () (codersdk.ProvisionerJob , error ) {
22
+ build , err := client .WorkspaceBuild (cmd .Context (), build )
23
+ return build .Job , err
24
+ },
25
+ Logs : func () (<- chan codersdk.ProvisionerJobLog , error ) {
26
+ return client .WorkspaceBuildLogsAfter (cmd .Context (), build , before )
27
+ },
28
+ })
29
+ }
30
+
18
31
type ProvisionerJobOptions struct {
19
32
Fetch func () (codersdk.ProvisionerJob , error )
20
33
Cancel func () error
21
34
Logs func () (<- chan codersdk.ProvisionerJobLog , error )
22
35
23
36
FetchInterval time.Duration
37
+ // Verbose determines whether debug and trace logs will be shown.
38
+ Verbose bool
24
39
}
25
40
26
41
// ProvisionerJob renders a provisioner job with interactive cancellation.
@@ -35,7 +50,7 @@ func ProvisionerJob(cmd *cobra.Command, opts ProvisionerJobOptions) error {
35
50
didLogBetweenStage = false
36
51
ctx , cancelFunc = context .WithCancel (cmd .Context ())
37
52
38
- errChan = make (chan error )
53
+ errChan = make (chan error , 1 )
39
54
job codersdk.ProvisionerJob
40
55
jobMutex sync.Mutex
41
56
)
@@ -44,7 +59,6 @@ func ProvisionerJob(cmd *cobra.Command, opts ProvisionerJobOptions) error {
44
59
printStage := func () {
45
60
_ , _ = fmt .Fprintf (cmd .OutOrStdout (), Styles .Prompt .Render ("⧗" )+ "%s\n " , Styles .Field .Render (currentStage ))
46
61
}
47
- printStage ()
48
62
49
63
updateStage := func (stage string , startedAt time.Time ) {
50
64
if currentStage != "" {
@@ -88,29 +102,32 @@ func ProvisionerJob(cmd *cobra.Command, opts ProvisionerJobOptions) error {
88
102
}
89
103
updateJob ()
90
104
91
- // Handles ctrl+c to cancel a job.
92
- stopChan := make (chan os.Signal , 1 )
93
- defer signal .Stop (stopChan )
94
- go func () {
105
+ if opts .Cancel != nil {
106
+ // Handles ctrl+c to cancel a job.
107
+ stopChan := make (chan os.Signal , 1 )
95
108
signal .Notify (stopChan , os .Interrupt )
96
- select {
97
- case <- ctx .Done ():
98
- return
99
- case _ , ok := <- stopChan :
100
- if ! ok {
109
+ go func () {
110
+ defer signal .Stop (stopChan )
111
+ select {
112
+ case <- ctx .Done ():
101
113
return
114
+ case _ , ok := <- stopChan :
115
+ if ! ok {
116
+ return
117
+ }
102
118
}
103
- }
104
- // Stop listening for signals so another one kills it!
105
- signal .Stop (stopChan )
106
- _ , _ = fmt .Fprintf (cmd .OutOrStdout (), "\033 [2K\r \n " + Styles .FocusedPrompt .String ()+ Styles .Bold .Render ("Gracefully canceling... wait for exit or data loss may occur!" )+ "\n \n " )
107
- err := opts .Cancel ()
108
- if err != nil {
109
- errChan <- xerrors .Errorf ("cancel: %w" , err )
110
- return
111
- }
112
- updateJob ()
113
- }()
119
+ _ , _ = fmt .Fprintf (cmd .OutOrStdout (), "\033 [2K\r \n " + Styles .FocusedPrompt .String ()+ Styles .Bold .Render ("Gracefully canceling..." )+ "\n \n " )
120
+ err := opts .Cancel ()
121
+ if err != nil {
122
+ errChan <- xerrors .Errorf ("cancel: %w" , err )
123
+ return
124
+ }
125
+ updateJob ()
126
+ }()
127
+ }
128
+
129
+ // The initial stage needs to print after the signal handler has been registered.
130
+ printStage ()
114
131
115
132
logs , err := opts .Logs ()
116
133
if err != nil {
@@ -128,8 +145,6 @@ func ProvisionerJob(cmd *cobra.Command, opts ProvisionerJobOptions) error {
128
145
updateJob ()
129
146
case log , ok := <- logs :
130
147
if ! ok {
131
- // The logs stream will end when the job does,
132
- // so it's safe to
133
148
updateJob ()
134
149
jobMutex .Lock ()
135
150
if job .CompletedAt != nil {
@@ -144,26 +159,33 @@ func ProvisionerJob(cmd *cobra.Command, opts ProvisionerJobOptions) error {
144
159
return nil
145
160
case codersdk .ProvisionerJobFailed :
146
161
}
162
+ err = xerrors .New (job .Error )
147
163
jobMutex .Unlock ()
148
- return xerrors . New ( job . Error )
164
+ return err
149
165
}
150
166
output := ""
151
167
switch log .Level {
152
- case database .LogLevelTrace , database .LogLevelDebug , database .LogLevelError :
168
+ case database .LogLevelTrace , database .LogLevelDebug :
169
+ if ! opts .Verbose {
170
+ continue
171
+ }
172
+ output = Styles .Placeholder .Render (log .Output )
173
+ case database .LogLevelError :
153
174
output = defaultStyles .Error .Render (log .Output )
154
175
case database .LogLevelWarn :
155
176
output = Styles .Warn .Render (log .Output )
156
177
case database .LogLevelInfo :
157
178
output = log .Output
158
179
}
180
+ jobMutex .Lock ()
159
181
if log .Stage != currentStage && log .Stage != "" {
160
- jobMutex .Lock ()
161
182
updateStage (log .Stage , log .CreatedAt )
162
183
jobMutex .Unlock ()
163
184
continue
164
185
}
165
186
_ , _ = fmt .Fprintf (cmd .OutOrStdout (), "%s %s\n " , Styles .Placeholder .Render (" " ), output )
166
187
didLogBetweenStage = true
188
+ jobMutex .Unlock ()
167
189
}
168
190
}
169
191
}
0 commit comments