diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 5fac3475..657a04d8 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -1931,9 +1931,202 @@ jobs: path: test/twister-out/twister.xml # Post test result check + test-downloader-fallback: + name: Test Downloader Fallback (${{ matrix.os }}, ${{ matrix.scenario }}) + needs: [ setup, build-dist-bundle ] + runs-on: ${{ matrix.runner }} + + strategy: + fail-fast: false + matrix: + include: + # Test curl fallback on Windows (remove wget) + - os: windows + runner: windows-2022 + scenario: curl-only + bundle-host: windows-x86_64 + bundle-archive: 7z + toolchain: arm-zephyr-eabi + + # Test wget on Windows (explicit /dl wget flag) + - os: windows + runner: windows-2022 + scenario: wget-explicit + bundle-host: windows-x86_64 + bundle-archive: 7z + toolchain: arm-zephyr-eabi + + # Test curl explicit on Windows + - os: windows + runner: windows-2022 + scenario: curl-explicit + bundle-host: windows-x86_64 + bundle-archive: 7z + toolchain: arm-zephyr-eabi + + # Test curl fallback on macOS (no wget by default) + - os: macos + runner: macos-13 + scenario: curl-fallback + bundle-host: macos-x86_64 + bundle-archive: tar.xz + toolchain: arm-zephyr-eabi + + # Test curl fallback on Linux (remove wget) + - os: linux + runner: ubuntu-24.04 + scenario: curl-only + bundle-host: linux-x86_64 + bundle-archive: tar.xz + toolchain: arm-zephyr-eabi + + defaults: + run: + shell: bash + + steps: + - name: Check out source code + if: ${{ github.event_name != 'pull_request_target' }} + uses: actions/checkout@v4 + with: + fetch-depth: 0 + persist-credentials: false + + - name: Check out source code (pull request) + if: ${{ github.event_name == 'pull_request_target' }} + uses: actions/checkout@v4 + with: + ref: ${{ github.event.pull_request.head.sha }} + fetch-depth: 0 + persist-credentials: false + + - name: Set up test environment (Windows) + if: ${{ matrix.os == 'windows' }} + run: | + # Install required packages (excluding wget for curl-only test) + if [ "${{ matrix.scenario }}" == "curl-only" ]; then + choco install cmake 7zip + echo "Testing curl-only fallback (wget not installed)" + elif [ "${{ matrix.scenario }}" == "wget-explicit" ]; then + choco install cmake 7zip wget + echo "Testing explicit wget flag" + elif [ "${{ matrix.scenario }}" == "curl-explicit" ]; then + choco install cmake 7zip + echo "Testing explicit curl flag" + fi + + # Verify which tools are available + echo "=== Available download tools ===" + which wget && echo "wget: $(which wget)" || echo "wget: NOT FOUND" + which curl && echo "curl: $(which curl)" || echo "curl: NOT FOUND" + echo "================================" + + - name: Set up test environment (macOS) + if: ${{ matrix.os == 'macos' }} + run: | + # macOS has curl by default but not wget + echo "Testing curl fallback on macOS (wget not installed by default)" + + # Verify which tools are available + echo "=== Available download tools ===" + which wget && echo "wget: $(which wget)" || echo "wget: NOT FOUND" + which curl && echo "curl: $(which curl)" || echo "curl: NOT FOUND" + echo "================================" + + - name: Set up test environment (Linux) + if: ${{ matrix.os == 'linux' }} + run: | + # Remove wget to force curl fallback + if [ "${{ matrix.scenario }}" == "curl-only" ]; then + sudo apt-get remove -y wget + echo "Testing curl-only fallback (wget removed)" + fi + + # Verify which tools are available + echo "=== Available download tools ===" + which wget && echo "wget: $(which wget)" || echo "wget: NOT FOUND" + which curl && echo "curl: $(which curl)" || echo "curl: NOT FOUND" + echo "================================" + + - name: Download version information + uses: actions/download-artifact@v4 + with: + name: version + path: artifacts + + - name: Resolve distribution bundle name + run: | + VERSION=$(> $GITHUB_ENV + echo "BUNDLE_DIR=${BUNDLE_DIR}" >> $GITHUB_ENV + echo "Testing with bundle: ${BUNDLE_NAME}" + + - name: Download minimal distribution bundle + run: | + # Download minimal bundle for testing (just one toolchain) + gh run download \ + -R ${GITHUB_REPOSITORY} \ + ${GITHUB_RUN_ID} \ + -n ${BUNDLE_NAME} \ + -D artifacts + env: + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + + - name: Extract distribution bundle + run: | + mkdir -p tools + BUNDLE_FILE=${BUNDLE_NAME}_minimal.${{ matrix.bundle-archive }} + + if [ "${{ matrix.bundle-archive }}" == "tar.xz" ]; then + tar -Jxf artifacts/${BUNDLE_FILE} -C tools || true + elif [ "${{ matrix.bundle-archive }}" == "7z" ]; then + 7z x -otools artifacts/${BUNDLE_FILE} || true + fi + + - name: Test setup script with scenario (${{ matrix.scenario }}) + run: | + cd tools/${BUNDLE_DIR} + + if [ "${{ matrix.os }}" == "windows" ]; then + # Windows batch script + if [ "${{ matrix.scenario }}" == "curl-only" ]; then + echo "Testing automatic fallback to curl..." + ./setup.cmd /t ${{ matrix.toolchain }} /c || exit 1 + elif [ "${{ matrix.scenario }}" == "wget-explicit" ]; then + echo "Testing explicit wget..." + ./setup.cmd /t ${{ matrix.toolchain }} /c /dl wget || exit 1 + elif [ "${{ matrix.scenario }}" == "curl-explicit" ]; then + echo "Testing explicit curl..." + ./setup.cmd /t ${{ matrix.toolchain }} /c /dl curl || exit 1 + fi + else + # POSIX shell script + if [ "${{ matrix.scenario }}" == "curl-fallback" ] || [ "${{ matrix.scenario }}" == "curl-only" ]; then + echo "Testing automatic fallback to curl..." + ./setup.sh -t ${{ matrix.toolchain }} -c || exit 1 + fi + fi + + echo "✅ Setup script completed successfully with ${{ matrix.scenario }}" + + - name: Verify toolchain installation + run: | + cd tools/${BUNDLE_DIR} + + # Check that the toolchain was actually installed + if [ -d "gnu/${{ matrix.toolchain }}" ]; then + echo "✅ Toolchain ${{ matrix.toolchain }} installed successfully" + ls -la gnu/${{ matrix.toolchain }} + else + echo "❌ ERROR: Toolchain directory not found!" + exit 1 + fi + test-result: name: Test Result - needs: [ test-dist-bundle ] + needs: [ test-dist-bundle, test-downloader-fallback ] runs-on: ubuntu-24.04 # NOTE: The 'test-result' job depends on the 'test-dist-bundle' job and diff --git a/scripts/template_setup_posix b/scripts/template_setup_posix index 036e27d0..df862407 100644 --- a/scripts/template_setup_posix +++ b/scripts/template_setup_posix @@ -48,6 +48,13 @@ check_command() fi } +# Silently check if command is available (for fallback logic) +check_command_silent() +{ + which $1 &> /dev/null + return $? +} + # Check if the current installation is a full SDK with all GNU toolchains check_full_gnu_sdk() { @@ -60,6 +67,31 @@ check_full_gnu_sdk() return 0 } +# Download helper function +# Usage: download URL OUTFILE +download() +{ + local url="$1" + local outfile="$2" + + if [ "${dl_tool}" = "wget" ]; then + # Emulate quiet+progress+timestamping + wget -q --show-progress -N -O "${outfile}" "${url}" + return $? + else + # curl: -f fail on HTTP errors; -L follow redirects + # --remote-time preserves Last-Modified on the file + # -z OUTFILE does conditional GET (only download if newer) + # --progress-bar shows progress + if [ -f "${outfile}" ]; then + curl -fL --retry 5 --retry-delay 2 --progress-bar --remote-time -z "${outfile}" -o "${outfile}" "${url}" + else + curl -fL --retry 5 --retry-delay 2 --progress-bar --remote-time -o "${outfile}" "${url}" + fi + return $? + fi +} + # Display script usage usage() { @@ -71,6 +103,7 @@ usage() echo " -h Install host tools" echo " -o Create symbolic links matching the old SDK layout for old Zephyr (< 4.3) bisectability" echo " -c Register Zephyr SDK CMake package" + echo " -dl Force downloader (default: wget, fallback to curl)" echo echo "Supported GNU Toolchains:" echo @@ -162,9 +195,20 @@ else -c) do_cmake_pkg="y" ;; + -dl) + shift + if [[ "$1" = "curl" ]]; then + dl_force="curl" + elif [[ "$1" = "wget" ]]; then + dl_force="wget" + else + echo "ERROR: -dl expects " + exit 3 + fi + ;; -o) - do_old_zephyr="y" - ;; + do_old_zephyr="y" + ;; '-?') usage exit 0 @@ -213,7 +257,43 @@ echo # Check dependencies check_command cmake 90 -check_command wget 91 + +# Choose downloader (default: wget; fallback to curl). Allow -dl override. +dl_tool="" + +if [ "${dl_force}" = "curl" ]; then + check_command_silent curl + if [ $? -eq 0 ]; then + dl_tool="curl" + else + echo "ERROR: -dl curl requested but 'curl' not found in PATH." + exit 91 + fi +elif [ "${dl_force}" = "wget" ]; then + check_command_silent wget + if [ $? -eq 0 ]; then + dl_tool="wget" + else + echo "ERROR: -dl wget requested but 'wget' not found in PATH." + exit 91 + fi +else + # Default behavior: prefer wget, else curl + check_command_silent wget + if [ $? -eq 0 ]; then + dl_tool="wget" + else + check_command_silent curl + if [ $? -eq 0 ]; then + dl_tool="curl" + fi + fi +fi + +if [ -z "${dl_tool}" ]; then + echo "Zephyr SDK setup requires either 'wget' or 'curl' in PATH." + exit 91 +fi # Ask for user inputs if no argument is specified if [ "${interactive}" = "y" ]; then @@ -238,7 +318,7 @@ if [ "${do_gnu_toolchain}" = "y" ]; then echo "Installing '${toolchain}' GNU toolchain ..." # Download toolchain archive - wget -q --show-progress -N -O "${toolchain_filename}" "${toolchain_uri}" + download "${toolchain_uri}" "${toolchain_filename}" if [ $? != 0 ]; then rm -f "${toolchain_filename}" echo "ERROR: GNU toolchain download failed" @@ -265,7 +345,7 @@ if [ "${do_llvm_toolchain}" = "y" ] && [ ! -d "llvm" ]; then toolchain_uri="${dl_rel_base}/${toolchain_filename}" # Download toolchain archive - wget -q --show-progress -N -O "${toolchain_filename}" "${toolchain_uri}" + download "${toolchain_uri}" "${toolchain_filename}" if [ $? != 0 ]; then rm -f "${toolchain_filename}" echo "ERROR: LLVM toolchain download failed" diff --git a/scripts/template_setup_win b/scripts/template_setup_win index ebb29a2d..1c8b3519 100644 --- a/scripts/template_setup_win +++ b/scripts/template_setup_win @@ -21,6 +21,11 @@ if [%ERRORLEVEL%] neq [0] ( ) exit /b 0 +REM # Silently check if command is available (for fallback logic) +:check_command_silent +where %1 >nul 2>&1 +exit /b %ERRORLEVEL% + :entry REM # Initialise GNU toolchain list @@ -53,8 +58,7 @@ REM # Check dependencies call :check_command cmake 90 if [%ERRORLEVEL%] neq [0] goto end -call :check_command wget 91 -if [%ERRORLEVEL%] neq [0] goto end + call :check_command 7z 92 if [%ERRORLEVEL%] neq [0] goto end @@ -81,6 +85,17 @@ if /i [%1] equ [/t] ( ) set DO_GNU_TOOLCHAIN=y shift +) else if /i [%1] equ [/dl] ( + if /i [%2] equ [curl] ( + set DL_FORCE=curl + ) else if /i [%2] equ [wget] ( + set DL_FORCE=wget + ) else ( + echo ERROR: /dl expects ^ + set EXITCODE=3 + goto end + ) + shift ) else if /i [%1] equ [/l] ( set DO_LLVM_TOOLCHAIN=y ) else if /i [%1] equ [/h] ( @@ -144,7 +159,71 @@ if [%ERRORLEVEL%] equ [1] set DO_CMAKE_PKG=y echo. +REM # Download helper +REM # usage: call :download URL OUTFILE +:download +setlocal ENABLEDELAYEDEXPANSION +set _URL=%~1 +set _OUT=%~2 + +if /i [%DL_TOOL%] equ [wget] ( + REM Emulate quiet+progress+timestamping: + wget -q --show-progress -N -O "!_OUT!" "!_URL!" + endlocal & exit /b %ERRORLEVEL% +) else ( + REM curl: -f fail on HTTP errors; -L follow redirects + REM --remote-time preserves Last-Modified on the file + REM -z OUTFILE does conditional GET (only download if newer) + REM Replace the --progress-bar with an -sS to make it quiet if needed + if exist "!_OUT!" ( + curl.exe -fL --retry 5 --retry-delay 2 --progress-bar --remote-time -z "!_OUT!" -o "!_OUT!" "!_URL!" + ) else ( + curl.exe -fL --retry 5 --retry-delay 2 --progress-bar --remote-time -o "!_OUT!" "!_URL!" + ) + endlocal & exit /b %ERRORLEVEL% +) + :process +REM # Choose downloader (default: wget; fallback to curl). Allow /dl override. +set DL_TOOL= + +if /i [%DL_FORCE%] equ [curl] ( + call :check_command curl 91 + if [!ERRORLEVEL!] equ [0] ( + set DL_TOOL=curl + ) else ( + echo ERROR: /dl curl requested but 'curl' not found in PATH. + set EXITCODE=91 + goto end + ) +) else if /i [%DL_FORCE%] equ [wget] ( + call :check_command wget 91 + if [!ERRORLEVEL!] equ [0] ( + set DL_TOOL=wget + ) else ( + echo ERROR: /dl wget requested but 'wget' not found in PATH. + set EXITCODE=91 + goto end + ) +) else ( + REM Default behavior: prefer wget, else curl + call :check_command_silent wget + if [!ERRORLEVEL!] equ [0] ( + set DL_TOOL=wget + ) else ( + call :check_command_silent curl + if [!ERRORLEVEL!] equ [0] ( + set DL_TOOL=curl + ) + ) +) + +if [%DL_TOOL%] equ [] ( + echo Zephyr SDK setup requires either 'wget' or 'curl' in PATH. + set EXITCODE=91 + goto end +) + REM # Install GNU toolchains if [%DO_GNU_TOOLCHAIN%] neq [] ( if not exist gnu\ mkdir gnu @@ -158,7 +237,7 @@ if [%DO_GNU_TOOLCHAIN%] neq [] ( echo Installing '%%t' GNU toolchain ... REM # Download toolchain archive - wget -q --show-progress -N -O !TOOLCHAIN_FILENAME! !TOOLCHAIN_URI! + call :download !TOOLCHAIN_URI! !TOOLCHAIN_FILENAME! if [!ERRORLEVEL!] neq [0] ( del /q !TOOLCHAIN_FILENAME! echo ERROR: GNU toolchain download failed @@ -190,7 +269,7 @@ if [%DO_LLVM_TOOLCHAIN%] neq [] ( set TOOLCHAIN_URI=%DL_REL_BASE%/!TOOLCHAIN_FILENAME! REM # Download toolchain archive - wget -q --show-progress -N -O !TOOLCHAIN_FILENAME! !TOOLCHAIN_URI! + call :download !TOOLCHAIN_URI! !TOOLCHAIN_FILENAME! if [!ERRORLEVEL!] neq [0] ( del /q !TOOLCHAIN_FILENAME! echo ERROR: LLVM toolchain download failed @@ -243,6 +322,7 @@ echo all Install all GNU toolchains echo /l Install LLVM toolchain echo /h Install host tools echo /c Register Zephyr SDK CMake package +echo /dl ^ Force downloader (default: wget, fallback to curl) echo. echo Supported GNU Toolchains: echo.