Skip to content

Commit 801840b

Browse files
committed
[sueprvisor] introduce shutdown hook on tasks
1 parent dbb182a commit 801840b

File tree

8 files changed

+61
-11
lines changed

8 files changed

+61
-11
lines changed

components/gitpod-protocol/data/gitpod-schema.json

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -86,6 +86,10 @@
8686
"type": "string",
8787
"description": "The main shell command to run after `before` and `init`. This command is executed last on every start and doesn't have to terminate."
8888
},
89+
"shutdown": {
90+
"type": "string",
91+
"description": "A shell command to run before a workspace stops. This command needs to finish with `terminationGracePeriodSeconds` and will be force killed if it runs longer."
92+
},
8993
"env": {
9094
"type": "object",
9195
"description": "Environment variables to set."
@@ -114,6 +118,10 @@
114118
"additionalProperties": false
115119
}
116120
},
121+
"terminationGracePeriodSeconds": {
122+
"type": "number",
123+
"description": "The grace period for all processes to stop before beeing force killed. Default is 15 seconds."
124+
},
117125
"image": {
118126
"type": [
119127
"object",

components/gitpod-protocol/src/protocol.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -827,6 +827,7 @@ export interface WorkspaceConfig {
827827
image?: ImageConfig;
828828
ports?: PortConfig[];
829829
tasks?: TaskConfig[];
830+
terminationGracePeriodSeconds?: number;
830831
checkoutLocation?: string;
831832
workspaceLocation?: string;
832833
gitConfig?: { [config: string]: string };
@@ -993,6 +994,7 @@ export interface TaskConfig {
993994
init?: string;
994995
prebuild?: string;
995996
command?: string;
997+
shutdown?: string;
996998
env?: { [env: string]: any };
997999
openIn?: "bottom" | "main" | "left" | "right";
9981000
openMode?: "split-top" | "split-left" | "split-right" | "split-bottom" | "tab-before" | "tab-after";

components/ide/code/startup.sh

Lines changed: 0 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -3,14 +3,6 @@
33
# Licensed under the GNU Affero General Public License (AGPL).
44
# See License-AGPL.txt in the project root for license information.
55

6-
7-
# DO NOT REMOVE THE SPACES AT THE BEGINNING OF THESE LINES
8-
# The spaces at the beginning of the line prevent those lines from being added to
9-
# the bash history.
10-
set +o history
11-
history -c
12-
truncate -s 0 "$HISTFILE"
13-
146
# This is the main entrypoint to workspace container in Gitpod. It is called (and controlled) by the supervisor
157
# container root process.
168
# To mimic a regular login shell on a local computer we execute this with "bash -li" (interactive login shell):

components/server/src/bitbucket/bitbucket-file-provider.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -63,7 +63,7 @@ export class BitbucketFileProvider implements FileProvider {
6363
).data;
6464
return contents as string;
6565
} catch (err) {
66-
log.debug({ userId: user.id }, err);
66+
log.error({ userId: user.id }, err);
6767
}
6868
}
6969
}

components/supervisor/pkg/supervisor/config.go

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -294,6 +294,7 @@ type TaskConfig struct {
294294
Init *string `json:"init,omitempty"`
295295
Prebuild *string `json:"prebuild,omitempty"`
296296
Command *string `json:"command,omitempty"`
297+
Shutdown *string `json:"shutdown,omitempty"`
297298
Env *map[string]interface{} `json:"env,omitempty"`
298299
OpenIn *string `json:"openIn,omitempty"`
299300
OpenMode *string `json:"openMode,omitempty"`

components/supervisor/pkg/supervisor/supervisor.go

Lines changed: 45 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55
package supervisor
66

77
import (
8+
"bufio"
89
"context"
910
"crypto/rand"
1011
"crypto/rsa"
@@ -50,6 +51,7 @@ import (
5051
"github.com/gitpod-io/gitpod/content-service/pkg/executor"
5152
"github.com/gitpod-io/gitpod/content-service/pkg/git"
5253
"github.com/gitpod-io/gitpod/content-service/pkg/initializer"
54+
"github.com/gitpod-io/gitpod/content-service/pkg/logs"
5355
gitpod "github.com/gitpod-io/gitpod/gitpod-protocol"
5456
"github.com/gitpod-io/gitpod/supervisor/api"
5557
"github.com/gitpod-io/gitpod/supervisor/pkg/activation"
@@ -388,19 +390,61 @@ func Run(options ...RunOption) {
388390
}
389391

390392
log.Info("received SIGTERM (or shutdown) - tearing down")
391-
cancel()
393+
392394
err = termMux.Close()
393395
if err != nil {
394396
log.WithError(err).Error("terminal closure failed")
395397
}
396398

399+
cancel()
397400
// terminate all child processes once the IDE is gone
398401
ideWG.Wait()
399402
terminateChildProcesses()
400403

401404
wg.Wait()
402405
}
403406

407+
func runTask(ctx context.Context, termMuxSrv *terminal.MuxTerminalService, task string, taskName string) {
408+
if task == "" {
409+
return
410+
}
411+
openTerminalResponse, err := termMuxSrv.Open(ctx, &api.OpenTerminalRequest{})
412+
if err != nil {
413+
log.WithError(err).Errorf("error running '%q' task", taskName)
414+
}
415+
term, ok := termMuxSrv.Mux.Get(openTerminalResponse.Terminal.Alias)
416+
if !ok {
417+
log.Errorf("cannot obtain terminal for '%q'.", taskName)
418+
} else {
419+
term.PTY.Write([]byte(task + "; exit\n"))
420+
}
421+
stdout := term.Stdout.ListenWithOptions(terminal.TermListenOptions{
422+
// ensure logging of entire task output
423+
ReadTimeout: terminal.NoTimeout,
424+
})
425+
426+
fileName := logs.TerminalStoreLocation + "/" + taskName + ".log"
427+
file, err := os.Create(fileName)
428+
var fileWriter *bufio.Writer
429+
if err != nil {
430+
log.WithError(err).Errorf("cannot create an '%q' log file", taskName)
431+
fileWriter = bufio.NewWriter(io.Discard)
432+
} else {
433+
defer file.Close()
434+
log.Info("Writing build output to " + fileName)
435+
fileWriter = bufio.NewWriter(file)
436+
defer fileWriter.Flush()
437+
}
438+
_, err = io.Copy(fileWriter, stdout)
439+
if err != nil {
440+
log.WithError(err).Errorf("cannot copy from '%q' task", taskName)
441+
}
442+
_, err = term.Wait()
443+
if err != nil {
444+
log.WithError(err).Errorf("terminal exited errorneous")
445+
}
446+
}
447+
404448
func isShallowRepository(rootDir string, env []string) bool {
405449
cmd := runAsGitpodUser(exec.Command("git", "rev-parse", "--is-shallow-repository"))
406450
cmd.Env = env

components/supervisor/pkg/supervisor/tasks_test.go

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -85,6 +85,7 @@ func TestTaskManager(t *testing.T) {
8585
ExpectedReporter: testHeadlessTaskProgressReporter{
8686
Done: true,
8787
Success: true,
88+
Data: "foo",
8889
},
8990
},
9091
{
@@ -243,9 +244,11 @@ func TestTaskManager(t *testing.T) {
243244
type testHeadlessTaskProgressReporter struct {
244245
Done bool
245246
Success bool
247+
Data string
246248
}
247249

248250
func (r *testHeadlessTaskProgressReporter) write(data string, task *task, terminal *terminal.Term) {
251+
r.Data = r.Data + data
249252
}
250253

251254
func (r *testHeadlessTaskProgressReporter) done(success taskSuccess) {

components/supervisor/pkg/terminal/service.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -100,7 +100,7 @@ func (srv *MuxTerminalService) OpenWithOptions(ctx context.Context, req *api.Ope
100100
if cmd.Dir == "" {
101101
cmd.Dir = srv.DefaultWorkdir
102102
}
103-
cmd.Env = append(srv.Env, "TERM=xterm-256color")
103+
cmd.Env = append(srv.Env, "TERM=xterm-256color", "PROMPT_COMMAND='history -a'")
104104
for key, value := range req.Env {
105105
cmd.Env = append(cmd.Env, fmt.Sprintf("%v=%v", key, value))
106106
}

0 commit comments

Comments
 (0)