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
4 changes: 4 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -130,6 +130,10 @@ out/
.vscode/
!config/vscode/.vscode/

# zed config files
.zed
!config/zed/.zed

# cursor editor config files
.cursor-config/
!config/cursor/.cursor-config/
Expand Down
1 change: 1 addition & 0 deletions backend/justfile
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,7 @@ help:
@echo "IDE Setup:"
@echo " docs/development/vscode-setup.md - VS Code configuration"
@echo " docs/development/intellij-setup.md - IntelliJ/PyCharm setup"
@echo " docs/development/zed-setup.md - Zed editor setup"
@echo ""
@echo "Other:"
@echo " docs/development/justfile.md - Just command reference"
Expand Down
208 changes: 208 additions & 0 deletions config/zed/.zed/debug.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,208 @@
// Zed debugger configurations for Baserow — shared/public baseline.
//
// ─── How to install ───────────────────────────────────────────────────────────
// Run the following from the repository root:
// config/zed/apply_standard_baserow_zed_config.sh
// This copies config/zed/.zed/ → .zed/ (overwriting any existing file).
//
// ─── Personal customisations ──────────────────────────────────────────────────
// After running the script, open .zed/debug.json and add:
// • Extra env vars specific to your environment (BASEROW_PUBLIC_URL, etc.)
// • Additional launch configs for your own workflows (frontend, gunicorn, …)
// .zed/ at the worktree root is git-ignored, so your edits are private.
//
// NO SECRETS are stored in this file — it is tracked in git and shared with
// all Baserow contributors. Add any personal or sensitive env vars only to
// .zed/debug.json after the script has copied it.
//
// ─── Adapter ──────────────────────────────────────────────────────────────────
// All configs below use the Debugpy adapter. Zed will auto-install it on
// first use. Open the Debug panel (Cmd-Shift-D / Ctrl-Shift-D) or run
// `debugger: start` from the command palette to pick a configuration.
[
{
// ── backend: django runserver (launch) ─────────────────────────────────
//
// Starts the Django dev server under Debugpy so you can set breakpoints
// directly in the editor and have them hit on incoming requests.
//
// WHY --noreload IS REQUIRED FOR BREAKPOINTS
// Django's autoreloader works by forking a child process (identified by
// the RUN_MAIN env var) that actually handles HTTP requests, while the
// parent process monitors source files for changes. Debugpy is attached
// to the *parent* at launch time, so any breakpoints you set in view or
// model code are in the wrong process — they are never reached.
//
// --noreload disables the fork entirely: Django runs single-process, and
// Debugpy (plus your breakpoints) lives in the same process that handles
// every request. The trade-off is that you must restart this config
// manually after editing Python source files.
//
// WHY `program` AND NOT `module`
// Using `module: "baserow"` tells Debugpy to run `python -m baserow`.
// The baserow __main__.py hands control to Django's execute_from_command_
// line(), which then re-invokes the autoreloader machinery *before*
// Debugpy can intercept the fork. Pointing `program` at the entry-point
// script bypasses that re-invocation path.
//
// ALTERNATIVE — if you need hot-reloading or are using Docker:
// Use the "backend: django (attach to :5678)" config below instead.
// It attaches *inside* the RUN_MAIN child where requests are handled,
// so breakpoints work even with the autoreloader enabled.
"label": "backend: django runserver (launch)",
"adapter": "Debugpy",
"request": "launch",
"program": "$ZED_WORKTREE_ROOT/backend/baserow",
"args": ["runserver", "--noreload", "0.0.0.0:8000"],
"cwd": "$ZED_WORKTREE_ROOT",
"python": "$ZED_WORKTREE_ROOT/.venv/bin/python",
"django": true,
"justMyCode": false,
"console": "integratedTerminal",
"env": {
// Relative paths work because cwd is the worktree root.
"PYTHONPATH": "backend/src:premium/backend/src:enterprise/backend/src",
"DJANGO_SETTINGS_MODULE": "baserow.config.settings.dev",
// Point at your local Postgres. Override in .zed/debug.json if needed.
"DATABASE_HOST": "localhost",
},
},
{
// ── backend: django (attach to :5678) ──────────────────────────────────
//
// Attaches Zed's debugger to a Django dev-server that is already listening
// for a Debugpy client on port 5678. This is the recommended approach
// when you want breakpoints *and* hot-reloading at the same time.
//
// HOW TO USE (local venv)
// 1. Start the backend with the debugger enabled:
// BASEROW_BACKEND_DEBUGGER_ENABLED=1 just b run-dev-server
// With that env var set, manage.py calls `debugpy.listen(5678)` and
// then `debugpy.wait_for_client()` inside the RUN_MAIN child process
// — the process that actually handles HTTP requests.
// 2. Wait until you see "Debugpy waiting for client…" in the terminal.
// 3. Launch this config from the Debug panel. Debugpy will resume the
// server and breakpoints will be hit on the next request.
//
// HOW TO USE (Docker dev env)
// Works identically with `just dc-dev up` once you set
// BASEROW_BACKEND_DEBUGGER_ENABLED=1 in your docker-compose override.
// The backend container already maps container port 5678 → host 5678.
// The pathMappings below translate container paths to your local
// worktree so that editor breakpoints resolve correctly.
"label": "backend: django (attach to :5678)",
"adapter": "Debugpy",
"request": "attach",
"tcp_connection": { "host": "127.0.0.1", "port": 5678 },
"cwd": "$ZED_WORKTREE_ROOT",
"django": true,
"justMyCode": false,
"pathMappings": [
{
"localRoot": "$ZED_WORKTREE_ROOT",
"remoteRoot": "/baserow",
},
],
},
{
// ── backend: celery worker (launch) ────────────────────────────────────
//
// Starts a Celery worker under Debugpy. Set breakpoints inside task
// functions and they will be hit when a task is dispatched.
//
// --pool=solo runs Celery in single-threaded mode (no subprocess pool),
// which is required for Debugpy breakpoints to work reliably — the pool
// strategies that use forked sub-processes suffer the same issue as the
// Django autoreloader.
//
// Queues consumed by this worker:
// celery — default / general task queue
// export — file-export tasks (spreadsheet, PDF, …)
// automation_workflow — automation trigger / action tasks
"label": "backend: celery worker (launch)",
"adapter": "Debugpy",
"request": "launch",
"module": "celery",
"args": [
"-A",
"baserow",
"worker",
"-Q",
"celery,export,automation_workflow",
"-l",
"INFO",
"--pool=solo",
],
"cwd": "$ZED_WORKTREE_ROOT",
"python": "$ZED_WORKTREE_ROOT/.venv/bin/python",
"justMyCode": false,
"console": "integratedTerminal",
"env": {
"PYTHONPATH": "backend/src:premium/backend/src:enterprise/backend/src",
"DJANGO_SETTINGS_MODULE": "baserow.config.settings.dev",
"DATABASE_HOST": "localhost",
},
},
{
// ── backend: pytest current file ───────────────────────────────────────
//
// Runs pytest against whichever test file is currently open/focused in Zed.
// Make sure the test file is the active editor tab before launching.
//
// -v one line per test with pass/fail status
// -s disable output capture so print() calls and logging appear inline
// (useful when debugging a single failing test)
"label": "backend: pytest current file",
"adapter": "Debugpy",
"request": "launch",
"module": "pytest",
"args": ["$ZED_FILE", "-v", "-s"],
"cwd": "$ZED_WORKTREE_ROOT/backend",
"python": "$ZED_WORKTREE_ROOT/.venv/bin/python",
"justMyCode": false,
"console": "integratedTerminal",
"env": {
// Absolute paths are required here because cwd is the backend sub-directory,
// not the worktree root, so relative paths would not resolve correctly.
"PYTHONPATH": "$ZED_WORKTREE_ROOT/backend/src:$ZED_WORKTREE_ROOT/premium/backend/src:$ZED_WORKTREE_ROOT/enterprise/backend/src:$ZED_WORKTREE_ROOT/backend/flake8_plugins",
"DJANGO_SETTINGS_MODULE": "baserow.config.settings.test",
"DATABASE_HOST": "localhost",
},
},
{
// ── backend: pytest all (with coverage) ────────────────────────────────
//
// Runs the complete backend test suite across core, premium, and enterprise
// packages and produces an XML coverage report.
//
// This can take several minutes on a full run. The report is written to:
// <worktree-root>/html_coverage/cov.xml
//
// -n=auto parallelises test collection and execution across all available
// CPU cores via pytest-xdist, significantly reducing wall-clock
// time. Note: parallel runs disable Debugpy breakpoints — remove
// this flag if you need to step through code during a full run.
"label": "backend: pytest all (with coverage)",
"adapter": "Debugpy",
"request": "launch",
"module": "pytest",
"args": [
"-n=auto",
"--cov-report=xml:html_coverage/cov.xml",
"--cov-config=$ZED_WORKTREE_ROOT/backend/.coveragerc",
"--cov=baserow",
"backend/tests/",
"premium/backend/tests/",
"enterprise/backend/tests/",
],
"cwd": "$ZED_WORKTREE_ROOT",
"python": "$ZED_WORKTREE_ROOT/.venv/bin/python",
"justMyCode": false,
"console": "integratedTerminal",
"env": {
"PYTHONPATH": "backend/src:premium/backend/src:enterprise/backend/src",
"DJANGO_SETTINGS_MODULE": "baserow.config.settings.test",
"DATABASE_HOST": "localhost",
},
},
]
30 changes: 30 additions & 0 deletions config/zed/.zed/settings.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
// Project-level Zed settings for Baserow.
// Copied into `<repo>/.zed/settings.json` by
// `config/zed/apply_standard_baserow_zed_config.sh`.
{
"languages": {
"Python": {
"language_servers": ["pyright", "ruff"],
"formatter": [
{ "language_server": { "name": "ruff" } }
],
"format_on_save": "on"
}
},
"lsp": {
"pyright": {
"settings": {
"python": {
"pythonPath": ".venv/bin/python"
},
"python.analysis": {
"extraPaths": [
"backend/src",
"premium/backend/src",
"enterprise/backend/src"
]
}
}
}
}
}
18 changes: 18 additions & 0 deletions config/zed/apply_standard_baserow_zed_config.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
#!/bin/bash
# Bash strict mode: http://redsymbol.net/articles/unofficial-bash-strict-mode/
set -euo pipefail

