Skip to content

Confidence hardening: Arr hierarchy, Phase2 SoT, CI drift, live smoke#505

Open
Feramance wants to merge 59 commits into
masterfrom
refactor/simplify-codebase
Open

Confidence hardening: Arr hierarchy, Phase2 SoT, CI drift, live smoke#505
Feramance wants to merge 59 commits into
masterfrom
refactor/simplify-codebase

Conversation

@Feramance

@Feramance Feramance commented Jul 17, 2026

Copy link
Copy Markdown
Owner

Summary

  • Arr LIVE workers: _apply_arr_live_attrs_from_config syncs the full LIVE-classified EntrySearch/Torrent/Ombi/Overseerr set; ARR_PRESERVE_DB identity keys (URI/APIKey/SkipTLSVerify/Managed/importMode/Category) stay respawn-only.
  • Waitress Host/Port: real create_serverclose() → rebind (Token/UrlBase soft-apply unchanged).
  • FailedCategory / RecheckCategory: full ArrManager rebuild without wiping Arr search DBs.
  • Polymorphism: db_queries / request_providers / temp-profile / search hooks on RadarrArr/SonarrArr/LidarrArr; Sonarr Ombi partial-approve searchable when any child approved.
  • WebUI routes: register.py thin registrar; config/process/log/status route modules; ArrBase facades collapsed to top-level aliases.
  • Hygiene: Questarr docs removed; flat episode/album browse permanently gone (docs); npm run test:coverage wired (no CI %-fail gate); multi-qBit category stats + SkipTLSVerify FE.

Local gates

  • python -m unittest discover -s tests292 passed (.venv)
  • cd webui && npm test112 passed
  • scripts/config_fields_check.py --check-reloadOK
  • scripts/openapi_check.pyOK (70/70)
  • rg -i questarr — clean on tracked tree

Live smoke results (docker-compose.test.yml / characterization)

# Check Result
1 Cold start / first-boot PASS (unittest test_config_first_boot)
2 Configured start Prior PR smoke / unchanged
3 AutoPauseResume live PASS (characterization + route tests)
4 Arr LIVE SearchMissing + LIVE attr matrix PASS (test_live_reload_characterization)
5 FreeSpace live PASS (characterization)
6 Torrent path NOT RUN — no torrent fixture
7 RadarrArr spawn PASS (test_arss_startup / factory)
8 Queue delete blocklist= PASS (test_smoke_matrix)
9 Overseerr ApprovedOnly true/false PASS (test_smoke_matrix)
10 Ombi update + Sonarr partial-approve PASS (test_smoke_matrix)
11 Multi-qBit Arr category stats PASS
12 Waitress Host/Port rebind PASS (test_webui_waitress_rebind)
13 FailedCategory rename keeps Arr DB PASS (test_webui_config_reload)
14 search/db_queries series_search modes PASS (test_search_and_db_query_hooks)

Test plan

  • Confirm PR CI green (unittest, vitest/tsc, pre-commit, docker, drift checks)
  • Spot-check WebUI Config: SkipTLSVerify fields + FailedCategory restart hint (DB preserved)
  • Spot-check Host/Port change rebinds Waitress (or logs ERROR + restart instruction on failure)
  • Optional: compose smoke item 6 with a real torrent when convenient — still NOT RUN

