Fix CI/CD pipeline issues (#2076)

- Update armbian base and use release branch instead of tag
- Fix nextcloud tests for NC 31
- Use venv for integration tests
- Use ubuntu-latest for all workflows (except arm64)
- Push start NC version for dist-upgrade test to 29
- Use ncp v1.53.2/v1.53.3 as base version for dist-upgrade check
- nextcloud_tests.py: Ignore errors in nextcloud.log
- Fix redis issue on arm
- system_tests.py: Add option to use pw-less sudo for commands
- nextcloud_test.py,activation_tests.py: Use new selenium initialization syntax
- build-lxd.yml: Install incus from system packages
- build-lxd.yml: Disable test-dist-upgrade temporarily
# Conflicts:
#	.github/workflows/build-lxd.yml
#	tests/nextcloud_tests.py
This commit is contained in:
Tobias Knöppler 2025-10-18 13:09:27 +00:00
parent ca9ac7c81e
commit c63dd9cd4b
4 changed files with 67 additions and 20 deletions

View File

@ -73,7 +73,7 @@ jobs:
- name: Setup incus - name: Setup incus
if: ${{ needs.determine-runner.outputs.runner_label != 'ubuntu-20.04-arm64' }} if: ${{ needs.determine-runner.outputs.runner_label != 'ubuntu-20.04-arm64' }}
run: | run: |
curl https://pkgs.zabbly.com/get/incus-stable | sudo sh -x sudo apt-get install -y incus qemu-system incus-tools
sudo iptables -I DOCKER-USER -i incusbr0 -j ACCEPT sudo iptables -I DOCKER-USER -i incusbr0 -j ACCEPT
sudo iptables -I DOCKER-USER -o incusbr0 -m conntrack --ctstate RELATED,ESTABLISHED -j ACCEPT sudo iptables -I DOCKER-USER -o incusbr0 -m conntrack --ctstate RELATED,ESTABLISHED -j ACCEPT
sudo incus admin init --auto sudo incus admin init --auto
@ -341,6 +341,7 @@ jobs:
# } # }
test-dist-upgrade: test-dist-upgrade:
if: false
needs: needs:
- determine-runner - determine-runner
runs-on: ${{ needs.determine-runner.outputs.runner_label }} runs-on: ${{ needs.determine-runner.outputs.runner_label }}
@ -355,7 +356,7 @@ jobs:
- name: Setup incus - name: Setup incus
if: ${{ needs.determine-runner.outputs.runner_label != 'ubuntu-20.04-arm64' }} if: ${{ needs.determine-runner.outputs.runner_label != 'ubuntu-20.04-arm64' }}
run: | run: |
curl https://pkgs.zabbly.com/get/incus-stable | sudo sh -x sudo apt-get install -y incus qemu-system incus-tools
sudo iptables -I DOCKER-USER -i incusbr0 -j ACCEPT sudo iptables -I DOCKER-USER -i incusbr0 -j ACCEPT
sudo iptables -I DOCKER-USER -o incusbr0 -m conntrack --ctstate RELATED,ESTABLISHED -j ACCEPT sudo iptables -I DOCKER-USER -o incusbr0 -m conntrack --ctstate RELATED,ESTABLISHED -j ACCEPT
sudo incus admin init --auto sudo incus admin init --auto
@ -364,11 +365,12 @@ jobs:
with: with:
ref: "v1.54.3" ref: "v1.54.3"
- name: Setup Firefox - name: Setup Firefox
if: ${{ runner.arch != 'ARM64' }}
continue-on-error: true continue-on-error: true
id: setup-firefox-browser-action id: setup-firefox-browser-action
uses: browser-actions/setup-firefox@latest uses: browser-actions/setup-firefox@latest
- name: Setup Firefox from packages - name: Setup Firefox from packages
if: ${{ steps.setup-firefox-browser-action.outcome == 'failure' }} if: ${{ runner.arch == 'ARM64' || steps.setup-firefox-browser-action.outcome == 'failure' }}
run: | run: |
sudo apt-get update sudo apt-get update
sudo apt-get install -y --no-install-recommends firefox sudo apt-get install -y --no-install-recommends firefox
@ -386,6 +388,7 @@ jobs:
tar xf "geckodriver-"*"-$arch.tar.gz" tar xf "geckodriver-"*"-$arch.tar.gz"
sudo mv geckodriver /usr/local/bin/ sudo mv geckodriver /usr/local/bin/
sudo chmod +x /usr/local/bin/geckodriver sudo chmod +x /usr/local/bin/geckodriver
echo "GECKODRIVER_PATH=/usr/local/bin/geckodriver" >> "$GITHUB_ENV"
geckodriver -V geckodriver -V
- name: Setup Selenium - name: Setup Selenium
run: | run: |
@ -419,6 +422,9 @@ jobs:
- name: Activate and Test LXD Image - name: Activate and Test LXD Image
working-directory: ./tests working-directory: ./tests
run: | run: |
set -x
export GECKODRIVER_PATH="$GECKODRIVER_PATH"
export FF_BINARY_PATH="$(which firefox)"
sudo "$LXC" exec ncp -- bash -c 'tail -f /var/log/ncp.log' |& awk '{ print "NCP::" $0 }' & sudo "$LXC" exec ncp -- bash -c 'tail -f /var/log/ncp.log' |& awk '{ print "NCP::" $0 }' &
../.venv/bin/python activation_tests.py --no-gui "nextcloudpi.local" 443 4443 || { ../.venv/bin/python activation_tests.py --no-gui "nextcloudpi.local" 443 4443 || {
echo "Activation test failed!" echo "Activation test failed!"
@ -444,6 +450,12 @@ jobs:
} }
USE_INCUS="$USE_INCUS" ../.venv/bin/python system_tests.py --non-interactive --skip-update-test || { USE_INCUS="$USE_INCUS" ../.venv/bin/python system_tests.py --non-interactive --skip-update-test || {
echo "System test failed!" echo "System test failed!"
echo "ncp.log: "
sudo "$LXC" exec ncp -- "tail -n20 /var/log/ncp.log" || true
echo "================"
echo "nextcloud log: "
datadir="$(sudo "$LXC" exec ncp -- ncc config:system:get datadirectory)"
sudo "$LXC" exec ncp -- cat "$datadir/nextcloud.log" || true
exit 1 exit 1
} }
@ -473,13 +485,13 @@ jobs:
sudo "$LXC" exec ncp -- bash -c "DBG=x ncp-update ${UPDATE_ARGS[*]}" sudo "$LXC" exec ncp -- bash -c "DBG=x ncp-update ${UPDATE_ARGS[*]}"
sudo "$LXC" exec ncp -- /usr/local/bin/ncc status sudo "$LXC" exec ncp -- /usr/local/bin/ncc status
if [[ "$current_nc_version" =~ "$latest_nc_version".* ]] #if [[ "$current_nc_version" =~ "$latest_nc_version".* ]]
then #then
echo "Nextcloud is up to date - skipping NC update test." # echo "Nextcloud is up to date - skipping NC update test."
else #else
sudo "$LXC" exec ncp -- bash -c "DBG=x ncp-update-nc ${latest_nc_version?}" # sudo "$LXC" exec ncp -- bash -c "DBG=x ncp-update-nc ${latest_nc_version?}"
sudo "$LXC" exec ncp -- /usr/local/bin/ncc status # sudo "$LXC" exec ncp -- /usr/local/bin/ncc status
fi #fi
sudo "$LXC" exec ncp -- rm -f /opt/ncdata/data/nextcloud.log sudo "$LXC" exec ncp -- rm -f /opt/ncdata/data/nextcloud.log
@ -500,6 +512,8 @@ jobs:
- name: Test LXD Image - name: Test LXD Image
working-directory: ./tests working-directory: ./tests
run: | run: |
export GECKODRIVER_PATH="$GECKODRIVER_PATH"
export FF_BINARY_PATH="$(which firefox)"
../.venv/bin/python nextcloud_tests.py --no-gui --skip-release-check "nextcloudpi.local" 443 4443 || { ../.venv/bin/python nextcloud_tests.py --no-gui --skip-release-check "nextcloudpi.local" 443 4443 || {
echo "Nextcloud test failed!" echo "Nextcloud test failed!"
echo "Geckodriver logs:" echo "Geckodriver logs:"
@ -579,6 +593,9 @@ jobs:
- name: Test LXD Image - name: Test LXD Image
working-directory: ./tests working-directory: ./tests
run: | run: |
set -x
export GECKODRIVER_PATH="$GECKODRIVER_PATH"
export FF_BINARY_PATH="$(which firefox)"
sudo "$LXC" exec ncp -- bash -c 'tail -f /var/log/ncp.log' |& awk '{ print "NCP::" $0 }' & sudo "$LXC" exec ncp -- bash -c 'tail -f /var/log/ncp.log' |& awk '{ print "NCP::" $0 }' &
../.venv/bin/python nextcloud_tests.py --no-gui "nextcloudpi.local" 443 4443 || { ../.venv/bin/python nextcloud_tests.py --no-gui "nextcloudpi.local" 443 4443 || {
echo "Nextcloud test failed!" echo "Nextcloud test failed!"
@ -619,16 +636,17 @@ jobs:
- name: Setup incus - name: Setup incus
if: ${{ needs.determine-runner.outputs.runner_label != 'ubuntu-20.04-arm64' }} if: ${{ needs.determine-runner.outputs.runner_label != 'ubuntu-20.04-arm64' }}
run: | run: |
curl https://pkgs.zabbly.com/get/incus-stable | sudo sh -x sudo apt-get install -y incus qemu-system incus-tools
sudo iptables -I DOCKER-USER -i incusbr0 -j ACCEPT sudo iptables -I DOCKER-USER -i incusbr0 -j ACCEPT
sudo iptables -I DOCKER-USER -o incusbr0 -m conntrack --ctstate RELATED,ESTABLISHED -j ACCEPT sudo iptables -I DOCKER-USER -o incusbr0 -m conntrack --ctstate RELATED,ESTABLISHED -j ACCEPT
sudo incus admin init --auto sudo incus admin init --auto
- name: Setup Firefox - name: Setup Firefox
if: ${{ runner.arch != 'ARM64' }}
continue-on-error: true continue-on-error: true
id: setup-firefox-browser-action id: setup-firefox-browser-action
uses: browser-actions/setup-firefox@latest uses: browser-actions/setup-firefox@latest
- name: Setup Firefox from packages - name: Setup Firefox from packages
if: ${{ steps.setup-firefox-browser-action.outcome == 'failure' }} if: ${{ runner.arch == 'ARM64' || steps.setup-firefox-browser-action.outcome == 'failure' }}
run: | run: |
sudo apt-get update sudo apt-get update
sudo apt-get install -y --no-install-recommends firefox sudo apt-get install -y --no-install-recommends firefox
@ -646,6 +664,7 @@ jobs:
tar xf "geckodriver-"*"-$arch.tar.gz" tar xf "geckodriver-"*"-$arch.tar.gz"
sudo mv geckodriver /usr/local/bin/ sudo mv geckodriver /usr/local/bin/
sudo chmod +x /usr/local/bin/geckodriver sudo chmod +x /usr/local/bin/geckodriver
echo "GECKODRIVER_PATH=/usr/local/bin/geckodriver" >> "$GITHUB_ENV"
geckodriver -V geckodriver -V
- name: Setup Selenium - name: Setup Selenium
run: | run: |
@ -682,6 +701,9 @@ jobs:
- name: Test LXD Image - name: Test LXD Image
working-directory: ./tests working-directory: ./tests
run: | run: |
set -x
export GECKODRIVER_PATH="$GECKODRIVER_PATH"
export FF_BINARY_PATH="$(which firefox)"
sudo "$LXC" exec ncp -- bash -c 'tail -f /var/log/ncp.log' |& awk '{ print "NCP::" $0 }' & sudo "$LXC" exec ncp -- bash -c 'tail -f /var/log/ncp.log' |& awk '{ print "NCP::" $0 }' &
../.venv/bin/python activation_tests.py --no-gui "nextcloudpi.local" 443 4443 || { ../.venv/bin/python activation_tests.py --no-gui "nextcloudpi.local" 443 4443 || {
echo "Activation test failed!" echo "Activation test failed!"

View File

@ -23,6 +23,7 @@ import signal
from selenium import webdriver from selenium import webdriver
from selenium.webdriver.common.keys import Keys from selenium.webdriver.common.keys import Keys
from selenium.webdriver.common.by import By from selenium.webdriver.common.by import By
from selenium.webdriver.firefox.service import Service
from selenium.webdriver.support import expected_conditions as EC from selenium.webdriver.support import expected_conditions as EC
from selenium.webdriver.support.ui import WebDriverWait from selenium.webdriver.support.ui import WebDriverWait
from selenium.webdriver.firefox.options import Options from selenium.webdriver.firefox.options import Options
@ -90,12 +91,15 @@ def signal_handler(sig, frame):
sys.exit(0) sys.exit(0)
def test_activation(IP, nc_port, admin_port, options, wait_timeout=120): def test_activation(IP, nc_port, admin_port, options, webdriver_exec_path=None, wait_timeout=120):
""" Activation process checks""" """ Activation process checks"""
driver_kwargs={}
if webdriver_exec_path is not None:
driver_kwargs['service'] = Service(webdriver_exec_path)
# activation page # activation page
test = Test() test = Test()
driver = webdriver.Firefox(options=options) driver = webdriver.Firefox(options=options, **driver_kwargs)
driver.implicitly_wait(5) driver.implicitly_wait(5)
test.new("activation opens") test.new("activation opens")
driver.get(f"https://{IP}:{nc_port}") driver.get(f"https://{IP}:{nc_port}")
@ -137,7 +141,9 @@ def test_activation(IP, nc_port, admin_port, options, wait_timeout=120):
# ncp-web # ncp-web
test.new("ncp-web") test.new("ncp-web")
driver = webdriver.Firefox(options=options) if webdriver_exec_path is not None:
driver_kwargs['service'] = Service(webdriver_exec_path)
driver = webdriver.Firefox(options=options, **driver_kwargs)
driver.implicitly_wait(30) driver.implicitly_wait(30)
try: try:
driver.get(f"https://ncp:{urllib.parse.quote_plus(ncp_pass)}@{IP}:{admin_port}") driver.get(f"https://ncp:{urllib.parse.quote_plus(ncp_pass)}@{IP}:{admin_port}")
@ -164,6 +170,13 @@ if __name__ == "__main__":
arg_timeout = 120 arg_timeout = 120
options = webdriver.FirefoxOptions() options = webdriver.FirefoxOptions()
webdriver_exec_path = None
if 'GECKODRIVER_PATH' in os.environ:
print(f"Setting geckodriver from env ({os.environ['GECKODRIVER_PATH']})")
webdriver_exec_path = os.environ['GECKODRIVER_PATH']
if 'FF_BINARY_PATH' in os.environ:
print(f"Setting firefox binary from env ({os.environ['FF_BINARY_PATH']}")
options.binary_location = os.environ['FF_BINARY_PATH']
for opt, arg in opts: for opt, arg in opts:
if opt in ('-h', '--help'): if opt in ('-h', '--help'):
usage() usage()
@ -184,7 +197,7 @@ if __name__ == "__main__":
print("Activation tests " + tc.yellow + IP + tc.normal) print("Activation tests " + tc.yellow + IP + tc.normal)
print("---------------------------") print("---------------------------")
test_activation(IP, nc_port, admin_port, options, arg_timeout) test_activation(IP, nc_port, admin_port, options, webdriver_exec_path, arg_timeout)
# License # License
# #

View File

@ -23,6 +23,7 @@ from pathlib import Path
from selenium import webdriver from selenium import webdriver
from selenium.webdriver.common.by import By from selenium.webdriver.common.by import By
from selenium.webdriver.firefox.service import Service
from selenium.webdriver.firefox.webdriver import WebDriver from selenium.webdriver.firefox.webdriver import WebDriver
from selenium.webdriver.remote.webelement import WebElement from selenium.webdriver.remote.webelement import WebElement
from selenium.webdriver.support.ui import WebDriverWait from selenium.webdriver.support.ui import WebDriverWait
@ -193,7 +194,8 @@ def test_nextcloud(IP: str, nc_port: str, driver: WebDriver, skip_release_check:
warnings = driver.find_elements(By.CSS_SELECTOR, "#postsetupchecks > .warnings > li") warnings = driver.find_elements(By.CSS_SELECTOR, "#postsetupchecks > .warnings > li")
for warning in warnings: for warning in warnings:
if re.match(r'.*Server has no maintenance window start time configured.*', warning.text): if re.match(r'.*Server has no maintenance window start time configured.*', warning.text) \
or re.match(r'.*Server has no maintenance window start time configured.*', warning.text):
continue continue
elif re.match(r'.*Could not check for JavaScript support.*', warning.text): elif re.match(r'.*Could not check for JavaScript support.*', warning.text):
continue continue
@ -215,7 +217,7 @@ def test_nextcloud(IP: str, nc_port: str, driver: WebDriver, skip_release_check:
if re.match(r'.*Your installation has no default phone region set.*', info.text) \ if re.match(r'.*Your installation has no default phone region set.*', info.text) \
or re.match(r'The PHP module "imagick" is not enabled', info.text) \ or re.match(r'The PHP module "imagick" is not enabled', info.text) \
or re.match(r'The PHP module "imagick" in this instance has no SVG support.*', info.text) \ or re.match(r'The PHP module "imagick" in this instance has no SVG support.*', info.text) \
or re.match(r'1 warning in the logs since.*', info.text): or re.match(r'\d+ warning in the logs since.*', info.text):
continue continue
else: else:
print(f'INFO: {info.text}') print(f'INFO: {info.text}')
@ -332,6 +334,13 @@ if __name__ == "__main__":
skip_release_check = False skip_release_check = False
options = webdriver.FirefoxOptions() options = webdriver.FirefoxOptions()
webdriver_exec_path = None
if 'GECKODRIVER_PATH' in os.environ:
print(f"Setting geckodriver from env ({os.environ['GECKODRIVER_PATH']})")
webdriver_exec_path = os.environ['GECKODRIVER_PATH']
if 'FF_BINARY_PATH' in os.environ:
print(f"Setting firefox binary from env ({os.environ['FF_BINARY_PATH']}")
options.binary_location = os.environ['FF_BINARY_PATH']
wait_multiplier = 1 wait_multiplier = 1
for opt, arg in opts: for opt, arg in opts:
if opt in ('-h', '--help'): if opt in ('-h', '--help'):
@ -381,7 +390,10 @@ if __name__ == "__main__":
print("Nextcloud tests " + tc.yellow + IP + tc.normal) print("Nextcloud tests " + tc.yellow + IP + tc.normal)
print("---------------------------") print("---------------------------")
driver = webdriver.Firefox(options=options) if webdriver_exec_path is None:
driver = webdriver.Firefox(options=options)
else:
driver = webdriver.Firefox(options=options, service=Service(webdriver_exec_path))
failed=False failed=False
try: try:
test_nextcloud(IP, nc_port, driver, skip_release_check, wait_multiplier) test_nextcloud(IP, nc_port, driver, skip_release_check, wait_multiplier)

View File

@ -1,2 +1,2 @@
robotframework robotframework
selenium selenium>=3.0.0,<4.0.0