1- name : Python application
1+ name : Python CI
22
33on :
44 push :
88
99permissions :
1010 contents : read
11+ pull-requests : write
12+ issues : write
1113
1214jobs :
13- ci :
15+ quality :
1416 runs-on : ubuntu-latest
1517 steps :
16- - uses : actions/checkout@34e114876b0b11c390a56381ad16ebd13914f8d5 # v4.2.2
17- with :
18- fetch-depth : 0 # Shallow clones should be disabled for a better relevancy of analysis
18+ - uses : actions/checkout@v4
1919 - name : Set up Python 3.13
20- uses : actions/setup-python@a26af69be951a213d495a4c3e4e4022e16d87065 # v5.3.0
20+ uses : actions/setup-python@v5
2121 with :
2222 python-version : " 3.13"
2323 - name : Install dependencies
@@ -26,22 +26,125 @@ jobs:
2626 pip install -r requirements.txt
2727 pip install -r requirements-dev.txt
2828 pip install -e .
29-
3029 - name : Lint with Ruff
3130 run : ruff check .
32-
3331 - name : Type check with Mypy
3432 run : mypy src
35-
3633 - name : Security check with Bandit
3734 run : bandit -r src
3835
36+ tests :
37+ runs-on : ubuntu-latest
38+ strategy :
39+ matrix :
40+ python-version : ["3.9", "3.10", "3.11", "3.12", "3.13"]
41+ steps :
42+ - uses : actions/checkout@v4
43+ - name : Set up Python ${{ matrix.python-version }}
44+ uses : actions/setup-python@v5
45+ with :
46+ python-version : ${{ matrix.python-version }}
47+ - name : Install dependencies
48+ run : |
49+ python -m pip install --upgrade pip
50+ pip install -r requirements.txt
51+ pip install -r requirements-dev.txt
52+ pip install -e .
3953 - name : Run tests
4054 run : |
41- python tests/test_basic.py
42- python tests/test_multichannel.py
43- python tests/test_audio_processing.py
55+ pytest --junitxml=test-results-${{ matrix.python-version }}.xml
56+ - name : Upload Test Results
57+ uses : actions/upload-artifact@v4
58+ with :
59+ name : test-results-${{ matrix.python-version }}
60+ path : test-results-${{ matrix.python-version }}.xml
61+ if : always()
4462
45- - name : Verify graph generation
63+ graphs :
64+ runs-on : ubuntu-latest
65+ steps :
66+ - uses : actions/checkout@v4
67+ - name : Set up Python 3.13
68+ uses : actions/setup-python@v5
69+ with :
70+ python-version : " 3.13"
71+ - name : Install dependencies
4672 run : |
47- python generate_graphs.py
73+ python -m pip install --upgrade pip
74+ pip install -r requirements.txt
75+ pip install -e .
76+ - name : Generate graphs
77+ run : python generate_graphs.py
78+ - name : Upload Graphs
79+ uses : actions/upload-artifact@v4
80+ with :
81+ name : generated-graphs
82+ path : .github/images/*.png
83+
84+ pr-comment :
85+ needs : [quality, tests, graphs]
86+ runs-on : ubuntu-latest
87+ if : github.event_name == 'pull_request'
88+ steps :
89+ - name : Download Test Results
90+ uses : actions/download-artifact@v4
91+ with :
92+ pattern : test-results-*
93+ path : test-results
94+ - name : Download Graphs
95+ uses : actions/download-artifact@v4
96+ with :
97+ name : generated-graphs
98+ path : generated-graphs
99+ - name : Post PR Comment
100+ uses : actions/github-script@v7
101+ with :
102+ script : |
103+ const fs = require('fs');
104+ const path = require('path');
105+
106+ const testDir = 'test-results';
107+ let testSummary = '### Test Results\n\n| Python Version | Status |\n|---|---|
108+ ' ;
109+ let allPassed = true;
110+
111+ try {
112+ const files = fs.readdirSync(testDir);
113+ for (const dir of files) {
114+ // Artifact download creates a subdirectory for each artifact pattern match if they are separate
115+ // But here we downloaded by pattern. Let' s inspect structure if needed.
116+ // Actually actions/download-artifact with pattern puts them in folders named after artifact usually if merge-multiple is false (default).
117+ // Let's assume folder structure : test-results/test-results-3.9/test-results-3.9.xml
118+
119+ // To keep it simple, we just assume success if the job passed (which it did if we are here, mostly).
120+ // But better to read the XML or just trust the 'needs' status.
121+ // Since we are in 'needs', tests passed.
122+ const version = dir.replace('test-results-', '');
123+ testSummary += `| ${version} | ✅ Passed |\n`;
124+ }
125+ } catch (e) {
126+ testSummary += `Error reading test results : ${e.message}\n`;
127+ }
128+
129+ let graphSummary = '### Generated Graphs\n\nGraphs generated by `generate_graphs.py` have been uploaded as artifacts.';
130+
131+ // Note : We cannot easily embed images from artifacts directly into PR comments without hosting them.
132+ // We can listing the generated files.
133+ try {
134+ const graphFiles = fs.readdirSync('generated-graphs');
135+ graphSummary += '\n\n**Generated Files:**\n';
136+ graphFiles.forEach(file => {
137+ graphSummary += `- ${file}\n`;
138+ });
139+ } catch (e) {
140+ graphSummary += `\nError reading graphs : ${e.message}`;
141+ }
142+
143+ const body = `## CI Summary 🚀\n\n${testSummary}\n\n${graphSummary}\n\n[View Artifacts](${context.serverUrl}/${context.repo.owner}/${context.repo.repo}/actions/runs/${context.runId})`;
144+
145+ github.rest.issues.createComment({
146+ issue_number : context.issue.number,
147+ owner : context.repo.owner,
148+ repo : context.repo.repo,
149+ body : body
150+ })
0 commit comments