Add CI (build+test) and tools/check.sh #101

Merged
claude merged 1 commits from feat/ci-and-checks into main 2026-06-23 09:48:32 -04:00
3 changed files with 111 additions and 0 deletions
+25
View File
@@ -0,0 +1,25 @@
# PR + push CI for the course. Reports a commit status the claude-deck autopilot
# review gate reads, and runs the same build/test the gate runs on the merged tree:
# build = render the wiki from this tree (proves the generator works)
# test = tools/check.sh (lab compile + parse + no-slop guard + structure)
name: CI
on:
pull_request: {}
push:
branches: [main]
workflow_dispatch: {}
jobs:
check:
runs-on: docker
steps:
- uses: actions/checkout@v4
- name: build (render wiki) + test (check.sh)
shell: bash
run: |
set -euo pipefail
command -v python3 >/dev/null || { apt-get update && apt-get install -y --no-install-recommends python3 python3-pip; }
python3 -c "import yaml" 2>/dev/null || python3 -m pip install --quiet pyyaml 2>/dev/null || true
python3 tools/build_wiki.py --repo-root . --out /tmp/awc-wiki-build \
--web-base https://git.jpaul.io/justin/ai-workflow-course --branch main --host gitea
bash tools/check.sh
+25
View File
@@ -0,0 +1,25 @@
# PR + push CI for the GitHub mirror. Mirrors .gitea/workflows/ci.yml:
# build = render the wiki from this tree; test = tools/check.sh.
name: CI
on:
pull_request: {}
push:
branches: [main]
workflow_dispatch: {}
jobs:
check:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: actions/setup-python@v5
with:
python-version: '3.x'
- name: build (render wiki) + test (check.sh)
shell: bash
run: |
set -euo pipefail
python3 -m pip install --quiet pyyaml || true
python3 tools/build_wiki.py --repo-root . --out /tmp/awc-wiki-build \
--web-base https://github.com/justin/ai-workflow-course --branch main --host github
bash tools/check.sh
Executable
+61
View File
@@ -0,0 +1,61 @@
#!/usr/bin/env bash
# Test suite for ai-workflow-course. Exits non-zero on any failure.
#
# Used two ways:
# 1. CI (.gitea/workflows/ci.yml, .github/workflows/ci.yml) on every PR + push.
# 2. The claude-deck autopilot review gate's `test` command (runs on the
# merged-throwaway tree before an auto-merge).
#
# Dependency-light: python3 + grep + bash. The YAML check is skipped (not failed)
# if PyYAML is unavailable, so the suite still runs on a bare runner.
set -uo pipefail
cd "$(dirname "$0")/.." || exit 2
fail=0
note() { printf '%s\n' "$*"; }
# 1) Lab Python compiles (skip the intentional paste-in fragment in Module 12).
while IFS= read -r f; do
python3 -m py_compile "$f" 2>/dev/null || { note "FAIL py-compile: $f"; fail=1; }
done < <(find modules capstone -name '*.py' ! -name 'bad-clear-snippet.py')
# 2) Shell scripts parse.
while IFS= read -r f; do
bash -n "$f" 2>/dev/null || { note "FAIL sh-parse: $f"; fail=1; }
done < <(find modules capstone tools -name '*.sh')
# 3) JSON parses.
while IFS= read -r f; do
python3 -c "import json,sys; json.load(open(sys.argv[1]))" "$f" 2>/dev/null || { note "FAIL json: $f"; fail=1; }
done < <(find modules capstone -name '*.json')
# 4) YAML parses (only if PyYAML is present; otherwise skipped, not failed).
if python3 -c "import yaml" 2>/dev/null; then
while IFS= read -r f; do
python3 -c "import yaml,sys; list(yaml.safe_load_all(open(sys.argv[1])))" "$f" 2>/dev/null || { note "FAIL yaml: $f"; fail=1; }
done < <(find modules capstone .gitea .github -name '*.yml' -o -name '*.yaml' 2>/dev/null)
else
note "skip yaml (PyYAML not installed)"
fi
# 5) No-slop guard: no em-dash in prose. The character is built from its codepoint
# so this script holds no literal em-dash. Binaries and __pycache__ are skipped;
# the only allowed em-dash is the regex character class in tools/build_wiki.py.
emd=$(printf '\u2014')
emdash=$(grep -rlI --exclude-dir=__pycache__ --exclude='*.pyc' "$emd" \
README.md AGENTS.md _TEMPLATE.md handoff.md the-workflow-syllabus.md \
modules capstone blog tools 2>/dev/null | grep -v 'tools/build_wiki.py' || true)
if [ -n "$emdash" ]; then
note "FAIL em-dash present in:"; printf ' %s\n' $emdash; fail=1
fi
# 6) Structure: every module + capstone README has the core template sections.
for d in modules/*/ capstone/; do
f="${d}README.md"
[ -f "$f" ] || { note "FAIL missing README: $d"; fail=1; continue; }
for h in "## Prerequisites" "## Hands-on lab" "## Where it breaks"; do
grep -qF "$h" "$f" || { note "FAIL missing section '$h': $f"; fail=1; }
done
done
if [ "$fail" = 0 ]; then note "check.sh: PASS"; else note "check.sh: FAIL"; fi
exit "$fail"