fix(tui): capture panics and harden GitHub workflow dispatch#362
Merged
Conversation
Dispatching a GitHub Actions workflow crashed the whole TUI with a generic "program was killed: program experienced a panic" and left no crash report, because Bubble Tea catches panics in the model's Update/View, swallows the value, and returns only a generic error, so main's top-level recover never runs. - Add crashlog.GuardTUI, deferred on the root model's Update, View, and Init: it recovers the in-flight panic, writes a crash report with the preserved stack to DataDir()/crashes, records the path, then re-panics so Bubble Tea still restores the terminal. cmd/root.go surfaces the report path after the program exits (a message printed mid-panic would be lost with the alternate screen). - Guard a nil GitHub client in handleWorkflowDispatchInputs so it yields a failure toast instead of a nil dereference. - Show the workflow-dispatch inputs in a multi-line composer (ShowMultilineInputWithValue) to match its key=value-per-line content; the single-line input could neither hold nor let the user add newlines. - Drop handleWindowSizeMsg's always-nil tea.Cmd return, surfaced by golangci-lint unparam once the Update guard defer broke return pass-through. Adds regression tests for the full dispatch flow (no panic + success toast), the panic-capture guard on Update/View/Init, the nil-client path, and the multi-line modal. Fixes #361 Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> Copilot-Session: 2fe7a260-26ac-4066-8f4f-369ab6a38550
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> Copilot-Session: 2fe7a260-26ac-4066-8f4f-369ab6a38550
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Fixes #361
What
crashlog.GuardTUI, deferred on the root model'sUpdate,View, andInit. It recovers an in-flight panic, writes a crash report (with the real stack) toDataDir()/crashes, records the path, then re-panics so Bubble Tea still restores the terminal.cmd/root.goprints the report path after the program exits.handleWorkflowDispatchInputsso it shows a failure toast instead of a nil dereference.ShowMultilineInputWithValue) instead of a single-line input.handleWindowSizeMsg's always-niltea.Cmdreturn (surfaced byunparamonce theUpdateguard defer broke return pass-through).Why
Dispatching a GitHub Actions workflow from the GitHub panel crashed the whole TUI with a generic "program was killed: program experienced a panic" and wrote no crash report: Bubble Tea catches panics in the model's
Update/View, swallows the value, and returns only a generic error, somain's top-level recover never runs. That made the crash undiagnosable. The inputs step also fed multi-linekey=valuecontent into a single-line input that couldn't hold or accept newlines, and the dispatch call lacked the nil-client guard its sibling already has.How
The panic is in the main event-loop goroutine (that's why the error is the wrapped
ErrProgramKilled), soGuardTUIonUpdate/View/Initcatches it.debug.Stack()inside the deferred recover still points at the original panic site, so the report is diagnosable; re-panicking hands control back to Bubble Tea's own recover, which restores the terminal. Now any TUI panic is captured, and the dispatch path no longer crashes.Testing
go build ./...passesgo test ./...passes (full suite and-race)go vet ./...passesNew regression tests cover the full dispatch flow (no panic plus success toast), the panic-capture guard on Update/View/Init (crash report written and re-panic), the nil-client path, and the multi-line modal. Also clean:
golangci-lint, gofumpt, deadcode, govulncheck.Screenshots
N/A (terminal UI). The inputs modal now renders as a multi-line composer: Enter inserts a newline, Ctrl+D submits, Esc cancels.