mirror of
https://github.com/penpot/penpot.git
synced 2026-08-01 19:06:18 +00:00
✨ Allow stopping ws0 independently of other workspaces
Remove the guard in stop-devenv that refused to stop ws0 while any ws1+ instance was running. Each workspace is now fully independent and can be started/stopped in any order. Shared infra shuts down only when no instances remain running. Updated docs (devenv.md, agentic-devenv.md) and devenv memory to reflect the new behavior. AI-assisted-by: mimo-v2.5-pro
This commit is contained in:
parent
5ad0ff752e
commit
32520e66e5
@ -25,7 +25,9 @@ Compose-based dev environment under `docker/devenv/`, driven by `manage.sh`. Par
|
||||
|
||||
## Worker policy
|
||||
|
||||
Backend workers run only on ws0. `_env` gates `enable-backend-worker` on `PENPOT_BACKEND_WORKER`; ws1+ inject it as false. ws0 must be running whenever any ws1+ is running, and is the last instance to stop — `run-devenv --agentic --ws N` (N≥1) auto-starts ws0 first; `stop-devenv` refuses to stop ws0 while any ws1+ is up. Workers are pure fire-and-forget: `wrk/submit!` inserts a row into the shared Postgres `task` table and returns; RPC handlers never wait on completion and workers never publish to msgbus. The reason for "ws0 only" is avoiding multi-instance worker races (cron dedup is best-effort across instances, `wrk/submit!` `dedupe` is racy across submitters); details in `mem:prod-infra/core`.
|
||||
Backend workers run only on ws0. `_env` gates `enable-backend-worker` on `PENPOT_BACKEND_WORKER`; ws1+ inject it as false. Workers are pure fire-and-forget: `wrk/submit!` inserts a row into the shared Postgres `task` table and returns; RPC handlers never wait on completion and workers never publish to msgbus. The reason for "ws0 only" is avoiding multi-instance worker races (cron dedup is best-effort across instances, `wrk/submit!` `dedupe` is racy across submitters); details in `mem:prod-infra/core`.
|
||||
|
||||
Each workspace is independent and can be started/stopped in any order. Shared infra (postgres, minio, etc.) is shut down only when no instances remain running.
|
||||
|
||||
## Port layout
|
||||
|
||||
@ -63,8 +65,8 @@ No `--delete` on the working-tree pass: gitignored caches in the workspace survi
|
||||
|
||||
## CLI surface
|
||||
|
||||
- `run-devenv --agentic [--ws main|0|wsN|N] [--sync] [--serena-context CTX]`: bring one instance up. Agentic only — MCP and Serena windows are always created. Default target main. Errors out if the target is already running. `--sync` is rejected on main; on ws1+ it's optional (forced only when the workspace dir does not exist yet). Auto-starts ws0 first when the target is ws1+ and ws0 is not yet up.
|
||||
- `stop-devenv [--ws main|0|wsN|N] [--all]`: stop instances. Flags mutually exclusive. `--ws N` (N≥1) stops just that workspace. `--ws 0` or no flag stops ws0 + shared infra, refused while any ws1+ is running. `--all` stops every ws highest-first then ws0, then infra.
|
||||
- `run-devenv --agentic [--ws main|0|wsN|N] [--sync] [--serena-context CTX]`: bring one instance up. Agentic only — MCP and Serena windows are always created. Default target main. Errors out if the target is already running. `--sync` is rejected on main; on ws1+ it's optional (forced only when the workspace dir does not exist yet).
|
||||
- `stop-devenv [--ws main|0|wsN|N] [--all]`: stop instances. Flags mutually exclusive. `--ws N` stops just that workspace. `--ws 0` or no flag stops ws0; shared infra shuts down only if no other instances remain. `--all` stops every ws highest-first then ws0, then infra.
|
||||
- `run-devenv`: legacy alias, ws0 non-agentic attached.
|
||||
- `attach-devenv [--ws main|0|wsN|N]`: pure attach. Fails fast if instance/session missing.
|
||||
- `run-devenv-shell [--instance 0|wsN|N] [cmd...]`: bash in target instance. (`--instance` flag not yet renamed to `--ws`.)
|
||||
|
||||
@ -100,7 +100,7 @@ RUN set -eux; \
|
||||
|
||||
FROM base AS setup-opencode
|
||||
|
||||
ENV OPENCODE_VERSION=1.18.4
|
||||
ENV OPENCODE_VERSION=1.18.11
|
||||
|
||||
RUN set -ex; \
|
||||
ARCH="$(dpkg --print-architecture)"; \
|
||||
@ -160,7 +160,7 @@ RUN set -eux; \
|
||||
FROM base AS setup-jvm
|
||||
|
||||
# https://clojure.org/releases/tools
|
||||
ENV CLOJURE_VERSION=1.12.5.1654
|
||||
ENV CLOJURE_VERSION=1.12.5.1664
|
||||
|
||||
RUN set -eux; \
|
||||
ARCH="$(dpkg --print-architecture)"; \
|
||||
@ -242,12 +242,12 @@ RUN set -eux; \
|
||||
|
||||
FROM base AS setup-utils
|
||||
|
||||
ENV CLJKONDO_VERSION=2026.05.25 \
|
||||
BABASHKA_VERSION=1.12.218 \
|
||||
CLJFMT_VERSION=0.16.4 \
|
||||
PIXI_VERSION=0.67.2 \
|
||||
GITHUB_CLI_VERSION=2.96.0 \
|
||||
UV_VERSION=0.11.9 \
|
||||
ENV CLJKONDO_VERSION=2026.07.24 \
|
||||
BABASHKA_VERSION=1.13.219 \
|
||||
CLJFMT_VERSION=0.16.5 \
|
||||
PIXI_VERSION=0.75.0 \
|
||||
GITHUB_CLI_VERSION=2.97.0 \
|
||||
UV_VERSION=0.12.1 \
|
||||
UV_TOOL_DIR=/opt/uv/tools \
|
||||
UV_TOOL_BIN_DIR=/opt/utils/bin \
|
||||
UV_PYTHON_INSTALL_DIR=/opt/uv/python \
|
||||
|
||||
@ -55,7 +55,7 @@ Serena, Playwright) and supports a launcher that wires them into your AI client.
|
||||
for Penpot development (see below for details).
|
||||
|
||||
6. **Shut down workspaces** with `./manage.sh stop-devenv`, either one by one or all at once.
|
||||
You cannot shut down `ws0` if any other workspace is still running, since it's the worker-bearer.
|
||||
Each workspace is independent and can be stopped in any order.
|
||||
Shared infrastructure will be cleaned up when the last workspace is stopped.
|
||||
|
||||
Optional: watch Serena's activity in its dashboard
|
||||
@ -153,8 +153,8 @@ automatically, so regular users never run this.
|
||||
|
||||
Brings one agentic instance up. Errors out if the target is already running.
|
||||
|
||||
`--ws N` (N ≥ 1) auto-starts ws0 first if it is not already up - ws0 is the
|
||||
worker-bearer and must be running whenever any wsN is. Per-instance ports
|
||||
`--ws N` (N ≥ 1) brings that workspace up independently — workspaces can be
|
||||
started and stopped in any order. Per-instance ports
|
||||
are offset by `10000 × N` (ws1's MCP at `http://localhost:14401/mcp`, Serena
|
||||
MCP at `http://localhost:24181`, Serena dashboard at
|
||||
`http://localhost:24182`, etc.). `manage.sh` prints the full URL set on
|
||||
|
||||
@ -69,13 +69,12 @@ The devenv runs as separate compose projects:
|
||||
(default `~/.penpot/penpot_workspaces/`). You can explicitly sync them
|
||||
with the `--sync` flag (automatic on first start).
|
||||
|
||||
Each call to `run-devenv` brings up one instance, and ws0 is always
|
||||
running whenever any ws1+ is — `--ws N` (N≥1) auto-starts ws0 first if it
|
||||
isn't already up:
|
||||
Each call to `run-devenv` brings up one instance. Workspaces are independent
|
||||
and can be started and stopped in any order:
|
||||
|
||||
```bash
|
||||
./manage.sh run-devenv # main (ws0)
|
||||
./manage.sh run-devenv --ws 1 # ws0 if needed, then ws1
|
||||
./manage.sh run-devenv --ws 1 # ws1
|
||||
./manage.sh run-devenv --ws 2 --sync # ws2, re-seeding from the live repo
|
||||
```
|
||||
|
||||
@ -91,12 +90,12 @@ the frontend's MCP flag) is copied into each workspace on its initial sync
|
||||
only. After that the developer maintains it in each workspace; subsequent
|
||||
`--sync` runs leave the workspace copy alone.
|
||||
|
||||
Stopping mirrors the start invariant — ws0 is the last to stop, and shared
|
||||
infra stops with it:
|
||||
Stopping is equally flexible — each workspace is independent. Shared infra
|
||||
stops only when no instances remain running:
|
||||
|
||||
```bash
|
||||
./manage.sh stop-devenv --ws 1 # stops ws1; ws0 + infra stay up
|
||||
./manage.sh stop-devenv # stops ws0 + infra; errors if ws1+ still running
|
||||
./manage.sh stop-devenv # stops ws0; infra stays up if ws1+ still running
|
||||
./manage.sh stop-devenv --all # stops every ws1+ first, then ws0 + infra
|
||||
```
|
||||
|
||||
@ -150,12 +149,14 @@ file-summary cache, rate-limit counters) isolated.
|
||||
Background workers (`enable-backend-worker`) run only on ws0 — ws1+ overlays
|
||||
disable it. ws1+ RPC handlers still enqueue tasks into the shared Postgres
|
||||
`task` table; ws0's dispatcher claims them via `FOR UPDATE SKIP LOCKED` and
|
||||
runs them against the shared DB and MinIO. The "ws0 always up when ws1+ is
|
||||
up" invariant exists for this reason: it keeps a single worker-bearer and
|
||||
avoids the multi-instance cron-dedup race (the lock on `scheduled_task` is
|
||||
released when the task body finishes, so two cron timers firing the same
|
||||
scheduled instant with a gap larger than the body's runtime can both
|
||||
execute it).
|
||||
runs them against the shared DB and MinIO. Workers are fire-and-forget:
|
||||
`wrk/submit!` inserts a row and returns; RPC handlers never wait on
|
||||
completion. The "ws0 only" policy avoids multi-instance worker races (cron
|
||||
dedup is best-effort across instances, `wrk/submit!` `dedupe` is racy across
|
||||
submitters).
|
||||
|
||||
Each workspace is independent and can be started and stopped in any order.
|
||||
Shared infrastructure shuts down only when no instances remain running.
|
||||
|
||||
### Upgrading from a pre-parallel devenv
|
||||
|
||||
|
||||
37
manage.sh
37
manage.sh
@ -511,11 +511,12 @@ function create-devenv {
|
||||
instance-compose ws0 create
|
||||
}
|
||||
|
||||
# Stop instances. ws0 is the worker-bearer and must be the last one to stop;
|
||||
# shared infra is shut down together with ws0. Flags are mutually exclusive.
|
||||
# Stop instances. Each workspace is independent and can be stopped in any
|
||||
# order. Shared infra is shut down only when no instances remain running.
|
||||
# Flags are mutually exclusive.
|
||||
#
|
||||
# --ws N (N>=1) stop just that workspace. Leaves ws0 and infra alone.
|
||||
# --ws 0 | (no flag) stop ws0 + shared infra. Refused if any ws1+ is running.
|
||||
# --ws 0 | (no flag) stop ws0; shuts down shared infra only if no ws1+ is running.
|
||||
# --all stop every wsN highest-first, then ws0, then infra.
|
||||
function stop-devenv {
|
||||
local target=""
|
||||
@ -555,21 +556,19 @@ function stop-devenv {
|
||||
[[ -z "$target" ]] && target="ws0"
|
||||
|
||||
if [[ "$target" == "ws0" ]]; then
|
||||
local non_main=""
|
||||
for ws in $running; do
|
||||
[[ "$ws" != "ws0" ]] && non_main="$non_main $ws"
|
||||
done
|
||||
if [[ -n "$non_main" ]]; then
|
||||
echo "stop-devenv: cannot stop ws0 while other instances are running:${non_main}." >&2
|
||||
echo "Stop them first (--ws N) or use --all." >&2
|
||||
return 1
|
||||
fi
|
||||
if printf '%s\n' $running | grep -qx ws0; then
|
||||
stop-instance ws0
|
||||
else
|
||||
echo "[ws0] not running."
|
||||
fi
|
||||
infra-compose down -t 2
|
||||
# Only stop shared infra when no other instances are still running.
|
||||
local remaining=""
|
||||
for ws in $(list-running-instances); do
|
||||
[[ "$ws" != "ws0" ]] && remaining="$remaining $ws"
|
||||
done
|
||||
if [[ -z "$remaining" ]]; then
|
||||
infra-compose down -t 2
|
||||
fi
|
||||
return 0
|
||||
fi
|
||||
|
||||
@ -1346,14 +1345,14 @@ function usage {
|
||||
echo " honouring per-repo local overrides; see"
|
||||
echo " devenv.md > 'Git identity inside the container')."
|
||||
echo "- create-devenv Create ws0 + shared-infra compose services without starting them."
|
||||
echo "- stop-devenv Stop one or more workspaces. Shared infra stops with the last one."
|
||||
echo " Options: --ws N (stop wsN, N >= 1) | (no flag) (stop ws0 + infra;"
|
||||
echo " refused if any wsN is still running) | --all (stop every wsN"
|
||||
echo " highest first, then ws0 + infra)."
|
||||
echo "- stop-devenv Stop one or more workspaces. Shared infra stops when no instances remain."
|
||||
echo " Options: --ws N (stop wsN) | (no flag) (stop ws0; shared infra only"
|
||||
echo " if no other ws is running) | --all (stop every wsN highest"
|
||||
echo " first, then ws0 + infra)."
|
||||
echo "- drop-devenv Same CLI and invariants as stop-devenv (see above), plus removal of"
|
||||
echo " the shared devenv image on full teardowns (no flag, --ws 0, or --all)."
|
||||
echo " Refused if any wsN (N >= 1) is still running. A single --ws N (N >= 1)"
|
||||
echo " keeps the image since other workspaces still need it."
|
||||
echo " A single --ws N (N >= 1) keeps the image since other workspaces still"
|
||||
echo " need it."
|
||||
echo "- log-devenv Tail a workspace's compose logs."
|
||||
echo " Options: --ws N (default: 0)."
|
||||
echo ""
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user