chart/Justfile

119 lines
3.8 KiB
Makefile

set dotenv-load := true
set shell := ["bash", "-euo", "pipefail", "-c"]
local_url := "http://localhost:" + env_var_or_default("PORT", "8010")
production_url := env_var_or_default("URL", "https://chart.amow.com")
# List available project commands.
default:
@just --list
# Start the local stack in the background.
up:
docker compose up -d
# Build images and run the local stack in the foreground.
dev:
docker compose up --build
# Build or rebuild local images.
build:
docker compose build
# Recreate the API container after environment or dependency changes.
restart:
docker compose up -d --force-recreate api
# Stop and remove the local stack.
down:
docker compose down
# Show local service state.
ps:
docker compose ps
# Validate and print the resolved Compose configuration.
compose-config:
docker compose config
# Follow service logs; e.g. `just logs api 20m`.
logs service="api" since="30m":
docker compose logs --follow --since "{{since}}" "{{service}}"
# Open a shell in the API container.
shell:
docker compose exec api sh
# Copy .env.example only when .env does not exist.
env:
@if [[ -e .env ]]; then echo ".env already exists"; else cp .env.example .env && echo "created .env"; fi
# Install local non-Docker development dependencies into .venv.
venv:
python3 -m venv .venv
.venv/bin/pip install -r requirements.txt -r requirements-dev.txt
# Run the app without Docker after `just venv`.
serve:
.venv/bin/uvicorn main:app --reload
# Run all backend tests, or one pytest path/selector.
test selector="":
@if [[ -n "{{selector}}" ]]; then docker compose exec -T api python -m pytest -q "{{selector}}"; else docker compose exec -T api python -m pytest -q; fi
# Run all browser tests, or files matching a filter such as `trendline`.
e2e filter="":
./bin/e2e "{{filter}}"
# Run complete backend and browser suites.
test-all: test e2e
# Check patches for whitespace errors.
check:
git diff --check
# Require a clean committed worktree.
clean:
@if [[ -n "$(git status --porcelain)" ]]; then echo "worktree is not clean; commit intended changes first" >&2; exit 1; fi
# Run every required pre-deploy check.
predeploy: check test-all
# Capture the local chart through the Playwright service.
screenshot file="chart.png":
docker compose exec -T playwright playwright screenshot --lang en-US --wait-for-timeout 5000 http://api:8000 "/artifacts/{{file}}"
# Show local API status.
status:
curl -fsS "{{local_url}}/api/status"
# Replay Yahoo history through the alert calibration sweep.
calibrate:
docker compose exec -T api python -m scripts.calibrate_alerts
# Validate existing Schwab credentials, or print the authorization URL.
schwab-check redirect_url="":
@if [[ -n "{{redirect_url}}" ]]; then docker compose exec -T api python -m scripts.check_schwab --redirect-url "{{redirect_url}}"; else docker compose exec -T api python -m scripts.check_schwab; fi
# Confirm Schwab stream messages for a duration and symbol.
stream seconds="60" symbol="/ES":
docker compose exec -T api python -m scripts.check_stream "{{seconds}}" "{{symbol}}"
# Wait until production serves local HEAD.
wait-deploy url=production_url timeout="300":
URL="{{url}}" TIMEOUT="{{timeout}}" ./bin/wait-deploy
# Check public production health and deployed version.
smoke url=production_url:
curl -fsS "{{url}}/api/health"
curl -fsS "{{url}}/api/version"
# Check authenticated production status using TOKEN from the environment.
production-status url=production_url:
@if [[ -z "${TOKEN:-}" ]]; then echo "TOKEN is required" >&2; exit 1; fi; curl -fsS -H "X-Chart-Token: $TOKEN" "{{url}}/api/status"
# Require a clean tree, run all tests, push main, wait, and smoke test.
deploy: clean predeploy
git push origin main
./bin/wait-deploy
just smoke