Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
9 changes: 8 additions & 1 deletion .github/workflows/render-and-publish.yml
Original file line number Diff line number Diff line change
@@ -1,4 +1,7 @@
on:
pull_request:
branches:
- main
push:
branches:
- main
Expand Down Expand Up @@ -49,8 +52,11 @@ jobs:
key: cljdeps-${{ hashFiles('deps.edn') }}
restore-keys: cljdeps-

- name: Test strict Clay failure detection
run: scripts/test-render-clay-strict.sh

- name: Build the content notebooks
run: clojure -M:clay -A:markdown
run: scripts/render-clay-strict.sh

- name: Install lsof and apt prerequisites for Janqua
run: sudo apt-get update && sudo apt-get install -y lsof gnupg lsb-release
Expand Down Expand Up @@ -91,6 +97,7 @@ jobs:
path: site/_site

deploy:
if: github.event_name == 'push' && github.ref == 'refs/heads/main'
needs: build
permissions:
pages: write
Expand Down
7 changes: 7 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -310,6 +310,13 @@ Goal: Minimize friction in authoring while ensuring publishable reproducibility.

The site is built and deployed using GitHub Actions with two workflows:

Before opening a pull request, run `scripts/pre-publish-gate.sh` from the
repository root. The same strict Clay renderer is used locally and in the full
GitHub Pages workflow. It requires Java 21, uses the runner's 1 MiB JVM thread
stack, fails when any source prints `Clay FAILED:`, then renders the full site
with Quarto. `scripts/test-render-clay-strict.sh` reproduces the historical
stack-overflow signal and checks that CI rejects it with an error annotation.

- **Full Build and Publish**: Triggered on pushes to `main`.
Rebuilds all notebooks with Clay, renders the entire site with Quarto, and deploys to GitHub Pages.
See [.github/workflows/render-and-publish.yml](.github/workflows/render-and-publish.yml).
Expand Down
9 changes: 9 additions & 0 deletions scripts/pre-publish-gate.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
#!/usr/bin/env bash

set -euo pipefail

repo_root="$(cd "$(dirname "${BASH_SOURCE[0]}")/.." && pwd)"
cd "$repo_root"

scripts/render-clay-strict.sh
quarto render site
41 changes: 41 additions & 0 deletions scripts/render-clay-strict.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
#!/usr/bin/env bash

set -euo pipefail

repo_root="$(cd "$(dirname "${BASH_SOURCE[0]}")/.." && pwd)"
cd "$repo_root"

java_version="$({ java -XshowSettings:properties -version; } 2>&1 \
| awk -F= '/java.specification.version/ {gsub(/[[:space:]]/, "", $2); print $2; exit}')"
if [[ "$java_version" != "21" ]]; then
echo "Expected Java 21 to match GitHub Pages, found Java ${java_version:-unknown}." >&2
exit 1
fi

# GitHub's Ubuntu runner uses a 1 MiB JVM thread stack. macOS commonly uses
# 2 MiB, which can hide recursive parser/regex failures until publication.
export JAVA_TOOL_OPTIONS="${JAVA_TOOL_OPTIONS:+${JAVA_TOOL_OPTIONS} }-Xss1m"

log_file="$(mktemp "${TMPDIR:-/tmp}/clay-render.XXXXXX.log")"
trap 'rm -f "$log_file"' EXIT

set +e
clojure -M:clay -A:markdown "$@" 2>&1 | tee "$log_file"
clay_status="${PIPESTATUS[0]}"
set -e

if [[ "$clay_status" -ne 0 ]]; then
exit "$clay_status"
fi

# Clay reports individual source failures but can still return success.
if grep -q 'Clay FAILED:' "$log_file"; then
echo "Clay reported source failures despite exiting successfully:" >&2
grep 'Clay FAILED:' "$log_file" >&2
if [[ "${GITHUB_ACTIONS:-}" == "true" ]]; then
while IFS= read -r failure; do
echo "::error title=Clay source render failed::${failure}" >&2
done < <(grep 'Clay FAILED:' "$log_file")
fi
exit 1
fi
40 changes: 40 additions & 0 deletions scripts/test-render-clay-strict.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
#!/usr/bin/env bash

set -euo pipefail

repo_root="$(cd "$(dirname "${BASH_SOURCE[0]}")/.." && pwd)"
fixture_bin="$(mktemp -d "${TMPDIR:-/tmp}/clay-strict-fixture.XXXXXX")"
output_file="$(mktemp "${TMPDIR:-/tmp}/clay-strict-output.XXXXXX.log")"
trap 'rm -rf "$fixture_bin"; rm -f "$output_file"' EXIT

cat >"$fixture_bin/java" <<'EOF'
#!/usr/bin/env bash
echo ' java.specification.version = 21' >&2
EOF

cat >"$fixture_bin/clojure" <<'EOF'
#!/usr/bin/env bash
echo 'Clay FAILED: src/language_learning/vocabulary_estimation/beta_binomial_first_pass.clj'
echo 'java.lang.StackOverflowError'
exit 0
EOF

chmod +x "$fixture_bin/java" "$fixture_bin/clojure"

set +e
GITHUB_ACTIONS=true PATH="$fixture_bin:$PATH" \
"$repo_root/scripts/render-clay-strict.sh" >"$output_file" 2>&1
result_status=$?
set -e

if [[ "$result_status" -ne 1 ]]; then
sed -n '1,120p' "$output_file" >&2
echo "Expected the strict Clay renderer to reject the historical failure; got status $result_status." >&2
exit 1
fi

grep -Fq 'java.lang.StackOverflowError' "$output_file"
grep -Fq 'Clay reported source failures despite exiting successfully:' "$output_file"
grep -Fq '::error title=Clay source render failed::Clay FAILED: src/language_learning/vocabulary_estimation/beta_binomial_first_pass.clj' "$output_file"

echo 'Strict Clay regression passed: the historical stack-overflow signal was rejected with a GitHub error annotation.'
Loading