@@ -9,8 +9,10 @@ import (
9
9
"fmt"
10
10
"os"
11
11
"os/exec"
12
+ "os/signal"
12
13
"path/filepath"
13
14
"strings"
15
+ "syscall"
14
16
"time"
15
17
16
18
"github.com/gitpod-io/gitpod/gitpod-cli/pkg/supervisor"
@@ -19,8 +21,8 @@ import (
19
21
"github.com/spf13/cobra"
20
22
)
21
23
22
- func TerminateExistingContainer () error {
23
- cmd := exec .Command ( "docker" , "ps" , "-q" , "-f" , "label=gp-rebuild" )
24
+ func TerminateExistingContainer (ctx context. Context ) error {
25
+ cmd := exec .CommandContext ( ctx , "docker" , "ps" , "-q" , "-f" , "label=gp-rebuild" )
24
26
containerIds , err := cmd .Output ()
25
27
if err != nil {
26
28
return err
@@ -31,13 +33,13 @@ func TerminateExistingContainer() error {
31
33
continue
32
34
}
33
35
34
- cmd = exec .Command ( "docker" , "stop" , id )
36
+ cmd = exec .CommandContext ( ctx , "docker" , "stop" , id )
35
37
err := cmd .Run ()
36
38
if err != nil {
37
39
return err
38
40
}
39
41
40
- cmd = exec .Command ( "docker" , "rm" , "-f" , id )
42
+ cmd = exec .CommandContext ( ctx , "docker" , "rm" , "-f" , id )
41
43
err = cmd .Run ()
42
44
if err != nil {
43
45
return err
@@ -47,17 +49,15 @@ func TerminateExistingContainer() error {
47
49
return nil
48
50
}
49
51
50
- func runRebuild (ctx context.Context , supervisorClient * supervisor.SupervisorClient , event * utils.EventTracker ) error {
52
+ func runRebuild (ctx context.Context , supervisorClient * supervisor.SupervisorClient , event * utils.EventTracker ) ( string , error ) {
51
53
wsInfo , err := supervisorClient .Info .WorkspaceInfo (ctx , & api.WorkspaceInfoRequest {})
52
54
if err != nil {
53
- event .Set ("ErrorCode" , utils .SystemErrorCode )
54
- return err
55
+ return utils .Outcome_SystemErr , err
55
56
}
56
57
57
58
tmpDir , err := os .MkdirTemp ("" , "gp-rebuild-*" )
58
59
if err != nil {
59
- event .Set ("ErrorCode" , utils .SystemErrorCode )
60
- return err
60
+ return utils .Outcome_SystemErr , err
61
61
}
62
62
defer os .RemoveAll (tmpDir )
63
63
@@ -68,7 +68,7 @@ func runRebuild(ctx context.Context, supervisorClient *supervisor.SupervisorClie
68
68
fmt .Println ("For help check out the reference page:" )
69
69
fmt .Println ("https://www.gitpod.io/docs/references/gitpod-yml#gitpodyml" )
70
70
event .Set ("ErrorCode" , utils .RebuildErrorCode_MalformedGitpodYaml )
71
- return err
71
+ return utils . Outcome_UserErr , err
72
72
}
73
73
74
74
if gitpodConfig == nil {
@@ -79,7 +79,7 @@ func runRebuild(ctx context.Context, supervisorClient *supervisor.SupervisorClie
79
79
fmt .Println ("Alternatively, check out the following docs for getting started configuring your project" )
80
80
fmt .Println ("https://www.gitpod.io/docs/configure#configure-gitpod" )
81
81
event .Set ("ErrorCode" , utils .RebuildErrorCode_MissingGitpodYaml )
82
- return err
82
+ return utils . Outcome_UserErr , nil
83
83
}
84
84
85
85
var baseimage string
@@ -93,13 +93,11 @@ func runRebuild(ctx context.Context, supervisorClient *supervisor.SupervisorClie
93
93
94
94
if _ , err := os .Stat (dockerfilePath ); os .IsNotExist (err ) {
95
95
fmt .Println ("Your .gitpod.yml points to a Dockerfile that doesn't exist: " + dockerfilePath )
96
- event .Set ("ErrorCode" , utils .RebuildErrorCode_DockerfileNotFound ).Send (ctx )
97
- return err
96
+ return utils .Outcome_UserErr , err
98
97
}
99
98
dockerfile , err := os .ReadFile (dockerfilePath )
100
99
if err != nil {
101
- event .Set ("ErrorCode" , utils .RebuildErrorCode_DockerfileCannotRead )
102
- return err
100
+ return utils .Outcome_SystemErr , err
103
101
}
104
102
if string (dockerfile ) == "" {
105
103
fmt .Println ("Your Gitpod's Dockerfile is empty" )
@@ -108,14 +106,13 @@ func runRebuild(ctx context.Context, supervisorClient *supervisor.SupervisorClie
108
106
fmt .Println ("https://www.gitpod.io/docs/configure/workspaces/workspace-image#use-a-custom-dockerfile" )
109
107
fmt .Println ("" )
110
108
fmt .Println ("Once you configure your Dockerfile, re-run this command to validate your changes" )
111
- event .Set ("ErrorCode" , utils .RebuildErrorCode_DockerfileEmpty )
112
- return err
109
+ return utils .Outcome_UserErr , nil
113
110
}
114
111
baseimage = "\n " + string (dockerfile ) + "\n "
115
112
default :
116
113
fmt .Println ("Check your .gitpod.yml and make sure the image property is configured correctly" )
117
114
event .Set ("ErrorCode" , utils .RebuildErrorCode_MalformedGitpodYaml )
118
- return err
115
+ return utils . Outcome_UserErr , nil
119
116
}
120
117
121
118
if baseimage == "" {
@@ -124,94 +121,107 @@ func runRebuild(ctx context.Context, supervisorClient *supervisor.SupervisorClie
124
121
fmt .Println ("" )
125
122
fmt .Println ("https://www.gitpod.io/docs/configure/workspaces/workspace-image#use-a-public-docker-image" )
126
123
event .Set ("ErrorCode" , utils .RebuildErrorCode_NoCustomImage )
127
- return err
124
+ return utils . Outcome_UserErr , nil
128
125
}
129
126
130
- err = os .WriteFile (filepath .Join (tmpDir , "Dockerfile" ), []byte (baseimage ), 0644 )
127
+ tmpDockerfile := filepath .Join (tmpDir , "Dockerfile" )
128
+
129
+ err = os .WriteFile (tmpDockerfile , []byte (baseimage ), 0644 )
131
130
if err != nil {
132
131
fmt .Println ("Could not write the temporary Dockerfile" )
133
- event .Set ("ErrorCode" , utils .RebuildErrorCode_DockerfileCannotWirte )
134
- return err
132
+ return utils .Outcome_SystemErr , err
135
133
}
136
134
137
135
dockerPath , err := exec .LookPath ("docker" )
138
136
if err != nil {
139
137
fmt .Println ("Docker is not installed in your workspace" )
140
138
event .Set ("ErrorCode" , utils .RebuildErrorCode_DockerNotFound )
141
- return err
139
+ return utils . Outcome_SystemErr , err
142
140
}
143
141
144
142
tag := "gp-rebuild-temp-build"
145
143
146
- dockerCmd := exec .Command (dockerPath , "build" , "-t" , tag , "--progress=tty" , "." )
147
- dockerCmd .Dir = tmpDir
144
+ dockerCmd := exec .CommandContext (ctx , dockerPath , "build" , "-f" , tmpDockerfile , "-t" , tag , wsInfo .CheckoutLocation )
148
145
dockerCmd .Stdout = os .Stdout
149
146
dockerCmd .Stderr = os .Stderr
150
147
151
148
imageBuildStartTime := time .Now ()
152
149
err = dockerCmd .Run ()
153
150
if _ , ok := err .(* exec.ExitError ); ok {
154
151
fmt .Println ("Image Build Failed" )
155
- event .Set ("ErrorCode" , utils .RebuildErrorCode_DockerBuildFailed )
156
- return err
152
+ event .Set ("ErrorCode" , utils .RebuildErrorCode_ImageBuildFailed )
153
+ return utils . Outcome_UserErr , nil
157
154
} else if err != nil {
158
155
fmt .Println ("Docker error" )
159
156
event .Set ("ErrorCode" , utils .RebuildErrorCode_DockerErr )
160
- return err
157
+ return utils . Outcome_SystemErr , err
161
158
}
162
159
ImageBuildDuration := time .Since (imageBuildStartTime ).Milliseconds ()
163
160
event .Set ("ImageBuildDuration" , ImageBuildDuration )
164
161
165
- err = TerminateExistingContainer ()
162
+ err = TerminateExistingContainer (ctx )
166
163
if err != nil {
167
- event .Set ("ErrorCode" , utils .SystemErrorCode )
168
- return err
169
- }
170
-
171
- messages := []string {
172
- "\n \n You are now connected to the container" ,
173
- "You can inspect the container and make sure the necessary tools & libraries are installed." ,
174
- "When you are done, just type exit to return to your Gitpod workspace\n " ,
164
+ return utils .Outcome_SystemErr , err
175
165
}
176
166
177
- welcomeMessage := strings .Join (messages , "\n " )
167
+ welcomeMessage := strings .Join ([]string {
168
+ "\n \n You are now connected to the container." ,
169
+ "Check if all tools and libraries you need are properly installed." ,
170
+ "When you are done, type \" exit\" to return to your Gitpod workspace.\n " ,
171
+ }, "\n " )
178
172
179
- dockerRunCmd := exec .Command (
173
+ dockerRunCmd := exec .CommandContext ( ctx ,
180
174
dockerPath ,
181
175
"run" ,
182
176
"--rm" ,
177
+ "-v" , "/workspace:/workspace" ,
183
178
"--label" , "gp-rebuild=true" ,
184
- "-it" ,
185
- tag ,
186
- "bash" ,
179
+ "-it" , tag ,
180
+ "sh" ,
187
181
"-c" ,
188
- fmt .Sprintf ("echo '%s'; bash" , welcomeMessage ),
182
+ fmt .Sprintf (`
183
+ echo "%s";
184
+ cd "%s";
185
+ if [ -x "$(command -v $SHELL)" ]; then
186
+ $SHELL;
187
+ else
188
+ if [ -x "$(command -v bash)" ]; then
189
+ bash;
190
+ else
191
+ sh;
192
+ fi;
193
+ fi;
194
+ ` , welcomeMessage , wsInfo .CheckoutLocation ),
189
195
)
190
196
191
197
dockerRunCmd .Stdout = os .Stdout
192
198
dockerRunCmd .Stderr = os .Stderr
193
199
dockerRunCmd .Stdin = os .Stdin
194
200
195
- err = dockerRunCmd .Run ()
196
- if _ , ok := err .( * exec. ExitError ); ok {
197
- fmt .Println ("Docker Run Command Failed " )
201
+ err = dockerRunCmd .Start ()
202
+ if err != nil {
203
+ fmt .Println ("Failed to run docker container " )
198
204
event .Set ("ErrorCode" , utils .RebuildErrorCode_DockerRunFailed )
199
- return err
200
- } else if err != nil {
201
- fmt .Println ("Docker error" )
202
- event .Set ("ErrorCode" , utils .RebuildErrorCode_DockerErr )
203
- return err
205
+ return utils .Outcome_UserErr , err
204
206
}
205
207
206
- return nil
208
+ _ = dockerRunCmd .Wait ()
209
+
210
+ return utils .Outcome_Success , nil
207
211
}
208
212
209
213
var buildCmd = & cobra.Command {
210
214
Use : "rebuild" ,
211
215
Short : "Re-builds the workspace image (useful to debug a workspace custom image)" ,
212
216
Hidden : false ,
213
217
Run : func (cmd * cobra.Command , args []string ) {
214
- ctx := context .Background ()
218
+ ctx , cancel := context .WithCancel (context .Background ())
219
+ sigChan := make (chan os.Signal , 1 )
220
+ signal .Notify (sigChan , os .Interrupt , syscall .SIGTERM , syscall .SIGHUP )
221
+ go func () {
222
+ <- sigChan
223
+ cancel ()
224
+ }()
215
225
supervisorClient , err := supervisor .New (ctx )
216
226
if err != nil {
217
227
utils .LogError (ctx , err , "Could not get workspace info required to build" , supervisorClient )
@@ -223,10 +233,18 @@ var buildCmd = &cobra.Command{
223
233
Command : cmd .Name (),
224
234
})
225
235
226
- err = runRebuild (ctx , supervisorClient , event )
227
- if err != nil && event .Data .ErrorCode == "" {
228
- event .Set ("ErrorCode" , utils .SystemErrorCode )
236
+ outcome , err := runRebuild (ctx , supervisorClient , event )
237
+ event .Set ("Outcome" , outcome )
238
+
239
+ if outcome != utils .Outcome_Success && event .Data .ErrorCode == "" {
240
+ switch outcome {
241
+ case utils .Outcome_UserErr :
242
+ event .Set ("ErrorCode" , utils .UserErrorCode )
243
+ case utils .Outcome_SystemErr :
244
+ event .Set ("ErrorCode" , utils .SystemErrorCode )
245
+ }
229
246
}
247
+
230
248
event .Send (ctx )
231
249
232
250
if err != nil {
0 commit comments