Skip to content

Commit 8b81bc0

Browse files
authored
Batch keyboard builds into groups of 10 per job (#24)
## Summary - Groups keyboards into batches of 10 in the CI matrix instead of one job per keyboard - Reduces job overhead and parallelism costs - Artifacts are now uploaded per-batch (`firmware-batch-N`) ## Test plan - [ ] Verify matrix job outputs batched structure - [ ] Verify build jobs compile all keyboards in their batch - [ ] Verify firmware artifacts are uploaded correctly
1 parent ff8193f commit 8b81bc0

1 file changed

Lines changed: 89 additions & 7 deletions

File tree

.github/workflows/keymaps.yml

Lines changed: 89 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -29,13 +29,20 @@ jobs:
2929
id: set-matrix
3030
run: |
3131
# Parse keymaps file into JSON array of {keyboard, keymap, artifact_name} objects
32+
# then batch them into groups of 10
3233
keyboards=$(grep -v '^#' keymaps | grep -v '^//' | grep -v '^$' | while read -r line; do
3334
kb=$(echo "$line" | awk '{print $1}')
3435
km=$(echo "$line" | awk '{print $2}')
3536
km="${km:-patcoll}"
3637
artifact_name=$(echo "${kb}-${km}" | tr '/' '_')
3738
echo "{\"keyboard\":\"$kb\",\"keymap\":\"$km\",\"artifact_name\":\"$artifact_name\"}"
38-
done | jq -s -c '.')
39+
done | jq -s -c '
40+
# Split into batches of 16
41+
[range(0; length; 16) as $i | {
42+
batch_id: ($i / 16 | floor),
43+
keyboards: .[$i:$i+16]
44+
}]
45+
')
3946
echo "keyboards=$keyboards" >> "$GITHUB_OUTPUT"
4047
4148
setup:
@@ -122,16 +129,91 @@ jobs:
122129
cd ${{ github.workspace }}/working_area/qmk_firmware
123130
sudo util/qmk_install.sh -y
124131
125-
- name: Sync keyboard
126-
run: mise run sync "${{ matrix.keyboard }}"
127-
128-
- name: Build ${{ matrix.keyboard }}
129-
run: mise run qmk compile -kb "${{ matrix.keyboard }}" -km "${{ matrix.keymap }}"
132+
- name: Sync and build keyboards
133+
env:
134+
KEYBOARDS_JSON: ${{ toJson(matrix.keyboards) }}
135+
run: |
136+
failed=0
137+
echo "$KEYBOARDS_JSON" | jq -c '.[]' | while read -r item; do
138+
keyboard=$(echo "$item" | jq -r '.keyboard')
139+
keymap=$(echo "$item" | jq -r '.keymap')
140+
echo "::group::Building $keyboard:$keymap"
141+
if ! mise run sync "$keyboard" || ! mise run qmk compile -kb "$keyboard" -km "$keymap"; then
142+
echo "::error::Failed to build $keyboard:$keymap"
143+
echo "1" > /tmp/build_failed
144+
fi
145+
echo "::endgroup::"
146+
done
147+
if [ -f /tmp/build_failed ]; then
148+
exit 1
149+
fi
130150
131151
- uses: actions/upload-artifact@v4
152+
if: always()
132153
with:
133-
name: firmware-${{ matrix.artifact_name }}
154+
name: firmware-batch-${{ matrix.batch_id }}
134155
path: |
135156
${{ github.workspace }}/*.bin
136157
${{ github.workspace }}/*.hex
137158
${{ github.workspace }}/*.uf2
159+
160+
collect:
161+
needs: [build]
162+
if: always()
163+
runs-on: ubuntu-latest
164+
outputs:
165+
files: ${{ steps.list.outputs.files }}
166+
steps:
167+
- uses: actions/download-artifact@v4
168+
with:
169+
pattern: firmware-batch-*
170+
path: firmware
171+
merge-multiple: true
172+
173+
- name: List firmware files
174+
id: list
175+
run: |
176+
files=$(ls firmware/ 2>/dev/null | jq -R -s -c 'split("\n") | map(select(length > 0))')
177+
echo "files=$files" >> "$GITHUB_OUTPUT"
178+
echo "Found files: $files"
179+
180+
- uses: actions/upload-artifact@v4
181+
with:
182+
name: firmware
183+
path: firmware/*
184+
185+
- name: Delete batch artifacts
186+
uses: geekyeggo/delete-artifact@v5
187+
with:
188+
name: firmware-batch-*
189+
190+
upload-individual:
191+
needs: [collect]
192+
if: always() && needs.collect.outputs.files != '[]'
193+
runs-on: ubuntu-latest
194+
strategy:
195+
matrix:
196+
file: ${{ fromJson(needs.collect.outputs.files) }}
197+
steps:
198+
- uses: actions/download-artifact@v4
199+
with:
200+
name: firmware
201+
202+
- name: Get artifact name
203+
id: name
204+
run: echo "name=$(echo '${{ matrix.file }}' | sed 's/\.[^.]*$//')" >> "$GITHUB_OUTPUT"
205+
206+
- uses: actions/upload-artifact@v4
207+
with:
208+
name: ${{ steps.name.outputs.name }}
209+
path: ${{ matrix.file }}
210+
211+
cleanup:
212+
needs: [upload-individual]
213+
if: always()
214+
runs-on: ubuntu-latest
215+
steps:
216+
- name: Delete firmware artifact
217+
uses: geekyeggo/delete-artifact@v5
218+
with:
219+
name: firmware

0 commit comments

Comments
 (0)