feat(packaging): require canonical Abstractions#389
Closed
RicherTunes wants to merge 81 commits intomainfrom
Closed
feat(packaging): require canonical Abstractions#389RicherTunes wants to merge 81 commits intomainfrom
RicherTunes wants to merge 81 commits intomainfrom
Conversation
Changes rootNamespace from Lidarr.Plugin.Brainarr to NzbDrone.Core.ImportLists.Brainarr to match the actual namespace used in source code. Validated with Common's ManifestCheck.ps1 -ResolveEntryPoints. Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- build.ps1: Add -ResolveEntryPoints to New-PluginPackage - plugin.json: Remove deprecated keys (minimumVersion, entryPoint, dll) and normalize to standard schema (homepage, license) Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- Bump ext/lidarr.plugin.common to cfb131f - Update ext-common-sha.txt - Add .github/workflows/packaging-gates-caller.yml calling Common workflow
Replace legacy schema (minimumVersion, entryPoint, dll, website, etc.) with ecosystem canonical format (minHostVersion, main, rootNamespace). This aligns with the shared library's manifest validation requirements and fixes the ajv-validate CI job.
Fix newline corruption that broke parsing and remove injected literal artifacts. Add a CI parse-check step in sanity-build.yml to prevent regressions.
Contributor
Dependency ReviewThe following issues were found:
License Issues.github/workflows/quarantine-review.yml
OpenSSF Scorecard
Scanned Files
|
Extract focused manager classes from the 1500+ line orchestrator: - IProviderLifecycleManager/ProviderLifecycleManager: Provider init, health, testing - IModelOptionsProvider/ModelOptionsProvider: Model detection and options - IReviewQueueManager/ReviewQueueManager: Review queue operations - IBrainarrUIActionHandler/BrainarrUIActionHandler: UI action handling This reduces BrainarrOrchestrator to ~900 lines while maintaining full backward compatibility through DI with optional constructor parameters. Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- Add test-runner-allowlist.json for category enforcement - Add quarantine-review.yml for flaky test monitoring - Update CI workflows with category lint integration - Align with Common's E2E infrastructure improvements Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- Remove unused using statements across test files - Update test categorization for category enforcement - Update packages.lock.json for new dependencies Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- Update README with improved architecture documentation - Add documentation navigation and learning paths - Update CONTRIBUTING.md with clearer guidelines - Bump ext-common-sha.txt to latest - Add test.ps1 and test-packaging.ps1 scripts Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- Update remaining test files with Area trait - Remove unused imports from configuration provider tests - Clean up test assertions and simplify mocks Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- Add ZaiGlmChatCompletionsUrl for Z.AI GLM API endpoint - Add DefaultZaiGlmModel (glm-4.7-flash) for free tier default
- Create ZaiGlmProvider implementing IAIProvider - Add ZaiGlm to AIProvider enum (value 11) - Add ZaiGlmModelKind enum with all GLM model tiers - Add zai-glm case to ModelIdMapper for model name mapping - Add ZaiGlm case to ProviderCapabilities (OpenAI-compatible) - Z.AI business error code handling (1000-1004, 1110-1121, 1300-1309) - Content filter handling for finish_reason: sensitive - GLM-4.7/4.6 default temperature of 1.0
- Add NormalizeZaiGlm method with model value mappings - Add _zaiGlmModelValues HashSet for valid enum values - Add _zaiGlmModelAliases Dictionary for raw model ID mappings - Support conversion between enum names and raw model IDs (glm-4.7-flash, etc.) Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
BrainarrSettings.cs: - Add ZaiGlmApiKey and ZaiGlmModelId properties - Add ZaiGlm cases to ModelSelection getter/setter - Add ZaiGlm cases to ApiKey getter/setter - Add ZaiGlm cases to GetProviderSettings, GetCurrentProviderModel - Add ZaiGlm cases to ClearCurrentProviderModel, ClearPreviousProviderModel - Add ZaiGlm cases to GetDefaultModelForProvider, GetModelForProvider - Add ZaiGlm cases to SetModelForProvider, GetApiKeyForProvider AIProviderFactory.cs: - Add ZaiGlm case to CheckProviderAvailability - Add ZaiGlm cases to GetProviderApiKey, SetProviderApiKey - Add ZaiGlm cases to GetProviderModelId, SetProviderModelId ProviderRegistry.cs: - Register AIProvider.ZaiGlm with ZaiGlmProvider factory - Add MapZaiGlmModel method delegating to ModelIdMapper Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- Constructor validation tests (valid, null, empty, whitespace API keys) - GetRecommendationsAsync tests (valid response, empty content, content filter) - HTTP error tests (401, 403, 500 return empty lists) - Z.AI business error code mapping (1002 auth, 1113 quota, 1305 rate, 1211 model) - TestConnectionAsync tests (success, failure, API error in body) - UpdateModel tests (valid, null, empty model handling)
- Add ZaiGlm => 'zai-glm' to ProviderSlugs.ToRegistrySlug - Update ProviderSlugsTests expectations for ZaiGlm - Fixes test: ToRegistrySlug_MapsAllProviders Full test suite: 2053 passed, 7 failed (pre-existing), 29 skipped
Add 6 high-value edge case tests: - Timeout handling (TaskCanceledException) - Cancellation handling (OperationCanceledException) - 429 Too Many Requests rate limit response - Malformed JSON response (invalid syntax) - Unexpected JSON schema (missing choices) - Null choices in response All return empty list gracefully instead of crashing. Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Quarantine WithHttpResilienceAsync_EnforcesConcurrencyCapPerHost: - Passes in isolation, fails under parallel test execution - Classic timing/parallelism flake, not a real regression - Tracked for weekly lane review Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Add manifest.json to csproj Content Include so it gets copied to output directory during build and included in package. Fixes BrainarrPackagingPolicyTests.Package_Should_Contain_Required_Files. Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Add tests to verify that API keys in inner exception chains are properly redacted and don't leak through logs: - GetRecommendations_WithInnerExceptionContainingApiKey_DoesNotLogApiKey - GetRecommendations_WithNestedInnerExceptions_DoesNotLogApiKey These tests confirm the existing redaction implementation handles inner exceptions correctly, guarding against potential leaks from HTTP client internals or deeply nested exception chains. Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
The unified test runner doesn't support --settings, which prevents coverlet from using the configured include/exclude rules in test.fast.runsettings. This caused coverage files to have lines-valid=0. Switch to direct dotnet test call with --settings parameter to ensure proper coverage instrumentation on Linux CI runners. Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- Update reusable workflow reference from @a7050c6 to @1f8bc74 to match the current ext/lidarr.plugin.common submodule - Add explicit permissions: contents: read Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Add comprehensive security contract tests for Z.AI GLM provider: - Inner exception chain redaction (API keys in nested exceptions) - 403 Forbidden handling - 503 Service Unavailable handling - Content filtered response handling Brings Z.AI GLM security test parity with OpenAI provider. Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Add comprehensive security contract tests for Gemini provider: - Inner exception chain redaction (API keys in nested exceptions) Brings Gemini security test parity with OpenAI and Z.AI GLM providers. Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Add inner exception chain redaction tests to achieve security test parity across all AI providers: - Anthropic - DeepSeek - Groq - OpenRouter - Perplexity All providers now have comprehensive security contract tests ensuring API keys are not leaked through exception chains or error messages. Total security tests: 98 (all passing) Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
The reusable workflow at packaging-gates.yml@1f8bc74 exists in the local Common submodule but hasn't been pushed to the remote GitHub repo yet (remote is at 16cd708a). Temporarily disable auto-trigger until the Common PR containing packaging-gates.yml is merged. Workflow can still be manually triggered. Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
The test category linter from Common only has a few approved categories: Integration, Packaging, LibraryLinking, Benchmark, Slow. Brainarr uses additional categories for provider testing: - Security: API key redaction and credential safety tests - Contract: Provider API contract tests - Configuration: Settings validation tests - E2E: End-to-end stub tests - Hermetic: Tests that don't require external dependencies Pass these as -AllowedCategories to the linter. Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- Extract ClaudeCodeProviderFactory to Providers namespace to avoid Core layer depending on concrete ClaudeCode types (layering guard) - Add test-and-coverage.yml to unified runner allowlist (--settings runsettings parameter not supported by unified runner) - Fix whitespace formatting in RecommendationValidatorTests and HallucinationDetectorTests Fixes CI failures: - Layering Guards: ProviderRegistry.cs no longer imports ClaudeCode - Parity Lint: test-and-coverage.yml allowlisted with expiry - Check formatting: dotnet format applied to test files Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- Remove line_pattern from test-and-coverage.yml allowlist entry (file-level allowlist is sufficient for coverage workflow) - Apply dotnet format auto-fixes to OpenAIProviderContractTests Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Add architecture tests that enforce layer dependencies via static analysis: - Core_Should_Not_Reference_Providers_ClaudeCode_Namespace: Prevents regression of fix in 5ee501c where Core depended on ClaudeCode - Core_Should_Not_Reference_Any_Providers_SubNamespace: Generalizes the rule to all provider sub-namespaces - Providers_Should_Not_Reference_Services_Core: Enforces reverse dependency rule These tests run as part of Category=Architecture and Category=Contract, providing fast feedback if layering violations are reintroduced. Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Add comprehensive edge case tests for Z.AI GLM provider: HTTP status codes: - 400 Bad Request, 502 Bad Gateway, 504 Gateway Timeout Response parsing edge cases: - Non-numeric error codes (malformed API response) - Missing message field in choices - Missing finish_reason (should still parse content) - Empty choices array - finish_reason "length" (truncated response) Network-level failures: - DNS resolution failure (SocketException 11001) - Connection refused (SocketException 10061) Total: 28 contract tests covering full negative-path checklist. Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
…+ add conformance tests ## Provider Consolidation (~1,192 lines saved) - DeepSeekProvider: 385 → 90 lines (77% reduction) - GroqProvider: 419 → 97 lines (77% reduction) - PerplexityProvider: 495 → 203 lines (59% reduction) - OpenRouterProvider: 477 → 169 lines (65% reduction) All providers now inherit from HttpChatProviderBase, implementing only: - ProviderName, DefaultModel, ApiUrl (abstract properties) - ConfigureHeaders(), CreateRequestBody(), ExtractContent() (abstract methods) - LogTokenUsage() (optional override) ## Conformance Contract Suite (52 new tests) - Header correctness: Authorization format, Content-Type - Request body shape: Required fields validation - Log redaction: API keys never in logs (error & success paths) - Exception safety: No credential leaks in exceptions - Error mapping parity: 401/403/429/5xx handling consistency ## Deterministic Testing - Added TimeProvider support to ConcurrentCache for fake clock injection - Cache expiration test: 3s Task.Delay → instant FakeTimeProvider (17ms) - ResilienceTests collection: Documented isolation policy ## ADR-002: Subscription Authentication - NO-GO decision for OpenAI/Gemini subscription auth - Documents that subscriptions don't provide API access - Recommends API key authentication only Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- ProviderLifecycleManager: Check IsProviderAvailable before CreateProvider - ProviderManager: Same pattern - log warning and disable gracefully - Both classes now track provider type even when disabled - Empty credentials no longer throw exceptions during initialization Implements Month 3 roadmap item: Empty key disables provider Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- Z.AI GLM provider with extended tests and edge cases - HttpChatProviderBase consolidation (4 providers, ~1,400 LOC reduction) - Inner exception redaction for all cloud providers - Claude Code NDJSON streaming support - Layering contract tests for architectural validation - FakeTimeProvider for deterministic CircuitBreaker tests - Workflow auth lint for CI Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- Add Quick Links section with documentation shortcuts - Link to ecosystem overview for plugin comparison - Organize links: README, Configuration, Troubleshooting, Architecture Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Add IsProviderAvailable mock setup to 15 test files to support the graceful provider disable feature. Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- Add Architecture category for layering contract tests - Add Conformance category for base class conformance tests - Remove unused parameters from theory methods to fix xUnit1026 warnings Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
MemberData provides 4 values but my previous edit removed the 4th parameter from several test methods, causing xUnit binding failures. Restore the `string __` discard parameter to maintain compatibility with the HttpChatProviders() data source. Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
…tests Create HttpChatProvidersWithApiKey() for log redaction tests that need the apiKey parameter, while HttpChatProviders() now returns only 3 values for all other tests. This fixes the conflict between dotnet format removing unused parameters and xUnit theory binding requiring matching parameter counts. Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- Remove 4th param from Provider_SetsAuthorizationHeader_WithCorrectFormat (uses HttpChatProviders which returns 3 values) - Change Provider_DoesNotExposeApiKey_InExceptions to use HttpChatProvidersWithApiKey (needs apiKey for assertions) Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Root cause: Readers could complete all iterations before the writer started, causing successCount=0 and flaky test failure. Fix: 1. Pre-populate cache with initial data before concurrent operations 2. Add ManualResetEventSlim barrier so readers wait for writer to start 3. Add timeout on barrier to prevent hanging if writer fails The test still verifies that concurrent reads/writes don't corrupt data (artistNum must equal albumNum in all read results). Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
The Stress_RecommendationCache_ConcurrentWrites_And_Reads test was failing nightly because it created 500 items (25 tasks × 20 items) but the cache evicts entries when exceeding MaxCacheEntries (100). Root cause: This wasn't a flaky test - the cache was correctly evicting entries per its design. The test simply didn't account for the cache limit. Fix: Reduce itemsPerTask from 20 to 4, keeping total items at exactly 100 (25 × 4 = 100) while maintaining high concurrency for stress testing. Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
…flow Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
…re workflow Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
The nightly workflow filters for Category=Stress but the test had Category=Slow. Updated to Category=Stress so the test actually runs in the nightly Perf/Stress workflow. Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
…ence policy The ExecuteRequestAsync method was hardcoding DefaultAITimeout (30s) for the resilience policy's perRequestTimeout, even when called from TestConnectionAsync which uses a shorter TestConnectionTimeout (10s). This mismatch caused the Jan 28 nightly failure where the test took 30s due to the inner timeout being used for retry delays instead of the outer 10s timeout. Changes: - Add optional timeoutSecondsOverride parameter to ExecuteRequestAsync - TestConnectionAsync now explicitly passes TestConnectionTimeout (10s) - Update test trait from "Slow" to "Unit" since it now completes in ~2s Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Add .test-categories.json to approve additional test categories used by the nightly Performance/Stress workflow. This fixes the Parity Lint failure caused by the "Stress" category not being in the built-in list. Categories added: - Performance: Nightly performance tests - Stress: Nightly stress tests (e.g., cache concurrency) - Unit, Contract, Security, etc.: Various test types Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Owner
Author
|
Superseded by #397 (reusable packaging-gates adoption, merged). Common submodule bumped to latest. |
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.
Depends on RicherTunes/Lidarr.Plugin.Common#307.
Local verification: