1 lisp-ci
dxtr edited this page 2026-10-11 16:41:50 +02:00

lisp-ci

Runs the Parachute test suite of a qlot-pinned Common Lisp project on SBCL and/or Clozure CL (CCL).

- uses: fakehacker/actions/checkout@v1.0.0
- uses: fakehacker/actions/lisp-ci@v1.0.0
  with:
    system: cl-ft2
    # test-system: cl-ft2/test
    # lisps: sbcl ccl
    # packages: libfreetype6 fonts-dejavu-core
    # features: cl-net-force-usocket
    # force: "true"
    # sbcl-version: "2.6.9"
    # ccl-version: "1.13"

Inputs

Input Default Description
system (required) The project's main ASDF system, for example cl-ft2.
test-system <system>/test ASDF system that contains the Parachute suite. Its package must have the same name (see Project layout).
lisps sbcl ccl Space-separated implementations to test on. Allowed values: sbcl and ccl.
packages (empty) Extra apt packages the project needs at run time, for example the C libraries used by CFFI bindings.
features (empty) Space-separated keywords pushed onto *features* before loading. A leading : is optional.
force "false" "true" recompiles system and test-system instead of reusing fasls.
sbcl-version "2.6.9" SBCL release to install.
ccl-version "1.13" CCL release to install.

Requirements

  • An apt-based image (Debian or Ubuntu). debian:forky and debian:trixie both work.
  • An x86-64 runner. That's the only Linux architecture SBCL and CCL publish binaries for.
  • Steps run as root, because the action installs to /usr/local and /opt.
  • A qlfile (and normally a qlfile.lock) in the repository root.
  • Network access to deb.debian.org, downloads.sourceforge.net, github.com and qlot.tech.

What it does

  1. System deps: apt-installs curl ca-certificates git tar gzip, plus bzip2 when SBCL is selected, plus anything in packages. If there's no apt-get, it fails with a clear error.
  2. Install SBCL (if sbcl is in lisps): downloads sbcl-<version>-x86-64-linux-binary.tar.bz2 from the official SourceForge release and runs its install.sh with INSTALL_ROOT=/usr/local. This is skipped if sbcl --version already prints SBCL <sbcl-version>.
  3. Install CCL (if ccl is in lisps): downloads ccl-<version>-linuxx86.tar.gz from the Clozure GitHub release, unpacks it to /opt/ccl, and puts a ccl wrapper script in /usr/local/bin. This is skipped if ccl is already on PATH.
  4. Install qlot from https://qlot.tech/installer, unless qlot is already on PATH.
  5. qlot install fetches the dependencies pinned in qlfile.lock into .qlot/.
  6. Test on each selected Lisp in turn (SBCL first, then CCL), under qlot exec. Neither Lisp loads init files.

Project layout

The bundled run-tests.lisp runs this for each Lisp:

(asdf:load-system "<test-system>")
(parachute:test :<TEST-SYSTEM>)   ; the test-system name, as a keyword

So Parachute is given the package whose name matches the test system, and it runs every test in that package. A layout that works:

;; cl-ft2.asd
(defsystem "cl-ft2/test"
  :depends-on ("cl-ft2" "parachute")
  :components ((:file "test")))

;; test.lisp
(defpackage #:cl-ft2/test
  (:use #:cl #:parachute))
(in-package #:cl-ft2/test)

(define-test smoke
  (true (cl-ft2:something)))

Exit codes

Code Meaning
0 The suite passed.
1 The suite ran and at least one test failed.
2 Loading or running signalled an error. The condition and a backtrace go to stderr.

The first Lisp that fails stops the job, so if SBCL fails, CCL doesn't run.

Testing several SBCL versions

Use a job matrix, which runs each version in its own fresh container:

jobs:
  lisp:
    runs-on: ubuntu-latest
    strategy:
      fail-fast: false
      matrix:
        sbcl: ['2.5.0', '2.6.9']
    container:
      image: debian:forky
    steps:
      - uses: fakehacker/actions/checkout@v1.0.0
      - uses: fakehacker/actions/lisp-ci@v1.0.0
        with:
          system: cl-ft2
          lisps: sbcl
          sbcl-version: ${{ matrix.sbcl }}

Version numbers must match a directory on SourceForge that contains an x86-64 Linux binary.

Testing several feature sets

Call the action once per feature set. On every call after the first, pass force: "true" so the fasls from the earlier call get rebuilt with the new features. The installs are skipped on later calls because the tools are already on PATH.

steps:
  - uses: fakehacker/actions/checkout@v1.0.0
  - uses: fakehacker/actions/lisp-ci@v1.0.0
    with:
      system: cl-net
  - uses: fakehacker/actions/lisp-ci@v1.0.0
    with:
      system: cl-net
      features: cl-net-force-usocket
      force: "true"

Native libraries

Add the C libraries your CFFI bindings load at run time through packages. Use the Debian package names:

with:
  system: cl-ft2
  packages: libfreetype6 fonts-dejavu-core