# Justfile for cc-libs # Run `just ci` to verify local tooling and lint Lua code. # List available recipes. default: @just --list # Install local development tooling. install: init-env install-git-hooks check-install # Create a local environment file when one does not exist. init-env: @if [ ! -f .env ]; then \ cp .env.sample .env; \ printf '%s\n' 'Created .env from .env.sample'; \ fi # Install Git hooks for this repository. install-git-hooks: @mkdir -p .git/hooks @printf '%s\n' '#!/bin/sh' '' 'just ci' > .git/hooks/pre-commit @chmod +x .git/hooks/pre-commit @printf '%s\n' 'Installed .git/hooks/pre-commit' # Verify the CraftOS-PC harness is installed and recent enough. check-craftos: @command -v craftos >/dev/null 2>&1 || { \ printf '%s\n' 'craftos not found on $PATH. See docs/install-craftos-pc.md.' >&2; \ exit 1; \ } @version="$(craftos --version)"; \ number="${version##* v}"; \ case "$number" in \ *.*.*) \ ;; \ *) \ printf '%s\n' "$version"; \ printf '%s\n' 'Could not parse CraftOS-PC version. See docs/install-craftos-pc.md.' >&2; \ exit 1; \ ;; \ esac; \ major="${number%%.*}"; \ rest="${number#*.}"; \ minor="${rest%%.*}"; \ patch="${rest#*.}"; \ patch="${patch%%[^0-9]*}"; \ printf '%s\n' "$version"; \ case "$major.$minor.$patch" in \ *[!0-9.]*|.*|*..*|*.) \ printf '%s\n' 'Could not parse CraftOS-PC version. See docs/install-craftos-pc.md.' >&2; \ exit 1; \ ;; \ esac; \ if ! { [ "${major:-0}" -gt 2 ] || \ { [ "${major:-0}" -eq 2 ] && [ "${minor:-0}" -gt 8 ]; } || \ { [ "${major:-0}" -eq 2 ] && [ "${minor:-0}" -eq 8 ] && [ "${patch:-0}" -ge 3 ]; }; }; then \ printf '%s\n' 'CraftOS-PC v2.8.3 or newer is required. See docs/install-craftos-pc.md.' >&2; \ exit 1; \ fi # Verify jq is installed. check-jq: @command -v jq >/dev/null 2>&1 || { \ printf '%s\n' 'jq not found on $PATH. See DEVELOPMENT.md.' >&2; \ exit 1; \ } # Verify luacheck is installed. check-luacheck: @command -v luacheck >/dev/null 2>&1 || { \ printf '%s\n' 'luacheck not found on $PATH. See DEVELOPMENT.md.' >&2; \ exit 1; \ } # Verify tools needed for local installation and CraftOS-PC launch recipes. check-install: check-craftos check-jq check-luacheck # Pass args through to `craftos`, for example: # just craftos --headless --exec 'print("__TRAPOS_TEST_OK__"); os.shutdown()' # Launch CraftOS-PC with repo-local data and read-only repo mounts. [positional-arguments] craftos *args: check-install #!/usr/bin/env bash set -euo pipefail repo='{{justfile_directory()}}' argv=(--directory "$repo/.craftos") if [ "$(uname -s)" = "Darwin" ]; then argv+=(--rom /Applications/CraftOS-PC.app/Contents/Resources) fi argv+=(--mount-ro "/trapos=$repo") while IFS= read -r dir; do argv+=(--mount-ro "/$dir=$repo/$dir") done < <(jq -r '.files[] | split("/")[0]' "$repo/manifest.json" | sort -u) exec craftos "${argv[@]}" "$@" # Human-only interactive REPL. LLM agents must not execute this command. repl: @just craftos --cli # Local CI entry point used by Git hooks. Pass args through to `test`. ci *args: check-craftos check @just test {{args}} # Run CraftOS-PC headless smoke tests. Pass `--verbose` to list each test. test *args: @if [ -f .env ]; then set -a; . ./.env; set +a; fi; \ verbose=0; \ timeout_seconds="${TRAP_CCLIBS_TEST_TIMEOUT_SECONDS:-3}"; \ case "$timeout_seconds" in ''|*[!0-9]*) printf '%s\n' 'TRAP_CCLIBS_TEST_TIMEOUT_SECONDS must be a positive integer' >&2; exit 1 ;; esac; \ if [ "$timeout_seconds" -lt 1 ]; then printf '%s\n' 'TRAP_CCLIBS_TEST_TIMEOUT_SECONDS must be >= 1' >&2; exit 1; fi; \ for a in {{args}}; do [ "$a" = "--verbose" ] && verbose=1; done; \ script_args=""; \ if [ "$verbose" -eq 1 ]; then script_args="--verbose"; fi; \ rom_arg=""; \ if [ "$(uname -s)" = "Darwin" ]; then \ rom_arg="--rom /Applications/CraftOS-PC.app/Contents/Resources"; \ fi; \ repo='{{justfile_directory()}}'; \ mount_arg="--mount-ro /apis=$repo/apis"; \ green=$(printf '\033[32m'); reset=$(printf '\033[0m'); red=$(printf '\033[31m'); \ for script in tests/boot.lua tests/ready.lua tests/eventloop.lua; do \ tmp="$(mktemp)"; \ craftos --headless $rom_arg $mount_arg --script "$script" $script_args >"$tmp" 2>&1 & \ pid="$!"; \ ( sleep "$timeout_seconds"; kill -TERM "$pid" >/dev/null 2>&1 ) & \ watchdog="$!"; \ wait "$pid" >/dev/null 2>&1; \ status="$?"; \ kill "$watchdog" >/dev/null 2>&1 || true; \ wait "$watchdog" >/dev/null 2>&1 || true; \ if grep -q __TRAPOS_TEST_OK__ "$tmp"; then \ rm -f "$tmp"; \ [ "$verbose" -eq 1 ] && printf '%s\n' "${green}PASS${reset} $script"; \ else \ if [ "$status" -eq 143 ]; then \ printf '%s\n' "${red}FAIL${reset} $script timed out after ${timeout_seconds}s" >&2; \ else \ printf '%s\n' "${red}FAIL${reset} $script did not print __TRAPOS_TEST_OK__" >&2; \ fi; \ cat "$tmp" >&2; \ rm -f "$tmp"; \ exit 1; \ fi; \ done; \ printf '%s\n' 'OK: smoke tests passed' # Lint all Lua source with luacheck. check: check-luacheck luacheck .