quasarr 2.4.10__tar.gz → 2.5.0__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.
- {quasarr-2.4.10 → quasarr-2.5.0}/.github/workflows/PullRequests.yml +75 -61
- {quasarr-2.4.10 → quasarr-2.5.0}/.github/workflows/Release.yml +43 -72
- {quasarr-2.4.10 → quasarr-2.5.0}/.gitignore +4 -0
- quasarr-2.5.0/.pre-commit-config.yaml +9 -0
- {quasarr-2.4.10 → quasarr-2.5.0}/CONTRIBUTING.md +9 -3
- {quasarr-2.4.10 → quasarr-2.5.0}/PKG-INFO +1 -1
- quasarr-2.4.10/maintenance.py → quasarr-2.5.0/pre-commit.py +59 -57
- {quasarr-2.4.10 → quasarr-2.5.0}/pyproject.toml +5 -2
- {quasarr-2.4.10 → quasarr-2.5.0}/quasarr/__init__.py +3 -3
- {quasarr-2.4.10 → quasarr-2.5.0}/quasarr/api/__init__.py +7 -7
- {quasarr-2.4.10 → quasarr-2.5.0}/quasarr/api/captcha/__init__.py +1 -1
- {quasarr-2.4.10 → quasarr-2.5.0}/quasarr/api/config/__init__.py +22 -169
- {quasarr-2.4.10 → quasarr-2.5.0}/quasarr/api/sponsors_helper/__init__.py +2 -2
- {quasarr-2.4.10 → quasarr-2.5.0}/quasarr/downloads/linkcrypters/hide.py +1 -1
- {quasarr-2.4.10 → quasarr-2.5.0}/quasarr/downloads/packages/__init__.py +5 -5
- {quasarr-2.4.10 → quasarr-2.5.0}/quasarr/downloads/sources/al.py +1 -1
- {quasarr-2.4.10 → quasarr-2.5.0}/quasarr/downloads/sources/dw.py +1 -1
- {quasarr-2.4.10 → quasarr-2.5.0}/quasarr/downloads/sources/sf.py +1 -1
- {quasarr-2.4.10 → quasarr-2.5.0}/quasarr/providers/notifications.py +1 -1
- {quasarr-2.4.10 → quasarr-2.5.0}/quasarr/providers/shared_state.py +0 -6
- {quasarr-2.4.10 → quasarr-2.5.0}/quasarr/providers/version.py +1 -1
- {quasarr-2.4.10 → quasarr-2.5.0}/quasarr/search/__init__.py +86 -15
- {quasarr-2.4.10 → quasarr-2.5.0}/quasarr/search/sources/al.py +0 -5
- {quasarr-2.4.10 → quasarr-2.5.0}/quasarr/search/sources/he.py +1 -2
- {quasarr-2.4.10 → quasarr-2.5.0}/quasarr/storage/setup.py +517 -236
- {quasarr-2.4.10 → quasarr-2.5.0}/quasarr/storage/sqlite_database.py +1 -1
- {quasarr-2.4.10 → quasarr-2.5.0}/uv.lock +135 -1
- {quasarr-2.4.10 → quasarr-2.5.0}/.github/FUNDING.yml +0 -0
- {quasarr-2.4.10 → quasarr-2.5.0}/.github/ISSUE_TEMPLATE/bug_report.yml +0 -0
- {quasarr-2.4.10 → quasarr-2.5.0}/.github/ISSUE_TEMPLATE/config.yml +0 -0
- {quasarr-2.4.10 → quasarr-2.5.0}/.github/workflows/HostnameRedaction.yml +0 -0
- {quasarr-2.4.10 → quasarr-2.5.0}/LICENSE +0 -0
- {quasarr-2.4.10 → quasarr-2.5.0}/Quasarr.png +0 -0
- {quasarr-2.4.10 → quasarr-2.5.0}/Quasarr.py +0 -0
- {quasarr-2.4.10 → quasarr-2.5.0}/README.md +0 -0
- {quasarr-2.4.10 → quasarr-2.5.0}/docker/Dockerfile +0 -0
- {quasarr-2.4.10 → quasarr-2.5.0}/docker/dev-services-compose.yml +0 -0
- {quasarr-2.4.10 → quasarr-2.5.0}/docker/docker-compose.yml +0 -0
- {quasarr-2.4.10 → quasarr-2.5.0}/quasarr/api/arr/__init__.py +0 -0
- {quasarr-2.4.10 → quasarr-2.5.0}/quasarr/api/packages/__init__.py +0 -0
- {quasarr-2.4.10 → quasarr-2.5.0}/quasarr/api/statistics/__init__.py +0 -0
- {quasarr-2.4.10 → quasarr-2.5.0}/quasarr/downloads/__init__.py +0 -0
- {quasarr-2.4.10 → quasarr-2.5.0}/quasarr/downloads/linkcrypters/__init__.py +0 -0
- {quasarr-2.4.10 → quasarr-2.5.0}/quasarr/downloads/linkcrypters/al.py +0 -0
- {quasarr-2.4.10 → quasarr-2.5.0}/quasarr/downloads/linkcrypters/filecrypt.py +0 -0
- {quasarr-2.4.10 → quasarr-2.5.0}/quasarr/downloads/sources/__init__.py +0 -0
- {quasarr-2.4.10 → quasarr-2.5.0}/quasarr/downloads/sources/by.py +0 -0
- {quasarr-2.4.10 → quasarr-2.5.0}/quasarr/downloads/sources/dd.py +0 -0
- {quasarr-2.4.10 → quasarr-2.5.0}/quasarr/downloads/sources/dj.py +0 -0
- {quasarr-2.4.10 → quasarr-2.5.0}/quasarr/downloads/sources/dl.py +0 -0
- {quasarr-2.4.10 → quasarr-2.5.0}/quasarr/downloads/sources/dt.py +0 -0
- {quasarr-2.4.10 → quasarr-2.5.0}/quasarr/downloads/sources/he.py +0 -0
- {quasarr-2.4.10 → quasarr-2.5.0}/quasarr/downloads/sources/mb.py +0 -0
- {quasarr-2.4.10 → quasarr-2.5.0}/quasarr/downloads/sources/nk.py +0 -0
- {quasarr-2.4.10 → quasarr-2.5.0}/quasarr/downloads/sources/nx.py +0 -0
- {quasarr-2.4.10 → quasarr-2.5.0}/quasarr/downloads/sources/sj.py +0 -0
- {quasarr-2.4.10 → quasarr-2.5.0}/quasarr/downloads/sources/sl.py +0 -0
- {quasarr-2.4.10 → quasarr-2.5.0}/quasarr/downloads/sources/wd.py +0 -0
- {quasarr-2.4.10 → quasarr-2.5.0}/quasarr/downloads/sources/wx.py +0 -0
- {quasarr-2.4.10 → quasarr-2.5.0}/quasarr/providers/__init__.py +0 -0
- {quasarr-2.4.10 → quasarr-2.5.0}/quasarr/providers/auth.py +0 -0
- {quasarr-2.4.10 → quasarr-2.5.0}/quasarr/providers/cloudflare.py +0 -0
- {quasarr-2.4.10 → quasarr-2.5.0}/quasarr/providers/hostname_issues.py +0 -0
- {quasarr-2.4.10 → quasarr-2.5.0}/quasarr/providers/html_images.py +0 -0
- {quasarr-2.4.10 → quasarr-2.5.0}/quasarr/providers/html_templates.py +0 -0
- {quasarr-2.4.10 → quasarr-2.5.0}/quasarr/providers/imdb_metadata.py +0 -0
- {quasarr-2.4.10 → quasarr-2.5.0}/quasarr/providers/jd_cache.py +0 -0
- {quasarr-2.4.10 → quasarr-2.5.0}/quasarr/providers/log.py +0 -0
- {quasarr-2.4.10 → quasarr-2.5.0}/quasarr/providers/myjd_api.py +0 -0
- {quasarr-2.4.10 → quasarr-2.5.0}/quasarr/providers/obfuscated.py +0 -0
- {quasarr-2.4.10 → quasarr-2.5.0}/quasarr/providers/sessions/__init__.py +0 -0
- {quasarr-2.4.10 → quasarr-2.5.0}/quasarr/providers/sessions/al.py +0 -0
- {quasarr-2.4.10 → quasarr-2.5.0}/quasarr/providers/sessions/dd.py +0 -0
- {quasarr-2.4.10 → quasarr-2.5.0}/quasarr/providers/sessions/dl.py +0 -0
- {quasarr-2.4.10 → quasarr-2.5.0}/quasarr/providers/sessions/nx.py +0 -0
- {quasarr-2.4.10 → quasarr-2.5.0}/quasarr/providers/statistics.py +0 -0
- {quasarr-2.4.10 → quasarr-2.5.0}/quasarr/providers/utils.py +0 -0
- {quasarr-2.4.10 → quasarr-2.5.0}/quasarr/providers/web_server.py +0 -0
- {quasarr-2.4.10 → quasarr-2.5.0}/quasarr/search/sources/__init__.py +0 -0
- {quasarr-2.4.10 → quasarr-2.5.0}/quasarr/search/sources/by.py +0 -0
- {quasarr-2.4.10 → quasarr-2.5.0}/quasarr/search/sources/dd.py +0 -0
- {quasarr-2.4.10 → quasarr-2.5.0}/quasarr/search/sources/dj.py +0 -0
- {quasarr-2.4.10 → quasarr-2.5.0}/quasarr/search/sources/dl.py +0 -0
- {quasarr-2.4.10 → quasarr-2.5.0}/quasarr/search/sources/dt.py +0 -0
- {quasarr-2.4.10 → quasarr-2.5.0}/quasarr/search/sources/dw.py +0 -0
- {quasarr-2.4.10 → quasarr-2.5.0}/quasarr/search/sources/fx.py +0 -0
- {quasarr-2.4.10 → quasarr-2.5.0}/quasarr/search/sources/mb.py +0 -0
- {quasarr-2.4.10 → quasarr-2.5.0}/quasarr/search/sources/nk.py +0 -0
- {quasarr-2.4.10 → quasarr-2.5.0}/quasarr/search/sources/nx.py +0 -0
- {quasarr-2.4.10 → quasarr-2.5.0}/quasarr/search/sources/sf.py +0 -0
- {quasarr-2.4.10 → quasarr-2.5.0}/quasarr/search/sources/sj.py +0 -0
- {quasarr-2.4.10 → quasarr-2.5.0}/quasarr/search/sources/sl.py +0 -0
- {quasarr-2.4.10 → quasarr-2.5.0}/quasarr/search/sources/wd.py +0 -0
- {quasarr-2.4.10 → quasarr-2.5.0}/quasarr/search/sources/wx.py +0 -0
- {quasarr-2.4.10 → quasarr-2.5.0}/quasarr/storage/__init__.py +0 -0
- {quasarr-2.4.10 → quasarr-2.5.0}/quasarr/storage/config.py +0 -0
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
name:
|
|
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
|
-
|
|
38
|
-
|
|
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
|
-
|
|
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 ]
|
|
@@ -54,6 +57,7 @@ jobs:
|
|
|
54
57
|
runs-on: ubuntu-latest
|
|
55
58
|
outputs:
|
|
56
59
|
version: ${{ steps.version.outputs.version }}
|
|
60
|
+
epoch: ${{ steps.version.outputs.epoch }}
|
|
57
61
|
steps:
|
|
58
62
|
- uses: actions/checkout@v6
|
|
59
63
|
- uses: actions/setup-python@v5
|
|
@@ -63,7 +67,12 @@ jobs:
|
|
|
63
67
|
with:
|
|
64
68
|
enable-cache: true
|
|
65
69
|
- id: version
|
|
66
|
-
run:
|
|
70
|
+
run: |
|
|
71
|
+
VERSION=$(uv run python quasarr/providers/version.py)
|
|
72
|
+
EPOCH=$(date +%s)
|
|
73
|
+
echo "version=$VERSION" >> $GITHUB_OUTPUT
|
|
74
|
+
echo "epoch=$EPOCH" >> $GITHUB_OUTPUT
|
|
75
|
+
echo "🏷️ Detected version: $VERSION ($EPOCH)"
|
|
67
76
|
|
|
68
77
|
build-wheel:
|
|
69
78
|
needs: [ quality-check, version ]
|
|
@@ -83,7 +92,9 @@ jobs:
|
|
|
83
92
|
- uses: astral-sh/setup-uv@v5
|
|
84
93
|
with:
|
|
85
94
|
enable-cache: true
|
|
86
|
-
- run:
|
|
95
|
+
- run: |
|
|
96
|
+
echo "📦 Building Python Wheel..."
|
|
97
|
+
uv build
|
|
87
98
|
- id: attest
|
|
88
99
|
uses: actions/attest-build-provenance@v2
|
|
89
100
|
with:
|
|
@@ -106,38 +117,32 @@ jobs:
|
|
|
106
117
|
- uses: actions/setup-python@v5
|
|
107
118
|
with:
|
|
108
119
|
python-version: '3.12'
|
|
109
|
-
|
|
110
120
|
- uses: astral-sh/setup-uv@v5
|
|
111
121
|
with:
|
|
112
122
|
enable-cache: true
|
|
113
|
-
cache-suffix: "win-build"
|
|
114
|
-
|
|
115
|
-
# --- CACHE ---
|
|
123
|
+
cache-suffix: "win-build"
|
|
116
124
|
- name: Cache PyInstaller Analysis
|
|
117
125
|
uses: actions/cache@v4
|
|
118
126
|
with:
|
|
119
127
|
path: |
|
|
120
128
|
build
|
|
121
129
|
~\AppData\Local\pyinstaller
|
|
122
|
-
# Invalidates cache only if dependencies (uv.lock) change
|
|
123
130
|
key: pyinstaller-analysis-${{ runner.os }}-${{ hashFiles('uv.lock') }}
|
|
124
131
|
restore-keys: |
|
|
125
132
|
pyinstaller-analysis-${{ runner.os }}-
|
|
126
|
-
|
|
127
133
|
- shell: powershell
|
|
128
|
-
run:
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
134
|
+
run: |
|
|
135
|
+
echo "🛡️ Disabling Real-time Monitoring..."
|
|
136
|
+
Set-MpPreference -DisableRealtimeMonitoring $true
|
|
137
|
+
- run: |
|
|
138
|
+
echo "📥 Syncing dependencies..."
|
|
139
|
+
uv sync --group build
|
|
133
140
|
- run: |
|
|
141
|
+
echo "🪟 Starting PyInstaller build..."
|
|
134
142
|
uv run python -c "from PIL import Image; Image.open('Quasarr.png').save('Quasarr.ico')"
|
|
135
143
|
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
144
|
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
|
-
|
|
145
|
+
echo "✅ EXE build finished."
|
|
141
146
|
- uses: actions/upload-artifact@v4
|
|
142
147
|
with:
|
|
143
148
|
name: exe-amd64
|
|
@@ -165,10 +170,13 @@ jobs:
|
|
|
165
170
|
myToken: ${{ secrets.GITHUB_TOKEN }}
|
|
166
171
|
- name: Create Release Body
|
|
167
172
|
run: |
|
|
168
|
-
echo "
|
|
173
|
+
echo "📝 Generating Release Body..."
|
|
174
|
+
echo "# ${{ needs.version.outputs.version }} (${{ needs.version.outputs.epoch }})" > release_body.md
|
|
175
|
+
echo "" >> release_body.md
|
|
176
|
+
echo "### Docker:" >> release_body.md
|
|
169
177
|
echo "\`docker pull ${{ env.GHCR_ENDPOINT }}:beta\`" >> release_body.md
|
|
170
178
|
echo "### Python:" >> release_body.md
|
|
171
|
-
echo "\`uv tool
|
|
179
|
+
echo "\`uv tool install https://github.com/rix1337/Quasarr/releases/download/beta/quasarr-${{ needs.version.outputs.version }}-py3-none-any.whl\`" >> release_body.md
|
|
172
180
|
echo "### Changelog:" >> release_body.md
|
|
173
181
|
echo "${{ steps.changelog.outputs.changelog }}" >> release_body.md
|
|
174
182
|
echo "[Attestation](https://github.com/${{ github.repository }}/attestations/${{ needs.build-wheel.outputs.attestation-id }})" >> release_body.md
|
|
@@ -179,7 +187,7 @@ jobs:
|
|
|
179
187
|
removeArtifacts: true
|
|
180
188
|
replacesArtifacts: true
|
|
181
189
|
tag: beta
|
|
182
|
-
name:
|
|
190
|
+
name: "${{ needs.version.outputs.version }} (${{ needs.version.outputs.epoch }})"
|
|
183
191
|
bodyFile: "release_body.md"
|
|
184
192
|
prerelease: true
|
|
185
193
|
token: ${{ secrets.GITHUB_TOKEN }}
|
|
@@ -200,7 +208,8 @@ jobs:
|
|
|
200
208
|
registry: ghcr.io
|
|
201
209
|
username: ${{ github.actor }}
|
|
202
210
|
password: ${{ secrets.GITHUB_TOKEN }}
|
|
203
|
-
-
|
|
211
|
+
- name: Build and Push
|
|
212
|
+
uses: docker/build-push-action@v6
|
|
204
213
|
with:
|
|
205
214
|
context: ./docker
|
|
206
215
|
platforms: linux/amd64
|
|
@@ -231,7 +240,8 @@ jobs:
|
|
|
231
240
|
registry: ghcr.io
|
|
232
241
|
username: ${{ github.actor }}
|
|
233
242
|
password: ${{ secrets.GITHUB_TOKEN }}
|
|
234
|
-
-
|
|
243
|
+
- name: Build and Push
|
|
244
|
+
uses: docker/build-push-action@v6
|
|
235
245
|
with:
|
|
236
246
|
context: ./docker
|
|
237
247
|
platforms: linux/arm64
|
|
@@ -257,6 +267,7 @@ jobs:
|
|
|
257
267
|
username: ${{ github.actor }}
|
|
258
268
|
password: ${{ secrets.GITHUB_TOKEN }}
|
|
259
269
|
- run: |
|
|
270
|
+
echo "🔗 Merging Docker manifests..."
|
|
260
271
|
TAG_AMD64="${{ needs.version.outputs.version }}-beta-amd64"
|
|
261
272
|
TAG_ARM64="${{ needs.version.outputs.version }}-beta-arm64"
|
|
262
273
|
ANNOTATION="index:org.opencontainers.image.description=$DESCRIPTION"
|
|
@@ -274,61 +285,64 @@ jobs:
|
|
|
274
285
|
notify:
|
|
275
286
|
name: Notify Discord & PR
|
|
276
287
|
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
288
|
if: needs.quality-check.outputs.changes_pushed != 'true' && needs.beta-release.result == 'success'
|
|
279
289
|
runs-on: ubuntu-latest
|
|
280
290
|
permissions:
|
|
281
|
-
pull-requests: write
|
|
291
|
+
pull-requests: write
|
|
282
292
|
contents: read
|
|
283
293
|
steps:
|
|
284
294
|
- uses: actions/checkout@v6
|
|
285
|
-
|
|
286
295
|
- name: Send Notifications
|
|
287
296
|
env:
|
|
288
297
|
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
|
289
298
|
DISCORD_WEBHOOK: ${{ secrets.DISCORD_WEBHOOK }}
|
|
290
299
|
VERSION: ${{ needs.version.outputs.version }}
|
|
300
|
+
EPOCH: ${{ needs.version.outputs.epoch }}
|
|
291
301
|
REPO: ${{ github.repository }}
|
|
292
302
|
run: |
|
|
293
|
-
echo "
|
|
294
|
-
# Get the body of the release we just created (beta tag)
|
|
303
|
+
echo "📢 Notifying stakeholders..."
|
|
295
304
|
RELEASE_BODY=$(gh release view beta --json body --jq .body)
|
|
296
|
-
|
|
297
|
-
# --- 1. DISCORD NOTIFICATION ---
|
|
298
305
|
if [ -n "$DISCORD_WEBHOOK" ]; then
|
|
299
|
-
|
|
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)"
|
|
306
|
+
jq -n --arg title "🚀 New Beta Build: $VERSION ($EPOCH)" --arg url "https://github.com/$REPO/releases/tag/beta" '{content: null, flags: 4096, embeds: [{title: $title, url: $url, color: 5814783}]}' > discord_payload.json
|
|
307
|
+
curl -H "Content-Type: application/json" -d @discord_payload.json "$DISCORD_WEBHOOK"
|
|
315
308
|
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
309
|
PR_NUMBER=$(gh pr list --search "${{ github.sha }}" --state merged --json number --jq '.[0].number')
|
|
321
|
-
|
|
322
310
|
if [ -n "$PR_NUMBER" ]; then
|
|
323
|
-
echo "Found PR #$PR_NUMBER. Posting comment..."
|
|
324
|
-
|
|
325
311
|
echo "## 🚀 Beta Release $VERSION is Live!" > pr_comment.md
|
|
326
|
-
echo "" >> pr_comment.md
|
|
327
312
|
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
313
|
gh pr comment "$PR_NUMBER" --body-file pr_comment.md
|
|
314
|
+
fi
|
|
315
|
+
|
|
316
|
+
job-summary:
|
|
317
|
+
name: 📊 Beta Summary
|
|
318
|
+
runs-on: ubuntu-latest
|
|
319
|
+
needs: [ quality-check, version, beta-release ]
|
|
320
|
+
if: always()
|
|
321
|
+
steps:
|
|
322
|
+
- name: Generate Summary
|
|
323
|
+
run: |
|
|
324
|
+
echo "## 🧪 Beta Build Summary" >> $GITHUB_STEP_SUMMARY
|
|
325
|
+
|
|
326
|
+
# Maintenance Outcome
|
|
327
|
+
if [[ "${{ needs.quality-check.outputs.changes_pushed }}" == "true" ]]; then
|
|
328
|
+
echo "### 🛠️ Maintenance Status: **Auto-Fixed**" >> $GITHUB_STEP_SUMMARY
|
|
329
|
+
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
330
|
else
|
|
333
|
-
echo "
|
|
331
|
+
echo "### ✨ Maintenance Status: **Clean**" >> $GITHUB_STEP_SUMMARY
|
|
332
|
+
echo "No formatting or maintenance issues were detected." >> $GITHUB_STEP_SUMMARY
|
|
334
333
|
fi
|
|
334
|
+
|
|
335
|
+
# Decision Logic
|
|
336
|
+
echo "### 🚦 Workflow Decision" >> $GITHUB_STEP_SUMMARY
|
|
337
|
+
if [[ "${{ needs.version.result }}" == "success" ]]; then
|
|
338
|
+
echo "✅ **Proceeded:** The build moved to beta release (Dev branch detected)." >> $GITHUB_STEP_SUMMARY
|
|
339
|
+
else
|
|
340
|
+
echo "🛑 **Stopped:** Build did not proceed to release (Not on dev or quality-check failed)." >> $GITHUB_STEP_SUMMARY
|
|
341
|
+
fi
|
|
342
|
+
|
|
343
|
+
echo "### 📦 Artifact Details" >> $GITHUB_STEP_SUMMARY
|
|
344
|
+
echo "| Metric | Value |" >> $GITHUB_STEP_SUMMARY
|
|
345
|
+
echo "| --- | --- |" >> $GITHUB_STEP_SUMMARY
|
|
346
|
+
echo "| **Version** | \`${{ needs.version.outputs.version || 'N/A' }}\` |" >> $GITHUB_STEP_SUMMARY
|
|
347
|
+
echo "| **Epoch** | \`${{ needs.version.outputs.epoch || 'N/A' }}\` |" >> $GITHUB_STEP_SUMMARY
|
|
348
|
+
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
|
-
|
|
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:
|
|
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 }}
|
|
228
|
-
|
|
229
|
-
|
|
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:
|
|
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
|
-
|
|
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,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
|
|
44
|
+
**Format code AND upgrade dependencie manually:**
|
|
39
45
|
|
|
40
46
|
```bash
|
|
41
|
-
uv run
|
|
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.
|
|
3
|
+
Version: 2.5.0
|
|
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
|