@@ -25,12 +25,19 @@ jobs:
2525 cache-key : python-tests
2626
2727 - name : Run tests
28- run : pytest ${{ steps.split.outputs.tests }} --junit-xml=junit-${{ matrix.index }}.xml
28+ run : pytest ${{ steps.split.outputs.tests }} --junit-xml=junit.xml
29+
30+ - name : Convert JUnit to timing JSON
31+ uses : dashdoc/fairsplice@v1
32+ with :
33+ command : convert
34+ from : junit.xml
35+ to : timing.json
2936
3037 - uses : actions/upload-artifact@v4
3138 with :
32- name : junit -${{ matrix.index }}
33- path : junit-${{ matrix.index }}.xml
39+ name : timing -${{ matrix.index }}
40+ path : timing.json
3441
3542 save-timings :
3643 needs : test
4451 uses : dashdoc/fairsplice@v1
4552 with :
4653 command : merge
47- prefix : ' junit -*/junit- '
54+ prefix : ' timing -*/timing '
4855 cache-key : python-tests
4956` ` `
5057
@@ -107,7 +114,8 @@ That's it! Caching is handled automatically.
107114
108115** Key concepts:**
109116- ** Split phase** : Distributes test files across workers based on historical timing data
110- - ** Merge phase** : Extracts timing from JUnit XML and caches for next run
117+ - ** Convert phase** : Extracts timing from JUnit XML into timing JSON (one per worker)
118+ - ** Merge phase** : Combines timing JSON files from all workers and caches for next run
111119- ** Bin packing** : Assigns tests to balance total execution time (heaviest tests first)
112120- ** Rolling average** : Keeps last 10 timings per test file for predictions
113121
@@ -117,13 +125,15 @@ That's it! Caching is handled automatically.
117125
118126| Input | Required | Description |
119127| -------| ----------| -------------|
120- | ` command ` | Yes | ` split ` or ` merge ` |
121- | ` cache-key ` | Yes | Cache key for storing timings (use different keys for frontend/backend workflows) |
128+ | ` command ` | Yes | ` split ` , ` convert ` , or ` merge ` |
129+ | ` cache-key ` | For split/merge | Cache key for storing timings (use different keys for frontend/backend workflows) |
122130| ` timings-file ` | No | JSON file for timings (default: ` .fairsplice-timings.json ` ) |
123131| ` pattern ` | For split | Glob pattern to match test files |
124132| ` total ` | For split | Total number of workers |
125133| ` index ` | For split | Current worker index (0-based) |
126- | ` prefix ` | For merge | Prefix to match JUnit XML files |
134+ | ` from ` | For convert | JUnit XML file to read |
135+ | ` to ` | For convert | Timing JSON file to write |
136+ | ` prefix ` | For merge | Prefix to match timing JSON files |
127137
128138### Cache Behavior
129139
@@ -158,9 +168,14 @@ bunx fairsplice
158168fairsplice split --timings-file timings.json --pattern " tests/**/*.py" --total 3 --out split.json
159169```
160170
161- ** Merge results :**
171+ ** Convert JUnit XML to timing JSON :**
162172``` bash
163- fairsplice merge --timings-file timings.json --prefix junit-
173+ fairsplice convert --from junit.xml --to timing.json
174+ ```
175+
176+ ** Merge timing results:**
177+ ``` bash
178+ fairsplice merge --timings-file timings.json --prefix timing-
164179```
165180
166181### CLI Options
@@ -172,9 +187,13 @@ fairsplice split
172187 --total <n> Number of workers
173188 --out <file> Output JSON file
174189
190+ fairsplice convert
191+ --from <file> JUnit XML file to read
192+ --to <file> Timing JSON file to write
193+
175194fairsplice merge
176195 --timings-file <file> JSON file to store timings
177- --prefix <prefix> Prefix to match JUnit XML files
196+ --prefix <prefix> Prefix to match timing JSON files
178197```
179198
180199## Contributing
0 commit comments