aboutsummaryrefslogtreecommitdiff
path: root/Makefile
diff options
context:
space:
mode:
authorCraig Jennings <c@cjennings.net>2026-05-24 13:44:34 -0500
committerCraig Jennings <c@cjennings.net>2026-05-24 13:44:34 -0500
commitb081d62276378b3168c92c06153fd59db0589535 (patch)
tree9be7f7d22e0c9b4a73432fe744c09bb456c671a9 /Makefile
downloadpearl-b081d62276378b3168c92c06153fd59db0589535.tar.gz
pearl-b081d62276378b3168c92c06153fd59db0589535.zip
feat: pearl — manage Linear issues from org-mode
Pearl fetches Linear issues into an org file and syncs edits back. It covers list / custom views / saved queries, per-issue and bulk rendering with comments inline, conflict-aware sync of descriptions, titles, and comments, field commands for priority / state / assignee / labels, and a transient dispatch menu. The render folds to a scannable outline and nests issues under a sortable parent. Based on and inspired by Gael Blanchemain's linear-emacs.
Diffstat (limited to 'Makefile')
-rw-r--r--Makefile156
1 files changed, 156 insertions, 0 deletions
diff --git a/Makefile b/Makefile
new file mode 100644
index 0000000..621cf95
--- /dev/null
+++ b/Makefile
@@ -0,0 +1,156 @@
+# Makefile for pearl.el
+# Test targets delegate to tests/Makefile.
+# setup / compile / coverage operate at project root.
+# Run 'make help' for available commands.
+
+EASK ?= eask
+EMACS_BATCH = $(EASK) emacs --batch
+# Coverage / test loops need default-directory = tests/ so test files'
+# relative paths (../pearl.el, sibling test files) resolve as they do
+# under tests/Makefile.
+EMACS_BATCH_TESTS = $(EASK) emacs --batch --eval '(cd "tests/")'
+
+TEST_DIR = tests
+SOURCE_FILE = pearl.el
+
+# Coverage configuration
+COVERAGE_DIR = .coverage
+COVERAGE_FILE = $(COVERAGE_DIR)/simplecov.json
+
+# Test-file list used by the coverage loop, mirroring tests/Makefile.
+# Coverage runs every test file so the report represents the full suite.
+ALL_TESTS = $(filter-out $(TEST_DIR)/test-bootstrap.el, \
+ $(wildcard $(TEST_DIR)/test-*.el))
+
+# Include local overrides if present (per-machine knobs, not committed)
+-include makefile-local
+
+.PHONY: help test test-all test-unit test-integration test-file test-one test-name \
+ count list validate lint check-deps clean \
+ setup compile coverage coverage-clean
+
+help:
+ @$(MAKE) -C $(TEST_DIR) help
+
+# Test target delegations
+test:
+ @$(MAKE) -C $(TEST_DIR) test
+
+test-all:
+ @$(MAKE) -C $(TEST_DIR) test-all
+
+test-unit:
+ @$(MAKE) -C $(TEST_DIR) test-unit
+
+test-integration:
+ @$(MAKE) -C $(TEST_DIR) test-integration
+
+test-file:
+ @$(MAKE) -C $(TEST_DIR) test-file FILE="$(FILE)"
+
+test-one:
+ @$(MAKE) -C $(TEST_DIR) test-one TEST="$(TEST)"
+
+test-name:
+ @$(MAKE) -C $(TEST_DIR) test-name TEST="$(TEST)"
+
+count:
+ @$(MAKE) -C $(TEST_DIR) count
+
+list:
+ @$(MAKE) -C $(TEST_DIR) list
+
+validate:
+ @$(MAKE) -C $(TEST_DIR) validate
+
+lint:
+ @$(MAKE) -C $(TEST_DIR) lint
+
+check-deps:
+ @$(MAKE) -C $(TEST_DIR) check-deps
+
+clean:
+ @$(MAKE) -C $(TEST_DIR) clean
+ @rm -rf $(COVERAGE_DIR)
+
+#
+# Project-root targets — operate on pearl.el at root level
+#
+
+# Install runtime + development dependencies via eask
+setup:
+ @if ! command -v $(EASK) >/dev/null 2>&1; then \
+ echo "[✗] eask not found on PATH"; \
+ echo " Install: npm install -g @emacs-eask/cli"; \
+ echo " Or: https://emacs-eask.github.io/Getting-Started/Install-Eask/"; \
+ exit 1; \
+ fi
+ @echo "[i] Installing dependencies via eask..."
+ @$(EASK) install-deps --dev
+ @echo "[i] Verifying runtime deps landed in the sandbox..."
+ @# eask skips a dep when an identical version sits in its GLOBAL store
+ @# (~/.eask/<ver>/elpa/), but `eask emacs' only activates the project
+ @# sandbox — so a globally-present dep is "installed" yet unloadable here.
+ @# Install any such skipped runtime dep straight into the sandbox.
+ @$(EASK) emacs --batch --eval "(progn \
+ (package-initialize) \
+ (dolist (pkg '(request dash s)) \
+ (unless (package-installed-p pkg) \
+ (message \" installing %s into sandbox...\" pkg) \
+ (unless package-archive-contents (package-refresh-contents)) \
+ (package-install pkg))))"
+ @echo "[✓] Dependencies installed in .eask/"
+
+# Byte-compile pearl.el — surfaces free-variable / unused-let /
+# suspicious-call warnings that checkdoc and elisp-lint don't catch.
+# byte-compile-error-on-warn is t so any warning fails the build.
+compile:
+ @echo "[i] Byte-compiling $(SOURCE_FILE)..."
+ @$(EMACS_BATCH) \
+ --eval "(progn \
+ (setq byte-compile-error-on-warn t) \
+ (batch-byte-compile))" $(SOURCE_FILE)
+ @echo "[✓] Compilation complete"
+
+#
+# Coverage (undercover + simplecov JSON)
+#
+# Each test file runs in its own Emacs process (matching test-unit);
+# tests/run-coverage-file.el instruments pearl.el before the source
+# is loaded, and undercover merges per-file results into a single simplecov
+# JSON.
+
+coverage: coverage-clean $(COVERAGE_DIR)
+ @echo "[i] Cleaning .elc files so undercover can instrument source..."
+ @find . -name "*.elc" -delete
+ @echo "[i] Running coverage across $(words $(ALL_TESTS)) test file(s)..."
+ @echo " (slower than 'make test' — each file runs in its own Emacs)"
+ @failed=0; \
+ for test in $(ALL_TESTS); do \
+ echo " Coverage: $$test..."; \
+ testfile=$$(basename $$test); \
+ $(EMACS_BATCH_TESTS) \
+ -l ert \
+ -l run-coverage-file.el \
+ -l ../$(SOURCE_FILE) \
+ -l $$testfile \
+ --eval "(ert-run-tests-batch-and-exit t)" || failed=$$((failed + 1)); \
+ done; \
+ if [ $$failed -gt 0 ]; then \
+ echo "[!] $$failed test file(s) failed during coverage run"; \
+ exit 1; \
+ fi
+ @coverage_file="$${COVERAGE_FILE_ACTUAL:-$(COVERAGE_FILE)}"; \
+ [ -n "$$CI" ] && coverage_file="$(COVERAGE_DIR)/coveralls.json"; \
+ if [ -f "$$coverage_file" ]; then \
+ echo "[✓] Coverage report: $$coverage_file ($$(du -h $$coverage_file | cut -f1))"; \
+ else \
+ echo "[!] No coverage file produced; check that undercover is installed"; \
+ exit 1; \
+ fi
+
+coverage-clean:
+ @rm -f $(COVERAGE_FILE)
+
+$(COVERAGE_DIR):
+ @mkdir -p $(COVERAGE_DIR)