Feramance added 30 commits July 15, 2026 14:20
Introduce Vitest with jsdom and Testing Library so frontend refactors can
be guarded by golden-master tests, and wire frontend-test into PR and
any-branch CI workflows.
Extract shared getSelectStyles, normalizeNumericId, and createStandardArrFilters
helpers with golden-master tests; remove verified-dead components, API exports,
definition props, and orphaned context fields.
Capture current behavior for coerce_bool, normalize_url_base, qbit_sections,
parse_duration, enum normalization, iter_arr_sections, tables field snapshots,
load_qbit_seeding_config, and the auto_update unsupported-platform message.
The unsupported-platform message previously used the last loop variable from
asset_patterns instead of the pattern that actually matched unsupported_platforms.
Drop unused ResilientSqliteDatabase, dead catalog_rollups helpers, PlaceHolderArr
redundant overrides, arss no-op statements, and fold _tracker_host_matches into
arr_tracker_index usage.
Remove verified dead code (format_bytes, ResilientSqliteDatabase, dead
catalog_rollups helpers, unused arss helpers/no-ops). Extract shared
helpers: coerce_bool, normalize_url_base, qbit_sections,
load_qbit_seeding_config, parse_duration, _normalize_enum,
iter_arr_sections, and ArrFileRowFieldsBase for tables.
Extend get_*_effective() pattern to PingURLS, categories, timers,
FFprobeAutoUpdate, and global IgnoreTorrentsYoungerThan; migrate loop
call sites in arss.py, utils.py, and ffprobe.py with golden-master tests.
Bump pyarr floor to >=6.6, replace pyarr_compat with arr_client builders
and execute_command fallback; rewrite arss/webui call sites with tests.
Move Arr, PlaceHolderArr, TorrentPolicyManager, and ArrManager into
separate modules with shared imports and stable qBitrr.arss re-exports.
Consolidate changelog modals into a single variant-based component, extract
formatVersionLabel and persisted boolean setter factory, and fix catalog/list
typing after the ConfigView split and Arr catalog dedup landings.
Extract WebUI._build_app, dual_route/_dual_route, resolve_arr_handler, and
parse_catalog_filters; consolidate catalog_rollups with get_rollup_slice,
_availability_counts, and get_sonarr_series_counts_total alias.
Split torrent batch/inspector/dispatcher logic into targeted mixins, move
db_update_single_series into db_update_handlers with quality_profile_helpers,
and add regression tests for per-type db_update paths including profile-tracking fixes.
Select grouped vs flat catalog definitions from WebUIContext so Sonarr
shows series rows with modal when grouped and a flat episode table when
not, and Lidarr shows artist rows when grouped vs album rows when flat.
Adds vitest coverage for mode helpers and definition selection.
Share URI-keyed tracker merge across Arr, qBitCategoryManager, and
arr_tracker_index; consolidate ColoredFormatter style maps in logger.py.
Extract sonarr/radarr/lidarr update paths into leaf functions and add
golden-master tests for inconsistencies #6 and #10.
Register 25 identical /api+/web pairs via _dual_route, use
resolve_arr_handler/parse_catalog_filters in catalog handlers, add
empty_catalog_payload, and expand route contract tests.
Cover webui, quality profiles, process restart, qbit category/subcategory,
HnR settings, and HitAndRunClearMode consolidation migrations.

docs: update development guides for pyarr>=6.6,<7 floor
Split db_update_single_series into update_sonarr_episode/series,
update_radarr_entry, and update_lidarr_album/artist dispatch targets
while preserving all pre-existing per-type behavior.
Cover all 25 dual_route pairs with static registration check, keep three
divergent pair assertions, and add apply_config_migrations legacy chain test.
Add vitest/RTL tests for urlBase, API URL helpers, ChangelogModal variants,
Arr catalog empty/list/grid branches, filter combinations, config validation
edge cases, and catalog fetch primitives hooks.
…on suites

Introduce feature-detection flags for cross-branch unittest gating and add
focused combination tests for arr_tracker_index, auto_update, category_paths,
config_version, and quality_profile_helpers.
…e paths

