1- name : 🧪 CI/CD Pipeline
1+ name : 🧪 CI
22
33on :
44 push :
5- branches : [ main, multi-dwl ]
5+ branches : [ main ]
66 pull_request :
77 branches : [ main ]
88
9- env :
10- PYTHON_VERSION : ' 3.11'
11-
129jobs :
13- # ============================================================================
14- # Job 1: Code Quality & Testing
15- # ============================================================================
1610 test :
17- name : 🧪 Test & Quality Check
18- runs-on : ${{ matrix.os }}
19- strategy :
20- matrix :
21- os : [ubuntu-latest, windows-latest, macos-latest]
22- python-version : ['3.8', '3.9', '3.10', '3.11', '3.12']
23- exclude :
24- # Reduce matrix size - test all Python versions only on Ubuntu
25- - os : windows-latest
26- python-version : ' 3.8'
27- - os : windows-latest
28- python-version : ' 3.9'
29- - os : windows-latest
30- python-version : ' 3.10'
31- - os : macos-latest
32- python-version : ' 3.8'
33- - os : macos-latest
34- python-version : ' 3.9'
35- - os : macos-latest
36- python-version : ' 3.10'
37-
38- steps :
39- - name : 🏗️ Checkout code
40- uses : actions/checkout@v4
41-
42- - name : 🐍 Setup Python ${{ matrix.python-version }}
43- uses : actions/setup-python@v4
44- with :
45- python-version : ${{ matrix.python-version }}
46-
47- - name : 📦 Install dependencies
48- run : |
49- python -m pip install --upgrade pip
50- pip install -r requirements.txt
51- pip install pytest pytest-cov flake8 black isort
52-
53- - name : 🎨 Code formatting check
54- run : |
55- black --check --diff .
56- isort --check-only --diff .
57-
58- - name : 🔍 Lint check
59- run : |
60- flake8 . --count --select=E9,F63,F7,F82 --show-source --statistics
61- flake8 . --count --exit-zero --max-complexity=10 --max-line-length=127 --statistics
62-
63- - name : 🧪 Run basic import tests
64- run : |
65- python -c "import thinkific_downloader; print('✅ Package imports successfully')"
66- python -c "from thinkific_downloader.config import Settings; print('✅ Config module works')"
67- python -c "from thinkific_downloader.downloader import main; print('✅ Main module works')"
68-
69- - name : 🔧 Test .env handling
70- run : |
71- # Test that config handles missing .env gracefully
72- python -c "
73- import os
74- from thinkific_downloader.config import load_env
75- from pathlib import Path
76-
77- # Test with non-existent .env file
78- non_existent = Path('non_existent.env')
79- try:
80- load_env(non_existent)
81- print('✅ Handles missing .env file gracefully')
82- except Exception as e:
83- print(f'❌ Error handling missing .env: {e}')
84- exit(1)
85- "
86-
87- - name : 📊 Test environment variable parsing
88- run : |
89- python -c "
90- import os
91- from thinkific_downloader.config import Settings
92-
93- # Set test environment variables
94- os.environ['CLIENT_DATE'] = 'test-date'
95- os.environ['COOKIE_DATA'] = 'test-cookie'
96- os.environ['OUTPUT_DIR'] = './test-downloads'
97- os.environ['CONCURRENT_DOWNLOADS'] = '5'
98- os.environ['DEBUG'] = 'true'
99-
100- try:
101- settings = Settings.from_env()
102- assert settings.output_dir == './test-downloads'
103- assert settings.concurrent_downloads == 5
104- assert settings.debug == True
105- print('✅ Environment variable parsing works correctly')
106- except SystemExit:
107- # Expected when required vars are set
108- print('✅ Environment validation works')
109- except Exception as e:
110- print(f'❌ Error in environment parsing: {e}')
111- exit(1)
112- "
113-
114- # ============================================================================
115- # Job 2: Docker Build Test
116- # ============================================================================
117- docker-test :
118- name : 🐳 Docker Build Test
11+ name : 🧪 Basic Tests
11912 runs-on : ubuntu-latest
12013
12114 steps :
122- - name : 🏗️ Checkout code
123- uses : actions/checkout@v4
124-
125- - name : 🐳 Set up Docker Buildx
126- uses : docker/setup-buildx-action@v3
127-
128- - name : 🔨 Build Docker image (test)
129- uses : docker/build-push-action@v5
130- with :
131- context : .
132- push : false
133- tags : thinkific-downloader:test
134- cache-from : type=gha
135- cache-to : type=gha,mode=max
136-
137- - name : 🧪 Test Docker image
138- run : |
139- # Test that the image starts without errors (with minimal config)
140- echo "Testing Docker image startup..."
141- docker run --rm thinkific-downloader:test python -c "
142- try:
143- import thinkific_downloader
144- print('✅ Docker image: Package imports successfully')
145- except Exception as e:
146- print(f'❌ Docker image: Import failed: {e}')
147- exit(1)
148- "
149-
150- # ============================================================================
151- # Job 3: Project Structure Validation
152- # ============================================================================
153- structure-test :
154- name : 📦 Project Structure Test
155- runs-on : ubuntu-latest
156-
157- steps :
158- - name : 🏗️ Checkout code
159- uses : actions/checkout@v4
160-
161- - name : � Validate project structure
162- run : |
163- echo "📁 Checking project structure..."
164-
165- # Check essential files exist
166- files_to_check=(
167- "thinkific_downloader/__init__.py"
168- "thinkific_downloader/config.py"
169- "thinkific_downloader/downloader.py"
170- "thinkific_downloader/download_manager.py"
171- "README.md"
172- "SETUP.md"
173- "requirements.txt"
174- ".env.example"
175- "Dockerfile"
176- "docker-compose.yml"
177- )
178-
179- for file in "${files_to_check[@]}"; do
180- if [ -f "$file" ]; then
181- echo "✅ $file exists"
182- else
183- echo "❌ $file is missing"
184- exit 1
185- fi
186- done
187-
188- echo "✅ All essential files present"
189-
190- - name : 🔧 Test environment configuration
191- run : |
192- echo "🧪 Testing .env.example structure..."
193-
194- # Check for required sections
195- required_vars=(
196- "COURSE_LINK"
197- "COOKIE_DATA"
198- "CLIENT_DATE"
199- "OUTPUT_DIR"
200- "CONCURRENT_DOWNLOADS"
201- )
202-
203- for var in "${required_vars[@]}"; do
204- if grep -q "$var" .env.example; then
205- echo "✅ .env.example contains $var"
206- else
207- echo "❌ .env.example missing $var"
208- exit 1
209- fi
210- done
211-
212- echo "✅ .env.example structure is valid"
213-
214- # ============================================================================
215- # Job 4: Security & Vulnerability Check
216- # ============================================================================
217- security :
218- name : 🔒 Security Check
219- runs-on : ubuntu-latest
220-
221- steps :
222- - name : 🏗️ Checkout code
15+ - name : 🏗️ Checkout
22316 uses : actions/checkout@v4
22417
22518 - name : 🐍 Setup Python
22619 uses : actions/setup-python@v4
22720 with :
228- python-version : ${{ env.PYTHON_VERSION }}
229-
230- - name : 🔒 Install security tools
231- run : |
232- python -m pip install --upgrade pip
233- pip install safety bandit
21+ python-version : ' 3.11'
23422
235- - name : 🧪 Check dependencies for vulnerabilities
23+ - name : 📦 Install dependencies
23624 run : |
237- safety check -r requirements.txt
25+ pip install -r requirements.txt
23826
239- - name : 🔍 Run static security analysis
27+ - name : 🧪 Test imports
24028 run : |
241- bandit -r thinkific_downloader/ -f json -o bandit-report.json
242- bandit -r thinkific_downloader/
29+ python -c "import thinkific_downloader; print('✅ Package imports work')"
30+ python -c "from thinkific_downloader.config import Settings; print('✅ Config works')"
24331
244- # ============================================================================
245- # Job 5: Documentation Check
246- # ============================================================================
247- docs-check :
248- name : 📚 Documentation Check
32+ docker :
33+ name : 🐳 Docker Build
24934 runs-on : ubuntu-latest
25035
25136 steps :
252- - name : 🏗️ Checkout code
37+ - name : 🏗️ Checkout
25338 uses : actions/checkout@v4
25439
255- - name : 📖 Check README structure
256- run : |
257- echo "📋 Checking documentation completeness..."
258-
259- # Check that essential sections exist in README
260- required_sections=(
261- "Quick Start"
262- "Docker"
263- "Configuration"
264- "Features"
265- )
266-
267- for section in "${required_sections[@]}"; do
268- if grep -qi "$section" README.md; then
269- echo "✅ README contains '$section' section"
270- else
271- echo "⚠️ README missing '$section' section"
272- fi
273- done
274-
275- # Check .env.example is properly structured
276- if [ -f ".env.example" ]; then
277- echo "✅ .env.example file exists"
278-
279- # Check for required sections
280- if grep -q "COURSE_LINK" .env.example && grep -q "COOKIE_DATA" .env.example; then
281- echo "✅ .env.example contains required authentication variables"
282- else
283- echo "❌ .env.example missing required authentication variables"
284- exit 1
285- fi
286-
287- if grep -q "OUTPUT_DIR" .env.example; then
288- echo "✅ .env.example contains OUTPUT_DIR configuration"
289- else
290- echo "❌ .env.example missing OUTPUT_DIR configuration"
291- exit 1
292- fi
293- else
294- echo "❌ .env.example file is missing"
295- exit 1
296- fi
297-
298- echo "✅ Documentation check passed"
299-
300- # ============================================================================
301- # Job 6: Summary
302- # ============================================================================
303- summary :
304- name : 📊 CI Summary
305- runs-on : ubuntu-latest
306- needs : [test, docker-test, structure-test, security, docs-check]
307- if : always()
308-
309- steps :
310- - name : 🎉 Success Summary
311- if : needs.test.result == 'success' && needs.docker-test.result == 'success' && needs.structure-test.result == 'success' && needs.security.result == 'success' && needs.docs-check.result == 'success'
312- run : |
313- echo "🎉 All CI checks passed successfully!"
314- echo ""
315- echo "✅ Code quality and testing"
316- echo "✅ Docker build verification"
317- echo "✅ Project structure validation"
318- echo "✅ Security vulnerability checks"
319- echo "✅ Documentation completeness"
320- echo ""
321- echo "🚀 Ready for merge/release!"
322-
323- - name : ❌ Failure Summary
324- if : needs.test.result == 'failure' || needs.docker-test.result == 'failure' || needs.structure-test.result == 'failure' || needs.security.result == 'failure' || needs.docs-check.result == 'failure'
40+ - name : 🐳 Build Docker image
32541 run : |
326- echo "❌ Some CI checks failed:"
327- echo ""
328- echo "🧪 Tests: ${{ needs.test.result }}"
329- echo "🐳 Docker: ${{ needs.docker-test.result }}"
330- echo "📦 Structure: ${{ needs.structure-test.result }}"
331- echo "🔒 Security: ${{ needs.security.result }}"
332- echo "📚 Docs: ${{ needs.docs-check.result }}"
333- echo ""
334- echo "🔧 Please review and fix failing checks before merging."
335- exit 1
42+ docker build -t thinkific-downloader:test .
43+ echo "✅ Docker image builds successfully"
0 commit comments