Skip to content

Add a headless app gallery rendered into docs/gallery - #488

Merged
matt-edmondson merged 2 commits into
mainfrom
claude/project-thread-4d94d3
Oct 9, 2026
Merged

matt-edmondson merged 2 commits into
mainfrom
claude/project-thread-4d94d3

Conversation

@matt-edmondson

@matt-edmondson matt-edmondson commented Oct 9, 2026 •

Copy link
Copy Markdown
Contributor

Requested by Matt · project thread

Before: ProjectDirector had no pictures of itself. Its ImGui layer had no tests, and Main built the whole application inline, so a test could not start it.

After: the new tests/ProjectDirector.UITests project renders an app gallery with the CPU rasterizer. There is no window, GPU or network involved. The six pictures are:

  1. Selecting a repository: the repo list plus the details panel with Similar Repos.
  2. Comparing two repositories: the table of shared and differing files.
  3. Comparing a file: a side-by-side diff with take arrows.
  4. Propagating a file: the propagate popup with both sibling repos checked.
  5. The Set Dev Directory dialog.
  6. The Add GitHub Owner dialog.

No PNGs and no docs/gallery/README.md are committed here. They arrive with the first run of .github/workflows/app-gallery.yml on main, or by dispatching that workflow by hand. The workflow follows ImGuiApp's widget gallery:

  • It is called from a new app-gallery job in ci.yml after the pipeline passes, and only on a push to main.
  • It uses workflow_call plus workflow_dispatch, never workflow_run.
  • It refuses to commit a PNG that is not an LFS pointer.
  • It commits as [bot][skip ci] Regenerate the app gallery.

The README now links to the gallery.

How: each gallery entry is an ordinary MSTest scenario, so every PR proves each picture can still be staged. The scenario:

  • Starts the real application through ImGuiAppHarness.
  • Redirects the settings file to a MockFileSystem and the GitHub token store to an in-memory credential cache, so nothing reads or writes the settings or credentials of whoever runs it.
  • Points the app at three repositories (Alpha, Beta, Gamma) that it seeds offline as real git repositories, with pinned author and committer names and dates and no system or global git config. Fetching on a timer is turned off.

PROJECTDIRECTOR_GALLERY_OUT names the output directory. Without it, the pictures go to a temporary directory that is deleted afterwards.

Things worth knowing:

  • Refactor to reach the app from a test. Main now calls new ProjectDirector().BuildConfig(). BuildConfig() is internal, and an internal constructor takes the settings to use, while the public constructor still loads them from disk as before. The views a test clicks are marked with ImGuiProbes.MarkItem, and InternalsVisibleTo admits the new test project. Runtime behaviour is otherwise unchanged.
  • Browser sort fix. The file browser listed entries in whatever order the file system returned them. That order differs between machines and file systems, so it would have made the propagate picture nondeterministic. ListBrowserEntries now sorts the entries by name, ignoring case. This is a small visible change in the app.
  • Log panel is cropped out. The log prefixes every line with the wall-clock time, so every picture is cropped just above the log panel.
  • Visible fixed path. The seeded repositories live at /tmp/projectdirector-gallery, a fixed path rather than a fresh temp directory. The app prints the dev directory and the selected repo's local path, so that path appears in the pictures.
  • The Add GitHub Owner picture shows the dialog's existing default text, ktsu-io. The dialog is never confirmed.

Verified locally:

  • The solution builds in Release with no warnings.
  • All 7 gallery tests pass.
  • ProjectDirector.Test: 162 passed, 1 skipped, and 1 failed. The failure is CloningAnLfsRepositoryRestoresTheFileContentRatherThanThePointer, and it fails the same way on an untouched main checkout in the same environment, so it predates this change.
  • Three gallery runs into separate directories produced byte-identical PNGs and README.

🤖 Generated with Claude Code

https://claude.ai/code/session_01WWRBkw7bXdWGzuLpqnCvrB

The gallery is a set of MSTest scenarios in a new tests/ProjectDirector.UITests
project. Each one starts the real application through ktsu.ImGui.App.Testing,
stages a view and saves a picture of it. A last test writes docs/gallery/README.md,
which captions every picture. The six pictures show:

- selecting a repository
- comparing two repositories
- comparing a file side by side
- propagating a file
- the Set Dev Directory dialog
- the Add GitHub Owner dialog

The pictures are byte-identical from run to run. The app's settings file and
secret store are replaced with in-memory ones, and the three repositories it
compares are seeded offline with pinned git authors and dates under a fixed
path. Fetching on a timer is turned off, and every picture is cropped above the
log panel, which prints wall-clock times.

Reaching the app from a test needed a small refactor:

- Main now starts the app through an internal BuildConfig(), and an internal
  constructor takes the settings to use.
- The views a test clicks are marked with ImGuiProbes.MarkItem.
- The file browser lists its entries in a case-insensitive name order rather
  than whatever order the file system returns them in.

app-gallery.yml regenerates the pictures and commits them after CI passes on
main, called from ci.yml the same way ImGuiApp's widget gallery is. No PNGs
are committed here; the first run on main writes them.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01WWRBkw7bXdWGzuLpqnCvrB
@matt-edmondson matt-edmondson self-assigned this Oct 9, 2026
Comment thread tests/ProjectDirector.UITests/Gallery/GalleryRepositories.cs Fixed
Comment thread ProjectDirector/ProjectDirector.cs Fixed
Comment thread ProjectDirector/ProjectDirector.cs Fixed
Comment thread ProjectDirector/ProjectDirector.cs Fixed
Path.Join treats a second segment that begins with a separator as part of
the path instead of discarding the repository directory before it, which
Path.Combine does. The browse path is relative, so nothing changes for it
today. The gallery fixture also maps repository names to paths in the loop
source rather than inside the loop body.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01WWRBkw7bXdWGzuLpqnCvrB
@sonarqubecloud

sonarqubecloud Bot commented Oct 9, 2026

Copy link
Copy Markdown

@matt-edmondson
matt-edmondson merged commit 316b0c0 into main Oct 9, 2026
15 checks passed
@matt-edmondson
matt-edmondson deleted the claude/project-thread-4d94d3 branch October 9, 2026 21:53
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants