-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathMakefile
More file actions
227 lines (173 loc) · 9.93 KB
/
Copy pathMakefile
File metadata and controls
227 lines (173 loc) · 9.93 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
.PHONY: setup init_local_env ensure_frontend_deps reinstall reinstall_frontend update_env run_api run_frontend dashboard dashboard_raw dashboard_codex run_dashboard stop_dashboard status run_demo run_observer clear_local_env update_and_run test coverage pyright pylint ruff ruff_format pyright_all pylint_all ruff_all typecheck lint validate check_fast check test_all check_explicit_any android_bootstrap_sdk android_apk android_staging_apk android_release_apk android_verify_debug_apk android_verify_staging_apk android_verify_release_apk android_install_smoke_debug android_install_smoke_staging build_windows_installer build_macos_pkg build_macos_app build_macos_dmg docker_build docker_up docker_down docker_logs docker_pull docker_watch
FRONTEND_DIR := frontend
FRONTEND_NEXT := $(FRONTEND_DIR)/node_modules/.bin/next
PY_SOURCE_SCRIPTS := scripts/build_windows.py scripts/check_explicit_any.py scripts/check_llm_activity_prompt.py scripts/check_versions.py scripts/clear_local_env.py scripts/create_task_tree.py scripts/get_version.py scripts/resolve_llm_backend.py scripts/status.py
PY_SOURCE_PATHS := todoist $(PY_SOURCE_SCRIPTS)
PY_CHECK_PATHS := todoist tests $(PY_SOURCE_SCRIPTS)
CHECK_FAST_TARGETS := check_explicit_any ruff
CHECK_TARGETS := check_explicit_any pyright pylint ruff
TEST_ALL_TARGETS := check_explicit_any pyright_all pylint_all ruff_all test
DASHBOARD_STATE_DIR := .cache/todoist-assistant/dashboard
DASHBOARD_PID_DIR := $(DASHBOARD_STATE_DIR)/pids
BACKEND ?= raw
BACKEND_AI ?=
setup: init_local_env ## First-time source setup: sync Todoist data, then use make dashboard
init_local_env: # syncs history, fetches activity
HYDRA_FULL_ERROR=1 uv run python3 -m todoist.automations.init_env.automation --config-dir configs --config-name automations
update_env: # updates history, fetches activity, do templates
HYDRA_FULL_ERROR=1 uv run python3 -m todoist.automations.update_env.automation --config-dir configs --config-name automations
ensure_frontend_deps: # installs frontend deps if missing
@needs_install=0; \
if [ ! -x "$(FRONTEND_NEXT)" ]; then \
needs_install=1; \
else \
desired="$$(node -e "const pkg=require('./$(FRONTEND_DIR)/package.json'); const deps=pkg.dependencies||{}; const dev=pkg.devDependencies||{}; console.log(deps.next || dev.next || '');")"; \
installed="$$(node -e "try{const pkg=require('./$(FRONTEND_DIR)/node_modules/next/package.json'); console.log(pkg.version || '');}catch(e){console.log('');}")"; \
if [ -z \"$$desired\" ] || [ -z \"$$installed\" ] || [ \"$$desired\" != \"$$installed\" ]; then \
needs_install=1; \
fi; \
fi; \
if [ $$needs_install -eq 1 ]; then \
echo \"Frontend dependencies missing or out of date; installing...\"; \
npm --prefix $(FRONTEND_DIR) install; \
fi
reinstall_frontend: # force reinstall frontend deps (clean node_modules)
rm -rf $(FRONTEND_DIR)/node_modules
npm --prefix $(FRONTEND_DIR) install
reinstall: reinstall_frontend # convenience alias
run_api:
@uv run uvicorn todoist.web.api:app --reload --host 127.0.0.1 --port 8000
run_frontend: ensure_frontend_deps
npm --prefix $(FRONTEND_DIR) run dev -- --port 3000
dashboard: run_dashboard ## Start dashboard without AI by default; BACKEND/BACKEND_AI may override
dashboard_raw: ensure_frontend_deps ## Start dashboard with AI disabled
DASHBOARD_STATE_DIR="$(DASHBOARD_STATE_DIR)" \
DASHBOARD_PID_DIR="$(DASHBOARD_PID_DIR)" \
bash ./scripts/dashboard_stack.sh start raw
dashboard_codex: ensure_frontend_deps ## Start dashboard using the local Codex CLI backend
DASHBOARD_STATE_DIR="$(DASHBOARD_STATE_DIR)" \
DASHBOARD_PID_DIR="$(DASHBOARD_PID_DIR)" \
bash ./scripts/dashboard_stack.sh start codex
run_dashboard: ensure_frontend_deps ## Start dashboard; supports BACKEND/BACKEND_AI=raw|codex
@backend="$(BACKEND)"; \
if [ -n "$(BACKEND_AI)" ]; then backend="$(BACKEND_AI)"; fi; \
case "$$backend" in \
raw|none|disabled) stack_backend="raw" ;; \
codex) stack_backend="codex" ;; \
*) echo "Unsupported dashboard backend: $$backend (use raw or codex)"; exit 2 ;; \
esac; \
DASHBOARD_STATE_DIR="$(DASHBOARD_STATE_DIR)" \
DASHBOARD_PID_DIR="$(DASHBOARD_PID_DIR)" \
bash ./scripts/dashboard_stack.sh start "$$stack_backend"
stop_dashboard:
@DASHBOARD_STATE_DIR="$(DASHBOARD_STATE_DIR)" \
DASHBOARD_PID_DIR="$(DASHBOARD_PID_DIR)" \
bash ./scripts/dashboard_stack.sh stop
status: ## Show local dashboard/API/frontend runtime status
@PYTHONPATH=. uv run python3 -m scripts.status
run_demo: ensure_frontend_deps
@bash -c '\
set -euo pipefail; \
pids=""; api_pid=""; fe_pid=""; \
wait_for_api() { \
local tries=0; \
echo "Waiting for API to be ready..."; \
if command -v curl >/dev/null 2>&1; then \
until curl -fsS http://127.0.0.1:8000/api/health >/dev/null 2>&1; do \
tries=$$((tries+1)); \
[ $$tries -ge 60 ] && break; \
sleep 0.5; \
done; \
else \
sleep 2; \
fi; \
}; \
cleanup() { \
echo "Stopping demo dashboard servers..."; \
[ -n "$$pids" ] && kill $$pids 2>/dev/null || true; \
wait 2>/dev/null || true; \
}; \
trap cleanup INT TERM EXIT; \
TODOIST_DASHBOARD_DEMO=1 uv run uvicorn todoist.web.api:app --reload --host 127.0.0.1 --port 8000 & api_pid="$$!"; pids="$$pids $$api_pid"; \
wait_for_api; \
TODOIST_DASHBOARD_DEMO=1 npm --prefix frontend run dev -- --port 3000 & fe_pid="$$!"; pids="$$pids $$fe_pid"; \
echo "Demo dashboard running (anonymized):"; \
echo " API: http://127.0.0.1:8000"; \
echo " Frontend: http://127.0.0.1:3000"; \
wait -n $$api_pid $$fe_pid; \
'
run_observer:
@HYDRA_FULL_ERROR=1 uv run python3 -m todoist.run_observer --config-dir configs --config-name automations
clear_local_env:
@PYTHONPATH=. uv run python3 -m scripts.clear_local_env $(CLEAR_LOCAL_ENV_ARGS)
update_and_run: # updates history, fetches activity, do templates, and runs the dashboard
HYDRA_FULL_ERROR=1 uv run python3 -m todoist.automations.update_env.automation --config-dir configs --config-name automations && \
make dashboard
test: ## Run unit tests with pytest
PYTHONPATH=. HYDRA_FULL_ERROR=1 uv run python3 -m pytest -v --tb=short tests/
coverage: ## Run full pytest coverage report
PYTHONPATH=. HYDRA_FULL_ERROR=1 uv run --with coverage python -m coverage run -m pytest tests/
PYTHONPATH=. uv run --with coverage python -m coverage report
check_explicit_any: ## Reject `: Any =` variable annotations used as typecheck escape hatches
PYTHONPATH=. uv run python3 -m scripts.check_explicit_any
android_bootstrap_sdk: ## Install repo-local Android SDK/JDK prerequisites
./scripts/android_bootstrap_sdk.sh
android_apk: ## Build the Android debug APK
./scripts/android_build_apk.sh
android_staging_apk: ## Build the Android staging APK for sideload testing
ANDROID_BUILD_VARIANT=Staging ./scripts/android_build_apk.sh
android_release_apk: ## Build the Android release APK
ANDROID_BUILD_VARIANT=Release ./scripts/android_build_apk.sh
android_verify_debug_apk: ## Verify the Android debug APK is signed and launchable
ANDROID_EXPECT_DEBUGGABLE=true ./scripts/android_verify_apk.sh android/app/build/outputs/apk/debug/app-debug.apk
android_verify_staging_apk: ## Verify the Android staging APK is signed and launchable
ANDROID_EXPECT_DEBUGGABLE=false ./scripts/android_verify_apk.sh android/app/build/outputs/apk/staging/app-staging.apk
android_verify_release_apk: ## Verify the Android release APK is signed and launchable
ANDROID_EXPECT_DEBUGGABLE=false ./scripts/android_verify_apk.sh android/app/build/outputs/apk/release/app-release.apk
android_install_smoke_debug: ## Install and launch the debug APK on the connected Android device/emulator
./scripts/android_install_smoke.sh android/app/build/outputs/apk/debug/app-debug.apk
android_install_smoke_staging: ## Install and launch the staging APK on the connected Android device/emulator
./scripts/android_install_smoke.sh android/app/build/outputs/apk/staging/app-staging.apk
pyright: ## Run Pyright type checks
PYTHONPATH=. uv run pyright --warnings $(PY_SOURCE_PATHS)
pylint: ## Run pylint
PYTHONPATH=. uv run pylint -j 0 --disable=cyclic-import $(PY_SOURCE_PATHS)
ruff: ## Run Ruff lint checks
PYTHONPATH=. uv run ruff check $(PY_SOURCE_PATHS)
ruff_format: ## Check Ruff formatting
PYTHONPATH=. uv run ruff format --check $(PY_SOURCE_PATHS)
pyright_all: ## Run Pyright on source, tests, and scripts
PYTHONPATH=. uv run pyright --warnings $(PY_CHECK_PATHS)
pylint_all: ## Run pylint on source, tests, and scripts
PYTHONPATH=. uv run pylint -j 0 --disable=cyclic-import $(PY_CHECK_PATHS)
ruff_all: ## Run Ruff on source, tests, and scripts
PYTHONPATH=. uv run ruff check $(PY_CHECK_PATHS)
typecheck: check_explicit_any pyright ## Run explicit-Any and Pyright checks
lint: pylint ruff ruff_format ## Run pylint and Ruff checks
check_fast: ## Run quick source-only checks in parallel
+@$(MAKE) --no-print-directory -j$(words $(CHECK_FAST_TARGETS)) $(CHECK_FAST_TARGETS)
check: ## Run all static quality checks in parallel
+@$(MAKE) --no-print-directory -j$(words $(CHECK_TARGETS)) $(CHECK_TARGETS)
validate: check ## Alias for make check
test_all: ## Run static checks and tests in parallel
+@$(MAKE) --no-print-directory -j$(words $(TEST_ALL_TARGETS)) $(TEST_ALL_TARGETS)
build_windows_installer: ## Build Windows MSI (requires Windows + WiX + Node if dashboard is included)
uv run python3 -m scripts.build_windows
build_macos_pkg: ## Build macOS pkg installer (requires macOS + pkgbuild/productbuild)
./scripts/build_macos_pkg.sh
build_macos_app: ## Build macOS app bundle (requires macOS + PyInstaller)
./scripts/build_macos_app.sh
build_macos_dmg: ## Build macOS DMG from the app bundle
./scripts/build_macos_dmg.sh
docker_build: ## Build API + frontend Docker images
docker compose build
docker_up: ## Run API + frontend with Docker Compose
docker compose up
docker_down: ## Stop Docker Compose services
docker compose down
docker_logs: ## Tail Docker Compose logs
docker compose logs -f
docker_pull: ## Pull published Docker images
docker compose pull
docker_watch: ## Live-reload with Docker Compose watch (Compose 2.22+)
docker compose watch