Repository navigation
Expand file tree
/
Copy pathjustfile
More file actions
206 lines (179 loc) · 6.42 KB
/
Copy pathjustfile
File metadata and controls
206 lines (179 loc) · 6.42 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
version := `git describe --tags --always 2>/dev/null || echo dev`
ldflags := "-s -w -X main.version=" + version
prefix := env_var_or_default("PREFIX", env_var("HOME") / ".local/bin")
scratch := "/tmp/stoat-scratch"
# show available recipes
default:
@just --list
# build ./stoat
[group('build')]
build:
go build -ldflags "{{ldflags}}" -o stoat ./cmd/stoat
# build and install to $PREFIX (default ~/.local/bin)
[group('build')]
install: build
install -Dm755 stoat {{prefix}}/stoat
@echo "installed {{prefix}}/stoat ({{version}})"
@command -v stoat >/dev/null || echo "note: {{prefix}} is not on your PATH"
# build and install stoat, interactively: checks the host too
[group('build')]
setup:
go run ./cmd/installer
# build and install stoat without a TTY: for CI and scripts
[group('build')]
setup-headless:
go run ./cmd/installer --no-tty
# set this clone up for contributing: enables the repository git hooks
[group('dev')]
dev-setup: hooks
@echo "run 'just setup' to build and install stoat itself"
# remove the installed binary: never touches ~/.stoat
[group('build')]
uninstall:
rm -f {{prefix}}/stoat
@echo "removed {{prefix}}/stoat, your VMs in ${STOAT_HOME:-~/.stoat} were left alone"
# run against your real ~/.stoat
[group('dev')]
run *args: build
./stoat {{args}}
# run against a throwaway data root, so dev cannot touch your real VMs
[group('dev')]
dev *args: build
@mkdir -p {{scratch}}
@echo "STOAT_HOME={{scratch}}"
STOAT_HOME={{scratch}} ./stoat {{args}}
# delete the throwaway data root used by `just dev`
[group('dev')]
dev-reset:
rm -rf {{scratch}}
@echo "wiped {{scratch}}"
# run all tests
[group('test')]
test:
go test ./...
# verbose tests for one package, e.g. `just test-pkg apkovl`
[group('test')]
test-pkg pkg:
go test ./internal/{{pkg}}/ -v
# tests with the race detector
[group('test')]
race:
go test -race ./...
# full lifecycle check on a real disk VM: install -> apply -> reboot -> mouse
# works. Needs KVM and network, ~15 min. Set STOAT_HOME to isolate it.
[group('test')]
e2e:
./scripts/e2e.sh
# shell gates that build a binary or add a worktree, run separately from
# `go test`
[group('test')]
gates:
bash tests/legacy-binary-refusal_test.sh
# coverage summary per package
[group('test')]
cover:
go test -cover ./...
# exactly what .githooks/pre-commit runs
[group('dev')]
check:
gofmt -l $(git ls-files "*.go")
go vet ./...
go build ./...
# exactly what the lint and shellcheck CI jobs run
[group('dev')]
lint:
golangci-lint run ./...
shellcheck -S warning $(git ls-files "internal/recipes/bundled/*.sh" "internal/recipes/bundled/*/*.sh" "scripts/*.sh" ".githooks/*")
# format in place
[group('dev')]
fmt:
gofmt -w $(git ls-files "*.go")
# tidy go.mod and show the go directive
[group('dev')]
tidy:
go mod tidy
@grep '^go ' go.mod
# enable the pre-commit and commit-msg hooks
[group('dev')]
hooks:
git config core.hooksPath .githooks
@echo "hooks enabled: $(git config core.hooksPath)"
# what stoat knows about: VMs, ISOs, ports
[group('vms')]
vms:
#!/usr/bin/env sh
. "{{justfile_directory()}}/.just/fmt.sh"
root="${STOAT_HOME:-$HOME/.stoat}"
[ -d "$root" ] || { warn "no data root at $root"; exit 0; }
head "vms" "$root"
dim "$(printf ' %-16s %-6s %-9s %-9s %6s %5s' NAME MODE STATE RECIPES RAM SSH)"
any=0
for d in "$root"/*/; do
[ -d "$d" ] || continue
n=$(basename "$d")
case "$n" in isos|recipes|logs) continue ;; esac
any=1
if [ ! -f "$d/vm.toml" ]; then
printf " %s %-16s %s\n" "$(c 8 '?')" "$n" "$(c 8 'no vm.toml')"
continue
fi
port=$(sed -n 's/^sshport *= *//p' "$d/vm.toml" | tr -d ' ')
mode=$(sed -n 's/^mode *= *//p' "$d/vm.toml" | tr -d '" ')
ram=$(sed -n 's/^ram *= *//p' "$d/vm.toml" | tr -d ' ')
rec=$(sed -n 's/^recipes *= *//p' "$d/vm.toml" | tr -d '[]" ')
[ -n "$mode" ] || { printf " %s %-16s %s\n" "$(c 1 '!')" "$n" "$(c 1 'broken vm.toml')"; continue; }
if [ -f "$d/qemu.pid" ] && kill -0 "$(cat "$d/qemu.pid" 2>/dev/null)" 2>/dev/null; then
dot=$(c 2 '●'); state=$(c 2 "$(printf '%-9s' running)")
else
dot=$(c 8 '○'); state=$(c 8 "$(printf '%-9s' stopped)")
fi
printf " %s %-16s %-6s %s %-9s %6s %5s\n" "$dot" "$n" "$mode" "$state" "${rec:--}" "${ram:-?}M" "${port:-?}"
done
[ "$any" = 1 ] || dim " no vms yet: run 'just dev' and press n"
echo
head "isos" "$root/isos"
ls -1sh "$root/isos" 2>/dev/null | sed '1d;s/^/ /' || dim " none"
# tail stoat's log
[group('vms')]
logs n="50":
@tail -n {{n}} "${STOAT_HOME:-$HOME/.stoat}/logs/stoat.log" 2>/dev/null || echo "no log yet"
# tail a VM's last provision run, e.g. `just provision-log alpine`
[group('vms')]
provision-log name n="40":
#!/usr/bin/env sh
. "{{justfile_directory()}}/.just/fmt.sh"
f="${STOAT_HOME:-$HOME/.stoat}/{{name}}/last-provision.log"
[ -f "$f" ] || { warn "no provision log for {{name}}: press p in the TUI first"; exit 0; }
head "provision log" "{{name}}"
tail -n {{n}} "$f" | sed 's/^/ /'
echo
dim " $(wc -l < "$f") lines · $f"
# check host prerequisites
[group('vms')]
doctor:
#!/usr/bin/env sh
. "{{justfile_directory()}}/.just/fmt.sh"
head "doctor" "$(uname -sr)"
miss=0
for b in qemu-system-x86_64 qemu-img ssh ssh-keygen go just; do
if p=$(command -v "$b" 2>/dev/null); then ok "$b" "$p"; else bad "$b" "not found"; miss=$((miss+1)); fi
done
if [ -r /dev/kvm ] && [ -w /dev/kvm ]; then ok /dev/kvm "readable and writable"
else bad /dev/kvm "add yourself to the kvm group, then re-login"; miss=$((miss+1)); fi
root="${STOAT_HOME:-$HOME/.stoat}"
[ -d "$root" ] && ok "data root" "$root" || warn2 "data root" "$root (created on first run)"
if command -v stoat >/dev/null; then ok "stoat on PATH" "$(command -v stoat) ($(stoat --version 2>/dev/null))"
else warn2 "stoat on PATH" "not installed: run 'just install'"; fi
echo
[ "$miss" = 0 ] && printf " %s all prerequisites present\n" "$(c 2 ✓)" || printf " %s %s missing\n" "$(c 1 ✗)" "$miss"
# remove build artifacts (never touches your VMs)
[group('build')]
clean:
rm -f stoat
go clean -testcache
# tag a release; pushing the tag triggers the release workflow
[group('release')]
tag v:
@git diff --quiet || { echo "working tree dirty"; exit 1; }
git tag {{v}}
@echo "created {{v}}, push with: git push origin {{v}}"