Files
questions/lint.sh
T
Bendik Aagaard Lynghaug 6ed0b65bc2
Lint and reload / lint-and-reload (push) Successful in 3s
Add portal_project_inquiries/portal_subscribers durable storage, review dashboard alternatives, newsletter compose
- index.yaml: record_as on "I want something built" and "Keep me
  posted" - those submissions previously only existed as a NATS
  event, nothing durable, despite promising a reply/subscription.
- review.yaml: consolidated into one dashboard question with four
  alternatives (Applicants, Inquiries, Subscribers, Compose
  newsletter) rather than separate pages per resource.
- Compose newsletter has no record_as/resource of its own - an
  automation (n8n) filters portal.answers.submitted directly for
  question_id == "/review" && alternative == "Compose newsletter",
  matching events.rs's own "gain a second subscriber" design.
- lint.sh: allow type: prosekit (the new rich-text requirement kind).
2026-08-05 13:46:17 +02:00

66 lines
1.9 KiB
Bash
Executable File

#!/usr/bin/env bash
# Validates every question YAML file's shape against what
# portal/src/content.rs actually requires at parse time - not a full
# schema check (that would mean building portal itself just to lint
# content, real coupling for no real benefit here), but the mistakes
# that would actually break a load: bad YAML, missing `id`/`name`,
# duplicate `id`s, and unknown requirement `type`s. Uses `yq` (the
# jq-wrapping kislyuk/yq, not the Go mikefarah/yq) so every check is a
# real jq filter, not bespoke parsing.
set -euo pipefail
dir="${1:-questions}"
fail=0
declare -A seen_ids
shopt -s nullglob
for f in "$dir"/*.yaml; do
if ! json=$(yq . "$f" 2>&1); then
echo "FAIL $f: invalid YAML: $json" >&2
fail=1
continue
fi
id=$(jq -r '.id // empty' <<<"$json")
name=$(jq -r '.name // empty' <<<"$json")
if [[ -z "$id" ]]; then
echo "FAIL $f: missing required 'id'" >&2
fail=1
elif [[ -n "${seen_ids[$id]:-}" ]]; then
echo "FAIL $f: duplicate id '$id' (also used by ${seen_ids[$id]})" >&2
fail=1
else
seen_ids[$id]="$f"
fi
if [[ -z "$name" ]]; then
echo "FAIL $f: missing required 'name'" >&2
fail=1
fi
# "textarea", "file", and "prosekit" are the three values
# content.rs/app.rs special-case; anything else is passed straight
# through as an HTML <input type> attribute, so this is the real set
# of valid values, not a guess.
bad_types=$(jq -r '
[.alternatives[]?.features[]?.requirements[]?
| select(.type != null and (.type | IN(
"text", "textarea", "file", "prosekit", "email", "tel", "url",
"number", "password", "date", "datetime-local", "time", "month",
"week", "color", "range", "checkbox", "radio", "hidden", "search"
) | not))
| .type]
| unique | .[]
' <<<"$json")
if [[ -n "$bad_types" ]]; then
echo "FAIL $f: unknown requirement type(s): $(tr '\n' ' ' <<<"$bad_types")" >&2
fail=1
fi
done
if [[ $fail -eq 0 ]]; then
echo "OK: all question files valid"
fi
exit $fail