tubetracks 1.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.
- tubetracks-1.5.0/.github/workflows/build.yml +1004 -0
- tubetracks-1.5.0/.github/workflows/publish-pypi.yml +88 -0
- tubetracks-1.5.0/CHANGELOG.md +47 -0
- tubetracks-1.5.0/LICENSE +448 -0
- tubetracks-1.5.0/MANIFEST.in +12 -0
- tubetracks-1.5.0/Makefile +272 -0
- tubetracks-1.5.0/PKG-INFO +307 -0
- tubetracks-1.5.0/PLUGIN_API.md +552 -0
- tubetracks-1.5.0/README.md +258 -0
- tubetracks-1.5.0/downloader.py +2453 -0
- tubetracks-1.5.0/example.audiodownload.conf +47 -0
- tubetracks-1.5.0/example_urls.txt +12 -0
- tubetracks-1.5.0/plugins/__init__.py +76 -0
- tubetracks-1.5.0/plugins/base.py +287 -0
- tubetracks-1.5.0/plugins/dailymotion.py +149 -0
- tubetracks-1.5.0/plugins/instagram.py +147 -0
- tubetracks-1.5.0/plugins/reddit.py +146 -0
- tubetracks-1.5.0/plugins/soundcloud.py +151 -0
- tubetracks-1.5.0/plugins/spotify.py +156 -0
- tubetracks-1.5.0/plugins/tiktok.py +150 -0
- tubetracks-1.5.0/plugins/twitch.py +147 -0
- tubetracks-1.5.0/plugins/vimeo.py +151 -0
- tubetracks-1.5.0/plugins/youtube.py +171 -0
- tubetracks-1.5.0/pyproject.toml +97 -0
- tubetracks-1.5.0/requirements.txt +7 -0
- tubetracks-1.5.0/setup.cfg +4 -0
- tubetracks-1.5.0/tests/test_plugins.py +641 -0
- tubetracks-1.5.0/tests/test_smoke.py +398 -0
- tubetracks-1.5.0/tubetracks.egg-info/PKG-INFO +307 -0
- tubetracks-1.5.0/tubetracks.egg-info/SOURCES.txt +46 -0
- tubetracks-1.5.0/tubetracks.egg-info/dependency_links.txt +1 -0
- tubetracks-1.5.0/tubetracks.egg-info/entry_points.txt +5 -0
- tubetracks-1.5.0/tubetracks.egg-info/requires.txt +12 -0
- tubetracks-1.5.0/tubetracks.egg-info/top_level.txt +3 -0
- tubetracks-1.5.0/tubetracks_gui.py +974 -0
|
@@ -0,0 +1,1004 @@
|
|
|
1
|
+
name: Build and Test
|
|
2
|
+
|
|
3
|
+
on:
|
|
4
|
+
workflow_dispatch: # Manual trigger only
|
|
5
|
+
schedule:
|
|
6
|
+
- cron: '0 0 * * 0' # Weekly run every Sunday at midnight UTC
|
|
7
|
+
|
|
8
|
+
permissions:
|
|
9
|
+
contents: read
|
|
10
|
+
pull-requests: write
|
|
11
|
+
checks: write
|
|
12
|
+
|
|
13
|
+
env:
|
|
14
|
+
PYTHON_VERSION_DEFAULT: '3.12'
|
|
15
|
+
CACHE_VERSION: v1
|
|
16
|
+
|
|
17
|
+
jobs:
|
|
18
|
+
lint:
|
|
19
|
+
name: Code Quality & Style Checks
|
|
20
|
+
runs-on: ubuntu-latest
|
|
21
|
+
timeout-minutes: 10
|
|
22
|
+
|
|
23
|
+
steps:
|
|
24
|
+
- name: Checkout code
|
|
25
|
+
uses: actions/checkout@v4
|
|
26
|
+
with:
|
|
27
|
+
fetch-depth: 0 # Full history for better analysis
|
|
28
|
+
|
|
29
|
+
- name: Set up Python ${{ env.PYTHON_VERSION_DEFAULT }}
|
|
30
|
+
uses: actions/setup-python@v5
|
|
31
|
+
with:
|
|
32
|
+
python-version: ${{ env.PYTHON_VERSION_DEFAULT }}
|
|
33
|
+
cache: 'pip'
|
|
34
|
+
cache-dependency-path: requirements.txt
|
|
35
|
+
|
|
36
|
+
- name: Install dependencies
|
|
37
|
+
run: |
|
|
38
|
+
python -m pip install --upgrade pip setuptools wheel
|
|
39
|
+
pip install flake8 black isort pylint mypy
|
|
40
|
+
|
|
41
|
+
- name: Code formatting check (Black)
|
|
42
|
+
run: |
|
|
43
|
+
black --check --diff . || {
|
|
44
|
+
echo "Code formatting issues detected"
|
|
45
|
+
echo "Fix with: black ."
|
|
46
|
+
exit 1
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
- name: Import sorting check (isort)
|
|
50
|
+
run: |
|
|
51
|
+
isort --check-only --diff . || {
|
|
52
|
+
echo "Import sorting issues detected"
|
|
53
|
+
echo "Fix with: isort ."
|
|
54
|
+
exit 1
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
- name: Lint with Flake8 (Critical errors)
|
|
58
|
+
run: |
|
|
59
|
+
# Stop on critical errors
|
|
60
|
+
flake8 . --count --select=E9,F63,F7,F82 --show-source --statistics
|
|
61
|
+
|
|
62
|
+
- name: Lint with Flake8 (Style guide)
|
|
63
|
+
run: |
|
|
64
|
+
# Check style but don't fail the build
|
|
65
|
+
flake8 . --count --max-complexity=10 --max-line-length=127 \
|
|
66
|
+
--statistics --exit-zero
|
|
67
|
+
|
|
68
|
+
- name: Lint with Pylint
|
|
69
|
+
run: |
|
|
70
|
+
pylint downloader.py plugins/ tests/ --exit-zero \
|
|
71
|
+
--output-format=colorized \
|
|
72
|
+
--reports=y
|
|
73
|
+
continue-on-error: true
|
|
74
|
+
|
|
75
|
+
- name: Type checking with mypy
|
|
76
|
+
run: |
|
|
77
|
+
mypy downloader.py plugins/ --ignore-missing-imports --no-strict-optional
|
|
78
|
+
continue-on-error: true
|
|
79
|
+
|
|
80
|
+
security:
|
|
81
|
+
name: Security Scanning
|
|
82
|
+
runs-on: ubuntu-latest
|
|
83
|
+
timeout-minutes: 10
|
|
84
|
+
|
|
85
|
+
steps:
|
|
86
|
+
- name: Checkout code
|
|
87
|
+
uses: actions/checkout@v4
|
|
88
|
+
|
|
89
|
+
- name: Set up Python ${{ env.PYTHON_VERSION_DEFAULT }}
|
|
90
|
+
uses: actions/setup-python@v5
|
|
91
|
+
with:
|
|
92
|
+
python-version: ${{ env.PYTHON_VERSION_DEFAULT }}
|
|
93
|
+
cache: 'pip'
|
|
94
|
+
cache-dependency-path: requirements.txt
|
|
95
|
+
|
|
96
|
+
- name: Install dependencies
|
|
97
|
+
run: |
|
|
98
|
+
python -m pip install --upgrade pip
|
|
99
|
+
pip install -r requirements.txt
|
|
100
|
+
|
|
101
|
+
- name: Install security tools
|
|
102
|
+
run: pip install bandit safety pip-audit
|
|
103
|
+
|
|
104
|
+
- name: Run Bandit security scanner
|
|
105
|
+
run: |
|
|
106
|
+
echo "Running Bandit security analysis..."
|
|
107
|
+
bandit -r . -f json -o bandit-report.json --exit-zero
|
|
108
|
+
bandit -r . -f screen --exit-zero
|
|
109
|
+
continue-on-error: true
|
|
110
|
+
|
|
111
|
+
- name: Check dependencies with Safety
|
|
112
|
+
run: |
|
|
113
|
+
echo "Checking dependencies for known vulnerabilities..."
|
|
114
|
+
safety check --json || echo "Vulnerabilities detected"
|
|
115
|
+
continue-on-error: true
|
|
116
|
+
|
|
117
|
+
- name: Audit dependencies with pip-audit
|
|
118
|
+
run: |
|
|
119
|
+
echo "Auditing Python packages..."
|
|
120
|
+
pip-audit --desc --format json || echo "Issues found"
|
|
121
|
+
continue-on-error: true
|
|
122
|
+
|
|
123
|
+
- name: Upload security reports
|
|
124
|
+
if: always()
|
|
125
|
+
uses: actions/upload-artifact@v4
|
|
126
|
+
with:
|
|
127
|
+
name: security-reports
|
|
128
|
+
path: |
|
|
129
|
+
bandit-report.json
|
|
130
|
+
retention-days: 30
|
|
131
|
+
|
|
132
|
+
build:
|
|
133
|
+
name: Test on ${{ matrix.os }} with Python ${{ matrix.python-version }}
|
|
134
|
+
runs-on: ${{ matrix.os }}
|
|
135
|
+
timeout-minutes: 20
|
|
136
|
+
|
|
137
|
+
strategy:
|
|
138
|
+
fail-fast: false
|
|
139
|
+
matrix:
|
|
140
|
+
os: [ubuntu-latest, windows-latest, macos-latest]
|
|
141
|
+
python-version: ['3.8', '3.9', '3.10', '3.11', '3.12']
|
|
142
|
+
exclude:
|
|
143
|
+
# Optimize CI time by skipping some combinations
|
|
144
|
+
- os: windows-latest
|
|
145
|
+
python-version: '3.8'
|
|
146
|
+
- os: windows-latest
|
|
147
|
+
python-version: '3.9'
|
|
148
|
+
- os: macos-latest
|
|
149
|
+
python-version: '3.8'
|
|
150
|
+
- os: macos-latest
|
|
151
|
+
python-version: '3.9'
|
|
152
|
+
|
|
153
|
+
env:
|
|
154
|
+
PYTHONIOENCODING: utf-8
|
|
155
|
+
PYTHONUTF8: 1
|
|
156
|
+
FORCE_COLOR: 1
|
|
157
|
+
|
|
158
|
+
steps:
|
|
159
|
+
- name: Checkout code
|
|
160
|
+
uses: actions/checkout@v4
|
|
161
|
+
with:
|
|
162
|
+
fetch-depth: 0
|
|
163
|
+
|
|
164
|
+
- name: Set up Python ${{ matrix.python-version }}
|
|
165
|
+
uses: actions/setup-python@v5
|
|
166
|
+
with:
|
|
167
|
+
python-version: ${{ matrix.python-version }}
|
|
168
|
+
cache: 'pip'
|
|
169
|
+
cache-dependency-path: |
|
|
170
|
+
requirements.txt
|
|
171
|
+
pyproject.toml
|
|
172
|
+
|
|
173
|
+
- name: Display Python version
|
|
174
|
+
run: python -c "import sys; print(f'Python {sys.version}')"
|
|
175
|
+
|
|
176
|
+
- name: Upgrade pip and install build tools
|
|
177
|
+
shell: bash
|
|
178
|
+
run: |
|
|
179
|
+
python -m pip install --upgrade pip setuptools wheel
|
|
180
|
+
pip --version
|
|
181
|
+
|
|
182
|
+
- name: Install project dependencies
|
|
183
|
+
shell: bash
|
|
184
|
+
run: |
|
|
185
|
+
echo "Installing dependencies..."
|
|
186
|
+
pip install -r requirements.txt || {
|
|
187
|
+
echo "Dependency installation failed"
|
|
188
|
+
echo ""
|
|
189
|
+
echo "Diagnostic information:"
|
|
190
|
+
cat requirements.txt
|
|
191
|
+
exit 1
|
|
192
|
+
}
|
|
193
|
+
echo ""
|
|
194
|
+
echo "📋 Installed packages:"
|
|
195
|
+
pip list
|
|
196
|
+
|
|
197
|
+
- name: Install test dependencies
|
|
198
|
+
shell: bash
|
|
199
|
+
run: |
|
|
200
|
+
echo "Installing test dependencies..."
|
|
201
|
+
pip install pytest pytest-cov pytest-xdist pytest-timeout pytest-mock
|
|
202
|
+
|
|
203
|
+
- name: Run test suite
|
|
204
|
+
shell: bash
|
|
205
|
+
run: |
|
|
206
|
+
echo "Running tests with coverage..."
|
|
207
|
+
pytest tests/ -v \
|
|
208
|
+
--cov=. \
|
|
209
|
+
--cov-report=xml \
|
|
210
|
+
--cov-report=html \
|
|
211
|
+
--cov-report=term-missing \
|
|
212
|
+
-n auto \
|
|
213
|
+
--timeout=300 \
|
|
214
|
+
--tb=short || {
|
|
215
|
+
echo "Tests failed"
|
|
216
|
+
echo ""
|
|
217
|
+
echo "Test environment:"
|
|
218
|
+
echo "Python: $(python --version)"
|
|
219
|
+
echo "pytest: $(pytest --version)"
|
|
220
|
+
echo ""
|
|
221
|
+
echo "Installed packages:"
|
|
222
|
+
pip list
|
|
223
|
+
echo ""
|
|
224
|
+
echo "Test directory structure:"
|
|
225
|
+
ls -la tests/
|
|
226
|
+
exit 1
|
|
227
|
+
}
|
|
228
|
+
echo "All tests passed"
|
|
229
|
+
timeout-minutes: 10
|
|
230
|
+
env:
|
|
231
|
+
COVERAGE_CORE: sysmon
|
|
232
|
+
|
|
233
|
+
- name: Upload coverage to Codecov
|
|
234
|
+
uses: codecov/codecov-action@v4
|
|
235
|
+
if: matrix.os == 'ubuntu-latest' && matrix.python-version == '3.12'
|
|
236
|
+
with:
|
|
237
|
+
file: ./coverage.xml
|
|
238
|
+
flags: unittests
|
|
239
|
+
name: codecov-${{ matrix.os }}-py${{ matrix.python-version }}
|
|
240
|
+
fail_ci_if_error: false
|
|
241
|
+
verbose: true
|
|
242
|
+
continue-on-error: true
|
|
243
|
+
|
|
244
|
+
- name: Compile Python files
|
|
245
|
+
shell: bash
|
|
246
|
+
run: |
|
|
247
|
+
echo "Compiling Python files..."
|
|
248
|
+
python -m py_compile downloader.py
|
|
249
|
+
python -m compileall plugins/ -q
|
|
250
|
+
python -m compileall tests/ -q
|
|
251
|
+
echo "Compilation successful"
|
|
252
|
+
|
|
253
|
+
- name: Verify imports
|
|
254
|
+
shell: bash
|
|
255
|
+
run: |
|
|
256
|
+
echo "Verifying imports..."
|
|
257
|
+
python -c "import downloader; print('OK: downloader imported')" || {
|
|
258
|
+
echo "Failed to import downloader"
|
|
259
|
+
echo ""
|
|
260
|
+
echo "Python environment:"
|
|
261
|
+
python -c "import sys; print('Python path:'); print('\n'.join(sys.path))"
|
|
262
|
+
echo ""
|
|
263
|
+
echo "Current directory:"
|
|
264
|
+
ls -la
|
|
265
|
+
exit 1
|
|
266
|
+
}
|
|
267
|
+
|
|
268
|
+
python -c "from plugins import get_global_registry; print('OK: plugins imported')" || {
|
|
269
|
+
echo "Failed to import plugins"
|
|
270
|
+
echo ""
|
|
271
|
+
echo "Plugins directory:"
|
|
272
|
+
ls -la plugins/
|
|
273
|
+
exit 1
|
|
274
|
+
}
|
|
275
|
+
|
|
276
|
+
echo "All imports successful"
|
|
277
|
+
|
|
278
|
+
- name: Test CLI interface
|
|
279
|
+
shell: bash
|
|
280
|
+
run: |
|
|
281
|
+
echo "Testing CLI..."
|
|
282
|
+
python downloader.py --help
|
|
283
|
+
python downloader.py --version
|
|
284
|
+
python downloader.py --show-config
|
|
285
|
+
python downloader.py --list-plugins
|
|
286
|
+
echo "CLI tests passed"
|
|
287
|
+
|
|
288
|
+
- name: Test GUI module imports
|
|
289
|
+
shell: bash
|
|
290
|
+
run: |
|
|
291
|
+
echo "Testing GUI module..."
|
|
292
|
+
python -c "import tubetracks_gui; print('OK: GUI module imports successfully')"
|
|
293
|
+
echo "GUI module test passed"
|
|
294
|
+
continue-on-error: true # tkinter may not be available in all CI environments
|
|
295
|
+
|
|
296
|
+
- name: Archive test artifacts
|
|
297
|
+
if: failure()
|
|
298
|
+
uses: actions/upload-artifact@v4
|
|
299
|
+
with:
|
|
300
|
+
name: test-artifacts-${{ matrix.os }}-py${{ matrix.python-version }}
|
|
301
|
+
path: |
|
|
302
|
+
htmlcov/
|
|
303
|
+
.coverage
|
|
304
|
+
coverage.xml
|
|
305
|
+
*.log
|
|
306
|
+
retention-days: 14
|
|
307
|
+
|
|
308
|
+
build-package:
|
|
309
|
+
name: Build Distribution Packages
|
|
310
|
+
runs-on: ubuntu-latest
|
|
311
|
+
needs: [build]
|
|
312
|
+
timeout-minutes: 10
|
|
313
|
+
|
|
314
|
+
steps:
|
|
315
|
+
- name: Checkout code
|
|
316
|
+
uses: actions/checkout@v4
|
|
317
|
+
with:
|
|
318
|
+
fetch-depth: 0 # Required for version detection
|
|
319
|
+
|
|
320
|
+
- name: Set up Python ${{ env.PYTHON_VERSION_DEFAULT }}
|
|
321
|
+
uses: actions/setup-python@v5
|
|
322
|
+
with:
|
|
323
|
+
python-version: ${{ env.PYTHON_VERSION_DEFAULT }}
|
|
324
|
+
cache: 'pip'
|
|
325
|
+
|
|
326
|
+
- name: Install build tools
|
|
327
|
+
run: |
|
|
328
|
+
echo "Installing build tools..."
|
|
329
|
+
python -m pip install --upgrade pip setuptools wheel
|
|
330
|
+
pip install build twine check-wheel-contents
|
|
331
|
+
pip list | grep -E "(build|twine|setuptools|wheel)"
|
|
332
|
+
|
|
333
|
+
- name: Validate package configuration
|
|
334
|
+
run: |
|
|
335
|
+
echo "Validating pyproject.toml..."
|
|
336
|
+
if [ ! -f pyproject.toml ]; then
|
|
337
|
+
echo "ERROR: pyproject.toml not found"
|
|
338
|
+
exit 1
|
|
339
|
+
fi
|
|
340
|
+
|
|
341
|
+
echo "pyproject.toml found"
|
|
342
|
+
echo "Configuration:"
|
|
343
|
+
python -c "import tomllib; f=open('pyproject.toml','rb'); print(tomllib.load(f))" || \
|
|
344
|
+
python -c "import tomli; f=open('pyproject.toml','rb'); print(tomli.load(f))" || \
|
|
345
|
+
echo "Cannot parse TOML (Python < 3.11 without tomli)"
|
|
346
|
+
|
|
347
|
+
echo ""
|
|
348
|
+
echo "Project structure:"
|
|
349
|
+
ls -la
|
|
350
|
+
echo ""
|
|
351
|
+
echo "Plugins directory:"
|
|
352
|
+
ls -la plugins/ || echo "plugins/ directory not found"
|
|
353
|
+
|
|
354
|
+
- name: Pre-build validation
|
|
355
|
+
run: |
|
|
356
|
+
echo "Pre-build validation..."
|
|
357
|
+
|
|
358
|
+
# Check required files exist
|
|
359
|
+
echo "Checking required files..."
|
|
360
|
+
test -f downloader.py || (echo "downloader.py missing" && exit 1)
|
|
361
|
+
test -f tubetracks_gui.py || (echo "tubetracks_gui.py missing" && exit 1)
|
|
362
|
+
test -d plugins || (echo "plugins/ directory missing" && exit 1)
|
|
363
|
+
test -f plugins/__init__.py || (echo "plugins/__init__.py missing" && exit 1)
|
|
364
|
+
|
|
365
|
+
# Verify Python syntax is valid (without importing dependencies)
|
|
366
|
+
echo "Verifying Python syntax..."
|
|
367
|
+
python -m py_compile downloader.py || (echo "downloader.py has syntax errors" && exit 1)
|
|
368
|
+
python -m py_compile tubetracks_gui.py || (echo "tubetracks_gui.py has syntax errors" && exit 1)
|
|
369
|
+
python -m compileall plugins/ -q || (echo "plugins/ has syntax errors" && exit 1)
|
|
370
|
+
|
|
371
|
+
echo "Pre-build validation passed"
|
|
372
|
+
|
|
373
|
+
- name: Build source and wheel distributions
|
|
374
|
+
run: |
|
|
375
|
+
echo "Building distributions..."
|
|
376
|
+
python -m build --verbose || {
|
|
377
|
+
echo "Build failed!"
|
|
378
|
+
echo ""
|
|
379
|
+
echo "Diagnostic information:"
|
|
380
|
+
echo "Python version: $(python --version)"
|
|
381
|
+
echo "pip version: $(pip --version)"
|
|
382
|
+
echo ""
|
|
383
|
+
echo "Installed packages:"
|
|
384
|
+
pip list
|
|
385
|
+
echo ""
|
|
386
|
+
echo "Current directory contents:"
|
|
387
|
+
ls -la
|
|
388
|
+
echo ""
|
|
389
|
+
echo "pyproject.toml content:"
|
|
390
|
+
cat pyproject.toml
|
|
391
|
+
exit 1
|
|
392
|
+
}
|
|
393
|
+
|
|
394
|
+
echo ""
|
|
395
|
+
echo "Build completed successfully"
|
|
396
|
+
echo ""
|
|
397
|
+
echo "Generated distributions:"
|
|
398
|
+
ls -lh dist/
|
|
399
|
+
echo ""
|
|
400
|
+
echo "Distribution details:"
|
|
401
|
+
du -h dist/*
|
|
402
|
+
|
|
403
|
+
- name: Verify distributions exist
|
|
404
|
+
run: |
|
|
405
|
+
echo "Verifying generated distributions..."
|
|
406
|
+
|
|
407
|
+
# Check for expected files
|
|
408
|
+
WHEEL_COUNT=$(ls -1 dist/*.whl 2>/dev/null | wc -l)
|
|
409
|
+
TARBALL_COUNT=$(ls -1 dist/*.tar.gz 2>/dev/null | wc -l)
|
|
410
|
+
|
|
411
|
+
echo "Found $WHEEL_COUNT wheel(s) and $TARBALL_COUNT source distribution(s)"
|
|
412
|
+
|
|
413
|
+
if [ "$WHEEL_COUNT" -eq 0 ]; then
|
|
414
|
+
echo "ERROR: No wheel (.whl) file generated"
|
|
415
|
+
echo "dist/ directory contents:"
|
|
416
|
+
ls -la dist/ || echo "dist/ directory does not exist"
|
|
417
|
+
exit 1
|
|
418
|
+
fi
|
|
419
|
+
|
|
420
|
+
if [ "$TARBALL_COUNT" -eq 0 ]; then
|
|
421
|
+
echo "ERROR: No source distribution (.tar.gz) file generated"
|
|
422
|
+
echo "dist/ directory contents:"
|
|
423
|
+
ls -la dist/
|
|
424
|
+
exit 1
|
|
425
|
+
fi
|
|
426
|
+
|
|
427
|
+
echo "All expected distributions generated"
|
|
428
|
+
|
|
429
|
+
- name: Check distribution packages
|
|
430
|
+
run: |
|
|
431
|
+
echo "Checking distribution quality..."
|
|
432
|
+
|
|
433
|
+
echo "Running twine check..."
|
|
434
|
+
twine check dist/* --strict || {
|
|
435
|
+
echo "Twine check failed"
|
|
436
|
+
echo ""
|
|
437
|
+
echo "Distribution contents:"
|
|
438
|
+
for file in dist/*; do
|
|
439
|
+
echo "--- $file ---"
|
|
440
|
+
if [[ $file == *.whl ]]; then
|
|
441
|
+
python -m zipfile -l "$file" || echo "Cannot list wheel contents"
|
|
442
|
+
elif [[ $file == *.tar.gz ]]; then
|
|
443
|
+
tar -tzf "$file" 2>/dev/null | head -30 || echo "Cannot list tarball contents"
|
|
444
|
+
fi
|
|
445
|
+
done
|
|
446
|
+
exit 1
|
|
447
|
+
}
|
|
448
|
+
|
|
449
|
+
echo "Twine check passed"
|
|
450
|
+
|
|
451
|
+
echo ""
|
|
452
|
+
echo "Running wheel contents check..."
|
|
453
|
+
check-wheel-contents dist/*.whl || {
|
|
454
|
+
echo "Wheel contents check found issues (non-critical)"
|
|
455
|
+
}
|
|
456
|
+
|
|
457
|
+
- name: Display package info
|
|
458
|
+
run: |
|
|
459
|
+
echo "Package information:"
|
|
460
|
+
echo ""
|
|
461
|
+
|
|
462
|
+
for file in dist/*; do
|
|
463
|
+
echo "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━"
|
|
464
|
+
echo "$(basename $file)"
|
|
465
|
+
echo "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━"
|
|
466
|
+
|
|
467
|
+
if [[ $file == *.whl ]]; then
|
|
468
|
+
echo "Type: Wheel Distribution"
|
|
469
|
+
echo "Size: $(du -h $file | cut -f1)"
|
|
470
|
+
echo ""
|
|
471
|
+
echo "Contents (first 30 files):"
|
|
472
|
+
python -m zipfile -l "$file" | head -30
|
|
473
|
+
elif [[ $file == *.tar.gz ]]; then
|
|
474
|
+
echo "Type: Source Distribution"
|
|
475
|
+
echo "Size: $(du -h $file | cut -f1)"
|
|
476
|
+
echo ""
|
|
477
|
+
echo "Contents (first 30 files):"
|
|
478
|
+
tar -tzf "$file" 2>/dev/null | head -30
|
|
479
|
+
fi
|
|
480
|
+
echo ""
|
|
481
|
+
done
|
|
482
|
+
|
|
483
|
+
- name: Test wheel installation in isolated environment
|
|
484
|
+
run: |
|
|
485
|
+
echo "Testing wheel installation in isolated environment..."
|
|
486
|
+
|
|
487
|
+
# Create a temporary virtual environment
|
|
488
|
+
python -m venv test_env
|
|
489
|
+
source test_env/bin/activate
|
|
490
|
+
|
|
491
|
+
echo "Installing wheel..."
|
|
492
|
+
pip install --upgrade pip
|
|
493
|
+
pip install dist/*.whl || {
|
|
494
|
+
echo "Wheel installation failed"
|
|
495
|
+
deactivate
|
|
496
|
+
exit 1
|
|
497
|
+
}
|
|
498
|
+
|
|
499
|
+
echo "Testing imports..."
|
|
500
|
+
python -c "import downloader; print('OK: downloader')" || {
|
|
501
|
+
echo "Cannot import downloader"
|
|
502
|
+
deactivate
|
|
503
|
+
exit 1
|
|
504
|
+
}
|
|
505
|
+
|
|
506
|
+
python -c "from plugins import get_global_registry; print('OK: plugins')" || {
|
|
507
|
+
echo "Cannot import plugins"
|
|
508
|
+
deactivate
|
|
509
|
+
exit 1
|
|
510
|
+
}
|
|
511
|
+
|
|
512
|
+
echo "Testing CLI..."
|
|
513
|
+
tubetracks --version || {
|
|
514
|
+
echo "CLI command failed"
|
|
515
|
+
deactivate
|
|
516
|
+
exit 1
|
|
517
|
+
}
|
|
518
|
+
|
|
519
|
+
deactivate
|
|
520
|
+
rm -rf test_env
|
|
521
|
+
|
|
522
|
+
echo "Wheel installation test passed"
|
|
523
|
+
|
|
524
|
+
- name: Upload distribution artifacts
|
|
525
|
+
uses: actions/upload-artifact@v4
|
|
526
|
+
with:
|
|
527
|
+
name: python-package-distributions
|
|
528
|
+
path: dist/
|
|
529
|
+
retention-days: 30
|
|
530
|
+
if-no-files-found: error
|
|
531
|
+
|
|
532
|
+
- name: Upload build logs on failure
|
|
533
|
+
if: failure()
|
|
534
|
+
uses: actions/upload-artifact@v4
|
|
535
|
+
with:
|
|
536
|
+
name: build-package-debug-logs
|
|
537
|
+
path: |
|
|
538
|
+
pyproject.toml
|
|
539
|
+
setup.py
|
|
540
|
+
build/
|
|
541
|
+
*.egg-info/
|
|
542
|
+
retention-days: 7
|
|
543
|
+
if-no-files-found: ignore
|
|
544
|
+
|
|
545
|
+
test-gui:
|
|
546
|
+
name: Test GUI Components on ${{ matrix.os }}
|
|
547
|
+
runs-on: ${{ matrix.os }}
|
|
548
|
+
needs: [build]
|
|
549
|
+
timeout-minutes: 10
|
|
550
|
+
|
|
551
|
+
strategy:
|
|
552
|
+
matrix:
|
|
553
|
+
os: [ubuntu-latest, windows-latest, macos-latest]
|
|
554
|
+
|
|
555
|
+
steps:
|
|
556
|
+
- name: Checkout code
|
|
557
|
+
uses: actions/checkout@v4
|
|
558
|
+
|
|
559
|
+
- name: Set up Python ${{ env.PYTHON_VERSION_DEFAULT }}
|
|
560
|
+
uses: actions/setup-python@v5
|
|
561
|
+
with:
|
|
562
|
+
python-version: ${{ env.PYTHON_VERSION_DEFAULT }}
|
|
563
|
+
cache: 'pip'
|
|
564
|
+
|
|
565
|
+
- name: Install dependencies
|
|
566
|
+
shell: bash
|
|
567
|
+
run: |
|
|
568
|
+
python -m pip install --upgrade pip
|
|
569
|
+
pip install -r requirements.txt
|
|
570
|
+
|
|
571
|
+
- name: Install tkinter (Ubuntu only)
|
|
572
|
+
if: matrix.os == 'ubuntu-latest'
|
|
573
|
+
run: |
|
|
574
|
+
sudo apt-get update
|
|
575
|
+
sudo apt-get install -y python3-tk
|
|
576
|
+
|
|
577
|
+
- name: Test GUI module import
|
|
578
|
+
shell: bash
|
|
579
|
+
run: |
|
|
580
|
+
echo "Testing GUI module import..."
|
|
581
|
+
python -c "import tubetracks_gui; print('OK: GUI module loaded')" || echo "GUI module import failed (tkinter may not be available)"
|
|
582
|
+
continue-on-error: true
|
|
583
|
+
|
|
584
|
+
- name: Test GUI help/version
|
|
585
|
+
shell: bash
|
|
586
|
+
run: |
|
|
587
|
+
echo "Testing GUI help..."
|
|
588
|
+
python tubetracks_gui.py --help || echo "GUI help not available"
|
|
589
|
+
continue-on-error: true
|
|
590
|
+
|
|
591
|
+
- name: Validate GUI file structure
|
|
592
|
+
shell: bash
|
|
593
|
+
run: |
|
|
594
|
+
echo "Validating GUI components..."
|
|
595
|
+
test -f tubetracks_gui.py || (echo "tubetracks_gui.py not found" && exit 1)
|
|
596
|
+
grep -q "class App" tubetracks_gui.py || (echo "App class not found" && exit 1)
|
|
597
|
+
grep -q "def main" tubetracks_gui.py || (echo "main function not found" && exit 1)
|
|
598
|
+
echo "GUI structure validated"
|
|
599
|
+
|
|
600
|
+
test-install:
|
|
601
|
+
name: Test Package Installation
|
|
602
|
+
runs-on: ${{ matrix.os }}
|
|
603
|
+
needs: [build-package]
|
|
604
|
+
timeout-minutes: 10
|
|
605
|
+
|
|
606
|
+
env:
|
|
607
|
+
PYTHONIOENCODING: utf-8
|
|
608
|
+
PYTHONUTF8: 1
|
|
609
|
+
|
|
610
|
+
strategy:
|
|
611
|
+
fail-fast: false
|
|
612
|
+
matrix:
|
|
613
|
+
os: [ubuntu-latest, windows-latest, macos-latest]
|
|
614
|
+
|
|
615
|
+
steps:
|
|
616
|
+
- name: Checkout code (for verification)
|
|
617
|
+
uses: actions/checkout@v4
|
|
618
|
+
|
|
619
|
+
- name: Set up Python ${{ env.PYTHON_VERSION_DEFAULT }}
|
|
620
|
+
uses: actions/setup-python@v5
|
|
621
|
+
with:
|
|
622
|
+
python-version: ${{ env.PYTHON_VERSION_DEFAULT }}
|
|
623
|
+
|
|
624
|
+
- name: Download distribution artifacts
|
|
625
|
+
uses: actions/download-artifact@v4
|
|
626
|
+
with:
|
|
627
|
+
name: python-package-distributions
|
|
628
|
+
path: dist/
|
|
629
|
+
|
|
630
|
+
- name: Display downloaded files
|
|
631
|
+
shell: bash
|
|
632
|
+
run: |
|
|
633
|
+
echo "Downloaded distributions:"
|
|
634
|
+
ls -lh dist/
|
|
635
|
+
echo ""
|
|
636
|
+
echo "File details:"
|
|
637
|
+
for file in dist/*; do
|
|
638
|
+
echo " - $(basename $file): $(du -h $file | cut -f1)"
|
|
639
|
+
done
|
|
640
|
+
|
|
641
|
+
- name: Verify distributions downloaded
|
|
642
|
+
shell: bash
|
|
643
|
+
run: |
|
|
644
|
+
if [ ! -d dist ] || [ -z "$(ls -A dist)" ]; then
|
|
645
|
+
echo "ERROR: No distribution files found"
|
|
646
|
+
echo "The dist/ directory is empty or does not exist"
|
|
647
|
+
exit 1
|
|
648
|
+
fi
|
|
649
|
+
|
|
650
|
+
WHEEL_COUNT=$(ls -1 dist/*.whl 2>/dev/null | wc -l)
|
|
651
|
+
if [ "$WHEEL_COUNT" -eq 0 ]; then
|
|
652
|
+
echo "ERROR: No wheel file found"
|
|
653
|
+
exit 1
|
|
654
|
+
fi
|
|
655
|
+
|
|
656
|
+
echo "Distribution files verified"
|
|
657
|
+
|
|
658
|
+
- name: Install from wheel
|
|
659
|
+
shell: bash
|
|
660
|
+
run: |
|
|
661
|
+
echo "Installing from wheel..."
|
|
662
|
+
pip install --upgrade pip setuptools wheel
|
|
663
|
+
|
|
664
|
+
echo "Installing package..."
|
|
665
|
+
pip install dist/*.whl --verbose || {
|
|
666
|
+
echo "Installation failed"
|
|
667
|
+
echo ""
|
|
668
|
+
echo "Diagnostic information:"
|
|
669
|
+
echo "Python: $(python --version)"
|
|
670
|
+
echo "pip: $(pip --version)"
|
|
671
|
+
echo ""
|
|
672
|
+
echo "Available wheels:"
|
|
673
|
+
ls -la dist/*.whl
|
|
674
|
+
exit 1
|
|
675
|
+
}
|
|
676
|
+
|
|
677
|
+
echo ""
|
|
678
|
+
echo "Installation successful"
|
|
679
|
+
echo ""
|
|
680
|
+
echo "📋 Installed packages:"
|
|
681
|
+
pip list | grep -i "tubetracks\|yt-dlp\|rich" || pip list
|
|
682
|
+
|
|
683
|
+
- name: Verify package files installed
|
|
684
|
+
shell: bash
|
|
685
|
+
run: |
|
|
686
|
+
echo "Verifying installed files..."
|
|
687
|
+
|
|
688
|
+
# Check if module can be found
|
|
689
|
+
python -c "import sys; import downloader; print(f'downloader location: {downloader.__file__}')" || {
|
|
690
|
+
echo "downloader module not found in installation"
|
|
691
|
+
echo ""
|
|
692
|
+
echo "Python path:"
|
|
693
|
+
python -c "import sys; print('\n'.join(sys.path))"
|
|
694
|
+
exit 1
|
|
695
|
+
}
|
|
696
|
+
|
|
697
|
+
python -c "import sys; import plugins; print(f'plugins location: {plugins.__file__}')" || {
|
|
698
|
+
echo "plugins module not found in installation"
|
|
699
|
+
exit 1
|
|
700
|
+
}
|
|
701
|
+
|
|
702
|
+
echo "Package files verified"
|
|
703
|
+
|
|
704
|
+
- name: Test installed CLI commands
|
|
705
|
+
shell: bash
|
|
706
|
+
run: |
|
|
707
|
+
echo "Testing tubetracks command..."
|
|
708
|
+
tubetracks --help || {
|
|
709
|
+
echo "tubetracks command failed"
|
|
710
|
+
echo ""
|
|
711
|
+
echo "Checking if command exists:"
|
|
712
|
+
which tubetracks || echo "Command not found in PATH"
|
|
713
|
+
exit 1
|
|
714
|
+
}
|
|
715
|
+
|
|
716
|
+
tubetracks --version || {
|
|
717
|
+
echo "tubetracks --version failed"
|
|
718
|
+
exit 1
|
|
719
|
+
}
|
|
720
|
+
|
|
721
|
+
echo "tubetracks command working"
|
|
722
|
+
echo ""
|
|
723
|
+
|
|
724
|
+
echo "Testing audiodownload command..."
|
|
725
|
+
audiodownload --help || {
|
|
726
|
+
echo "audiodownload command failed"
|
|
727
|
+
echo ""
|
|
728
|
+
echo "Checking if command exists:"
|
|
729
|
+
which audiodownload || echo "Command not found in PATH"
|
|
730
|
+
exit 1
|
|
731
|
+
}
|
|
732
|
+
|
|
733
|
+
audiodownload --version || {
|
|
734
|
+
echo "audiodownload --version failed"
|
|
735
|
+
exit 1
|
|
736
|
+
}
|
|
737
|
+
|
|
738
|
+
echo "audiodownload command working"
|
|
739
|
+
echo ""
|
|
740
|
+
|
|
741
|
+
echo "Testing ytdl alias..."
|
|
742
|
+
ytdl --help || {
|
|
743
|
+
echo "ytdl command failed"
|
|
744
|
+
which ytdl || echo "Command not found in PATH"
|
|
745
|
+
exit 1
|
|
746
|
+
}
|
|
747
|
+
|
|
748
|
+
ytdl --version || {
|
|
749
|
+
echo "ytdl --version failed"
|
|
750
|
+
exit 1
|
|
751
|
+
}
|
|
752
|
+
|
|
753
|
+
echo "ytdl alias working"
|
|
754
|
+
echo ""
|
|
755
|
+
|
|
756
|
+
echo "Testing GUI command..."
|
|
757
|
+
tubetracks-gui --help 2>&1 || {
|
|
758
|
+
RESULT=$?
|
|
759
|
+
if [ $RESULT -ne 0 ]; then
|
|
760
|
+
echo "GUI command failed (may be expected without tkinter)"
|
|
761
|
+
echo "GUI requires tkinter which may not be available in CI"
|
|
762
|
+
fi
|
|
763
|
+
}
|
|
764
|
+
|
|
765
|
+
echo ""
|
|
766
|
+
echo "All critical CLI commands working"
|
|
767
|
+
|
|
768
|
+
- name: Test package imports
|
|
769
|
+
shell: bash
|
|
770
|
+
run: |
|
|
771
|
+
echo "Testing Python imports..."
|
|
772
|
+
|
|
773
|
+
python -c "import downloader; print('OK: downloader module')" || {
|
|
774
|
+
echo "Cannot import downloader"
|
|
775
|
+
exit 1
|
|
776
|
+
}
|
|
777
|
+
|
|
778
|
+
python -c "from plugins import get_global_registry; print('OK: plugins module')" || {
|
|
779
|
+
echo "Cannot import plugins.get_global_registry"
|
|
780
|
+
exit 1
|
|
781
|
+
}
|
|
782
|
+
|
|
783
|
+
python -c "import downloader; print(f'Version: {downloader.__version__}')" || {
|
|
784
|
+
echo "Cannot access version information"
|
|
785
|
+
exit 1
|
|
786
|
+
}
|
|
787
|
+
|
|
788
|
+
echo ""
|
|
789
|
+
echo "Testing plugin system..."
|
|
790
|
+
python -c "from plugins import get_global_registry; r=get_global_registry(); print(f'Loaded {len(r.list_plugins())} plugins')" || {
|
|
791
|
+
echo "Plugin system not working"
|
|
792
|
+
exit 1
|
|
793
|
+
}
|
|
794
|
+
|
|
795
|
+
echo ""
|
|
796
|
+
echo "Package installation fully verified"
|
|
797
|
+
|
|
798
|
+
- name: Test functional CLI operations
|
|
799
|
+
shell: bash
|
|
800
|
+
run: |
|
|
801
|
+
echo "Testing CLI functionality..."
|
|
802
|
+
|
|
803
|
+
# Test config display
|
|
804
|
+
tubetracks --show-config || {
|
|
805
|
+
echo "--show-config failed"
|
|
806
|
+
exit 1
|
|
807
|
+
}
|
|
808
|
+
|
|
809
|
+
# Test plugin listing
|
|
810
|
+
tubetracks --list-plugins || {
|
|
811
|
+
echo "--list-plugins failed"
|
|
812
|
+
exit 1
|
|
813
|
+
}
|
|
814
|
+
|
|
815
|
+
echo "Functional tests passed"
|
|
816
|
+
continue-on-error: false
|
|
817
|
+
|
|
818
|
+
- name: Upload installation logs on failure
|
|
819
|
+
if: failure()
|
|
820
|
+
uses: actions/upload-artifact@v4
|
|
821
|
+
with:
|
|
822
|
+
name: install-failure-logs-${{ matrix.os }}
|
|
823
|
+
path: |
|
|
824
|
+
~/.cache/pip/
|
|
825
|
+
pip-log.txt
|
|
826
|
+
retention-days: 7
|
|
827
|
+
if-no-files-found: ignore
|
|
828
|
+
|
|
829
|
+
status-check:
|
|
830
|
+
name: ✅ All Tests Passed
|
|
831
|
+
if: always()
|
|
832
|
+
needs: [lint, security, build, test-gui, build-package, test-install]
|
|
833
|
+
runs-on: ubuntu-latest
|
|
834
|
+
timeout-minutes: 5
|
|
835
|
+
|
|
836
|
+
steps:
|
|
837
|
+
- name: Check all job statuses
|
|
838
|
+
run: |
|
|
839
|
+
echo "================================================"
|
|
840
|
+
echo " CI/CD Pipeline Status Report "
|
|
841
|
+
echo "================================================"
|
|
842
|
+
echo ""
|
|
843
|
+
echo "Job Results:"
|
|
844
|
+
echo " Lint: ${{ needs.lint.result }}"
|
|
845
|
+
echo " Security: ${{ needs.security.result }}"
|
|
846
|
+
echo " Build: ${{ needs.build.result }}"
|
|
847
|
+
echo " GUI Tests: ${{ needs.test-gui.result }}"
|
|
848
|
+
echo " Build Package: ${{ needs.build-package.result }}"
|
|
849
|
+
echo " Test Install: ${{ needs.test-install.result }}"
|
|
850
|
+
echo ""
|
|
851
|
+
echo "================================================"
|
|
852
|
+
|
|
853
|
+
# Check if any job was cancelled
|
|
854
|
+
if [ "${{ needs.lint.result }}" == "cancelled" ] || \
|
|
855
|
+
[ "${{ needs.security.result }}" == "cancelled" ] || \
|
|
856
|
+
[ "${{ needs.build.result }}" == "cancelled" ] || \
|
|
857
|
+
[ "${{ needs.test-gui.result }}" == "cancelled" ] || \
|
|
858
|
+
[ "${{ needs.build-package.result }}" == "cancelled" ] || \
|
|
859
|
+
[ "${{ needs.test-install.result }}" == "cancelled" ]; then
|
|
860
|
+
echo "CANCELLED: One or more jobs were cancelled"
|
|
861
|
+
echo ""
|
|
862
|
+
echo "The workflow was stopped before completion."
|
|
863
|
+
exit 1
|
|
864
|
+
fi
|
|
865
|
+
|
|
866
|
+
# Check required jobs
|
|
867
|
+
if [ "${{ needs.build.result }}" != "success" ]; then
|
|
868
|
+
echo "CRITICAL: Build job failed"
|
|
869
|
+
echo " The main build and test suite did not pass."
|
|
870
|
+
echo " Check the Build job logs for details."
|
|
871
|
+
echo ""
|
|
872
|
+
fi
|
|
873
|
+
|
|
874
|
+
if [ "${{ needs.build-package.result }}" != "success" ]; then
|
|
875
|
+
echo "CRITICAL: Build Package job failed"
|
|
876
|
+
echo " Unable to create distribution packages."
|
|
877
|
+
echo " Common causes:"
|
|
878
|
+
echo " • Missing or invalid pyproject.toml"
|
|
879
|
+
echo " • Missing required files (downloader.py, plugins/)"
|
|
880
|
+
echo " • Package structure issues"
|
|
881
|
+
echo " Check the Build Package job logs for details."
|
|
882
|
+
echo ""
|
|
883
|
+
fi
|
|
884
|
+
|
|
885
|
+
if [ "${{ needs.test-install.result }}" != "success" ] && \
|
|
886
|
+
[ "${{ needs.test-install.result }}" != "skipped" ]; then
|
|
887
|
+
echo "CRITICAL: Test Install job failed"
|
|
888
|
+
echo " The package was built but cannot be installed or used."
|
|
889
|
+
echo " Common causes:"
|
|
890
|
+
echo " • Missing dependencies in package"
|
|
891
|
+
echo " • Incorrect entry points in pyproject.toml"
|
|
892
|
+
echo " • Module import errors"
|
|
893
|
+
echo " Check the Test Install job logs for details."
|
|
894
|
+
echo ""
|
|
895
|
+
fi
|
|
896
|
+
|
|
897
|
+
# Check if required jobs failed
|
|
898
|
+
if [ "${{ needs.build.result }}" != "success" ] || \
|
|
899
|
+
[ "${{ needs.build-package.result }}" != "success" ] || \
|
|
900
|
+
([ "${{ needs.test-install.result }}" != "success" ] && \
|
|
901
|
+
[ "${{ needs.test-install.result }}" != "skipped" ]); then
|
|
902
|
+
echo "FAILED: One or more required jobs failed"
|
|
903
|
+
echo ""
|
|
904
|
+
echo "📖 Troubleshooting tips:"
|
|
905
|
+
echo " 1. Check the failed job logs above"
|
|
906
|
+
echo " 2. Run tests locally: make test"
|
|
907
|
+
echo " 3. Verify package build: python -m build"
|
|
908
|
+
echo " 4. Check imports: python -c 'import downloader'"
|
|
909
|
+
echo ""
|
|
910
|
+
echo "For detailed error messages, click on the failed jobs above."
|
|
911
|
+
exit 1
|
|
912
|
+
fi
|
|
913
|
+
|
|
914
|
+
# Warn on optional job failures
|
|
915
|
+
if [ "${{ needs.lint.result }}" == "failure" ]; then
|
|
916
|
+
echo "WARNING: Linting issues detected"
|
|
917
|
+
echo " Run 'make format' to auto-fix style issues"
|
|
918
|
+
echo " Or run: black . && isort ."
|
|
919
|
+
echo ""
|
|
920
|
+
fi
|
|
921
|
+
|
|
922
|
+
if [ "${{ needs.security.result }}" == "failure" ]; then
|
|
923
|
+
echo "WARNING: Security scan detected potential issues"
|
|
924
|
+
echo " Review security reports for details"
|
|
925
|
+
echo " Run: bandit -r . && safety check"
|
|
926
|
+
echo ""
|
|
927
|
+
fi
|
|
928
|
+
|
|
929
|
+
if [ "${{ needs.test-gui.result }}" == "failure" ]; then
|
|
930
|
+
echo "WARNING: GUI tests had issues"
|
|
931
|
+
echo " This is often due to missing tkinter in CI"
|
|
932
|
+
echo " Test GUI locally if making GUI changes"
|
|
933
|
+
echo ""
|
|
934
|
+
fi
|
|
935
|
+
|
|
936
|
+
echo ""
|
|
937
|
+
echo "================================================"
|
|
938
|
+
echo "SUCCESS: All required jobs passed!"
|
|
939
|
+
echo "================================================"
|
|
940
|
+
echo ""
|
|
941
|
+
echo "🎉 The CI/CD pipeline completed successfully!"
|
|
942
|
+
echo ""
|
|
943
|
+
echo "Next steps:"
|
|
944
|
+
echo " • Package distributions are ready in artifacts"
|
|
945
|
+
echo " • Can be installed with: pip install dist/*.whl"
|
|
946
|
+
echo " • Ready for release or deployment"
|
|
947
|
+
|
|
948
|
+
- name: Summary
|
|
949
|
+
run: |
|
|
950
|
+
echo "### 🎉 CI/CD Pipeline Complete" >> $GITHUB_STEP_SUMMARY
|
|
951
|
+
echo "" >> $GITHUB_STEP_SUMMARY
|
|
952
|
+
echo "| Job | Status |" >> $GITHUB_STEP_SUMMARY
|
|
953
|
+
echo "|-----|--------|" >> $GITHUB_STEP_SUMMARY
|
|
954
|
+
echo "| Lint | ${{ needs.lint.result }} |" >> $GITHUB_STEP_SUMMARY
|
|
955
|
+
echo "| Security | ${{ needs.security.result }} |" >> $GITHUB_STEP_SUMMARY
|
|
956
|
+
echo "| Build | ${{ needs.build.result }} |" >> $GITHUB_STEP_SUMMARY
|
|
957
|
+
echo "| GUI Tests | ${{ needs.test-gui.result }} |" >> $GITHUB_STEP_SUMMARY
|
|
958
|
+
echo "| Package | ${{ needs.build-package.result }} |" >> $GITHUB_STEP_SUMMARY
|
|
959
|
+
echo "| Install | ${{ needs.test-install.result }} |" >> $GITHUB_STEP_SUMMARY
|
|
960
|
+
echo "" >> $GITHUB_STEP_SUMMARY
|
|
961
|
+
|
|
962
|
+
# Add troubleshooting section if any job failed
|
|
963
|
+
if [ "${{ needs.build.result }}" != "success" ] || \
|
|
964
|
+
[ "${{ needs.build-package.result }}" != "success" ] || \
|
|
965
|
+
([ "${{ needs.test-install.result }}" != "success" ] && \
|
|
966
|
+
[ "${{ needs.test-install.result }}" != "skipped" ]); then
|
|
967
|
+
echo "## Failed Jobs" >> $GITHUB_STEP_SUMMARY
|
|
968
|
+
echo "" >> $GITHUB_STEP_SUMMARY
|
|
969
|
+
|
|
970
|
+
if [ "${{ needs.build.result }}" != "success" ]; then
|
|
971
|
+
echo "### Build" >> $GITHUB_STEP_SUMMARY
|
|
972
|
+
echo "The main build and test suite failed. Check the Build job logs." >> $GITHUB_STEP_SUMMARY
|
|
973
|
+
echo "" >> $GITHUB_STEP_SUMMARY
|
|
974
|
+
fi
|
|
975
|
+
|
|
976
|
+
if [ "${{ needs.build-package.result }}" != "success" ]; then
|
|
977
|
+
echo "### Build Package" >> $GITHUB_STEP_SUMMARY
|
|
978
|
+
echo "Package creation failed. Verify pyproject.toml and file structure." >> $GITHUB_STEP_SUMMARY
|
|
979
|
+
echo "" >> $GITHUB_STEP_SUMMARY
|
|
980
|
+
fi
|
|
981
|
+
|
|
982
|
+
if [ "${{ needs.test-install.result }}" != "success" ] && \
|
|
983
|
+
[ "${{ needs.test-install.result }}" != "skipped" ]; then
|
|
984
|
+
echo "### Test Install" >> $GITHUB_STEP_SUMMARY
|
|
985
|
+
echo "Package installation testing failed. Check entry points and imports." >> $GITHUB_STEP_SUMMARY
|
|
986
|
+
echo "" >> $GITHUB_STEP_SUMMARY
|
|
987
|
+
fi
|
|
988
|
+
|
|
989
|
+
echo "## 📖 Troubleshooting" >> $GITHUB_STEP_SUMMARY
|
|
990
|
+
echo "" >> $GITHUB_STEP_SUMMARY
|
|
991
|
+
echo "1. Review the failed job logs for specific error messages" >> $GITHUB_STEP_SUMMARY
|
|
992
|
+
echo "2. Run tests locally: \`make test\` or \`pytest tests/\`" >> $GITHUB_STEP_SUMMARY
|
|
993
|
+
echo "3. Build package locally: \`python -m build\`" >> $GITHUB_STEP_SUMMARY
|
|
994
|
+
echo "4. Verify imports: \`python -c 'import downloader'\`" >> $GITHUB_STEP_SUMMARY
|
|
995
|
+
else
|
|
996
|
+
echo "## ✅ All Jobs Passed" >> $GITHUB_STEP_SUMMARY
|
|
997
|
+
echo "" >> $GITHUB_STEP_SUMMARY
|
|
998
|
+
echo "The package is ready for use!" >> $GITHUB_STEP_SUMMARY
|
|
999
|
+
echo "" >> $GITHUB_STEP_SUMMARY
|
|
1000
|
+
echo "- Distribution artifacts are available for download" >> $GITHUB_STEP_SUMMARY
|
|
1001
|
+
echo "- All tests passed across multiple platforms" >> $GITHUB_STEP_SUMMARY
|
|
1002
|
+
echo "- Package installation verified" >> $GITHUB_STEP_SUMMARY
|
|
1003
|
+
fi
|
|
1004
|
+
|