quasarr 2.4.10__tar.gz → 2.4.11__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.

Potentially problematic release.


This version of quasarr might be problematic. Click here for more details.

Files changed (96) hide show
  1. {quasarr-2.4.10 → quasarr-2.4.11}/.github/workflows/PullRequests.yml +65 -58
  2. {quasarr-2.4.10 → quasarr-2.4.11}/.github/workflows/Release.yml +43 -72
  3. {quasarr-2.4.10 → quasarr-2.4.11}/.gitignore +4 -0
  4. quasarr-2.4.11/.pre-commit-config.yaml +9 -0
  5. {quasarr-2.4.10 → quasarr-2.4.11}/CONTRIBUTING.md +9 -3
  6. {quasarr-2.4.10 → quasarr-2.4.11}/PKG-INFO +1 -1
  7. quasarr-2.4.10/maintenance.py → quasarr-2.4.11/pre-commit.py +42 -53
  8. {quasarr-2.4.10 → quasarr-2.4.11}/pyproject.toml +5 -2
  9. {quasarr-2.4.10 → quasarr-2.4.11}/quasarr/__init__.py +3 -3
  10. {quasarr-2.4.10 → quasarr-2.4.11}/quasarr/api/__init__.py +1 -1
  11. {quasarr-2.4.10 → quasarr-2.4.11}/quasarr/api/captcha/__init__.py +1 -1
  12. {quasarr-2.4.10 → quasarr-2.4.11}/quasarr/api/config/__init__.py +1 -1
  13. {quasarr-2.4.10 → quasarr-2.4.11}/quasarr/api/sponsors_helper/__init__.py +2 -2
  14. {quasarr-2.4.10 → quasarr-2.4.11}/quasarr/downloads/linkcrypters/hide.py +1 -1
  15. {quasarr-2.4.10 → quasarr-2.4.11}/quasarr/downloads/packages/__init__.py +5 -5
  16. {quasarr-2.4.10 → quasarr-2.4.11}/quasarr/downloads/sources/al.py +1 -1
  17. {quasarr-2.4.10 → quasarr-2.4.11}/quasarr/downloads/sources/dw.py +1 -1
  18. {quasarr-2.4.10 → quasarr-2.4.11}/quasarr/downloads/sources/sf.py +1 -1
  19. {quasarr-2.4.10 → quasarr-2.4.11}/quasarr/providers/notifications.py +1 -1
  20. {quasarr-2.4.10 → quasarr-2.4.11}/quasarr/providers/shared_state.py +0 -6
  21. {quasarr-2.4.10 → quasarr-2.4.11}/quasarr/providers/version.py +1 -1
  22. {quasarr-2.4.10 → quasarr-2.4.11}/quasarr/search/sources/al.py +0 -5
  23. {quasarr-2.4.10 → quasarr-2.4.11}/quasarr/search/sources/he.py +1 -2
  24. {quasarr-2.4.10 → quasarr-2.4.11}/quasarr/storage/sqlite_database.py +1 -1
  25. {quasarr-2.4.10 → quasarr-2.4.11}/uv.lock +135 -1
  26. {quasarr-2.4.10 → quasarr-2.4.11}/.github/FUNDING.yml +0 -0
  27. {quasarr-2.4.10 → quasarr-2.4.11}/.github/ISSUE_TEMPLATE/bug_report.yml +0 -0
  28. {quasarr-2.4.10 → quasarr-2.4.11}/.github/ISSUE_TEMPLATE/config.yml +0 -0
  29. {quasarr-2.4.10 → quasarr-2.4.11}/.github/workflows/HostnameRedaction.yml +0 -0
  30. {quasarr-2.4.10 → quasarr-2.4.11}/LICENSE +0 -0
  31. {quasarr-2.4.10 → quasarr-2.4.11}/Quasarr.png +0 -0
  32. {quasarr-2.4.10 → quasarr-2.4.11}/Quasarr.py +0 -0
  33. {quasarr-2.4.10 → quasarr-2.4.11}/README.md +0 -0
  34. {quasarr-2.4.10 → quasarr-2.4.11}/docker/Dockerfile +0 -0
  35. {quasarr-2.4.10 → quasarr-2.4.11}/docker/dev-services-compose.yml +0 -0
  36. {quasarr-2.4.10 → quasarr-2.4.11}/docker/docker-compose.yml +0 -0
  37. {quasarr-2.4.10 → quasarr-2.4.11}/quasarr/api/arr/__init__.py +0 -0
  38. {quasarr-2.4.10 → quasarr-2.4.11}/quasarr/api/packages/__init__.py +0 -0
  39. {quasarr-2.4.10 → quasarr-2.4.11}/quasarr/api/statistics/__init__.py +0 -0
  40. {quasarr-2.4.10 → quasarr-2.4.11}/quasarr/downloads/__init__.py +0 -0
  41. {quasarr-2.4.10 → quasarr-2.4.11}/quasarr/downloads/linkcrypters/__init__.py +0 -0
  42. {quasarr-2.4.10 → quasarr-2.4.11}/quasarr/downloads/linkcrypters/al.py +0 -0
  43. {quasarr-2.4.10 → quasarr-2.4.11}/quasarr/downloads/linkcrypters/filecrypt.py +0 -0
  44. {quasarr-2.4.10 → quasarr-2.4.11}/quasarr/downloads/sources/__init__.py +0 -0
  45. {quasarr-2.4.10 → quasarr-2.4.11}/quasarr/downloads/sources/by.py +0 -0
  46. {quasarr-2.4.10 → quasarr-2.4.11}/quasarr/downloads/sources/dd.py +0 -0
  47. {quasarr-2.4.10 → quasarr-2.4.11}/quasarr/downloads/sources/dj.py +0 -0
  48. {quasarr-2.4.10 → quasarr-2.4.11}/quasarr/downloads/sources/dl.py +0 -0
  49. {quasarr-2.4.10 → quasarr-2.4.11}/quasarr/downloads/sources/dt.py +0 -0
  50. {quasarr-2.4.10 → quasarr-2.4.11}/quasarr/downloads/sources/he.py +0 -0
  51. {quasarr-2.4.10 → quasarr-2.4.11}/quasarr/downloads/sources/mb.py +0 -0
  52. {quasarr-2.4.10 → quasarr-2.4.11}/quasarr/downloads/sources/nk.py +0 -0
  53. {quasarr-2.4.10 → quasarr-2.4.11}/quasarr/downloads/sources/nx.py +0 -0
  54. {quasarr-2.4.10 → quasarr-2.4.11}/quasarr/downloads/sources/sj.py +0 -0
  55. {quasarr-2.4.10 → quasarr-2.4.11}/quasarr/downloads/sources/sl.py +0 -0
  56. {quasarr-2.4.10 → quasarr-2.4.11}/quasarr/downloads/sources/wd.py +0 -0
  57. {quasarr-2.4.10 → quasarr-2.4.11}/quasarr/downloads/sources/wx.py +0 -0
  58. {quasarr-2.4.10 → quasarr-2.4.11}/quasarr/providers/__init__.py +0 -0
  59. {quasarr-2.4.10 → quasarr-2.4.11}/quasarr/providers/auth.py +0 -0
  60. {quasarr-2.4.10 → quasarr-2.4.11}/quasarr/providers/cloudflare.py +0 -0
  61. {quasarr-2.4.10 → quasarr-2.4.11}/quasarr/providers/hostname_issues.py +0 -0
  62. {quasarr-2.4.10 → quasarr-2.4.11}/quasarr/providers/html_images.py +0 -0
  63. {quasarr-2.4.10 → quasarr-2.4.11}/quasarr/providers/html_templates.py +0 -0
  64. {quasarr-2.4.10 → quasarr-2.4.11}/quasarr/providers/imdb_metadata.py +0 -0
  65. {quasarr-2.4.10 → quasarr-2.4.11}/quasarr/providers/jd_cache.py +0 -0
  66. {quasarr-2.4.10 → quasarr-2.4.11}/quasarr/providers/log.py +0 -0
  67. {quasarr-2.4.10 → quasarr-2.4.11}/quasarr/providers/myjd_api.py +0 -0
  68. {quasarr-2.4.10 → quasarr-2.4.11}/quasarr/providers/obfuscated.py +0 -0
  69. {quasarr-2.4.10 → quasarr-2.4.11}/quasarr/providers/sessions/__init__.py +0 -0
  70. {quasarr-2.4.10 → quasarr-2.4.11}/quasarr/providers/sessions/al.py +0 -0
  71. {quasarr-2.4.10 → quasarr-2.4.11}/quasarr/providers/sessions/dd.py +0 -0
  72. {quasarr-2.4.10 → quasarr-2.4.11}/quasarr/providers/sessions/dl.py +0 -0
  73. {quasarr-2.4.10 → quasarr-2.4.11}/quasarr/providers/sessions/nx.py +0 -0
  74. {quasarr-2.4.10 → quasarr-2.4.11}/quasarr/providers/statistics.py +0 -0
  75. {quasarr-2.4.10 → quasarr-2.4.11}/quasarr/providers/utils.py +0 -0
  76. {quasarr-2.4.10 → quasarr-2.4.11}/quasarr/providers/web_server.py +0 -0
  77. {quasarr-2.4.10 → quasarr-2.4.11}/quasarr/search/__init__.py +0 -0
  78. {quasarr-2.4.10 → quasarr-2.4.11}/quasarr/search/sources/__init__.py +0 -0
  79. {quasarr-2.4.10 → quasarr-2.4.11}/quasarr/search/sources/by.py +0 -0
  80. {quasarr-2.4.10 → quasarr-2.4.11}/quasarr/search/sources/dd.py +0 -0
  81. {quasarr-2.4.10 → quasarr-2.4.11}/quasarr/search/sources/dj.py +0 -0
  82. {quasarr-2.4.10 → quasarr-2.4.11}/quasarr/search/sources/dl.py +0 -0
  83. {quasarr-2.4.10 → quasarr-2.4.11}/quasarr/search/sources/dt.py +0 -0
  84. {quasarr-2.4.10 → quasarr-2.4.11}/quasarr/search/sources/dw.py +0 -0
  85. {quasarr-2.4.10 → quasarr-2.4.11}/quasarr/search/sources/fx.py +0 -0
  86. {quasarr-2.4.10 → quasarr-2.4.11}/quasarr/search/sources/mb.py +0 -0
  87. {quasarr-2.4.10 → quasarr-2.4.11}/quasarr/search/sources/nk.py +0 -0
  88. {quasarr-2.4.10 → quasarr-2.4.11}/quasarr/search/sources/nx.py +0 -0
  89. {quasarr-2.4.10 → quasarr-2.4.11}/quasarr/search/sources/sf.py +0 -0
  90. {quasarr-2.4.10 → quasarr-2.4.11}/quasarr/search/sources/sj.py +0 -0
  91. {quasarr-2.4.10 → quasarr-2.4.11}/quasarr/search/sources/sl.py +0 -0
  92. {quasarr-2.4.10 → quasarr-2.4.11}/quasarr/search/sources/wd.py +0 -0
  93. {quasarr-2.4.10 → quasarr-2.4.11}/quasarr/search/sources/wx.py +0 -0
  94. {quasarr-2.4.10 → quasarr-2.4.11}/quasarr/storage/__init__.py +0 -0
  95. {quasarr-2.4.10 → quasarr-2.4.11}/quasarr/storage/config.py +0 -0
  96. {quasarr-2.4.10 → quasarr-2.4.11}/quasarr/storage/setup.py +0 -0
