spinuptui 0.24.4 → 0.25.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +18 -1
- package/README.md +4 -2
- package/package.json +1 -1
- package/src/ui/Splash.tsx +3 -0
- package/src/ui/views/ServerActions.tsx +30 -4
package/CHANGELOG.md
CHANGED
|
@@ -11,6 +11,22 @@ versions; such changes are called out here.
|
|
|
11
11
|
|
|
12
12
|
## [Unreleased]
|
|
13
13
|
|
|
14
|
+
## [0.25.0] - 2026-08-12
|
|
15
|
+
|
|
16
|
+
### Added
|
|
17
|
+
- **Server actions now surfaces a pending SpinupWP platform upgrade**, not just
|
|
18
|
+
a silent badge. The overlay (`a`) shows a banner explaining the API only
|
|
19
|
+
exposes it as a flag with no actionable detail, and `w` jumps straight to the
|
|
20
|
+
server's page in the SpinupWP web app to run it.
|
|
21
|
+
- **App version on the splash screen**, shown below the tagline while the first
|
|
22
|
+
batch of data loads.
|
|
23
|
+
|
|
24
|
+
### Fixed
|
|
25
|
+
- **The reboot-pending detail line now shows the real reason when the SSH probe
|
|
26
|
+
fails**, instead of a generic "couldn't read detail over SSH" message — e.g.
|
|
27
|
+
an SSH auth failure now shows the actual error. Both this and the new upgrade
|
|
28
|
+
banner wrap across lines instead of overflowing the panel on longer text.
|
|
29
|
+
|
|
14
30
|
## [0.24.4] - 2026-08-06
|
|
15
31
|
|
|
16
32
|
### Fixed
|
|
@@ -1299,7 +1315,8 @@ Initial tagged release.
|
|
|
1299
1315
|
### Notes
|
|
1300
1316
|
- Read-only release: works with a SpinupWP **Read Only** API token.
|
|
1301
1317
|
|
|
1302
|
-
[Unreleased]: https://github.com/mwender/spinupwp-tui/compare/v0.
|
|
1318
|
+
[Unreleased]: https://github.com/mwender/spinupwp-tui/compare/v0.25.0...HEAD
|
|
1319
|
+
[0.25.0]: https://github.com/mwender/spinupwp-tui/compare/v0.24.4...v0.25.0
|
|
1303
1320
|
[0.24.4]: https://github.com/mwender/spinupwp-tui/compare/v0.24.3...v0.24.4
|
|
1304
1321
|
[0.24.3]: https://github.com/mwender/spinupwp-tui/compare/v0.24.2...v0.24.3
|
|
1305
1322
|
[0.24.2]: https://github.com/mwender/spinupwp-tui/compare/v0.24.1...v0.24.2
|
package/README.md
CHANGED
|
@@ -320,8 +320,10 @@ Full details: [docs/php-upgrade.md](docs/php-upgrade.md).
|
|
|
320
320
|
## Server actions
|
|
321
321
|
|
|
322
322
|
`a` on a server reboots it or restarts a service (Nginx/PHP-FPM/MySQL/Redis),
|
|
323
|
-
|
|
324
|
-
|
|
323
|
+
shows *why* a reboot is pending (the actual OS packages, read over SSH), and for
|
|
324
|
+
a pending SpinupWP platform upgrade — which the API can't act on — offers `w` to
|
|
325
|
+
jump straight to it in the SpinupWP web app. Needs a Read/Write token. Full
|
|
326
|
+
details: [docs/server-actions.md](docs/server-actions.md).
|
|
325
327
|
|
|
326
328
|
## Site monitoring
|
|
327
329
|
|
package/package.json
CHANGED
package/src/ui/Splash.tsx
CHANGED
|
@@ -4,6 +4,7 @@
|
|
|
4
4
|
import { useEffect, useState } from "react"
|
|
5
5
|
import { theme } from "../lib/theme.ts"
|
|
6
6
|
import { Spinner } from "./components.tsx"
|
|
7
|
+
import { APP_VERSION } from "../version.ts"
|
|
7
8
|
|
|
8
9
|
const TAGLINE = "Terminal control center for your SpinupWP fleet"
|
|
9
10
|
|
|
@@ -40,6 +41,8 @@ export function Splash({ status }: { status: string }) {
|
|
|
40
41
|
<box style={{ height: 1 }} />
|
|
41
42
|
<text content={TAGLINE} fg={theme.text} />
|
|
42
43
|
<box style={{ height: 1 }} />
|
|
44
|
+
<text content={`Version ${APP_VERSION}`} fg={theme.brand} />
|
|
45
|
+
<box style={{ height: 1 }} />
|
|
43
46
|
<Pulse />
|
|
44
47
|
<box style={{ height: 2 }} />
|
|
45
48
|
<box style={{ flexDirection: "row" }}>
|
|
@@ -15,6 +15,9 @@ import { Panel, Spinner, Centered } from "../components.tsx"
|
|
|
15
15
|
import { StatusBar } from "../StatusBar.tsx"
|
|
16
16
|
import { useStore } from "../store.tsx"
|
|
17
17
|
import { moveSelection } from "../List.tsx"
|
|
18
|
+
import { openUrl } from "../../lib/open.ts"
|
|
19
|
+
import { serverWebUrl } from "../../lib/spinupweb.ts"
|
|
20
|
+
import { toast } from "../toast.ts"
|
|
18
21
|
import type { RebootInfo } from "../../lib/ssh.ts"
|
|
19
22
|
import type { ServerOpKind } from "../store.tsx"
|
|
20
23
|
|
|
@@ -56,9 +59,11 @@ export function ServerActions() {
|
|
|
56
59
|
rebootInfoLoading,
|
|
57
60
|
rebootInfoErrors,
|
|
58
61
|
loadRebootInfo,
|
|
62
|
+
accountSlug,
|
|
59
63
|
} = store
|
|
60
64
|
|
|
61
65
|
const rebootRequired = !!server?.reboot_required
|
|
66
|
+
const upgradeRequired = !!server?.upgrade_required
|
|
62
67
|
const [phase, setPhase] = useState<Phase>("pick")
|
|
63
68
|
// Cursor starts on Reboot when one is pending, else on the first restart.
|
|
64
69
|
const [index, setIndex] = useState(() => (server?.reboot_required ? 0 : 1))
|
|
@@ -108,6 +113,12 @@ export function ServerActions() {
|
|
|
108
113
|
setTarget(ACTIONS[index])
|
|
109
114
|
setPhase("confirm")
|
|
110
115
|
return
|
|
116
|
+
case "w":
|
|
117
|
+
if (upgradeRequired && server) {
|
|
118
|
+
openUrl(serverWebUrl(server.id, accountSlug))
|
|
119
|
+
toast.success(accountSlug ? "Opening in SpinupWP…" : "Set accountSlug for deep links — opening dashboard")
|
|
120
|
+
}
|
|
121
|
+
return
|
|
111
122
|
}
|
|
112
123
|
return
|
|
113
124
|
}
|
|
@@ -179,17 +190,17 @@ export function ServerActions() {
|
|
|
179
190
|
{/* Reboot "why" context */}
|
|
180
191
|
{rebootRequired && (
|
|
181
192
|
<>
|
|
182
|
-
<box style={{ flexDirection: "
|
|
183
|
-
<text content="⚠ reboot pending
|
|
193
|
+
<box style={{ flexDirection: "column" }}>
|
|
194
|
+
<text content="⚠ reboot pending" fg={theme.warn} wrapMode="none" />
|
|
184
195
|
{infoLoading ? (
|
|
185
196
|
<box style={{ flexDirection: "row" }}>
|
|
186
197
|
<Spinner interval={120} />
|
|
187
198
|
<text content=" checking what's pending…" fg={theme.textDim} wrapMode="none" />
|
|
188
199
|
</box>
|
|
189
200
|
) : info ? (
|
|
190
|
-
<text content={rebootSummary(info)} fg={theme.textDim}
|
|
201
|
+
<text content={rebootSummary(info)} fg={theme.textDim} />
|
|
191
202
|
) : infoError ? (
|
|
192
|
-
<text content=
|
|
203
|
+
<text content={infoError} fg={theme.textFaint} />
|
|
193
204
|
) : (
|
|
194
205
|
<text content="reboot required" fg={theme.textDim} wrapMode="none" />
|
|
195
206
|
)}
|
|
@@ -197,6 +208,20 @@ export function ServerActions() {
|
|
|
197
208
|
<box style={{ height: 1 }} />
|
|
198
209
|
</>
|
|
199
210
|
)}
|
|
211
|
+
{/* SpinupWP platform upgrade — the API only exposes this as a flag,
|
|
212
|
+
no detail; the only actionable path is the web app. Two lines
|
|
213
|
+
(not a height:1 row) so the explanation can wrap instead of
|
|
214
|
+
overflowing the panel — see the flexGrow/flexShrink gotcha in
|
|
215
|
+
CLAUDE.md. */}
|
|
216
|
+
{upgradeRequired && (
|
|
217
|
+
<>
|
|
218
|
+
<box style={{ flexDirection: "column" }}>
|
|
219
|
+
<text content="⬆ SpinupWP upgrade pending" fg={theme.warn} wrapMode="none" />
|
|
220
|
+
<text content="Not doable from here — press w to open it in SpinupWP." fg={theme.textDim} />
|
|
221
|
+
</box>
|
|
222
|
+
<box style={{ height: 1 }} />
|
|
223
|
+
</>
|
|
224
|
+
)}
|
|
200
225
|
{ACTIONS.map((a, i) => {
|
|
201
226
|
const selected = i === index
|
|
202
227
|
const recommended = a.kind === "reboot" && rebootRequired
|
|
@@ -308,6 +333,7 @@ export function ServerActions() {
|
|
|
308
333
|
return [
|
|
309
334
|
{ key: "↑↓/jk", label: "action" },
|
|
310
335
|
{ key: "⏎", label: "choose" },
|
|
336
|
+
...(upgradeRequired ? [{ key: "w", label: "open in SpinupWP" }] : []),
|
|
311
337
|
{ key: "esc", label: "cancel" },
|
|
312
338
|
]
|
|
313
339
|
case "confirm":
|