Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
68 changes: 65 additions & 3 deletions Makefile
Original file line number Diff line number Diff line change
@@ -1,5 +1,13 @@
SHELL := /bin/bash

GO_TEST_PACKAGE ?= $(shell cd server && go list ./... | grep -Ev 'internal/(store|seed)$$')
GO_TEST_RUN ?=
GO_TEST_ARGS ?=

ifneq ($(strip $(GO_TEST_RUN)),)
GO_TEST_RUN_FLAG := -run '$(GO_TEST_RUN)'
endif

# Production image knobs. Override at the CLI:
# make docker-build PARSAR_IMAGE=parsar PARSAR_IMAGE_TAG=v0.1.0
# PARSAR_IMAGE is intentionally a generic local name — the open-source
Expand All @@ -8,16 +16,40 @@ SHELL := /bin/bash
PARSAR_IMAGE ?= parsar
PARSAR_IMAGE_TAG ?= dev

.PHONY: setup dev dev-db check reset-dev clean-dev paths migrate-dev sqlc-generate server web cli devgateway http-runner-once http-runner-loop dev-all smoke e2e-http-agent e2e-feishu-gateway dev-server-up dev-server-down dev-server-log bootstrap docker-build docker-build-no-cache openapi
.PHONY: help setup node-deps dev dev-db check test test-fast test-go test-web typecheck-web lint-web-design lint-web test-cli typecheck reset-dev clean-dev paths migrate-dev sqlc-generate server web cli devgateway http-runner-once http-runner-loop dev-all smoke e2e-http-agent e2e-feishu-gateway dev-server-up dev-server-down dev-server-log bootstrap docker-build docker-build-no-cache openapi

help:
@printf '%s\n' \
'Local development:' \
' make dev-all Start Postgres, API, web, and HTTP runner' \
' make dev-db Start the development Postgres only' \
' make server Run the API in the foreground' \
' make web Run the web app in the foreground' \
'' \
'Fast feedback:' \
' make test-fast Run Go tests plus frontend/CLI checks' \
' make test-go Run all Go tests without integration DB packages' \
' make test-go GO_TEST_PACKAGE=./server/internal/api/...' \
' make test-go GO_TEST_PACKAGE=./server/internal/api GO_TEST_RUN=TestHealth' \
' make test-web Typecheck web and check design-system lint' \
' make lint-web Run the full web lint (existing debt may fail)' \
' make test-cli Run CLI unit tests' \
' make typecheck Typecheck all TypeScript packages' \
'' \
'Before review:' \
' make check Run the required full repository gate'

setup:
./scripts/setup.sh

node-deps:
@if [[ ! -d node_modules ]]; then pnpm install --frozen-lockfile; fi

paths:
./scripts/setup.sh paths

migrate-dev:
cd server && go run ./cmd/migrate
./scripts/with-dev-env.sh bash -c 'cd server && exec go run ./cmd/migrate'

# `make bootstrap` is the operator-side first-owner provisioning
# entry point for a freshly-installed Parsar. Required flags must
Expand Down Expand Up @@ -47,14 +79,44 @@ dev: dev-db
check:
./scripts/check.sh

# Fast local feedback. Unlike `make check`, these targets skip setup,
# code-generation drift checks, and database-backed migration tests.
test: test-fast

test-fast: test-go test-web test-cli

test-go:
go test $(GO_TEST_PACKAGE) $(GO_TEST_RUN_FLAG) $(GO_TEST_ARGS)

test-web: typecheck-web lint-web-design

typecheck-web: node-deps
pnpm --filter @parsar/web typecheck

lint-web-design: node-deps
@if (cd apps/web && npx eslint src/ 2>&1) | grep -q "no-restricted-syntax"; then \
echo "Design-system lint violations (arbitrary font sizes or raw palette):" >&2; \
(cd apps/web && npx eslint src/ 2>&1) | grep "no-restricted-syntax" >&2; \
exit 1; \
fi

lint-web: node-deps
pnpm --filter @parsar/web lint

test-cli: node-deps
pnpm --filter @parsar/cli test

typecheck: node-deps
pnpm typecheck

reset-dev:
./scripts/reset-dev.sh

clean-dev:
./scripts/reset-dev.sh --all

server:
cd server && go run ./cmd/server
./scripts/with-dev-env.sh bash -c 'cd server && exec go run ./cmd/server'

# Persistent dev server lifecycle. The binary lives at ~/.parsar/bin
# and runs inside a tmux session that survives sandbox bash exits and
Expand Down
16 changes: 16 additions & 0 deletions scripts/dev-compose.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
#!/usr/bin/env bash
set -euo pipefail

ROOT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")/.." && pwd)"
compose=(docker compose --project-name parsar --file "$ROOT_DIR/docker-compose.dev.yml")

if docker info >/dev/null 2>&1; then
exec "${compose[@]}" "$@"
fi

