fix/exec-umask 2cd66dc

sandbox_check.go RawHistoryFolder

1// SPDX-License-Identifier: MIT
2
3package main
4
5import (
6	"context"
7	"errors"
8	"fmt"
9	"os"
10	"strings"
11	"time"
12
13	"github.com/bnema/zerowrap"
14
15	"bnema.dev/ermite-runner/internal/execstream"
16	"bnema.dev/ermite-runner/internal/execstream/execpb"
17	"bnema.dev/ermite-runner/internal/sandbox"
18	"bnema.dev/ermite-runner/internal/sandbox/drivers"
19)
20
21// sandboxCheck runs one stub job in the sandbox chosen by
22// ERMITE_RUNNER_ISOLATION: reap leftovers, start, stream the output to stdout
23// and stderr, stop. Its exit code is the script's. It is the manual counterpart
24// of the integration tests and the smoke test of an installation.
25func sandboxCheck(ctx context.Context, args []string) int {
26	log := zerowrap.FromCtx(ctx)
27	cfg, err := sandbox.LoadConfig(os.Getenv)
28	if err != nil {
29		fmt.Fprintln(os.Stderr, "ermite-runner:", err)
30		return 2
31	}
32	setupExternals(ctx, &cfg)
33	drv, err := sandbox.Select(ctx, cfg, drivers.Factories(), sandbox.Prober{})
34	if err != nil {
35		fmt.Fprintln(os.Stderr, "ermite-runner:", err)
36		return 1
37	}
38	defer func() { _ = drv.Close() }()
39	if err := drv.Reap(ctx); err != nil {
40		log.Warn().Err(err).Msg("reaping leftovers of a previous run")
41	}
42	sb, err := drv.New()
43	if err != nil {
44		fmt.Fprintln(os.Stderr, "ermite-runner:", err)
45		return 1
46	}
47	// Stop runs even when the job context was cancelled.
48	defer func() {
49		sctx, cancel := context.WithTimeout(context.WithoutCancel(ctx), 60*time.Second)
50		defer cancel()
51		if err := sb.Stop(sctx); err != nil {
52			fmt.Fprintln(os.Stderr, "ermite-runner: cleanup:", err)
53			if errors.Is(err, sandbox.ErrLeaked) {
54				fmt.Fprintln(os.Stderr, "ermite-runner: something leaked: run again (the start reaps) or check the state directory")
55			}
56		}
57	}()
58	conn, err := sb.Start(ctx, sandbox.JobSpec{JobID: "sandbox-check"})
59	if err != nil {
60		fmt.Fprintln(os.Stderr, "ermite-runner:", err)
61		return 1
62	}
63	// Ctrl-C / SIGTERM cancel the job: the executor escalates by itself.
64	cancel := make(chan *execpb.Cancel, 1)
65	stop := context.AfterFunc(ctx, func() { cancel <- &execpb.Cancel{Reason: "interrupted"} })
66	defer stop()
67	_, exit, err := execstream.Drive(conn, &execpb.Run{Script: strings.Join(args, " ")}, cancel, func(o *execpb.Output) {
68		f := os.Stdout
69		if o.Stream == execpb.StreamKind_STREAM_KIND_STDERR {
70			f = os.Stderr
71		}
72		_, _ = f.Write(o.Data)
73	})
74	if err != nil {
75		fmt.Fprintln(os.Stderr, "ermite-runner:", err)
76		return 1
77	}
78	if exit.Error != "" {
79		fmt.Fprintln(os.Stderr, "ermite-runner: executor:", exit.Error)
80	}
81	return int(exit.Code)
82}

Keyboard shortcuts

Single-key shortcuts are on. ctrl k and esc work whatever this says.

ctrl k :
go to a section, branch, tag, file or repository
?
this list
j k
move the row cursor down / up
enter
open the row under the cursor; on Files, a directory opens or closes in place
↑ ↓ ← → home end
in the file tree (focus on a row): previous / next row, close / open a directory or go to its parent / first entry, first / last row. They never open a file
l h
on Files: open a directory or a file / close a directory or go up to its parent, then to the parent page. Elsewhere: into the side panel (on a merge request, its files) / back to the content; there j k move between its controls
g g G
first / last row
/
filter the list; on Files, find a file anywhere in the repository (esc clears, enter opens the best match)
b
switch branch or tag
g s g f g c g b g m g i g r g a
tabs: summary, files, commits, branches & tags, merge requests, issues, releases, actions (when available)
g h
home
w
wide mode: use the whole width of the screen, or not (remembered)
y
copy a permalink pinned to the commit
d u x
diff: split / unified / collapse or expand all
e E
diff: the whole file in view / every file, with the lines the hunks hide
n
merge request: next note in the diff
esc
close a dialog, leave a field

Branches 4

Tags 11

↑↓ moveenter openesc close