Unpack the mock app store fixtures and build the zips at test time - #209
Merged
Conversation
Nothing referenced it: no test installs it by name, and its only trace was the `# todo: test_large_app_does_not_start` comment removed here. Its app_meta shape duplicated filebrowser's, so it added nothing to the corpus that test_all_mock_app_store_metas_migrate walks either. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01AHmisdKK8deh7iEd3Shn2Q
The fixtures were checked in as zips, so the compose templates and app_meta files they carry could not be read or diffed without unpacking them first. Four of the loose copies sitting next to the zips had already drifted from the zip that actually ran: they lacked the `version: '3.5'` line, and always_on's named the `shard` network where the live one names `portal`. The zips are now unpacked into the repo and a session-scoped fixture packs them into a temporary directory at test start, removing it at session end. The unpacked files come from the zips themselves, so what the suite installs is byte-identical to before, bar the port change below. Dropping `ports: - 80:80` from every template while the files were open: nothing consumed the host binding. Traefik reaches an app over the shared portal network at `http://<container>:<port>`, and no app in the app-repository publishes a host port. The binding only ever collided with whatever already held port 80 on the machine, which made test_app_starts_and_stops unpassable on a host running its own reverse proxy. pause_cycle already carried no ports block. immich's zip contains a .env that .gitignore's `.env` rule would have kept out of the repo, so the built zip would have silently lost it — hence the negation. build_mock_app_store_zips asserts every fixture file is git-tracked, so the next such file fails the run instead of quietly producing a different app in CI than on a developer machine. test_all_mock_app_store_metas_migrate now reads the app_meta.json files directly rather than unpacking each zip for one entry. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01AHmisdKK8deh7iEd3Shn2Q
ClaydeCode
added a commit
that referenced
this pull request
Aug 25, 2026
The mock app store no longer ships zips; build_mock_app_store_zips packs each app directory at session start (#209). Leaving this one in place would pack a stale copy of the app inside the zip built from it. Its app_meta.json, docker-compose.yml.template and icon.svg were already byte-identical to the zip's contents, so nothing is lost. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01AHmisdKK8deh7iEd3Shn2Q
ClaydeCode
added a commit
that referenced
this pull request
Aug 25, 2026
The mock app store no longer ships zips; build_mock_app_store_zips packs each app directory at session start (#209). Leaving this one in place would pack a stale copy of the app inside the zip built from it. Its app_meta.json, docker-compose.yml.template and icon.svg were already byte-identical to the zip's contents, so nothing is lost. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01AHmisdKK8deh7iEd3Shn2Q
ClaydeCode
added a commit
that referenced
this pull request
Aug 26, 2026
The mock app store no longer ships zips; build_mock_app_store_zips packs each app directory at session start (#209). Leaving this one in place would pack a stale copy of the app inside the zip built from it. Its app_meta.json, docker-compose.yml.template and icon.svg were already byte-identical to the zip's contents, so nothing is lost. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01AHmisdKK8deh7iEd3Shn2Q
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.
The mock app store fixtures were checked in as zips, so the compose templates and
app_meta.jsonfiles inside them could not be read or diffed without unpacking first. This unpacks them into the repo and builds the zips at test time instead.Two commits:
tests: drop the unused large_app fixture, thentests, meta: build the mock app store zips at test time.What changed
Fixtures are now plain files. Each app directory holds its
app_meta.json,docker-compose.yml.templateand icon directly. A session-scoped fixture (mock_app_store_zips) packs them into aTemporaryDirectoryat session start and removes it at the end, yielding the same<root>/<name>/<name>.ziplayout the six consumers already expected.The unpacked files came out of the zips, not from the loose copies that were sitting beside them — four of those had already drifted from what actually ran.
always_on,filebrowser,large_appandmock_applacked theversion: '3.5'line the live template carried, andalways_on's named theshardnetwork where the live one namesportal. Taking the zip as the source means the suite installs byte-identical apps to before, apart from the port change below.large_appis gone. No test installed it by name; its only trace was# todo: test_large_app_does_not_start, removed with it. Itsapp_metashape duplicatedfilebrowser's, so the migration corpus loses nothing.ports: - 80:80dropped from every template. Nothing consumed the host binding: Traefik reaches apps over the sharedportalnetwork athttp://<container>:<port>(shard_core/service/traefik_dynamic_config.py:193), and no app in the app-repository publishes a host port. The binding only collided with whatever already held port 80, which madetest_app_starts_and_stopsunpassable on any host running its own reverse proxy.pause_cyclealready had no ports block, so this makes the set consistent.immich/.envneeded a.gitignorenegation. The repo's.envrule matched it, so unpacking it as a loose file would have left it uncommitted and the built immich zip would have silently lost it.build_mock_app_store_zipsnow asserts every fixture file is git-tracked, so the next such file fails the run instead of quietly producing a different app in CI than on a developer machine.test_all_mock_app_store_metas_migratereads theapp_meta.jsonfiles directly rather than opening each zip for one entry.Verification
main, the same machine gives 1 failed —test_app_lifecycle.py::test_app_starts_and_stops, onBind for 0.0.0.0:80 failed: port is already allocated.pytest --collect-onlygives 308 on both this branch andmain, so no test was dropped.main: every entry byte-identical, and the six templates differ only by the removedportsblock.stray_secret.envinmock_app/producedAssertionError: mock_app has uncommitted fixture files: ['stray_secret.env'].Recommended reading order
.gitignore— the negation that letsimmich/.envbe committedtests/mock_app_store/**— the unpacked fixtures (the template diffs are the removedportsblock;version: '3.5'lines appear because the stale loose copies lacked them)tests/util.py—build_mock_app_store_zipsand the git-tracked assertiontests/conftest.py— the session fixture, andmock_app_storetaking the built roottests/test_app_installation.py,tests/test_app_zip.py,tests/test_app_install_crash_recovery.py— consumers moved onto the fixturetests/test_app_meta_migration.py— readsapp_meta.jsondirectlytests/test_app_lifecycle.py— the removed todo🤖 Generated with Claude Code
https://claude.ai/code/session_01AHmisdKK8deh7iEd3Shn2Q