chore: progression checkpoint script

Co-Authored-By: Claude Sonnet 5.5 <[email protected]>
This commit is contained in:
Lucas Winther
2026-10-29 00:07:27 +01:00
co-authored by Claude Sonnet 5.5
parent 1e186733d1
commit 56bc6b4cf7
+77
View File
@@ -0,0 +1,77 @@
#!/usr/bin/env bash
# Usage: scripts/check-progression.sh <js|scala|fsharp>
# Progression checkpoint: for each module N (that has tests in the track), build a temp copy where src/ holds the
# reference solutions of modules <= N and the untouched student stubs for the rest, then run the tests of modules
# M01..MN. All must pass: this proves a student who has finished module N has a green suite up to N, and that
# no earlier solution secretly depends on a later one.
set -uo pipefail
track="${1:?usage: check-progression.sh <js|scala|fsharp>}"
repo="$(cd "$(dirname "$0")/.." && pwd)"
export PATH="$HOME/.dotnet:$HOME/.local/bin:$PATH"
# Module -> files (relative to src/ and solutions/) that the module introduces. A directory entry copies it whole.
# Later tasks: extend the entries for m07+ in the Scala and F# tables.
files_for() {
case "$track:$1" in
js:01) echo "util.js todo.js" ;;
js:02) echo "model.js" ;;
js:03) echo "rules.js" ;;
js:04) echo "random.js spawn.js" ;;
js:05) echo "game.js" ;;
js:06) echo "view.js" ;;
js:07) echo "io.js" ;;
js:08) echo "stream.js" ;;
js:09) echo "input.js app.js runtime.js browser.js main.js" ;;
js:10) echo "" ;; # edits game/input/app, already included by m05/m09
js:11) echo "pong" ;;
scala:01) echo "Util.scala" ;;
scala:02) echo "Model.scala" ;;
scala:03) echo "Rules.scala" ;;
scala:04) echo "Random.scala Spawn.scala" ;;
scala:05) echo "Game.scala" ;;
scala:06) echo "View.scala" ;;
scala:07) echo "IO.scala" ;;
scala:08) echo "Stream.scala" ;;
scala:09) echo "Input.scala App.scala Runtime.scala" ;;
scala:10) echo "" ;;
scala:11) echo "pong" ;;
fsharp:*) echo "" ;; # added by the F# tasks
*) echo "" ;;
esac
}
case "$track" in
js) has() { compgen -G "$repo/js/test/m$1-*.test.js" >/dev/null; } ;;
scala) has() { compgen -G "$repo/scala/test/M$1*.test.scala" >/dev/null; } ;;
fsharp) has() { compgen -G "$repo/fsharp/tests/M$1*.fs" >/dev/null; } ;;
*) echo "unknown track: $track" >&2; exit 2 ;;
esac
status=0
for n in 01 02 03 04 05 06 07 08 09 10 11; do
has "$n" || continue
tmp="$(mktemp -d)"
tar -C "$repo" --exclude=.git --exclude=node_modules --exclude=bin --exclude=obj \
--exclude=.scala-build --exclude=.bsp --exclude=.superpowers -cf - . | tar -C "$tmp" -xf -
for m in 01 02 03 04 05 06 07 08 09 10 11; do
[ "$m" -le "$n" ] || break
for f in $(files_for "$m"); do
[ -e "$tmp/$track/solutions/$f" ] || continue # module not (yet) present in this track
rm -rf "$tmp/$track/src/$f"
cp -r "$tmp/$track/solutions/$f" "$tmp/$track/src/$f"
done
done
ok=1
for m in 01 02 03 04 05 06 07 08 09 10 11; do
[ "$m" -le "$n" ] || break
has "$m" || continue
if ! out="$(cd "$tmp/$track" && ./test.sh "M$m" 2>&1)"; then
echo "checkpoint M$n: FAIL (M$m tests fail with solutions up to M$n)"
echo "$out" | tail -40
ok=0; status=1; break
fi
done
[ $ok -eq 1 ] && echo "checkpoint M$n: ok (M01..M$n pass)"
rm -rf "$tmp"
done
exit $status