@@ -1,4 +1,4 @@
1
- name: CI/CD & Beta Build
1
+ name: Pull Requests
2
2
 
3
3
  on:
4
4
  workflow_dispatch:
@@ -34,8 +34,9 @@ jobs:
34
34
  with:
35
35
  enable-cache: true
36
36
 
37
- # We just install python here so uv run has something to target
38
- - run: uv python install 3.12
37
+ - run: |
38
+ echo "🐍 Installing Python 3.12..."
39
+ uv python install 3.12
39
40
 
40
41
  - name: Run Maintenance
41
42
  id: manager
@@ -46,7 +47,9 @@ jobs:
46
47
  GITHUB_REPO: ${{ github.repository }}
47
48
  WORKFLOW_NAME: ${{ github.workflow }}
48
49
  run: |
49
- uv run maintenance.py --ci
50
+ echo "🛠️ Running pre-commit.py..."
51
+ uv run pre-commit.py --ci
52
+ echo "✨ Maintenance complete."
50
53
 
51
54
  version:
52
55
  needs: [ quality-check ]
@@ -63,7 +66,10 @@ jobs:
63
66
  with:
64
67
  enable-cache: true
65
68
  - id: version
66
- run: echo "version=$(uv run python quasarr/providers/version.py)" >> $GITHUB_OUTPUT
69
+ run: |
70
+ VERSION=$(uv run python quasarr/providers/version.py)
71
+ echo "version=$VERSION" >> $GITHUB_OUTPUT
72
+ echo "🏷️ Detected version: $VERSION"
67
73
 
