mirror of
https://github.com/Studio-Saelix/sencho.git
synced 2026-07-27 04:11:01 +00:00
52ff0725f414fdebebd5cd18c8ba044211b68e0c
6 Commits
| Author | SHA1 | Message | Date | |
|---|---|---|---|---|
|
|
d369b03a38 |
feat: detect stalled stack updates and add in-app recovery actions (#1347)
* feat: detect stalled stack updates and add in-app recovery actions Add a backend idle-output backstop that stops a deploy/update compose step that has gone silent (SENCHO_COMPOSE_STALL_TIMEOUT_MS, default 10m), so a hung image pull surfaces a fast failure instead of spinning indefinitely. Surface failed, timed-out, and stalled operations with recovery actions on the stack page: a desktop chip plus popover menu and an inline mobile card offering retry, restart, roll back (when a backup exists), refresh state, and copy diagnostics, all gated by deploy permission. The streaming deploy/update progress modal is now on by default and warns when output goes quiet. Container state is refreshed after a failed or stalled operation, and the UI never sits in an indefinite spinner. * fix: harden rollback against policy-blocked file mutation and refine recovery Address review findings on the stalled-update recovery work: - The rollback route restored backup files before running the policy gate, so a policy-blocked rollback could leave the on-disk config rolled back while the deployed containers were unchanged. Snapshot the current files first and revert them when the gate blocks; if that revert itself fails, escalate it on the persistent alert feed since the 409 is already sent. - Refresh container state after a successful manual rollback (rollback redeploys), without mis-recording a refetch failure as a rollback failure. - Suppress the stalled-output warning once live progress is unavailable. * test: mock snapshotStackFiles in the atomic-deploy rollback route tests The rollback route now snapshots stack files before restoring a backup, so its FileSystemService mock needs snapshotStackFiles. Without it the mocked call threw and the route returned 500, failing the success-path rollback assertions. |
||
|
|
ce08a593d7 |
feat(settings): reorganize the settings hub into domain groups (#1321)
* refactor(settings): split System Limits and regroup the hub System Limits had grown into a grab-bag of host alert thresholds, Docker cleanup, and mesh data-plane controls under one mislabeled section. Split it into Host Alerts, Docker & Storage, and Fleet Mesh, and split Developer into Developer Diagnostics and Data Retention. Reorganize the sidebar into ten domain groups: Personal, Access, Infrastructure, Monitoring, Notifications, Automation, Organization, Security, Operations, Help. Each section now saves only its own keys, so a concurrent edit in one section no longer clobbers another. Data Retention sends the audit-log window only on a paid plan, matching the field's existing visibility, so a Community save no longer fails on a key the operator cannot set. NumberChip moves to a shared module and the toggle reuses the existing shared component. The /settings API is unchanged. * test(settings): cover registry structure and per-section save payloads Add structural invariants for the ten-group registry (every item maps to a real group, ids are unique, the System Limits and Developer splits land in the right groups with the right gates, renamed labels and the Registries paid gate hold) and per-section payload tests asserting each split section patches only its own keys, including the Community path where Data Retention omits the paid audit-log key. * docs(settings): document the regrouped settings hub Rewrite the settings reference for the ten-group layout, replace the System Limits page with Host Alerts, Docker & Storage, and Fleet Mesh, and document the prune-on-update, reclaimable-space banner, and mesh auto-recreate settings that were previously undocumented. Update the Settings navigation breadcrumbs across the feature docs and refresh the affected screenshots. * fix(settings): show Access sections as instance-global, not operator-scoped License, Users, SSO, and API Tokens are instance-global settings but the masthead scope label rendered them as operator-scoped because it keyed off the old Identity group. Only Personal sections (account, appearance) are operator/browser-scoped now; everything else reads as global. Also add a compile-time exhaustiveness guard to the section switch so a future SectionId added without a matching case fails the build instead of silently rendering a blank panel. * docs(settings): remap remaining settings breadcrumbs to the new groups Update the navigation breadcrumbs that still pointed at the removed Identity, Alerts, and Advanced groups: API Tokens and Users now sit under Access, Webhooks under Automation, Labels under Organization, App Store under Infrastructure, Appearance under Personal, and scan policies under Security > Vulnerability Scanning. Correct the settings reference scope note so Access reads as global. * docs(settings): remap renamed-section breadcrumbs across feature docs Sweep every feature, operations, getting-started, and reference page for navigation paths that still named the renamed settings sections, and point them at the current ones: Security becomes Security > Vulnerability Scanning, Notifications becomes Notifications > Channels, Routing becomes Notifications > Notification Routing, and Developer becomes Operations > Developer Diagnostics (with its retention windows under Operations > Data Retention). App Store moves under Infrastructure and the four-group overview in the getting-started intro is rewritten to the ten groups. Separators each page already used are preserved. |
||
|
|
5dea040ec8 |
fix(deploy-progress): decouple deploys from the live progress stream (#1246)
* fix(deploy-progress): decouple deploys from the live progress stream The deploy progress modal streamed compose output over a WebSocket, but the deploy itself was coupled to that socket in two ways that could break or silently abort a deploy: - The deploy request was gated on the progress socket connecting, so any upgrade failure (a reverse proxy blocking WebSocket upgrades, or the admin-only stream rejecting a scoped deployer) left the modal stuck on "Connecting..." and the deploy never fired. - The backend terminated the running compose process when that socket closed, so minimizing the modal, navigating away, or a network blip aborted an in-flight deploy. Make the progress socket output-only: the deploy is owned by its request and runs to completion (or the existing command timeout) regardless of the stream. The modal now degrades to a "Live progress unavailable" state and still reports success or failure from the request result. Connect failures, drops, and a connect timeout all release the deploy instead of blocking it. Also route progress output per deploy: the frontend sends a correlation id on both the connectTerminal message and the deploy request header, and the backend keys progress sockets by that id so concurrent deploys from different tabs or users no longer cross-stream each other's output. Cap the in-memory parsed log rows so a very long deploy cannot grow the modal's state unbounded. * fix(deploy-progress): generate the deploy session id with a CSPRNG The per-deploy correlation id keys which WebSocket receives a deploy's live output, so a guessable id lets one authenticated client register a victim's id and read its compose output. It was built from Math.random() plus a timestamp, which is not cryptographically secure. Generate it with crypto.getRandomValues (128 bits, hex). That is the one Crypto member available in insecure contexts, so it still works over LAN HTTP where crypto.randomUUID is unavailable. * fix(deploy-progress): stop headerless ops bleeding into a keyed progress modal Address review findings on the progress-stream routing: - Only an id-less connectTerminal registration may become the id-less fallback socket. Previously every connectTerminal (including keyed deploy modals) set the fallback, so a headerless operation (bulk update, rollback, or a legacy client) resolved via getTerminalWs() into another user's keyed deploy modal. Keyed sockets are now excluded from the fallback, and a socket that adopts a session id is removed from it. - The connect-timeout fallback now also flags the modal as "Live progress unavailable" instead of leaving it on "Connecting..." while the deploy runs. - Log only a short prefix of the deploy session id in developer diagnostics, not the full capability value. |
||
|
|
5f7a887ed6 |
docs: reorganize navigation for feature discoverability (#1147)
Restructures the Documentation tab so each group answers one operator question. - Split the 12-page "Stacks & Deployments" into Stacks (per-stack work) and Deployment (the act of deploying); promote Resources Hub to a standalone item. - Dissolve the 2-page "Platform" junk drawer: Sidebar moves to Stacks, Host Console moves to Fleet. - Rename "Fleet & Multi-Node" to "Fleet"; absorb Node Compatibility from Reference. Move Scheduled Operations from Fleet to Automation (now a 4-page group covering Scheduled Ops, Auto-Update, Auto-Heal, Webhooks). - Clean up the Reference tab: drop misplaced node-compatibility, move root-level security.mdx into reference/, delete the orphan reference/verifying-images.mdx after porting its Available Tags table into operations/verifying-images.mdx. - Reorder top-level groups: Operations moves above Reference. - Rename two misleading page titles: "Deploy Progress Modal" becomes "Deploy Progress" (drops the UI implementation leak); "Auto-Update Readiness" becomes "Auto-Update Policies" (matches filename and sibling "Auto-Heal Policies"). Verified: docs.json parses as valid JSON, 59 disk .mdx files match 59 nav entries with zero orphans and zero broken refs. |
||
|
|
0be479100c |
docs: v1 docs refresh (#966)
* docs(introduction): rewrite intro page and refresh screenshots
Rewrite the Getting Started introduction to reflect the current product:
adds the Mesh, Blueprints, Pilot, Fleet, Resources concepts up front;
restructures capability sections around Stacks, Fleet (now including
Fleet Actions), Mesh, Blueprints, Monitoring, Resources, Security,
Automation, and Pilot/Remote ops; cross-links every claim to the
matching feature page.
Replaces the dashboard hero shot with a fresh capture against the
redesigned cockpit chrome and adds three inline shots (running stack
with anatomy and logs, fleet command deck, resources hub with
reclaim header). All screenshots taken at 1920x900, dark theme,
with node names, usernames, IPs, and home paths neutralized.
Drops outdated claims: stale "190+ templates" count, the
"viewer accounts" RBAC summary, and the "atomic" deployment label
that did not match the actual rollback mechanism.
* docs(introduction): add Federation and Fleet Secrets
Federation has shipped (Admiral) with cordon and pin policy as
operator overrides on the blueprint reconciler. Fleet Secrets is
landing as a Skipper+ tab for versioned env-var bundles encrypted
at rest, with diff preview and target push.
Mirror those in the Run-one-machine-or-many bullet list and in the
Tiers paragraph so the introduction matches the current product.
* docs(introduction): re-shoot screenshots against v0.72.0 production
Re-capture all four introduction screenshots from the upgraded
production node so the fleet view shows the current full tab strip
(Overview / Snapshots / Status / Deployments / Traffic / Federation
/ Fleet Actions / Secrets) instead of the older Overview / Snapshots
/ Status only. Same 1920x900 dark-theme capture and the same PII
scrub applied (node names, usernames, IPs, home paths neutralized).
* docs(quickstart): rewrite around v0.72.0 cockpit and add screenshots
Replaces the bare install snippet with a five-minute walkthrough that
matches the redesigned UI. Leads with a docker-compose.yml block (the
bare docker run command is collapsed in an Accordion), keeps the 1:1
path rule, and adds two new sections that show the user what happens
on first boot.
Adds two screenshots at 1920x900 dark theme:
- setup-cold-start.png: the Cold start card with Username, Password,
Confirm password fields, and the Initialize console button.
- dashboard.png: the post-sign-in dashboard captured against v0.72.0
with the full top nav (Home, Fleet, Resources, App Store, Logs,
Auto-Update, Console, Audit, Schedules) and the populated Stack
health table sorted by load.
Where-to-next now uses CardGroup cols=2 to match the introduction
page's pattern.
* docs(configuration): align env var reference with current backend
Bring docs/getting-started/configuration.mdx up to date with the
v0.72.0 backend:
- Remove PORT from the optional env vars table. The listen port is
hardcoded to 1852 in backend/src/helpers/constants.ts and is never
read from the environment. Replace it with a Listen port section
that explains the fixed port and host-port remapping.
- Document API_RATE_LIMIT (default 200) and API_POLLING_RATE_LIMIT
(default 300), both applied in production only.
- Note the /app/compose fallback default for COMPOSE_DIR while still
pointing readers at the 1:1 path rule.
- Point the SSO env var section at the new SSO Quickstart page and
keep the SSO feature reference as the deeper dive.
- Tighten First boot and cross-link to Quickstart so the screenshot
is not duplicated.
- Add a Where to next CardGroup matching the refreshed Introduction
and Quickstart pages.
Drop stale PORT=1852 and JWT_SECRET=your-secure-jwt-secret-here
lines from .env.example so the example no longer contradicts the
docs (PORT is hardcoded, JWT_SECRET is auto-generated and persisted
to the database during initial setup).
* docs(configuration): replace em-dash-substitute hyphens in prose
Three sentences used ` - ` (space-hyphen-space) as an em-dash
substitute. Replaced with the punctuation that fits each case:
- "How Sencho organizes your compose directory": semicolon between
the two related clauses.
- Data directory Warning: parentheses around the parenthetical
insertion.
- 1:1 path rule explanation: comma before the contrastive clause.
Heading slugs and YAML code-block comments are unchanged.
* docs(sso): refresh setup guide and drop misleading "one-click" wording
Brings the SSO Setup Guide in line with how SSO actually works in the
current build, and corrects misleading copy across both SSO docs pages.
- Setup Guide: explains the env-var-seeds-once / DB-is-authoritative
config model up front, replacing per-section "Restart Sencho"
wording that implied a restart was always required.
- Setup Guide: promotes the per-provider Test Connection button out
of the LDAP-only paragraph into a generic intro callout, and adds
a self-signed LDAPS tip.
- Setup Guide: notes that all OIDC providers accept a *_DISPLAY_NAME
override for the login button label, and adds a commented LDAP TLS
toggle to the full compose example.
- Setup Guide: adds two screenshots of the redesigned Settings > SSO
panel (overview + LDAP card expanded with form).
- Both pages: replaces "one-click presets" / "one-click configuration"
with "preset providers". The Skipper-tier presets still require an
OAuth app provisioned in the provider's console; what they actually
buy is provider-aware defaults and a branded login button. The old
wording overpromised.
* docs(features-overview): regroup catalog and add 17 missing features
Restructure the Features Overview into the same six groups the docs
sidebar uses (Stacks & Deployments, Observability, Fleet & Multi-Node,
Security & Identity, Automation, Platform) plus a short Reference tail.
Add catalog entries for 17 shipped features that the previous overview
never mentioned: Stack Activity, Stack File Explorer, Deploy Progress,
Deploy Enforcement, Blueprints, Git Sources, Global Search, Pilot Agent,
Sencho Mesh, Fleet Federation, Fleet Actions, Fleet Sync, Fleet Secrets,
Two-Factor Authentication, CVE Suppressions, Auto-Heal Policies, Stack
Sidebar.
Fix two factual inaccuracies:
- Fleet View blurb wrongly gated search, sort, filter, and stack
drill-down behind Skipper. The deep-dive is explicit that those are
available on every tier; only the bulk Update All action inside the
Node Updates modal is paid.
- Auto-update entry was titled and described as a scheduling system.
The deep-dive page is the Auto-Update Readiness board (risk tags,
changelog previews, rollback targets); the scheduler lives under
Scheduled Operations.
Add three hero screenshots captured from production at 1920x900,
illustrating the redesigned cockpit visual language: Home dashboard,
stack anatomy, and fleet topology.
* docs(stack-management): refresh page around v0.72.0 cockpit and add screenshots
Updates the Stack Management page to match the current UI: sidebar with
filter chips and label groups, bulk mode, restructured kebab menu,
two-tab anatomy panel, and three-source New stack dialog (Empty, From
Git, From Docker Run).
Adds sections for Filter chips, Pinned and label groups, and Bulk mode.
Restructures the Stack context menu around the inspect, organize,
lifecycle, and destructive groups with their keyboard shortcuts.
Documents the From Git tab and cross-links Git Sources for the full
sync flow.
Replaces every existing screenshot with fresh captures from the current
UI and adds eight new captures for the new sections. Cross-links Stack
Activity, Stack Labels, Stack File Explorer, Compose Editor, Atomic
Deployments, Scheduled Operations, Auto-Heal Policies, Auto-Update
Policies, and Alerts and Notifications for features documented on
their own pages.
* docs(stack-activity): refresh page around v1 cockpit and recapture screenshots
Realign the page with the current Anatomy panel tab strip and the
StackActivityTimeline component:
- Frame the Activity tab as a sibling of Anatomy under the right-hand
panel, with files/edit actions belonging to the strip.
- Expand the category guidance: list the five iconized categories and
call out that other stack-scoped notifications (deploy failure,
available image updates, auto-heal triggers, monitor alerts, scan
findings) flow into the timeline with a generic icon.
- Tighten the actor-attribution rule to match the component: omitted
for events without an actor and for system-driven events.
- Add the day-format example to the relative-time row.
- Recapture both screenshots from a populated stack (Today + Yesterday
+ Earlier with three distinct icons) and an empty stack.
- Convert troubleshooting blurbs to H3 for anchor links and consistency
with the v1-refresh sibling pages.
* docs(stack-activity): wrap troubleshooting entries in Accordion blocks
Match the foldable troubleshooting pattern established by
docs/features/deploy-progress.mdx so the page stays compact and
readers can scan to their issue. This is the canonical formatting
for the /features section's troubleshooting blurbs going forward.
* docs(editor): refresh page around v1 cockpit and recapture screenshots
Rewrites the page around the dual-mode right panel (Anatomy by default,
Monaco when the user clicks edit), the redesigned Command Center action
bar, the new container row layout with status badges and live stats, the
Structured / Raw terminal logs toggle, the Git Source toolbar button, and
the opt-in diff preview. Drops the obsolete persistent embedded terminal
section. Preserves the #diff-preview-before-save and #log-viewer anchors
referenced from settings.mdx and global-observability.mdx. Replaces
editor-overview.png and container-exec-modal.png with fresh captures
against v0.72.0 production at 1920x900 dark theme; renames container
-actions.png to containers-list.png; adds command-center.png and
editor-edit-mode.png. PII scrubbed (host paths normalized) and the
compose-diff-preview/diff-modal.png shared asset is left untouched after
visual diff against the live UI showed no chrome change.
* docs(features): wrap troubleshooting accordions in AccordionGroup
Wraps the loose <Accordion> blocks in editor.mdx and stack-activity.mdx
in a single <AccordionGroup> to match the troubleshooting design used
by fleet-federation.mdx. Structural only; no content changes.
* docs(stack-file-explorer): refresh page around v1 explorer and add screenshots
Full rewrite to match the live two-pane Files tab. Replaces the false
'Edit' toolbar flow with the read-only chip + always-on Save model,
fixes the protected-files list (5 names) and dedicated-tab redirect
list (3 names), drops the fabricated 100 MB download cap, and corrects
the upload claim to single file at a time.
Adds sections for New File, Rename, Permissions, the type-to-confirm
protected-file delete flow, the non-empty folder delete confirmation,
the 500-entry tree display cap, and the symlink rendering. Restructures
troubleshooting around <AccordionGroup> + <Accordion> to match
fleet-federation.mdx, and adds two new entries (display cap, 403 on
Community admin write).
Ships nine screenshots captured against v0.72.0 production at 1920x900
in dark theme: overview, two-pane layout, protected-tree-marker,
viewer-edit-mode, new-file-dialog, context-menu-folder, context-menu-file,
permissions-dialog, delete-protected-confirm.
* docs(deploy-progress): rewrite around current modal + capture v1 screenshots
Aligns the page with the v0.72.0 implementation and standardizes the
troubleshooting layout with the rest of the docs refresh.
Setting and gating
- Renames the Settings field to "Deploy progress modal" and quotes the
current helper text verbatim. Documents that the toggle is off by
default, lives under Settings > Appearance > Display, is stored in
localStorage, and syncs across tabs in the same browser.
Modal anatomy
- Names every visible UI string: header verbs, status indicator (with
the "closes in <n>s" countdown that was previously undocumented),
empty-body strings, footer toggle that flips between "Raw output" and
"Hide raw", and the destructive border on ERR rows vs the softer warn
tint on WARN rows.
- Replaces the vague "after a few seconds" with the actual 4-second
auto-close timer; documents hover-to-pause and the
leave-hover-restarts-the-countdown behavior.
- Documents the truncated error message in the failed-state header and
the manual close-only requirement.
- Notes that the pill is portal-mounted and survives navigation.
Stage badges
- Keeps the 9-badge table but adds an honest note that most lines render
as LOG because the badges are gated on Compose's "[+]" progress
prefix, which Compose only emits in TTY mode and Sencho spawns it
without one.
Entry points
- Splits the supported actions into the four that produce a populated
structured-log body (Deploy, Update, Install, Git Apply) and the two
that bypass compose and finish with 0 lines (Restart, Stop). Drops the
"Down" claim from the user-facing list since no UI control currently
triggers it; mentions the down route as an automation surface only.
Troubleshooting
- Wraps the existing accordions in an <AccordionGroup> matching the
pattern used by the editor and stack-activity refreshes. Adds two new
entries: one explaining the Restart/Stop "0 lines" outcome, one
explaining the LOG-everywhere case for non-TTY compose output.
Screenshots (six PNGs in docs/images/deploy-progress/, 1920x900, dark
theme, captured against the upgraded production node)
- setting-toggle.png: the Display section with the toggle enabled.
- modal-streaming.png: a real update in flight at 19s, 554 lines.
- modal-succeeded.png: succeeded state with the live closes-in
countdown visible.
- modal-raw-output.png: structured rows with the Raw output panel
expanded beneath.
- pill.png: minimized pill anchored bottom-center on a stack editor
view.
- modal-failed.png: failed state with the truncated error in the
header and ERR rows highlighted.
* docs(resources): refresh Resources Hub page for v1 redesign and feature additions
Rewrite the page to match the shipping UI and replace stale screenshots
with fresh captures of the redesigned chrome.
- Document the admin-only Reclaim hero and clarify the per-tile Sencho-only
vs. All Docker (includes external) split in Quick Clean.
- Add coverage of the Scan history toolbar button and the per-row severity
badge plus shield-icon scan dropdown in the Images tab; cross-link to the
vulnerability scanning page.
- Correct the Volumes column list (no Size column; size lives on the Largest
5 landing card) and call out admin gates on browse and delete.
- Spell out the List/Topology view-mode toggle and that Create Network is
admin-only and List-mode only.
- Rewrite the Unmanaged tab section around the project-grouped layout, the
Select all + Purge Selected (N) admin-only multi-select, and the empty
state copy.
- Replace screenshots: resources-reclaim, networks-list, create-network,
network-inspect, network-topology, network-topology-toggle. Add fresh
resources-volumes-tab and resources-unmanaged-tab captures.
* docs(app-store): refresh page around v1 deploy sheet, scan integration, and registry settings
Rewrites the App Store reference to match the current cockpit:
- Documents the weekly-rotated featured banner picked from the top-5 by GitHub stars and the star-descending grid sort.
- Adds the deploy-sheet structure (breadcrumb, meta line, About panel with Read more) and splits the Advanced tab into Ports, Volumes, Environment variables, Custom variables, and Security subsections.
- Documents the Trivy-gated Security checkbox, atomic vs non-atomic deploys by tier, and the rollback semantics driven by error class.
- Adds a Watching the deploy section linking to the deploy-progress modal.
- Rewrites the Custom registry section against the new two-panel settings layout (Default + Custom) with the URL validation rule and the using default / using custom hint.
- Adds a four-entry Accordion troubleshooting block in the house style.
- Replaces three screenshots and adds two (Advanced tab, Settings registry panel) captured against the production node.
Permissions wording aligns with current backend (admin only); the broader stack:create gate will land in a follow-up fix branch.
* docs(app-store): describe inline port-conflict messaging on deploy sheet
Update the deploy-sheet section to match the visible port-conflict
behavior: the Essentials tab surfaces a Port-conflict warning that
replaces the defaults hint when any default port is already bound, and
the Advanced tab shows an inline "in use by {stack}" message next to
the container port instead of a hover-only tooltip. Refresh the
screenshot alt-text and the troubleshooting Accordion to match.
* docs(app-store): align permissions note with stack:create gate
Pairs with the backend gate swap in fix/templates-deploy-rbac (#986)
which moves POST /api/templates/deploy from requireAdmin to
requirePermission('stack:create'). Updates the Note block under
'Watching the deploy' so the docs match the new behavior: admin and
node-admin can deploy templates from the App Store; viewer, deployer,
and auditor cannot.
|
||
|
|
dd9d33813b |
feat(deploy-logs): opt-in deploy progress modal with structured log rows (#779)
* feat(notifications): dispatch deploy_failure alert on stack action errors
* feat(terminal): add onReady and onMessage callback props
* feat(deploy-logs): add DeployLogContext with runWithLog API
* feat(deploy-logs): add DeployLogPanel bottom drawer with resize and minimize
* feat(deploy-logs): wire DeployLogContext to App and EditorLayout action runners
* test(deploy-logs): add E2E test for deploy log panel open, failure, and minimize
* docs(deploy-logs): add user-facing and internal architecture docs
* feat(deploy-logs): redesign as opt-in modal with structured log rows
Replace the full-width bottom drawer (DeployLogPanel) with a centered
modal that streams structured log output for deploy, stop, restart,
update, install, and Git apply operations. The modal is disabled by
default; users opt in from Settings -> Appearance.
Core changes:
- New DeployFeedbackContext with runWithLog() API: if opt-in is off,
silently bypasses the UI so all call sites degrade to the existing
toast behavior without code changes.
- composeLogParser.ts: pure parser that strips ANSI escapes and
classifies compose output into stage badges (PULL, BUILD, CREATE,
START, STOP, DOWN, WARN, ERR, LOG). 15 unit tests.
- StructuredLogRow.tsx: memoized row with timestamp, stage badge, and
message. Error rows get a rose left rail; warn rows get a tinted bg.
- DeployFeedbackModal: Dialog-based, max-w-640px/max-h-70vh, elapsed
timer, auto-close 4s on success (hover cancels), persistent on
failure. Raw xterm output collapsible in footer.
- DeployFeedbackPill: minimized state anchored top-right, survives
navigation, click restores modal.
- Wires App Store install (action: install), Git apply (action: deploy),
and Git pull (action: update) in addition to the existing EditorLayout
actions.
- Fixes Terminal.tsx WS URL in generic mode (was connecting to root path
not proxied by Vite; now uses /ws).
- Settings: adds "Show deploy progress modal" checkbox to Appearance.
- Docs: renames deploy-logs.mdx to deploy-progress.mdx; updates
internal architecture doc.
* fix(deploy-logs): connect Terminal in generic mode and move pill to bottom-center
Terminal was passed stackName which routes it to the stack logs WS
(container stdout). In that mode onReady is never called, so the
deployStarted gate never resolves and the compose command never runs.
Remove stackName so Terminal uses generic WS mode, which calls onReady
on open and streams compose output.
Also reposition the minimized pill from top-right to bottom-center
(fixed bottom-6 left-1/2 -translate-x-1/2) per UX feedback.
* docs(deploy-logs): update pill position to bottom center
* test(deploy-logs): rewrite E2E spec for deploy feedback modal
The old spec targeted the removed bottom-drawer DeployLogPanel and used
the wrong field name when calling POST /api/stacks (sent 'name' but the
endpoint reads 'stackName'), causing every test to fail with a 400 before
any UI assertions ran.
Fixes:
- POST /api/stacks body now uses 'stackName' matching the API contract
- All locators updated to target the new DeployFeedbackModal and
DeployFeedbackPill components (data-testid attributes added)
- Added enableDeployFeedback helper to opt-in via localStorage before
each test that expects the modal (feature is off by default)
- Added opt-in OFF test to confirm the modal is suppressed when disabled
- Minimize/expand test now asserts the pill appears and contains the
stack name before clicking to restore the modal
* test(deploy-logs): fix compose file write endpoint in E2E helper
createStackViaApi was calling PUT /api/stacks/:name/files/docker-compose.yml
which does not exist. The correct endpoint is PUT /api/stacks/:name with
{ content } in the body.
* test(deploy-logs): use addInitScript to persist opt-in across reloads
The opt-in flag was set via page.evaluate before setupDeployStack, which
calls page.reload() and loginAs (a second navigation). Although localStorage
should persist across same-origin reloads, the React tree was reading
'false' on remount in CI. Switching to addInitScript guarantees the
localStorage value is set before any page script on every navigation, so
useDeployFeedbackEnabled's useState initializer always sees the right
value when React mounts.
* test(deploy-logs): verify localStorage and re-dispatch event before deploy
Adds syncDeployFeedbackState() called right before each deploy click in
the ON tests. It both verifies localStorage is set (failing the test
loudly with a clear message if not) and re-dispatches the
SENCHO_SETTINGS_CHANGED event to defeat any stale React state after
navigation. If the modal still does not appear with the assertion green,
the issue is downstream of localStorage and we have a clear signal.
* test(deploy-logs): wait for React re-render after dispatching opt-in event
After syncDeployFeedbackState dispatches SENCHO_SETTINGS_CHANGED, React
schedules the state update but does not flush it synchronously. The
click that follows can fire against the stale closure where isEnabled is
still false, so runWithLog takes its early-return path and the modal
never opens. A 200ms wait is enough to let React commit the new state
before the next interaction.
* test(deploy-logs): wait for stack file fetch before clicking deploy
deployStack() in EditorLayout returns early at 'if (!selectedFile)'
without calling runWithLog. selectedFile is set inside loadFile() after
GET /api/stacks/:name resolves. The previous setup clicked the stack in
the sidebar and immediately asked the test to click Deploy, racing the
fetch. CI backend logs confirmed no deploy POST ever fired for the ON
tests, while the OFF test passed only because it asserts non-existence.
Now setup awaits both the stack click and the file response together,
then verifies the action bar's deploy button is visible before returning.
* test(deploy-logs): wait for network idle and capture browser logs
Adds a networkidle wait plus a 500ms settle after the stack click so
React commits selectedFile and any follow-up env/container/backup
fetches drain before the deploy click. Also mirrors browser console
errors and pageerrors into the Playwright output so the next failure
ships with the React stack trace instead of just a 'modal not visible'
message.
* test(deploy-logs): temporary debug logging in runWithLog
Adds a console.log at the entry of runWithLog so we can see in CI logs
whether it is being called and what isEnabled value the closure has.
Also widens the test's console capture to include these debug lines.
This is diagnostic only and will be removed once the root cause of the
modal-not-opening-in-CI failure is identified.
* test(deploy-logs): debug log at deployStack entry to trace click path
Adds console.log at the first line of deployStack handler so we can
confirm in CI whether the click is reaching it at all and what
selectedFile/isStackBusy resolve to. Combined with the existing
runWithLog debug logs, this isolates whether the modal failure is in
deployStack guarding out, runWithLog early-returning, or something
else entirely.
* test(deploy-logs): drop filter, log every browser console msg
The previous filter only emitted error/warning plus the deploy-feedback
substring. The deploy-feedback debug logs never appeared, so we don't
yet know whether the log itself is firing. Remove the filter so the
full console stream shows up in CI.
* test(deploy-logs): app-level console log to verify capture pipeline
If even an unconditional log at App component render time does not
appear in CI browser logs, then the console capture listener is broken
or the dispatched logs are being filtered upstream of Playwright. This
isolates whether the issue is in the production code or the test
harness.
* test(deploy-logs): use testid locator for stack action button
Replaces the regex-based getByRole locator (/Deploy|Start/i) with
getByTestId('stack-deploy-button'). The regex matched something other
than the actual deploy button: backend logs proved no deploy POST ever
fired, and instrumentation confirmed neither deployStack nor runWithLog
ran on click despite the test claiming success.
Adds data-testid='stack-deploy-button' to both the Restart and Start
button branches in EditorLayout's action bar so the same locator works
whether the stack is running or not.
Also drops the temporary debug console.log entries in deployStack,
runWithLog, and App, and restores the test's console listener filter
to only emit error and warning messages.
* test(deploy-logs): park cursor in corner so auto-close countdown fires
After clicking the deploy button, the cursor lands inside the centered
modal. The modal pauses its 4s auto-close countdown on hover, so the
HAPPY test was waiting for a close that never happened. page.mouse.move
to (0,0) parks the cursor outside the modal before the success banner
appears, letting the countdown complete.
* test(deploy-logs): drop redundant loginAs after page.reload
page.reload preserves auth cookies, so the page lands back on the
dashboard without needing a fresh login. The loginAs call after reload
was racing on isLoginPage(): a transient login-page state during page
load made loginAs commit to filling #username, then the dashboard
committed and #username never came back. Playwright's auto-wait then
hung the fill until the test's 120s timeout, which also dragged later
stacks.spec tests down with collateral timeouts.
waitForStacksLoaded is enough to confirm we're on the dashboard with
the sidebar populated before clicking the new stack.
* test(e2e): make loginAs race-safe when login page is a false positive
isLoginPage() reports the page as a login screen if the Login button
locator reports visible at the moment of the check. Under CI load (more
real container deploys from the deploy-log-panel suite), the auth
context can render the login form for one paint, then redirect to the
dashboard. The original code committed to filling #username and hung
until the test timeout when the field was no longer there.
Now the login branch waits up to 2s for #username to actually appear
before filling. If it never appears, we fall through to the dashboard
check instead of hanging.
|