bootstrap_testing.yml 10.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302
  1. name: Bootstrap Script Testing
  2. on:
  3. push:
  4. branches: [master, develop, xap]
  5. paths:
  6. - 'util/env-bootstrap.sh'
  7. - '.github/workflows/bootstrap_testing.yml'
  8. pull_request:
  9. paths:
  10. - 'util/env-bootstrap.sh'
  11. - '.github/workflows/bootstrap_testing.yml'
  12. workflow_dispatch:
  13. permissions:
  14. contents: read
  15. jobs:
  16. prep:
  17. runs-on: ubuntu-latest
  18. outputs:
  19. any_changed: ${{ steps.file_changes.outputs.any_changed }}
  20. steps:
  21. - name: Get changed files
  22. id: file_changes
  23. if: ${{ github.event_name == 'pull_request' }}
  24. uses: tj-actions/changed-files@v47
  25. with:
  26. use_rest_api: true
  27. files: |
  28. util/env-bootstrap.sh
  29. .github/workflows/bootstrap_testing.yml
  30. bootstrap-test-linux:
  31. name: Bootstrap (Linux)
  32. needs: prep
  33. if: ${{ github.event_name != 'pull_request' || needs.prep.outputs.any_changed == 'true' }}
  34. runs-on: ubuntu-latest
  35. strategy:
  36. fail-fast: false
  37. matrix:
  38. distribution:
  39. # Ubuntu/Debian based
  40. - debian:11
  41. - debian:12
  42. - debian:13
  43. - ubuntu:22.04
  44. - ubuntu:24.04
  45. - ubuntu:26.04
  46. # RHEL/CentOS/Fedora based
  47. - fedora:42
  48. - fedora:43
  49. - fedora:44
  50. - rockylinux:8
  51. - rockylinux:9
  52. - rockylinux/rockylinux:10
  53. - almalinux:8
  54. - almalinux:9
  55. - almalinux:10
  56. # OpenSUSE based (we skip Tumbleweed as it has issues with package mirrors regularly being out of date)
  57. - opensuse/leap:latest
  58. # Gentoo-based
  59. - gentoo/stage3:latest
  60. # Arch based
  61. - archlinux:latest
  62. - cachyos/cachyos:latest
  63. - manjarolinux/base:latest
  64. container:
  65. image: ${{ matrix.distribution }}
  66. options: --privileged
  67. steps:
  68. - name: Install base dependencies
  69. run: |
  70. # Attempt to run the package installation up to 10 times to mitigate transient network issues
  71. ok=''
  72. for n in $(seq 1 10); do
  73. {
  74. echo "Attempt #$n of 10 to install base dependencies:"
  75. case "${{ matrix.distribution }}" in
  76. *ubuntu*|*debian*)
  77. apt-get update &&
  78. apt-get install -y sudo git passwd
  79. ;;
  80. *fedora*|*rockylinux*|*almalinux*)
  81. dnf install -y sudo git passwd findutils # findutils=xargs
  82. ;;
  83. *suse*)
  84. zypper --non-interactive refresh &&
  85. zypper --non-interactive install sudo git shadow findutils tar # findutils=xargs
  86. ;;
  87. *gentoo*)
  88. { emaint sync -a || emerge --sync --quiet || emerge-webrsync -q ; } &&
  89. emerge --noreplace --ask=n sudo dev-vcs/git shadow findutils # findutils=xargs
  90. ;;
  91. *archlinux*|*cachyos*|*manjaro*)
  92. pacman -Syu --noconfirm &&
  93. pacman -S --noconfirm sudo git
  94. ;;
  95. esac
  96. } && { ok=1; break ; } || sleep 10
  97. done
  98. [ -n "$ok" ] || exit 1
  99. # Fix PAM configuration for sudo in containers
  100. # Fix /etc/shadow permissions - common issue in container environments
  101. chmod 640 /etc/shadow || chmod 400 /etc/shadow || true
  102. # Disable problematic PAM modules that commonly fail in RHEL-like containers
  103. sed -i 's/^session.*pam_systemd.so/#&/' /etc/pam.d/sudo || true
  104. sed -i 's/^session.*pam_loginuid.so/#&/' /etc/pam.d/sudo || true
  105. # Ensure proper sudoers configuration
  106. echo 'Defaults !requiretty' >> /etc/sudoers
  107. echo 'Defaults secure_path="/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin"' >> /etc/sudoers
  108. - name: Checkout repository
  109. uses: actions/checkout@v7
  110. with:
  111. fetch-depth: 1
  112. submodules: recursive
  113. path: qmk_firmware
  114. - name: Create test user
  115. run: |
  116. # Create a test user for the bootstrap script
  117. useradd -m -s /bin/bash -U testuser
  118. echo 'testuser:testpassword' | chpasswd || true
  119. # Configure passwordless sudo
  120. echo "root ALL=(ALL) NOPASSWD:ALL" >> /etc/sudoers # some distros complain about root not being in sudoers
  121. echo "testuser ALL=(ALL) NOPASSWD:ALL" >> /etc/sudoers
  122. # Test sudo functionality
  123. sudo -u testuser whoami || echo "Sudo test failed, but continuing..."
  124. - name: Move QMK repository to test user home
  125. run: |
  126. # Add upstream remote to the cloned repository so `qmk doctor` doesn't flag a warning
  127. git -C qmk_firmware remote add upstream https://github.com/qmk/qmk_firmware.git
  128. # Move the QMK repository to the test user's home directory
  129. mv qmk_firmware /home/testuser/qmk_firmware
  130. chown -R testuser:testuser /home/testuser/qmk_firmware
  131. - name: Run bootstrap script
  132. env:
  133. GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
  134. run: |
  135. # Ensure the bootstrap script can access sudo
  136. sudo -u testuser --preserve-env=GITHUB_TOKEN bash -c "
  137. export CONFIRM=1
  138. export PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin
  139. cd /home/testuser
  140. bash /home/testuser/qmk_firmware/util/env-bootstrap.sh
  141. "
  142. - name: Install dependencies
  143. run: |
  144. sudo -u testuser bash -c "
  145. /home/testuser/.local/share/uv/tools/qmk/bin/python -m pip install -r /home/testuser/qmk_firmware/requirements.txt
  146. "
  147. - name: Test QMK CLI
  148. run: |
  149. sudo -u testuser bash -c "
  150. export PATH=/home/testuser/.local/bin:\$PATH
  151. cd /home/testuser
  152. qmk setup -y -H /home/testuser/qmk_firmware # setup implies doctor, no need to run it separately
  153. cd /home/testuser/qmk_firmware
  154. qmk mass-compile -j $(nproc) -e DUMP_CI_METADATA=yes -f 'keyboard_name==*onekey*' -km reset -p || touch .failed # Compile a bunch of different platforms
  155. "
  156. cd /home/testuser/qmk_firmware
  157. ./util/ci/generate_failure_markdown.sh > $GITHUB_STEP_SUMMARY || true
  158. [ ! -e .failed ] || exit 1
  159. bootstrap-test-macos:
  160. name: Bootstrap (macOS)
  161. needs: prep
  162. if: ${{ github.event_name != 'pull_request' || needs.prep.outputs.any_changed == 'true' }}
  163. strategy:
  164. fail-fast: false
  165. matrix:
  166. os:
  167. - macos-14 # Apple Silicon ARM64
  168. - macos-15 # Apple Silicon ARM64
  169. - macos-15-intel # Intel x64
  170. - macos-26 # Apple Silicon ARM64
  171. - macos-26-intel # Intel x64
  172. runs-on: ${{ matrix.os }}
  173. steps:
  174. - name: Install base dependencies
  175. run: |
  176. # Attempt to run the brew update up to 10 times to mitigate transient issues
  177. for n in $(seq 1 10); do
  178. brew update && exit 0
  179. brew update-reset || true
  180. sleep 10
  181. done
  182. exit 1
  183. - name: Checkout repository
  184. uses: actions/checkout@v7
  185. with:
  186. fetch-depth: 1
  187. submodules: recursive
  188. - name: Run bootstrap script
  189. env:
  190. GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
  191. run: |
  192. # Add upstream remote to the cloned repository so `qmk doctor` doesn't flag a warning
  193. git remote add upstream https://github.com/qmk/qmk_firmware.git
  194. # Run the bootstrap script
  195. export CONFIRM=1
  196. sh ./util/env-bootstrap.sh
  197. - name: Install dependencies
  198. run: |
  199. $HOME/.local/share/uv/tools/qmk/bin/python -m pip install -r requirements.txt
  200. - name: Test QMK CLI
  201. run: |
  202. # Add QMK CLI to PATH (bootstrap script installs it to ~/.local/bin on macOS)
  203. export PATH="$HOME/.local/bin:$PATH"
  204. qmk setup -y -H . # setup implies doctor, no need to run it separately
  205. qmk mass-compile -j $(sysctl -n hw.ncpu) -e DUMP_CI_METADATA=yes -f 'keyboard_name==*onekey*' -km reset || touch .failed # Compile a bunch of different platforms
  206. ./util/ci/generate_failure_markdown.sh > $GITHUB_STEP_SUMMARY || true
  207. [ ! -e .failed ] || exit 1
  208. bootstrap-test-windows:
  209. name: Bootstrap (Windows)
  210. needs: prep
  211. if: ${{ github.event_name != 'pull_request' || needs.prep.outputs.any_changed == 'true' }}
  212. strategy:
  213. fail-fast: false
  214. matrix:
  215. msys-variant:
  216. - mingw64
  217. - clang64
  218. - ucrt64
  219. runs-on: windows-latest
  220. defaults:
  221. run:
  222. shell: msys2 {0}
  223. steps:
  224. - name: Install MSYS2
  225. uses: msys2/setup-msys2@v2
  226. with:
  227. msystem: ${{ matrix.msys-variant }}
  228. pacboy: >-
  229. git:
  230. - name: Checkout repository
  231. uses: actions/checkout@v7
  232. with:
  233. fetch-depth: 1
  234. submodules: recursive
  235. - name: Run bootstrap script
  236. env:
  237. GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
  238. run: |
  239. # Add upstream remote to the cloned repository so `qmk doctor` doesn't flag a warning
  240. git remote add upstream https://github.com/qmk/qmk_firmware.git
  241. # Run the bootstrap script
  242. export CONFIRM=1
  243. sh ./util/env-bootstrap.sh
  244. - name: Install dependencies
  245. run: |
  246. /opt/uv/tools/qmk/Scripts/python -m pip install -r requirements.txt
  247. - name: Test QMK CLI
  248. run: |
  249. # Add QMK CLI to PATH (bootstrap script installs it to /opt/uv/tools/bin on Windows MSYS2)
  250. export PATH="/opt/uv/tools/bin:$PATH"
  251. qmk setup -y -H . # setup implies doctor, no need to run it separately
  252. qmk mass-compile -j $(nproc) -e DUMP_CI_METADATA=yes -f 'keyboard_name==*onekey*' -km reset || touch .failed # Compile a bunch of different platforms
  253. ./util/ci/generate_failure_markdown.sh > $GITHUB_STEP_SUMMARY || true
  254. [ ! -e .failed ] || exit 1