v0.35.2 80d5067

serve.sh RawHistoryFolder

1#!/usr/bin/env bash
2# SPDX-License-Identifier: AGPL-3.0-or-later
3#
4# Builds ermite from this checkout and starts a throw-away server for the load
5# tests, seeded with repositories whose history spreads over 90 days. The
6# server is pinned to CPUS cores (GOMAXPROCS and taskset), so that the figures
7# say what a small host can do, not what the workstation can.
8#
9#   scripts/loadtest/serve.sh            # 1 core, http://127.0.0.1:7418
10#   CPUS=2 scripts/loadtest/serve.sh
11#   scripts/loadtest/serve.sh stop
12set -euo pipefail
13
14ROOT=${LOADTEST_DIR:-${TMPDIR:-/tmp}/ermite-loadtest}
15ADDR=${ADDR:-127.0.0.1:7418}
16CPUS=${CPUS:-1}
17URL=http://$ADDR
18TOKEN=loadtest-admin-token-0123456789abcdefghijklmnop
19
20# stop ends the server and waits for it (it shuts down gracefully), so that
21# its data is never removed under it.
22stop() {
23  [[ -f $ROOT/pid ]] || return 0
24  local pid; pid=$(cat "$ROOT/pid")
25  if kill "$pid" 2>/dev/null; then
26    for _ in $(seq 150); do kill -0 "$pid" 2>/dev/null || break; sleep 0.1; done
27    kill -9 "$pid" 2>/dev/null || true
28  fi
29  rm -f "$ROOT/pid"
30}
31if [[ ${1:-} == stop ]]; then stop; exit 0; fi
32stop
33
34cd "$(git rev-parse --show-toplevel)"
35rm -rf "$ROOT" && mkdir -p "$ROOT/data" "$ROOT/wt"
36GOWORK=off go build -o "$ROOT/ermite" ./cmd/ermite
37BIN=$ROOT/ermite
38
39export ERMITE_DATA_DIR=$ROOT/data ERMITE_PUBLIC_URL=$URL ERMITE_ADDR=$ADDR
40export ERMITE_ADMIN_TOKEN=$TOKEN ERMITE_LOG_FORMAT=console ERMITE_LOG_LEVEL=warn
41export ERMITE_URL=$URL ERMITE_TOKEN=$TOKEN ERMITE_CONFIG=$ROOT/cfg
42
43# The last CPUS of the CPUs this shell may use run the server; run the load
44# generator on the others (see README.md).
45mapfile -t allowed < <(python3 -c 'import os; print(*sorted(os.sched_getaffinity(0)), sep="\n")')
46if ! [[ $CPUS =~ ^[1-9][0-9]*$ ]] || ((CPUS >= ${#allowed[@]})); then
47  echo "CPUS must be between 1 and $((${#allowed[@]} - 1)), got $CPUS" >&2; exit 2
48fi
49server_cpus=$(IFS=,; echo "${allowed[*]: -CPUS}")
50GOMAXPROCS=$CPUS taskset -c "$server_cpus" "$BIN" serve >"$ROOT/log" 2>&1 &
51echo $! >"$ROOT/pid"
52for _ in $(seq 100); do curl -fs "$URL/-/health" >/dev/null && break; sleep 0.1; done
53
54now=$(date +%s)
55seed() { # name visibility description profile
56  local name=$1 vis=$2 desc=$3 prof=$4 d=$ROOT/wt/$1
57  "$BIN" repo create "$name" --visibility "$vis" --description "$desc" >/dev/null
58  mkdir -p "$d" && cd "$d"
59  git init -q -b main . && git config user.email loadtest@example.test && git config user.name Loadtest
60  python3 - "$prof" "$now" >"$ROOT/$name.dates" <<'PY'
61import sys, math, random
62prof, now = sys.argv[1], int(sys.argv[2]); random.seed(prof)
63out = []
64for day in range(89, -1, -1):
65    if prof == 'busy': lam = 6 + 5*math.sin(day/9) + (14 if day < 6 else 0)
66    elif prof == 'bursty': lam = 18 if 40 < day < 48 or 10 < day < 14 else 0.3
67    elif prof == 'sleepy': lam = 3 if day > 60 else 0
68    else: lam = 1.2
69    for _ in range(max(0, int(random.gauss(lam, math.sqrt(lam + 0.1))))):
70        out.append(now - day*86400 - random.randint(0, 80000))
71for t in sorted(out): print(t)
72PY
73  local i=0 subjects=("initial import" "add the parser" "fix an off-by-one error in the tokenizer" "refactor storage layer" "bump dependencies" "document the public API" "tidy up")
74  while read -r t; do
75    i=$((i + 1)); echo $i >f.txt; git add -A
76    GIT_AUTHOR_DATE="@$t" GIT_COMMITTER_DATE="@$t" git commit -qm "${subjects[$((i % 7))]} $i"
77  done <"$ROOT/$name.dates"
78  git tag "v1.$((i / 10)).0"
79  git push -q --tags "http://x:$TOKEN@$ADDR/$name.git" main
80}
81seed alpha public "A small Wayland compositor that spends its frames on your apps" busy
82seed bravo public "Keyboard-driven web browser for tiling window managers" bursty
83seed charlie public "Self-hosted container deployment: push an image, deploy it" steady
84seed delta private "Library that reads terminal output and tracks the screen" sleepy
85"$BIN" repo create echo --visibility public --description "Never pushed" >/dev/null
86
87echo "ermite on $URL, CPU(s) $server_cpus, data in $ROOT (pid $(cat "$ROOT/pid"))"
88echo "admin token: $TOKEN"

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 45

↑↓ moveenter openesc close