aboutsummaryrefslogtreecommitdiffstats
path: root/.github/workflows/bootstrap_testing.yml
blob: 42c87204869141446ba57adba9b9901a9b7e0f48 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
name: Bootstrap Script Testing

on:
  push:
    branches: [master, develop, xap]
    paths:
    - 'util/env-bootstrap.sh'
    - '.github/workflows/bootstrap_testing.yml'
  pull_request:
    paths:
    - 'util/env-bootstrap.sh'
    - '.github/workflows/bootstrap_testing.yml'
  workflow_dispatch:

permissions:
  contents: read

jobs:
  prep:
    runs-on: ubuntu-latest

    outputs:
      any_changed: ${{ steps.file_changes.outputs.any_changed }}

    steps:
    - name: Get changed files
      id: file_changes
      if: ${{ github.event_name == 'pull_request' }}
      uses: tj-actions/changed-files@v47
      with:
        use_rest_api: true
        files: |
          util/env-bootstrap.sh
          .github/workflows/bootstrap_testing.yml

  bootstrap-test-linux:
    name: Bootstrap (Linux)

    needs: prep
    if: ${{ github.event_name != 'pull_request' || needs.prep.outputs.any_changed == 'true' }}

    runs-on: ubuntu-latest

    strategy:
      fail-fast: false
      matrix:
        distribution:
          # Ubuntu/Debian based
          - debian:11
          - debian:12
          - debian:13
          - ubuntu:20.04
          - ubuntu:22.04
          - ubuntu:24.04

          # RHEL/CentOS/Fedora based
          - fedora:41
          - fedora:42
          - fedora:43
          - rockylinux:8
          - rockylinux:9
          - rockylinux/rockylinux:10
          - almalinux:8
          - almalinux:9
          - almalinux:10

          # OpenSUSE based (we skip Tumbleweed as it has issues with package versions between pattern installs and other dependencies preinstalled into the base container)
          - opensuse/leap:latest

          # Gentoo-based
          - gentoo/stage3:latest

          # Arch based
          - archlinux:latest
          - cachyos/cachyos:latest
          - manjarolinux/base:latest

    container:
      image: ${{ matrix.distribution }}
      options: --privileged

    steps:
      - name: Install base dependencies
        run: |
          # Attempt to run the package installation up to 10 times to mitigate transient network issues
          for n in $(seq 1 10); do
            {
              echo "Attempt #$n of 10 to install base dependencies:"
              case "${{ matrix.distribution }}" in
                *ubuntu*|*debian*)
                  apt-get update
                  apt-get install -y sudo git passwd
                  ;;
                *fedora*|*rockylinux*|*almalinux*)
                  dnf install -y sudo git passwd findutils  # findutils=xargs
                  ;;
                *suse*)
                  zypper --non-interactive refresh
                  zypper --non-interactive install sudo git shadow findutils  # findutils=xargs
                  ;;
                *gentoo*)
                  emerge-webrsync
                  emerge --noreplace --ask=n sudo dev-vcs/git shadow findutils  # findutils=xargs
                  ;;
                *archlinux*|*cachyos*|*manjaro*)
                  pacman -Syu --noconfirm
                  pacman -S --noconfirm sudo git
                  ;;
              esac
            } && break || sleep 10
          done

          # Fix PAM configuration for sudo in containers
          # Fix /etc/shadow permissions - common issue in container environments
          chmod 640 /etc/shadow || chmod 400 /etc/shadow || true

          # Disable problematic PAM modules that commonly fail in RHEL-like containers
          sed -i 's/^session.*pam_systemd.so/#&/' /etc/pam.d/sudo || true
          sed -i 's/^session.*pam_loginuid.so/#&/' /etc/pam.d/sudo || true

          # Ensure proper sudoers configuration
          echo 'Defaults !requiretty' >> /etc/sudoers
          echo 'Defaults secure_path="/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin"' >> /etc/sudoers

      - name: Checkout repository
        uses: actions/checkout@v6
        with:
          fetch-depth: 1
          submodules: recursive
          path: qmk_firmware

      - name: Create test user
        run: |
          # Create a test user for the bootstrap script
          useradd -m -s /bin/bash -U testuser
          echo 'testuser:testpassword' | chpasswd || true
          
          # Configure passwordless sudo
          echo "root ALL=(ALL) NOPASSWD:ALL" >> /etc/sudoers  # some distros complain about root not being in sudoers
          echo "testuser ALL=(ALL) NOPASSWD:ALL" >> /etc/sudoers
          
          # Test sudo functionality
          sudo -u testuser whoami || echo "Sudo test failed, but continuing..."

      - name: Move QMK repository to test user home
        run: |
          # Add upstream remote to the cloned repository so `qmk doctor` doesn't flag a warning
          git -C qmk_firmware remote add upstream https://github.com/qmk/qmk_firmware.git
          # Move the QMK repository to the test user's home directory
          mv qmk_firmware /home/testuser/qmk_firmware
          chown -R testuser:testuser /home/testuser/qmk_firmware

      - name: Run bootstrap script
        env:
          GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
        run: |
          # Ensure the bootstrap script can access sudo
          sudo -u testuser --preserve-env=GITHUB_TOKEN bash -c "
            export CONFIRM=1
            export PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin
            cd /home/testuser
            bash /home/testuser/qmk_firmware/util/env-bootstrap.sh
          "

      - name: Install dependencies
        run: |
          sudo -u testuser bash -c "
            /home/testuser/.local/share/uv/tools/qmk/bin/python -m pip install -r /home/testuser/qmk_firmware/requirements.txt
          "

      - name: Test QMK CLI
        run: |
          sudo -u testuser bash -c "
            export PATH=/home/testuser/.local/bin:\$PATH
            cd /home/testuser
            qmk setup -y -H /home/testuser/qmk_firmware  # setup implies doctor, no need to run it separately
            cd /home/testuser/qmk_firmware
            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
          "
          
          cd /home/testuser/qmk_firmware
          ./util/ci/generate_failure_markdown.sh > $GITHUB_STEP_SUMMARY || true
          [ ! -e .failed ] || exit 1

  bootstrap-test-macos:
    name: Bootstrap (macOS)

    needs: prep
    if: ${{ github.event_name != 'pull_request' || needs.prep.outputs.any_changed == 'true' }}

    strategy:
      fail-fast: false
      matrix:
        os:
          - macos-14        # Apple Silicon ARM64
          - macos-15        # Apple Silicon ARM64
          - macos-15-intel  # Intel x64
          - macos-26        # Apple Silicon ARM64

    runs-on: ${{ matrix.os }}

    steps:
      - name: Checkout repository
        uses: actions/checkout@v6
        with:
          fetch-depth: 1
          submodules: recursive

      - name: Run bootstrap script
        env:
          GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
        run: |
          # Add upstream remote to the cloned repository so `qmk doctor` doesn't flag a warning
          git remote add upstream https://github.com/qmk/qmk_firmware.git
          # Run the bootstrap script
          export CONFIRM=1
          sh ./util/env-bootstrap.sh

      - name: Install dependencies
        run: |
          $HOME/.local/share/uv/tools/qmk/bin/python -m pip install -r requirements.txt

      - name: Test QMK CLI
        run: |
          # Add QMK CLI to PATH (bootstrap script installs it to ~/.local/bin on macOS)
          export PATH="$HOME/.local/bin:$PATH"
          qmk setup -y -H .  # setup implies doctor, no need to run it separately
          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
          
          ./util/ci/generate_failure_markdown.sh > $GITHUB_STEP_SUMMARY || true
          [ ! -e .failed ] || exit 1

  bootstrap-test-windows:
    name: Bootstrap (Windows)

    needs: prep
    if: ${{ github.event_name != 'pull_request' || needs.prep.outputs.any_changed == 'true' }}

    strategy:
      fail-fast: false
      matrix:
        msys-variant:
          - mingw64
          - clang64
          - ucrt64

    runs-on: windows-latest
    defaults:
      run:
        shell: msys2 {0}

    steps:
      - name: Install MSYS2
        uses: msys2/setup-msys2@v2
        with:
          msystem: ${{ matrix.msys-variant }}
          pacboy: >-
            git:

      - name: Checkout repository
        uses: actions/checkout@v6
        with:
          fetch-depth: 1
          submodules: recursive

      - name: Run bootstrap script
        env:
          GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
        run: |
          # Add upstream remote to the cloned repository so `qmk doctor` doesn't flag a warning
          git remote add upstream https://github.com/qmk/qmk_firmware.git
          # Run the bootstrap script
          export CONFIRM=1
          sh ./util/env-bootstrap.sh

      - name: Install dependencies
        run: |
          /opt/uv/tools/qmk/Scripts/python -m pip install -r requirements.txt

      - name: Test QMK CLI
        run: |
          # Add QMK CLI to PATH (bootstrap script installs it to /opt/uv/tools/bin on Windows MSYS2)
          export PATH="/opt/uv/tools/bin:$PATH"
          qmk setup -y -H .  # setup implies doctor, no need to run it separately
          qmk mass-compile -j $(nproc) -e DUMP_CI_METADATA=yes -f 'keyboard_name==*onekey*' -km reset || touch .failed  # Compile a bunch of different platforms
          
          ./util/ci/generate_failure_markdown.sh > $GITHUB_STEP_SUMMARY || true
          [ ! -e .failed ] || exit 1