68
74
  build-wheel:
69
75
  needs: [ quality-check, version ]
@@ -83,7 +89,9 @@ jobs:
83
89
  - uses: astral-sh/setup-uv@v5
84
90
  with:
85
91
  enable-cache: true
86
- - run: uv build
92
+ - run: |
93
+ echo "📦 Building Python Wheel..."
94
+ uv build
87
95
  - id: attest
88
96
  uses: actions/attest-build-provenance@v2
89
97
  with:
@@ -106,38 +114,32 @@ jobs:
106
114
  - uses: actions/setup-python@v5
107
115
  with:
108
116
  python-version: '3.12'
109
-
110
117
  - uses: astral-sh/setup-uv@v5
111
118
  with:
112
119
  enable-cache: true
113
- cache-suffix: "win-build" # Isolate this cache from Linux builds if you share keys
114
-
115
- # --- CACHE ---
120
+ cache-suffix: "win-build"
116
121
  - name: Cache PyInstaller Analysis
117
122
  uses: actions/cache@v4
118
123
  with:
119
124
  path: |
120
125
  build
121
126
  ~\AppData\Local\pyinstaller
122
- # Invalidates cache only if dependencies (uv.lock) change
123
127
  key: pyinstaller-analysis-${{ runner.os }}-${{ hashFiles('uv.lock') }}
