1name: Build with Clang/LLVM
2
3on: pull_request_target
4
5concurrency:
6  group: ${{ github.workflow }}-${{ github.event_name }}-${{ github.head_ref || github.ref }}
7  cancel-in-progress: true
8
9jobs:
10  clang-build:
11    if: github.repository_owner == 'zephyrproject-rtos'
12    runs-on: zephyr-runner-linux-x64-4xlarge
13    container:
14      image: ghcr.io/zephyrproject-rtos/ci:v0.26.7
15      options: '--entrypoint /bin/bash'
16      volumes:
17        - /repo-cache/zephyrproject:/github/cache/zephyrproject
18    strategy:
19      fail-fast: false
20      matrix:
21        platform: ["native_sim"]
22    env:
23      LLVM_TOOLCHAIN_PATH: /usr/lib/llvm-16
24      COMMIT_RANGE: ${{ github.event.pull_request.base.sha }}..${{ github.event.pull_request.head.sha }}
25      BASE_REF: ${{ github.base_ref }}
26    outputs:
27      report_needed: ${{ steps.twister.outputs.report_needed }}
28    steps:
29      - name: Apply container owner mismatch workaround
30        run: |
31          # FIXME: The owner UID of the GITHUB_WORKSPACE directory may not
32          #        match the container user UID because of the way GitHub
33          #        Actions runner is implemented. Remove this workaround when
34          #        GitHub comes up with a fundamental fix for this problem.
35          git config --global --add safe.directory ${GITHUB_WORKSPACE}
36
37      - name: Clone cached Zephyr repository
38        continue-on-error: true
39        run: |
40          git clone --shared /github/cache/zephyrproject/zephyr .
41          git remote set-url origin ${GITHUB_SERVER_URL}/${GITHUB_REPOSITORY}
42
43      - name: Checkout
44        uses: actions/checkout@v4
45        with:
46          ref: ${{ github.event.pull_request.head.sha }}
47          fetch-depth: 0
48          persist-credentials: false
49
50      - name: Environment Setup
51        run: |
52          echo "$HOME/.local/bin" >> $GITHUB_PATH
53          git config --global user.email "bot@zephyrproject.org"
54          git config --global user.name "Zephyr Bot"
55          rm -fr ".git/rebase-apply"
56          git rebase origin/${BASE_REF}
57          git log  --pretty=oneline | head -n 10
58          west init -l . || true
59          west config --global update.narrow true
60          west config manifest.group-filter -- +ci,+optional
61          # In some cases modules are left in a state where they can't be
62          # updated (i.e. when we cancel a job and the builder is killed),
63          # So first retry to update, if that does not work, remove all modules
64          # and start over. (Workaround until we implement more robust module
65          # west caching).
66          west update --path-cache /github/cache/zephyrproject 2>&1 1> west.log || west update --path-cache /github/cache/zephyrproject 2>&1 1> west2.log || ( rm -rf ../modules ../bootloader ../tools && west update --path-cache /github/cache/zephyrproject)
67
68          echo "ZEPHYR_SDK_INSTALL_DIR=/opt/toolchains/zephyr-sdk-$( cat SDK_VERSION )" >> $GITHUB_ENV
69
70      - name: Check Environment
71        run: |
72          cmake --version
73          ${LLVM_TOOLCHAIN_PATH}/bin/clang --version
74          gcc --version
75          ls -la
76
77      - name: Prepare ccache timestamp/data
78        id: ccache_cache_timestamp
79        shell: cmake -P {0}
80        run: |
81          string(TIMESTAMP current_date "%Y-%m-%d-%H;%M;%S" UTC)
82          string(REPLACE "/" "_" repo ${{github.repository}})
83          string(REPLACE "-" "_" repo2 ${repo})
84          file(APPEND $ENV{GITHUB_OUTPUT} "repo=${repo2}\n")
85
86      - name: use cache
87        id: cache-ccache
88        uses: zephyrproject-rtos/action-s3-cache@v1.2.0
89        with:
90          key: ${{ steps.ccache_cache_timestamp.outputs.repo }}-${{ github.ref_name }}-clang-${{ matrix.platform }}-ccache
91          path: /github/home/.cache/ccache
92          aws-s3-bucket: ccache.zephyrproject.org
93          aws-access-key-id: ${{ vars.AWS_CCACHE_ACCESS_KEY_ID }}
94          aws-secret-access-key: ${{ secrets.AWS_CCACHE_SECRET_ACCESS_KEY }}
95          aws-region: us-east-2
96
97      - name: ccache stats initial
98        run: |
99          mkdir -p /github/home/.cache
100          test -d github/home/.cache/ccache && rm -rf /github/home/.cache/ccache && mv github/home/.cache/ccache /github/home/.cache/ccache
101          ccache -M 10G -s
102
103      - name: Run Tests with Twister
104        id: twister
105        run: |
106          export ZEPHYR_BASE=${PWD}
107          export ZEPHYR_TOOLCHAIN_VARIANT=llvm
108
109          # check if we need to run a full twister or not based on files changed
110          python3 ./scripts/ci/test_plan.py --platform ${{ matrix.platform }} -c origin/${BASE_REF}..
111
112          # We can limit scope to just what has changed
113          if [ -s testplan.json ]; then
114            echo "report_needed=1" >> $GITHUB_OUTPUT
115            # Full twister but with options based on changes
116            ./scripts/twister --force-color --inline-logs -M -N -v --load-tests testplan.json --retry-failed 2
117          else
118            # if nothing is run, skip reporting step
119            echo "report_needed=0" >> $GITHUB_OUTPUT
120          fi
121
122      - name: ccache stats post
123        run: |
124          ccache -s
125          ccache -p
126
127      - name: Upload Unit Test Results
128        if: always() && steps.twister.outputs.report_needed != 0
129        uses: actions/upload-artifact@v4
130        with:
131          name: Unit Test Results (Subset ${{ matrix.platform }})
132          path: twister-out/twister.xml
133
134  clang-build-results:
135    name: "Publish Unit Tests Results"
136    needs: clang-build
137    runs-on: ubuntu-22.04
138    if: (success() || failure() ) && needs.clang-build.outputs.report_needed != 0
139    steps:
140      - name: Download Artifacts
141        uses: actions/download-artifact@v4
142        with:
143          path: artifacts
144      - name: Merge Test Results
145        run: |
146          pip3 install junitparser junit2html
147          junitparser merge artifacts/*/twister.xml junit.xml
148          junit2html junit.xml junit-clang.html
149
150      - name: Upload Unit Test Results in HTML
151        if: always()
152        uses: actions/upload-artifact@v4
153        with:
154          name: HTML Unit Test Results
155          if-no-files-found: ignore
156          path: |
157            junit-clang.html
158
159      - name: Publish Unit Test Results
160        uses: EnricoMi/publish-unit-test-result-action@v2
161        if: always()
162        with:
163          check_name: Unit Test Results
164          files: "**/twister.xml"
165          comment_mode: off
166