diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 3120f0db5e..9cb365796b 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -27,20 +27,66 @@ We will only accept bug reports that met the following criteria: ## Development Setup > [!NOTE] -> Check our our [development setup guide](/docs/development-setup) in the docs for more information. +> Local development requires a Unix-like environment. Use Linux, macOS, or WSL2 +> on Windows. Native Windows shells such as PowerShell and Git Bash are not +> supported for the full setup because Tracecat depends on Python packages that +> do not support Windows, such as `uvloop`. + +Install the required tools before starting the stack: + +- `bash` +- Docker with Compose +- `curl` +- `git` +- `jq` +- `node` +- `openssl` +- `pnpm` +- `uv` +- `just` + +On Windows, run the commands from WSL2 and enable Docker Desktop's WSL +integration for your Linux distribution. If PowerShell reports that `sh` is +missing, open WSL2 and run the commands there. + +We use `just cluster` to manage the Docker Compose development stack. +Check your environment first: -We use `docker compose` and the `docker-compose.dev.yml` files for development. +```bash +just doctor +``` To set up your development environment, run: + ```bash just cluster up -d --seed ``` -This starts the development environment and seeds a test user (`test@tracecat.com` / `password1234`). -You can then access the application at [http://localhost:80](http://localhost:80). +This creates `.env` if needed, syncs Python dependencies, installs frontend +dependencies, starts the `docker-compose.dev.yml` stack, and seeds local users. + +Default seeded users: + +- `test@tracecat.com` / `password1234` +- `dev@tracecat.com` / `password1234` > [!IMPORTANT] -> `--seed` creates a test user only. Superadmin is determined by `TRACECAT__AUTH_SUPERADMIN_EMAIL` in `.env` (set via `./env.sh`), and the first signup/login with that email becomes the organization owner. +> `--seed` creates local development users directly. The seeded platform +> superuser defaults to `test@tracecat.com` and can be changed with +> `TRACECAT__DEV_SUPERUSER_EMAIL`. `TRACECAT__AUTH_SUPERADMIN_EMAIL` in `.env` +> controls the first-user bootstrap flow when users sign up normally. + +You can then access the application at [http://localhost:80](http://localhost:80). + +Useful commands: + +```bash +just cluster ps +just cluster ports +just cluster logs api +just cluster restart api +just cluster down +``` ## PR and Commit Message Guidelines diff --git a/justfile b/justfile index 11cf7b037f..1627f08b6d 100644 --- a/justfile +++ b/justfile @@ -3,6 +3,11 @@ set dotenv-load default: @just --list + +# Check local development prerequisites +doctor: + @bash ./scripts/dev-doctor + test: pytest --cache-clear tests/registry tests/unit tests/playbooks -x diff --git a/scripts/dev-doctor b/scripts/dev-doctor new file mode 100644 index 0000000000..385f5f88a1 --- /dev/null +++ b/scripts/dev-doctor @@ -0,0 +1,110 @@ +#!/usr/bin/env bash +set -u + +failures=0 + +if [ -t 1 ] && [ -z "${NO_COLOR:-}" ]; then + GREEN='\033[32m' + RED='\033[31m' + RESET='\033[0m' +else + GREEN='' + RED='' + RESET='' +fi + +ok() { + printf '%bOK%b %s\n' "$GREEN" "$RESET" "$1" +} + +fail() { + printf '%bFAIL%b %s\n' "$RED" "$RESET" "$1" + failures=$((failures + 1)) +} + +info() { + printf 'INFO %s\n' "$1" +} + +check_command_runs() { + local name=$1 + shift + if ! command -v "$name" >/dev/null 2>&1; then + fail "$name is not installed or is not on PATH" + return + fi + if "$name" "$@" >/dev/null 2>&1; then + ok "$name" + else + fail "$name is installed but could not run" + fi +} + +echo "Tracecat development environment" +echo "" + +uname_s=$(uname -s 2>/dev/null || echo unknown) +case "$uname_s" in + Linux*) + if grep -qi microsoft /proc/version 2>/dev/null; then + ok "OS: WSL2/Linux" + else + ok "OS: Linux" + fi + ;; + Darwin*) + ok "OS: macOS" + ;; + MINGW*|MSYS*|CYGWIN*) + fail "OS: native Windows shell detected" + info "Use WSL2 on Windows for the full development setup." + ;; + *) + fail "OS: unsupported or unknown (${uname_s})" + ;; +esac + +check_command_runs bash --version +check_command_runs curl --version +check_command_runs git --version +check_command_runs jq --version +check_command_runs node --version +if command -v node >/dev/null 2>&1 && ! node --version >/dev/null 2>&1; then + info "Install Node.js inside this environment, not only on the host." +fi +check_command_runs openssl version +check_command_runs pnpm --version +if command -v pnpm >/dev/null 2>&1 && ! pnpm --version >/dev/null 2>&1; then + info "Install pnpm inside this environment, not only on the host." +fi +check_command_runs uv --version +check_command_runs just --version + +if command -v docker >/dev/null 2>&1; then + ok "docker" + if docker compose version >/dev/null 2>&1; then + ok "docker compose" + else + fail "docker compose is not available" + fi + + if docker info >/dev/null 2>&1; then + ok "Docker daemon" + else + fail "Docker daemon is not reachable" + info "Start Docker Desktop or your Docker service, then rerun this check." + fi +else + fail "docker is not installed or is not on PATH" +fi + +echo "" +if [ "$failures" -eq 0 ]; then + echo "Ready. Run:" + echo " just cluster up -d --seed" +else + echo "Fix the failed checks, then rerun:" + echo " just doctor" +fi + +exit "$failures"