-
Notifications
You must be signed in to change notification settings - Fork 0
186 lines (166 loc) · 6.88 KB
/
Copy pathci.yml
File metadata and controls
186 lines (166 loc) · 6.88 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
name: CI
on:
push:
branches: [main]
pull_request:
workflow_dispatch:
# No write access needed: this workflow only reads the code.
permissions:
contents: read
concurrency:
group: ci-${{ github.ref }}
cancel-in-progress: true
jobs:
test:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v7
- uses: actions/setup-go@v7
with:
# Single source of truth for the toolchain version.
go-version-file: go.mod
cache: true
- name: gofmt
run: |
unformatted=$(gofmt -l .)
if [ -n "$unformatted" ]; then
echo "::error::not gofmt-clean: $unformatted"
gofmt -d .
exit 1
fi
- name: go vet
run: go vet ./...
# vet already runs 35 x/tools analyzers. This adds nilness (needs SSA,
# so it is not in vet's default set) and nologsecrets, which enforces
# the CONTRIBUTING invariant that caller IDs and PINs never reach the
# logs — the kind of leak that keeps every test green.
- name: analyzer tests
run: cd tools && go test ./...
- name: lint (nilness + nologsecrets)
run: make lint
# -race matters here: one call is one goroutine and the session state
# machine is driven entirely by channel sends from the ARI event router.
- name: test + coverage floors
run: bash scripts/coverage.sh
- uses: actions/upload-artifact@v7
if: always()
with:
name: coverage
path: coverage.out
retention-days: 14
# The examples are the first thing a new user copies, so a broken
# cross-reference in them is a real defect. This runs the same
# validator the daemon uses, against EVERY example rather than the one
# at the top of examples/: a directory holding a policy.example.toml is
# an example, and that filename is the whole discovery rule. A scenario
# that stops loading fails the build.
# The examples carry the placeholder PIN sentinel and CANNOT pass a
# strict check — that is the point. --allow-placeholders validates
# structure (cross-references, ladders, schedules) without pretending the
# config is usable.
- name: validate every shipped example config
run: |
for policy in $(find examples -name policy.example.toml | sort); do
dir=$(dirname "$policy")
echo "── $policy"
trunks=""
[ -f "$dir/trunks.example.toml" ] && trunks="--trunks $dir/trunks.example.toml"
# shellcheck disable=SC2086
go run ./cmd/doorman check --allow-placeholders \
--handsets "$dir/handsets.example.toml" \
$trunks "$policy" || exit 1
done
# And the inverse: copying any of them verbatim must fail, or the
# sentinel is not doing its job.
- name: examples must not pass a strict check
run: |
for policy in $(find examples -name policy.example.toml | sort); do
dir=$(dirname "$policy")
if go run ./cmd/doorman check \
--handsets "$dir/handsets.example.toml" \
"$policy" 2>/dev/null; then
echo "::error::$policy passed a strict check — the placeholder sentinel is not working"
exit 1
fi
done
echo "examples correctly refuse to load without doorman init"
# A shipped template that does not validate would be a broken example in
# the one place people look for a working one.
- name: shipped templates lint
run: go run ./cmd/doorman template lint templates/*.toml
# init must produce something that passes the strict check.
- name: doorman init round-trip
run: |
tmp=$(mktemp -d)
mkdir -p "$tmp/examples"
cp examples/.env.example "$tmp/examples/"
go build -o "$tmp/doorman" ./cmd/doorman
(cd "$tmp" && ./doorman init --rooms "Kitchen,Office,Kids Room" >/dev/null)
(cd "$tmp" && ./doorman check)
- name: build
run: make build
# The schema is the documented contract for the config surface, so a
# wiring break must fail the build, not just be caught by unit tests.
- name: doorman schema emits valid JSON
run: |
for name in "" policy handsets trunks env; do
./bin/doorman schema $name | python3 -m json.tool >/dev/null \
|| { echo "::error::doorman schema $name is not valid JSON"; exit 1; }
done
echo "schema ok: bundle + $(./bin/doorman schema | python3 -c 'import json,sys; print(len(json.load(sys.stdin)["schemas"]))') documents"
# A man page that does not render is worse than none: the operator who
# needs it is on a Pi with no browser.
# Everything the site serves to models is generated, not hand-copied:
# llms.txt, llms-policy.txt, and the JSON Schema this binary emits.
# Regenerating and diffing catches the schema drifting from the code as
# well as a copy going stale — the old check compared one file by hand
# and missed four pushes' worth of drift.
- name: site assets are current
run: |
make site-assets
git diff --exit-code -- site/public \
|| { echo "::error::site/public is stale — run 'make site-assets' and commit"; exit 1; }
- name: man page lints
run: |
sudo apt-get update -qq && sudo apt-get install -y -qq mandoc
mandoc -Tlint docs/doorman.1
# The site is a deliverable too, and a broken build should be loud.
site:
runs-on: ubuntu-latest
defaults:
run:
working-directory: site
steps:
- uses: actions/checkout@v7
- uses: actions/setup-node@v6
with:
node-version: 22
cache: npm
cache-dependency-path: site/package-lock.json
- run: npm ci
- run: npm run build
# Proves the Pi targets still compile. Cheap, and catches the 32-bit
# breakage (int size, unaligned atomics) that amd64 tests never see.
cross:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v7
- uses: actions/setup-go@v7
with:
go-version-file: go.mod
cache: true
- name: cross-compile Pi binaries
run: make cross
# --severity=warning gates on real defects (an ffmpeg that eats the
# loop's stdin) without enforcing style opinions: smoke.sh's
# `test && pass || fail` idiom is deliberate, and install.sh prints a
# literal $PATH for the user to paste. Both are info-level notes.
- name: shellcheck the shipped scripts
run: |
sudo apt-get update -qq && sudo apt-get install -y -qq shellcheck
shellcheck --severity=warning \
install.sh \
scripts/smoke.sh \
scripts/coverage.sh \
prompts/build.sh \
.githooks/pre-push