Build and Push Docker Image / build (push) Successful in 41s
Licence Check / Licence compatibility and copyright header verification (push) Successful in 56s
CI / Security audit (push) Successful in 1m6s
CI / Tests & coverage (push) Successful in 1m27s
Sonarr tracks the exact SAB download ID (nzo_id). Now tries to match
by downloadId first, then falls back to title matching. Also adds
debug to show if matches are via downloadId vs title, and logs
downloadIds in history to verify the link exists.
Build and Push Docker Image / build (push) Successful in 39s
Licence Check / Licence compatibility and copyright header verification (push) Successful in 53s
CI / Security audit (push) Successful in 1m10s
CI / Tests & coverage (push) Successful in 1m30s
When a match is found, logs whether it came from queue or history.
When no match, shows history counts and sample titles to verify
history is being checked properly.
Build and Push Docker Image / build (push) Successful in 44s
Licence Check / Licence compatibility and copyright header verification (push) Successful in 1m6s
CI / Security audit (push) Successful in 1m21s
CI / Tests & coverage (push) Successful in 1m34s
SAB items often persist after Sonarr has processed them.
Previously only checked the active queue, now also checks
history records so completed downloads still appear.
Build and Push Docker Image / build (push) Successful in 13s
Licence Check / Licence compatibility and copyright header verification (push) Successful in 46s
CI / Security audit (push) Has been cancelled
CI / Tests & coverage (push) Has been cancelled
SAB filenames use dots (dora.the.explorer.s02e08) but Sonarr titles
use spaces (Dora the Explorer - S02E08). Now tries matching with
both formats to improve match rate.
Also logs actual Sonarr titles when no match found for debugging.
Build and Push Docker Image / build (push) Successful in 29s
Licence Check / Licence compatibility and copyright header verification (push) Successful in 1m4s
CI / Security audit (push) Successful in 1m29s
CI / Tests & coverage (push) Successful in 1m49s
Shows exactly which SAB items match/don't match to Sonarr/Radarr:
- ✓ Sonarr match: SAB name → Sonarr name
- ✓ Radarr match: SAB name → Radarr name
- ✗ No match: SAB name (with Sonarr queue count)
This will help diagnose why Sonarr Activity Queue shows matches but Sofarr doesn't.
Build and Push Docker Image / build (push) Successful in 43s
Licence Check / Licence compatibility and copyright header verification (push) Successful in 1m7s
CI / Security audit (push) Successful in 1m28s
CI / Tests & coverage (push) Successful in 1m47s
SABnzbd API returns labels as an array in newer versions,
but the code assumed it was a comma-separated string.
Now handles both cases to prevent 'slot.labels.split is not a function' error.
Build and Push Docker Image / build (push) Successful in 46s
Licence Check / Licence compatibility and copyright header verification (push) Successful in 1m8s
CI / Security audit (push) Successful in 1m33s
CI / Tests & coverage (push) Successful in 1m41s
1. Fixed download client collision:
- SABnzbd client with id 'i3omb' was being overwritten by qBittorrent
- Now uses unique key ':' like the arr retrievers
2. Fixed webhook metrics showing 0:
- instanceName from webhooks is generic ('Sonarr', 'Radarr')
- Not the configured instance name ('i3omb')
- Now updates metrics for ALL instances of that type
Build and Push Docker Image / build (push) Successful in 33s
Licence Check / Licence compatibility and copyright header verification (push) Successful in 1m10s
CI / Security audit (push) Successful in 1m33s
CI / Tests & coverage (push) Successful in 1m52s
When Sonarr and Radarr had the same instance ID (e.g., 'i3omb'),
the Radarr retriever would overwrite the Sonarr retriever in the Map.
This caused webhook refreshes to show '0 instance(s)' for Sonarr.
Now uses ':' as the unique key so both can coexist.
Build and Push Docker Image / build (push) Successful in 46s
Licence Check / Licence compatibility and copyright header verification (push) Has been cancelled
CI / Security audit (push) Has been cancelled
CI / Tests & coverage (push) Has been cancelled
The status panel was showing webhooks as disabled (null) when no events
had been received yet. Now it checks Sonarr/Radarr API to see if the
Sofarr webhook notification is actually configured.
- Added checkWebhookConfigured() to verify webhook exists in Sonarr/Radarr
- Shows 'enabled: true' with 0 events when webhook is configured
- Only shows null when webhook is not configured at all
Build and Push Docker Image / build (push) Successful in 34s
Licence Check / Licence compatibility and copyright header verification (push) Successful in 1m3s
CI / Security audit (push) Successful in 1m20s
CI / Tests & coverage (push) Successful in 1m38s
Add debug logging to trace:
- When downloads payload is built
- Data sizes from cache (SAB, qBit, Sonarr, Radarr)
- Number of downloads found and their titles
This will help diagnose why Dora downloads aren't appearing.
Licence Check / Licence compatibility and copyright header verification (push) Successful in 1m8s
CI / Security audit (push) Successful in 1m28s
CI / Tests & coverage (push) Successful in 1m53s
Build and Push Docker Image / build (push) Successful in 35s
- Fixed webhooks section to load collapsed (content hidden, toggle arrow reset)
- Added webhook metrics card to status panel for admin users:
- Shows Sonarr/Radarr enabled/disabled status
- Shows events received and polls skipped counts
- Updated /api/dashboard/status endpoint to include webhook metrics
- Metrics are aggregated from all Sonarr/Radarr instances
Build and Push Docker Image / build (push) Successful in 41s
Licence Check / Licence compatibility and copyright header verification (push) Successful in 59s
CI / Security audit (push) Successful in 1m20s
CI / Tests & coverage (push) Successful in 1m33s
- Moved webhooks-section to be inline with status-panel in HTML
- Updated toggleStatusPanel() to show/hide webhooks section for admin users
- Updated closeStatusPanel() to also hide webhooks section
- Removed webhooks visibility from showDashboard() - now tied to status panel
- Updated CSS to make webhooks section styling consistent with status panel:
- Same border, border-radius, margin, box-shadow
- Updated webhook-stats to use status-card styling (background, border)
- Webhooks metrics now display inline with status panel for admin users
Build and Push Docker Image / build (push) Successful in 48s
Licence Check / Licence compatibility and copyright header verification (push) Successful in 1m9s
CI / Security audit (push) Successful in 1m23s
CI / Tests & coverage (push) Successful in 1m42s
The /notifications/test endpoint requires the full notification object,
not just the ID. Changed testSonarrWebhook() and testRadarrWebhook() to
send the complete notification object (sonarrSofarr/radarrSofarr).
Fixes: 400 validation error when testing webhooks
Build and Push Docker Image / build (push) Successful in 44s
Licence Check / Licence compatibility and copyright header verification (push) Successful in 1m6s
CI / Security audit (push) Successful in 1m17s
CI / Tests & coverage (push) Successful in 1m33s
The webhook notification payload was using string 'POST' for the method
field, but Sonarr/Radarr API expects numeric values:
- 1 = POST
- 2 = PUT
Also added onManualInteractionRequired: false to match the schema.
Fixes: Radarr/Sonarr rejecting webhook configuration with validation errors
Build and Push Docker Image / build (push) Successful in 31s
Licence Check / Licence compatibility and copyright header verification (push) Successful in 1m8s
CI / Security audit (push) Successful in 1m21s
CI / Tests & coverage (push) Successful in 1m36s
The notification routes were using process.env.SONARR_URL directly,
which is undefined when using the newer SONARR_INSTANCES JSON format.
Changes:
- Added getFirstSonarrInstance() and getFirstRadarrInstance() helpers
- Updated /notifications, /notifications/test, and /notifications/sofarr-webhook
routes to use instance config from getSonarrInstances()/getRadarrInstances()
- Returns 503 error if no instances are configured
Fixes: 'Invalid URL' errors when calling Sonarr/Radarr notification APIs
Build and Push Docker Image / build (push) Successful in 27s
Licence Check / Licence compatibility and copyright header verification (push) Successful in 1m3s
CI / Security audit (push) Successful in 1m19s
CI / Tests & coverage (push) Successful in 1m34s
Added detailed error logging to help diagnose 500 errors when calling
Sonarr/Radarr notification APIs. Logs include:
- Error message
- Response status (if available)
- Response data (if available)
This will help identify if the issue is:
- Missing SONARR_URL/RADARR_URL or API keys
- Network connectivity issues
- Sonarr/Radarr API version incompatibility
Build and Push Docker Image / build (push) Successful in 1m14s
Licence Check / Licence compatibility and copyright header verification (push) Successful in 1m8s
CI / Security audit (push) Successful in 1m22s
CI / Tests & coverage (push) Successful in 1m43s
The React build replaced the full-featured vanilla JS app with a
simpler UI, causing the dashboard to disappear and lose theming.
This commit:
- Restores original vanilla JS app with auth, themes, tabs, history
- Adds Webhooks Configuration panel for admin users
- Adds webhook status, enable/test buttons, triggers, and stats
- Uses proper CSS variables for theme support
Fixes the dashboard disappearing issue and restores all original functionality.
Webhook routes were only registered in app.js (the test factory) but
not in index.js (the production entry point). POST /api/webhook/*
was therefore falling through to the verifyCsrf middleware and being
rejected with 403 in production.
Inline onclick attribute was silently blocked by the server CSP nonce
policy. Replace with addEventListener after innerHTML is set.
chore: bump version to 1.5.0a
Build and Push Docker Image / build (push) Successful in 1m7s
Licence Check / Licence compatibility and copyright header verification (push) Successful in 1m15s
CI / Security audit (push) Successful in 1m44s
CI / Tests & coverage (push) Successful in 1m53s
- Added POST /api/webhook/sonarr and POST /api/webhook/radarr endpoints
- Implemented webhook secret validation via SOFARR_WEBHOOK_SECRET environment variable
- Added logging for all incoming webhook events using existing logToFile utility
- Returns HTTP 200 immediately to prevent webhook retries
- Mounted webhook routes before CSRF middleware (called by external services)
- Non-breaking: no changes to polling, caching, SSE, or any existing behavior
- Lays groundwork for Phase 2 (cache + SSE integration) without implementing it yet
Build and Push Docker Image / build (push) Successful in 40s
Licence Check / Licence compatibility and copyright header verification (push) Successful in 54s
CI / Security audit (push) Successful in 1m15s
CI / Tests & coverage (push) Successful in 1m20s
refactor(arr-retrievers): implement Pluggable *arr Retrieval Layer (PALDRA) (#19)
- Added abstract ArrRetriever base class and concrete PollingSonarrRetriever / PollingRadarrRetriever
- Created centralized ArrRetrieverRegistry (pure singleton, matching PDCA style)
- Refactored poller.js and historyFetcher.js to use the new pluggable registry
- 100% backward compatible: no changes to behavior, caching, SSE, performance, or APIs
This completes the PALDRA work from ticket #19 and lays the groundwork for webhook support.
Build and Push Docker Image / build (push) Successful in 20s
CI / Security audit (push) Successful in 1m18s
CI / Tests & coverage (push) Successful in 1m14s
Licence Check / Licence compatibility and copyright header verification (push) Successful in 54s
- Remove instanceConfig parameter from all retriever methods (getTags, getQueue, getHistory)
- Retriever instances now use this.url, this.apiKey, this.id instead of passed parameter
- Convert ArrRetrieverRegistry from class with convenience functions to pure singleton object
- Export singleton instance directly instead of class + convenience functions
- Update poller.js and historyFetcher.js to call methods on singleton directly
- All 261 tests pass with zero behavior changes
Build and Push Docker Image / build (push) Successful in 42s
Licence Check / Licence compatibility and copyright header verification (push) Successful in 46s
CI / Security audit (push) Successful in 1m21s
CI / Tests & coverage (push) Successful in 1m35s
- Create ArrRetriever abstract base class defining pluggable interface
- Implement PollingSonarrRetriever and PollingRadarrRetriever with HTTP polling
- Add ArrRetrieverRegistry for managing retriever instances
- Refactor poller.js to use retriever registry instead of direct Axios calls
- Update historyFetcher.js to use retriever registry
- Preserve all cache keys, TTLs, timing logs, SSE broadcasts, error handling
- Enable future webhook listeners without touching poller logic
CI / Tests & coverage (pull_request) Successful in 2m3s
- Replace vi.mock('axios') with nock for HTTP request mocking (ES/CJS interop issue)
- Fix RTorrentClient by mocking client.client.methodCall directly instead of xmlrpc module
- Fix downloadClients.test.js by manually adding mock clients to registry
- Fix qbittorrent.test.js to use getActiveDownloads() and normalized properties
- Fix integration test env var mocks and error assertions
- Fix SABnzbdClient size parsing and test fixtures
- Fix RTorrentClient ETA calculation expectation
All 261 tests now passing.
Build and Push Docker Image / build (push) Successful in 37s
Licence Check / Licence compatibility and copyright header verification (push) Successful in 45s
CI / Security audit (push) Successful in 1m3s
CI / Tests & coverage (push) Failing after 1m18s
- Convert all client test files from CommonJS require() to ES module import syntax
- Convert downloadClients.test.js and integration/downloadClients.test.js to ES modules
- Fix qbittorrent.test.js to use getActiveDownloads() instead of getTorrents()
- All test files now use proper Vitest-compatible ES module syntax
- Resolves Vitest import errors and QBittorrentClient method call errors