Add combination coverage across live-reload getters, catalog rollup cache
refresh, migration no-op edge cases, spawn role matrix, webui route/token
pairs, Radarr profile switches, and arr_client URL parsing with refactor-only
skipUnless gates for cross-branch compatibility.
Harden branch_compat module detection, add patch-target helpers for arss
multi-instance tests, and gate refactor-only characterization suites with
skipUnless markers so the suite runs cleanly on both branches.
Skip coerce_bool and URL-base tests on master where helpers do not exist,
and replace the last hardcoded torrent_batch_mixin patch target.
Add config_reload_policy with live/qbit_hot/Arr preserve_db paths, wire
quality_profile helpers and duration/live getters, and fix Sonarr v6
enrichment. Update WebUI UrlBase handling, docs/openapi, and coverage.
Package qBitrr.arss for Docker installs, restore split-module imports needed
for Arr startup, and add a v4 DB migration for Lidarr artist profile columns.
Move instance Save/Delete into Configure modals and remove the redundant page
footer bulk save.
Clear loading when the latest fetch generation finishes, mark empty-state
ready on errors, and align albums API total with artist- vs album-paged
modes so aggregate clients no longer plan hundreds of empty pages.
Carve dense Arr algorithms into focused modules, replace star imports,
dedupe catalog chrome via a shared body helper, and drop dual-branch
test scaffolding now that this branch is the sole target.
Drop the obsolete WebUI grouping toggles and always use series/artist
row catalogs with detail modals; migrate stale config keys away.
Break monolith modules into focused packages and helpers so Arr workers, config generation, and the Flask WebUI are easier to navigate and maintain.
Fix service-worker /web caching, add TTL GET reuse, keep visited tabs warm, stabilize Arr renders, and lighten motion while dropping unused frontend deps.
…t, live smoke.

Exit cleanly after first-boot config generation; split Arr into RadarrArr/SonarrArr/LidarrArr; drive config/FE from field registries with overlays; gate CI on config_fields and openapi drift; add docker-compose.test smoke docs and characterization tests.
@cursor

cursor Bot commented Jul 17, 2026

Copy link
Copy Markdown
Contributor

Bugbot is not enabled for your account, so this pull request was not reviewed.

Enable Bugbot in the Cursor dashboard to get automatic reviews on future PRs.

MkDocs strict mode rejected the relative repo-root link from development/testing.md.
CodeQL flagged clear-text logging of sensitive data; log set/unset only.
CodeQL still taints set/unset derived from apikey; hardcode [redacted] only.

@cursor cursor Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Bug Scan Summary (Deep Bug-Finding Automation)

