Upgrade .NET 10 / Node 24 + clean architecture migration#524
Upgrade .NET 10 / Node 24 + clean architecture migration#524therobbiedavis merged 21 commits intocanaryfrom
Conversation
Bump platform and toolchain versions and reorganize repository contracts/implementations. Workflows updated to use .NET 10 and Node 24, legacy ci.yml removed, and run-tests.yml enhanced with concurrency, expanded setup (node), layering enforcement checks (api/application -> infrastructure), async void detection, frontend lint/type-check/test steps and an API publish step. Project files updated: Directory.Build.props TargetFramework set to net10.0 and Dockerfile base/sdk images moved to .NET 10. Repository interfaces were moved out of listenarr.api into listenarr.application and corresponding EF implementations into listenarr.infrastructure (many files added/renamed). Directory.Packages.props removed an explicit Microsoft.AspNetCore.Authorization entry. Frontend package.json/lock were updated to bump several dependencies. Misc test and project file adjustments to align with these changes.
Replace direct ListenArrDbContext access with repository abstractions across the API to decouple data access and improve testability. Controllers (AdminMetadataController, DownloadsController, HistoryController, IndexersController, and others) now use repository interfaces (e.g. IDownloadRepository, IIndexerRepository, IAudiobookFileRepository, IHistoryRepository) and call repository methods instead of EF Core DbContext operations. Added new application/infrastructure pieces (IDownloadHistoryRepository, IDatabaseConnectionProvider, QueueStats, EfDatabaseConnectionProvider) and updated service registration accordingly. Also: bump package versions (Microsoft.AspNetCore.Mvc.Testing -> 10.0.6; Serilog.AspNetCore -> 10.0.0; Serilog.Sinks.File -> 7.0.0). Frontend fixes include improved typings and test mocks (use vi.mocked, typed SearchResult/RootFolder), added v-for keys, minor refactors (var -> let), normalized genre typing, and removal of some unused UI helpers. A number of tests were updated to match the refactor.
Introduce focused query methods to avoid loading all downloads into memory: add GetCompletionCandidatesAsync, GetActiveForMonitoringAsync, GetRecentAsync and GetActiveAudiobookIdsAsync to IDownloadRepository and implement them in EfDownloadRepository and the test repository. Change GetStuckProcessingJobsAsync to accept a CancellationToken (and remove SaveChangesAsync) in IDownloadProcessingJobRepository and update EfDownloadProcessingJobRepository and tests accordingly. Update consumers (LibraryController, DownloadMonitorService, DownloadProcessingBackgroundService) to use the new repository APIs. Replace the custom SimpleDbContextFactory with AddDbContextFactory registration in InfrastructureServiceRegistrationExtensions. Misc: small TS typing fix in fe/vite.config.ts, add a comment pinning Microsoft.AspNetCore.OpenApi to 8.x in Directory.Packages.props, and remove many unused using directives across multiple files. Tests and mocks updated to exercise the new methods.
Add optional CancellationToken to GetDueRetryJobsAsync in the repository interface and update EF implementation to pass the token to CreateDbContextAsync and ToListAsync, ensuring queries can be cancelled. Update test repository GetDueRetryJobsAsync to accept the token, apply ordering (Priority desc, NextRetryAt asc) and use ToListAsync(cancellationToken). Implement GetStatsAsync in the test repo to compute queue counts and oldest pending job. Also include AudiobookId and Language mapping in TestDownloadRepository DTO conversion. These changes improve cancellation support and test utilities for queue statistics and ensure new fields are mapped in tests.
There was a problem hiding this comment.
Pull request overview
This PR advances Listenarr’s clean-architecture goals by moving persistence concerns behind application-layer repository interfaces, while also upgrading the runtime/tooling stack (NET 10, Node 24) and tightening CI enforcement.
Changes:
- Introduces application-layer repository interfaces and infrastructure EF implementations; updates API/services/tests to depend on interfaces instead of
ListenArrDbContext. - Upgrades .NET target frameworks and container/CI Node toolchain; expands CI to include frontend build/lint/type-check/tests and layering checks.
- Refactors several background/services hot paths to use repositories (with some remaining in-memory filtering needing follow-up).
Reviewed changes
Copilot reviewed 203 out of 206 changed files in this pull request and generated 7 comments.
Show a summary per file
| File | Description |
|---|---|
| tools/dbscan/DbScan.csproj | Bumps tool target framework to net10.0. |
| tests/Listenarr.Api.Tests/TestServiceFactory.cs | Updates DI test factory for new repository interfaces. |
| tests/Listenarr.Api.Tests/TestDownloadRepository.cs | Expands in-memory download repo to match new repository interface surface. |
| tests/Listenarr.Api.Tests/TestDownloadQueueService.cs | Updates test imports to application repositories. |
| tests/Listenarr.Api.Tests/TestCompletedDownloadProcessor.cs | Updates test imports to application repositories. |
| tests/Listenarr.Api.Tests/SeriesMonitoringServiceTests.cs | Adjusts tests to construct services with repositories instead of DbContext. |
| tests/Listenarr.Api.Tests/SearchServiceSortingTests.cs | Updates tests for async private sorting method invocation. |
| tests/Listenarr.Api.Tests/SearchServiceScoringTests.cs | Updates SearchService test setup to inject repositories instead of DbContext. |
| tests/Listenarr.Api.Tests/SearchServiceFixesTests.cs | Updates SearchService test setup to inject repositories instead of DbContext. |
| tests/Listenarr.Api.Tests/RootFoldersControllerTests.cs | Updates controller tests for new constructor dependencies. |
| tests/Listenarr.Api.Tests/RenameServiceTests.cs | Updates RenameService tests for repository-based persistence. |
| tests/Listenarr.Api.Tests/QualityScoringTests.cs | Updates QualityProfileService tests for repository-based persistence. |
| tests/Listenarr.Api.Tests/QualityProfileScoringTests.cs | Updates scoring tests for new repository-based constructors/deps. |
| tests/Listenarr.Api.Tests/ProwlarrCompatControllerTests.cs | Updates controller tests to inject indexer repository instead of DbContext. |
| tests/Listenarr.Api.Tests/MoveQueueServiceTests.cs | Updates tests/DI wiring for move job repository usage. |
| tests/Listenarr.Api.Tests/MoveBackgroundService_FilePathPreservationTests.cs | Updates test DI to register new repositories. |
| tests/Listenarr.Api.Tests/MoveBackgroundService_FailureTests.cs | Updates test DI to register new repositories. |
| tests/Listenarr.Api.Tests/MoveBackgroundService_BroadcastTests.cs | Updates test DI and history repo wiring. |
| tests/Listenarr.Api.Tests/MoveBackgroundServiceTests.cs | Updates test DI to register new repositories. |
| tests/Listenarr.Api.Tests/MetadataIntegrationTests.cs | Updates DI setup for file/history/audiobook repositories. |
| tests/Listenarr.Api.Tests/LibraryController_WantedFlagRegressionTests.cs | Refactors tests to use mocks for new controller dependencies. |
| tests/Listenarr.Api.Tests/LibraryController_UpdateAudiobookTests.cs | Updates tests for expanded controller constructor deps. |
| tests/Listenarr.Api.Tests/LibraryController_ScanPathValidationTests.cs | Updates tests for expanded controller constructor deps. |
| tests/Listenarr.Api.Tests/LibraryController_ScanPathConfigFailureTests.cs | Updates tests for expanded controller constructor deps. |
| tests/Listenarr.Api.Tests/LibraryController_QualityCutoffTests.cs | Updates reflection invocation to match new method signature/deps. |
| tests/Listenarr.Api.Tests/LibraryController_MoveTests.cs | Updates tests for expanded controller constructor deps. |
| tests/Listenarr.Api.Tests/LibraryController_LibraryListSlimPayloadTests.cs | Refactors to mock repos for new controller dependencies. |
| tests/Listenarr.Api.Tests/LibraryController_DeleteImageSafetyTests.cs | Updates tests for expanded controller constructor deps. |
| tests/Listenarr.Api.Tests/LibraryController_DeleteFilesystemTests.cs | Updates test helpers for new controller dependencies. |
| tests/Listenarr.Api.Tests/LibraryController_BulkUpdateTests.cs | Updates tests to use new history/repo abstractions. |
| tests/Listenarr.Api.Tests/LibraryController_BasePathTests.cs | Updates tests for expanded controller constructor deps. |
| tests/Listenarr.Api.Tests/LibraryController_AddToLibraryTests.cs | Updates tests for expanded controller constructor deps. |
| tests/Listenarr.Api.Tests/IndexersPersistedAuthTests.cs | Injects repository into IndexersController tests. |
| tests/Listenarr.Api.Tests/IndexersNewznabParsingTests.cs | Updates SearchService/provider tests for repository-based deps. |
| tests/Listenarr.Api.Tests/IndexersNewznabAuthTests.cs | Injects repository into IndexersController tests. |
| tests/Listenarr.Api.Tests/IndexersControllerTests.cs | Injects repository into IndexersController tests. |
| tests/Listenarr.Api.Tests/IndexersControllerProwlarrImportTests.cs | Updates configuration/indexer wiring to repository implementations. |
| tests/Listenarr.Api.Tests/IndexersAuthTests.cs | Injects repository into IndexersController tests. |
| tests/Listenarr.Api.Tests/ImportServiceHardlinkTests.cs | Updates ImportService construction to use AudiobookRepository. |
| tests/Listenarr.Api.Tests/ForwardedHeadersTrustModelTests.cs | Updates forwarded headers network assertions for new IPNetwork API. |
| tests/Listenarr.Api.Tests/EndToEndDownloadImportFlowTests.cs | Updates end-to-end harness wiring for new repository deps. |
| tests/Listenarr.Api.Tests/DownloadsControllerTests.cs | Updates controller tests to use TestDownloadRepository. |
| tests/Listenarr.Api.Tests/DownloadQueueServiceReconciliationTests.cs | Updates imports for repository interface move. |
| tests/Listenarr.Api.Tests/DownloadProcessing_NoDoubleMoveTests.cs | Updates ImportService construction to use AudiobookRepository. |
| tests/Listenarr.Api.Tests/DownloadProcessing_FileMissingRetryTests.cs | Updates DI registrations for repo interfaces in processing tests. |
| tests/Listenarr.Api.Tests/DownloadProcessingTests.cs | Updates ImportService construction to use AudiobookRepository. |
| tests/Listenarr.Api.Tests/DownloadProcessingQueueServiceTests.cs | Registers new job repository interface in tests. |
| tests/Listenarr.Api.Tests/DownloadProcessingBackgroundServiceRecoveryTests.cs | Registers new repo interfaces for recovery tests. |
| tests/Listenarr.Api.Tests/DownloadNaming_AudiobookMetadataTests.cs | Updates ImportService construction to use AudiobookRepository. |
| tests/Listenarr.Api.Tests/DownloadMonitorServiceTests.cs | Registers new download repository interface in tests. |
| tests/Listenarr.Api.Tests/DownloadMonitorPipelineClientCoverageTests.cs | Registers new download repository interface in tests. |
| tests/Listenarr.Api.Tests/DownloadMonitorFinalizationTests.cs | Updates reflection invocation to pass repository instead of DbContext. |
| tests/Listenarr.Api.Tests/ConfigurationServiceTests.cs | Refactors ConfigurationService tests to use repository implementations. |
| tests/Listenarr.Api.Tests/CompletedDownloadProcessorTests.cs | Updates history repo mock signatures (adds CancellationToken). |
| tests/Listenarr.Api.Tests/AuthorMonitoringServiceTests.cs | Adjusts tests to construct services with repositories. |
| tests/Listenarr.Api.Tests/AudiobookDtoFactoryTests.cs | Updates AudiobookDtoFactory call signature. |
| tests/Listenarr.Api.Tests/AudioFileService_UpdateAudiobookFieldsTests.cs | Updates DI for file/history/audiobook repositories. |
| tests/Listenarr.Api.Tests/AudioFileServiceTests.cs | Updates DI for file/history/audiobook repositories. |
| package.json | Adds wait-on and gates dev:web on API health endpoint. |
| listenarr.infrastructure/Services/EfDatabaseConnectionProvider.cs | Adds EF-backed database connection provider implementation. |
| listenarr.infrastructure/Services/AudiobookRepository.cs | Adds new query/update helpers and JSON normalization via repository. |
| listenarr.infrastructure/Repositories/EfUserSessionRepository.cs | Adds EF implementation for session persistence. |
| listenarr.infrastructure/Repositories/EfUserRepository.cs | Adds EF implementation for user persistence. |
| listenarr.infrastructure/Repositories/EfRemotePathMappingRepository.cs | Adds EF implementation for remote path mapping persistence. |
| listenarr.infrastructure/Repositories/EfProcessExecutionLogRepository.cs | Adds EF implementation for process execution logging persistence. |
| listenarr.infrastructure/Repositories/EfMoveJobRepository.cs | Adds EF implementation for move job persistence. |
| listenarr.infrastructure/Repositories/EfMonitoredSeriesRepository.cs | Adds EF implementation for monitored series persistence. |
| listenarr.infrastructure/Repositories/EfMonitoredAuthorRepository.cs | Adds EF implementation for monitored author persistence. |
| listenarr.infrastructure/Repositories/EfIndexerRepository.cs | Adds EF implementation for indexer persistence. |
| listenarr.infrastructure/Repositories/EfHistoryRepository.cs | Adds EF implementation for history persistence. |
| listenarr.infrastructure/Repositories/EfDownloadClientConfigurationRepository.cs | Adds EF implementation for download client configuration persistence. |
| listenarr.infrastructure/Repositories/EfAudiobookFileRepository.cs | Adds EF implementation for audiobook file persistence. |
| listenarr.infrastructure/Repositories/EfApplicationSettingsRepository.cs | Adds EF implementation for application settings persistence. |
| listenarr.infrastructure/Repositories/EfApiConfigurationRepository.cs | Adds EF implementation for API configuration persistence. |
| listenarr.infrastructure/Repositories/DownloadHistoryRepository.cs | Updates to implement application-layer history repository interface. |
| listenarr.infrastructure/Extensions/InfrastructureServiceRegistrationExtensions.cs | Consolidates infrastructure DI registration (DbContextFactory + repos). |
| listenarr.domain/Models/QueueStats.cs | Moves queue stats model into domain. |
| listenarr.application/Services/IDatabaseConnectionProvider.cs | Adds application contract for obtaining open DB connections. |
| listenarr.application/Services/IAudiobookRepository.cs | Expands audiobook repository contract with new methods. |
| listenarr.application/Repositories/IUserSessionRepository.cs | Adds repository contract for user sessions. |
| listenarr.application/Repositories/IUserRepository.cs | Adds repository contract for users. |
| listenarr.application/Repositories/IRootFolderRepository.cs | Adds repository contract for root folders. |
| listenarr.application/Repositories/IRemotePathMappingRepository.cs | Adds repository contract for remote path mappings. |
| listenarr.application/Repositories/IQualityProfileRepository.cs | Minor cleanup of repository contract usings. |
| listenarr.application/Repositories/IProcessExecutionLogRepository.cs | Adds repository contract for process execution logs. |
| listenarr.application/Repositories/IMoveJobRepository.cs | Adds repository contract for move jobs. |
| listenarr.application/Repositories/IMonitoredSeriesRepository.cs | Adds repository contract for monitored series. |
| listenarr.application/Repositories/IMonitoredAuthorRepository.cs | Adds repository contract for monitored authors. |
| listenarr.application/Repositories/IIndexerRepository.cs | Adds repository contract for indexers. |
| listenarr.application/Repositories/IHistoryRepository.cs | Adds repository contract for history. |
| listenarr.application/Repositories/IDownloadRepository.cs | Adds repository contract for downloads incl. targeted query methods. |
| listenarr.application/Repositories/IDownloadProcessingJobRepository.cs | Adds repository contract for processing jobs (incl. stats/retry APIs). |
| listenarr.application/Repositories/IDownloadHistoryRepository.cs | Adds repository contract for download history. |
| listenarr.application/Repositories/IDownloadClientConfigurationRepository.cs | Adds repository contract for download client configurations. |
| listenarr.application/Repositories/IAudiobookFileRepository.cs | Adds repository contract for audiobook files. |
| listenarr.application/Repositories/IApplicationSettingsRepository.cs | Adds repository contract for application settings. |
| listenarr.application/Repositories/IApiConfigurationRepository.cs | Adds repository contract for API configurations. |
| listenarr.api/tools/discord-bot/package.json | Bumps sanitize-html patch version. |
| listenarr.api/tools/discord-bot/package-lock.json | Locks sanitize-html patch version. |
| listenarr.api/Services/UserService.cs | Refactors to use IUserRepository and modern PBKDF2 API. |
| listenarr.api/Services/UnmatchedScanBackgroundService.cs | Refactors unmatched scanning to use repositories instead of DbContext. |
| listenarr.api/Services/StartupDbNormalizer.cs | Moves JSON normalization execution behind IAudiobookRepository. |
| listenarr.api/Services/SessionService.cs | Refactors session storage behind IUserSessionRepository. |
| listenarr.api/Services/Search/Strategies/MetadataStrategyCoordinator.cs | Removes direct DbContext imports in search strategy code. |
| listenarr.api/Services/Search/Strategies/IMetadataStrategy.cs | Removes direct DbContext imports in search strategy code. |
| listenarr.api/Services/Search/Strategies/AudnexusStrategy.cs | Removes direct DbContext imports in search strategy code. |
| listenarr.api/Services/Search/Strategies/AudibleMetadataStrategy.cs | Removes direct DbContext imports in search strategy code. |
| listenarr.api/Services/Search/SearchValidation.cs | Removes direct DbContext imports in search validation. |
| listenarr.api/Services/Search/Providers/TorznabNewznabSearchProvider.cs | Removes direct DbContext imports in provider. |
| listenarr.api/Services/Search/Providers/MyAnonamouseSearchProvider.cs | Refactors to persist MamId via IIndexerRepository. |
| listenarr.api/Services/Search/Providers/InternetArchiveSearchProvider.cs | Removes direct DbContext imports in provider. |
| listenarr.api/Services/Search/MetadataMerger.cs | Removes direct DbContext imports in metadata merging. |
| listenarr.api/Services/Search/MetadataConverters.cs | Removes direct DbContext imports in converters. |
| listenarr.api/Services/Search/Filters/SearchResultFilterPipeline.cs | Removes direct DbContext imports in filter pipeline. |
| listenarr.api/Services/Search/Filters/PromotionalTitleFilter.cs | Removes direct DbContext imports in filter. |
| listenarr.api/Services/Search/Filters/ProductLikeTitleFilter.cs | Removes direct DbContext imports in filter. |
| listenarr.api/Services/Search/Filters/MissingInformationFilter.cs | Removes direct DbContext imports in filter. |
| listenarr.api/Services/Search/Filters/KindleEditionFilter.cs | Removes direct DbContext imports in filter. |
| listenarr.api/Services/Search/Filters/ISearchResultFilter.cs | Removes direct DbContext imports in filter interface. |
| listenarr.api/Services/Search/Filters/AudiobookOnlyFilter.cs | Removes direct DbContext imports in filter. |
| listenarr.api/Services/Search/AsinSearchHandler.cs | Removes direct DbContext imports in handler. |
| listenarr.api/Services/Search/AsinCandidateCollector.cs | Removes direct DbContext imports in collector. |
| listenarr.api/Services/Scoring/SearchResultScorer.cs | Refactors indexer retention lookup to IIndexerRepository. |
| listenarr.api/Services/Scoring/CompositeScorer.cs | Cleans up model imports after layering changes. |
| listenarr.api/Services/RenameService.cs | Refactors rename persistence to IAudiobookRepository/History repository. |
| listenarr.api/Services/QualityProfileService.cs | Refactors to repository-based persistence; injects optional indexer repo. |
| listenarr.api/Services/ProcessExecutionStore.cs | Refactors persistence to IProcessExecutionLogRepository. |
| listenarr.api/Services/NzbUrlResolver.cs | Refactors indexer lookup to IIndexerRepository. |
| listenarr.api/Services/MoveQueueService.cs | Refactors move job persistence to IMoveJobRepository. |
| listenarr.api/Services/MoveBackgroundService.cs | Refactors DB operations to repositories; updates DTO build path. |
| listenarr.api/Services/MetadataRescanService.cs | Refactors metadata-rescan persistence to repositories. |
| listenarr.api/Services/LibraryAddService.cs | Refactors history writes to IHistoryRepository and hashing API updates. |
| listenarr.api/Services/IDownloadProcessingQueueService.cs | Removes embedded QueueStats type in favor of domain model. |
| listenarr.api/Services/FileProcessingHandler.cs | Refactors download lookup to IDownloadRepository. |
| listenarr.api/Services/FileFinalizer.cs | Removes scoped DbContext sync workaround; relies on repository updates. |
| listenarr.api/Services/DownloadValidationPipeline.cs | Refactors to IDownloadHistoryRepository interface. |
| listenarr.api/Services/DownloadStateMachine.cs | Refactors to IDownloadHistoryRepository interface. |
| listenarr.api/Services/DownloadQueueService.cs | Updates to use application-layer download repository interface. |
| listenarr.api/Services/DownloadHashRetrievalService.cs | Refactors to IDownloadHistoryRepository interface. |
| listenarr.api/Services/CompletedDownloadHandlingService.cs | Refactors to IDownloadRepository (with remaining in-memory filtering). |
| listenarr.api/Services/AudiobookMatchingService.cs | Refactors audiobook lookup to IAudiobookRepository. |
| listenarr.api/Services/AudiobookDtoFactory.cs | Removes DbContext dependency from DTO building. |
| listenarr.api/Repositories/IRootFolderRepository.cs | Deletes API-layer repository contract (moved to application). |
| listenarr.api/Repositories/IDownloadRepository.cs | Deletes API-layer repository contract (moved to application). |
| listenarr.api/Repositories/IDownloadProcessingJobRepository.cs | Deletes API-layer repository contract (moved to application). |
| listenarr.api/Repositories/EfRootFolderRepository.cs | Deletes API-layer EF repo (moved to infrastructure). |
| listenarr.api/Repositories/EfDownloadProcessingJobRepository.cs | Deletes API-layer EF repo (moved to infrastructure). |
| listenarr.api/Program.cs | Switches startup wiring to AddListenarrInfrastructure(sqliteDbPath) and updates forwarded headers API. |
| listenarr.api/Listenarr.Api.csproj | Removes explicit Authorization package reference. |
| listenarr.api/Extensions/ServiceRegistrationExtensions.cs | Removes persistence wiring (moved to infrastructure extension). |
| listenarr.api/Extensions/ServiceProviderExtensions.cs | Deletes helper for resolving DbContext via provider/factory. |
| listenarr.api/Extensions/AppServiceRegistrationExtensions.cs | Removes API-layer repo registrations (now infrastructure-provided). |
| listenarr.api/Dockerfile.runtime | Upgrades base runtime/toolchain and pins npm sub-deps to address CVEs. |
| listenarr.api/Controllers/RootFoldersController.cs | Refactors controller to use repositories for tracked file-path checks. |
| global.json | Pins repo SDK to .NET 10 preview/toolchain settings. |
| fe/vite.config.ts | Adds proxy error handling to reduce startup noise and improve resilience. |
| fe/src/views/library/CollectionView.vue | Removes unused author count computed properties. |
| fe/src/views/activity/ActivityView.vue | Removes unused formatting helpers. |
| fe/src/stores/libraryImport.ts | Tightens types; improves error handling for 409 “already in library” path. |
| fe/src/components/settings/RootFolderFormModal.vue | Fixes var usage in save logic. |
| fe/src/components/feedback/ManualImportModal.vue | Adds stable keys for v-for; improves type signatures for field accessors. |
| fe/src/tests/libraryImport.store.spec.ts | Tightens types; sets action in test setup. |
| fe/src/tests/LibraryImportSearchModal.spec.ts | Tightens types for mocked API results. |
| fe/src/tests/LibraryImportFooter.spec.ts | Tightens types; replaces unsafe cast/spying patterns. |
| fe/src/tests/EditAudiobookModal.moveOptions.spec.ts | Switches to vi.mocked(...) usage for safer mocks. |
| fe/package.json | Updates frontend toolchain versions (vite/vitest/visualizer/start-server-and-test). |
| Dockerfile | Upgrades base images to .NET 10. |
| Directory.Packages.props | Updates core package versions; updates test package to ASP.NET Core 10. |
| Directory.Build.props | Updates default target framework to net10.0. |
| .github/workflows/run-tests.yml | Modernizes CI: .NET 10 + Node 24, adds frontend steps + layering/async-void enforcement + publish step. |
| .github/workflows/release.yml | Updates release workflow to .NET 10 + Node 24. |
| .github/workflows/nightly.yml | Updates nightly workflow to .NET 10 + Node 24. |
| .github/workflows/codeql.yml | Updates CodeQL .NET toolchain to .NET 10. |
| .github/workflows/ci.yml | Removes legacy CI workflow (superseded). |
| .github/workflows/canary.yml | Updates canary workflow to .NET 10 + Node 24. |
Files not reviewed (2)
- fe/package-lock.json: Language not supported
- listenarr.api/tools/discord-bot/package-lock.json: Language not supported
Comments suppressed due to low confidence (1)
listenarr.api/Services/MoveQueueService.cs:126
- UpdateJobStatus also blocks synchronously on SignalR SendAsync via GetAwaiter().GetResult(). If a hub connection is slow/unavailable this can stall the caller thread. Prefer firing the broadcast asynchronously (e.g.,
_ = hub.Clients.All.SendAsync(...)) or make the method async and await with proper timeouts/cancellation.
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 92ab409879
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
Use targeted repository queries instead of loading all downloads: CompletedDownloadHandlingService now calls GetCompletionCandidatesAsync(500) and GetActiveForMonitoringAsync to avoid fetching the entire downloads table. Move settings-preservation logic earlier in ConfigurationService so existing fields are preserved before normalization and remove the duplicated preservation block. Simplify AudiobookRepository JSON normalization by filtering column names with a regex (ensuring safe SQL identifiers) and removing the redundant allowedColumns check. In tests, always register a mocked IIndexerRepository to avoid injecting a DbContext into a singleton factory (prevents lifetime violations). These changes improve performance, safety, and test stability.
Change SDK rollForward from "latestMajor" to "latestMinor" in global.json. This makes the .NET SDK auto-roll to the latest minor releases (preventing automatic major-version roll-forward) while keeping the SDK pinned to 10.0.100 and still allowing prerelease builds.
T4g1
left a comment
There was a problem hiding this comment.
I feel like Sqlite and In memory for test could benefit from being their own provider but looking at the implementation it would mean defining their own repositories too
Rename .github/workflows/nightly.yml to beta.yml and convert workflow from targeting develop/nightly to targeting beta/beta builds: update job names, branch refs, artifact names, Docker image tags, prerelease tag format (v{VERSION}-beta), and notification text. Update canary workflow prerelease tag to v{VERSION}-canary. Adjust run-tests workflow to run on beta instead of develop. Update CONTRIBUTING.md and README.md to document the new branching model (canary → beta → main), PR targeting rules, and revised version bump/semver behavior for canary/beta/release builds.
Add a new .github/CODEOWNERS file to require @Listenarrs/maintainers review for all PRs and key files (CI workflows, security/legal files, Docker, and dependency manifests). Update .github/WARP.md to list Docker tags (latest, stable, canary, beta) and add CI versioning rules for canary, beta, and release builds. Update SECURITY.md to direct vulnerability reports to GitHub Private Vulnerability Reporting instead of an email address.
- Replace "Robbie Davis" with "Listenarr Contributors" across all source files - Update copyright year from 2024-2025 to 2024-2026 - Add NOTICE file (required by AGPLv3 §4 for distribution) - Add AGPLv3 copyright headers to 493 C# files and 229 frontend files - Replace sidebar "Source" text link with GitHub icon (AGPLv3 §13)
There was a problem hiding this comment.
I cant really review the workflow themselves because i got no idea how this works but regarding the process, I'm not convinced by automatic version numbering and automatic release.
I would recommend a manual tagging approach that then triggers the workflow if possible
Also, the changelog updates could probably be delayed until we merge to either beta or main (its easier for contributors too that way as they dont have to be involved in the software lifecycle and can focus on the feature): We would simply have to look at the git log or PR history to know what we should include in it or not
Convert JS-style /* ... */ license headers to HTML <!-- ... --> comments across many Vue single-file components so the license appears correctly in SFC templates. Also tweak App.vue: remove the SVG's fill="currentColor" and update .sidebar-source-link styles to use svg fill + transition and hover fill (with a hover media query) instead of opacity—adjusting how the GitHub/source icon is colored on hover.
Refactor code to use global usings and shorter type names across the API: remove many fully-qualified type references (e.g. Listenarr.Api.Services.* and System.Collections.Generic.*) in favor of direct types (List<>, Dictionary<>, Audible*, SearchRequest, etc.). Update dependency injection registrations and resolutions to use the simplified types (including HttpClients, adapters, options, repositories, hosted services and SignalR IHubContext<DownloadHub>). Rename a few local fields for clarity (e.g. _downloadRepo -> _downloadRepository) and adjust related usages. Miscellaneous small fixes: punctuation/c comment cleanups and a couple of repository/interface file moves to Repositories folders. Tests and DI wiring updated accordingly.
Refactor CI to use PR labels for canary versioning and include a short commit SHA in artifacts/tags. Key changes: - Canary workflow: trigger on PR closed (merged) and workflow_dispatch; determine bump type (patch/minor/major) from PR labels; support manual dispatch with no bump; compute TARGET_VERSION accordingly; simplified PR info extraction using github-script; include SHORT_SHA in artifact names, upload names and docker tags. - Beta workflow: treat beta as a stabilization snapshot of canary (no version bump), use canary version as-is; compute and propagate SHORT_SHA; include SHA in zip names, artifact upload name, and prerelease tag/name; adjust actor check to exclude github-actions[bot]. - Release workflow: allow workflow_dispatch with tag input or use ref name; verify the tagged commit is reachable from beta before proceeding. - Add validate-pr-labels workflow: a blocking check (when enabled in branch protection) that enforces exactly one of patch/minor/major labels on canary PRs. - Docs: update README and CONTRIBUTING to explain label-driven canary bumps, beta behaviour, and the branch-protection requirement for the label check. These changes make version bumps explicit via PR labels, produce traceable artifact names with short SHAs, and add validation to reduce accidental merges without version metadata.
Add a post-release workflow step that opens a PR from main → canary to forward any hotfixes introduced during the beta stabilisation window. The step checks for an existing open PR, uses the gh CLI to create one with a descriptive title/body, and exits gracefully if there are no differences or a PR already exists. Note: the PR is not auto-merged — version file conflicts must be resolved manually (keep canary's version number). GITHUB_TOKEN is used for authentication.
Grant explicit `contents: read` and `pull-requests: read` permissions to the validate-pr-labels GitHub Actions workflow so it can access repository contents and PR metadata when processing label events. This narrows token scope to required read-only rights and avoids relying on default permissions.
Fix a typo/unprintable character in a comment handling HTTP 409 response in fe/src/stores/libraryImport.ts. Replaced the stray character with a comma to make the comment read: "409 = book already in library, extract existing audiobook from response body" — no functional changes.
Add a top-level .editorconfig establishing repo-wide editor settings (utf-8, LF, final newline, trim trailing whitespace, default 4-space indent) with language-specific overrides for C#, XML/project files, YAML, JSON, Markdown, shell scripts, and Windows batch/PowerShell. Also update fe/.editorconfig to set root = true so it owns frontend file types (JS/TS/Vue/CSS/etc.), ensuring consistent formatting across the repo.
T4g1
left a comment
There was a problem hiding this comment.
A lot of nice changes, i would just recommend cleaning those workflow to avoid logic duplication but otherwise i can't wait to see this merged 👍
Add a new reusable workflow (.github/workflows/build-and-publish.yml) that centralizes .NET build, publishing, artifact zipping, GH Release creation, Docker image build/push, and Discord notifications. Update beta, canary and release workflows to compute version/PR metadata and short SHA, expose them as job outputs, and delegate the heavy lifting to the new reusable workflow, removing large amounts of duplicated steps. Pass channel, docker tags, release metadata and PR info into the reusable workflow so release logic and sanitization are unified.
Enable trimming of trailing whitespace for Markdown files in .editorconfig and remove the debug-level MinimumLevel.Override for TransmissionAdapter in Program.cs. This reduces noisy debug logs from the Transmission adapter and enforces consistent Markdown whitespace trimming.
|
@T4g1 Good for hopefully a last review here |
|
lgtm! Can't wait to see how the rebase for other PR will go 😭 |
Refactor: renamed repository fields, constructor parameters and local variables from names like _indexerRepo / indexerRepo to _indexerRepository / indexerRepository (and similar for other repos) and updated all usages. Changes span controllers, services and tests (e.g. IndexersController, LibraryController, ProwlarrCompatController, RootFoldersController, AudioFileService, AutomaticSearchService, CompletedDownloadHandlingService, CompletedDownloadProcessor, ConfigurationService, and related tests). Purely a naming/clarity refactor with no functional changes.
Summary
This one's been a while coming. The API layer was directly importing EF Core types so controllers and services had
ListenArrDbContextinjected all over the place, making it impossible to unit test without spinning up a real database and tightly coupling business logic to persistence details. This PR fixes that, and takes the opportunity to upgrade the runtime stack at the same time.Added
listenarr.application/Repositories/(IDownloadRepository,IDownloadHistoryRepository,IHistoryRepository,IIndexerRepository,IUserRepository,IUserSessionRepository,IApplicationSettingsRepository,IApiConfigurationRepository,IDownloadClientConfigurationRepository,IRemotePathMappingRepository,IAudiobookFileRepository,IMoveJobRepository,IMonitoredAuthorRepository,IMonitoredSeriesRepository,IProcessExecutionLogRepository,IDownloadProcessingJobRepository,IRootFolderRepository)listenarr.infrastructure/Repositories/(EfHistoryRepository,EfIndexerRepository,EfUserRepository,EfUserSessionRepository,EfApplicationSettingsRepository,EfApiConfigurationRepository,EfDownloadClientConfigurationRepository,EfRemotePathMappingRepository,EfAudiobookFileRepository,EfMoveJobRepository,EfMonitoredAuthorRepository,EfMonitoredSeriesRepository,EfProcessExecutionLogRepository)IDatabaseConnectionProvider/EfDatabaseConnectionProviderfor exposing raw connection info without leaking EF typesQueueStatsdomain model for download processing queue metricsrun-tests.ymlnow fails the build if any file outsideProgram.csin the API layer imports fromlistenarr.infrastructure, or if anyasync voidappears in production codeIDownloadRepository:GetCompletionCandidatesAsync,GetActiveForMonitoringAsync,GetRecentAsync,GetActiveAudiobookIdsAsync— replaces hot-pathGetAllAsync()+ in-memory LINQ in several background servicesChanged
global.json,Directory.Build.props, both Dockerfiles)golang:1.24-alpine→golang:1.26-alpineto pull in a patched Go stdlibDockerfile.runtimeEfDownloadProcessingJobRepositoryandEfRootFolderRepositorymoved fromlistenarr.api/Repositories/tolistenarr.infrastructure/Repositories/where they belongListenArrDbContextorIDbContextFactory<ListenArrDbContext>now inject the appropriate application-layer interface(s)InfrastructureServiceRegistrationExtensions.AddListenarrInfrastructure()is now the single DI registration surface for all repositories;Program.csis the only API-layer file that references infrastructureAddDbContext + manual SimpleDbContextFactory singletonwith a singleAddDbContextFactory<ListenArrDbContext>(ServiceLifetime.Singleton)call, which registers both the factory and a scoped context automaticallyrun-tests.ymladds concurrency group (cancel-in-progress on re-push), switches from matrix to env vars, upgradessetup-dotnetto v4, and adds a publish step for linux-x64vite.config.tsadds explicit type annotation for the visualizer plugin to satisfy TypeScript strict checkingFixed
picomatch@4.0.4andbrace-expansion@2.0.3inside the npm install inDockerfile.runtimeto resolve CVEs present in the versions bundled with npm 11TestDownloadRepository.ToQueueTrackedDownloadProjectionwas missingAudiobookIdandLanguagefields present in the EF implementation — queue display tests would pass even if downstream code relying on those fields was brokenTestDownloadProcessingJobRepository.GetDueRetryJobsAsyncwas returning results in insertion order instead ofPriority DESC, NextRetryAt ASC, diverging from the EF implementationTestDownloadProcessingJobRepository.GetStatsAsyncwas returning an emptyQueueStatsobject instead of computing real counts — any test asserting on queue metrics would always passGetDueRetryJobsAsynclacked aCancellationTokenparameter on both the interface and implementation, inconsistent with every other async method in the same repositoryRemoved
.github/workflows/ci.yml— old CI workflow that targetedmain/masterbranches and was never triggered; superseded byrun-tests.ymllistenarr.api/Extensions/ServiceProviderExtensions.cs— no longer needed after DI wiring moved to infrastructurelistenarr.api/Repositories/EfDownloadProcessingJobRepository.cs,EfRootFolderRepository.cs— moved to infrastructurelistenarr.api/Repositories/IDownloadProcessingJobRepository.cs,IDownloadRepository.cs,IRootFolderRepository.cs— moved to application layerSimpleDbContextFactory— made redundant byAddDbContextFactory