diff --git a/.gitea/workflows/lint-and-reload.yml b/.gitea/workflows/lint-and-reload.yml index b8e229f..831491a 100644 --- a/.gitea/workflows/lint-and-reload.yml +++ b/.gitea/workflows/lint-and-reload.yml @@ -10,8 +10,13 @@ jobs: steps: - uses: actions/checkout@v4 + # Same bare-metal runner/host as portal's own deploy job, which + # publishes this binary to a stable path on every deploy - runs + # portal's real transition-table/shape validation directly, not a + # hand-maintained yq/jq subset of the same rules (lint.sh, now + # superseded and removed). - name: Lint questions - run: bash lint.sh questions + run: /srv/app/uhhm-portal/current/question_lint --path questions # Tells every running portal instance to re-fetch and atomically # swap in the new content - see content::watch_for_reload in the diff --git a/lint.sh b/lint.sh deleted file mode 100755 index 126ea95..0000000 --- a/lint.sh +++ /dev/null @@ -1,65 +0,0 @@ -#!/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", "prosekit", and "select" are the four values - # content.rs/app.rs special-case; anything else is passed straight - # through as an HTML 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", "select", "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