Files
DDI/scripts/ci/smoke-server.sh
T
beug.k@beugsiud.deandClaude Opus 5.5 56347ec5ff
ci / Web (lint, test, audit, build) (push) Successful in 1m1s
ci / Shell and licence headers (push) Successful in 7s
ci / Go (lint, test, vuln) (push) Failing after 2m40s
ci / Protobuf (push) Successful in 6s
ci / Release build (dry run) (push) Successful in 2m27s
ci / End-to-end (server, agents, BIND, Kea) (push) Failing after 1m26s
ci / Development environment (compose) (push) Successful in 13s
ci / Integration (real BIND and Kea) (push) Failing after 1m58s
test: end-to-end test of the agent path, fix first CI findings
test/e2e runs server, PostgreSQL, BIND and Kea with both agents in
containers (make test-e2e, CI job End-to-end): enrollment with the
command from the API, revision 1 and 2 applied and served by BIND and
Kea, unchanged data creates no revision, revoking disconnects the agent
while BIND keeps serving.

Fixes from the first CI run: quote a spec description containing a
comma, exempt the agent lock-out routes in the route protection test,
whole-second certificate lifetimes, a push replacing queued pulls, the
truncation marker containing the letter checked, and curl|grep -q under
pipefail in the server smoke test.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-13 19:29:58 +02:00

87 lines
3.2 KiB
Bash
Executable File

#!/usr/bin/env bash
# SPDX-License-Identifier: Apache-2.0
#
# Starts the released server binary against a database and checks that it
# serves health, metrics, the API and the embedded web UI.
#
# Usage: scripts/ci/smoke-server.sh DIST_DIR
# Environment: DDI_DATABASE_URL (required), BIN_SERVER (default ddi-server)
set -euo pipefail
dist="${1:?usage: smoke-server.sh DIST_DIR}"
: "${DDI_DATABASE_URL:?DDI_DATABASE_URL must be set}"
bin_name="${BIN_SERVER:-ddi-server}"
work="$(mktemp -d)"
pid=""
cleanup() {
if [[ -n "$pid" ]]; then
kill "$pid" 2>/dev/null || true
wait "$pid" 2>/dev/null || true
fi
rm -rf "$work"
}
trap cleanup EXIT
arch="$(uname -m)"
case "$arch" in
x86_64) goarch=amd64 ;;
aarch64 | arm64) goarch=arm64 ;;
*) echo "unsupported architecture $arch" >&2; exit 1 ;;
esac
tarball="$(find "$dist" -maxdepth 1 -name "${bin_name}_*_linux_${goarch}.tar.gz" | head -n1)"
[[ -n "$tarball" ]] || { echo "no server tarball for linux/${goarch} in ${dist}" >&2; exit 1; }
tar -xzf "$tarball" -C "$work"
server="$(find "$work" -type f -name "$bin_name" | head -n1)"
"$server" version
"$server" gen-master-key -out "$work/master.key" >/dev/null
port=18443
export DDI_HTTP_LISTEN="127.0.0.1:${port}" DDI_AGENT_API_LISTEN="127.0.0.1:$((port + 1))" DDI_MASTER_KEY_FILE="$work/master.key" DDI_STATE_DIR="$work/state"
# An unreachable license server: the server must start anyway (trial).
export KEYGEN_URL="http://127.0.0.1:1"
"$server" bootstrap-admin >"$work/admin.txt"
grep -q '^password: ' "$work/admin.txt"
"$server" serve >"$work/server.log" 2>&1 &
pid=$!
base="http://127.0.0.1:${port}"
for _ in $(seq 1 60); do
if curl -fsS "$base/readyz" >/dev/null 2>&1; then break; fi
if ! kill -0 "$pid" 2>/dev/null; then cat "$work/server.log" >&2; exit 1; fi
sleep 0.5
done
fail() {
echo "FAIL: $*" >&2
cat "$work/server.log" >&2
exit 1
}
grep -q '"database":"ok"' <<<"$(curl -fsS "$base/readyz")" || fail "readyz"
grep -q '^ddi_license_writable 1' <<<"$(curl -fsS "$base/metrics")" || fail "metrics"
grep -q '"license_state":"trial"' <<<"$(curl -fsS "$base/api/v1/system/info")" || fail "system info"
# The web UI is embedded: index.html references hashed assets that load.
index="$(curl -fsS -D "$work/headers" "$base/")"
grep -q '<div id="root">' <<<"$index" || fail "index.html is not the built UI"
grep -qi '^content-security-policy:' "$work/headers" || fail "CSP header missing"
asset="$(grep -o 'src="/assets/[^"]*\.js"' <<<"$index" | head -n1 | sed 's/src="//; s/"$//')"
[[ -n "$asset" ]] || fail "no script asset in index.html"
curl -fsS -o /dev/null -D "$work/asset-headers" "$base$asset" || fail "asset $asset"
grep -qi '^cache-control: .*immutable' "$work/asset-headers" || fail "assets must be immutable"
# Client-side routes fall back to the UI.
grep -q '<div id="root">' <<<"$(curl -fsS "$base/addresses?q=x")" || fail "SPA fallback"
# Unknown API paths are JSON errors, not the UI.
code="$(curl -s -o /dev/null -w '%{http_code}' "$base/api/v1/nope")"
[[ "$code" == "401" || "$code" == "404" ]] || fail "unknown API path returned $code"
# The license trust anchor is embedded (configuration cannot replace it).
grep -q 'license trust anchor comes from configuration' "$work/server.log" && fail "trust anchor not embedded"
echo "server smoke test passed"