name: CI on: push: branches: [main] pull_request: permissions: contents: read jobs: test: name: elisp-only (Emacs ${{ matrix.emacs-version }}) runs-on: ubuntu-latest continue-on-error: ${{ matrix.emacs-version == 'snapshot' }} strategy: fail-fast: false matrix: # 29.1 is the declared floor (Package-Requires); 30.1 is current # stable; snapshot is advisory (allowed to fail) emacs-version: ['29.1', '30.1', 'snapshot'] steps: - uses: actions/checkout@11d5960a326750d5838078e36cf38b85af677262 # v4.4.0 with: persist-credentials: false - uses: purcell/setup-emacs@bdc64dc730ae1fcba200bfd52cb1b4cf6159cbe5 # v8.0 with: version: ${{ matrix.emacs-version }} - name: Byte-compile (warnings are errors) run: | emacs -Q --batch -L . \ --eval '(setq byte-compile-error-on-warn t)' \ -f batch-byte-compile ekp.el ekp-utils.el ekp-hyphen.el ekp-region.el - name: Run ERT suite (C-module tests auto-skip) run: tests/run-tests.sh emacs - name: Run ERT suite in permuted order if: matrix.emacs-version == '30.1' env: EKP_TEST_SEED: '20260728' run: tests/run-tests.sh emacs --random-order lint: name: package-lint + checkdoc runs-on: ubuntu-latest steps: - uses: actions/checkout@11d5960a326750d5838078e36cf38b85af677262 # v4.4.0 with: persist-credentials: false - uses: purcell/setup-emacs@bdc64dc730ae1fcba200bfd52cb1b4cf6159cbe5 # v8.0 with: version: '30.1' - name: Check out pinned package-lint uses: actions/checkout@11d5960a326750d5838078e36cf38b85af677262 # v4.4.0 with: repository: purcell/package-lint ref: 35996f478d81e51dae4fa30d051f741895d07399 path: .ci/package-lint persist-credentials: false - name: package-lint run: | emacs -Q --batch -L .ci/package-lint \ --eval "(require 'package-lint)" \ --eval "(setq package-lint-main-file \"ekp.el\")" \ -f package-lint-batch-and-exit \ ekp.el ekp-utils.el ekp-hyphen.el ekp-region.el - name: checkdoc run: | emacs -Q --batch \ --eval "(setq sentence-end-double-space t)" \ --eval "(dolist (f '(\"ekp.el\" \"ekp-utils.el\" \"ekp-hyphen.el\" \"ekp-region.el\")) (checkdoc-file f))" \ 2>&1 | tee checkdoc.log test ! -s checkdoc.log - name: Release invariants run: tests/check-release.sh - name: Dictionary manifest and pinned source run: | tests/check-dictionaries.sh dictionaries/update.sh check test-c-module: name: full suite + C parity (apt Emacs) runs-on: ubuntu-latest steps: - uses: actions/checkout@11d5960a326750d5838078e36cf38b85af677262 # v4.4.0 with: persist-credentials: false - name: Install Emacs run: sudo apt-get update && sudo apt-get install -y emacs-nox - name: Ensure emacs-module.h is findable run: | if [ ! -e /usr/include/emacs-module.h ]; then HDR=$(dpkg -L emacs-common emacs-bin-common 2>/dev/null | grep -m1 '/emacs-module\.h$' || true) [ -n "$HDR" ] || HDR=$(sudo find /usr -name emacs-module.h 2>/dev/null | head -1) test -n "$HDR" || { echo 'emacs-module.h not found'; exit 1; } sudo install -m 644 "$HDR" /usr/local/include/ fi - name: Build C module run: make -C ekp_c - name: Run ERT suite (with C module) run: tests/run-tests.sh emacs - name: Property fuzz (300 cases, C vs elisp parity) run: emacs -Q --batch -L . -l tests/ekp-fuzz.el test-c-sanitizers: name: C module under ASan/UBSan runs-on: ubuntu-latest steps: - uses: actions/checkout@11d5960a326750d5838078e36cf38b85af677262 # v4.4.0 with: persist-credentials: false - name: Install Emacs run: sudo apt-get update && sudo apt-get install -y emacs-nox gcc - name: Ensure emacs-module.h is findable run: | if [ ! -e /usr/include/emacs-module.h ]; then HDR=$(dpkg -L emacs-common emacs-bin-common 2>/dev/null | grep -m1 '/emacs-module\.h$' || true) [ -n "$HDR" ] || HDR=$(sudo find /usr -name emacs-module.h 2>/dev/null | head -1) test -n "$HDR" || { echo 'emacs-module.h not found'; exit 1; } sudo install -m 644 "$HDR" /usr/local/include/ fi - name: Build C module with sanitizers run: make -C ekp_c PROFILE=sanitize - name: Property fuzz under ASan/UBSan # Emacs itself is not ASan-instrumented: preload the runtime and # skip leak checking (the Emacs process "leaks" by design). run: | LIBASAN=$(gcc -print-file-name=libasan.so) LD_PRELOAD="$LIBASAN" ASAN_OPTIONS=detect_leaks=0 \ emacs -Q --batch -L . -l tests/ekp-fuzz.el test-macos: name: macOS (dylib build + full suite) runs-on: macos-latest steps: - uses: actions/checkout@11d5960a326750d5838078e36cf38b85af677262 # v4.4.0 with: persist-credentials: false - uses: purcell/setup-emacs@bdc64dc730ae1fcba200bfd52cb1b4cf6159cbe5 # v8.0 with: version: '30.1' - name: Build C module run: make -C ekp_c - name: Run ERT suite (with C module) run: tests/run-tests.sh emacs - name: Property fuzz (300 cases, C vs elisp parity) run: emacs -Q --batch -L . -l tests/ekp-fuzz.el test-windows: name: Windows Elisp baseline (Emacs 30.1) runs-on: windows-latest steps: - uses: actions/checkout@11d5960a326750d5838078e36cf38b85af677262 # v4.4.0 with: persist-credentials: false - name: Install Emacs 30.1 shell: pwsh run: choco install emacs --version=30.1.0 --yes --no-progress - name: Byte-compile (warnings are errors) shell: pwsh run: > emacs -Q --batch -L . --eval "(setq byte-compile-error-on-warn t)" -f batch-byte-compile ekp.el ekp-utils.el ekp-hyphen.el ekp-region.el - name: Run ERT suite (C-module tests auto-skip) shell: pwsh run: > emacs -Q --batch -L . -L tests -l tests/ekp-tests.el -l tests/ekp-region-tests.el -l tests/ekp-gui-tests.el -l tests/ekp-c-tests.el -f ert-run-tests-batch-and-exit