124
128
  restore-keys: |
125
129
  pyinstaller-analysis-${{ runner.os }}-
126
-
127
130
  - shell: powershell
128
- run: Set-MpPreference -DisableRealtimeMonitoring $true
129
-
130
- - run: uv sync --group build
131
-
132
- # --- BUILD COMMAND ---
131
+ run: |
132
+ echo "🛡️ Disabling Real-time Monitoring..."
133
+ Set-MpPreference -DisableRealtimeMonitoring $true
134
+ - run: |
135
+ echo "📥 Syncing dependencies..."
136
+ uv sync --group build
133
137
  - run: |
138
+ echo "🪟 Starting PyInstaller build..."
134
139
  uv run python -c "from PIL import Image; Image.open('Quasarr.png').save('Quasarr.ico')"
135
140
  uv run python quasarr/providers/version.py --create-version-file
136
- # 1. Removed '--clean'
137
- # 2. Added '--workpath "build"' (Matches the cached path above)
138
- # 3. Added '--distpath "dist"' (Explicit output folder)
139
141
  uv run pyinstaller --onefile -y --version-file "file_version_info.txt" --workpath "build" --distpath "dist" --icon "Quasarr.ico" "Quasarr.py" -n "quasarr-${{ needs.version.outputs.version }}-standalone-win64"
140
-
142
+ echo "✅ EXE build finished."
141
143
  - uses: actions/upload-artifact@v4
142
144
  with:
143
145
  name: exe-amd64
@@ -165,6 +167,7 @@ jobs:
165
167
  myToken: ${{ secrets.GITHUB_TOKEN }}
166
168
  - name: Create Release Body
167
169
  run: |
170
+ echo "📝 Generating Release Body..."
168
171
  echo "### Docker:" > release_body.md
169
172
  echo "\`docker pull ${{ env.GHCR_ENDPOINT }}:beta\`" >> release_body.md
170
173
  echo "### Python:" >> release_body.md
@@ -200,7 +203,8 @@ jobs:
200
203
  registry: ghcr.io
201
204
  username: ${{ github.actor }}
202
205
  password: ${{ secrets.GITHUB_TOKEN }}
203
- - uses: docker/build-push-action@v6
206
+ - name: Build and Push
207
+ uses: docker/build-push-action@v6
204
208
  with:
205
209
  context: ./docker
206
210
  platforms: linux/amd64
@@ -231,7 +235,8 @@ jobs:
231
235
  registry: ghcr.io
232
236
  username: ${{ github.actor }}
233
237
  password: ${{ secrets.GITHUB_TOKEN }}
234
- - uses: docker/build-push-action@v6
238
+ - name: Build and Push
239
+ uses: docker/build-push-action@v6
235
240
  with:
236
241
  context: ./docker
237
242
  platforms: linux/arm64
@@ -257,6 +262,7 @@ jobs:
257
262
  username: ${{ github.actor }}
258
263
  password: ${{ secrets.GITHUB_TOKEN }}
259
264
  - run: |
265
+ echo "🔗 Merging Docker manifests..."
260
266
  TAG_AMD64="${{ needs.version.outputs.version }}-beta-amd64"
261
267
  TAG_ARM64="${{ needs.version.outputs.version }}-beta-arm64"
262
268
  ANNOTATION="index:org.opencontainers.image.description=$DESCRIPTION"
@@ -274,15 +280,13 @@ jobs:
274
280
  notify:
275
281
  name: Notify Discord & PR
276
282
  needs: [ quality-check, version, beta-release, merge-docker-manifest ]
277
- # Only run if the build wasn't skipped by the auto-fixer and the release succeeded
278
283
  if: needs.quality-check.outputs.changes_pushed != 'true' && needs.beta-release.result == 'success'
279
284
  runs-on: ubuntu-latest
280
285
  permissions:
281
- pull-requests: write # Required to comment on the PR
286
+ pull-requests: write
282
287
  contents: read
283
288
  steps:
284
289
  - uses: actions/checkout@v6
285
-
286
290
  - name: Send Notifications
287
291
  env:
288
292
  GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
@@ -290,45 +294,48 @@ jobs:
290
294
  VERSION: ${{ needs.version.outputs.version }}
291
295
  REPO: ${{ github.repository }}
292
296
  run: |
293
- echo "Fetching release details..."
294
- # Get the body of the release we just created (beta tag)
297
+ echo "📢 Notifying stakeholders..."
295
298
  RELEASE_BODY=$(gh release view beta --json body --jq .body)
296
-
297
- # --- 1. DISCORD NOTIFICATION ---
298
299
  if [ -n "$DISCORD_WEBHOOK" ]; then