RED=$(tput setaf 1)
GREEN=$(tput setaf 2)
YELLOW=$(tput setaf 3)
NC=$(tput sgr0) # No Color
read -p "${YELLOW}This script will overwrite any existing Zed config you might already have for this Baserow repo with a standard set of config, are you sure? ${NC}${GREEN}Enter Y or y to continue${NC}${RED}, or any other character to abort.${NC}" -n 1 -r
echo # (optional) move to a new line
if [[ $REPLY =~ ^[Yy]$ ]]
then
SCRIPT_DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" &> /dev/null && pwd )"
cp -a "${SCRIPT_DIR}/.zed" "${SCRIPT_DIR}/../../"
echo "${GREEN}Successfully applied the default Baserow Zed config...${NC}"
else
echo "${RED}Aborted application of the default Baserow Zed config...${NC}"
fi
113 changes: 113 additions & 0 deletions docs/development/zed-setup.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,113 @@
# Zed Setup

This guide explains how to use [Zed](https://zed.dev) with Baserow, including the
Python/Django debugger configurations that ship with the repo.

## Prerequisites

- [just](https://github.com/casey/just)
- [uv](https://github.com/astral-sh/uv)
- A local backend virtualenv created by `just b init` (lives at `.venv/`)

## Apply the standard config

From the repo root run:

```bash
./config/zed/apply_standard_baserow_zed_config.sh
```

This copies `config/zed/.zed/` into `<repo>/.zed/`, giving you:

- `.zed/debug.json` — Debug Adapter Protocol (Debugpy) configurations
- `.zed/settings.json` — Python LSP (`pyright` + `ruff`) extra paths

You can also copy the files manually if you prefer to merge by hand.

> **Personal customisations** — `.zed/` at the repo root is git-ignored, so any
> changes you make after running the script are private to your machine. Add
> extra env vars, additional launch configs, or personal secrets directly to
> `.zed/debug.json` without worrying about committing them.

## Debug configurations

Open the debug panel in Zed (`cmd-shift-d` / `ctrl-shift-d`) or run the
`debugger: start` command, then pick one of:

### backend: django runserver (launch)

Starts the Django dev server single-process under Debugpy. Breakpoints set in
view/model code are hit on the next matching request.

> **Why `--noreload`?** Django's autoreloader forks a child process to handle
> HTTP requests while the parent watches source files. Debugpy attaches to the
> parent, so without `--noreload` breakpoints in request-handling code are never
> reached. The trade-off is that you must **restart the debug session manually**
> after editing Python source files.
>
> If you need hot-reloading, use the attach config below instead.

### backend: django (attach to :5678)

Attaches to an already-running Django process that is listening for a Debugpy
client on port 5678. This is the **recommended approach for local development**
because breakpoints work correctly *and* the autoreloader stays enabled.

**Local venv workflow:**

```bash
BASEROW_BACKEND_DEBUGGER_ENABLED=1 just b run-dev-server
```

With that env var set, `manage.py` calls `debugpy.listen(5678)` inside the
`RUN_MAIN` child process — the process that actually handles HTTP requests.
Once you see the server start up, launch this config from the Debug panel to
attach.

**Docker dev env workflow:**

```bash
just dc-dev up -d
```

The backend container already maps container port 5678 → host 5678. Set
`BASEROW_BACKEND_DEBUGGER_ENABLED=1` in your `docker-compose.override.yml` and
then attach as above.

### backend: celery worker (launch)

Runs a Celery worker under Debugpy in single-threaded mode (`--pool=solo`).
Breakpoints set inside task functions are hit when a task is dispatched.

> `--pool=solo` is required for the same reason as `--noreload` above — pool
> strategies that use forked sub-processes put the task execution in a child
> that Debugpy is not attached to.

Queues consumed: `celery`, `export`, `automation_workflow`.

### backend: pytest current file

Runs `pytest` on the file that is currently open and focused in the editor.
Make sure the test file is the active tab before launching this config.

### backend: pytest all (with coverage)

Runs the full core + premium + enterprise test suite with coverage, writing an
XML report to `html_coverage/cov.xml`.

> `-n=auto` parallelises execution across all CPU cores, which significantly
> reduces wall-clock time but **disables Debugpy breakpoints**. Remove that
> flag from `.zed/debug.json` if you need to step through code during a full
> run.

## Interpreter path

All launch configs expect the virtualenv at `.venv/bin/python` (created by
`just b init`). If your interpreter lives elsewhere, update the `python` field
in `.zed/debug.json`.

## See also

- `docs/development/debugging.md` — `snoop`, `django-silk`, `flower`, etc.
- `docs/development/vscode-setup.md` — equivalent VSCode setup
- `docs/development/running-tests.md` — full test command reference
Loading