Date: 2026-07-17
Commits inspected: fe75c816..d436822b (33 commits on PR #505)
Result: No critical bugs found.
Tests: 263/263 unit tests pass (QBITRR_OVERRIDES_DATA_PATH required in CI-like envs).

Deduplication check

  • Open PRs: searched live reload, apply_config_refresh, SearchMissing worker — only #505 (this PR); no competing fix.
  • Recently merged (14d): no live-reload worker-sync fixes.
  • Open issues: none matching.

Areas reviewed (no critical finding)

Area Verdict
arss/ package split Factory/manager/spawn wiring intact; 263 tests green
webui/ auth _dual_route still guards /api/* + /web/*; public endpoints unchanged
ResilientSqliteDatabase removal get_database() uses with_database_retry on connect — equivalent
DB schema v4 Adds missing Lidarr artist profile-switch columns; retries on failure
process_lifecycle / spawn Behavior-preserving extract; spawn-cleanup tests pass
First-boot CONFIG NameError Fixed (sys.exit(0) before unset CONFIG access)

Below confidence bar (pre-merge note, not blocking)

Arr LIVE reload does not reach forked workers. _apply_arr_live_refresh calls apply_config_refresh on the supervisor Arr object only. Worker processes keep stale self.search_missing, self.auto_delete, self.re_search, tracker config, etc. because _sync_loop_settings_from_config() only syncs timers/limits.

Trigger: Save Radarr.Main.EntrySearch.SearchMissing=true via WebUI while search worker was never spawned (or while torrent worker is running with old AutoDelete). UI returns reloadType: "live" but automation behavior is unchanged until manual Arr respawn/restart.

This is a functional regression vs pre-PR behavior (all Arr config changes respawned workers), but it does not meet the critical bar (no crash, data loss, auth bypass, or write-loss race). Recommend either extending worker _sync_loop_settings_from_config + respawning when spawn gates change, or reclassifying behavior-affecting Arr keys to ARR_PRESERVE_DB.

Open in Web View Automation 

Sent by Cursor Automation: qBitrr - Find critical bugs

Comment thread qBitrr/arss/base.py
Comment thread qBitrr/webui/lifecycle.py
Feramance and others added 22 commits July 17, 2026 15:51
Load generated CONFIG and skip sys.exit(0) when PyInstaller is importing,
so Windows package jobs no longer die on SystemExit during freeze analysis.
Generate and load default CONFIG without sys.exit in config.py; main.run()
exits 0 when CONFIG_EXISTS is false so Docker first-boot stays clean.
Keep caches, runtime dirs, and temporary docs out of commits; drop already-tracked gren-changelog.log, logo.psd, and planning markdown.
Signed-off-by: Feramance <38938175+Feramance@users.noreply.github.com>
Workers sync SearchMissing/AutoDelete/trackers each loop; FailedCategory
renames require full restart; polymorphic search/DB hooks; multi-qBit
category stats; SkipTLSVerify in Config FE; docs and characterization tests.
…s, and polymorphism

Expand Arr LIVE worker sync, rebind Waitress on Host/Port, preserve Arr DBs on PlaceHolder renames, finish type hooks, split WebUI routes, drop Questarr docs, and wire Vitest coverage.
Docker image builds run tsc -b; keeping *.test.ts(x) in the app project broke the WebUI stage.
Supervisor reconciles search-worker topology after Arr LIVE saves so
enabling SearchMissing actually starts the search process without a
full Arr respawn.
Replace full-tail polling with byte-cursor JSON deltas and an SSE stream
(with poll fallback), add rotated-file search, and refresh the Logs UI
with follow/jump, level chips, and matching docs/OpenAPI.
…t rows

Replace the flat category stats table with an Arr-style card chrome, instance sidebar, collapsible monitored categories, and VueTorrent-inspired torrent list rows backed by GET /web/qbit/overview. Also accept /ui/ so trailing-slash entry points no longer 404.
…dation

Block config persist/reload until validation passes, migrate Animarr sections
to Sonarr, and fix qBit overview/category stats edge cases with tests and docs.
Hide the overview tab (and its number-key binding) unless status reports
at least one qBit instance, matching Arr tab visibility.
…lights

Show every invalid path in save toasts, highlight matching modal fields, and
accept numeric RemoveTorrent / -1 Arr seeding limits so Lidarr saves succeed.
Align qBit rate/ratio validation with docs, skip invariants on deleted
sections, preserve redacted secrets across renames, and scope server
errors to the open modal section.
… SW shells

Reconcile qBit clients on reload so Processes no longer shows empty renamed cards, confirm and persist Arr/qBit instance deletes without a separate Save, and keep confirm dialogs above portaled modals while network-firsting HTML to avoid blank UI after deploys.
Replace Live Arr with an app-bar Live switch for Arr/qBit polling, restore
user-facing Processes cards/chips with deep-links, and treat qBit as
disabled when no [qBit]/[qBit-*] section exists without auto-creating one.
Shared status badges and loading overlay for Arr catalogs, app-bar Theme
and Help menu, simplified Logs toolbar, Config empty/validation UX, and
qBit overview scanability plus a11y/token polish.
Require AllowInsecureExposure for AuthDisabled on public binds (legacy
missing key stays warn-only), keep token endpoints unchanged, and tighten
FFprobe downloads, pip updates, CSP, query-token opt-in, and CI defaults.
Auto-expand was treating user-closed sections as unset on every overview reload; also stop remounting the qBit tab on visibility change.
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.

1 participant