299
- echo "Sending Discord Webhook..."
300
-
301
- # Construct a JSON payload safely using jq (handles escaping quotes/newlines)
302
- # We create a simple embed with the version and the release body
303
- jq -n \
304
- --arg title "🚀 New Beta Build: $VERSION" \
305
- --arg desc "$RELEASE_BODY" \
306
- --arg url "https://github.com/$REPO/releases/tag/beta" \
307
- '{content: null, embeds: [{title: $title, description: $desc, url: $url, color: 5814783}]}' \
308
- > discord_payload.json
309
-
310
- curl -H "Content-Type: application/json" \
311
- -d @discord_payload.json \
312
- "$DISCORD_WEBHOOK"
313
- else
314
- echo "::warning::Skipping Discord notification (DISCORD_WEBHOOK secret not set)"
300
+ jq -n --arg title "🚀 New Beta Build: $VERSION" --arg desc "$RELEASE_BODY" --arg url "https://github.com/$REPO/releases/tag/beta" '{content: null, embeds: [{title: $title, description: $desc, url: $url, color: 5814783}]}' > discord_payload.json
301
+ curl -H "Content-Type: application/json" -d @discord_payload.json "$DISCORD_WEBHOOK"
315
302
  fi
316
-
317
- # --- 2. PR COMMENT FALLBACK ---
318
- # Find the PR associated with the commit that triggered this push
319
- echo "Looking for associated PR..."
320
303
  PR_NUMBER=$(gh pr list --search "${{ github.sha }}" --state merged --json number --jq '.[0].number')
321
-
322
304
  if [ -n "$PR_NUMBER" ]; then
323
- echo "Found PR #$PR_NUMBER. Posting comment..."
324
-
325
305
  echo "## 🚀 Beta Release $VERSION is Live!" > pr_comment.md
326
- echo "" >> pr_comment.md
327
306
  echo "$RELEASE_BODY" >> pr_comment.md
328
- echo "" >> pr_comment.md
329
- echo "[View Release on GitHub](https://github.com/$REPO/releases/tag/beta)" >> pr_comment.md
330
-
331
307
  gh pr comment "$PR_NUMBER" --body-file pr_comment.md
308
+ fi
309
+
310
+ job-summary:
311
+ name: 📊 Beta Summary
312
+ runs-on: ubuntu-latest
313
+ needs: [ quality-check, version, beta-release ]
314
+ if: always()
315
+ steps:
316
+ - name: Generate Summary
317
+ run: |
318
+ echo "## 🧪 Beta Build Summary" >> $GITHUB_STEP_SUMMARY
319
+
320
+ # Maintenance Outcome
321
+ if [[ "${{ needs.quality-check.outputs.changes_pushed }}" == "true" ]]; then
322
+ echo "### 🛠️ Maintenance Status: **Auto-Fixed**" >> $GITHUB_STEP_SUMMARY
323
+ echo "The script found formatting or dependency issues and pushed fixes directly. The current build was skipped to allow the new commit to run." >> $GITHUB_STEP_SUMMARY
332
324
  else
333
- echo "No merged PR found for commit ${{ github.sha }}. Skipping PR comment."
325
+ echo "### Maintenance Status: **Clean**" >> $GITHUB_STEP_SUMMARY
326
+ echo "No formatting or maintenance issues were detected." >> $GITHUB_STEP_SUMMARY
334
327
  fi
328
+
329
+ # Decision Logic
330
+ echo "### 🚦 Workflow Decision" >> $GITHUB_STEP_SUMMARY
331
+ if [[ "${{ needs.version.result }}" == "success" ]]; then
332
+ echo "✅ **Proceeded:** The build moved to beta release (Dev branch detected)." >> $GITHUB_STEP_SUMMARY
333
+ else
334
+ echo "🛑 **Stopped:** Build did not proceed to release (Not on dev or quality-check failed)." >> $GITHUB_STEP_SUMMARY
335
+ fi
336
+
337
+ echo "### 📦 Artifact Details" >> $GITHUB_STEP_SUMMARY
338
+ echo "| Metric | Value |" >> $GITHUB_STEP_SUMMARY
339
+ echo "| --- | --- |" >> $GITHUB_STEP_SUMMARY
340
+ echo "| **Version** | \`${{ needs.version.outputs.version || 'N/A' }}\` |" >> $GITHUB_STEP_SUMMARY
341
+ echo "| **Release Job** | ${{ needs.beta-release.result || 'Skipped' }} |" >> $GITHUB_STEP_SUMMARY
@@ -37,7 +37,9 @@ jobs:
37
37
  - name: Get Version
38
38
  id: version
39
39
  run: |
40
- echo "version=$(uv run python quasarr/providers/version.py)" >> $GITHUB_OUTPUT
40
+ VERSION=$(uv run python quasarr/providers/version.py)
41
+ echo "version=$VERSION" >> $GITHUB_OUTPUT
42
+ echo "🏷️ Version: $VERSION"
41
43
 
42
44
  build-wheel:
43
45
  name: Build Wheel
@@ -58,7 +60,9 @@ jobs:
58
60
  with:
