CI: Retry apt ops for mirror sync resilience #3617
Workflow file for this run
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| name: CI | |
| on: [push, pull_request] | |
| concurrency: | |
| group: ${{ github.workflow }}-${{ github.event.pull_request.number || github.ref }} | |
| cancel-in-progress: true | |
| jobs: | |
| detect-code-related-file-changes: | |
| runs-on: ubuntu-24.04 | |
| outputs: | |
| has_code_related_changes: ${{ steps.set_has_code_related_changes.outputs.has_code_related_changes }} | |
| steps: | |
| - name: Check out the repo | |
| uses: actions/checkout@v4 | |
| - name: Test changed files | |
| id: changed-files | |
| uses: tj-actions/changed-files@v46 | |
| with: | |
| files: | | |
| .ci/** | |
| build/** | |
| mk/** | |
| src/** | |
| tests/** | |
| tools/** | |
| .clang-format | |
| Dockerfile | |
| Makefile | |
| - name: Set has_code_related_changes | |
| id: set_has_code_related_changes | |
| run: | | |
| if [[ ${{ steps.changed-files.outputs.any_changed }} == true ]]; then | |
| echo "has_code_related_changes=true" >> $GITHUB_OUTPUT | |
| else | |
| echo "has_code_related_changes=false" >> $GITHUB_OUTPUT | |
| fi | |
| host-x64: | |
| needs: [detect-code-related-file-changes] | |
| if: needs.detect-code-related-file-changes.outputs.has_code_related_changes == 'true' | |
| timeout-minutes: 60 | |
| strategy: | |
| fail-fast: false | |
| matrix: | |
| compiler: [gcc, clang] | |
| runs-on: ubuntu-24.04 | |
| steps: | |
| - uses: actions/checkout@v4 | |
| with: | |
| submodules: 'true' | |
| - name: Cache LLVM 18 | |
| id: cache-llvm | |
| uses: actions/cache@v4 | |
| with: | |
| path: /usr/lib/llvm-18 | |
| key: ${{ runner.os }}-${{ runner.arch }}-llvm-18-v2 | |
| restore-keys: | | |
| ${{ runner.os }}-${{ runner.arch }}-llvm-18- | |
| - name: Cache RISC-V Toolchain | |
| id: cache-toolchain | |
| uses: actions/cache@v4 | |
| with: | |
| path: ${{ github.workspace }}/toolchain | |
| key: ${{ runner.os }}-${{ runner.arch }}-riscv-toolchain-${{ hashFiles('.ci/riscv-toolchain-install.sh') }} | |
| - name: Install dependencies | |
| run: | | |
| set +e # Disable errexit | |
| # Configure apt to tolerate mirror sync failures | |
| sudo tee /etc/apt/apt.conf.d/99-ci-reliability > /dev/null << 'EOF' | |
| APT::Update::Error-Mode "any"; | |
| Acquire::IndexTargets::deb::DEP-11::DefaultEnabled "false"; | |
| Acquire::IndexTargets::deb::DEP-11-icons::DefaultEnabled "false"; | |
| Acquire::IndexTargets::deb::DEP-11-icons-hidpi::DefaultEnabled "false"; | |
| Acquire::Retries "3"; | |
| Acquire::Check-Valid-Until "false"; | |
| EOF | |
| # Update with error tolerance | |
| sudo apt-get update -q=2 2>&1 | |
| UPDATE_EXIT=$? | |
| if [ $UPDATE_EXIT -ne 0 ]; then | |
| echo "WARNING: apt update exited with code $UPDATE_EXIT, continuing..." | |
| fi | |
| sudo apt-get install -q=2 curl libsdl2-dev libsdl2-mixer-dev device-tree-compiler expect bc p7zip-full | |
| set -e # Re-enable errexit | |
| shell: bash | |
| - name: Install RISC-V Toolchain | |
| if: steps.cache-toolchain.outputs.cache-hit != 'true' | |
| run: | | |
| .ci/riscv-toolchain-install.sh | |
| - name: Setup RISC-V Toolchain PATH | |
| run: echo "${{ github.workspace }}/toolchain/bin" >> $GITHUB_PATH | |
| - name: Install LLVM 18 | |
| if: steps.cache-llvm.outputs.cache-hit != 'true' | |
| run: | | |
| .ci/fetch.sh -q -o llvm.sh https://apt.llvm.org/llvm.sh | |
| chmod +x ./llvm.sh | |
| sudo ./llvm.sh 18 | |
| - name: Setup LLVM PATH | |
| run: echo "/usr/lib/llvm-18/bin" >> $GITHUB_PATH | |
| shell: bash | |
| - name: Install compiler | |
| id: install_cc | |
| uses: rlalik/setup-cpp-compiler@master | |
| with: | |
| compiler: ${{ matrix.compiler }} | |
| - name: Setup emsdk | |
| uses: mymindstorm/setup-emsdk@v14 | |
| with: | |
| version: 3.1.51 | |
| actions-cache-folder: 'emsdk-cache' | |
| - name: Set parallel jobs variable | |
| run: | | |
| echo "PARALLEL=-j$(nproc)" >> "$GITHUB_ENV" | |
| echo "BOOT_LINUX_TEST=TMP_FILE=\$(mktemp "$RUNNER_TEMP/tmpfile.XXXXXX"); \ | |
| sudo env TMP_FILE=\${TMP_FILE} .ci/boot-linux-prepare.sh setup; \ | |
| . \${TMP_FILE}; \ | |
| .ci/boot-linux.sh; \ | |
| EXIT_CODE=\$?; \ | |
| sudo env TMP_FILE=\${TMP_FILE} BLK_DEV_EXT4=\${BLK_DEV_EXT4} \ | |
| BLK_DEV_SIMPLEFS=\${BLK_DEV_SIMPLEFS} .ci/boot-linux-prepare.sh cleanup; \ | |
| exit \${EXIT_CODE};" >> "$GITHUB_ENV" | |
| - name: Cache build artifacts | |
| uses: actions/cache@v4 | |
| with: | |
| path: build/ | |
| key: rv32emu-artifacts-${{ runner.os }}-${{ hashFiles('mk/artifact.mk', 'mk/external.mk') }} | |
| restore-keys: | | |
| rv32emu-artifacts-${{ runner.os }}- | |
| - name: Fetch artifacts | |
| env: | |
| CC: ${{ steps.install_cc.outputs.cc }} | |
| run: | | |
| make artifact | |
| make ENABLE_SYSTEM=1 artifact | |
| make ENABLE_ARCH_TEST=1 artifact | |
| # get from rv32emu-prebuilt | |
| .ci/fetch.sh -o build/shareware_doom_iwad.zip "https://raw.githubusercontent.com/sysprog21/rv32emu-prebuilt/doom-artifact/shareware_doom_iwad.zip" | |
| unzip -o -d build/ build/shareware_doom_iwad.zip | |
| - name: default build using emcc | |
| if: success() | |
| run: | | |
| make CC=emcc ENABLE_JIT=0 $PARALLEL | |
| - name: default build for system emulation using emcc | |
| if: success() | |
| run: | | |
| make distclean | |
| make CC=emcc ENABLE_SYSTEM=1 ENABLE_JIT=0 $PARALLEL | |
| make distclean ENABLE_SYSTEM=1 | |
| - name: Build with various optimization levels | |
| if: success() | |
| env: | |
| CC: ${{ steps.install_cc.outputs.cc }} | |
| run: | | |
| set -euo pipefail | |
| for opt_level in -g -Og -O0 -O1 -O2 -O3 -Ofast; do | |
| echo "Building with OPT_LEVEL=$opt_level" | |
| if ! (make distclean && make OPT_LEVEL=$opt_level $PARALLEL); then | |
| echo "ERROR: Build failed with OPT_LEVEL=$opt_level" | |
| exit 1 | |
| fi | |
| done | |
| - name: Build system emulation with various optimization levels | |
| if: success() | |
| env: | |
| CC: ${{ steps.install_cc.outputs.cc }} | |
| run: | | |
| set -euo pipefail | |
| for opt_level in -g -Og -O0 -O1 -O2 -O3 -Ofast; do | |
| echo "Building system emulation with OPT_LEVEL=$opt_level" | |
| if ! (make distclean && make OPT_LEVEL=$opt_level ENABLE_SYSTEM=1 $PARALLEL); then | |
| echo "ERROR: System emulation build failed with OPT_LEVEL=$opt_level" | |
| exit 1 | |
| fi | |
| done | |
| - name: check + tests | |
| if: success() | |
| env: | |
| CC: ${{ steps.install_cc.outputs.cc }} | |
| run: | | |
| make distclean | |
| make check $PARALLEL | |
| make tests $PARALLEL | |
| make misalign $PARALLEL | |
| make tool $PARALLEL | |
| - name: diverse configurations | |
| if: success() | |
| env: | |
| CC: ${{ steps.install_cc.outputs.cc }} | |
| run: | | |
| set -euo pipefail | |
| for config in ENABLE_EXT_M ENABLE_EXT_A ENABLE_EXT_F ENABLE_EXT_C \ | |
| ENABLE_SDL ENABLE_Zicsr ENABLE_MOP_FUSION ENABLE_BLOCK_CHAINING \ | |
| ENABLE_Zba ENABLE_Zbb ENABLE_Zbc ENABLE_Zbs ENABLE_Zifencei; do | |
| echo "Testing with ${config}=0" | |
| if ! (make distclean && make ${config}=0 check $PARALLEL); then | |
| echo "ERROR: Test failed with ${config}=0" | |
| exit 1 | |
| fi | |
| done | |
| - name: misalignment test in block emulation | |
| if: success() | |
| env: | |
| CC: ${{ steps.install_cc.outputs.cc }} | |
| run: | | |
| make -C tests/system/alignment/ | |
| make distclean && make ENABLE_ELF_LOADER=1 ENABLE_EXT_C=0 ENABLE_SYSTEM=1 misalign-in-blk-emu $PARALLEL | |
| - name: MMU test | |
| if: success() | |
| env: | |
| CC: ${{ steps.install_cc.outputs.cc }} | |
| run: | | |
| make -C tests/system/mmu/ | |
| make distclean && make ENABLE_ELF_LOADER=1 ENABLE_SYSTEM=1 mmu-test $PARALLEL | |
| - name: gdbstub test | |
| if: success() | |
| env: | |
| CC: ${{ steps.install_cc.outputs.cc }} | |
| run: | | |
| make distclean && make ENABLE_GDBSTUB=1 gdbstub-test $PARALLEL | |
| - name: JIT test | |
| if: success() | |
| env: | |
| CC: ${{ steps.install_cc.outputs.cc }} | |
| run: | | |
| set -euo pipefail | |
| # Base JIT test | |
| make ENABLE_JIT=1 clean && make ENABLE_JIT=1 check $PARALLEL | |
| # JIT tests with disabled extensions | |
| for ext in ENABLE_EXT_A ENABLE_EXT_F ENABLE_EXT_C ENABLE_EXT_M \ | |
| ENABLE_Zba ENABLE_Zbb ENABLE_Zbc ENABLE_Zbs \ | |
| ENABLE_Zicsr ENABLE_Zifencei \ | |
| ENABLE_MOP_FUSION ENABLE_BLOCK_CHAINING; do | |
| echo "JIT test with ${ext}=0" | |
| if ! (make ENABLE_JIT=1 clean && make ${ext}=0 ENABLE_JIT=1 check $PARALLEL); then | |
| echo "ERROR: JIT test failed with ${ext}=0" | |
| exit 1 | |
| fi | |
| done | |
| - name: undefined behavior test | |
| if: success() || failure() | |
| run: | | |
| make distclean && make ENABLE_UBSAN=1 check $PARALLEL | |
| make ENABLE_JIT=1 clean && make ENABLE_JIT=1 ENABLE_UBSAN=1 check $PARALLEL | |
| - name: boot Linux kernel test | |
| if: success() | |
| env: | |
| CC: ${{ steps.install_cc.outputs.cc }} | |
| run: | | |
| make distclean && make INITRD_SIZE=32 ENABLE_SYSTEM=1 $PARALLEL && make ENABLE_SYSTEM=1 artifact $PARALLEL | |
| bash -c "${BOOT_LINUX_TEST}" | |
| make ENABLE_SYSTEM=1 clean | |
| - name: boot Linux kernel test (JIT) | |
| if: success() | |
| env: | |
| CC: ${{ steps.install_cc.outputs.cc }} | |
| run: | | |
| make distclean && make INITRD_SIZE=32 ENABLE_SYSTEM=1 ENABLE_JIT=1 ENABLE_MOP_FUSION=0 $PARALLEL && make ENABLE_SYSTEM=1 artifact $PARALLEL | |
| bash -c "${BOOT_LINUX_TEST}" | |
| make ENABLE_SYSTEM=1 ENABLE_JIT=1 ENABLE_MOP_FUSION=0 clean | |
| - name: Architecture test | |
| if: success() | |
| env: | |
| CC: ${{ steps.install_cc.outputs.cc }} | |
| GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} | |
| run: | | |
| . .ci/common.sh | |
| export LATEST_RELEASE=$(download_with_headers "https://api.github.com/repos/sysprog21/rv32emu-prebuilt/releases" \ | |
| "Authorization: Bearer ${GH_TOKEN}" \ | |
| | grep '"tag_name"' \ | |
| | grep "sail" \ | |
| | head -n 1 \ | |
| | sed -E 's/.*"tag_name": "([^"]+)".*/\1/') | |
| .ci/riscv-tests.sh | |
| host-arm64: | |
| needs: [detect-code-related-file-changes] | |
| if: needs.detect-code-related-file-changes.outputs.has_code_related_changes == 'true' | |
| timeout-minutes: 45 | |
| runs-on: ubuntu-24.04 | |
| steps: | |
| - name: checkout code | |
| uses: actions/checkout@v4 | |
| with: | |
| submodules: 'true' | |
| - name: build artifact | |
| # The GitHub Action for non-x86 CPU | |
| uses: uraimo/run-on-arch-action@v3 | |
| with: | |
| arch: aarch64 | |
| distro: ubuntu24.04 | |
| githubToken: ${{ github.token }} | |
| # No 'sudo' is available | |
| install: | | |
| set +e # Disable errexit for entire install block | |
| # Configure apt to tolerate mirror sync failures | |
| cat > /etc/apt/apt.conf.d/99-ci-reliability << 'APTCONF' | |
| APT::Update::Error-Mode "any"; | |
| Acquire::IndexTargets::deb::DEP-11::DefaultEnabled "false"; | |
| Acquire::IndexTargets::deb::DEP-11-icons::DefaultEnabled "false"; | |
| Acquire::IndexTargets::deb::DEP-11-icons-hidpi::DefaultEnabled "false"; | |
| Acquire::Retries "3"; | |
| Acquire::Check-Valid-Until "false"; | |
| APTCONF | |
| # Update with error tolerance - may fail during mirror sync | |
| apt update -qq 2>&1 | |
| UPDATE_EXIT=$? | |
| if [ $UPDATE_EXIT -ne 0 ]; then | |
| echo "WARNING: apt update exited with code $UPDATE_EXIT (mirror sync likely in progress)" | |
| echo "Continuing with installation using cached/partial indexes..." | |
| fi | |
| # Install packages - will use whatever indexes are available | |
| apt install -yqq make git curl wget clang libsdl2-dev libsdl2-mixer-dev lsb-release software-properties-common gnupg bc || { | |
| echo "WARNING: Some packages may have failed to install, retrying critical ones..." | |
| apt install -yqq --no-download make git curl wget clang || true | |
| } | |
| which wget || echo "WARNING: wget not found after installation" | |
| set -e # Re-enable errexit | |
| exit 0 # Force success exit code | |
| # FIXME: gcc build fails on Aarch64/Linux hosts | |
| env: | | |
| CC: clang-18 | |
| # Append custom commands here | |
| run: | | |
| # Verify and install wget if needed (workaround for install step issues) | |
| if ! command -v wget > /dev/null 2>&1; then | |
| # Config file should already exist from install step, but apt may still fail | |
| apt update -qq 2>&1 || true | |
| apt install -yqq wget || { echo "wget install failed, trying without update..."; apt install -yqq wget --no-download || true; } | |
| fi | |
| git config --global --add safe.directory ${{ github.workspace }} | |
| git config --global --add safe.directory ${{ github.workspace }}/src/softfloat | |
| git config --global --add safe.directory ${{ github.workspace }}/src/mini-gdbstub | |
| wget -O /tmp/llvm.sh https://apt.llvm.org/llvm.sh | |
| chmod +x /tmp/llvm.sh | |
| /tmp/llvm.sh 18 | |
| export PATH=/usr/lib/llvm-18/bin:$PATH | |
| PARALLEL=-j$(nproc) | |
| make artifact | |
| make $PARALLEL | |
| make check $PARALLEL | |
| make ENABLE_JIT=1 clean && make ENABLE_JIT=1 check $PARALLEL | |
| make ENABLE_JIT=1 clean && make ENABLE_EXT_A=0 ENABLE_JIT=1 check $PARALLEL | |
| make ENABLE_JIT=1 clean && make ENABLE_EXT_F=0 ENABLE_JIT=1 check $PARALLEL | |
| make ENABLE_JIT=1 clean && make ENABLE_EXT_C=0 ENABLE_JIT=1 check $PARALLEL | |
| macOS-arm64: | |
| needs: [detect-code-related-file-changes] | |
| if: needs.detect-code-related-file-changes.outputs.has_code_related_changes == 'true' | |
| timeout-minutes: 60 | |
| strategy: | |
| fail-fast: false | |
| matrix: | |
| compiler: [gcc-15, clang] | |
| runs-on: macos-latest # M1 chip | |
| steps: | |
| - uses: actions/checkout@v4 | |
| with: | |
| submodules: 'true' | |
| - name: Cache RISC-V Toolchain | |
| id: cache-toolchain | |
| uses: actions/cache@v4 | |
| with: | |
| path: ${{ github.workspace }}/toolchain | |
| key: ${{ runner.os }}-${{ runner.arch }}-riscv-toolchain-${{ hashFiles('.ci/riscv-toolchain-install.sh') }} | |
| - name: Cache Homebrew packages | |
| id: cache-brew | |
| uses: actions/cache@v4 | |
| with: | |
| path: | | |
| /opt/homebrew/Cellar/llvm@18 | |
| /opt/homebrew/Cellar/sdl2 | |
| /opt/homebrew/Cellar/dtc | |
| key: ${{ runner.os }}-${{ runner.arch }}-brew-${{ hashFiles('.github/workflows/main.yml') }} | |
| - name: Install dependencies | |
| run: | | |
| brew install make dtc expect sdl2 bc e2fsprogs p7zip llvm@18 dcfldd | |
| brew install sdl2_mixer || echo "Warning: sdl2_mixer installation failed, continuing without SDL_MIXER support" | |
| - name: Install RISC-V Toolchain | |
| if: steps.cache-toolchain.outputs.cache-hit != 'true' | |
| run: | | |
| .ci/riscv-toolchain-install.sh | |
| - name: Setup toolchain paths | |
| run: | | |
| echo "${{ github.workspace }}/toolchain/bin" >> $GITHUB_PATH | |
| echo "$(brew --prefix llvm@18)/bin" >> $GITHUB_PATH | |
| - name: Set up Python 3.12 | |
| uses: actions/setup-python@v6 | |
| with: | |
| python-version: '3.12' | |
| - name: Install compiler | |
| id: install_cc | |
| uses: rlalik/setup-cpp-compiler@master | |
| with: | |
| compiler: ${{ matrix.compiler }} | |
| - name: Setup emsdk | |
| uses: mymindstorm/setup-emsdk@v14 | |
| with: | |
| version: 3.1.51 | |
| actions-cache-folder: 'emsdk-cache' | |
| - name: Set parallel jobs variable | |
| run: | | |
| echo "PARALLEL=-j$(sysctl -n hw.logicalcpu)" >> "$GITHUB_ENV" | |
| echo "BOOT_LINUX_TEST=TMP_FILE=\$(mktemp "$RUNNER_TEMP/tmpfile.XXXXXX"); \ | |
| sudo env TMP_FILE=\${TMP_FILE} .ci/boot-linux-prepare.sh setup; \ | |
| . \${TMP_FILE}; \ | |
| .ci/boot-linux.sh; \ | |
| EXIT_CODE=\$?; \ | |
| sudo env TMP_FILE=\${TMP_FILE} BLK_DEV_EXT4=\${BLK_DEV_EXT4} .ci/boot-linux-prepare.sh cleanup; \ | |
| exit \${EXIT_CODE};" >> "$GITHUB_ENV" | |
| - name: Symlink gcc-15 due to the default /usr/local/bin/gcc links to system's clang | |
| run: | | |
| ln -s /opt/homebrew/opt/gcc/bin/gcc-15 /usr/local/bin/gcc-15 | |
| - name: fetch artifact first to reduce HTTP requests | |
| env: | |
| CC: ${{ steps.install_cc.outputs.cc }} | |
| GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} | |
| run: | | |
| . .ci/common.sh | |
| LATEST_RELEASE=$(download_with_headers "https://api.github.com/repos/sysprog21/rv32emu-prebuilt/releases" \ | |
| "Authorization: Bearer ${GH_TOKEN}" \ | |
| | grep '"tag_name"' \ | |
| | grep "ELF" \ | |
| | head -n 1 \ | |
| | sed -E 's/.*"tag_name": "([^"]+)".*/\1/') | |
| make LATEST_RELEASE=$LATEST_RELEASE artifact | |
| LATEST_RELEASE=$(download_with_headers "https://api.github.com/repos/sysprog21/rv32emu-prebuilt/releases" \ | |
| "Authorization: Bearer ${GH_TOKEN}" \ | |
| | grep '"tag_name"' \ | |
| | grep "Linux-Image" \ | |
| | head -n 1 \ | |
| | sed -E 's/.*"tag_name": "([^"]+)".*/\1/') | |
| make LATEST_RELEASE=$LATEST_RELEASE ENABLE_SYSTEM=1 artifact | |
| LATEST_RELEASE=$(download_with_headers "https://api.github.com/repos/sysprog21/rv32emu-prebuilt/releases" \ | |
| "Authorization: Bearer ${GH_TOKEN}" \ | |
| | grep '"tag_name"' \ | |
| | grep "sail" \ | |
| | head -n 1 \ | |
| | sed -E 's/.*"tag_name": "([^"]+)".*/\1/') | |
| make LATEST_RELEASE=$LATEST_RELEASE ENABLE_ARCH_TEST=1 artifact | |
| # get from rv32emu-prebuilt | |
| .ci/fetch.sh -o build/shareware_doom_iwad.zip "https://raw.githubusercontent.com/sysprog21/rv32emu-prebuilt/doom-artifact/shareware_doom_iwad.zip" | |
| unzip -o -d build/ build/shareware_doom_iwad.zip | |
| - name: default build using emcc | |
| if: success() | |
| run: | | |
| make CC=emcc ENABLE_JIT=0 $PARALLEL | |
| - name: default build for system emulation using emcc | |
| if: success() | |
| run: | | |
| make distclean | |
| make CC=emcc ENABLE_SYSTEM=1 ENABLE_JIT=0 $PARALLEL | |
| make distclean ENABLE_SYSTEM=1 | |
| - name: check + tests | |
| if: success() | |
| env: | |
| CC: ${{ steps.install_cc.outputs.cc }} | |
| run: | | |
| make distclean | |
| make check $PARALLEL | |
| make tests $PARALLEL | |
| make misalign $PARALLEL | |
| make tool $PARALLEL | |
| - name: diverse configurations | |
| if: success() | |
| env: | |
| CC: ${{ steps.install_cc.outputs.cc }} | |
| run: | | |
| set -euo pipefail | |
| for config in ENABLE_EXT_M ENABLE_EXT_A ENABLE_EXT_F ENABLE_EXT_C \ | |
| ENABLE_SDL ENABLE_Zicsr ENABLE_MOP_FUSION ENABLE_BLOCK_CHAINING \ | |
| ENABLE_Zba ENABLE_Zbb ENABLE_Zbc ENABLE_Zbs ENABLE_Zifencei; do | |
| echo "Testing with ${config}=0" | |
| if ! (make distclean && make ${config}=0 check $PARALLEL); then | |
| echo "ERROR: Test failed with ${config}=0" | |
| exit 1 | |
| fi | |
| done | |
| - name: gdbstub test, need RV32 toolchain | |
| if: success() | |
| env: | |
| CC: ${{ steps.install_cc.outputs.cc }} | |
| run: | | |
| make distclean && make ENABLE_GDBSTUB=1 gdbstub-test $PARALLEL | |
| - name: JIT test | |
| if: success() | |
| env: | |
| CC: ${{ steps.install_cc.outputs.cc }} | |
| run: | | |
| set -euo pipefail | |
| # Base JIT test | |
| make ENABLE_JIT=1 clean && make ENABLE_JIT=1 check $PARALLEL | |
| # JIT tests with disabled extensions | |
| for ext in ENABLE_EXT_A ENABLE_EXT_F ENABLE_EXT_C ENABLE_EXT_M \ | |
| ENABLE_Zba ENABLE_Zbb ENABLE_Zbc ENABLE_Zbs \ | |
| ENABLE_Zicsr ENABLE_Zifencei \ | |
| ENABLE_MOP_FUSION ENABLE_BLOCK_CHAINING; do | |
| echo "JIT test with ${ext}=0" | |
| if ! (make ENABLE_JIT=1 clean && make ${ext}=0 ENABLE_JIT=1 check $PARALLEL); then | |
| echo "ERROR: JIT test failed with ${ext}=0" | |
| exit 1 | |
| fi | |
| done | |
| - name: undefined behavior test | |
| if: (success() || failure()) && steps.install_cc.outputs.cc == 'clang' # gcc on macOS/arm64 does not support sanitizers | |
| env: | |
| CC: ${{ steps.install_cc.outputs.cc }} | |
| run: | | |
| make distclean && make ENABLE_UBSAN=1 check $PARALLEL | |
| make ENABLE_JIT=1 clean && make ENABLE_JIT=1 ENABLE_UBSAN=1 check $PARALLEL | |
| - name: boot Linux kernel test | |
| if: success() | |
| env: | |
| CC: ${{ steps.install_cc.outputs.cc }} | |
| run: | | |
| make distclean && make INITRD_SIZE=32 ENABLE_SYSTEM=1 $PARALLEL && \ | |
| make ENABLE_SYSTEM=1 artifact $PARALLEL | |
| bash -c "${BOOT_LINUX_TEST}" | |
| make ENABLE_SYSTEM=1 clean | |
| - name: boot Linux kernel test (JIT) | |
| if: success() | |
| env: | |
| CC: ${{ steps.install_cc.outputs.cc }} | |
| run: | | |
| make distclean && make INITRD_SIZE=32 ENABLE_SYSTEM=1 ENABLE_JIT=1 ENABLE_MOP_FUSION=0 $PARALLEL && make ENABLE_SYSTEM=1 artifact $PARALLEL | |
| bash -c "${BOOT_LINUX_TEST}" | |
| make ENABLE_SYSTEM=1 ENABLE_JIT=1 ENABLE_MOP_FUSION=0 clean | |
| - name: Architecture test | |
| if: success() | |
| env: | |
| CC: ${{ steps.install_cc.outputs.cc }} | |
| GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} | |
| run: | | |
| . .ci/common.sh | |
| export LATEST_RELEASE=$(download_with_headers "https://api.github.com/repos/sysprog21/rv32emu-prebuilt/releases" \ | |
| "Authorization: Bearer ${GH_TOKEN}" \ | |
| | grep '"tag_name"' \ | |
| | grep "sail" \ | |
| | head -n 1 \ | |
| | sed -E 's/.*"tag_name": "([^"]+)".*/\1/') | |
| python3 -m venv venv | |
| . venv/bin/activate | |
| .ci/riscv-tests.sh | |
| coding-style: | |
| needs: [detect-code-related-file-changes] | |
| if: needs.detect-code-related-file-changes.outputs.has_code_related_changes == 'true' | |
| timeout-minutes: 15 | |
| runs-on: ubuntu-24.04 | |
| steps: | |
| - uses: actions/checkout@v4 | |
| - name: coding convention | |
| run: | | |
| sudo apt-get install -q=2 clang-format-18 shfmt python3-pip | |
| pip3 install black==25.1.0 | |
| .ci/check-newline.sh | |
| .ci/check-format.sh | |
| shell: bash | |
| static-analysis: | |
| needs: [detect-code-related-file-changes] | |
| if: needs.detect-code-related-file-changes.outputs.has_code_related_changes == 'true' | |
| timeout-minutes: 45 | |
| runs-on: ubuntu-24.04 | |
| steps: | |
| - uses: actions/checkout@v4 | |
| with: | |
| submodules: 'true' | |
| # LLVM static analysis | |
| - name: set up scan-build | |
| run: | | |
| set +e # Disable errexit | |
| # Configure apt to tolerate mirror sync failures | |
| sudo tee /etc/apt/apt.conf.d/99-ci-reliability > /dev/null << 'EOF' | |
| APT::Update::Error-Mode "any"; | |
| Acquire::IndexTargets::deb::DEP-11::DefaultEnabled "false"; | |
| Acquire::IndexTargets::deb::DEP-11-icons::DefaultEnabled "false"; | |
| Acquire::IndexTargets::deb::DEP-11-icons-hidpi::DefaultEnabled "false"; | |
| Acquire::Retries "3"; | |
| Acquire::Check-Valid-Until "false"; | |
| EOF | |
| # Update with error tolerance | |
| sudo apt-get update -q=2 2>&1 | |
| UPDATE_EXIT=$? | |
| if [ $UPDATE_EXIT -ne 0 ]; then | |
| echo "WARNING: apt update exited with code $UPDATE_EXIT, continuing..." | |
| fi | |
| sudo apt-get install -q=2 curl libsdl2-dev libsdl2-mixer-dev | |
| .ci/fetch.sh -q -o llvm.sh https://apt.llvm.org/llvm.sh | |
| chmod +x ./llvm.sh | |
| sudo ./llvm.sh 18 | |
| sudo apt-get install -q=2 clang-18 clang-tools-18 | |
| set -e # Re-enable errexit | |
| shell: bash | |
| - name: run scan-build without JIT | |
| env: | |
| LATEST_RELEASE: dummy | |
| run: make distclean && scan-build-18 -v -o ~/scan-build --status-bugs --use-cc=clang-18 --force-analyze-debug-code --show-description -analyzer-config stable-report-filename=true -enable-checker valist,nullability make ENABLE_EXT_F=0 ENABLE_SDL=0 ENABLE_JIT=0 | |
| - name: run scan-build with JIT | |
| env: | |
| LATEST_RELEASE: dummy | |
| run: | | |
| make ENABLE_JIT=1 distclean && scan-build-18 -v -o ~/scan-build --status-bugs --use-cc=clang-18 --force-analyze-debug-code --show-description -analyzer-config stable-report-filename=true -enable-checker valist,nullability make ENABLE_EXT_F=0 ENABLE_SDL=0 ENABLE_JIT=1 | |
| # https://docs.docker.com/build/ci/github-actions/multi-platform/ | |
| docker-hub-build-and-publish: | |
| needs: [detect-code-related-file-changes] | |
| if: needs.detect-code-related-file-changes.outputs.has_code_related_changes == 'true' | |
| timeout-minutes: 60 | |
| runs-on: ubuntu-24.04 | |
| steps: | |
| - name: Check out the repo | |
| uses: actions/checkout@v4 | |
| with: | |
| submodules: 'true' | |
| - name: Set up QEMU | |
| uses: docker/setup-qemu-action@v3 | |
| - name: Set up Docker Buildx | |
| uses: docker/setup-buildx-action@v3 | |
| - name: Login to Docker Hub | |
| uses: docker/login-action@v3 | |
| if: github.event_name == 'push' | |
| with: | |
| username: ${{ secrets.DOCKERHUB_USERNAME }} | |
| password: ${{ secrets.DOCKERHUB_ACCESS_TOKEN }} | |
| - name: Get short commit SHA1 | |
| if: github.event_name == 'push' | |
| shell: bash | |
| run: | | |
| echo "short_hash=$(git rev-parse --short "$GITHUB_SHA")" >> "$GITHUB_ENV" | |
| - name: Build and push | |
| if: github.event_name == 'push' | |
| uses: docker/build-push-action@v6 | |
| with: | |
| push: true | |
| context: . | |
| platforms: linux/amd64,linux/arm64/v8 | |
| tags: sysprog21/rv32emu:latest, sysprog21/rv32emu:${{ env.short_hash }} |