# opentracker task runner. `just --list` for the menu. sdk := env("ANDROID_HOME", env("HOME") / "android-sdk") scratch := "dev" default: @just --list # --- checks ------------------------------------------------------------------ # Everything CI would run. check: test clippy fmt-check web-build android-test android-lint test: cargo test --workspace clippy: cargo clippy --workspace --all-targets -- -D warnings fmt: cargo fmt --all fmt-check: cargo fmt --all -- --check # --- protocol ---------------------------------------------------------------- # Regenerate the golden vectors that are the Rust <-> Kotlin contract. # `just test` then verifies them, and the Android suite decodes the same file. gen-vectors: cargo run -p otproto --features serde --example gen_vectors # Coverage-guided fuzzing. Needs a nightly toolchain and cargo-fuzz: # rustup toolchain install nightly && cargo install cargo-fuzz fuzz target="decode" secs="60": cd crates/otproto/fuzz && cargo +nightly fuzz run {{target}} -- -max_total_time={{secs}} -rss_limit_mb=4096 # --- server ------------------------------------------------------------------ # One-time: a server key and an admin account in ./{{scratch}}. dev-setup user="sim" password="simsimsimsim": mkdir -p {{scratch}} test -f {{scratch}}/secret.key || (head -c32 /dev/urandom | base64 > {{scratch}}/secret.key && chmod 600 {{scratch}}/secret.key) OT_SECRET_KEY={{scratch}}/secret.key OT_ADMIN_EMAIL=ops@example.net OT_DB_PATH={{scratch}}/ot.db \ cargo run -p otserver -- --create-admin {{user}} {{password}} # The server plus an in-process fake phone walking a synthetic route over real # OTP/1 on loopback. The fastest way to see the whole pipeline move. # # Serves the UI from web/dist if it has been built. For live reload, run # `just web-dev` in a second terminal and use http://localhost:5173 instead. dev: OT_SECRET_KEY={{scratch}}/secret.key OT_ADMIN_EMAIL=ops@example.net OT_DB_PATH={{scratch}}/ot.db \ OT_HTTP_ADDR=127.0.0.1:7372 OT_UDP_ADDR=127.0.0.1:7373 \ cargo run -p otserver -- --dev --simulate-device # --- web --------------------------------------------------------------------- web-install: cd web && bun install # Vite with hot reload on :5173, proxying /api to the backend on :7372. web-dev: web-install cd web && bun run dev # Type-check and bundle into web/dist, which the server embeds in release builds. web-build: web-install cd web && bun run build # --- docker ------------------------------------------------------------------ docker-build: docker build -f Containerfile -t opentracker:dev . # The whole thing in one container, with the simulated phone walking its route: # open http://127.0.0.1:7372 and sign in as {{user}}. # # 127.0.0.1, not localhost: the port is published on IPv4 only, and localhost # resolves to ::1 first on this machine. # # The key below is a literal on purpose — this is a throwaway demo database. A # real deployment passes OT_SECRET_KEY from a file or a secret store, and losing # it makes every stored token key unrecoverable. docker-demo user="sim" password="simsimsimsim": docker-build docker volume create opentracker-demo >/dev/null -docker run --rm -v opentracker-demo:/data \ -e OT_SECRET_KEY=ZGVtby1vbmx5LW5vdC1hLXJlYWwtc2VjcmV0LWtleSE= -e OT_ADMIN_EMAIL=ops@example.net \ opentracker:dev --create-admin {{user}} {{password}} docker run --rm --name opentracker-demo -p 7372:7372 -p 7373:7373/udp -v opentracker-demo:/data \ -e OT_SECRET_KEY=ZGVtby1vbmx5LW5vdC1hLXJlYWwtc2VjcmV0LWtleSE= -e OT_ADMIN_EMAIL=ops@example.net \ -e OT_SIM_USER={{user}} -e OT_SIM_PASSWORD={{password}} \ opentracker:dev --dev --simulate-device # Wipes the demo database so `just docker-demo` starts from nothing. docker-demo-reset: -docker rm -f opentracker-demo docker volume rm opentracker-demo # --- android ----------------------------------------------------------------- # JVM tests, including the golden-vector cross-check against otproto. android-test: cd android && ANDROID_HOME={{sdk}} ./gradlew :app:testDebugUnitTest android-lint: cd android && ANDROID_HOME={{sdk}} ./gradlew :app:lintDebug android-build: cd android && ANDROID_HOME={{sdk}} ./gradlew :app:assembleDebug android-install: android-build cd android && ANDROID_HOME={{sdk}} ./gradlew :app:installDebug adb shell am start -n net.lexcom.opentracker.debug/net.lexcom.opentracker.MainActivity # Only our own tags, at verbose. Everything else silenced. logcat: adb logcat -c && adb logcat OpenTracker:V AndroidRuntime:E '*:S' # The Compose compiler plugin version must equal the KGP version AGP bundles. # Run this after any AGP bump and update app/build.gradle.kts to match. android-kotlin-version: cd android && ANDROID_HOME={{sdk}} ./gradlew :app:buildEnvironment | grep -i kotlin-gradle-plugin # --- emulator ---------------------------------------------------------------- # The AVDs, oldest to newest. ot29 is minSdk and the one that finds the # API-level bugs; ot36 is targetSdk and the one that finds the policy bugs. avd := "ot36" # Create the AVD. Needs the matching system image installed first: # sdkmanager "system-images;android-36;default;x86_64" # # Create an AVD if `just emu` says there is none. emu-create name=avd api="36": {{sdk}}/cmdline-tools/latest/bin/avdmanager create avd -n {{name}} -k "system-images;android-{{api}};default;x86_64" -d pixel_6 # -no-snapshot so every run is a cold boot: a snapshot restores stale # permission grants and a stale credentials file, which is exactly what you are # trying to test. # # Start the emulator and wait until it has booted. emu name=avd: {{sdk}}/emulator/emulator -avd {{name}} -no-boot-anim -no-snapshot & adb wait-for-device shell 'while [ "$(getprop sys.boot_completed)" != 1 ]; do sleep 1; done' @echo "booted" # Defaults to Marienplatz, Munich. Repeat with new values to simulate walking. # # Move the emulated GPS. Longitude first, that is the order `geo fix` wants. emu-geo lon="11.5754" lat="48.1372": adb emu geo fix {{lon}} {{lat}} # 10.0.2.2 is the emulator's alias for the host's loopback, so the server itself # still binds 127.0.0.1 and stays off the LAN. # # The dev server, handing out the UDP address the emulator can reach. dev-emu: OT_SECRET_KEY={{scratch}}/secret.key OT_ADMIN_EMAIL=ops@example.net OT_DB_PATH={{scratch}}/ot.db \ OT_HTTP_ADDR=127.0.0.1:7372 OT_UDP_ADDR=127.0.0.1:7373 OT_PUBLIC_UDP_HOST=10.0.2.2 \ cargo run -p otserver -- --dev