ci_build_major_branch_keymap.yml 6.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211
  1. name: CI Build Major Branch Keymap
  2. permissions:
  3. contents: read
  4. actions: write
  5. on:
  6. workflow_call:
  7. inputs:
  8. branch:
  9. type: string
  10. required: true
  11. keymap:
  12. type: string
  13. required: true
  14. slice_length:
  15. type: string
  16. required: true
  17. jobs:
  18. generate_targets:
  19. name: "Generate targets (${{ inputs.keymap }})"
  20. runs-on: ubuntu-latest
  21. container: ghcr.io/qmk/qmk_cli
  22. outputs:
  23. targets: ${{ steps.generate_targets.outputs.targets }}
  24. steps:
  25. - name: Disable safe.directory check
  26. run: |
  27. git config --global --add safe.directory '*'
  28. - name: Checkout QMK Firmware
  29. uses: actions/checkout@v7
  30. - name: Install dependencies
  31. run: pip3 install -r requirements-dev.txt
  32. - name: Generate build targets
  33. shell: 'bash {0}'
  34. id: generate_targets
  35. run: |
  36. { # Intentionally use `shuf` here so that we share manufacturers across all build groups -- some have a lot of ARM-based boards which inherently take longer
  37. counter=0
  38. echo -n '{'
  39. qmk find -km ${{ inputs.keymap }} 2>/dev/null | sort | uniq | shuf --random-source=<(openssl enc -aes-256-ctr -pass pass:qmk -nosalt </dev/zero 2>/dev/null) | xargs -L${{ inputs.slice_length }} | while IFS=$'\n' read target ; do
  40. if [ $counter -gt 0 ]; then
  41. echo -n ','
  42. fi
  43. counter=$((counter+1))
  44. printf "\"group-%02d\":{" $counter
  45. echo -n '"targets":"'
  46. echo $target | tr ' ' '\n' | sort | uniq | xargs echo -n
  47. echo -n '"}'
  48. done
  49. echo -n '}'
  50. } | sed -e 's@\n@@g' > targets.json
  51. # Output the target keys as a variable
  52. echo "targets=$(jq -c 'keys' targets.json)" >> $GITHUB_OUTPUT
  53. - name: Upload targets json
  54. uses: actions/upload-artifact@v7
  55. with:
  56. name: targets-${{ inputs.keymap }}
  57. path: targets.json
  58. build_targets:
  59. name: "Compile ${{ matrix.target }} (${{ inputs.keymap }})"
  60. needs: generate_targets
  61. runs-on: ubuntu-latest
  62. container: ghcr.io/qmk/qmk_cli
  63. continue-on-error: true
  64. env:
  65. CCACHE_CONFIGPATH: ~/.cache
  66. strategy:
  67. matrix:
  68. target: ${{ fromJson(needs.generate_targets.outputs.targets) }}
  69. steps:
  70. - name: Disable safe.directory check
  71. run: |
  72. git config --global --add safe.directory '*'
  73. - name: Checkout QMK Firmware
  74. uses: actions/checkout@v7
  75. with:
  76. submodules: recursive
  77. - name: Install dependencies
  78. run: pip3 install -r requirements-dev.txt
  79. - name: Get target definitions
  80. uses: actions/download-artifact@v8
  81. with:
  82. name: targets-${{ inputs.keymap }}
  83. path: .
  84. - name: Dump targets
  85. run: |
  86. jq -r '.["${{ matrix.target }}"].targets' targets.json | tr ' ' '\n' | sort
  87. - name: Restore Cache
  88. id: cache
  89. uses: actions/cache/restore@v6
  90. with:
  91. path: ${{ env.CCACHE_CONFIGPATH }}
  92. key: compile-${{ inputs.keymap }}-${{ matrix.target }}
  93. - name: Build targets
  94. continue-on-error: true
  95. run: |
  96. targets=$(jq -r '.["${{ matrix.target }}"].targets' targets.json | tr ' ' '\n' | sort)
  97. if [ -z "${targets}" ]; then
  98. echo "Zero build targets detected"
  99. exit 0
  100. fi
  101. qmk mass-compile -t -j $(nproc) -e DUMP_CI_METADATA=yes -e USE_CCACHE=yes $targets || touch .failed
  102. - name: Dump ccache stats
  103. run: |
  104. ccache -s
  105. # Delete the old cache on hit to emulate a cache update. See https://github.com/actions/cache/issues/342.
  106. - name: Delete old cache
  107. env:
  108. GH_TOKEN: ${{ github.token }}
  109. if: steps.cache.outputs.cache-hit
  110. run: |
  111. count=$(gh cache list --ref ${{ github.ref }} --key ${{ steps.cache.outputs.cache-primary-key }} --json id | jq length)
  112. if [ $count -gt 0 ]; then
  113. gh cache delete --ref ${{ github.ref }} ${{ steps.cache.outputs.cache-primary-key }}
  114. fi
  115. - name: Save Cache
  116. uses: actions/cache/save@v6
  117. with:
  118. path: ${{ env.CCACHE_CONFIGPATH }}
  119. key: compile-${{ inputs.keymap }}-${{ matrix.target }}
  120. - name: Upload binaries
  121. uses: actions/upload-artifact@v7
  122. with:
  123. name: firmware-${{ inputs.keymap }}-${{ matrix.target }}
  124. if-no-files-found: ignore
  125. path: |
  126. *.bin
  127. *.hex
  128. *.uf2
  129. .build/failed.*
  130. .failed
  131. - name: Fail build if any group failed
  132. run: |
  133. # Exit with failure if the compilation stage failed
  134. [ ! -f .failed ] || exit 1
  135. repack_firmware:
  136. if: always()
  137. name: "Repack artifacts"
  138. needs: build_targets
  139. runs-on: ubuntu-latest
  140. steps:
  141. - name: Checkout QMK Firmware
  142. uses: actions/checkout@v7
  143. - name: Download firmwares
  144. uses: actions/download-artifact@v8
  145. with:
  146. pattern: firmware-${{ inputs.keymap }}-*
  147. path: .
  148. merge-multiple: true
  149. - name: Upload all firmwares
  150. uses: actions/upload-artifact@v7
  151. with:
  152. name: firmware-${{ inputs.keymap }}
  153. if-no-files-found: ignore
  154. path: |
  155. *.bin
  156. *.hex
  157. *.uf2
  158. .build/failed.*
  159. .failed
  160. - name: Generate output logs
  161. run: |
  162. # Generate the step summary markdown
  163. ./util/ci/generate_failure_markdown.sh > $GITHUB_STEP_SUMMARY || true
  164. # Truncate to a maximum of 1MB to deal with GitHub workflow limit
  165. truncate --size='<960K' $GITHUB_STEP_SUMMARY || true
  166. - name: Delete temporary build artifacts
  167. uses: geekyeggo/delete-artifact@v6
  168. with:
  169. name: |
  170. firmware-${{ inputs.keymap }}-*
  171. targets-${{ inputs.keymap }}
  172. - name: 'CI Discord Notification'
  173. if: always() && !cancelled()
  174. working-directory: util/ci/
  175. env:
  176. DISCORD_WEBHOOK: ${{ secrets.CI_DISCORD_WEBHOOK }}
  177. run: |
  178. python3 -m pip install -r requirements.txt
  179. python3 ./discord-results.py --branch ${{ inputs.branch || github.ref_name }} --sha $(git rev-parse HEAD) --keymap ${{ inputs.keymap }} --url ${{ github.server_url }}/${{ github.repository }}/actions/runs/${{ github.run_id }}