From 361ae1d6e0a6319037e463a982d26d50a805e9c4 Mon Sep 17 00:00:00 2001 From: Patrick Collins Date: Sun, 25 Jan 2026 15:11:45 -0500 Subject: [PATCH 1/6] Batch keyboard builds into groups of 10 per job Reduces job overhead by building multiple keyboards per CI job instead of spawning a separate job for each keyboard. --- .github/workflows/keymaps.yml | 28 +++++++++++++++++++++------- 1 file changed, 21 insertions(+), 7 deletions(-) diff --git a/.github/workflows/keymaps.yml b/.github/workflows/keymaps.yml index d68c6c8..d195bce 100644 --- a/.github/workflows/keymaps.yml +++ b/.github/workflows/keymaps.yml @@ -29,13 +29,20 @@ jobs: id: set-matrix run: | # Parse keymaps file into JSON array of {keyboard, keymap, artifact_name} objects + # then batch them into groups of 10 keyboards=$(grep -v '^#' keymaps | grep -v '^//' | grep -v '^$' | while read -r line; do kb=$(echo "$line" | awk '{print $1}') km=$(echo "$line" | awk '{print $2}') km="${km:-patcoll}" artifact_name=$(echo "${kb}-${km}" | tr '/' '_') echo "{\"keyboard\":\"$kb\",\"keymap\":\"$km\",\"artifact_name\":\"$artifact_name\"}" - done | jq -s -c '.') + done | jq -s -c ' + # Split into batches of 10 + [range(0; length; 10) as $i | { + batch_id: ($i / 10 | floor), + keyboards: .[$i:$i+10] + }] + ') echo "keyboards=$keyboards" >> "$GITHUB_OUTPUT" setup: @@ -122,15 +129,22 @@ jobs: cd ${{ github.workspace }}/working_area/qmk_firmware sudo util/qmk_install.sh -y - - name: Sync keyboard - run: mise run sync "${{ matrix.keyboard }}" - - - name: Build ${{ matrix.keyboard }} - run: mise run qmk compile -kb "${{ matrix.keyboard }}" -km "${{ matrix.keymap }}" + - name: Sync and build keyboards + env: + KEYBOARDS_JSON: ${{ toJson(matrix.keyboards) }} + run: | + echo "$KEYBOARDS_JSON" | jq -c '.[]' | while read -r item; do + keyboard=$(echo "$item" | jq -r '.keyboard') + keymap=$(echo "$item" | jq -r '.keymap') + echo "::group::Building $keyboard:$keymap" + mise run sync "$keyboard" + mise run qmk compile -kb "$keyboard" -km "$keymap" + echo "::endgroup::" + done - uses: actions/upload-artifact@v4 with: - name: firmware-${{ matrix.artifact_name }} + name: firmware-batch-${{ matrix.batch_id }} path: | ${{ github.workspace }}/*.bin ${{ github.workspace }}/*.hex From 6c20cff05ef2bc8f6f5583297015cfe40bb84807 Mon Sep 17 00:00:00 2001 From: Patrick Collins Date: Sun, 25 Jan 2026 15:23:42 -0500 Subject: [PATCH 2/6] Upload artifacts even when builds fail - Continue building remaining keyboards if one fails - Use if: always() on artifact upload step - Track failures and report at end of batch --- .github/workflows/keymaps.yml | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) diff --git a/.github/workflows/keymaps.yml b/.github/workflows/keymaps.yml index d195bce..f448ec6 100644 --- a/.github/workflows/keymaps.yml +++ b/.github/workflows/keymaps.yml @@ -133,16 +133,23 @@ jobs: env: KEYBOARDS_JSON: ${{ toJson(matrix.keyboards) }} run: | + failed=0 echo "$KEYBOARDS_JSON" | jq -c '.[]' | while read -r item; do keyboard=$(echo "$item" | jq -r '.keyboard') keymap=$(echo "$item" | jq -r '.keymap') echo "::group::Building $keyboard:$keymap" - mise run sync "$keyboard" - mise run qmk compile -kb "$keyboard" -km "$keymap" + if ! mise run sync "$keyboard" || ! mise run qmk compile -kb "$keyboard" -km "$keymap"; then + echo "::error::Failed to build $keyboard:$keymap" + echo "1" > /tmp/build_failed + fi echo "::endgroup::" done + if [ -f /tmp/build_failed ]; then + exit 1 + fi - uses: actions/upload-artifact@v4 + if: always() with: name: firmware-batch-${{ matrix.batch_id }} path: | From 957bdf25c09f0f82f2988da49a4b7a484ed158d9 Mon Sep 17 00:00:00 2001 From: Patrick Collins Date: Sun, 25 Jan 2026 15:30:28 -0500 Subject: [PATCH 3/6] Add collect job to merge batch artifacts - Downloads all firmware-batch-* artifacts - Merges into single 'firmware' artifact with all files - Deletes intermediate batch artifacts --- .github/workflows/keymaps.yml | 24 ++++++++++++++++++++++++ 1 file changed, 24 insertions(+) diff --git a/.github/workflows/keymaps.yml b/.github/workflows/keymaps.yml index f448ec6..974262b 100644 --- a/.github/workflows/keymaps.yml +++ b/.github/workflows/keymaps.yml @@ -156,3 +156,27 @@ jobs: ${{ github.workspace }}/*.bin ${{ github.workspace }}/*.hex ${{ github.workspace }}/*.uf2 + + collect: + needs: [build] + if: always() + runs-on: ubuntu-latest + steps: + - uses: actions/download-artifact@v4 + with: + pattern: firmware-batch-* + path: firmware + merge-multiple: true + + - name: List firmware files + run: ls -la firmware/ + + - uses: actions/upload-artifact@v4 + with: + name: firmware + path: firmware/* + + - name: Delete batch artifacts + uses: geekyeggo/delete-artifact@v5 + with: + name: firmware-batch-* From cf7f394209d3c1cf7c4ea92c931a5364ac0b2545 Mon Sep 17 00:00:00 2001 From: Patrick Collins Date: Sun, 25 Jan 2026 15:37:02 -0500 Subject: [PATCH 4/6] Upload each firmware file as individual artifact - collect job outputs list of firmware filenames - upload-individual job uses matrix to upload each file separately - Each artifact named after the firmware file (without extension) --- .github/workflows/keymaps.yml | 29 ++++++++++++++++++++++++++++- 1 file changed, 28 insertions(+), 1 deletion(-) diff --git a/.github/workflows/keymaps.yml b/.github/workflows/keymaps.yml index 974262b..c7c30ba 100644 --- a/.github/workflows/keymaps.yml +++ b/.github/workflows/keymaps.yml @@ -161,6 +161,8 @@ jobs: needs: [build] if: always() runs-on: ubuntu-latest + outputs: + files: ${{ steps.list.outputs.files }} steps: - uses: actions/download-artifact@v4 with: @@ -169,7 +171,11 @@ jobs: merge-multiple: true - name: List firmware files - run: ls -la firmware/ + id: list + run: | + files=$(ls firmware/ 2>/dev/null | jq -R -s -c 'split("\n") | map(select(length > 0))') + echo "files=$files" >> "$GITHUB_OUTPUT" + echo "Found files: $files" - uses: actions/upload-artifact@v4 with: @@ -180,3 +186,24 @@ jobs: uses: geekyeggo/delete-artifact@v5 with: name: firmware-batch-* + + upload-individual: + needs: [collect] + if: always() && needs.collect.outputs.files != '[]' + runs-on: ubuntu-latest + strategy: + matrix: + file: ${{ fromJson(needs.collect.outputs.files) }} + steps: + - uses: actions/download-artifact@v4 + with: + name: firmware + + - name: Get artifact name + id: name + run: echo "name=$(echo '${{ matrix.file }}' | sed 's/\.[^.]*$//')" >> "$GITHUB_OUTPUT" + + - uses: actions/upload-artifact@v4 + with: + name: ${{ steps.name.outputs.name }} + path: ${{ matrix.file }} From 386cc12841c3bbfb185cd2f83f536dc79e3c4cf3 Mon Sep 17 00:00:00 2001 From: Patrick Collins Date: Sun, 25 Jan 2026 15:43:38 -0500 Subject: [PATCH 5/6] Delete firmware artifact after individual uploads --- .github/workflows/keymaps.yml | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/.github/workflows/keymaps.yml b/.github/workflows/keymaps.yml index c7c30ba..f509df2 100644 --- a/.github/workflows/keymaps.yml +++ b/.github/workflows/keymaps.yml @@ -207,3 +207,13 @@ jobs: with: name: ${{ steps.name.outputs.name }} path: ${{ matrix.file }} + + cleanup: + needs: [upload-individual] + if: always() + runs-on: ubuntu-latest + steps: + - name: Delete firmware artifact + uses: geekyeggo/delete-artifact@v5 + with: + name: firmware From b6de242c567db33f36f83daecad14f34a2a31ecb Mon Sep 17 00:00:00 2001 From: Patrick Collins Date: Sun, 25 Jan 2026 15:45:17 -0500 Subject: [PATCH 6/6] Increase batch size from 10 to 16 keyboards per job --- .github/workflows/keymaps.yml | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/.github/workflows/keymaps.yml b/.github/workflows/keymaps.yml index f509df2..5ee9f17 100644 --- a/.github/workflows/keymaps.yml +++ b/.github/workflows/keymaps.yml @@ -37,10 +37,10 @@ jobs: artifact_name=$(echo "${kb}-${km}" | tr '/' '_') echo "{\"keyboard\":\"$kb\",\"keymap\":\"$km\",\"artifact_name\":\"$artifact_name\"}" done | jq -s -c ' - # Split into batches of 10 - [range(0; length; 10) as $i | { - batch_id: ($i / 10 | floor), - keyboards: .[$i:$i+10] + # Split into batches of 16 + [range(0; length; 16) as $i | { + batch_id: ($i / 16 | floor), + keyboards: .[$i:$i+16] }] ') echo "keyboards=$keyboards" >> "$GITHUB_OUTPUT"