v0.18.0 0cea275

serve.go RawHistoryFolder

1// SPDX-License-Identifier: AGPL-3.0-or-later
2
3package app
4
5import (
6	"context"
7	"errors"
8	"os"
9	"os/signal"
10	"strings"
11	"syscall"
12
13	"github.com/bnema/zerowrap"
14	"github.com/spf13/cobra"
15
16	"bnema.dev/ermite/internal/config"
17	"bnema.dev/ermite/internal/domain"
18)
19
20func newServeCmd() *cobra.Command {
21	return &cobra.Command{
22		Use:   "serve",
23		Short: "Run the server",
24		Long: "Run the server. It is configured by the environment only:\n" +
25			config.EnvAddr + ", " + config.EnvDataDir + ", " + config.EnvPublicURL + ", " + config.EnvAdminToken + ",\n" +
26			config.EnvTrustedProxies + ", " + config.EnvGit + ", " + config.EnvSourceURL + ", " +
27			config.EnvLogLevel + ", " + config.EnvLogFormat + ",\n" +
28			config.EnvCommitterName + ", " + config.EnvCommitterEmail + ".",
29		Args: cobra.NoArgs,
30		RunE: func(cmd *cobra.Command, _ []string) error {
31			return serve(cmd.Context())
32		},
33	}
34}
35
36// serve wires the adapters and runs the server until SIGINT or SIGTERM.
37func serve(ctx context.Context) error {
38	cfg, err := loadConfig(os.Getenv)
39	if err != nil {
40		return err
41	}
42	// The logger is built from the validated settings, which carry the
43	// defaults of ERMITE_LOG_LEVEL and ERMITE_LOG_FORMAT.
44	log := zerowrap.New(zerowrap.Config{Level: cfg.LogLevel, Format: cfg.LogFormat})
45	ctx = zerowrap.WithCtx(ctx, log)
46	ctx, stop := signal.NotifyContext(ctx, os.Interrupt, syscall.SIGTERM)
47	defer stop()
48	// Restore the default signal handling as soon as the first signal
49	// arrives, so a second one kills the process during the shutdown.
50	go func() {
51		<-ctx.Done()
52		stop()
53	}()
54
55	log.Info().Str("version", version()).Str("addr", cfg.Addr).Str("data_dir", cfg.DataDir).Msg("starting")
56
57	if err := prepareDataDir(cfg.DataDir); err != nil {
58		return err
59	}
60	f, err := newForge(ctx, cfg, options{})
61	if err != nil {
62		return err
63	}
64	// The server has stopped by the time this runs; close even when ctx ended.
65	defer f.Close(context.WithoutCancel(ctx))
66
67	if err := f.Run(ctx); err != nil {
68		return err
69	}
70	log.Info().Msg("stopped")
71	return nil
72}
73
74// loadConfig reads the configuration and adds the checks that need the domain,
75// which config does not import: ERMITE_OWNER follows the rules of repository
76// names. Its problem joins the others in one report.
77func loadConfig(get func(string) string) (config.Config, error) {
78	cfg, err := config.Load(get)
79	var problems []string
80	var ce *config.Error
81	switch {
82	case errors.As(err, &ce):
83		problems = ce.Problems
84	case err != nil:
85		return config.Config{}, err
86	}
87	if owner := strings.TrimSpace(get(config.EnvOwner)); owner != "" {
88		if _, perr := domain.ParseRepoName(owner); perr != nil {
89			problems = append(problems, config.EnvOwner+": must follow the rules of repository names ("+perr.Error()+")")
90		}
91	}
92	if len(problems) > 0 {
93		return config.Config{}, &config.Error{Problems: problems}
94	}
95	return cfg, nil
96}

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 2

Tags 44

↑↓ moveenter openesc close