From 0524ce7751bcf083eaae95baba8eb0b012a08a18 Mon Sep 17 00:00:00 2001 From: "benjamin.baker" Date: Wed, 2 Sep 2026 05:27:01 -0400 Subject: [PATCH] add config-driven channel label and dev-workstation bootstrap A bleeding-edge container running next to a stable one on the same dev box is easy to confuse, and a branch-only badge would force perpetual rebase/cherry-pick drift between main and dev-be. Instead the badge is config-driven: the settings endpoint injects a synthetic env_label from SHOPDB_ENV_LABEL, the sidebar renders a red DEV tag only when it is non-empty, and stable simply leaves it unset. Same code on both channels, no divergence. dev-bootstrap.ps1 makes a fresh Windows box turnkey: it checks git/Docker (winget-installs with a prompt), verifies the engine is actually running, then builds and starts an isolated per-channel stack so stable and edge coexist on distinct ports, projects, and volumes. docker-compose.channel.yml is a thin overlay so the base compose file stays channel-agnostic. --- docker-compose.channel.yml | 27 +++ frontend/src/utils/siteSettings.js | 8 + frontend/src/views/AppLayout.vue | 22 ++- scripts/dev-bootstrap.ps1 | 274 +++++++++++++++++++++++++++++ shopdb/core/api/settings.py | 48 ++++- 5 files changed, 377 insertions(+), 2 deletions(-) create mode 100644 docker-compose.channel.yml create mode 100644 scripts/dev-bootstrap.ps1 diff --git a/docker-compose.channel.yml b/docker-compose.channel.yml new file mode 100644 index 00000000..2f16b22e --- /dev/null +++ b/docker-compose.channel.yml @@ -0,0 +1,27 @@ +# Channel overlay for side-by-side stable / bleeding-edge stacks. +# +# The base docker-compose.yml is channel-agnostic. This overlay adds only the +# pieces that differ between a stable (main) and an edge (dev-be) stack so the +# two can run at once on one dev workstation without colliding: +# +# - SHOPDB_ENV_LABEL is passed into the api container. When non-empty the +# public settings endpoint surfaces it as env_label and the sidebar renders +# a red DEV badge. Stable leaves it unset, so nothing renders. +# - Ports fall back to the SAME defaults as the base file, so running this +# overlay alone changes nothing; the bootstrap script overrides API_PORT / +# MYSQL_PORT for the edge stack so both channels bind distinct host ports. +# +# The stacks are isolated by compose project name (-p shopdb-stable / +# -p shopdb-edge), which namespaces containers, networks, and the named +# volumes, so each channel keeps its own database and instance state. +# +# Usage (driven by scripts/dev-bootstrap.ps1, shown here for reference): +# docker compose -p shopdb-edge \ +# -f docker-compose.yml -f docker-compose.channel.yml up -d + +services: + api: + environment: + # Empty on stable. The edge stack sets SHOPDB_ENV_LABEL=DEV in its .env + # (written by the bootstrap script) to light up the badge. + SHOPDB_ENV_LABEL: ${SHOPDB_ENV_LABEL:-} diff --git a/frontend/src/utils/siteSettings.js b/frontend/src/utils/siteSettings.js index 7edf5914..87333a77 100644 --- a/frontend/src/utils/siteSettings.js +++ b/frontend/src/utils/siteSettings.js @@ -37,6 +37,14 @@ export async function getFacilityName() { return getSetting('facility_name', 'ShopDB') } +// Environment channel label (e.g. 'DEV') injected by the backend from +// SHOPDB_ENV_LABEL. Empty on stable/main deployments, which renders no badge. +// Drives the red DEV tag in the sidebar so a bleeding-edge container is +// obviously distinct from a stable one running side by side. +export async function getEnvLabel() { + return getSetting('env_label', '') +} + // Main site logo (sidebar, login, dashboard header). Fallback = shipped GE mark. export async function getSiteLogo() { return withBase(await getSetting('site_logo', '/ge-aerospace-logo.svg')) diff --git a/frontend/src/views/AppLayout.vue b/frontend/src/views/AppLayout.vue index dfe40089..907a8ddc 100644 --- a/frontend/src/views/AppLayout.vue +++ b/frontend/src/views/AppLayout.vue @@ -4,6 +4,9 @@