Commit 0146039
authored
Add one-click bug report bundle and prefilled issue forms (#8722)
## Summary
Adds a **Report a Bug** button that saves the current game, collects the
relevant logs, and writes a single zip the player can attach to an
issue. The MegaMek, MegaMekLab and MekHQ buttons now open the issue form
with the version, operating system and Java version already filled in.
This is the MegaMek counterpart of MekHQ #8433. MegaMek already had the
dialog itself (`BugReportDialog`, the four repo links, the Discord
button), so this fills in the part that was missing: the player still
had to find their save, work out which of the files in `logs/` mattered,
and zip them by hand.
Reporting is also now offered where a player actually is when something
goes wrong, rather than only under the Help menu: on the error dialog
raised for an uncaught exception, on the Commands button above the
board, and on a button that sits in the same place in the phase display
all game.
## What the player sees
Before: the dialog told them to "save your game... best make a ZIP of
it", then the issue form asked for MegaMek Suite Version, Operating
System and Java Version - all required - and instructed them to open
`megamek.log` in a text editor and copy them out of the header, with a
screenshot showing what to look for.
After: one button produces `MegaMek-BugReport-<timestamp>.zip`
containing the save, the logs that matter, and a `system-info.txt`.
Pressing "MegaMek" opens the issue form with those three fields already
populated. In the dialog that button is larger than its neighbours and
framed in yellow and red hazard stripes; in game it keeps the ordinary
phase display skin and sits at the bottom of the Done column in every
phase, so it does not have to be hunted for in a menu.
<img width="712" height="382" alt="image"
src="https://github.com/user-attachments/assets/0d113d69-4ed1-4ce4-9272-16bb21c99f79"
/>
https://github.com/user-attachments/assets/0f9ee990-a4e2-40fb-840c-5a2f932940de
## Changes
1. **`BugReportBundle`** decides what goes in the archive and writes it.
It uses an explicit manifest rather than scanning the log folder,
because that folder also accumulates one `gamelog*.html` combat report
per game and a `Bot_*.mul` unit list per bot per game - a working
install can hold hundreds of megabytes there. A plain `*.log` filter has
the opposite problem: it would skip the combat report, which is usually
the most useful single artifact in a MegaMek bug report. The archive is
capped at the 25 MB GitHub allows for attachments, and anything dropped
is named back to the player rather than silently omitted.
2. **`IssueReportUrl`** builds the prefilled URL. All three suite
repositories use issue forms whose field ids are identical, so one
builder serves them all and only the repository differs. `mm-data` has
no template and is left alone.
3. **Save-completion callback on `AbstractClient`.** Saving is
asynchronous: `/localsave` goes to the server, which serializes the game
and streams it back as a `SEND_SAVEGAME` packet, so the archive cannot
be built until that arrives. There is a 30 second timeout after which
the archive is written with logs alone - see "Known limitation" below.
4. **Reporting offered from three new places.** The error dialog gains a
Report a Bug button, gated on the error carrying a `Throwable`; the
Commands menu gains a Report a Bug entry; and every phase display
carries one at the bottom of the Done column, added in
`StatusBarPhaseDisplay` after the phase's own contents so it lands below
Skip where there is one and below Done where there is not. It is in the
same place regardless of which button group is showing, so it is never a
"More..." away.
5. **Copy System Data is now offered only where nothing gathers the
files automatically.** In MegaMek the archive carries a
`system-info.txt` and the repository buttons fill the same three details
into the issue form, so the button duplicated work the player no longer
has to do. MegaMekLab and MekHQ open this dialog without a packaging
action and keep it, and the Help menu keeps the item in its own right.
## Two decisions worth reviewing
**No customs export.** MekHQ #8433 threaded an `isBugReportPrep` flag
through `Campaign.writeToXML` so custom units would be baked into the
save. MegaMek needs no equivalent: `GameManagerSaveHelper` serializes
the whole `Game` with XStream and `Server.loadGame` restores it without
ever consulting `MekSummaryCache`, so customs are already inside the
save.
**The `labels` query parameter is deliberately not set, and should stay
that way.** GitHub requires the visitor to hold permission for any
action a query parameter performs, and serves a **404 page** when they
do not. Ordinary players have no triage permission here, so adding a
`labels` parameter would replace the issue form with a 404 for exactly
the people this feature is for - while working fine for every maintainer
who tested it. There is a regression test named for this
(`IssueReportUrlTest.neverSetsTheLabelsParameter`) and the reasoning is
in `IssueReportUrl`'s Javadoc.
**Separately, and not caused by this PR:** while testing the above I
noticed that bug reports filed through the web form arrive with **no
label at all**. `bug_report.yml` declares `labels: [bug]`, but the
repository's label is named `Bug`, and issue-template label matching is
case sensitive - so it silently applies nothing. The RFE template, which
declares the exactly-matching `(RFE) Enhancement`, does work. Compare
#8718 (bug form, unlabelled) with #8709 (RFE form, labelled). That is a
one-character fix in `.github/` and is up as #8724.
## Known limitation (not introduced here)
The 30 second timeout exists to work around #8721: the server refuses a
local save in a double-blind game with local saves disabled by sending a
chat message and no packet, so `awaitingSave` is never cleared and the
client can never finish shutting down. This PR works around it for the
packager only; the underlying bug is filed separately and is not fixed
here.
## Layering note
`MMLogger` takes the error-dialog button as an installable hook rather
than calling the dialog directly, because `megamek.logging` sits below
the user interface and is shared with MegaMekLab, MekHQ and the headless
dedicated server. Those install nothing and keep the plain OK dialog
they have today. The hook carries both button labels, already localized,
so no player-facing text lives in `megamek.logging`.
## Files Changed
- `megamek/common/util/BugReportBundle.java` - new; manifest and zip
writer, Swing-free so it is headless-testable
- `megamek/common/util/IssueReportUrl.java` - new; prefilled issue-form
URL builder
- `megamek/client/ui/PackageBugReportAction.java` - new; the Swing
action - chooser, save request, timeout, result dialog
- `megamek/client/AbstractClient.java` - one-shot save-completion
callback
- `megamek/client/Client.java` - fire the callback on both
`SEND_SAVEGAME` exit paths
- `megamek/logging/MMLogger.java` - installable error-dialog button,
offered only for errors carrying a `Throwable`
- `megamek/client/ui/clientGUI/MegaMekGUI.java` - install the hook;
resolve the running client on click
- `megamek/client/ui/clientGUI/BugReportDialog.java` - button order, the
enlarged reporting button and its hazard stripe border; prefilled repo
links
- `megamek/client/ui/clientGUI/GameCommandsMenu.java` - Report a Bug
entry
- `megamek/client/ui/panels/phaseDisplay/StatusBarPhaseDisplay.java` -
the always-present button in the Done column
- `megamek/client/ui/ShowBugReportDialogAction.java`,
`CommonMenuBar.java`, `ClientGUI.java` - wiring
- `BugReport.properties`, `messages.properties` - new keys; step 1 of
the dialog text no longer says to zip by hand
- `BugReportBundleTest.java`, `IssueReportUrlTest.java` - new; 15 tests
## Testing
Unit tests: 15 new across the two test classes, covering the empty and
missing log directory, manifest selection against a directory seeded
with 40 `Bot_*.mul` files and three game logs, newest-game-log-only,
save-at-archive-root, the size cap, and the labels regression. Full
suite green at 15,072 tests, 0 failures.
Playtested and confirmed:
- The crash dialog. A deliberate `NullPointerException` on both the
event dispatch thread and a background thread produces the "Uncaught
Exception" dialog with the Report a Bug button, and it opens the helper.
- Packaging in game. The archive was produced and its contents were
complete, which exercises the asynchronous save round trip, the
completion callback, and the manifest against a real log directory.
- **The archived save loads back into MegaMek correctly.** The save the
packager writes is a normal, complete save; being routed through the
archive does not damage it.
- Copy File to Clipboard, on Windows 11.
- **The prefilled issue form, end to end against this repository.** A
test report was filed from the in-game button and arrived with MegaMek
Suite Version, Operating System and Java Version already populated, and
with the generated archive attached. That test issue has since been
closed.
## What is NOT proven yet
- **The phase-display button has been compiled, not seen.** The Done
column now asks for three button heights instead of two; whether that
costs board space or fills the gap that was already under Skip needs a
look in game.
- The prefilled form has only been opened from an account with triage
permission. The URL sets no permission-gated query parameter, so it
should behave identically for everyone, but that has not been confirmed
from a plain account.
- The **double-blind save timeout** has not been exercised. It needs a
game deliberately configured with Double Blind plus "Disable local saves
when using double blind".
- **Copy File to Clipboard is untested on macOS and Linux.** Where the
desktop does not support it the button simply does nothing and Open
Folder remains the guaranteed route.
- The dedicated server path is unchanged by inspection - the hook is
never installed there - but has not been run.17 files changed
Lines changed: 1734 additions & 35 deletions
File tree
- megamek
- resources/megamek/client
- src/megamek
- client
- ui
- clientGUI
- panels/phaseDisplay
- common/util
- logging
- unittests/megamek/common/util
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
29 | 29 | | |
30 | 30 | | |
31 | 31 | | |
32 | | - | |
| 32 | + | |
33 | 33 | | |
34 | 34 | | |
35 | 35 | | |
36 | 36 | | |
37 | 37 | | |
38 | 38 | | |
| 39 | + | |
| 40 | + | |
| 41 | + | |
| 42 | + | |
| 43 | + | |
| 44 | + | |
| 45 | + | |
| 46 | + | |
| 47 | + | |
| 48 | + | |
| 49 | + | |
| 50 | + | |
| 51 | + | |
| 52 | + | |
| 53 | + | |
| 54 | + | |
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
6566 | 6566 | | |
6567 | 6567 | | |
6568 | 6568 | | |
| 6569 | + | |
| 6570 | + | |
6569 | 6571 | | |
6570 | 6572 | | |
6571 | 6573 | | |
| |||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
1 | 1 | | |
2 | | - | |
| 2 | + | |
3 | 3 | | |
4 | 4 | | |
5 | 5 | | |
| |||
33 | 33 | | |
34 | 34 | | |
35 | 35 | | |
| 36 | + | |
36 | 37 | | |
37 | 38 | | |
38 | 39 | | |
39 | 40 | | |
40 | 41 | | |
| 42 | + | |
41 | 43 | | |
42 | 44 | | |
| 45 | + | |
43 | 46 | | |
44 | 47 | | |
45 | 48 | | |
| |||
85 | 88 | | |
86 | 89 | | |
87 | 90 | | |
| 91 | + | |
| 92 | + | |
88 | 93 | | |
89 | 94 | | |
90 | 95 | | |
| |||
607 | 612 | | |
608 | 613 | | |
609 | 614 | | |
| 615 | + | |
| 616 | + | |
| 617 | + | |
| 618 | + | |
| 619 | + | |
| 620 | + | |
| 621 | + | |
| 622 | + | |
| 623 | + | |
| 624 | + | |
| 625 | + | |
| 626 | + | |
| 627 | + | |
| 628 | + | |
| 629 | + | |
| 630 | + | |
| 631 | + | |
| 632 | + | |
| 633 | + | |
| 634 | + | |
| 635 | + | |
| 636 | + | |
| 637 | + | |
| 638 | + | |
| 639 | + | |
| 640 | + | |
| 641 | + | |
| 642 | + | |
| 643 | + | |
| 644 | + | |
| 645 | + | |
| 646 | + | |
| 647 | + | |
610 | 648 | | |
611 | 649 | | |
612 | 650 | | |
| |||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
1340 | 1340 | | |
1341 | 1341 | | |
1342 | 1342 | | |
| 1343 | + | |
1343 | 1344 | | |
1344 | 1345 | | |
1345 | 1346 | | |
| |||
1360 | 1361 | | |
1361 | 1362 | | |
1362 | 1363 | | |
| 1364 | + | |
| 1365 | + | |
| 1366 | + | |
| 1367 | + | |
1363 | 1368 | | |
1364 | 1369 | | |
1365 | 1370 | | |
| |||
0 commit comments