if command -v sudo >/dev/null 2>&1 && sudo -n docker info >/dev/null 2>&1; then
exec sudo -n "${compose[@]}" "$@"
fi

echo "Docker is unavailable. Start Docker or grant this user access to its socket." >&2
exit 1
11 changes: 11 additions & 0 deletions scripts/dev-env.sh
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,17 @@ export PARSAR_WEB_PORT="${PARSAR_WEB_PORT:-5173}"
# in prod) — see docs/deploy/config.example.yaml.
export PARSAR_DEV_AUTH="${PARSAR_DEV_AUTH:-true}"

# ── Server runtime posture ───────────────────────────────────────────
# Loopback public_url selects the development validation profile. These
# values are intentionally safe only for local development and remain
# override-friendly for alternate ports or integration setups.
export PARSAR_ADDR="${PARSAR_ADDR:-127.0.0.1:$PARSAR_DEV_SERVER_PORT}"
export PARSAR_PUBLIC_URL="${PARSAR_PUBLIC_URL:-http://127.0.0.1:$PARSAR_DEV_SERVER_PORT}"
export PARSAR_COOKIE_SECURE="${PARSAR_COOKIE_SECURE:-false}"
export PARSAR_MASTER_KEY="${PARSAR_MASTER_KEY:-parsar-dev-master-key-2026}"
export PARSAR_FEISHU_MOCK="${PARSAR_FEISHU_MOCK:-true}"
export PARSAR_AGENT_DAEMON_OWNER_URL="${PARSAR_AGENT_DAEMON_OWNER_URL:-$PARSAR_PUBLIC_URL}"

# Builds the dev DATABASE_URL from the parts above. Optional args let a
# caller override host ($1) and port ($2) without touching the creds —
# used by dev-all.sh, which picks an ephemeral free port for Postgres.
Expand Down
23 changes: 21 additions & 2 deletions scripts/dev-stack.sh
Original file line number Diff line number Diff line change
Expand Up @@ -13,13 +13,32 @@ PARSAR_STATE_DIR="$PARSAR_HOME/state"
PARSAR_DEV_DIR="$PARSAR_HOME/dev"
mkdir -p "$PARSAR_LOG_DIR" "$PARSAR_STATE_DIR" "$PARSAR_DEV_DIR"

docker compose -f docker-compose.dev.yml up -d postgres
./scripts/dev-compose.sh up -d postgres

printf 'Waiting for Postgres'
for _ in {1..30}; do
if ./scripts/dev-compose.sh exec -T postgres \
pg_isready -U "$PARSAR_PG_USER" -d "$PARSAR_PG_DB" >/dev/null 2>&1; then
printf ' ready\n'
break
fi
printf '.'
sleep 1
done

if ! ./scripts/dev-compose.sh exec -T postgres \
pg_isready -U "$PARSAR_PG_USER" -d "$PARSAR_PG_DB" >/dev/null 2>&1; then
printf '\nPostgres did not become ready; inspect logs with:\n' >&2
printf ' ./scripts/dev-compose.sh logs postgres\n' >&2
exit 1
fi

cat <<INFO
Parsar dev stack started.

Postgres: ${PARSAR_POSTGRES_HOST}:${PARSAR_POSTGRES_PORT} (db=${PARSAR_PG_DB} user=${PARSAR_PG_USER} password=${PARSAR_PG_PASSWORD})
Migrate: make migrate-dev
Server: make server # http://127.0.0.1:8080/api/v1/health
Server: make server # http://127.0.0.1:${PARSAR_DEV_SERVER_PORT}/api/v1/health
Web: make web # http://127.0.0.1:${PARSAR_WEB_PORT}
Runner: make http-runner-loop # bounded local HTTP Agent runner
Logs: $PARSAR_LOG_DIR
Expand Down
4 changes: 2 additions & 2 deletions scripts/reset-dev.sh
Original file line number Diff line number Diff line change
Expand Up @@ -4,9 +4,9 @@ set -euo pipefail
PARSAR_HOME="${PARSAR_HOME:-$HOME/.parsar}"

if [[ "${1:-}" == "--all" ]]; then
docker compose -f docker-compose.dev.yml down -v --remove-orphans
./scripts/dev-compose.sh down -v --remove-orphans
else
docker compose -f docker-compose.dev.yml down --remove-orphans
./scripts/dev-compose.sh down --remove-orphans
fi

mkdir -p "$PARSAR_HOME/dev"
Expand Down
12 changes: 12 additions & 0 deletions scripts/with-dev-env.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
#!/usr/bin/env bash
set -euo pipefail

ROOT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")/.." && pwd)"

# shellcheck source=scripts/dev-env.sh
source "$ROOT_DIR/scripts/dev-env.sh"

export DATABASE_URL="${DATABASE_URL:-$(parsar_dev_database_url)}"
export PARSAR_MIGRATIONS_DIR="${PARSAR_MIGRATIONS_DIR:-$ROOT_DIR/server/migrations}"

exec "$@"