From 6feffa5177439420bdfbc7b802192f0726bbe41d Mon Sep 17 00:00:00 2001 From: Matthias Linhuber Date: Thu, 27 Aug 2026 13:33:22 +0200 Subject: [PATCH 1/3] chore: enforce vX.Y.Z release tags Calls the shared tag-format check from EduIDE/.github, so a tag push that is not vX.Y.Z fails instead of quietly joining the three spellings this org already has (1.1.0, v1.1.0, v.1.1.1). The grammar lives in one place rather than being copied into each repo. Runs only on tag pushes, so it costs nothing on a normal PR. Depends on EduIDE/.github#3. --- .github/workflows/tag-format.yml | 19 +++++++++++++++++++ 1 file changed, 19 insertions(+) create mode 100644 .github/workflows/tag-format.yml diff --git a/.github/workflows/tag-format.yml b/.github/workflows/tag-format.yml new file mode 100644 index 0000000..10ba123 --- /dev/null +++ b/.github/workflows/tag-format.yml @@ -0,0 +1,19 @@ +# Enforce one spelling for release tags. The grammar lives in +# EduIDE/.github so the repos cannot drift apart on it. +# +# git tag vX.Y.Z +# image tag X.Y.Z +# chart version X.Y.Z + +name: Tag format + +on: + push: + tags: ["**"] + +permissions: + contents: read + +jobs: + check: + uses: EduIDE/.github/.github/workflows/check-tag-format.yml@main From abb0d97da0366f20957809c8216f562ed7357bac Mon Sep 17 00:00:00 2001 From: Matthias Linhuber Date: Thu, 27 Aug 2026 13:33:22 +0200 Subject: [PATCH 2/3] chore: check AGENTS.md path claims in both directions A backticked path must exist - unless the sentence says it does not, in which case it must NOT exist. This repo's AGENTS.md is the one that survived the rewrite unchanged, so it kept the one-directional guard while the other five repos got the improved one. Only true absence flips the check: "is dead" and "retired" describe something that exists and does not work, which is a different claim. --- scripts/check-agents-md.sh | 57 ++++++++++++++++++++++++++++---------- 1 file changed, 43 insertions(+), 14 deletions(-) diff --git a/scripts/check-agents-md.sh b/scripts/check-agents-md.sh index 2aa8353..7054e5f 100755 --- a/scripts/check-agents-md.sh +++ b/scripts/check-agents-md.sh @@ -1,13 +1,18 @@ #!/usr/bin/env bash -# Flag paths referenced by AGENTS.md that no longer exist. +# Check AGENTS.md's factual claims about paths, in both directions. # -# Both pre-existing AGENTS.md files in this org had rotted into fiction. One -# named a CI job that had been deleted and a package.json path that does not -# exist; the other described a landing page removed months earlier. Nothing -# checked them, so nothing noticed. +# Every AGENTS.md in this org had rotted into fiction. One named a CI job that +# had been deleted and a package.json path that does not exist; another +# described a landing page removed months earlier. Nothing checked them, so +# nothing noticed. +# +# A path in backticks must exist - unless the sentence says it does not, in +# which case it must NOT exist. That second direction matters: these docs +# deliberately name dead paths so nobody mistakes them for live code, and if +# someone later creates one the doc has quietly become wrong again. # # Only repo-relative, extension-bearing paths in backticks are checked. Prose is -# not validated, and this is a lint rather than a proof. +# not validated; this is a lint, not a proof. set -uo pipefail @@ -15,21 +20,45 @@ ROOT="$(cd "$(dirname "${BASH_SOURCE[0]}")/.." && pwd)" DOC="$ROOT/AGENTS.md" [[ -f "$DOC" ]] || { echo "no AGENTS.md here"; exit 0; } -missing=0 -while read -r p; do - [[ "$p" == */* ]] || continue # must look like a path - [[ "$p" == *.* ]] || continue # and carry an extension +# A line asserting absence. Kept deliberately narrow so an ordinary sentence +# that happens to contain "no" does not silence a real check. +# Only true absence flips the check. "is dead", "retired" and "never built" +# describe something that exists and does not work, which is a different claim. +NEGATED='does not exist|do not exist|no longer exists|no longer exist|was removed|were removed|has no root' + +interesting() { + local p="$1" + [[ "$p" == */* ]] || return 1 # must look like a path + [[ "$p" == *.* ]] || return 1 # and carry an extension case "$p" in - http*|*ghcr.io*|*github.com*|oci://*|*.tum.de*) continue ;; + http*|*ghcr.io*|*github.com*|oci://*|*.tum.de*|*.io/*|*@*) return 1 ;; esac + return 0 +} + +missing=0; resurrected=0; checked=0 +while IFS= read -r p; do + interesting "$p" || continue + checked=$((checked + 1)) + + # Every line mentioning this path; if any asserts absence, treat it as a + # deliberate reference to something dead. + if grep -nF -- "\`$p\`" "$DOC" | grep -qiE "$NEGATED"; then + if [[ -e "$ROOT/$p" ]]; then + echo " now EXISTS but AGENTS.md says it does not: $p" + resurrected=1 + fi + continue + fi + if [[ ! -e "$ROOT/$p" ]]; then echo " missing: $p" missing=1 fi done < <(grep -oE '`[A-Za-z0-9_./-]+`' "$DOC" | tr -d '`' | sort -u) -if [[ $missing -ne 0 ]]; then - echo "AGENTS.md references paths that do not exist. Fix the doc or the path." +if [[ $missing -ne 0 || $resurrected -ne 0 ]]; then + echo "AGENTS.md disagrees with the repository. Fix the doc or the path." exit 1 fi -echo "AGENTS.md: every referenced path exists" +echo "AGENTS.md: $checked referenced paths all check out" From a3ec9d44f8197440d64f9662b4416451cb07407e Mon Sep 17 00:00:00 2001 From: Matthias Linhuber Date: Thu, 27 Aug 2026 13:44:09 +0200 Subject: [PATCH 3/3] fix: address review on the AGENTS.md guard, and mask the second random secret Two review findings on check-agents-md.sh, both real. A `../` reference resolved against whatever sits beside the checkout, so it passed locally and failed in CI - or the reverse. That is not hypothetical: an earlier draft of the landing page's AGENTS.md named a chart template in a sibling repository and only CI disagreed. Such paths are rejected with an explanation rather than silently evaluated. Absence was decided per PATH rather than per REFERENCE, so a doc that said a file was gone in one sentence and told you to edit it in another passed. Every reference is now judged in its own sentence. Confirmed against all four cases: a live path, an absent-and-declared-absent path, a resurrected one, and a doc that contradicts itself. Separately, the render-diff bot's own output on this PR showed a secret churning between base and head. prometheusPassword is a second randAlphaNum in the same subchart as redis-password and was never masked, so every render diff carried a spurious secret change - which is how a diff stops being read. Masking it is the small fix. The real one is that render-envs.sh now renders each environment twice and fails if the two differ, so the next lookup or random value is caught by the check rather than by someone noticing noise. Verified by removing the new mask and watching it fail. --- scripts/check-agents-md.sh | 65 ++++++++++++++++++++++---------------- scripts/render-envs.sh | 21 ++++++++++++ 2 files changed, 59 insertions(+), 27 deletions(-) diff --git a/scripts/check-agents-md.sh b/scripts/check-agents-md.sh index 7054e5f..734b84b 100755 --- a/scripts/check-agents-md.sh +++ b/scripts/check-agents-md.sh @@ -6,10 +6,14 @@ # described a landing page removed months earlier. Nothing checked them, so # nothing noticed. # -# A path in backticks must exist - unless the sentence says it does not, in -# which case it must NOT exist. That second direction matters: these docs -# deliberately name dead paths so nobody mistakes them for live code, and if -# someone later creates one the doc has quietly become wrong again. +# A path in backticks must exist - unless the sentence containing it says it +# does not, in which case it must NOT exist. That second direction matters: +# these docs deliberately name dead paths so nobody mistakes them for live code, +# and if someone later creates one the doc has quietly become wrong again. +# +# Checking is per REFERENCE, not per path: a doc that says a file is gone in one +# sentence and tells you to edit it in another is wrong, and evaluating the path +# once would let the negated sentence excuse the live one. # # Only repo-relative, extension-bearing paths in backticks are checked. Prose is # not validated; this is a lint, not a proof. @@ -20,9 +24,7 @@ ROOT="$(cd "$(dirname "${BASH_SOURCE[0]}")/.." && pwd)" DOC="$ROOT/AGENTS.md" [[ -f "$DOC" ]] || { echo "no AGENTS.md here"; exit 0; } -# A line asserting absence. Kept deliberately narrow so an ordinary sentence -# that happens to contain "no" does not silence a real check. -# Only true absence flips the check. "is dead", "retired" and "never built" +# A sentence asserting absence. Deliberately narrow: "is dead" and "retired" # describe something that exists and does not work, which is a different claim. NEGATED='does not exist|do not exist|no longer exists|no longer exist|was removed|were removed|has no root' @@ -36,29 +38,38 @@ interesting() { return 0 } -missing=0; resurrected=0; checked=0 -while IFS= read -r p; do - interesting "$p" || continue - checked=$((checked + 1)) +failed=0; checked=0 +# One line at a time, so each reference is judged in its own sentence. +while IFS=: read -r lineno line; do + while IFS= read -r p; do + interesting "$p" || continue - # Every line mentioning this path; if any asserts absence, treat it as a - # deliberate reference to something dead. - if grep -nF -- "\`$p\`" "$DOC" | grep -qiE "$NEGATED"; then - if [[ -e "$ROOT/$p" ]]; then - echo " now EXISTS but AGENTS.md says it does not: $p" - resurrected=1 - fi - continue - fi + # A parent-directory reference resolves against whatever happens to sit + # beside the checkout, so it passes locally and fails in CI - or worse, the + # reverse. Cross-repo paths belong in prose, not in backticks. + case "$p" in + ../*|*/../*) + echo " line $lineno: leaves the repository: $p" + echo " cross-repo paths cannot be checked; name the file without a path" + failed=1 + continue ;; + esac - if [[ ! -e "$ROOT/$p" ]]; then - echo " missing: $p" - missing=1 - fi -done < <(grep -oE '`[A-Za-z0-9_./-]+`' "$DOC" | tr -d '`' | sort -u) + checked=$((checked + 1)) + if grep -qiE "$NEGATED" <<<"$line"; then + if [[ -e "$ROOT/$p" ]]; then + echo " line $lineno: says this does not exist, but it does: $p" + failed=1 + fi + elif [[ ! -e "$ROOT/$p" ]]; then + echo " line $lineno: missing: $p" + failed=1 + fi + done < <(grep -oE '`[A-Za-z0-9_./-]+`' <<<"$line" | tr -d '`') +done < <(grep -n '`' "$DOC") -if [[ $missing -ne 0 || $resurrected -ne 0 ]]; then +if [[ $failed -ne 0 ]]; then echo "AGENTS.md disagrees with the repository. Fix the doc or the path." exit 1 fi -echo "AGENTS.md: $checked referenced paths all check out" +echo "AGENTS.md: $checked path references all check out" diff --git a/scripts/render-envs.sh b/scripts/render-envs.sh index bcc509f..0c4b1c7 100755 --- a/scripts/render-envs.sh +++ b/scripts/render-envs.sh @@ -102,10 +102,29 @@ mkdir -p "$OUT" mask() { sed -E \ -e 's/^([[:space:]]*redis-password:).*/\1 /' \ + -e 's/^([[:space:]]*prometheusPassword:).*/\1 /' \ -e 's/^([[:space:]]*minInstances:).*/\1 /' \ -e 's/^([[:space:]]*maxInstances:).*/\1 /' } +# Rendering the same input twice must produce the same output. This is what +# actually keeps the mask list honest: prometheusPassword was a second +# randAlphaNum in the same subchart as redis-password, was never masked, and put +# a spurious secret change in every single render diff - which is how a diff +# stops being read. +assert_deterministic() { + local chart="$1" name="$2"; shift 2 + local a b + a="$(helm template determinism-check "$chart" "$@" 2>/dev/null | mask)" + b="$(helm template determinism-check "$chart" "$@" 2>/dev/null | mask)" + if [[ "$a" != "$b" ]]; then + echo "RENDER IS NONDETERMINISTIC for ${name}:" >&2 + diff <(printf '%s' "$a") <(printf '%s' "$b") | grep '^[<>]' | head -6 | sed 's/^/ /' >&2 + echo " A template gained a lookup or a random value. Add it to mask() above." >&2 + return 1 + fi +} + rendered=0 for dir in "$DEPLOY"/$LAYOUT/*/; do env_name="$(basename "$dir")" @@ -130,6 +149,8 @@ for dir in "$DEPLOY"/$LAYOUT/*/; do ns="$(yq -r '.hosts.configuration.landing // "default"' "$values")" fi + assert_deterministic "$CHARTS_DIR/$TENANT_CHART" "$env_name" "${extra[@]}" -f "$values" --namespace "$ns" || exit 1 + if ! helm template theia-cloud "$CHARTS_DIR/$TENANT_CHART" \ "${extra[@]}" -f "$values" --namespace "$ns" 2> "$OUT/$env_name.err" | mask > "$OUT/$env_name.yaml"; then echo "RENDER FAILED for $env_name:" >&2