diff --git a/.github/workflows/unit-tests.yml b/.github/workflows/unit-tests.yml index db5419ce4..527bc9f61 100644 --- a/.github/workflows/unit-tests.yml +++ b/.github/workflows/unit-tests.yml @@ -19,23 +19,20 @@ concurrency: jobs: - test: - name: "Unit tests" - runs-on: ubuntu-24.04 + prepare: + name: "Armbian configurator unit tests" + runs-on: "ubuntu-24.04" outputs: - matrix: ${{steps.json.outputs.JSON_CONTENT}} + DEPLOYMENT_MATRIX: "${{ steps.json.outputs.DEPLOYMENT_MATRIX }}" steps: - name: Checkout uses: actions/checkout@v4 - with: - path: 'config' - name: Get changed files id: changed-files uses: tj-actions/changed-files@v45 with: - path: config files: | tests/*.conf @@ -43,20 +40,16 @@ jobs: id: json run: | - echo 'JSON_CONTENT<> $GITHUB_OUTPUT - # define docker images where we will run test install - dockerimages=("debian:bookworm" "ubuntu:jammy" "ubuntu:noble") - - # go to repo folder - cd config - + delimiter="$(openssl rand -hex 8)" + echo "DEPLOYMENT_MATRIX<<${delimiter}" >> "${GITHUB_OUTPUT}" + # define OS variants where we can run test install + images=("bookworm" "jammy" "noble") # read tests cases if [[ -n "${{ steps.changed-files.outputs.all_changed_files }}" ]]; then tests=($(grep -rwl ${{ steps.changed-files.outputs.all_changed_files }} -e "ENABLED=true" | cut -d":" -f1)) else tests=($(grep -rwl tests/*.conf -e "ENABLED=true" | cut -d":" -f1)) fi - # loop enabled test cases for i in "${tests[@]}"; do unset RELEASE @@ -64,91 +57,80 @@ jobs: if [[ -z "${RELEASE}" ]]; then RELEASE=all; fi # if we speficy releases, we need to loop docker images and use if there is a match if [[ $RELEASE != all || -z $RELEASE ]]; then - for j in ${dockerimages[@]}; do + for j in ${images[@]}; do elements=($(echo $RELEASE | tr ':' "\n")) + testid=($(echo $i | cut -d"/" -f2 | cut -d"." -f1)) for SELECTED_RELEASE in "${elements[@]}"; do if [[ $j == *"${SELECTED_RELEASE}"* ]]; then - echo "{\"package\":\"${i}\",\"image\":\"$j\"}" + echo "{\"package\":\"${i}\",\"os\":\"$j\",\"id\":\"$testid\"}" fi done done else - for j in ${dockerimages[@]}; do - echo "{\"package\":\"${i}\",\"image\":\"$j\"}" + for j in ${images[@]}; do + testid=($(echo $i | cut -d"/" -f2 | cut -d"." -f1)) + echo "{\"package\":\"${i}\",\"os\":\"$j\",\"id\":\"$testid\"}" done fi - done | jq -s >> $GITHUB_OUTPUT - echo 'EOF' >> $GITHUB_OUTPUT + echo "${delimiter}" >> "${GITHUB_OUTPUT}" gradle: - needs: test - if: ${{ needs.test.outputs.matrix != '[]' && needs.test.outputs.matrix != '' }} + needs: prepare + if: ${{ needs.prepare.outputs.DEPLOYMENT_MATRIX != '[]' }} strategy: fail-fast: false max-parallel: 32 matrix: - image: ${{ fromJSON(needs.test.outputs.matrix) }} - - name: "I" - runs-on: ubuntu-24.04 + server: ${{ fromJSON(needs.prepare.outputs.DEPLOYMENT_MATRIX) }} + name: "${{ matrix.server.id }} on Armbian ${{ matrix.server.os }}" + runs-on: "${{ matrix.server.os }}" timeout-minutes: 7 - container: - image: "${{ matrix.image.image }}" steps: - - name: Checkout + - name: "Install dependencies: fastfetch" + run: sudo apt-get -y install fastfetch + + - name: "Checkout Armbian configuration tool" uses: actions/checkout@v4 with: path: 'config' - - name: Install + - name: "${{ env.DESCRIPTION }}" + run: | + fastfetch + + - name: "Run unit test: ${{ matrix.server.id }} " + run: | + + export TERM=linux + rm -rf test + mkdir -p test + cd config + bash tools/config-assemble.sh -p + RAWCOMMAND=$(./bin/armbian-config --cmd | grep "${{ matrix.server.id }}" | xargs) + COMMAND=$(echo $RAWCOMMAND | cut -d" " -f1,2) + DESCRIPTION=$(echo $RAWCOMMAND | cut -d" " -f4-) + echo "DESCRIPTION=$DESCRIPTION" >> "${GITHUB_ENV}" + source "${{ matrix.server.package }}" + + # Test case execution + start_time=$(date +%s) + figlet "RUN TEST CASE" + testcase # function inside test script + finish_time=$(date +%s) + + # Generate table entry + echo "|${{ matrix.server.os }}|\`armbian-config ${COMMAND}\`| ${DESCRIPTION} | $((finish_time - start_time)) sec |" > ../test/${{ matrix.server.id }}-${{ matrix.server.os }} + + - name: "${{ env.DESCRIPTION }}" run: | + fastfetch - mkdir -p test - - RELEASE=$(echo "${{ matrix.image.image }}" | cut -d":" -f2) - TEST_ID=$(echo "${{ matrix.image.package }}" | cut -d "/" -f2 | cut -d "." -f1) - - # store to GH environment - echo "TEST_ID=${TEST_ID}" >> $GITHUB_ENV - echo "RELEASE=${RELEASE}" >> $GITHUB_ENV - - # update index - apt update - # install basics - DEBIAN_FRONTEND=noninteractive TZ=Etc/UTC apt-get -y install tzdata keyboard-configuration wget gpg netcat-traditional lsof - - # add armbian repository - URL=apt.armbian.com - wget https://${URL}/armbian.key -O key - gpg --dearmor < key | tee /usr/share/keyrings/armbian.gpg > /dev/null - chmod go+r /usr/share/keyrings/armbian.gpg - echo "deb [signed-by=/usr/share/keyrings/armbian.gpg] http://${{ env.REPOSITORY }} $RELEASE main ${RELEASE}-utils ${RELEASE}-desktop" | tee /etc/apt/sources.list.d/armbian.list - apt update -y - apt upgrade -y - apt -y -o Dpkg::Options::="--force-confold" install sudo procps systemd whiptail jq lsb-release iproute2 armbian-bsp-cli-wsl2-x86-current-grub - sudo -b unshare --pid --fork --mount-proc /lib/systemd/systemd --system-unit=basic.target - - # install packages / except howdy as its too large - export DEBIAN_FRONTEND=noninteractive - cd config - bash tools/config-assemble.sh -p - #eval $"( "${PREINSTALL}" )" - eval "$PREINSTALL" - sudo bash bin/armbian-config --cmd "$TEST_ID" - #eval $"( "${CONDITION}" )" - eval "$CONDITION" - - RAWCOMMAND=$(bash bin/armbian-config --cmd | grep "${TEST_ID}" | xargs) - COMMAND=$(echo $RAWCOMMAND | cut -d" " -f1,2) - DESCRIPTION=$(echo $RAWCOMMAND | cut -d" " -f4-) - echo "|${RELEASE}|\`armbian-config ${COMMAND}\`| ${DESCRIPTION} |" > ../test/${TEST_ID}-${RELEASE} - - - name: "Upload ${{ env.TEST_ID }} for ${{ env.RELEASE }}" + - name: "Upload test summary" uses: actions/upload-artifact@v4 with: - name: test-${{ env.TEST_ID }}-${{ env.RELEASE }} + name: test-${{ matrix.server.id }}-${{ matrix.server.os }} path: test if-no-files-found: ignore @@ -170,11 +152,11 @@ jobs: run: | echo "# Succesful tests:" >> $GITHUB_STEP_SUMMARY - echo "|Release|Command|Description|" >> $GITHUB_STEP_SUMMARY - echo "|:---|:---|:---|" >> $GITHUB_STEP_SUMMARY + echo "|Release|Command|Description|Duration|" >> $GITHUB_STEP_SUMMARY + echo "|:---|:---|:---|---:|" >> $GITHUB_STEP_SUMMARY cat test/* | sed '$ s/.$//' >> $GITHUB_STEP_SUMMARY - uses: geekyeggo/delete-artifact@v5 with: name: | - test-* + test-* \ No newline at end of file diff --git a/bin/armbian-config b/bin/armbian-config index 30590e663..ea10907eb 100755 --- a/bin/armbian-config +++ b/bin/armbian-config @@ -1,7 +1,8 @@ #!/bin/bash -tput init -# +# initializes the terminal from TERM if stdin is a terminal +[[ -t 0 ]] && tput init + # Language-based variable assignment for script directory path # This serves as a Rosetta Stone for developers, # allowing them to use the variable name they are most comfortable with. diff --git a/tests/CON002.conf b/tests/CON002.conf deleted file mode 100644 index 57f7cf42e..000000000 --- a/tests/CON002.conf +++ /dev/null @@ -1,3 +0,0 @@ -ENABLED=true -RELEASE="bookworm:jammy:noble" -CONDITION="docker run hello-world" diff --git a/tests/CON005.conf b/tests/CON005.conf index 0493851cb..31331da59 100644 --- a/tests/CON005.conf +++ b/tests/CON005.conf @@ -1,3 +1,8 @@ ENABLED=true -RELEASE="bookworm:jammy:noble" -CONDITION="test=\$(docker container ls -a | grep portainer )" +RELEASE="bookworm:noble" + +function testcase { + ./bin/armbian-config --api module_portainer remove + ./bin/armbian-config --api module_portainer status + echo $? +} diff --git a/tests/DAT001.conf b/tests/DAT001.conf new file mode 100644 index 000000000..478655ea4 --- /dev/null +++ b/tests/DAT001.conf @@ -0,0 +1,7 @@ +ENABLED=false + +function testcase { + ./bin/armbian-config --api module_mariadb install + ./bin/armbian-config --api module_mariadb status + docker container ls -a +} diff --git a/tests/HAB001.conf b/tests/HAB001.conf index af065d462..3825313c1 100644 --- a/tests/HAB001.conf +++ b/tests/HAB001.conf @@ -1,2 +1,7 @@ ENABLED=true -CONDITION="[ -f /lib/systemd/system/openhab.service ]" +RELEASE="bookworm" + +function testcase { + ./bin/armbian-config --api module_openhab install + systemctl is-active --quiet openhab.service +} diff --git a/tests/HAS001.conf b/tests/HAS001.conf new file mode 100644 index 000000000..ca200ad91 --- /dev/null +++ b/tests/HAS001.conf @@ -0,0 +1,6 @@ +ENABLED=false +RELEASE="bookworm" + +function testcase { + ./bin/armbian-config --api module_haos install +} diff --git a/tests/MAN001.conf b/tests/MAN001.conf index a7a1f41bd..a7bbbe90b 100644 --- a/tests/MAN001.conf +++ b/tests/MAN001.conf @@ -1,4 +1,9 @@ ENABLED=true -PREINSTALL="./bin/armbian-config --api module_cockpit install" in order to satisfy test case -CONDITION="[ -f /usr/bin/cockpit-bridge ]" -RELEASE="bookworm:jammy:noble" run on specific or leave empty to run on all +RELEASE="bookworm:noble" # run on specific or leave empty to run on all + +function testcase { + ./bin/armbian-config --api module_cockpit remove + ./bin/armbian-config --api module_cockpit install + [ -f /usr/bin/cockpit-bridge ] +} + diff --git a/tests/MAN002.conf b/tests/MAN002.conf deleted file mode 100644 index f201b7b25..000000000 --- a/tests/MAN002.conf +++ /dev/null @@ -1,4 +0,0 @@ -ENABLED=false -PREINSTALL="./bin/armbian-config --api module_cockpit purge" in order to satisfy test case -CONDITION="[ ! -f /usr/bin/cockpit-bridge ]" -RELEASE="bookworm:jammy:noble" run on specific or leave empty to run on all diff --git a/tests/MON001.conf b/tests/MON001.conf index d8a5c0e39..92b1f676e 100644 --- a/tests/MON001.conf +++ b/tests/MON001.conf @@ -1,3 +1,10 @@ ENABLED=true -RELEASE="bookworm:jammy:noble" -CONDITION="test=\$(docker container ls -a | grep uptime-kuma )" +RELEASE="bookworm:noble" + +function testcase { + ./bin/armbian-config --api module_uptimekuma remove + ./bin/armbian-config --api module_uptimekuma install + ./bin/armbian-config --api module_uptimekuma status + ./bin/armbian-config --api module_uptimekuma remove + ./bin/armbian-config --api module_uptimekuma status +} diff --git a/tests/NET001.conf b/tests/NET001.conf deleted file mode 100644 index aa6a8b91a..000000000 --- a/tests/NET001.conf +++ /dev/null @@ -1,2 +0,0 @@ -ENABLED=true -CONDITION="command -v nload" diff --git a/tests/README.md b/tests/README.md index 01217f85e..d35c10654 100644 --- a/tests/README.md +++ b/tests/README.md @@ -1,7 +1,19 @@ # Unit tests -- name of the the file is function ID. +If function testcase returns 0, test is succesful. Put the code there. + +- name of the the file is function ID.conf - ENABLED=false|true -- PREINSTALL="cmd" in order to satisfy test case -- CONDITION must return 0 for test success - RELEASE="bookworm:jammy:noble" run on specific or leave empty to run on all + +Example: + +``` +ENABLED=true +RELEASE="bookworm:noble" + +function testcase { + ./bin/armbian-config --api module_cockpit install + [ -f /usr/bin/cockpit-bridge ] +} +```