59
61
  enable-cache: true
60
62
  - name: Build wheel
61
- run: uv build
63
+ run: |
64
+ echo "📦 Starting Wheel build..."
65
+ uv build
62
66
  - name: Generate artifact attestation
63
67
  id: attest
64
68
  uses: actions/attest-build-provenance@v2
@@ -74,26 +78,20 @@ jobs:
74
78
  runs-on: windows-latest
75
79
  needs: version
76
80
  env:
77
- # We define a consistent build path to make caching reliable
78
81
  BUILD_PATH: "build"
79
82
  steps:
80
83
  - uses: actions/checkout@v6
81
84
  - uses: actions/setup-python@v5
82
85
  with:
83
86
  python-version: '3.12'
84
-
85
- # 1. Install uv with its own persistent cache
86
87
  - name: Install uv
87
88
  uses: astral-sh/setup-uv@v5
88
89
  with:
89
90
  enable-cache: true
90
91
  cache-suffix: "win-build"
91
-
92
- # 2. PyInstaller Caching
93
- # We cache the local 'build' folder AND the global PyInstaller cache.
94
- # The key invalidates if 'uv.lock' changes, forcing a re-analysis only when deps update.
95
92
  - name: Cache PyInstaller Analysis
96
93
  uses: actions/cache@v4
94
+ id: pyinstaller-cache
97
95
  with:
98
96
  path: |
99
97
  build
@@ -101,25 +99,20 @@ jobs:
101
99
  key: pyinstaller-analysis-${{ runner.os }}-${{ hashFiles('uv.lock') }}
102
100
  restore-keys: |
103
101
  pyinstaller-analysis-${{ runner.os }}-
104
-
105
102
  - name: Disable Windows Defender
106
103
  shell: powershell
107
104
  run: Set-MpPreference -DisableRealtimeMonitoring $true
108
-
109
105
  - name: Install dependencies
110
106
  run: |
107
+ echo "📥 Installing build dependencies..."
111
108
  uv sync --group build
112
-
113
109
  - name: Build exe
114
- # CHANGES:
115
- # 1. Removed '--clean' (Critical for speed)
116
- # 2. Added '--workpath' to point to our cached folder
117
- # 3. Added '--distpath' explicitly
118
110
  run: |
111
+ echo "🪟 Building Windows Binary..."
119
112
  uv run python -c "from PIL import Image; Image.open('Quasarr.png').save('Quasarr.ico')"
120
113
  uv run python quasarr/providers/version.py --create-version-file
121
114
  uv run pyinstaller --onefile -y --version-file "file_version_info.txt" --workpath "build" --distpath "dist" --icon "Quasarr.ico" "Quasarr.py" -n "quasarr-${{ needs.version.outputs.version }}-standalone-win64"
122
-
115
+ echo "✨ Windows binary created."
123
116
  - uses: actions/upload-artifact@v4
124
117
  with:
125
118
  name: exe-amd64
@@ -220,27 +213,14 @@ jobs:
220
213
  password: ${{ secrets.GITHUB_TOKEN }}
221
214
  - name: Create and Push Manifests
222
215
  run: |
216
+ echo "🔗 Linking Multi-arch images..."
223
217
  TAG_AMD64="${{ needs.version.outputs.version }}-amd64"
224
218
  TAG_ARM64="${{ needs.version.outputs.version }}-arm64"
225
219
  ANNOTATION="index:org.opencontainers.image.description=$DESCRIPTION"
226
-
227
- docker buildx imagetools create -t ${{ env.ENDPOINT }}:latest \
228
- ${{ env.ENDPOINT }}:latest-amd64 \
229
- ${{ env.ENDPOINT }}:latest-arm64
230
-
231
- docker buildx imagetools create -t ${{ env.ENDPOINT }}:${{ needs.version.outputs.version }} \
232
- ${{ env.ENDPOINT }}:${TAG_AMD64} \
233
- ${{ env.ENDPOINT }}:${TAG_ARM64}
234
-
235
- docker buildx imagetools create -t ${{ env.GHCR_ENDPOINT }}:latest \
236
- --annotation "$ANNOTATION" \
237
- ${{ env.GHCR_ENDPOINT }}:latest-amd64 \
238
- ${{ env.GHCR_ENDPOINT }}:latest-arm64
239
-
240
- docker buildx imagetools create -t ${{ env.GHCR_ENDPOINT }}:${{ needs.version.outputs.version }} \
241
- --annotation "$ANNOTATION" \
242
- ${{ env.GHCR_ENDPOINT }}:${TAG_AMD64} \
243
- ${{ env.GHCR_ENDPOINT }}:${TAG_ARM64}
220
+ docker buildx imagetools create -t ${{ env.ENDPOINT }}:latest ${{ env.ENDPOINT }}:latest-amd64 ${{ env.ENDPOINT }}:latest-arm64
221
+ docker buildx imagetools create -t ${{ env.ENDPOINT }}:${{ needs.version.outputs.version }} ${{ env.ENDPOINT }}:${TAG_AMD64} ${{ env.ENDPOINT }}:${TAG_ARM64}
222
+ docker buildx imagetools create -t ${{ env.GHCR_ENDPOINT }}:latest --annotation "$ANNOTATION" ${{ env.GHCR_ENDPOINT }}:latest-amd64 ${{ env.GHCR_ENDPOINT }}:latest-arm64
223
+ docker buildx imagetools create -t ${{ env.GHCR_ENDPOINT }}:${{ needs.version.outputs.version }} --annotation "$ANNOTATION" ${{ env.GHCR_ENDPOINT }}:${TAG_AMD64} ${{ env.GHCR_ENDPOINT }}:${TAG_ARM64}
244
224
 
