---

name: Zephyr

# 'workflow_dispatch' allows running this workflow manually from the
# 'Actions' tab
# yamllint disable-line rule:truthy
on: [push, pull_request, workflow_dispatch, workflow_call]

# Specifies group name that stops previous wokrflows if the name matches
concurrency:
  # eg. "Zephyr-pull_request-my_fork_branch_to_merge"
  # eg. "Zephyr-push-refs/heads/my_branch_merging"
  group: ${{ github.workflow }}-${{ github.event_name }}-${{ github.head_ref || github.ref }}
  cancel-in-progress: true

jobs:

  manifest-check:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v3
        with:
          path: ./workspace/sof

      - name: plain west update
        run: |

          : This plain 'west update' does not provide 100% certainty that
          : all the manifest revisions make sense but it is quick and
          : will catch many revision problems. Other jobs typically
          : use 'west update --narrow' which is faster but
          : also able to fetch "wild" SHA1s from any random place! --narrow
          : is useful for testing unmerged Zephyr commits but risks
          : accepting "invalid" ones, this will not.

          pip3 install west
          cd workspace/sof/
          west init -l
          west update --fetch-opt=--filter=tree:0

      # Temporary check until we change west.yml and stop nesting rimage
      # and tomlc99 inside sof which will cleanly separate them from
      # XTOS submodules and... temporarily break every CI, which is why
      # it hasn't been done yet.
      - name: git submodules consistency
        run: |

          cd workspace/sof
          git submodule update --init --recursive

          west update
          if git status --porcelain=v2 | grep ^ ; then
             git status
             echo 'FAIL: inconsistency between git submodules and west.yml!'
             echo 'See rimage comment in west.yml.'
             echo 'Always use "git status"'
             exit 1
          fi

  build-linux:
    runs-on: ubuntu-20.04
    strategy:
      fail-fast: false
      matrix:
        # Using groups to avoid spamming the small results box with too
        # many lines. Pay attention to COMMAS.
        IPC_platforms: [
          # - IPC3 default
          imx8 imx8x imx8m,
          tgl tgl-h,  # UNSUPPORTED! Will be removed
          # - IPC4 default
          mtl,
          # Temporary testbed for Zephyr development.
          -i IPC4 tgl tgl-h,
        ]
        zephyr_revision: [
          manifest_revision,
          "https://github.com/zephyrproject-rtos/zephyr  main",
        ]

    steps:
      - uses: actions/checkout@v3
        # Download a full clone to fix `git describe`, sof_version.h and
        # build reproducibility. sof.git is still small.
        # This is especially useful for daily builds (but not just).
        with:
          fetch-depth: 0
          path: ./workspace/sof

      # As of December 2022 `--shallow-exclude=v3.2.0-rc3` fixes `git
      # describe`, Zephyr's version.h and build reproducibility while
      # downloading about 200MB less compared to a full clone.
      #
      # Ideally, the --shallow-exclude= argument should be regularly
      # bumped whenever SOF upgrades Zephyr to keep this as fast as
      # possible.
      # In a bigger Zephyr future maybe we could move to a more permanent
      # git fetch --shallow-since='5 months ago' because Zephyr follows
      # a "roughly 4-month release" but for now that saves only 100MB
      # https://docs.zephyrproject.org/latest/project/release_process.html
      #
      # TODO: try replacing --narrow and --depth with some
      # --fetch-opt=--filter=?
      # https://github.blog/2020-12-21-get-up-to-speed-with-partial-clone-and-shallow-clone/
      - name: west clones

        # Get some git tags in Zephyr. keep in sync with build-windows below
        run: pip3 install west && cd workspace/sof/ && west init -l &&
               west update --narrow --fetch-opt=--depth=5 &&
               git -C ../zephyr fetch --shallow-exclude=v3.2.0-rc3

      - name: select zephyr revision
        run: cd workspace/zephyr/ &&
             if [ 'manifest_revision' != '${{ matrix.zephyr_revision }}' ]; then
                 git fetch ${{ matrix.zephyr_revision }} &&
                 git checkout FETCH_HEAD;
             fi &&
             git log --oneline -n 5 --decorate --graph --no-abbrev-commit

      # Not strictly necessary but saves a lot of scrolling in the next step
      # Caching a 12G image is unfortunately not possible:
      #   https://github.com/ScribeMD/docker-cache/issues/304
      # For faster builds we would have to pay for some persistent runners.
      - name: Download docker image && ls /opt/toolchains/
        run: cd workspace && ./sof/zephyr/docker-run.sh ls -l /opt/toolchains/

      # https://github.com/zephyrproject-rtos/docker-image
      # Note: env variables can be passed to the container with
      # -e https_proxy=...
      - name: build
        run: cd workspace && ./sof/zephyr/docker-run.sh
             ./sof/zephyr/docker-build.sh --cmake-args=-DEXTRA_CFLAGS=-Werror
             --cmake-args=--warn-uninitialized ${{ matrix.IPC_platforms }}

      - name: Upload build artifacts
        uses: actions/upload-artifact@v3
        if: ${{ matrix.zephyr_revision == 'manifest_revision' }}
        with:
          name: linux-build ${{ matrix.IPC_platforms }}
          path: |
            ${{ github.workspace }}/workspace/build-sof-staging
            ${{ github.workspace }}/workspace/**/compile_commands.json

  build-windows:
    runs-on: windows-latest
    strategy:
      fail-fast: false
      # FIXME: Create common matrix for build-linux and build-windows
      matrix:
        # Using groups to avoid spamming the small results box with too
        # many lines. Pay attention to COMMAS.
        platforms: [
          # - IPC3 default
          imx8 imx8x imx8m,
          tgl tgl-h,  # UNSUPPORTED! Will be removed
          # - IPC4 default
          mtl,
          # Very few IPC3 platforms support IPC4 too.
          -i IPC4 tgl tgl-h,
        ]

    steps:
      - uses: actions/checkout@v3
        with:
          fetch-depth: 0
          path: ./workspace/sof

      # Cache artifacts so we do not overload external servers with downloads
      # Remember to change step key if you change the tools so old cache is not restored,
      # or delete cache manually in Github Actions tab
      - name: Cache unzip
        id: cache-unzip
        uses: actions/cache@v3.0.11
        with:
          path: unzip-5.51-1-bin.zip
          key: ${{ runner.os }}-cache-unzip-5-51-1

      - name: Cache wget
        id: cache-wget
        uses: actions/cache@v3.0.11
        with:
          path: wget-1.11.4-1-bin.zip
          key: ${{ runner.os }}-cache-wget-1-11-4-1

      # Keep this SDK version identical to the one in
      # sof/zephyr/docker-run.sh
      - name: Cache Zephyr SDK 0.15.2
        id: cache-zephyr-sdk
        uses: actions/cache@v3.0.11
        with:
          path: zephyr-sdk-0.15.2_windows-x86_64.zip
          key: ${{ runner.os }}-cache-zephyr-sdk-0-15-2

      # Unzip is needed by Zephyr SDK setup.cmd installation script
      - name: Download unzip
        if: ${{ steps.cache-unzip.outputs.cache-hit != 'true' }}
        run: |
          curl -L -o unzip-5.51-1-bin.zip `
          https://gnuwin32.sourceforge.net/downlinks/unzip-bin-zip.php

      # Wget is needed by Zephyr SDK setup.cmd installation script
      - name: Download wget
        if: ${{ steps.cache-wget.outputs.cache-hit != 'true' }}
        run: |
          curl -L -O http://downloads.sourceforge.net/gnuwin32/wget-1.11.4-1-bin.zip

      - name: Download Zephyr SDK 0.15.2
        if: ${{ steps.cache-zephyr-sdk.outputs.cache-hit != 'true' }}
        run: |  # yamllint disable-line rule:line-length
          curl -L -O `
          https://github.com/zephyrproject-rtos/sdk-ng/releases/download/v0.15.2/zephyr-sdk-0.15.2_windows-x86_64.zip

      # Unzips every .zip package to directory matching its name without extension
      - name: Unzip downloaded packages
        run: 7z x *.zip -o*

      - name: Add unzip to system PATH
        run: |
          echo "${{ github.workspace }}/unzip-5.51-1-bin/bin" | `
          Out-File -FilePath $env:GITHUB_PATH -Encoding utf8 -Append

      - name: Add wget to system PATH
        run: |
          echo "${{ github.workspace }}/wget-1.11.4-1-bin/bin" | `
          Out-File -FilePath $env:GITHUB_PATH -Encoding utf8 -Append

      # Install Zephyr SDK - all toolchains including Host Tools
      # and registering CMake package in the registry
      # setup.cmd may not be called in from msys shell as it does not parse
      # forward slash script input arguments correctly.
      - name: Install Zephyr SDK
        run: zephyr-sdk-0.15.2_windows-x86_64/zephyr-sdk-0.15.2/setup.cmd /t all /h /c

      - name: Setup Python
        uses: actions/setup-python@v4
        with:
          python-version: '3.8'

      - name: West install
        run: pip3 install west

      - name: West clone
        working-directory: ${{ github.workspace }}/workspace
        # Keep in sync with build-linux above
        run: west init -l sof &&
             west update --narrow --fetch-opt=--depth=5 &&
             git -C zephyr fetch --shallow-exclude=v3.2.0-rc3

      # Call Setup Python again to save the PIP packages in cache
      - name: Setup Python
        uses: actions/setup-python@v4
        id: cache-python
        with:
          python-version: '3.8'
          cache: 'pip'
          cache-dependency-path: workspace/zephyr/scripts/requirements.txt

      # All requirements will be satisfied if the restored cache matches existing state
      - name: Validate python PIP cache
        working-directory: ${{ github.workspace }}/workspace
        run: pip install -r zephyr/scripts/requirements.txt

      # MSYS2 provides gcc x64_86 toolchain & openssl
      - name: Initialize MSYS2
        uses: msys2/setup-msys2@v2
        with:
          msystem: MSYS
          install: gcc openssl-devel
          path-type: inherit

      - name: Build
        shell: msys2 {0}
        working-directory: ${{ github.workspace }}/workspace
        run: python sof/scripts/xtensa-build-zephyr.py
          --no-interactive
          --cmake-args=-DEXTRA_CFLAGS=-Werror
          --cmake-args=--warn-uninitialized ${{ matrix.platforms }}

      - name: Upload build artifacts
        uses: actions/upload-artifact@v3
        with:
          name: windows-build ${{ matrix.platforms}}
          path: |
            ${{ github.workspace }}/workspace/build-sof-staging
            ${{ github.workspace }}/workspace/**/compile_commands.json


  compare-linux-win:

    runs-on: ubuntu-latest

    # - We don't compare _all_ the builds, and
    # - even when some of the ones we compare fail, we still want to compare the rest.
    if: ${{ always() }}
    needs: [build-linux, build-windows]

    steps:
      - uses: actions/checkout@v3
        # we need only one script but it's simpler to get the (last
        # revision of the) whole repo and it takes seconds.
        with:
          # Isolate the clone in a subdirectory to make sure globbing
          # does not catch random SOF files.
          path: ./sof

      - name: Download Windows and Linux builds
        uses: actions/download-artifact@v3

      - name: apt-get dos2unix
        run: sudo apt-get update; sudo apt-get -y install dos2unix

      - name: Delete and fix expected differences
        run: |
          ls -l
          # run it twice to make sure it's idempotent
          for i in 0 1; do
            ./sof/zephyr/scripts/clean-expected-release-differences.sh \
               windows-build* linux-build*
          done

      - name: Compare Linux vs Windows builds
        run: |
          # FIXME: for windows the Z_SDK version is hardcoded above, for Linux it's not.
          diffs=0
          for windir in windows-build*; do
            lindir=linux-"${windir#windows-}"
            diff -qr "$lindir" "$windir" || : $((diffs++))
          done
          exit $diffs
