bootstrap_testing.yml 9.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289
  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. for n in $(seq 1 10); do
  72. {
  73. echo "Attempt #$n of 10 to install base dependencies:"
  74. case "${{ matrix.distribution }}" in
  75. *ubuntu*|*debian*)
  76. apt-get update
  77. apt-get install -y sudo git passwd
  78. ;;
  79. *fedora*|*rockylinux*|*almalinux*)
  80. dnf install -y sudo git passwd findutils # findutils=xargs
  81. ;;
  82. *suse*)
  83. zypper --non-interactive refresh
  84. zypper --non-interactive install sudo git shadow findutils tar # findutils=xargs
  85. ;;
  86. *gentoo*)
  87. emaint sync
  88. emerge --noreplace --ask=n sudo dev-vcs/git shadow findutils # findutils=xargs
  89. ;;
  90. *archlinux*|*cachyos*|*manjaro*)
  91. pacman -Syu --noconfirm
  92. pacman -S --noconfirm sudo git
  93. ;;
  94. esac
  95. } && break || sleep 10
  96. done
  97. # Fix PAM configuration for sudo in containers
  98. # Fix /etc/shadow permissions - common issue in container environments
  99. chmod 640 /etc/shadow || chmod 400 /etc/shadow || true
  100. # Disable problematic PAM modules that commonly fail in RHEL-like containers
  101. sed -i 's/^session.*pam_systemd.so/#&/' /etc/pam.d/sudo || true
  102. sed -i 's/^session.*pam_loginuid.so/#&/' /etc/pam.d/sudo || true
  103. # Ensure proper sudoers configuration
  104. echo 'Defaults !requiretty' >> /etc/sudoers
  105. echo 'Defaults secure_path="/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin"' >> /etc/sudoers
  106. - name: Checkout repository
  107. uses: actions/checkout@v7
  108. with:
  109. fetch-depth: 1
  110. submodules: recursive
  111. path: qmk_firmware
  112. - name: Create test user
  113. run: |
  114. # Create a test user for the bootstrap script
  115. useradd -m -s /bin/bash -U testuser
  116. echo 'testuser:testpassword' | chpasswd || true
  117. # Configure passwordless sudo
  118. echo "root ALL=(ALL) NOPASSWD:ALL" >> /etc/sudoers # some distros complain about root not being in sudoers
  119. echo "testuser ALL=(ALL) NOPASSWD:ALL" >> /etc/sudoers
  120. # Test sudo functionality
  121. sudo -u testuser whoami || echo "Sudo test failed, but continuing..."
  122. - name: Move QMK repository to test user home
  123. run: |
  124. # Add upstream remote to the cloned repository so `qmk doctor` doesn't flag a warning
  125. git -C qmk_firmware remote add upstream https://github.com/qmk/qmk_firmware.git
  126. # Move the QMK repository to the test user's home directory
  127. mv qmk_firmware /home/testuser/qmk_firmware
  128. chown -R testuser:testuser /home/testuser/qmk_firmware
  129. - name: Run bootstrap script
  130. env:
  131. GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
  132. run: |
  133. # Ensure the bootstrap script can access sudo
  134. sudo -u testuser --preserve-env=GITHUB_TOKEN bash -c "
  135. export CONFIRM=1
  136. export PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin
  137. cd /home/testuser
  138. bash /home/testuser/qmk_firmware/util/env-bootstrap.sh
  139. "
  140. - name: Install dependencies
  141. run: |
  142. sudo -u testuser bash -c "
  143. /home/testuser/.local/share/uv/tools/qmk/bin/python -m pip install -r /home/testuser/qmk_firmware/requirements.txt
  144. "
  145. - name: Test QMK CLI
  146. run: |
  147. sudo -u testuser bash -c "
  148. export PATH=/home/testuser/.local/bin:\$PATH
  149. cd /home/testuser
  150. qmk setup -y -H /home/testuser/qmk_firmware # setup implies doctor, no need to run it separately
  151. cd /home/testuser/qmk_firmware
  152. 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
  153. "
  154. cd /home/testuser/qmk_firmware
  155. ./util/ci/generate_failure_markdown.sh > $GITHUB_STEP_SUMMARY || true
  156. [ ! -e .failed ] || exit 1
  157. bootstrap-test-macos:
  158. name: Bootstrap (macOS)
  159. needs: prep
  160. if: ${{ github.event_name != 'pull_request' || needs.prep.outputs.any_changed == 'true' }}
  161. strategy:
  162. fail-fast: false
  163. matrix:
  164. os:
  165. - macos-14 # Apple Silicon ARM64
  166. - macos-15 # Apple Silicon ARM64
  167. - macos-15-intel # Intel x64
  168. - macos-26 # Apple Silicon ARM64
  169. runs-on: ${{ matrix.os }}
  170. steps:
  171. - name: Checkout repository
  172. uses: actions/checkout@v7
  173. with:
  174. fetch-depth: 1
  175. submodules: recursive
  176. - name: Run bootstrap script
  177. env:
  178. GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
  179. run: |
  180. # Add upstream remote to the cloned repository so `qmk doctor` doesn't flag a warning
  181. git remote add upstream https://github.com/qmk/qmk_firmware.git
  182. # Run the bootstrap script
  183. export CONFIRM=1
  184. sh ./util/env-bootstrap.sh
  185. - name: Install dependencies
  186. run: |
  187. $HOME/.local/share/uv/tools/qmk/bin/python -m pip install -r requirements.txt
  188. - name: Test QMK CLI
  189. run: |
  190. # Add QMK CLI to PATH (bootstrap script installs it to ~/.local/bin on macOS)
  191. export PATH="$HOME/.local/bin:$PATH"
  192. qmk setup -y -H . # setup implies doctor, no need to run it separately
  193. 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
  194. ./util/ci/generate_failure_markdown.sh > $GITHUB_STEP_SUMMARY || true
  195. [ ! -e .failed ] || exit 1
  196. bootstrap-test-windows:
  197. name: Bootstrap (Windows)
  198. needs: prep
  199. if: ${{ github.event_name != 'pull_request' || needs.prep.outputs.any_changed == 'true' }}
  200. strategy:
  201. fail-fast: false
  202. matrix:
  203. msys-variant:
  204. - mingw64
  205. - clang64
  206. - ucrt64
  207. runs-on: windows-latest
  208. defaults:
  209. run:
  210. shell: msys2 {0}
  211. steps:
  212. - name: Install MSYS2
  213. uses: msys2/setup-msys2@v2
  214. with:
  215. msystem: ${{ matrix.msys-variant }}
  216. pacboy: >-
  217. git:
  218. - name: Checkout repository
  219. uses: actions/checkout@v7
  220. with:
  221. fetch-depth: 1
  222. submodules: recursive
  223. - name: Run bootstrap script
  224. env:
  225. GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
  226. run: |
  227. # Add upstream remote to the cloned repository so `qmk doctor` doesn't flag a warning
  228. git remote add upstream https://github.com/qmk/qmk_firmware.git
  229. # Run the bootstrap script
  230. export CONFIRM=1
  231. sh ./util/env-bootstrap.sh
  232. - name: Install dependencies
  233. run: |
  234. /opt/uv/tools/qmk/Scripts/python -m pip install -r requirements.txt
  235. - name: Test QMK CLI
  236. run: |
  237. # Add QMK CLI to PATH (bootstrap script installs it to /opt/uv/tools/bin on Windows MSYS2)
  238. export PATH="/opt/uv/tools/bin:$PATH"
  239. qmk setup -y -H . # setup implies doctor, no need to run it separately
  240. qmk mass-compile -j $(nproc) -e DUMP_CI_METADATA=yes -f 'keyboard_name==*onekey*' -km reset || touch .failed # Compile a bunch of different platforms
  241. ./util/ci/generate_failure_markdown.sh > $GITHUB_STEP_SUMMARY || true
  242. [ ! -e .failed ] || exit 1