245
225
  release:
246
226
  name: Create Release
@@ -252,7 +232,6 @@ jobs:
252
232
  - uses: actions/checkout@v6
253
233
  with:
254
234
  fetch-depth: 0
255
-
256
235
  - uses: actions/download-artifact@v4
257
236
  with:
258
237
  name: wheel
@@ -261,16 +240,15 @@ jobs:
261
240
  with:
262
241
  name: exe-amd64
263
242
  path: ./exe-amd64
264
-
265
243
  - name: Install uv
266
244
  uses: astral-sh/setup-uv@v5
267
245
  with:
268
246
  enable-cache: true
269
-
270
247
  - name: Publish to PyPI
271
248
  if: ${{ !inputs.skip_pypi }}
272
- run: uv publish ./wheel/* --token ${{ secrets.PYPI_TOKEN }}
273
-
249
+ run: |
250
+ echo "🚀 Publishing to PyPI..."
251
+ uv publish ./wheel/* --token ${{ secrets.PYPI_TOKEN }}
274
252
  - name: Generate changelog
275
253
  id: changelog
276
254
  uses: metcalfc/changelog-generator@v4.6.2
@@ -281,25 +259,16 @@ jobs:
281
259
  GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
282
260
  run: |
283
261
  PR_BODY=$(gh pr list --search "${{ github.sha }}" --state merged --json body --jq '.[0].body // empty')
284
- if [ -n "$PR_BODY" ]; then
285
- echo -e "\n$PR_BODY" >> .github/Changelog.md
286
- fi
262
+ if [ -n "$PR_BODY" ]; then echo -e "\n$PR_BODY" >> .github/Changelog.md; fi
287
263
  - name: Create Release Body
288
264
  run: |
289
265
  echo "### Docker:" > release_body.md
290
- echo "" >> release_body.md
291
266
  echo "\`docker pull ${{ env.GHCR_ENDPOINT }}:latest\`" >> release_body.md
292
- echo "" >> release_body.md
293
267
  echo "### Python:" >> release_body.md
294
- echo "" >> release_body.md
295
268
  echo "\`uv tool upgrade quasarr\`" >> release_body.md
296
- echo "" >> release_body.md
297
269
  echo "### Changelog:" >> release_body.md
298
- echo "" >> release_body.md
299
270
  echo "${{ steps.changelog.outputs.changelog }}" >> release_body.md
300
- echo "" >> release_body.md
301
271
  echo "[Attestation](https://github.com/${{ github.repository }}/attestations/${{ needs.build-wheel.outputs.attestation-id }})" >> release_body.md
302
-
303
272
  - name: Create Release
304
273
  uses: ncipollo/release-action@v1
305
274
  with:
@@ -315,7 +284,6 @@ jobs:
315
284
  runs-on: ubuntu-latest
316
285
  steps:
317
286
  - uses: actions/checkout@v6
318
-
319
287
  - name: Send Discord Webhook
320
288
  env:
321
289
  GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
@@ -323,28 +291,31 @@ jobs:
323
291
  VERSION: ${{ needs.version.outputs.version }}
324
292
  REPO: ${{ github.repository }}
325
293
  run: |
326
- # Use the exact tag format defined in the release job (v.X.X.X)
327
294
  TAG="v.$VERSION"
328
- echo "Fetching release details for $TAG..."
329
-
330
- # Fetch the body from the release we just created
331
295
  RELEASE_BODY=$(gh release view "$TAG" --json body --jq .body)
332
-
333
296
  if [ -n "$DISCORD_WEBHOOK" ]; then
334
- echo "Sending notification..."
335
-
336
- # Construct JSON payload using jq
337
- # Color 5763719 is 'Green'
338
- jq -n \
339
- --arg title "🚀 New Release: $TAG" \
340
- --arg desc "$RELEASE_BODY" \
341
- --arg url "https://github.com/$REPO/releases/tag/$TAG" \
342
- '{content: null, embeds: [{title: $title, description: $desc, url: $url, color: 5763719}]}' \
343
- > discord_payload.json
344
-
345
- curl -H "Content-Type: application/json" \
346
- -d @discord_payload.json \
347
- "$DISCORD_WEBHOOK"
348
- else
349
- echo "::warning::Skipping Discord notification (DISCORD_WEBHOOK secret not set)"
297
+ jq -n --arg title "🚀 New Release: $TAG" --arg desc "$RELEASE_BODY" --arg url "https://github.com/$REPO/releases/tag/$TAG" '{content: null, embeds: [{title: $title, description: $desc, url: $url, color: 5763719}]}' > discord_payload.json
298
+ curl -H "Content-Type: application/json" -d @discord_payload.json "$DISCORD_WEBHOOK"
350
299
  fi
300
+
301
+ job-summary:
302
+ name: 📈 Build Report
303
+ runs-on: ubuntu-latest
304
+ needs: [ version, build-wheel, build-exe, build-docker-amd64, build-docker-arm64, release ]
305
+ if: always()
306
+ steps:
307
+ - name: Generate Job Summary
308
+ run: |
309
+ echo "## 📊 Release Production Report" >> $GITHUB_STEP_SUMMARY
310
+ echo "| Artifact | Status |" >> $GITHUB_STEP_SUMMARY
311
+ echo "| --- | --- |" >> $GITHUB_STEP_SUMMARY
312
+ echo "| **Python Wheel** | ${{ needs.build-wheel.result == 'success' && '✅' || '❌' }} |" >> $GITHUB_STEP_SUMMARY
313
+ echo "| **Windows Standalone** | ${{ needs.build-exe.result == 'success' && '✅' || '❌' }} |" >> $GITHUB_STEP_SUMMARY
314
+ echo "| **Docker AMD64** | ${{ needs.build-docker-amd64.result == 'success' && '✅' || '❌' }} |" >> $GITHUB_STEP_SUMMARY
315
+ echo "| **Docker ARM64** | ${{ needs.build-docker-arm64.result == 'success' && '✅' || '❌' }} |" >> $GITHUB_STEP_SUMMARY
316
+ echo "| **GitHub Release** | ${{ needs.release.result == 'success' && '🚀 Published' || '⚠️ Failed' }} |" >> $GITHUB_STEP_SUMMARY
317
+
318
+ echo "### ⚡ Cache Performance" >> $GITHUB_STEP_SUMMARY
319
+ # This assumes you use the default GITHUB_TOKEN permissions to read cache API if you wanted complex stats,
320
+ # but for simplicity we report on the PyInstaller cache key match.
321
+ echo "* **PyInstaller Cache:** ${{ needs.build-exe.outputs.cache-hit == 'true' && 'Hit (Fast 🚀)' || 'Miss (Full Build 🐢)' }}" >> $GITHUB_STEP_SUMMARY
@@ -10,6 +10,10 @@
10
10
  # PyCharm
11
11
  .idea
12
12
 
13
+ # MacOS
14
+ .DS_Store
15
+ **/.DS_Store
16
+
13
17
  # Quasarr
