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.
Files changed (35) hide show
  1. tubetracks-1.5.0/.github/workflows/build.yml +1004 -0
  2. tubetracks-1.5.0/.github/workflows/publish-pypi.yml +88 -0
  3. tubetracks-1.5.0/CHANGELOG.md +47 -0
  4. tubetracks-1.5.0/LICENSE +448 -0
  5. tubetracks-1.5.0/MANIFEST.in +12 -0
  6. tubetracks-1.5.0/Makefile +272 -0
  7. tubetracks-1.5.0/PKG-INFO +307 -0
  8. tubetracks-1.5.0/PLUGIN_API.md +552 -0
  9. tubetracks-1.5.0/README.md +258 -0
  10. tubetracks-1.5.0/downloader.py +2453 -0
  11. tubetracks-1.5.0/example.audiodownload.conf +47 -0
  12. tubetracks-1.5.0/example_urls.txt +12 -0
  13. tubetracks-1.5.0/plugins/__init__.py +76 -0
  14. tubetracks-1.5.0/plugins/base.py +287 -0
  15. tubetracks-1.5.0/plugins/dailymotion.py +149 -0
  16. tubetracks-1.5.0/plugins/instagram.py +147 -0
  17. tubetracks-1.5.0/plugins/reddit.py +146 -0
  18. tubetracks-1.5.0/plugins/soundcloud.py +151 -0
  19. tubetracks-1.5.0/plugins/spotify.py +156 -0
  20. tubetracks-1.5.0/plugins/tiktok.py +150 -0
  21. tubetracks-1.5.0/plugins/twitch.py +147 -0
  22. tubetracks-1.5.0/plugins/vimeo.py +151 -0
  23. tubetracks-1.5.0/plugins/youtube.py +171 -0
  24. tubetracks-1.5.0/pyproject.toml +97 -0
  25. tubetracks-1.5.0/requirements.txt +7 -0
  26. tubetracks-1.5.0/setup.cfg +4 -0
  27. tubetracks-1.5.0/tests/test_plugins.py +641 -0
  28. tubetracks-1.5.0/tests/test_smoke.py +398 -0
  29. tubetracks-1.5.0/tubetracks.egg-info/PKG-INFO +307 -0
  30. tubetracks-1.5.0/tubetracks.egg-info/SOURCES.txt +46 -0
  31. tubetracks-1.5.0/tubetracks.egg-info/dependency_links.txt +1 -0
  32. tubetracks-1.5.0/tubetracks.egg-info/entry_points.txt +5 -0
  33. tubetracks-1.5.0/tubetracks.egg-info/requires.txt +12 -0
  34. tubetracks-1.5.0/tubetracks.egg-info/top_level.txt +3 -0
  35. 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
+