name: Tests on: push: tags: - 'v*' workflow_dispatch: jobs: test: runs-on: ubuntu-latest env: FORCE_JAVASCRIPT_ACTIONS_TO_NODE24: true steps: - uses: actions/checkout@v4 - name: Install system dependencies run: | sudo apt-get update && sudo apt-get install -y --no-install-recommends \ sbcl emacs-nox git curl socat rlwrap - name: Install Quicklisp run: | curl -fsSL https://beta.quicklisp.org/quicklisp.lisp -o /tmp/quicklisp.lisp sbcl --noinform --non-interactive \ --load /tmp/quicklisp.lisp \ --eval '(quicklisp-quickstart:install)' rm -f /tmp/quicklisp.lisp sbcl --noinform --non-interactive \ --eval '(load (merge-pathnames "quicklisp/setup.lisp" (user-homedir-pathname)))' \ --eval '(ql:quickload :fiveam :silent t)' \ --eval '(quit)' - name: Load and verify system run: | export PASSEPARTOUT_DATA_DIR="$PWD/.github-test" mkdir -p "$PASSEPARTOUT_DATA_DIR/org" "$PASSEPARTOUT_DATA_DIR/lisp" "$PASSEPARTOUT_DATA_DIR/test" # Tangle org files into lisp/ cp org/*.org "$PASSEPARTOUT_DATA_DIR/org/" cd "$PASSEPARTOUT_DATA_DIR/org" && for f in *.org; do if command -v emacs; then emacs -Q --batch --eval "(require 'org)" \ --eval "(setq org-confirm-babel-evaluate nil)" \ --eval "(org-babel-tangle-file \"$f\")" 2>/dev/null || true fi done rm -f *.org cd "$OLDPWD" # Move test files to test/ find "$PASSEPARTOUT_DATA_DIR/lisp" -name "*-tests.lisp" -exec mv {} "$PASSEPARTOUT_DATA_DIR/test/" \; 2>/dev/null || true - name: Load passepartout and initialize skills run: | export PASSEPARTOUT_DATA_DIR="$PWD/.github-test" sbcl --non-interactive \ --eval '(load (merge-pathnames "quicklisp/setup.lisp" (user-homedir-pathname)))' \ --eval "(push (truename \"$PWD/\") asdf:*central-registry*)" \ --eval "(push (truename \"$PASSEPARTOUT_DATA_DIR/\") asdf:*central-registry*)" \ --eval '(ql:quickload :passepartout :silent t)' \ --eval "(setf (uiop:getenv \"PASSEPARTOUT_DATA_DIR\") \"$PASSEPARTOUT_DATA_DIR\")" \ --eval '(passepartout:skill-initialize-all)' \ --eval "(let ((n (hash-table-count passepartout:*skill-registry*))) (format t \"~%Skills loaded: ~a~%\" n) (unless (>= n 10) (sb-ext:exit :code 1)))" - name: Daemon smoke test run: | export PASSEPARTOUT_DATA_DIR="$PWD/.github-test" sbcl --non-interactive \ --eval '(load (merge-pathnames "quicklisp/setup.lisp" (user-homedir-pathname)))' \ --eval "(push (truename \"$PWD/\") asdf:*central-registry*)" \ --eval "(push (truename \"$PASSEPARTOUT_DATA_DIR/\") asdf:*central-registry*)" \ --eval '(ql:quickload :passepartout :silent t)' \ --eval "(setf (uiop:getenv \"PASSEPARTOUT_DATA_DIR\") \"$PASSEPARTOUT_DATA_DIR\")" \ --eval '(passepartout:main)' \ > /tmp/passepartout-daemon.log 2>&1 & DAEMON_PID=$! for i in $(seq 1 20); do if ss -tln 2>/dev/null | grep -q 9105; then echo "✓ Daemon ready on port 9105" timeout 3 bash -c 'exec 3<>/dev/tcp/localhost/9105; head -c 200 <&3' 2>/dev/null | grep -q "handshake" && \ echo "✓ Protocol handshake received" break fi sleep 1 done kill $DAEMON_PID 2>/dev/null || true wait $DAEMON_PID 2>/dev/null || true echo "✓ Daemon smoke test passed"