From 61743cf3a76bfc6dba2c4d4d6be725c705162bb3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Istv=C3=A1n=20Zolt=C3=A1n=20Szab=C3=B3?= Date: Mon, 14 Sep 2026 14:34:04 +0200 Subject: [PATCH] Fix CI. --- .github/workflows/prompts.yml | 21 ++------- automation/prompts/README.md | 10 +++- automation/prompts/check-prompts.sh | 72 ++++++++++++++++++++--------- 3 files changed, 60 insertions(+), 43 deletions(-) diff --git a/.github/workflows/prompts.yml b/.github/workflows/prompts.yml index 901eabd25..d99b28ae4 100644 --- a/.github/workflows/prompts.yml +++ b/.github/workflows/prompts.yml @@ -3,7 +3,6 @@ name: Check documentation prompts on: pull_request: paths: - - 'qdrant-landing/content/documentation/headless/prompts/**' - 'qdrant-landing/content/**/*.md' - 'qdrant-landing/layouts/shortcodes/prompt.markdown.md' - 'qdrant-landing/themes/qdrant-2024/layouts/shortcodes/prompt.html' @@ -16,22 +15,8 @@ jobs: steps: - uses: actions/checkout@v4 - - name: Install Hugo - uses: peaceiris/actions-hugo@v3 - with: - hugo-version: '0.160.1' - extended: true - - - name: Install Dart Sass - run: | - curl -sSL -o dart-sass.tar.gz \ - https://github.com/sass/dart-sass/releases/download/1.70.0/dart-sass-1.70.0-linux-x64.tar.gz - tar -xzf dart-sass.tar.gz - echo "$PWD/dart-sass" >> "$GITHUB_PATH" - - - name: Build site - working-directory: qdrant-landing - run: hugo --destination public - + # Source checks only: no Hugo, no Dart Sass, no npm install. The rules + # this guards are all visible in the source, so a full site build would + # cost minutes on every docs PR to verify something that takes seconds. - name: Check prompts run: automation/prompts/check-prompts.sh diff --git a/automation/prompts/README.md b/automation/prompts/README.md index c8bb8a730..f0262d921 100644 --- a/automation/prompts/README.md +++ b/automation/prompts/README.md @@ -32,7 +32,9 @@ pages include them by id. 2. Add `{{< prompt "" >}}` to that page, near the top of the section it relates to rather than at the bottom. -3. Run `automation/prompts/check-prompts.sh` after a build. +3. Run `automation/prompts/check-prompts.sh`. It needs no build. Pass a built + site directory to also verify the real output, for example + `automation/prompts/check-prompts.sh qdrant-landing/public`. ## Writing one @@ -68,4 +70,8 @@ prompt is never written as a plain fenced block on the page. who includes them, so a stale declaration would put a wrong link in the index, and a prompt that is never included would still be listed. -`check-prompts.sh` guards both. +`check-prompts.sh` guards both, plus a third rule that keeps them equivalent: +the Markdown variant of the shortcode must never render the body. Rule one is +checked in the source rather than in the built output, because pasting a body +inline is a source-level mistake and catching it there means CI needs no site +build. diff --git a/automation/prompts/check-prompts.sh b/automation/prompts/check-prompts.sh index 726f24382..355586149 100755 --- a/automation/prompts/check-prompts.sh +++ b/automation/prompts/check-prompts.sh @@ -1,25 +1,34 @@ #!/usr/bin/env bash -# Guards the two rules that keep documentation prompts working. Both fail +# Guards the rules that keep documentation prompts working. All of them fail # silently otherwise, which is why they are checked rather than reviewed. # -# 1. No prompt body reaches a built index.md. Those files are consumed by -# agents, and a prompt is an instruction addressed to an agent, so it can -# displace the question the agent was actually asked. Writing a prompt as a -# plain fenced block instead of using the shortcode is how this breaks. -# 2. Every prompt's declared `page:` really includes it. The prompt files live +# 1. No prompt body is written inline on a page. Prompt bodies must not reach +# a built index.md, because those files are consumed by agents and a prompt +# is an instruction addressed to an agent, so it can displace the question +# the agent was actually asked. The shortcode's Markdown variant drops the +# body, so the only way a body reaches index.md is an author pasting it as +# a fenced block instead of using the shortcode. That is a source-level +# mistake, so it is caught in the source. +# 2. The Markdown variant of the shortcode still drops the body. Rule 1 is +# only equivalent to "no body in index.md" while this holds. +# 3. Every prompt's declared `page:` really includes it. The prompt files live # in one folder and cannot know who includes them, so the declaration is # what the index trusts. This also catches a prompt that is written but # never used, which would otherwise appear in the index anyway. # -# Usage: automation/prompts/check-prompts.sh [built-site-dir] -# Default built-site-dir is qdrant-landing/public. +# These are all source checks, so no site build is needed and the run takes +# seconds. Pass a built-site directory to additionally verify the real output: +# +# automation/prompts/check-prompts.sh # source checks only +# automation/prompts/check-prompts.sh qdrant-landing/public # and the build set -Eeuo pipefail repo_root="$(cd "$(dirname "${BASH_SOURCE[0]}")/../.." && pwd)" -public_dir="${1:-$repo_root/qdrant-landing/public}" +public_dir="${1:-}" prompts_dir="$repo_root/qdrant-landing/content/documentation/headless/prompts" content_dir="$repo_root/qdrant-landing/content" +md_shortcode="$repo_root/qdrant-landing/layouts/shortcodes/prompt.markdown.md" failures=0 @@ -33,23 +42,23 @@ if [[ ! -d "$prompts_dir" ]]; then exit 0 fi -if [[ ! -d "$public_dir" ]]; then - fail "built site not found at $public_dir (run hugo first, or pass the directory)" - exit 1 +# --- rule 2: the Markdown variant must not render the prompt body --- +if [[ ! -f "$md_shortcode" ]]; then + fail "missing $md_shortcode: without it, prompt bodies reach the agent-facing Markdown" +elif grep -qE '\.(RawContent|Content|Inner)\b' "$md_shortcode"; then + fail "$md_shortcode renders the prompt body; it must emit only the skill pointer" fi shopt -s nullglob -prompt_files=("$prompts_dir"/*.md) checked=0 -for file in "${prompt_files[@]}"; do +for file in "$prompts_dir"/*.md; do id="$(basename "$file" .md)" [[ "$id" == "_index" ]] && continue checked=$((checked + 1)) - # --- rule 1: the body must not appear in any built index.md --- - # Use the first non-empty body line as the probe. Front matter is delimited - # by the first two '---' lines. + # First non-empty body line, used as the probe. Front matter is delimited by + # the first two '---' lines. probe="$(awk ' /^---[[:space:]]*$/ { d++; next } d >= 2 && NF { print; exit } @@ -60,13 +69,15 @@ for file in "${prompt_files[@]}"; do continue fi - if hits="$(grep -rlF "$probe" --include='index.md' "$public_dir" 2>/dev/null)" && [[ -n "$hits" ]]; then - fail "$id: prompt body reached the agent-facing Markdown output:" + # --- rule 1: the body must not appear inline anywhere in the content tree --- + if hits="$(grep -rlF "$probe" --include='*.md' "$content_dir" 2>/dev/null \ + | grep -v "^$prompts_dir/" || true)" && [[ -n "$hits" ]]; then + fail "$id: prompt body is written inline instead of using the shortcode:" printf ' %s\n' $hits >&2 - printf ' Use {{< prompt "%s" >}} rather than a fenced block.\n' "$id" >&2 + printf ' Replace it with {{< prompt "%s" >}}\n' "$id" >&2 fi - # --- rule 2: the declared page must include the shortcode --- + # --- rule 3: the declared page must include the shortcode --- page="$(awk -F': *' ' /^---[[:space:]]*$/ { d++; if (d >= 2) exit; next } d == 1 && $1 == "page" { print $2; exit } @@ -77,7 +88,6 @@ for file in "${prompt_files[@]}"; do continue fi - # /documentation/foo/bar/ -> content/documentation/foo/bar.md or .../bar/_index.md rel="${page#/}" rel="${rel%/}" src="" @@ -94,6 +104,18 @@ for file in "${prompt_files[@]}"; do fail "$id: declared page $page does not include it" printf ' Expected {{< prompt "%s" >}} in %s\n' "$id" "${src#"$repo_root"/}" >&2 fi + + # --- optional: verify the real built output when a build is available --- + if [[ -n "$public_dir" ]]; then + if [[ ! -d "$public_dir" ]]; then + fail "built site not found at $public_dir" + public_dir="" + elif built="$(grep -rlF "$probe" --include='index.md' "$public_dir" 2>/dev/null || true)" \ + && [[ -n "$built" ]]; then + fail "$id: prompt body reached the agent-facing Markdown output:" + printf ' %s\n' $built >&2 + fi + fi done if (( failures > 0 )); then @@ -101,4 +123,8 @@ if (( failures > 0 )); then exit 1 fi -printf 'Prompt checks passed: %d prompt(s).\n' "$checked" +if [[ -n "$public_dir" ]]; then + printf 'Prompt checks passed (source and build): %d prompt(s).\n' "$checked" +else + printf 'Prompt checks passed: %d prompt(s).\n' "$checked" +fi