14
18
  *.conf
15
19
  *.db
@@ -0,0 +1,9 @@
1
+ repos:
2
+ - repo: local
3
+ hooks:
4
+ - id: pre-commit
5
+ name: Pre-Commit Check
6
+ entry: uv run python pre-commit.py
7
+ language: system
8
+ pass_filenames: false
9
+ always_run: true
@@ -10,6 +10,12 @@ Ensure you have the development tools (like `ruff`) installed and your environme
10
10
  uv sync --group dev
11
11
  ```
12
12
 
13
+ Install the pre-commit hook that ensures linting, formatting and version upgrades through pre-commit.py
14
+
15
+ ```bash
16
+ uv run pre-commit install
17
+ ```
18
+
13
19
  **2. Run Quasarr with the `--internal_address` parameter**
14
20
 
15
21
  ```bash
@@ -33,10 +39,10 @@ The `CONFIG_VOLUMES` environment variable is **mandatory**.
33
39
  ### Code Quality & Maintenance
34
40
 
35
41
  The CI pipeline enforces strict code styling and import optimization. Please run this commands before pushing your
36
- changes:
42
+ changes. Alternatively, you should just set up the pre-commit hook as described above.
37
43
 
38
- **Format code AND upgrade dependencies:**
44
+ **Format code AND upgrade dependencie manually:**
39
45
 
40
46
  ```bash
41
- uv run maintenance.py --upgrade
47
+ uv run pre-commit.py --upgrade
42
48
  ```
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: quasarr
3
- Version: 2.4.10
3
+ Version: 2.4.11
4
4
  Summary: Quasarr connects JDownloader with Radarr, Sonarr and LazyLibrarian. It also decrypts links protected by CAPTCHAs.
5
5
  Author-email: rix1337 <rix1337@users.noreply.github.com>
6
6
  License-File: LICENSE