diff --git a/.github/workflows/crates-ci.yml b/.github/workflows/crates-ci.yml index ef9f3204..9e4dfeb5 100644 --- a/.github/workflows/crates-ci.yml +++ b/.github/workflows/crates-ci.yml @@ -7,12 +7,17 @@ on: - "crates/**" - "Cargo.toml" - "Cargo.lock" + - "rust-toolchain.toml" + - ".github/workflows/crates-ci.yml" push: branches: [main] paths: - "crates/**" - "Cargo.toml" - "Cargo.lock" + - "rust-toolchain.toml" + - ".github/workflows/crates-ci.yml" + workflow_dispatch: env: CARGO_TERM_COLOR: always @@ -21,6 +26,8 @@ jobs: check: name: Check runs-on: ubuntu-latest + permissions: + contents: read steps: - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6 diff --git a/.github/workflows/mark-ci.yml b/.github/workflows/mark-ci.yml index 927de4b4..dad77ce3 100644 --- a/.github/workflows/mark-ci.yml +++ b/.github/workflows/mark-ci.yml @@ -5,12 +5,23 @@ on: branches: [main] paths: - "apps/mark/**" + - "packages/**" - "crates/**" + - "pnpm-lock.yaml" + - "pnpm-workspace.yaml" + - "package.json" + - ".github/workflows/mark-ci.yml" push: branches: [main] paths: - "apps/mark/**" + - "packages/**" - "crates/**" + - "pnpm-lock.yaml" + - "pnpm-workspace.yaml" + - "package.json" + - ".github/workflows/mark-ci.yml" + workflow_dispatch: env: CARGO_TERM_COLOR: always @@ -19,6 +30,8 @@ jobs: check: name: Check runs-on: ubuntu-latest + permissions: + contents: read steps: - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6 diff --git a/.github/workflows/staged-ci.yml b/.github/workflows/staged-ci.yml new file mode 100644 index 00000000..3ea0f725 --- /dev/null +++ b/.github/workflows/staged-ci.yml @@ -0,0 +1,65 @@ +name: Staged CI + +on: + pull_request: + branches: [main] + paths: + - "apps/staged/**" + - "crates/**" + - "pnpm-lock.yaml" + - "pnpm-workspace.yaml" + - "package.json" + - ".github/workflows/staged-ci.yml" + push: + branches: [main] + paths: + - "apps/staged/**" + - "crates/**" + - "pnpm-lock.yaml" + - "pnpm-workspace.yaml" + - "package.json" + - ".github/workflows/staged-ci.yml" + workflow_dispatch: + +env: + CARGO_TERM_COLOR: always + +jobs: + check: + name: Check + runs-on: ubuntu-latest + permissions: + contents: read + steps: + - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6 + + # Install hermit (manages node, rust, just) + - uses: cashapp/activate-hermit@e49f5cb4dd64ff0b0b659d1d8df499595451155a # v1 + + # Enable pnpm via corepack (node ships with corepack; version comes from packageManager in package.json) + - run: corepack enable pnpm + + # Cache Cargo dependencies + - uses: Swatinem/rust-cache@779680da715d629ac1d338a641029a2f4372abb5 # v2 + with: + workspaces: apps/staged/src-tauri + + # Install system dependencies for Tauri (Linux) + - name: Install Tauri dependencies (Linux) + run: | + sudo apt-get update + sudo apt-get install -y \ + libwebkit2gtk-4.1-dev \ + libappindicator3-dev \ + librsvg2-dev \ + patchelf + + # Install dependencies + - name: Install dependencies + run: | + pnpm install --frozen-lockfile + cd apps/staged/src-tauri && cargo fetch + + # Run all checks via the app justfile + - name: Check all (fmt, lint, typecheck) + run: just -f apps/staged/justfile ci diff --git a/.gitignore b/.gitignore index e08c7941..af9ed794 100644 --- a/.gitignore +++ b/.gitignore @@ -1,2 +1,4 @@ target/ .DS_Store +.hermit +node_modules/ diff --git a/README.md b/README.md new file mode 100644 index 00000000..2638b6d4 --- /dev/null +++ b/README.md @@ -0,0 +1,80 @@ +# Builderbot Monorepo + +This repository contains Builderbot apps, shared UI packages, and Rust crates. + +## Quick Start + +```bash +# from repo root +source ./bin/activate-hermit +just setup +``` + +`just setup` runs `lefthook install` and `pnpm install`. + +Then run an app: + +```bash +just dev # start Mark +just dev staged # start Staged +``` + +## Command Guide + +The root `justfile` supports both styles: + +```bash +just dev staged # verb-first (recommended for humans) +just app staged dev # explicit delegation form +``` + +Useful commands: + +```bash +just apps # list app names +just setup # first-time setup (hooks + JS deps) +just dev # run Mark app +just dev staged # run Staged app +just mark # alias for `just app mark dev` +just staged # alias for `just app staged dev` +just check # full non-modifying checks +just ci # alias of `just check` +just fmt # format repo +just lint # lint repo +just test # run Rust workspace tests +``` + +## Repo Layout + +- `apps/mark`: main desktop app. +- `apps/staged`: standalone staged/diff app. +- `packages/diff-viewer`: shared Svelte diff viewer package. +- `crates/`: shared Rust crates. +- `scripts/`: helper scripts used by app tooling. + +## App-Level Commands + +Each app has its own `justfile` for app-specific workflows: + +- `apps/mark/justfile` +- `apps/staged/justfile` + +Use root delegation to run any app recipe: + +```bash +just app mark ci +just app staged build +``` + +## Troubleshooting + +- `just: command not found` + - Run `source ./bin/activate-hermit` in your shell. +- Frontend waiting on dev server / port issues + - Check listeners: `lsof -nP -iTCP: -sTCP:LISTEN` +- `node_modules` appears at repo root + - Expected for this `pnpm` workspace monorepo; app `node_modules` entries are symlinked into the root store. + +## More Docs + +- Mark app docs: `apps/mark/README.md` diff --git a/apps/staged/package.json b/apps/staged/package.json index 893f6aaf..9b8ffbac 100644 --- a/apps/staged/package.json +++ b/apps/staged/package.json @@ -16,6 +16,7 @@ "@sveltejs/vite-plugin-svelte": "^6.2.1", "@tauri-apps/cli": "^2.10.0", "@tsconfig/svelte": "^5.0.6", + "@types/node": "^24.10.1", "prettier": "^3.7.4", "prettier-plugin-svelte": "^3.4.1", "svelte": "^5.46.4", diff --git a/apps/staged/src-tauri/tauri.conf.json b/apps/staged/src-tauri/tauri.conf.json index e7f6be9e..b0247abe 100644 --- a/apps/staged/src-tauri/tauri.conf.json +++ b/apps/staged/src-tauri/tauri.conf.json @@ -6,7 +6,7 @@ "build": { "frontendDist": "../dist", "devUrl": "http://localhost:5175", - "beforeDevCommand": "pnpm run dev", + "beforeDevCommand": "VITE_PORT=${VITE_PORT:-5175} pnpm run dev", "beforeBuildCommand": "pnpm run build" }, "app": { diff --git a/apps/staged/vite.config.ts b/apps/staged/vite.config.ts index 682c8371..d6d8e05a 100644 --- a/apps/staged/vite.config.ts +++ b/apps/staged/vite.config.ts @@ -1,10 +1,12 @@ import { defineConfig } from 'vite'; import { svelte } from '@sveltejs/vite-plugin-svelte'; +const port = parseInt(process.env.VITE_PORT || '5175', 10); + export default defineConfig({ plugins: [svelte()], server: { - port: 5175, + port, strictPort: true, }, }); diff --git a/justfile b/justfile index b9c32277..c5d9870b 100644 --- a/justfile +++ b/justfile @@ -1,51 +1,108 @@ # Builderbot Monorepo # Run `just setup` once after cloning. +# +# Common flows: +# just dev # Start Mark +# just dev staged # Start Staged +# just app mark ci # Run any app recipe +# just check # Full non-modifying checks # Default: list available recipes default: @just --list -# ── Setup ────────────────────────────────────────────────── +# ============================================================================ +# Setup +# ============================================================================ # First-time setup setup: lefthook install pnpm install -# ── Per-App (delegate) ───────────────────────────────────── +# ============================================================================ +# App Delegation +# ============================================================================ -# Run a just recipe in a specific app (e.g., just app mark dev) -app name *ARGS: - just -f apps/{{name}}/justfile {{ARGS}} +# List app workspaces that expose a justfile +apps: + #!/usr/bin/env bash + set -euo pipefail + for dir in apps/*/; do + [[ -f "$dir/justfile" ]] || continue + basename "$dir" + done + +# Run a recipe in a specific app (e.g. `just app mark dev`) +app name recipe="dev" *args: + #!/usr/bin/env bash + set -euo pipefail + + app_justfile="apps/{{name}}/justfile" + if [[ ! -f "$app_justfile" ]]; then + echo "Unknown app '{{name}}'. Available apps:" + for dir in apps/*/; do + [[ -f "$dir/justfile" ]] || continue + echo " - $(basename "$dir")" + done + exit 1 + fi + + just -f "$app_justfile" {{recipe}} {{args}} -# Shortcuts for the most common app commands -dev app="mark" *ARGS: - just -f apps/{{app}}/justfile dev {{ARGS}} +# Human-friendly shortcuts (supports `just dev staged` style) +dev app="mark" *args: + just app {{app}} dev {{args}} -# ── Cross-Cutting ────────────────────────────────────────── +# Convenience aliases +mark recipe="dev" *args: + just app mark {{recipe}} {{args}} + +staged recipe="dev" *args: + just app staged {{recipe}} {{args}} + +# ============================================================================ +# Cross-Cutting +# ============================================================================ # Format all apps + crates fmt: + #!/usr/bin/env bash + set -euo pipefail cargo fmt --all - for dir in apps/*/; do \ - [ -f "$dir/justfile" ] && just -f "$dir/justfile" fmt || true; \ + for dir in apps/*/; do + [[ -f "$dir/justfile" ]] || continue + just -f "$dir/justfile" fmt done # Lint everything lint: + #!/usr/bin/env bash + set -euo pipefail cargo clippy --workspace -- -D warnings - for dir in apps/*/; do \ - [ -f "$dir/justfile" ] && just -f "$dir/justfile" lint || true; \ + for dir in apps/*/; do + [[ -f "$dir/justfile" ]] || continue + just -f "$dir/justfile" lint done -# Check everything (what CI runs) -ci: - for dir in apps/*/; do \ - [ -f "$dir/justfile" ] && just -f "$dir/justfile" ci || true; \ +# Verify everything without modifying files (CI-friendly) +check: + #!/usr/bin/env bash + set -euo pipefail + cargo fmt --all --check + cargo clippy --workspace -- -D warnings + for dir in apps/*/; do + [[ -f "$dir/justfile" ]] || continue + just -f "$dir/justfile" ci done cargo test --workspace -# ── Crates ───────────────────────────────────────────────── +# Alias: many people expect `just ci` +ci: check + +# ============================================================================ +# Crates +# ============================================================================ # Build shared crates build: @@ -59,6 +116,6 @@ test: install-summarize: cargo install --path crates/summarize -# Run summarize directly (e.g. just summarize --prompt "What?" src/) -summarize *ARGS: - cargo run --release -p summarize -- {{ARGS}} +# Run summarize directly (e.g. `just summarize --prompt "What?" src/`) +summarize *args: + cargo run --release -p summarize -- {{args}} diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 3cd834f9..7eed3cdf 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -84,6 +84,9 @@ importers: '@tsconfig/svelte': specifier: ^5.0.6 version: 5.0.8 + '@types/node': + specifier: ^24.10.1 + version: 24.10.13 prettier: specifier: ^3.7.4 version: 3.8.1 @@ -333,66 +336,79 @@ packages: resolution: {integrity: sha512-t4ONHboXi/3E0rT6OZl1pKbl2Vgxf9vJfWgmUoCEVQVxhW6Cw/c8I6hbbu7DAvgp82RKiH7TpLwxnJeKv2pbsw==} cpu: [arm] os: [linux] + libc: [glibc] '@rollup/rollup-linux-arm-musleabihf@4.59.0': resolution: {integrity: sha512-CikFT7aYPA2ufMD086cVORBYGHffBo4K8MQ4uPS/ZnY54GKj36i196u8U+aDVT2LX4eSMbyHtyOh7D7Zvk2VvA==} cpu: [arm] os: [linux] + libc: [musl] '@rollup/rollup-linux-arm64-gnu@4.59.0': resolution: {integrity: sha512-jYgUGk5aLd1nUb1CtQ8E+t5JhLc9x5WdBKew9ZgAXg7DBk0ZHErLHdXM24rfX+bKrFe+Xp5YuJo54I5HFjGDAA==} cpu: [arm64] os: [linux] + libc: [glibc] '@rollup/rollup-linux-arm64-musl@4.59.0': resolution: {integrity: sha512-peZRVEdnFWZ5Bh2KeumKG9ty7aCXzzEsHShOZEFiCQlDEepP1dpUl/SrUNXNg13UmZl+gzVDPsiCwnV1uI0RUA==} cpu: [arm64] os: [linux] + libc: [musl] '@rollup/rollup-linux-loong64-gnu@4.59.0': resolution: {integrity: sha512-gbUSW/97f7+r4gHy3Jlup8zDG190AuodsWnNiXErp9mT90iCy9NKKU0Xwx5k8VlRAIV2uU9CsMnEFg/xXaOfXg==} cpu: [loong64] os: [linux] + libc: [glibc] '@rollup/rollup-linux-loong64-musl@4.59.0': resolution: {integrity: sha512-yTRONe79E+o0FWFijasoTjtzG9EBedFXJMl888NBEDCDV9I2wGbFFfJQQe63OijbFCUZqxpHz1GzpbtSFikJ4Q==} cpu: [loong64] os: [linux] + libc: [musl] '@rollup/rollup-linux-ppc64-gnu@4.59.0': resolution: {integrity: sha512-sw1o3tfyk12k3OEpRddF68a1unZ5VCN7zoTNtSn2KndUE+ea3m3ROOKRCZxEpmT9nsGnogpFP9x6mnLTCaoLkA==} cpu: [ppc64] os: [linux] + libc: [glibc] '@rollup/rollup-linux-ppc64-musl@4.59.0': resolution: {integrity: sha512-+2kLtQ4xT3AiIxkzFVFXfsmlZiG5FXYW7ZyIIvGA7Bdeuh9Z0aN4hVyXS/G1E9bTP/vqszNIN/pUKCk/BTHsKA==} cpu: [ppc64] os: [linux] + libc: [musl] '@rollup/rollup-linux-riscv64-gnu@4.59.0': resolution: {integrity: sha512-NDYMpsXYJJaj+I7UdwIuHHNxXZ/b/N2hR15NyH3m2qAtb/hHPA4g4SuuvrdxetTdndfj9b1WOmy73kcPRoERUg==} cpu: [riscv64] os: [linux] + libc: [glibc] '@rollup/rollup-linux-riscv64-musl@4.59.0': resolution: {integrity: sha512-nLckB8WOqHIf1bhymk+oHxvM9D3tyPndZH8i8+35p/1YiVoVswPid2yLzgX7ZJP0KQvnkhM4H6QZ5m0LzbyIAg==} cpu: [riscv64] os: [linux] + libc: [musl] '@rollup/rollup-linux-s390x-gnu@4.59.0': resolution: {integrity: sha512-oF87Ie3uAIvORFBpwnCvUzdeYUqi2wY6jRFWJAy1qus/udHFYIkplYRW+wo+GRUP4sKzYdmE1Y3+rY5Gc4ZO+w==} cpu: [s390x] os: [linux] + libc: [glibc] '@rollup/rollup-linux-x64-gnu@4.59.0': resolution: {integrity: sha512-3AHmtQq/ppNuUspKAlvA8HtLybkDflkMuLK4DPo77DfthRb71V84/c4MlWJXixZz4uruIH4uaa07IqoAkG64fg==} cpu: [x64] os: [linux] + libc: [glibc] '@rollup/rollup-linux-x64-musl@4.59.0': resolution: {integrity: sha512-2UdiwS/9cTAx7qIUZB/fWtToJwvt0Vbo0zmnYt7ED35KPg13Q0ym1g442THLC7VyI6JfYTP4PiSOWyoMdV2/xg==} cpu: [x64] os: [linux] + libc: [musl] '@rollup/rollup-openbsd-x64@4.59.0': resolution: {integrity: sha512-M3bLRAVk6GOwFlPTIxVBSYKUaqfLrn8l0psKinkCFxl4lQvOSz8ZrKDz2gxcBwHFpci0B6rttydI4IpS4IS/jQ==} @@ -491,30 +507,35 @@ packages: engines: {node: '>= 10'} cpu: [arm64] os: [linux] + libc: [glibc] '@tauri-apps/cli-linux-arm64-musl@2.10.0': resolution: {integrity: sha512-GUoPdVJmrJRIXFfW3Rkt+eGK9ygOdyISACZfC/bCSfOnGt8kNdQIQr5WRH9QUaTVFIwxMlQyV3m+yXYP+xhSVA==} engines: {node: '>= 10'} cpu: [arm64] os: [linux] + libc: [musl] '@tauri-apps/cli-linux-riscv64-gnu@2.10.0': resolution: {integrity: sha512-JO7s3TlSxshwsoKNCDkyvsx5gw2QAs/Y2GbR5UE2d5kkU138ATKoPOtxn8G1fFT1aDW4LH0rYAAfBpGkDyJJnw==} engines: {node: '>= 10'} cpu: [riscv64] os: [linux] + libc: [glibc] '@tauri-apps/cli-linux-x64-gnu@2.10.0': resolution: {integrity: sha512-Uvh4SUUp4A6DVRSMWjelww0GnZI3PlVy7VS+DRF5napKuIehVjGl9XD0uKoCoxwAQBLctvipyEK+pDXpJeoHng==} engines: {node: '>= 10'} cpu: [x64] os: [linux] + libc: [glibc] '@tauri-apps/cli-linux-x64-musl@2.10.0': resolution: {integrity: sha512-AP0KRK6bJuTpQ8kMNWvhIpKUkQJfcPFeba7QshOQZjJ8wOS6emwTN4K5g/d3AbCMo0RRdnZWwu67MlmtJyxC1Q==} engines: {node: '>= 10'} cpu: [x64] os: [linux] + libc: [musl] '@tauri-apps/cli-win32-arm64-msvc@2.10.0': resolution: {integrity: sha512-97DXVU3dJystrq7W41IX+82JEorLNY+3+ECYxvXWqkq7DBN6FsA08x/EFGE8N/b0LTOui9X2dvpGGoeZKKV08g==}