From 7d284e8447f5b3ae17ea6f6e216af11bc4fd71f6 Mon Sep 17 00:00:00 2001 From: Kay0u Date: Sat, 16 May 2020 14:18:52 +0200 Subject: [PATCH 01/62] [enh] build and install deb --- .gitlab-ci.yml | 105 +++++++++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 102 insertions(+), 3 deletions(-) diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml index 23a0075de..b474b92c1 100644 --- a/.gitlab-ci.yml +++ b/.gitlab-ci.yml @@ -1,8 +1,106 @@ stages: + - build + - install - postinstall - tests - lint +######################################## +# BUILD DEB +######################################## + +.build-stage: + image: before-install + stage: build + variables: + YNH_BUILD_DIR: "ynh-build" + YNH_SOURCE: "https://github.com/yunohost" + before_script: + - DEBIAN_FRONTEND=noninteractive apt --assume-yes -o Dpkg::Options::="--force-confold" install git git-buildpackage postfix python-setuptools + - mkdir -p $YNH_BUILD_DIR + - cd $YNH_BUILD_DIR + - git clone $YNH_SOURCE/$DEB_TO_BUILD + - DEBIAN_FRONTEND=noninteractive apt --assume-yes -o Dpkg::Options::="--force-confold" build-dep $(pwd)/$DEB_TO_BUILD + cache: + paths: + - $YNH_BUILD_DIR/*.deb + key: "$CI_COMMIT_REF_SLUG" + +build-yunohost: + extends: .build-stage + variables: + DEB_TO_BUILD: "yunohost" + script: + - cd $DEB_TO_BUILD + - debuild -us -uc + +build-ssowat: + extends: .build-stage + variables: + DEB_TO_BUILD: "ssowat" + script: + - cd $DEB_TO_BUILD + - debuild -us -uc + +build-moulinette: + extends: .build-stage + variables: + DEB_TO_BUILD: "moulinette" + script: + - cd $DEB_TO_BUILD + - debuild -us -uc + +build-metronome: + extends: .build-stage + variables: + DEB_TO_BUILD: "metronome" + script: + - cd $DEB_TO_BUILD + - dpkg-buildpackage -rfakeroot -uc -b -d + +######################################## +# INSTALL DEB +######################################## + +install: + image: before-install + stage: install + variables: + YNH_BUILD_DIR: "ynh-build" + script: + - | + debconf-set-selections << EOF + slapd slapd/password1 password yunohost + slapd slapd/password2 password yunohost + slapd slapd/domain string yunohost.org + slapd shared/organization string yunohost.org + slapd slapd/allow_ldap_v2 boolean false + slapd slapd/invalid_config boolean true + slapd slapd/backend select MDB + postfix postfix/main_mailer_type select Internet Site + postfix postfix/mailname string /etc/mailname + mariadb-server-10.1 mysql-server/root_password password yunohost + mariadb-server-10.1 mysql-server/root_password_again password yunohost + nslcd nslcd/ldap-bindpw password + nslcd nslcd/ldap-starttls boolean false + nslcd nslcd/ldap-reqcert select + nslcd nslcd/ldap-uris string ldap://localhost/ + nslcd nslcd/ldap-binddn string + nslcd nslcd/ldap-base string dc=yunohost,dc=org + libnss-ldapd libnss-ldapd/nsswitch multiselect group, passwd, shadow + postsrsd postsrsd/domain string yunohost.org + EOF + - cd $YNH_BUILD_DIR + - SUDO_FORCE_REMOVE=yes apt --assume-yes -o Dpkg::Options::="--force-confold" --allow-downgrades install ./*.deb + artifacts: + paths: + - $YNH_BUILD_DIR/*.deb + cache: + paths: + - $YNH_BUILD_DIR/ + policy: pull + key: "$CI_COMMIT_REF_SLUG" + ######################################## # POSTINSTALL ######################################## @@ -21,16 +119,17 @@ postinstall: .test-stage: image: after-postinstall stage: tests + variables: + PIP_CACHE_DIR: "$CI_PROJECT_DIR/.cache/pip" before_script: - apt-get install python-pip -y - - mkdir -p .pip - pip install -U pip - hash -d pip - - pip --cache-dir=.pip install pytest pytest-sugar pytest-mock requests-mock mock + - pip install pytest pytest-sugar pytest-mock requests-mock mock - export PYTEST_ADDOPTS="--color=yes" cache: paths: - - .pip + - .cache/pip - src/yunohost/tests/apps key: "$CI_JOB_STAGE-$CI_COMMIT_REF_SLUG" From 7f4b0ce6e3c89b290ce4fe63614af3fd9699e3b2 Mon Sep 17 00:00:00 2001 From: Kay0u Date: Sun, 17 May 2020 15:02:58 +0200 Subject: [PATCH 02/62] Add YNH repo before install --- .gitlab-ci.yml | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml index b474b92c1..ee6caee48 100644 --- a/.gitlab-ci.yml +++ b/.gitlab-ci.yml @@ -67,6 +67,11 @@ install: stage: install variables: YNH_BUILD_DIR: "ynh-build" + before_script: + - apt install wget --assume-yes + - echo "deb http://forge.yunohost.org/debian/ stretch stable testing unstable" > /etc/apt/sources.list.d/yunohost.list + - wget -O- https://forge.yunohost.org/yunohost.asc -q | apt-key add -qq - >/dev/null 2>&1 + - apt update script: - | debconf-set-selections << EOF From 01f8ee6b7bd515fa03bb46d275b853f3a3d28a72 Mon Sep 17 00:00:00 2001 From: Kay0u Date: Sun, 17 May 2020 18:29:10 +0200 Subject: [PATCH 03/62] fix stupid fail2ban issue --- .gitlab-ci.yml | 2 ++ 1 file changed, 2 insertions(+) diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml index ee6caee48..81dc3aa97 100644 --- a/.gitlab-ci.yml +++ b/.gitlab-ci.yml @@ -72,6 +72,8 @@ install: - echo "deb http://forge.yunohost.org/debian/ stretch stable testing unstable" > /etc/apt/sources.list.d/yunohost.list - wget -O- https://forge.yunohost.org/yunohost.asc -q | apt-key add -qq - >/dev/null 2>&1 - apt update + # https://github.com/YunoHost/install_script/blob/3e16abd7c4e1fe9c518cbc573282cb8fb1fcbbd7/install_yunohost#L433-L485 + - touch /var/log/auth.log script: - | debconf-set-selections << EOF From 24d83b6a97d7aa406595bf855702f9ee7c3f1b7e Mon Sep 17 00:00:00 2001 From: Kay0u Date: Sun, 17 May 2020 19:41:38 +0200 Subject: [PATCH 04/62] fix avahi install --- .gitlab-ci.yml | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml index 81dc3aa97..7777e283b 100644 --- a/.gitlab-ci.yml +++ b/.gitlab-ci.yml @@ -74,6 +74,15 @@ install: - apt update # https://github.com/YunoHost/install_script/blob/3e16abd7c4e1fe9c518cbc573282cb8fb1fcbbd7/install_yunohost#L433-L485 - touch /var/log/auth.log + - > + if ! id avahi > /dev/null 2>&1; then + avahi_id=$((500 + RANDOM % 500)) + while cut -d ':' -f 3 /etc/passwd | grep -q $avahi_id + do + avahi_id=$((500 + RANDOM % 500)) + done + adduser --disabled-password --quiet --system --home /var/run/avahi-daemon --no-create-home --gecos "Avahi mDNS daemon" --group avahi --uid $avahi_id + fi script: - | debconf-set-selections << EOF @@ -98,7 +107,7 @@ install: postsrsd postsrsd/domain string yunohost.org EOF - cd $YNH_BUILD_DIR - - SUDO_FORCE_REMOVE=yes apt --assume-yes -o Dpkg::Options::="--force-confold" --allow-downgrades install ./*.deb + - DEBIAN_FRONTEND=noninteractive SUDO_FORCE_REMOVE=yes apt --assume-yes -o Dpkg::Options::="--force-confold" --allow-downgrades install ./*.deb artifacts: paths: - $YNH_BUILD_DIR/*.deb From 09ff411664e4f93c339df2b5338bfbddaec69293 Mon Sep 17 00:00:00 2001 From: Kay0u Date: Mon, 18 May 2020 15:11:31 +0200 Subject: [PATCH 05/62] rework build scripts --- .gitlab-ci.yml | 43 +++++++++++++++++++++++-------------------- 1 file changed, 23 insertions(+), 20 deletions(-) diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml index 7777e283b..c0c49d447 100644 --- a/.gitlab-ci.yml +++ b/.gitlab-ci.yml @@ -18,45 +18,48 @@ stages: before_script: - DEBIAN_FRONTEND=noninteractive apt --assume-yes -o Dpkg::Options::="--force-confold" install git git-buildpackage postfix python-setuptools - mkdir -p $YNH_BUILD_DIR - - cd $YNH_BUILD_DIR - - git clone $YNH_SOURCE/$DEB_TO_BUILD - - DEBIAN_FRONTEND=noninteractive apt --assume-yes -o Dpkg::Options::="--force-confold" build-dep $(pwd)/$DEB_TO_BUILD cache: paths: - $YNH_BUILD_DIR/*.deb key: "$CI_COMMIT_REF_SLUG" +.build_script: &build_script | + cd $YNH_BUILD_DIR/$PACKAGE + VERSION=$(dpkg-parsechangelog -S Version 2>/dev/null) + VERSION_NIGHTLY="${VERSION}+$CI_PIPELINE_ID+$(date +%Y%m%d%H%M)" + dch --package "${PACKAGE}" --force-bad-version -v "${VERSION_NIGHTLY}" -D "unstable" --force-distribution "Daily build." + debuild -us -uc + build-yunohost: extends: .build-stage variables: - DEB_TO_BUILD: "yunohost" + PACKAGE: "yunohost" script: - - cd $DEB_TO_BUILD - - debuild -us -uc + - git ls-files | xargs tar -czf archive.tar.gz + - mkdir -p $YNH_BUILD_DIR/$PACKAGE + - cat archive.tar.gz | tar -xz -C $YNH_BUILD_DIR/$PACKAGE + - rm archive.tar.gz + - DEBIAN_FRONTEND=noninteractive apt --assume-yes -o Dpkg::Options::="--force-confold" build-dep $(pwd)/$YNH_BUILD_DIR/$PACKAGE + - *build_script + build-ssowat: extends: .build-stage variables: - DEB_TO_BUILD: "ssowat" + PACKAGE: "ssowat" script: - - cd $DEB_TO_BUILD - - debuild -us -uc + - git clone $YNH_SOURCE/$PACKAGE -b $CI_COMMIT_REF_NAME $YNH_BUILD_DIR/$PACKAGE || git clone $YNH_SOURCE/$PACKAGE $YNH_BUILD_DIR/$PACKAGE + - DEBIAN_FRONTEND=noninteractive apt --assume-yes -o Dpkg::Options::="--force-confold" build-dep $(pwd)/$YNH_BUILD_DIR/$PACKAGE + - *build_script build-moulinette: extends: .build-stage variables: - DEB_TO_BUILD: "moulinette" + PACKAGE: "moulinette" script: - - cd $DEB_TO_BUILD - - debuild -us -uc - -build-metronome: - extends: .build-stage - variables: - DEB_TO_BUILD: "metronome" - script: - - cd $DEB_TO_BUILD - - dpkg-buildpackage -rfakeroot -uc -b -d + - git clone $YNH_SOURCE/$PACKAGE -b $CI_COMMIT_REF_NAME $YNH_BUILD_DIR/$PACKAGE || git clone $YNH_SOURCE/$PACKAGE $YNH_BUILD_DIR/$PACKAGE + - DEBIAN_FRONTEND=noninteractive apt --assume-yes -o Dpkg::Options::="--force-confold" build-dep $(pwd)/$YNH_BUILD_DIR/$PACKAGE + - *build_script ######################################## # INSTALL DEB From 85442c42dcc6462f17fe90ce3f1b6c5efc2febae Mon Sep 17 00:00:00 2001 From: Kay0u Date: Mon, 18 May 2020 15:11:38 +0200 Subject: [PATCH 06/62] fix install --- .gitlab-ci.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml index c0c49d447..e48cb62bb 100644 --- a/.gitlab-ci.yml +++ b/.gitlab-ci.yml @@ -86,6 +86,7 @@ install: done adduser --disabled-password --quiet --system --home /var/run/avahi-daemon --no-create-home --gecos "Avahi mDNS daemon" --group avahi --uid $avahi_id fi + - apt install --assume-yes debhelper script: - | debconf-set-selections << EOF From 471dc025dbb6cab18d3c7441348ed9bd427432b5 Mon Sep 17 00:00:00 2001 From: Kay0u Date: Mon, 18 May 2020 15:24:42 +0200 Subject: [PATCH 07/62] move debhelper install [skip ci] --- .gitlab-ci.yml | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml index e48cb62bb..b58a8868e 100644 --- a/.gitlab-ci.yml +++ b/.gitlab-ci.yml @@ -71,7 +71,7 @@ install: variables: YNH_BUILD_DIR: "ynh-build" before_script: - - apt install wget --assume-yes + - apt install --assume-yes wget debhelper - echo "deb http://forge.yunohost.org/debian/ stretch stable testing unstable" > /etc/apt/sources.list.d/yunohost.list - wget -O- https://forge.yunohost.org/yunohost.asc -q | apt-key add -qq - >/dev/null 2>&1 - apt update @@ -86,7 +86,6 @@ install: done adduser --disabled-password --quiet --system --home /var/run/avahi-daemon --no-create-home --gecos "Avahi mDNS daemon" --group avahi --uid $avahi_id fi - - apt install --assume-yes debhelper script: - | debconf-set-selections << EOF From 09ebed1d0b67bea9af19457ff4171e338a046f8d Mon Sep 17 00:00:00 2001 From: Kay0u Date: Mon, 18 May 2020 15:44:53 +0200 Subject: [PATCH 08/62] change deb name --- .gitlab-ci.yml | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml index b58a8868e..befa66c1e 100644 --- a/.gitlab-ci.yml +++ b/.gitlab-ci.yml @@ -21,12 +21,12 @@ stages: cache: paths: - $YNH_BUILD_DIR/*.deb - key: "$CI_COMMIT_REF_SLUG" + key: "$CI_PIPELINE_ID" .build_script: &build_script | cd $YNH_BUILD_DIR/$PACKAGE VERSION=$(dpkg-parsechangelog -S Version 2>/dev/null) - VERSION_NIGHTLY="${VERSION}+$CI_PIPELINE_ID+$(date +%Y%m%d%H%M)" + VERSION_NIGHTLY="${VERSION}~${CI_COMMIT_REF_SLUG//-}+$(date +%Y%m%d%H%M)" dch --package "${PACKAGE}" --force-bad-version -v "${VERSION_NIGHTLY}" -D "unstable" --force-distribution "Daily build." debuild -us -uc @@ -118,7 +118,7 @@ install: paths: - $YNH_BUILD_DIR/ policy: pull - key: "$CI_COMMIT_REF_SLUG" + key: "$CI_PIPELINE_ID" ######################################## # POSTINSTALL From 1abdf16b84db314e52fd37cb341885870fe67650 Mon Sep 17 00:00:00 2001 From: Kay0u Date: Wed, 20 May 2020 14:53:31 +0200 Subject: [PATCH 09/62] CI: Global refactor, yunohost-ci v2 ready --- .gitlab-ci.yml | 262 ++----------------------------- .gitlab/ci/build.gitlab-ci.yml | 52 ++++++ .gitlab/ci/install.gitlab-ci.yml | 16 ++ .gitlab/ci/lint.gitlab-ci.yml | 22 +++ .gitlab/ci/test.gitlab-ci.yml | 102 ++++++++++++ 5 files changed, 203 insertions(+), 251 deletions(-) create mode 100644 .gitlab/ci/build.gitlab-ci.yml create mode 100644 .gitlab/ci/install.gitlab-ci.yml create mode 100644 .gitlab/ci/lint.gitlab-ci.yml create mode 100644 .gitlab/ci/test.gitlab-ci.yml diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml index befa66c1e..b4ee10cc3 100644 --- a/.gitlab-ci.yml +++ b/.gitlab-ci.yml @@ -1,260 +1,20 @@ stages: - build - install - - postinstall - tests - lint -######################################## -# BUILD DEB -######################################## +default: + tags: + - yunohost-ci + # All jobs are interruptible by default + interruptible: true -.build-stage: - image: before-install - stage: build - variables: +variables: YNH_BUILD_DIR: "ynh-build" - YNH_SOURCE: "https://github.com/yunohost" - before_script: - - DEBIAN_FRONTEND=noninteractive apt --assume-yes -o Dpkg::Options::="--force-confold" install git git-buildpackage postfix python-setuptools - - mkdir -p $YNH_BUILD_DIR - cache: - paths: - - $YNH_BUILD_DIR/*.deb - key: "$CI_PIPELINE_ID" -.build_script: &build_script | - cd $YNH_BUILD_DIR/$PACKAGE - VERSION=$(dpkg-parsechangelog -S Version 2>/dev/null) - VERSION_NIGHTLY="${VERSION}~${CI_COMMIT_REF_SLUG//-}+$(date +%Y%m%d%H%M)" - dch --package "${PACKAGE}" --force-bad-version -v "${VERSION_NIGHTLY}" -D "unstable" --force-distribution "Daily build." - debuild -us -uc - -build-yunohost: - extends: .build-stage - variables: - PACKAGE: "yunohost" - script: - - git ls-files | xargs tar -czf archive.tar.gz - - mkdir -p $YNH_BUILD_DIR/$PACKAGE - - cat archive.tar.gz | tar -xz -C $YNH_BUILD_DIR/$PACKAGE - - rm archive.tar.gz - - DEBIAN_FRONTEND=noninteractive apt --assume-yes -o Dpkg::Options::="--force-confold" build-dep $(pwd)/$YNH_BUILD_DIR/$PACKAGE - - *build_script - - -build-ssowat: - extends: .build-stage - variables: - PACKAGE: "ssowat" - script: - - git clone $YNH_SOURCE/$PACKAGE -b $CI_COMMIT_REF_NAME $YNH_BUILD_DIR/$PACKAGE || git clone $YNH_SOURCE/$PACKAGE $YNH_BUILD_DIR/$PACKAGE - - DEBIAN_FRONTEND=noninteractive apt --assume-yes -o Dpkg::Options::="--force-confold" build-dep $(pwd)/$YNH_BUILD_DIR/$PACKAGE - - *build_script - -build-moulinette: - extends: .build-stage - variables: - PACKAGE: "moulinette" - script: - - git clone $YNH_SOURCE/$PACKAGE -b $CI_COMMIT_REF_NAME $YNH_BUILD_DIR/$PACKAGE || git clone $YNH_SOURCE/$PACKAGE $YNH_BUILD_DIR/$PACKAGE - - DEBIAN_FRONTEND=noninteractive apt --assume-yes -o Dpkg::Options::="--force-confold" build-dep $(pwd)/$YNH_BUILD_DIR/$PACKAGE - - *build_script - -######################################## -# INSTALL DEB -######################################## - -install: - image: before-install - stage: install - variables: - YNH_BUILD_DIR: "ynh-build" - before_script: - - apt install --assume-yes wget debhelper - - echo "deb http://forge.yunohost.org/debian/ stretch stable testing unstable" > /etc/apt/sources.list.d/yunohost.list - - wget -O- https://forge.yunohost.org/yunohost.asc -q | apt-key add -qq - >/dev/null 2>&1 - - apt update - # https://github.com/YunoHost/install_script/blob/3e16abd7c4e1fe9c518cbc573282cb8fb1fcbbd7/install_yunohost#L433-L485 - - touch /var/log/auth.log - - > - if ! id avahi > /dev/null 2>&1; then - avahi_id=$((500 + RANDOM % 500)) - while cut -d ':' -f 3 /etc/passwd | grep -q $avahi_id - do - avahi_id=$((500 + RANDOM % 500)) - done - adduser --disabled-password --quiet --system --home /var/run/avahi-daemon --no-create-home --gecos "Avahi mDNS daemon" --group avahi --uid $avahi_id - fi - script: - - | - debconf-set-selections << EOF - slapd slapd/password1 password yunohost - slapd slapd/password2 password yunohost - slapd slapd/domain string yunohost.org - slapd shared/organization string yunohost.org - slapd slapd/allow_ldap_v2 boolean false - slapd slapd/invalid_config boolean true - slapd slapd/backend select MDB - postfix postfix/main_mailer_type select Internet Site - postfix postfix/mailname string /etc/mailname - mariadb-server-10.1 mysql-server/root_password password yunohost - mariadb-server-10.1 mysql-server/root_password_again password yunohost - nslcd nslcd/ldap-bindpw password - nslcd nslcd/ldap-starttls boolean false - nslcd nslcd/ldap-reqcert select - nslcd nslcd/ldap-uris string ldap://localhost/ - nslcd nslcd/ldap-binddn string - nslcd nslcd/ldap-base string dc=yunohost,dc=org - libnss-ldapd libnss-ldapd/nsswitch multiselect group, passwd, shadow - postsrsd postsrsd/domain string yunohost.org - EOF - - cd $YNH_BUILD_DIR - - DEBIAN_FRONTEND=noninteractive SUDO_FORCE_REMOVE=yes apt --assume-yes -o Dpkg::Options::="--force-confold" --allow-downgrades install ./*.deb - artifacts: - paths: - - $YNH_BUILD_DIR/*.deb - cache: - paths: - - $YNH_BUILD_DIR/ - policy: pull - key: "$CI_PIPELINE_ID" - -######################################## -# POSTINSTALL -######################################## - -postinstall: - image: before-postinstall - stage: postinstall - script: - - apt install --no-install-recommends -y $(cat debian/control | grep "^Depends" -A50 | grep "Recommends:" -B50 | grep "^ *," | grep -o -P "[\w\-]{3,}") - - yunohost tools postinstall -d domain.tld -p the_password --ignore-dyndns - -######################################## -# TESTS -######################################## - -.test-stage: - image: after-postinstall - stage: tests - variables: - PIP_CACHE_DIR: "$CI_PROJECT_DIR/.cache/pip" - before_script: - - apt-get install python-pip -y - - pip install -U pip - - hash -d pip - - pip install pytest pytest-sugar pytest-mock requests-mock mock - - export PYTEST_ADDOPTS="--color=yes" - cache: - paths: - - .cache/pip - - src/yunohost/tests/apps - key: "$CI_JOB_STAGE-$CI_COMMIT_REF_SLUG" - -root-tests: - extends: .test-stage - script: - - py.test tests - -test-apps: - extends: .test-stage - script: - - cd src/yunohost - - py.test tests/test_apps.py - -test-appscatalog: - extends: .test-stage - script: - - cd src/yunohost - - py.test tests/test_appscatalog.py - -test-appurl: - extends: .test-stage - script: - - cd src/yunohost - - py.test tests/test_appurl.py - -test-apps-arguments-parsing: - extends: .test-stage - script: - - cd src/yunohost - - py.test tests/test_apps_arguments_parsing.py - -test-backuprestore: - extends: .test-stage - script: - - cd src/yunohost - - py.test tests/test_backuprestore.py - -test-changeurl: - extends: .test-stage - script: - - cd src/yunohost - - py.test tests/test_changeurl.py - -test-permission: - extends: .test-stage - script: - - cd src/yunohost - - py.test tests/test_permission.py - -test-settings: - extends: .test-stage - script: - - cd src/yunohost - - py.test tests/test_settings.py - -test-user-group: - extends: .test-stage - script: - - cd src/yunohost - - py.test tests/test_user-group.py - -test-regenconf: - extends: .test-stage - script: - - cd src/yunohost - - py.test tests/test_regenconf.py - -test-service: - extends: .test-stage - script: - - cd src/yunohost - - py.test tests/test_service.py - -######################################## -# LINTER -######################################## - -.lint-stage: - image: before-postinstall - stage: lint - before_script: - - apt-get install python-pip -y - - mkdir -p .pip - - pip install -U pip - - hash -d pip - - pip --cache-dir=.pip install tox - cache: - paths: - - .pip - - .tox - key: "$CI_JOB_STAGE-$CI_COMMIT_REF_SLUG" - -lint: - extends: .lint-stage - allow_failure: true - script: - - tox -e lint - -invalidcode: - extends: .lint-stage - script: - - tox -e invalidcode - -# Disabled, waiting for buster -#format-check: -# extends: .lint-stage -# script: -# - black --check --diff +include: + - local: .gitlab/ci/build.gitlab-ci.yml + - local: .gitlab/ci/install.gitlab-ci.yml + - local: .gitlab/ci/test.gitlab-ci.yml + - local: .gitlab/ci/lint.gitlab-ci.yml diff --git a/.gitlab/ci/build.gitlab-ci.yml b/.gitlab/ci/build.gitlab-ci.yml new file mode 100644 index 000000000..67232ba1f --- /dev/null +++ b/.gitlab/ci/build.gitlab-ci.yml @@ -0,0 +1,52 @@ +.build-stage: + stage: build + image: "before-install" + variables: + YNH_SOURCE: "https://github.com/yunohost" + before_script: + - mkdir -p $YNH_BUILD_DIR + artifacts: + paths: + - $YNH_BUILD_DIR/*.deb + +.build_script: &build_script + - cd $YNH_BUILD_DIR/$PACKAGE + - VERSION=$(dpkg-parsechangelog -S Version 2>/dev/null) + - VERSION_NIGHTLY="${VERSION}+$(date +%Y%m%d%H%M)" + - dch --package "${PACKAGE}" --force-bad-version -v "${VERSION_NIGHTLY}" -D "unstable" --force-distribution "Daily build." + - debuild --no-lintian -us -uc + +######################################## +# BUILD DEB +######################################## + +build-yunohost: + extends: .build-stage + variables: + PACKAGE: "yunohost" + script: + - git ls-files | xargs tar -czf archive.tar.gz + - mkdir -p $YNH_BUILD_DIR/$PACKAGE + - cat archive.tar.gz | tar -xz -C $YNH_BUILD_DIR/$PACKAGE + - rm archive.tar.gz + - DEBIAN_FRONTEND=noninteractive apt --assume-yes -o Dpkg::Options::="--force-confold" build-dep $(pwd)/$YNH_BUILD_DIR/$PACKAGE + - *build_script + + +build-ssowat: + extends: .build-stage + variables: + PACKAGE: "ssowat" + script: + - git clone $YNH_SOURCE/$PACKAGE -b $CI_COMMIT_REF_NAME $YNH_BUILD_DIR/$PACKAGE || git clone $YNH_SOURCE/$PACKAGE $YNH_BUILD_DIR/$PACKAGE + - DEBIAN_FRONTEND=noninteractive apt --assume-yes -o Dpkg::Options::="--force-confold" build-dep $(pwd)/$YNH_BUILD_DIR/$PACKAGE + - *build_script + +build-moulinette: + extends: .build-stage + variables: + PACKAGE: "moulinette" + script: + - git clone $YNH_SOURCE/$PACKAGE -b $CI_COMMIT_REF_NAME $YNH_BUILD_DIR/$PACKAGE || git clone $YNH_SOURCE/$PACKAGE $YNH_BUILD_DIR/$PACKAGE + - DEBIAN_FRONTEND=noninteractive apt --assume-yes -o Dpkg::Options::="--force-confold" build-dep $(pwd)/$YNH_BUILD_DIR/$PACKAGE + - *build_script diff --git a/.gitlab/ci/install.gitlab-ci.yml b/.gitlab/ci/install.gitlab-ci.yml new file mode 100644 index 000000000..664fc66d5 --- /dev/null +++ b/.gitlab/ci/install.gitlab-ci.yml @@ -0,0 +1,16 @@ +######################################## +# INSTALL DEB +######################################## + +upgrade: + stage: install + image: "after-install" + script: + - DEBIAN_FRONTEND=noninteractive SUDO_FORCE_REMOVE=yes apt --assume-yes -o Dpkg::Options::="--force-confold" --allow-downgrades install ./$YNH_BUILD_DIR/*.deb + +install-postinstall: + stage: install + image: "before-install" + script: + - DEBIAN_FRONTEND=noninteractive SUDO_FORCE_REMOVE=yes apt --assume-yes -o Dpkg::Options::="--force-confold" --allow-downgrades install ./$YNH_BUILD_DIR/*.deb + - yunohost tools postinstall -d domain.tld -p the_password --ignore-dyndns diff --git a/.gitlab/ci/lint.gitlab-ci.yml b/.gitlab/ci/lint.gitlab-ci.yml new file mode 100644 index 000000000..31f88dad1 --- /dev/null +++ b/.gitlab/ci/lint.gitlab-ci.yml @@ -0,0 +1,22 @@ +######################################## +# LINTER +######################################## + +lint: + stage: lint + image: "before-install" + allow_failure: true + script: + - tox -e lint + +invalidcode: + stage: lint + image: "before-install" + script: + - tox -e invalidcode + +# Disabled, waiting for buster +#format-check: +# extends: .lint-stage +# script: +# - black --check --diff diff --git a/.gitlab/ci/test.gitlab-ci.yml b/.gitlab/ci/test.gitlab-ci.yml new file mode 100644 index 000000000..dcc1b2d94 --- /dev/null +++ b/.gitlab/ci/test.gitlab-ci.yml @@ -0,0 +1,102 @@ +.install_debs: &install_debs + - DEBIAN_FRONTEND=noninteractive SUDO_FORCE_REMOVE=yes apt --assume-yes -o Dpkg::Options::="--force-confold" --allow-downgrades install ./$YNH_BUILD_DIR/*.deb + +.test-stage: + stage: tests + image: "after-install" + variables: + PYTEST_ADDOPTS: "--color=yes" + before_script: + - *install_debs + cache: + paths: + - src/yunohost/tests/apps + key: "$CI_JOB_STAGE-$CI_COMMIT_REF_SLUG" + +######################################## +# TESTS +######################################## + +full-tests: + stage: tests + image: "before-install" + variables: + PYTEST_ADDOPTS: "--color=yes" + before_script: + - *install_debs + - yunohost tools postinstall -d domain.tld -p the_password --ignore-dyndns + script: + - py.test tests + - cd src/yunohost + - py.test tests + +root-tests: + extends: .test-stage + script: + - py.test tests + +test-apps: + extends: .test-stage + script: + - cd src/yunohost + - py.test tests/test_apps.py + +test-appscatalog: + extends: .test-stage + script: + - cd src/yunohost + - py.test tests/test_appscatalog.py + +test-appurl: + extends: .test-stage + script: + - cd src/yunohost + - py.test tests/test_appurl.py + +test-apps-arguments-parsing: + extends: .test-stage + script: + - cd src/yunohost + - py.test tests/test_apps_arguments_parsing.py + +test-backuprestore: + extends: .test-stage + script: + - cd src/yunohost + - py.test tests/test_backuprestore.py + +test-changeurl: + extends: .test-stage + script: + - cd src/yunohost + - py.test tests/test_changeurl.py + +test-permission: + extends: .test-stage + script: + - cd src/yunohost + - py.test tests/test_permission.py + +test-settings: + extends: .test-stage + script: + - cd src/yunohost + - py.test tests/test_settings.py + +test-user-group: + extends: .test-stage + script: + - cd src/yunohost + - py.test tests/test_user-group.py + +test-regenconf: + extends: .test-stage + script: + - cd src/yunohost + - py.test tests/test_regenconf.py + +test-service: + extends: .test-stage + script: + - cd src/yunohost + - py.test tests/test_service.py From de81a9349802f1f328ecec35f8dd3f30692a025f Mon Sep 17 00:00:00 2001 From: Kay0u Date: Wed, 20 May 2020 15:27:18 +0200 Subject: [PATCH 10/62] generate helper doc --- .gitlab-ci.yml | 2 ++ .gitlab/ci/doc.gitlab-ci.yml | 14 ++++++++++++++ .gitlab/ci/lint.gitlab-ci.yml | 2 ++ 3 files changed, 18 insertions(+) create mode 100644 .gitlab/ci/doc.gitlab-ci.yml diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml index b4ee10cc3..eb34de38e 100644 --- a/.gitlab-ci.yml +++ b/.gitlab-ci.yml @@ -3,6 +3,7 @@ stages: - install - tests - lint + - doc default: tags: @@ -18,3 +19,4 @@ include: - local: .gitlab/ci/install.gitlab-ci.yml - local: .gitlab/ci/test.gitlab-ci.yml - local: .gitlab/ci/lint.gitlab-ci.yml + - local: .gitlab/ci/doc.gitlab-ci.yml diff --git a/.gitlab/ci/doc.gitlab-ci.yml b/.gitlab/ci/doc.gitlab-ci.yml new file mode 100644 index 000000000..b246cc238 --- /dev/null +++ b/.gitlab/ci/doc.gitlab-ci.yml @@ -0,0 +1,14 @@ +######################################## +# DOC +######################################## + +generate-helpers-doc: + stage: doc + image: "before-install" + needs: [] + script: + - cd doc + - python generate_helper_doc.py + artifacts: + paths: + - doc/helpers.html diff --git a/.gitlab/ci/lint.gitlab-ci.yml b/.gitlab/ci/lint.gitlab-ci.yml index 31f88dad1..c6967d5a5 100644 --- a/.gitlab/ci/lint.gitlab-ci.yml +++ b/.gitlab/ci/lint.gitlab-ci.yml @@ -5,6 +5,7 @@ lint: stage: lint image: "before-install" + needs: [] allow_failure: true script: - tox -e lint @@ -12,6 +13,7 @@ lint: invalidcode: stage: lint image: "before-install" + needs: [] script: - tox -e invalidcode From 348d80664d5e966c93516e73dc4c36b9a02bf921 Mon Sep 17 00:00:00 2001 From: Kay0u Date: Wed, 20 May 2020 15:44:56 +0200 Subject: [PATCH 11/62] Add needs keyword --- .gitlab/ci/install.gitlab-ci.yml | 15 +++++++++++++-- .gitlab/ci/test.gitlab-ci.yml | 15 +++++++++++++++ 2 files changed, 28 insertions(+), 2 deletions(-) diff --git a/.gitlab/ci/install.gitlab-ci.yml b/.gitlab/ci/install.gitlab-ci.yml index 664fc66d5..8363b6e58 100644 --- a/.gitlab/ci/install.gitlab-ci.yml +++ b/.gitlab/ci/install.gitlab-ci.yml @@ -1,15 +1,26 @@ +.install-stage: + stage: install + needs: + - job: build-yunohost + artifacts: true + - job: build-ssowat + artifacts: true + - job: build-moulinette + artifacts: true + ######################################## # INSTALL DEB ######################################## upgrade: - stage: install + extends: .install-stage image: "after-install" script: - DEBIAN_FRONTEND=noninteractive SUDO_FORCE_REMOVE=yes apt --assume-yes -o Dpkg::Options::="--force-confold" --allow-downgrades install ./$YNH_BUILD_DIR/*.deb + install-postinstall: - stage: install + extends: .install-stage image: "before-install" script: - DEBIAN_FRONTEND=noninteractive SUDO_FORCE_REMOVE=yes apt --assume-yes -o Dpkg::Options::="--force-confold" --allow-downgrades install ./$YNH_BUILD_DIR/*.deb diff --git a/.gitlab/ci/test.gitlab-ci.yml b/.gitlab/ci/test.gitlab-ci.yml index dcc1b2d94..fde96e5ff 100644 --- a/.gitlab/ci/test.gitlab-ci.yml +++ b/.gitlab/ci/test.gitlab-ci.yml @@ -12,6 +12,14 @@ paths: - src/yunohost/tests/apps key: "$CI_JOB_STAGE-$CI_COMMIT_REF_SLUG" + needs: + - job: build-yunohost + artifacts: true + - job: build-ssowat + artifacts: true + - job: build-moulinette + artifacts: true + - job: upgrade ######################################## # TESTS @@ -29,6 +37,13 @@ full-tests: - py.test tests - cd src/yunohost - py.test tests + needs: + - job: build-yunohost + artifacts: true + - job: build-ssowat + artifacts: true + - job: build-moulinette + artifacts: true root-tests: extends: .test-stage From c2d990fd37e8f7935b481fceb0651de7372f44b3 Mon Sep 17 00:00:00 2001 From: Kay0u Date: Wed, 20 May 2020 16:23:24 +0200 Subject: [PATCH 12/62] Ignore pytest InsecureRequestWarning --- pytest.ini | 2 ++ 1 file changed, 2 insertions(+) diff --git a/pytest.ini b/pytest.ini index fb4d5b265..709e0e0b9 100644 --- a/pytest.ini +++ b/pytest.ini @@ -10,3 +10,5 @@ markers = with_legacy_app_installed with_backup_recommended_app_installed_with_ynh_restore with_permission_app_installed +filterwarnings = + ignore::urllib3.exceptions.InsecureRequestWarning \ No newline at end of file From 767c68d186866f992e921ce7fdab53b9950e3aac Mon Sep 17 00:00:00 2001 From: Kay0u Date: Wed, 20 May 2020 16:34:42 +0200 Subject: [PATCH 13/62] add junitxml report --- .gitlab/ci/test.gitlab-ci.yml | 27 +++++++++++++++------------ 1 file changed, 15 insertions(+), 12 deletions(-) diff --git a/.gitlab/ci/test.gitlab-ci.yml b/.gitlab/ci/test.gitlab-ci.yml index fde96e5ff..a70f0e5c9 100644 --- a/.gitlab/ci/test.gitlab-ci.yml +++ b/.gitlab/ci/test.gitlab-ci.yml @@ -20,6 +20,9 @@ - job: build-moulinette artifacts: true - job: upgrade + artifacts: + reports: + junit: report.xml ######################################## # TESTS @@ -48,70 +51,70 @@ full-tests: root-tests: extends: .test-stage script: - - py.test tests + - py.test tests --junitxml=report.xml test-apps: extends: .test-stage script: - cd src/yunohost - - py.test tests/test_apps.py + - py.test tests/test_apps.py --junitxml=report.xml test-appscatalog: extends: .test-stage script: - cd src/yunohost - - py.test tests/test_appscatalog.py + - py.test tests/test_appscatalog.py --junitxml=report.xml test-appurl: extends: .test-stage script: - cd src/yunohost - - py.test tests/test_appurl.py + - py.test tests/test_appurl.py --junitxml=report.xml test-apps-arguments-parsing: extends: .test-stage script: - cd src/yunohost - - py.test tests/test_apps_arguments_parsing.py + - py.test tests/test_apps_arguments_parsing.py --junitxml=report.xml test-backuprestore: extends: .test-stage script: - cd src/yunohost - - py.test tests/test_backuprestore.py + - py.test tests/test_backuprestore.py --junitxml=report.xml test-changeurl: extends: .test-stage script: - cd src/yunohost - - py.test tests/test_changeurl.py + - py.test tests/test_changeurl.py --junitxml=report.xml test-permission: extends: .test-stage script: - cd src/yunohost - - py.test tests/test_permission.py + - py.test tests/test_permission.py --junitxml=report.xml test-settings: extends: .test-stage script: - cd src/yunohost - - py.test tests/test_settings.py + - py.test tests/test_settings.py --junitxml=report.xml test-user-group: extends: .test-stage script: - cd src/yunohost - - py.test tests/test_user-group.py + - py.test tests/test_user-group.py --junitxml=report.xml test-regenconf: extends: .test-stage script: - cd src/yunohost - - py.test tests/test_regenconf.py + - py.test tests/test_regenconf.py --junitxml=report.xml test-service: extends: .test-stage script: - cd src/yunohost - - py.test tests/test_service.py + - py.test tests/test_service.py --junitxml=report.xml From 37f0273ff4a7eb7bba834728eec1e88c92528010 Mon Sep 17 00:00:00 2001 From: Kay0u Date: Wed, 20 May 2020 17:10:02 +0200 Subject: [PATCH 14/62] adding test coverage --- .gitlab/ci/test.gitlab-ci.yml | 35 ++++++++++++------------ src/yunohost/tests/conftest.py | 3 ++ src/yunohost/tests/test_apps.py | 14 +++++----- src/yunohost/tests/test_appurl.py | 9 ++++-- src/yunohost/tests/test_backuprestore.py | 26 +++++++++--------- src/yunohost/tests/test_changeurl.py | 5 +++- src/yunohost/tests/test_permission.py | 13 +++++---- 7 files changed, 57 insertions(+), 48 deletions(-) diff --git a/.gitlab/ci/test.gitlab-ci.yml b/.gitlab/ci/test.gitlab-ci.yml index a70f0e5c9..b52e08085 100644 --- a/.gitlab/ci/test.gitlab-ci.yml +++ b/.gitlab/ci/test.gitlab-ci.yml @@ -20,9 +20,7 @@ - job: build-moulinette artifacts: true - job: upgrade - artifacts: - reports: - junit: report.xml + ######################################## # TESTS @@ -37,9 +35,7 @@ full-tests: - *install_debs - yunohost tools postinstall -d domain.tld -p the_password --ignore-dyndns script: - - py.test tests - - cd src/yunohost - - py.test tests + - pytest --cov=yunohost tests/ src/yunohost/tests/ --junitxml=report.xml needs: - job: build-yunohost artifacts: true @@ -47,74 +43,77 @@ full-tests: artifacts: true - job: build-moulinette artifacts: true + artifacts: + reports: + junit: report.xml root-tests: extends: .test-stage script: - - py.test tests --junitxml=report.xml + - py.test tests test-apps: extends: .test-stage script: - cd src/yunohost - - py.test tests/test_apps.py --junitxml=report.xml + - py.test tests/test_apps.py test-appscatalog: extends: .test-stage script: - cd src/yunohost - - py.test tests/test_appscatalog.py --junitxml=report.xml + - py.test tests/test_appscatalog.py test-appurl: extends: .test-stage script: - cd src/yunohost - - py.test tests/test_appurl.py --junitxml=report.xml + - py.test tests/test_appurl.py test-apps-arguments-parsing: extends: .test-stage script: - cd src/yunohost - - py.test tests/test_apps_arguments_parsing.py --junitxml=report.xml + - py.test tests/test_apps_arguments_parsing.py test-backuprestore: extends: .test-stage script: - cd src/yunohost - - py.test tests/test_backuprestore.py --junitxml=report.xml + - py.test tests/test_backuprestore.py test-changeurl: extends: .test-stage script: - cd src/yunohost - - py.test tests/test_changeurl.py --junitxml=report.xml + - py.test tests/test_changeurl.py test-permission: extends: .test-stage script: - cd src/yunohost - - py.test tests/test_permission.py --junitxml=report.xml + - py.test tests/test_permission.py test-settings: extends: .test-stage script: - cd src/yunohost - - py.test tests/test_settings.py --junitxml=report.xml + - py.test tests/test_settings.py test-user-group: extends: .test-stage script: - cd src/yunohost - - py.test tests/test_user-group.py --junitxml=report.xml + - py.test tests/test_user-group.py test-regenconf: extends: .test-stage script: - cd src/yunohost - - py.test tests/test_regenconf.py --junitxml=report.xml + - py.test tests/test_regenconf.py test-service: extends: .test-stage script: - cd src/yunohost - - py.test tests/test_service.py --junitxml=report.xml + - py.test tests/test_service.py diff --git a/src/yunohost/tests/conftest.py b/src/yunohost/tests/conftest.py index 073c880f8..d5f3ed186 100644 --- a/src/yunohost/tests/conftest.py +++ b/src/yunohost/tests/conftest.py @@ -19,6 +19,9 @@ def clone_test_app(request): else: os.system("cd %s/apps && git pull > /dev/null 2>&1" % cwd) +def get_test_apps_dir(): + cwd = os.path.split(os.path.realpath(__file__))[0] + return os.path.join(cwd, "apps") @contextmanager def message(mocker, key, **kwargs): diff --git a/src/yunohost/tests/test_apps.py b/src/yunohost/tests/test_apps.py index c2c7b8415..0f4c3749a 100644 --- a/src/yunohost/tests/test_apps.py +++ b/src/yunohost/tests/test_apps.py @@ -4,7 +4,7 @@ import pytest import shutil import requests -from conftest import message, raiseYunohostError +from conftest import message, raiseYunohostError, get_test_apps_dir from moulinette.utils.filesystem import mkdir @@ -150,7 +150,7 @@ def app_is_exposed_on_http(domain, path, message_in_page): def install_legacy_app(domain, path, public=True): app_install( - "./tests/apps/legacy_app_ynh", + os.path.join(get_test_apps_dir(), "legacy_app_ynh"), args="domain=%s&path=%s&is_public=%s" % (domain, path, 1 if public else 0), force=True, ) @@ -159,14 +159,14 @@ def install_legacy_app(domain, path, public=True): def install_full_domain_app(domain): app_install( - "./tests/apps/full_domain_app_ynh", args="domain=%s" % domain, force=True + os.path.join(get_test_apps_dir(), "full_domain_app_ynh"), args="domain=%s" % domain, force=True ) def install_break_yo_system(domain, breakwhat): app_install( - "./tests/apps/break_yo_system_ynh", + os.path.join(get_test_apps_dir(), "break_yo_system_ynh"), args="domain=%s&breakwhat=%s" % (domain, breakwhat), force=True, ) @@ -376,7 +376,7 @@ def test_systemfuckedup_during_app_upgrade(mocker, secondary_domain): with pytest.raises(YunohostError): with message(mocker, "app_action_broke_system"): - app_upgrade("break_yo_system", file="./tests/apps/break_yo_system_ynh") + app_upgrade("break_yo_system", file=os.path.join(get_test_apps_dir(), "break_yo_system_ynh")) def test_failed_multiple_app_upgrade(mocker, secondary_domain): @@ -389,7 +389,7 @@ def test_failed_multiple_app_upgrade(mocker, secondary_domain): app_upgrade( ["break_yo_system", "legacy_app"], file={ - "break_yo_system": "./tests/apps/break_yo_system_ynh", - "legacy": "./tests/apps/legacy_app_ynh", + "break_yo_system": os.path.join(get_test_apps_dir(), "break_yo_system_ynh"), + "legacy": os.path.join(get_test_apps_dir(), "legacy_app_ynh"), }, ) diff --git a/src/yunohost/tests/test_appurl.py b/src/yunohost/tests/test_appurl.py index b0a47d89f..8c30a8ec7 100644 --- a/src/yunohost/tests/test_appurl.py +++ b/src/yunohost/tests/test_appurl.py @@ -1,4 +1,7 @@ import pytest +import os + +from conftest import get_test_apps_dir from yunohost.utils.error import YunohostError from yunohost.app import app_install, app_remove @@ -43,19 +46,19 @@ def test_urlavailable(): def test_registerurl(): - app_install("./tests/apps/register_url_app_ynh", + app_install(os.path.join(get_test_apps_dir(), "register_url_app_ynh"), args="domain=%s&path=%s" % (maindomain, "/urlregisterapp"), force=True) assert not domain_url_available(maindomain, "/urlregisterapp") # Try installing at same location with pytest.raises(YunohostError): - app_install("./tests/apps/register_url_app_ynh", + app_install(os.path.join(get_test_apps_dir(), "register_url_app_ynh"), args="domain=%s&path=%s" % (maindomain, "/urlregisterapp"), force=True) def test_registerurl_baddomain(): with pytest.raises(YunohostError): - app_install("./tests/apps/register_url_app_ynh", + app_install(os.path.join(get_test_apps_dir(), "register_url_app_ynh"), args="domain=%s&path=%s" % ("yolo.swag", "/urlregisterapp"), force=True) diff --git a/src/yunohost/tests/test_backuprestore.py b/src/yunohost/tests/test_backuprestore.py index 026e87c95..5cffc186e 100644 --- a/src/yunohost/tests/test_backuprestore.py +++ b/src/yunohost/tests/test_backuprestore.py @@ -3,7 +3,7 @@ import os import shutil import subprocess -from conftest import message, raiseYunohostError +from conftest import message, raiseYunohostError, get_test_apps_dir from yunohost.app import app_install, app_remove, app_ssowatconf from yunohost.app import _is_installed @@ -117,9 +117,9 @@ def app_is_installed(app): def backup_test_dependencies_are_met(): # Dummy test apps (or backup archives) - assert os.path.exists("./tests/apps/backup_wordpress_from_2p4") - assert os.path.exists("./tests/apps/legacy_app_ynh") - assert os.path.exists("./tests/apps/backup_recommended_app_ynh") + assert os.path.exists(os.path.join(get_test_apps_dir(), "backup_wordpress_from_2p4")) + assert os.path.exists(os.path.join(get_test_apps_dir(), "legacy_app_ynh")) + assert os.path.exists(os.path.join(get_test_apps_dir(), "backup_recommended_app_ynh")) return True @@ -175,7 +175,7 @@ def uninstall_test_apps_if_needed(): def install_app(app, path, additionnal_args=""): - app_install("./tests/apps/%s" % app, + app_install(os.path.join(get_test_apps_dir(), app), args="domain=%s&path=%s%s" % (maindomain, path, additionnal_args), force=True) @@ -184,22 +184,22 @@ def add_archive_wordpress_from_2p4(): os.system("mkdir -p /home/yunohost.backup/archives") - os.system("cp ./tests/apps/backup_wordpress_from_2p4/backup.info.json \ - /home/yunohost.backup/archives/backup_wordpress_from_2p4.info.json") + os.system("cp " + os.path.join(get_test_apps_dir(), "backup_wordpress_from_2p4/backup.info.json") + \ + " /home/yunohost.backup/archives/backup_wordpress_from_2p4.info.json") - os.system("cp ./tests/apps/backup_wordpress_from_2p4/backup.tar.gz \ - /home/yunohost.backup/archives/backup_wordpress_from_2p4.tar.gz") + os.system("cp " + os.path.join(get_test_apps_dir(), "backup_wordpress_from_2p4/backup.tar.gz") + \ + " /home/yunohost.backup/archives/backup_wordpress_from_2p4.tar.gz") def add_archive_system_from_2p4(): os.system("mkdir -p /home/yunohost.backup/archives") - os.system("cp ./tests/apps/backup_system_from_2p4/backup.info.json \ - /home/yunohost.backup/archives/backup_system_from_2p4.info.json") + os.system("cp " + os.path.join(get_test_apps_dir(), "backup_system_from_2p4/backup.info.json") + \ + " /home/yunohost.backup/archives/backup_system_from_2p4.info.json") - os.system("cp ./tests/apps/backup_system_from_2p4/backup.tar.gz \ - /home/yunohost.backup/archives/backup_system_from_2p4.tar.gz") + os.system("cp " + os.path.join(get_test_apps_dir(), "backup_system_from_2p4/backup.tar.gz") + \ + " /home/yunohost.backup/archives/backup_system_from_2p4.tar.gz") # # System backup # diff --git a/src/yunohost/tests/test_changeurl.py b/src/yunohost/tests/test_changeurl.py index 8888dd9e9..b1bedc7eb 100644 --- a/src/yunohost/tests/test_changeurl.py +++ b/src/yunohost/tests/test_changeurl.py @@ -1,6 +1,9 @@ import pytest import time import requests +import os + +from conftest import get_test_apps_dir from yunohost.app import app_install, app_change_url, app_remove, app_map from yunohost.domain import _get_maindomain @@ -20,7 +23,7 @@ def teardown_function(function): def install_changeurl_app(path): - app_install("./tests/apps/change_url_app_ynh", + app_install(os.path.join(get_test_apps_dir(), "change_url_app_ynh"), args="domain=%s&path=%s" % (maindomain, path), force=True) diff --git a/src/yunohost/tests/test_permission.py b/src/yunohost/tests/test_permission.py index b6b7d9577..82ec151f3 100644 --- a/src/yunohost/tests/test_permission.py +++ b/src/yunohost/tests/test_permission.py @@ -1,7 +1,8 @@ import requests import pytest +import os -from conftest import message, raiseYunohostError +from conftest import message, raiseYunohostError, get_test_apps_dir from yunohost.app import app_install, app_remove, app_change_url, app_list, app_map, _installed_apps from yunohost.user import user_list, user_create, user_delete, \ @@ -418,7 +419,7 @@ def test_permission_remove_url(): def test_permission_app_install(): - app_install("./tests/apps/permissions_app_ynh", + app_install(os.path.join(get_test_apps_dir(), "permissions_app_ynh"), args="domain=%s&path=%s&is_public=0&admin=%s" % (maindomain, "/urlpermissionapp", "alice"), force=True) res = user_permission_list(full=True)['permissions'] @@ -446,7 +447,7 @@ def test_permission_app_install(): def test_permission_app_remove(): - app_install("./tests/apps/permissions_app_ynh", + app_install(os.path.join(get_test_apps_dir(), "permissions_app_ynh"), args="domain=%s&path=%s&is_public=0&admin=%s" % (maindomain, "/urlpermissionapp", "alice"), force=True) app_remove("permissions_app") @@ -456,7 +457,7 @@ def test_permission_app_remove(): def test_permission_app_change_url(): - app_install("./tests/apps/permissions_app_ynh", + app_install(os.path.join(get_test_apps_dir(), "permissions_app_ynh"), args="domain=%s&path=%s&admin=%s" % (maindomain, "/urlpermissionapp", "alice"), force=True) # FIXME : should rework this test to look for differences in the generated app map / app tiles ... @@ -475,7 +476,7 @@ def test_permission_app_change_url(): def test_permission_app_propagation_on_ssowat(): - app_install("./tests/apps/permissions_app_ynh", + app_install(os.path.join(get_test_apps_dir(), "permissions_app_ynh"), args="domain=%s&path=%s&is_public=1&admin=%s" % (maindomain, "/urlpermissionapp", "alice"), force=True) res = user_permission_list(full=True)['permissions'] @@ -505,7 +506,7 @@ def test_permission_app_propagation_on_ssowat(): def test_permission_legacy_app_propagation_on_ssowat(): - app_install("./tests/apps/legacy_app_ynh", + app_install(os.path.join(get_test_apps_dir(), "legacy_app_ynh"), args="domain=%s&path=%s" % (maindomain, "/legacy"), force=True) # App is configured as public by default using the legacy unprotected_uri mechanics From 88f6dbe7f65c228643c1fb1917649bf9c1008dd2 Mon Sep 17 00:00:00 2001 From: Kay0u Date: Wed, 20 May 2020 18:12:18 +0200 Subject: [PATCH 15/62] add urllib3 to the tox dependencies --- tox.ini | 1 + 1 file changed, 1 insertion(+) diff --git a/tox.ini b/tox.ini index 8d033367b..4598ad3d3 100644 --- a/tox.ini +++ b/tox.ini @@ -10,6 +10,7 @@ deps = pytest >= 4.6.3, < 5.0 pyyaml >= 5.1.2, < 6.0 flake8 >= 3.7.9, < 3.8 + urllib3 commands = pytest {posargs} From bb8c7ebb6a117b93b1f0f1420df8800e3aa9e4f5 Mon Sep 17 00:00:00 2001 From: Kayou Date: Fri, 22 May 2020 12:32:49 +0200 Subject: [PATCH 16/62] Do not create a new password if the user already exists --- data/helpers.d/postgresql | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/data/helpers.d/postgresql b/data/helpers.d/postgresql index 78ef4f7ce..0b027c78f 100644 --- a/data/helpers.d/postgresql +++ b/data/helpers.d/postgresql @@ -229,12 +229,14 @@ ynh_psql_setup_db() { # Manage arguments with getopts ynh_handle_getopts_args "$@" - local new_db_pwd=$(ynh_string_random) # Generate a random password - # If $db_pwd is not given, use new_db_pwd instead for db_pwd - db_pwd="${db_pwd:-$new_db_pwd}" - if ! ynh_psql_user_exists --user=$db_user; then + local new_db_pwd=$(ynh_string_random) # Generate a random password + # If $db_pwd is not given, use new_db_pwd instead for db_pwd + db_pwd="${db_pwd:-$new_db_pwd}" + ynh_psql_create_user "$db_user" "$db_pwd" + elif [ -z $db_pwd ]; then + ynh_die --message="The user $db_user exists, please provide his password" fi ynh_psql_create_db "$db_name" "$db_user" # Create the database From f0cc679828f9daace29a6aad8a78cf0a7e09a4dd Mon Sep 17 00:00:00 2001 From: Alexandre Aubin Date: Fri, 22 May 2020 20:30:54 +0200 Subject: [PATCH 17/62] Add an exception if packaging format is not recognized --- locales/en.json | 1 + src/yunohost/app.py | 5 +++++ 2 files changed, 6 insertions(+) diff --git a/locales/en.json b/locales/en.json index 95e297bc1..851656532 100644 --- a/locales/en.json +++ b/locales/en.json @@ -48,6 +48,7 @@ "app_upgrade_script_failed": "An error occurred inside the app upgrade script", "app_upgrade_some_app_failed": "Some apps could not be upgraded", "app_upgraded": "{app:s} upgraded", + "app_packaging_format_not_supported": "This app cannot be installed because its packaging format is not supported by your Yunohost version. You should probably consider upgrading your system.", "apps_already_up_to_date": "All apps are already up-to-date", "apps_catalog_init_success": "App catalog system initialized!", "apps_catalog_updating": "Updating application catalog…", diff --git a/src/yunohost/app.py b/src/yunohost/app.py index b9116693b..d11bceda5 100644 --- a/src/yunohost/app.py +++ b/src/yunohost/app.py @@ -2322,6 +2322,11 @@ def _encode_string(value): def _check_manifest_requirements(manifest, app_instance_name): """Check if required packages are met from the manifest""" + + packaging_format = int(manifest.get('packaging_format', 0)) + if packaging_format not in [0, 1]: + raise YunohostError("app_packaging_format_not_supported") + requirements = manifest.get('requirements', dict()) if not requirements: From 85f1802ec9a2444e305c374bdb937cc39646b664 Mon Sep 17 00:00:00 2001 From: Kay0u Date: Fri, 22 May 2020 21:05:19 +0200 Subject: [PATCH 18/62] [fix] empty services.yml file --- data/hooks/conf_regen/01-yunohost | 2 +- src/yunohost/service.py | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/data/hooks/conf_regen/01-yunohost b/data/hooks/conf_regen/01-yunohost index 4bd763b70..02f191c29 100755 --- a/data/hooks/conf_regen/01-yunohost +++ b/data/hooks/conf_regen/01-yunohost @@ -98,7 +98,7 @@ with open('services.yml') as f: new_services = yaml.load(f) with open('/etc/yunohost/services.yml') as f: - services = yaml.load(f) + services = yaml.load(f) or {} updated = False diff --git a/src/yunohost/service.py b/src/yunohost/service.py index 1f77e3545..91edeb2e6 100644 --- a/src/yunohost/service.py +++ b/src/yunohost/service.py @@ -586,7 +586,7 @@ def _get_services(): """ try: with open('/etc/yunohost/services.yml', 'r') as f: - services = yaml.load(f) + services = yaml.load(f) or {} except: return {} From fedad580e1d0e830bc21ebbb19902abad20fee5d Mon Sep 17 00:00:00 2001 From: Kay0u Date: Fri, 22 May 2020 19:27:10 +0000 Subject: [PATCH 19/62] Update changelog for 3.8.4.4 release --- debian/changelog | 15 +++++++++++++++ 1 file changed, 15 insertions(+) diff --git a/debian/changelog b/debian/changelog index 83ae9c3d4..ab7b110a3 100644 --- a/debian/changelog +++ b/debian/changelog @@ -1,3 +1,18 @@ +yunohost (3.8.4.4) stable; urgency=low + + - [fix] Crash when the services file is empty (85f1802) + - [fix] IPv6 detection when using wg-quick (#997) + - [fix] Use a .get() to avoid crash if key doesn't exist (1f1b2338) + - [enh] Don't display the hostname when calling journalctl, this takes horizontal space for nothing (2bcfb5a1) + - [fix] Add --quiet, otherwise getopts is confused by "-- Logs" at the beginning (bdbf1822) + - [mod] We don't need those color codes... and warnings are already warnings... (2a631fa2) + - [fix] psql_setup_db: Do not create a new password if the user already exists (#998) + - [enh] Add an exception if packaging format is not recognized (f0cc6798) + + Thanks to all contributors <3 ! (Aleks, Julien Rabier, Kayou) + + -- Kay0u Fri, 22 May 2020 19:26:05 +0000 + yunohost (3.8.4.3) stable; urgency=low - [fix] Workaround for the sury pinning issues when installing dependencies From 6637c8a84dbe3aaca708940df4abe64b283eab28 Mon Sep 17 00:00:00 2001 From: Alexandre Aubin Date: Sat, 23 May 2020 13:52:08 +0200 Subject: [PATCH 20/62] Tell systemctl to stfu about creating symlinks when enabling/disabling services --- data/helpers.d/postgresql | 2 +- data/helpers.d/systemd | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/data/helpers.d/postgresql b/data/helpers.d/postgresql index 0b027c78f..cce1f7959 100644 --- a/data/helpers.d/postgresql +++ b/data/helpers.d/postgresql @@ -295,7 +295,7 @@ ynh_psql_test_if_first_run() { # postgresql could be flagged as active even though the cluster is in # failed state because of how the service is configured..) systemctl is-active postgresql@$PSQL_VERSION-main -q || ynh_systemd_action --service_name=postgresql --action=restart - systemctl is-enabled postgresql -q || systemctl enable postgresql + systemctl is-enabled postgresql -q || systemctl enable postgresql --quiet # If this is the very first time, we define the root password # and configure a few things diff --git a/data/helpers.d/systemd b/data/helpers.d/systemd index 236781f8b..5c5fda852 100644 --- a/data/helpers.d/systemd +++ b/data/helpers.d/systemd @@ -58,7 +58,7 @@ ynh_add_systemd_config () { ynh_store_file_checksum --file="$finalsystemdconf" chown root: "$finalsystemdconf" - systemctl enable $service + systemctl enable $service --quiet systemctl daemon-reload } @@ -81,7 +81,7 @@ ynh_remove_systemd_config () { if [ -e "$finalsystemdconf" ] then ynh_systemd_action --service_name=$service --action=stop - systemctl disable $service + systemctl disable $service --quiet ynh_secure_remove --file="$finalsystemdconf" systemctl daemon-reload fi From e30e25fa93e98183d676d165dd020d37d2e9cd5d Mon Sep 17 00:00:00 2001 From: Alexandre Aubin Date: Sat, 23 May 2020 13:55:10 +0200 Subject: [PATCH 21/62] Add maindomain in diagnosis email subject --- src/yunohost/diagnosis.py | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/src/yunohost/diagnosis.py b/src/yunohost/diagnosis.py index 4fad86ffd..035e1a889 100644 --- a/src/yunohost/diagnosis.py +++ b/src/yunohost/diagnosis.py @@ -558,9 +558,10 @@ def _list_diagnosis_categories(): def _email_diagnosis_issues(): from yunohost.domain import _get_maindomain - from_ = "diagnosis@%s (Automatic diagnosis)" % _get_maindomain() + maindomain = _get_maindomain() + from_ = "diagnosis@%s (Automatic diagnosis on %s)" % (maindomain, maindomain) to_ = "root" - subject_ = "Issues found by automatic diagnosis" + subject_ = "Issues found by automatic diagnosis on %s" % maindomain disclaimer = "The automatic diagnosis on your YunoHost server identified some issues on your server. You will find a description of the issues below. You can manage those issues in the 'Diagnosis' section in your webadmin." From 58ce6e5e583dac1cd87be96721397812c8f95d78 Mon Sep 17 00:00:00 2001 From: Alexandre Aubin Date: Sat, 23 May 2020 23:12:08 +0200 Subject: [PATCH 22/62] Webpath should also be normalized for args_list, so that we can get rid of the 'malformed path' check of the CI... --- src/yunohost/app.py | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/src/yunohost/app.py b/src/yunohost/app.py index d11bceda5..0b16123cb 100644 --- a/src/yunohost/app.py +++ b/src/yunohost/app.py @@ -713,12 +713,14 @@ def app_install(operation_logger, app, label=None, args=None, no_remove_on_failu args_dict = {} if not args else \ dict(urlparse.parse_qsl(args, keep_blank_values=True)) args_odict = _parse_args_from_manifest(manifest, 'install', args=args_dict) - args_list = [value[0] for value in args_odict.values()] - args_list.append(app_instance_name) # Validate domain / path availability for webapps _validate_and_normalize_webpath(manifest, args_odict, extracted_app_folder) + # build arg list tq + args_list = [value[0] for value in args_odict.values()] + args_list.append(app_instance_name) + # Attempt to patch legacy helpers ... _patch_legacy_helpers(extracted_app_folder) From ec9b020376b974653647e9e7edfab09a9d9733a9 Mon Sep 17 00:00:00 2001 From: Laurent Peuch Date: Sat, 16 May 2020 01:42:41 +0200 Subject: [PATCH 23/62] [mod] moar test for arguments parsing --- .../tests/test_apps_arguments_parsing.py | 88 +++++++++++++++++++ 1 file changed, 88 insertions(+) diff --git a/src/yunohost/tests/test_apps_arguments_parsing.py b/src/yunohost/tests/test_apps_arguments_parsing.py index 8fe3d7728..c92007873 100644 --- a/src/yunohost/tests/test_apps_arguments_parsing.py +++ b/src/yunohost/tests/test_apps_arguments_parsing.py @@ -98,6 +98,32 @@ def test_parse_args_in_yunohost_format_string_no_input_optional(): assert _parse_args_in_yunohost_format(answers, questions) == expected_result +def test_parse_args_in_yunohost_format_string_optional_with_input(): + questions = [{ + "name": "some_string", + "ask": "some question", + "optional": True, + }] + answers = {} + expected_result = OrderedDict({"some_string": ("some_value", "string")}) + + with patch.object(msignals, "prompt", return_value="some_value"): + assert _parse_args_in_yunohost_format(answers, questions) == expected_result + + +@pytest.mark.skip # this should work without ask +def test_parse_args_in_yunohost_format_string_optional_with_input_without_ask(): + questions = [{ + "name": "some_string", + "optional": True, + }] + answers = {} + expected_result = OrderedDict({"some_string": ("some_value", "string")}) + + with patch.object(msignals, "prompt", return_value="some_value"): + assert _parse_args_in_yunohost_format(answers, questions) == expected_result + + def test_parse_args_in_yunohost_format_string_no_input_default(): questions = [{ "name": "some_string", @@ -107,3 +133,65 @@ def test_parse_args_in_yunohost_format_string_no_input_default(): answers = {} expected_result = OrderedDict({"some_string": ("some_value", "string")}) assert _parse_args_in_yunohost_format(answers, questions) == expected_result + + +def test_parse_args_in_yunohost_format_string_input_test_ask(): + ask_text = "some question" + questions = [{ + "name": "some_string", + "ask": ask_text, + }] + answers = {} + + with patch.object(msignals, "prompt", return_value="some_value") as prompt: + _parse_args_in_yunohost_format(answers, questions) + prompt.assert_called_with(ask_text, False) + + +def test_parse_args_in_yunohost_format_string_input_test_ask_with_default(): + ask_text = "some question" + default_text = "some example" + questions = [{ + "name": "some_string", + "ask": ask_text, + "default": default_text, + }] + answers = {} + + with patch.object(msignals, "prompt", return_value="some_value") as prompt: + _parse_args_in_yunohost_format(answers, questions) + prompt.assert_called_with("%s (default: %s)" % (ask_text, default_text), False) + + +@pytest.mark.skip # we should do something with this example +def test_parse_args_in_yunohost_format_string_input_test_ask_with_example(): + ask_text = "some question" + example_text = "some example" + questions = [{ + "name": "some_string", + "ask": ask_text, + "example": example_text, + }] + answers = {} + + with patch.object(msignals, "prompt", return_value="some_value") as prompt: + _parse_args_in_yunohost_format(answers, questions) + assert ask_text in prompt.call_args[0] + assert example_text in prompt.call_args[0] + + +@pytest.mark.skip # we should do something with this help +def test_parse_args_in_yunohost_format_string_input_test_ask_with_help(): + ask_text = "some question" + help_text = "some_help" + questions = [{ + "name": "some_string", + "ask": ask_text, + "help": help_text, + }] + answers = {} + + with patch.object(msignals, "prompt", return_value="some_value") as prompt: + _parse_args_in_yunohost_format(answers, questions) + assert ask_text in prompt.call_args[0] + assert help_text in prompt.call_args[0] From e41d6186eee6cc76c2304d30b8a1afacac28ca52 Mon Sep 17 00:00:00 2001 From: Laurent Peuch Date: Sat, 16 May 2020 01:59:28 +0200 Subject: [PATCH 24/62] [mod] and more tests --- .../tests/test_apps_arguments_parsing.py | 23 +++++++++++++++++++ 1 file changed, 23 insertions(+) diff --git a/src/yunohost/tests/test_apps_arguments_parsing.py b/src/yunohost/tests/test_apps_arguments_parsing.py index c92007873..1b155656f 100644 --- a/src/yunohost/tests/test_apps_arguments_parsing.py +++ b/src/yunohost/tests/test_apps_arguments_parsing.py @@ -195,3 +195,26 @@ def test_parse_args_in_yunohost_format_string_input_test_ask_with_help(): _parse_args_in_yunohost_format(answers, questions) assert ask_text in prompt.call_args[0] assert help_text in prompt.call_args[0] + + +def test_parse_args_in_yunohost_format_string_with_choice(): + questions = [{ + "name": "some_string", + "type": "string", + "choices": ["fr", "en"] + }] + answers = {"some_string": "fr"} + expected_result = OrderedDict({"some_string": ("fr", "string")}) + assert _parse_args_in_yunohost_format(answers, questions) == expected_result + + +def test_parse_args_in_yunohost_format_string_with_choice_bad(): + questions = [{ + "name": "some_string", + "type": "string", + "choices": ["fr", "en"] + }] + answers = {"some_string": "bad"} + + with pytest.raises(YunohostError): + assert _parse_args_in_yunohost_format(answers, questions) From 1b52eafcb723cf0307eefbead1e99b9c23ae322b Mon Sep 17 00:00:00 2001 From: Laurent Peuch Date: Sat, 16 May 2020 02:48:01 +0200 Subject: [PATCH 25/62] [mod] blablabla testin' --- .../tests/test_apps_arguments_parsing.py | 50 +++++++++++++++++-- 1 file changed, 46 insertions(+), 4 deletions(-) diff --git a/src/yunohost/tests/test_apps_arguments_parsing.py b/src/yunohost/tests/test_apps_arguments_parsing.py index 1b155656f..a4acc20f4 100644 --- a/src/yunohost/tests/test_apps_arguments_parsing.py +++ b/src/yunohost/tests/test_apps_arguments_parsing.py @@ -176,8 +176,8 @@ def test_parse_args_in_yunohost_format_string_input_test_ask_with_example(): with patch.object(msignals, "prompt", return_value="some_value") as prompt: _parse_args_in_yunohost_format(answers, questions) - assert ask_text in prompt.call_args[0] - assert example_text in prompt.call_args[0] + assert ask_text in prompt.call_args[0][0] + assert example_text in prompt.call_args[0][0] @pytest.mark.skip # we should do something with this help @@ -193,8 +193,8 @@ def test_parse_args_in_yunohost_format_string_input_test_ask_with_help(): with patch.object(msignals, "prompt", return_value="some_value") as prompt: _parse_args_in_yunohost_format(answers, questions) - assert ask_text in prompt.call_args[0] - assert help_text in prompt.call_args[0] + assert ask_text in prompt.call_args[0][0] + assert help_text in prompt.call_args[0][0] def test_parse_args_in_yunohost_format_string_with_choice(): @@ -208,6 +208,18 @@ def test_parse_args_in_yunohost_format_string_with_choice(): assert _parse_args_in_yunohost_format(answers, questions) == expected_result +def test_parse_args_in_yunohost_format_string_with_choice_prompt(): + questions = [{ + "name": "some_string", + "type": "string", + "choices": ["fr", "en"] + }] + answers = {"some_string": "fr"} + expected_result = OrderedDict({"some_string": ("fr", "string")}) + with patch.object(msignals, "prompt", return_value="fr"): + assert _parse_args_in_yunohost_format(answers, questions) == expected_result + + def test_parse_args_in_yunohost_format_string_with_choice_bad(): questions = [{ "name": "some_string", @@ -218,3 +230,33 @@ def test_parse_args_in_yunohost_format_string_with_choice_bad(): with pytest.raises(YunohostError): assert _parse_args_in_yunohost_format(answers, questions) + + +def test_parse_args_in_yunohost_format_string_with_choice_ask(): + ask_text = "some question" + choices = ["fr", "en", "es", "it", "ru"] + questions = [{ + "name": "some_string", + "ask": ask_text, + "choices": choices, + }] + answers = {} + + with patch.object(msignals, "prompt", return_value="ru") as prompt: + _parse_args_in_yunohost_format(answers, questions) + assert ask_text in prompt.call_args[0][0] + + for choice in choices: + assert choice in prompt.call_args[0][0] + + +def test_parse_args_in_yunohost_format_string_with_choice_default(): + questions = [{ + "name": "some_string", + "type": "string", + "choices": ["fr", "en"], + "default": "en", + }] + answers = {} + expected_result = OrderedDict({"some_string": ("en", "string")}) + assert _parse_args_in_yunohost_format(answers, questions) == expected_result From ebf9fa9d71b3f93083617dda8c15191fca4790fa Mon Sep 17 00:00:00 2001 From: Laurent Peuch Date: Sat, 16 May 2020 03:19:15 +0200 Subject: [PATCH 26/62] [mod] moar tests and tests for password argument parsing --- .../tests/test_apps_arguments_parsing.py | 176 ++++++++++++++++++ 1 file changed, 176 insertions(+) diff --git a/src/yunohost/tests/test_apps_arguments_parsing.py b/src/yunohost/tests/test_apps_arguments_parsing.py index a4acc20f4..f3ec8e8f1 100644 --- a/src/yunohost/tests/test_apps_arguments_parsing.py +++ b/src/yunohost/tests/test_apps_arguments_parsing.py @@ -260,3 +260,179 @@ def test_parse_args_in_yunohost_format_string_with_choice_default(): answers = {} expected_result = OrderedDict({"some_string": ("en", "string")}) assert _parse_args_in_yunohost_format(answers, questions) == expected_result + + +def test_parse_args_in_yunohost_format_password(): + questions = [{ + "name": "some_password", + "type": "password", + }] + answers = {"some_password": "some_value"} + expected_result = OrderedDict({"some_password": ("some_value", "password")}) + assert _parse_args_in_yunohost_format(answers, questions) == expected_result + + +def test_parse_args_in_yunohost_format_password_default_type(): + questions = [{ + "name": "some_password", + "type": "password", + }] + answers = {"some_password": "some_value"} + expected_result = OrderedDict({"some_password": ("some_value", "password")}) + assert _parse_args_in_yunohost_format(answers, questions) == expected_result + + +def test_parse_args_in_yunohost_format_password_no_input(): + questions = [{ + "name": "some_password", + "type": "password", + }] + answers = {} + + with pytest.raises(YunohostError): + _parse_args_in_yunohost_format(answers, questions) + + +def test_parse_args_in_yunohost_format_password_input(): + questions = [{ + "name": "some_password", + "type": "password", + "ask": "some question", + }] + answers = {} + expected_result = OrderedDict({"some_password": ("some_value", "password")}) + + with patch.object(msignals, "prompt", return_value="some_value"): + assert _parse_args_in_yunohost_format(answers, questions) == expected_result + + +@pytest.mark.skip # that shit should work x( +def test_parse_args_in_yunohost_format_password_input_no_ask(): + questions = [{ + "name": "some_password", + "type": "password", + }] + answers = {} + expected_result = OrderedDict({"some_password": ("some_value", "password")}) + + with patch.object(msignals, "prompt", return_value="some_value"): + assert _parse_args_in_yunohost_format(answers, questions) == expected_result + + +def test_parse_args_in_yunohost_format_password_no_input_optional(): + questions = [{ + "name": "some_password", + "type": "password", + "optional": True, + }] + answers = {} + expected_result = OrderedDict({"some_password": ("", "password")}) + assert _parse_args_in_yunohost_format(answers, questions) == expected_result + + +def test_parse_args_in_yunohost_format_password_optional_with_input(): + questions = [{ + "name": "some_password", + "ask": "some question", + "type": "password", + "optional": True, + }] + answers = {} + expected_result = OrderedDict({"some_password": ("some_value", "password")}) + + with patch.object(msignals, "prompt", return_value="some_value"): + assert _parse_args_in_yunohost_format(answers, questions) == expected_result + + +@pytest.mark.skip # this should work without ask +def test_parse_args_in_yunohost_format_password_optional_with_input_without_ask(): + questions = [{ + "name": "some_password", + "type": "password", + "optional": True, + }] + answers = {} + expected_result = OrderedDict({"some_password": ("some_value", "password")}) + + with patch.object(msignals, "prompt", return_value="some_value"): + assert _parse_args_in_yunohost_format(answers, questions) == expected_result + + +@pytest.mark.skip # this should raises +def test_parse_args_in_yunohost_format_password_no_input_default(): + questions = [{ + "name": "some_password", + "type": "password", + "ask": "some question", + "default": "some_value", + }] + answers = {} + + # no default for password! + with pytest.raises(YunohostError): + _parse_args_in_yunohost_format(answers, questions) + + +@pytest.mark.skip # this should raises +def test_parse_args_in_yunohost_format_password_no_input_example(): + questions = [{ + "name": "some_password", + "type": "password", + "ask": "some question", + "example": "some_value", + }] + answers = {"some_password": "some_value"} + + # no example for password! + with pytest.raises(YunohostError): + _parse_args_in_yunohost_format(answers, questions) + + +def test_parse_args_in_yunohost_format_password_input_test_ask(): + ask_text = "some question" + questions = [{ + "name": "some_password", + "type": "password", + "ask": ask_text, + }] + answers = {} + + with patch.object(msignals, "prompt", return_value="some_value") as prompt: + _parse_args_in_yunohost_format(answers, questions) + prompt.assert_called_with(ask_text, True) + + +@pytest.mark.skip # we should do something with this example +def test_parse_args_in_yunohost_format_password_input_test_ask_with_example(): + ask_text = "some question" + example_text = "some example" + questions = [{ + "name": "some_password", + "type": "password", + "ask": ask_text, + "example": example_text, + }] + answers = {} + + with patch.object(msignals, "prompt", return_value="some_value") as prompt: + _parse_args_in_yunohost_format(answers, questions) + assert ask_text in prompt.call_args[0][0] + assert example_text in prompt.call_args[0][0] + + +@pytest.mark.skip # we should do something with this help +def test_parse_args_in_yunohost_format_password_input_test_ask_with_help(): + ask_text = "some question" + help_text = "some_help" + questions = [{ + "name": "some_password", + "type": "password", + "ask": ask_text, + "help": help_text, + }] + answers = {} + + with patch.object(msignals, "prompt", return_value="some_value") as prompt: + _parse_args_in_yunohost_format(answers, questions) + assert ask_text in prompt.call_args[0][0] + assert help_text in prompt.call_args[0][0] From d1d38b173cc404eccf165ffa2e8c82dfb815178e Mon Sep 17 00:00:00 2001 From: Laurent Peuch Date: Sat, 16 May 2020 03:25:51 +0200 Subject: [PATCH 27/62] [mod] add tests for path --- .../tests/test_apps_arguments_parsing.py | 174 +++++++++++++++++- 1 file changed, 164 insertions(+), 10 deletions(-) diff --git a/src/yunohost/tests/test_apps_arguments_parsing.py b/src/yunohost/tests/test_apps_arguments_parsing.py index f3ec8e8f1..da24245dd 100644 --- a/src/yunohost/tests/test_apps_arguments_parsing.py +++ b/src/yunohost/tests/test_apps_arguments_parsing.py @@ -272,16 +272,6 @@ def test_parse_args_in_yunohost_format_password(): assert _parse_args_in_yunohost_format(answers, questions) == expected_result -def test_parse_args_in_yunohost_format_password_default_type(): - questions = [{ - "name": "some_password", - "type": "password", - }] - answers = {"some_password": "some_value"} - expected_result = OrderedDict({"some_password": ("some_value", "password")}) - assert _parse_args_in_yunohost_format(answers, questions) == expected_result - - def test_parse_args_in_yunohost_format_password_no_input(): questions = [{ "name": "some_password", @@ -436,3 +426,167 @@ def test_parse_args_in_yunohost_format_password_input_test_ask_with_help(): _parse_args_in_yunohost_format(answers, questions) assert ask_text in prompt.call_args[0][0] assert help_text in prompt.call_args[0][0] + + +def test_parse_args_in_yunohost_format_path(): + questions = [{ + "name": "some_path", + "type": "path", + }] + answers = {"some_path": "some_value"} + expected_result = OrderedDict({"some_path": ("some_value", "path")}) + assert _parse_args_in_yunohost_format(answers, questions) == expected_result + + +def test_parse_args_in_yunohost_format_path_no_input(): + questions = [{ + "name": "some_path", + "type": "path", + }] + answers = {} + + with pytest.raises(YunohostError): + _parse_args_in_yunohost_format(answers, questions) + + +def test_parse_args_in_yunohost_format_path_input(): + questions = [{ + "name": "some_path", + "type": "path", + "ask": "some question", + }] + answers = {} + expected_result = OrderedDict({"some_path": ("some_value", "path")}) + + with patch.object(msignals, "prompt", return_value="some_value"): + assert _parse_args_in_yunohost_format(answers, questions) == expected_result + + +@pytest.mark.skip # that shit should work x( +def test_parse_args_in_yunohost_format_path_input_no_ask(): + questions = [{ + "name": "some_path", + "type": "path", + }] + answers = {} + expected_result = OrderedDict({"some_path": ("some_value", "path")}) + + with patch.object(msignals, "prompt", return_value="some_value"): + assert _parse_args_in_yunohost_format(answers, questions) == expected_result + + +def test_parse_args_in_yunohost_format_path_no_input_optional(): + questions = [{ + "name": "some_path", + "type": "path", + "optional": True, + }] + answers = {} + expected_result = OrderedDict({"some_path": ("", "path")}) + assert _parse_args_in_yunohost_format(answers, questions) == expected_result + + +def test_parse_args_in_yunohost_format_path_optional_with_input(): + questions = [{ + "name": "some_path", + "ask": "some question", + "type": "path", + "optional": True, + }] + answers = {} + expected_result = OrderedDict({"some_path": ("some_value", "path")}) + + with patch.object(msignals, "prompt", return_value="some_value"): + assert _parse_args_in_yunohost_format(answers, questions) == expected_result + + +@pytest.mark.skip # this should work without ask +def test_parse_args_in_yunohost_format_path_optional_with_input_without_ask(): + questions = [{ + "name": "some_path", + "type": "path", + "optional": True, + }] + answers = {} + expected_result = OrderedDict({"some_path": ("some_value", "path")}) + + with patch.object(msignals, "prompt", return_value="some_value"): + assert _parse_args_in_yunohost_format(answers, questions) == expected_result + + +def test_parse_args_in_yunohost_format_path_no_input_default(): + questions = [{ + "name": "some_path", + "ask": "some question", + "type": "path", + "default": "some_value", + }] + answers = {} + expected_result = OrderedDict({"some_path": ("some_value", "path")}) + assert _parse_args_in_yunohost_format(answers, questions) == expected_result + + +def test_parse_args_in_yunohost_format_path_input_test_ask(): + ask_text = "some question" + questions = [{ + "name": "some_path", + "type": "path", + "ask": ask_text, + }] + answers = {} + + with patch.object(msignals, "prompt", return_value="some_value") as prompt: + _parse_args_in_yunohost_format(answers, questions) + prompt.assert_called_with(ask_text, False) + + +def test_parse_args_in_yunohost_format_path_input_test_ask_with_default(): + ask_text = "some question" + default_text = "some example" + questions = [{ + "name": "some_path", + "type": "path", + "ask": ask_text, + "default": default_text, + }] + answers = {} + + with patch.object(msignals, "prompt", return_value="some_value") as prompt: + _parse_args_in_yunohost_format(answers, questions) + prompt.assert_called_with("%s (default: %s)" % (ask_text, default_text), False) + + +@pytest.mark.skip # we should do something with this example +def test_parse_args_in_yunohost_format_path_input_test_ask_with_example(): + ask_text = "some question" + example_text = "some example" + questions = [{ + "name": "some_path", + "type": "path", + "ask": ask_text, + "example": example_text, + }] + answers = {} + + with patch.object(msignals, "prompt", return_value="some_value") as prompt: + _parse_args_in_yunohost_format(answers, questions) + assert ask_text in prompt.call_args[0][0] + assert example_text in prompt.call_args[0][0] + + +@pytest.mark.skip # we should do something with this help +def test_parse_args_in_yunohost_format_path_input_test_ask_with_help(): + ask_text = "some question" + help_text = "some_help" + questions = [{ + "name": "some_path", + "type": "path", + "ask": ask_text, + "help": help_text, + }] + answers = {} + + with patch.object(msignals, "prompt", return_value="some_value") as prompt: + _parse_args_in_yunohost_format(answers, questions) + assert ask_text in prompt.call_args[0][0] + assert help_text in prompt.call_args[0][0] From e181866dcafb105a2604687bf202dc435526d3a4 Mon Sep 17 00:00:00 2001 From: Laurent Peuch Date: Sun, 17 May 2020 00:46:57 +0200 Subject: [PATCH 28/62] [mod] add tests for password --- .../tests/test_apps_arguments_parsing.py | 188 ++++++++++++++++++ 1 file changed, 188 insertions(+) diff --git a/src/yunohost/tests/test_apps_arguments_parsing.py b/src/yunohost/tests/test_apps_arguments_parsing.py index da24245dd..26cb4e9ab 100644 --- a/src/yunohost/tests/test_apps_arguments_parsing.py +++ b/src/yunohost/tests/test_apps_arguments_parsing.py @@ -590,3 +590,191 @@ def test_parse_args_in_yunohost_format_path_input_test_ask_with_help(): _parse_args_in_yunohost_format(answers, questions) assert ask_text in prompt.call_args[0][0] assert help_text in prompt.call_args[0][0] + + +def test_parse_args_in_yunohost_format_boolean(): + questions = [{ + "name": "some_boolean", + "type": "boolean", + }] + answers = {"some_boolean": "y"} + expected_result = OrderedDict({"some_boolean": (1, "boolean")}) + assert _parse_args_in_yunohost_format(answers, questions) == expected_result + + +def test_parse_args_in_yunohost_format_boolean_all_yes(): + questions = [{ + "name": "some_boolean", + "type": "boolean", + }] + expected_result = OrderedDict({"some_boolean": (1, "boolean")}) + assert _parse_args_in_yunohost_format({"some_boolean": "y"}, questions) == expected_result + assert _parse_args_in_yunohost_format({"some_boolean": "Y"}, questions) == expected_result + assert _parse_args_in_yunohost_format({"some_boolean": "yes"}, questions) == expected_result + assert _parse_args_in_yunohost_format({"some_boolean": "Yes"}, questions) == expected_result + assert _parse_args_in_yunohost_format({"some_boolean": "YES"}, questions) == expected_result + assert _parse_args_in_yunohost_format({"some_boolean": "1"}, questions) == expected_result + assert _parse_args_in_yunohost_format({"some_boolean": 1}, questions) == expected_result + assert _parse_args_in_yunohost_format({"some_boolean": True}, questions) == expected_result + + +def test_parse_args_in_yunohost_format_boolean_all_no(): + questions = [{ + "name": "some_boolean", + "type": "boolean", + }] + expected_result = OrderedDict({"some_boolean": (0, "boolean")}) + assert _parse_args_in_yunohost_format({"some_boolean": "n"}, questions) == expected_result + assert _parse_args_in_yunohost_format({"some_boolean": "N"}, questions) == expected_result + assert _parse_args_in_yunohost_format({"some_boolean": "no"}, questions) == expected_result + assert _parse_args_in_yunohost_format({"some_boolean": "No"}, questions) == expected_result + assert _parse_args_in_yunohost_format({"some_boolean": "No"}, questions) == expected_result + assert _parse_args_in_yunohost_format({"some_boolean": "0"}, questions) == expected_result + assert _parse_args_in_yunohost_format({"some_boolean": 0}, questions) == expected_result + assert _parse_args_in_yunohost_format({"some_boolean": False}, questions) == expected_result + + +# XXX apparently boolean are always False (0) by default, I'm not sure what to think about that +def test_parse_args_in_yunohost_format_boolean_no_input(): + questions = [{ + "name": "some_boolean", + "type": "boolean", + }] + answers = {} + + expected_result = OrderedDict({"some_boolean": (0, "boolean")}) + assert _parse_args_in_yunohost_format(answers, questions) == expected_result + + +def test_parse_args_in_yunohost_format_boolean_bad_input(): + questions = [{ + "name": "some_boolean", + "type": "boolean", + }] + answers = {"some_boolean": "stuff"} + + with pytest.raises(YunohostError): + _parse_args_in_yunohost_format(answers, questions) + + +def test_parse_args_in_yunohost_format_boolean_input(): + questions = [{ + "name": "some_boolean", + "type": "boolean", + "ask": "some question", + }] + answers = {} + + expected_result = OrderedDict({"some_boolean": (1, "boolean")}) + with patch.object(msignals, "prompt", return_value="y"): + assert _parse_args_in_yunohost_format(answers, questions) == expected_result + + expected_result = OrderedDict({"some_boolean": (0, "boolean")}) + with patch.object(msignals, "prompt", return_value="n"): + assert _parse_args_in_yunohost_format(answers, questions) == expected_result + + +@pytest.mark.skip # we should work +def test_parse_args_in_yunohost_format_boolean_input_no_ask(): + questions = [{ + "name": "some_boolean", + "type": "boolean", + }] + answers = {} + expected_result = OrderedDict({"some_boolean": ("some_value", "boolean")}) + + with patch.object(msignals, "prompt", return_value="y"): + assert _parse_args_in_yunohost_format(answers, questions) == expected_result + + +def test_parse_args_in_yunohost_format_boolean_no_input_optional(): + questions = [{ + "name": "some_boolean", + "type": "boolean", + "optional": True, + }] + answers = {} + expected_result = OrderedDict({"some_boolean": (0, "boolean")}) # default to false + assert _parse_args_in_yunohost_format(answers, questions) == expected_result + + +def test_parse_args_in_yunohost_format_boolean_optional_with_input(): + questions = [{ + "name": "some_boolean", + "ask": "some question", + "type": "boolean", + "optional": True, + }] + answers = {} + expected_result = OrderedDict({"some_boolean": (1, "boolean")}) + + with patch.object(msignals, "prompt", return_value="y"): + assert _parse_args_in_yunohost_format(answers, questions) == expected_result + + +def test_parse_args_in_yunohost_format_boolean_optional_with_input_without_ask(): + questions = [{ + "name": "some_boolean", + "type": "boolean", + "optional": True, + }] + answers = {} + expected_result = OrderedDict({"some_boolean": (0, "boolean")}) + + with patch.object(msignals, "prompt", return_value="n"): + assert _parse_args_in_yunohost_format(answers, questions) == expected_result + + +def test_parse_args_in_yunohost_format_boolean_no_input_default(): + questions = [{ + "name": "some_boolean", + "ask": "some question", + "type": "boolean", + "default": 0, + }] + answers = {} + expected_result = OrderedDict({"some_boolean": (0, "boolean")}) + assert _parse_args_in_yunohost_format(answers, questions) == expected_result + + +@pytest.mark.skip # we should raise +def test_parse_args_in_yunohost_format_boolean_bad_default(): + questions = [{ + "name": "some_boolean", + "ask": "some question", + "type": "boolean", + "default": "bad default", + }] + answers = {} + with pytest.raises(YunohostError): + _parse_args_in_yunohost_format(answers, questions) + + +def test_parse_args_in_yunohost_format_boolean_input_test_ask(): + ask_text = "some question" + questions = [{ + "name": "some_boolean", + "type": "boolean", + "ask": ask_text, + }] + answers = {} + + with patch.object(msignals, "prompt", return_value=0) as prompt: + _parse_args_in_yunohost_format(answers, questions) + prompt.assert_called_with(ask_text + " [yes | no] (default: no)", False) + + +def test_parse_args_in_yunohost_format_boolean_input_test_ask_with_default(): + ask_text = "some question" + default_text = 1 + questions = [{ + "name": "some_boolean", + "type": "boolean", + "ask": ask_text, + "default": default_text, + }] + answers = {} + + with patch.object(msignals, "prompt", return_value=1) as prompt: + _parse_args_in_yunohost_format(answers, questions) + prompt.assert_called_with("%s [yes | no] (default: yes)" % ask_text, False) From 69f8ab1ac45eb3f0d93c3ff1dd070f7240420f3c Mon Sep 17 00:00:00 2001 From: Laurent Peuch Date: Sun, 17 May 2020 02:04:50 +0200 Subject: [PATCH 29/62] [mod] black file --- .../tests/test_apps_arguments_parsing.py | 495 ++++++++---------- 1 file changed, 207 insertions(+), 288 deletions(-) diff --git a/src/yunohost/tests/test_apps_arguments_parsing.py b/src/yunohost/tests/test_apps_arguments_parsing.py index 26cb4e9ab..641823506 100644 --- a/src/yunohost/tests/test_apps_arguments_parsing.py +++ b/src/yunohost/tests/test_apps_arguments_parsing.py @@ -36,28 +36,21 @@ def test_parse_args_in_yunohost_format_empty(): def test_parse_args_in_yunohost_format_string(): - questions = [{ - "name": "some_string", - "type": "string", - }] + questions = [{"name": "some_string", "type": "string",}] answers = {"some_string": "some_value"} expected_result = OrderedDict({"some_string": ("some_value", "string")}) assert _parse_args_in_yunohost_format(answers, questions) == expected_result def test_parse_args_in_yunohost_format_string_default_type(): - questions = [{ - "name": "some_string", - }] + questions = [{"name": "some_string",}] answers = {"some_string": "some_value"} expected_result = OrderedDict({"some_string": ("some_value", "string")}) assert _parse_args_in_yunohost_format(answers, questions) == expected_result def test_parse_args_in_yunohost_format_string_no_input(): - questions = [{ - "name": "some_string", - }] + questions = [{"name": "some_string",}] answers = {} with pytest.raises(YunohostError): @@ -65,10 +58,7 @@ def test_parse_args_in_yunohost_format_string_no_input(): def test_parse_args_in_yunohost_format_string_input(): - questions = [{ - "name": "some_string", - "ask": "some question", - }] + questions = [{"name": "some_string", "ask": "some question",}] answers = {} expected_result = OrderedDict({"some_string": ("some_value", "string")}) @@ -78,9 +68,7 @@ def test_parse_args_in_yunohost_format_string_input(): @pytest.mark.skip # that shit should work x( def test_parse_args_in_yunohost_format_string_input_no_ask(): - questions = [{ - "name": "some_string", - }] + questions = [{"name": "some_string",}] answers = {} expected_result = OrderedDict({"some_string": ("some_value", "string")}) @@ -89,21 +77,14 @@ def test_parse_args_in_yunohost_format_string_input_no_ask(): def test_parse_args_in_yunohost_format_string_no_input_optional(): - questions = [{ - "name": "some_string", - "optional": True, - }] + questions = [{"name": "some_string", "optional": True,}] answers = {} expected_result = OrderedDict({"some_string": ("", "string")}) assert _parse_args_in_yunohost_format(answers, questions) == expected_result def test_parse_args_in_yunohost_format_string_optional_with_input(): - questions = [{ - "name": "some_string", - "ask": "some question", - "optional": True, - }] + questions = [{"name": "some_string", "ask": "some question", "optional": True,}] answers = {} expected_result = OrderedDict({"some_string": ("some_value", "string")}) @@ -113,10 +94,7 @@ def test_parse_args_in_yunohost_format_string_optional_with_input(): @pytest.mark.skip # this should work without ask def test_parse_args_in_yunohost_format_string_optional_with_input_without_ask(): - questions = [{ - "name": "some_string", - "optional": True, - }] + questions = [{"name": "some_string", "optional": True,}] answers = {} expected_result = OrderedDict({"some_string": ("some_value", "string")}) @@ -125,11 +103,9 @@ def test_parse_args_in_yunohost_format_string_optional_with_input_without_ask(): def test_parse_args_in_yunohost_format_string_no_input_default(): - questions = [{ - "name": "some_string", - "ask": "some question", - "default": "some_value", - }] + questions = [ + {"name": "some_string", "ask": "some question", "default": "some_value",} + ] answers = {} expected_result = OrderedDict({"some_string": ("some_value", "string")}) assert _parse_args_in_yunohost_format(answers, questions) == expected_result @@ -137,10 +113,7 @@ def test_parse_args_in_yunohost_format_string_no_input_default(): def test_parse_args_in_yunohost_format_string_input_test_ask(): ask_text = "some question" - questions = [{ - "name": "some_string", - "ask": ask_text, - }] + questions = [{"name": "some_string", "ask": ask_text,}] answers = {} with patch.object(msignals, "prompt", return_value="some_value") as prompt: @@ -151,11 +124,7 @@ def test_parse_args_in_yunohost_format_string_input_test_ask(): def test_parse_args_in_yunohost_format_string_input_test_ask_with_default(): ask_text = "some question" default_text = "some example" - questions = [{ - "name": "some_string", - "ask": ask_text, - "default": default_text, - }] + questions = [{"name": "some_string", "ask": ask_text, "default": default_text,}] answers = {} with patch.object(msignals, "prompt", return_value="some_value") as prompt: @@ -167,11 +136,7 @@ def test_parse_args_in_yunohost_format_string_input_test_ask_with_default(): def test_parse_args_in_yunohost_format_string_input_test_ask_with_example(): ask_text = "some question" example_text = "some example" - questions = [{ - "name": "some_string", - "ask": ask_text, - "example": example_text, - }] + questions = [{"name": "some_string", "ask": ask_text, "example": example_text,}] answers = {} with patch.object(msignals, "prompt", return_value="some_value") as prompt: @@ -184,11 +149,7 @@ def test_parse_args_in_yunohost_format_string_input_test_ask_with_example(): def test_parse_args_in_yunohost_format_string_input_test_ask_with_help(): ask_text = "some question" help_text = "some_help" - questions = [{ - "name": "some_string", - "ask": ask_text, - "help": help_text, - }] + questions = [{"name": "some_string", "ask": ask_text, "help": help_text,}] answers = {} with patch.object(msignals, "prompt", return_value="some_value") as prompt: @@ -198,22 +159,14 @@ def test_parse_args_in_yunohost_format_string_input_test_ask_with_help(): def test_parse_args_in_yunohost_format_string_with_choice(): - questions = [{ - "name": "some_string", - "type": "string", - "choices": ["fr", "en"] - }] + questions = [{"name": "some_string", "type": "string", "choices": ["fr", "en"]}] answers = {"some_string": "fr"} expected_result = OrderedDict({"some_string": ("fr", "string")}) assert _parse_args_in_yunohost_format(answers, questions) == expected_result def test_parse_args_in_yunohost_format_string_with_choice_prompt(): - questions = [{ - "name": "some_string", - "type": "string", - "choices": ["fr", "en"] - }] + questions = [{"name": "some_string", "type": "string", "choices": ["fr", "en"]}] answers = {"some_string": "fr"} expected_result = OrderedDict({"some_string": ("fr", "string")}) with patch.object(msignals, "prompt", return_value="fr"): @@ -221,11 +174,7 @@ def test_parse_args_in_yunohost_format_string_with_choice_prompt(): def test_parse_args_in_yunohost_format_string_with_choice_bad(): - questions = [{ - "name": "some_string", - "type": "string", - "choices": ["fr", "en"] - }] + questions = [{"name": "some_string", "type": "string", "choices": ["fr", "en"]}] answers = {"some_string": "bad"} with pytest.raises(YunohostError): @@ -235,11 +184,7 @@ def test_parse_args_in_yunohost_format_string_with_choice_bad(): def test_parse_args_in_yunohost_format_string_with_choice_ask(): ask_text = "some question" choices = ["fr", "en", "es", "it", "ru"] - questions = [{ - "name": "some_string", - "ask": ask_text, - "choices": choices, - }] + questions = [{"name": "some_string", "ask": ask_text, "choices": choices,}] answers = {} with patch.object(msignals, "prompt", return_value="ru") as prompt: @@ -251,32 +196,28 @@ def test_parse_args_in_yunohost_format_string_with_choice_ask(): def test_parse_args_in_yunohost_format_string_with_choice_default(): - questions = [{ - "name": "some_string", - "type": "string", - "choices": ["fr", "en"], - "default": "en", - }] + questions = [ + { + "name": "some_string", + "type": "string", + "choices": ["fr", "en"], + "default": "en", + } + ] answers = {} expected_result = OrderedDict({"some_string": ("en", "string")}) assert _parse_args_in_yunohost_format(answers, questions) == expected_result def test_parse_args_in_yunohost_format_password(): - questions = [{ - "name": "some_password", - "type": "password", - }] + questions = [{"name": "some_password", "type": "password",}] answers = {"some_password": "some_value"} expected_result = OrderedDict({"some_password": ("some_value", "password")}) assert _parse_args_in_yunohost_format(answers, questions) == expected_result def test_parse_args_in_yunohost_format_password_no_input(): - questions = [{ - "name": "some_password", - "type": "password", - }] + questions = [{"name": "some_password", "type": "password",}] answers = {} with pytest.raises(YunohostError): @@ -284,11 +225,7 @@ def test_parse_args_in_yunohost_format_password_no_input(): def test_parse_args_in_yunohost_format_password_input(): - questions = [{ - "name": "some_password", - "type": "password", - "ask": "some question", - }] + questions = [{"name": "some_password", "type": "password", "ask": "some question",}] answers = {} expected_result = OrderedDict({"some_password": ("some_value", "password")}) @@ -298,10 +235,7 @@ def test_parse_args_in_yunohost_format_password_input(): @pytest.mark.skip # that shit should work x( def test_parse_args_in_yunohost_format_password_input_no_ask(): - questions = [{ - "name": "some_password", - "type": "password", - }] + questions = [{"name": "some_password", "type": "password",}] answers = {} expected_result = OrderedDict({"some_password": ("some_value", "password")}) @@ -310,23 +244,21 @@ def test_parse_args_in_yunohost_format_password_input_no_ask(): def test_parse_args_in_yunohost_format_password_no_input_optional(): - questions = [{ - "name": "some_password", - "type": "password", - "optional": True, - }] + questions = [{"name": "some_password", "type": "password", "optional": True,}] answers = {} expected_result = OrderedDict({"some_password": ("", "password")}) assert _parse_args_in_yunohost_format(answers, questions) == expected_result def test_parse_args_in_yunohost_format_password_optional_with_input(): - questions = [{ - "name": "some_password", - "ask": "some question", - "type": "password", - "optional": True, - }] + questions = [ + { + "name": "some_password", + "ask": "some question", + "type": "password", + "optional": True, + } + ] answers = {} expected_result = OrderedDict({"some_password": ("some_value", "password")}) @@ -336,11 +268,7 @@ def test_parse_args_in_yunohost_format_password_optional_with_input(): @pytest.mark.skip # this should work without ask def test_parse_args_in_yunohost_format_password_optional_with_input_without_ask(): - questions = [{ - "name": "some_password", - "type": "password", - "optional": True, - }] + questions = [{"name": "some_password", "type": "password", "optional": True,}] answers = {} expected_result = OrderedDict({"some_password": ("some_value", "password")}) @@ -350,12 +278,14 @@ def test_parse_args_in_yunohost_format_password_optional_with_input_without_ask( @pytest.mark.skip # this should raises def test_parse_args_in_yunohost_format_password_no_input_default(): - questions = [{ - "name": "some_password", - "type": "password", - "ask": "some question", - "default": "some_value", - }] + questions = [ + { + "name": "some_password", + "type": "password", + "ask": "some question", + "default": "some_value", + } + ] answers = {} # no default for password! @@ -365,12 +295,14 @@ def test_parse_args_in_yunohost_format_password_no_input_default(): @pytest.mark.skip # this should raises def test_parse_args_in_yunohost_format_password_no_input_example(): - questions = [{ - "name": "some_password", - "type": "password", - "ask": "some question", - "example": "some_value", - }] + questions = [ + { + "name": "some_password", + "type": "password", + "ask": "some question", + "example": "some_value", + } + ] answers = {"some_password": "some_value"} # no example for password! @@ -380,11 +312,7 @@ def test_parse_args_in_yunohost_format_password_no_input_example(): def test_parse_args_in_yunohost_format_password_input_test_ask(): ask_text = "some question" - questions = [{ - "name": "some_password", - "type": "password", - "ask": ask_text, - }] + questions = [{"name": "some_password", "type": "password", "ask": ask_text,}] answers = {} with patch.object(msignals, "prompt", return_value="some_value") as prompt: @@ -396,12 +324,14 @@ def test_parse_args_in_yunohost_format_password_input_test_ask(): def test_parse_args_in_yunohost_format_password_input_test_ask_with_example(): ask_text = "some question" example_text = "some example" - questions = [{ - "name": "some_password", - "type": "password", - "ask": ask_text, - "example": example_text, - }] + questions = [ + { + "name": "some_password", + "type": "password", + "ask": ask_text, + "example": example_text, + } + ] answers = {} with patch.object(msignals, "prompt", return_value="some_value") as prompt: @@ -414,12 +344,14 @@ def test_parse_args_in_yunohost_format_password_input_test_ask_with_example(): def test_parse_args_in_yunohost_format_password_input_test_ask_with_help(): ask_text = "some question" help_text = "some_help" - questions = [{ - "name": "some_password", - "type": "password", - "ask": ask_text, - "help": help_text, - }] + questions = [ + { + "name": "some_password", + "type": "password", + "ask": ask_text, + "help": help_text, + } + ] answers = {} with patch.object(msignals, "prompt", return_value="some_value") as prompt: @@ -429,20 +361,14 @@ def test_parse_args_in_yunohost_format_password_input_test_ask_with_help(): def test_parse_args_in_yunohost_format_path(): - questions = [{ - "name": "some_path", - "type": "path", - }] + questions = [{"name": "some_path", "type": "path",}] answers = {"some_path": "some_value"} expected_result = OrderedDict({"some_path": ("some_value", "path")}) assert _parse_args_in_yunohost_format(answers, questions) == expected_result def test_parse_args_in_yunohost_format_path_no_input(): - questions = [{ - "name": "some_path", - "type": "path", - }] + questions = [{"name": "some_path", "type": "path",}] answers = {} with pytest.raises(YunohostError): @@ -450,11 +376,7 @@ def test_parse_args_in_yunohost_format_path_no_input(): def test_parse_args_in_yunohost_format_path_input(): - questions = [{ - "name": "some_path", - "type": "path", - "ask": "some question", - }] + questions = [{"name": "some_path", "type": "path", "ask": "some question",}] answers = {} expected_result = OrderedDict({"some_path": ("some_value", "path")}) @@ -464,10 +386,7 @@ def test_parse_args_in_yunohost_format_path_input(): @pytest.mark.skip # that shit should work x( def test_parse_args_in_yunohost_format_path_input_no_ask(): - questions = [{ - "name": "some_path", - "type": "path", - }] + questions = [{"name": "some_path", "type": "path",}] answers = {} expected_result = OrderedDict({"some_path": ("some_value", "path")}) @@ -476,23 +395,16 @@ def test_parse_args_in_yunohost_format_path_input_no_ask(): def test_parse_args_in_yunohost_format_path_no_input_optional(): - questions = [{ - "name": "some_path", - "type": "path", - "optional": True, - }] + questions = [{"name": "some_path", "type": "path", "optional": True,}] answers = {} expected_result = OrderedDict({"some_path": ("", "path")}) assert _parse_args_in_yunohost_format(answers, questions) == expected_result def test_parse_args_in_yunohost_format_path_optional_with_input(): - questions = [{ - "name": "some_path", - "ask": "some question", - "type": "path", - "optional": True, - }] + questions = [ + {"name": "some_path", "ask": "some question", "type": "path", "optional": True,} + ] answers = {} expected_result = OrderedDict({"some_path": ("some_value", "path")}) @@ -502,11 +414,7 @@ def test_parse_args_in_yunohost_format_path_optional_with_input(): @pytest.mark.skip # this should work without ask def test_parse_args_in_yunohost_format_path_optional_with_input_without_ask(): - questions = [{ - "name": "some_path", - "type": "path", - "optional": True, - }] + questions = [{"name": "some_path", "type": "path", "optional": True,}] answers = {} expected_result = OrderedDict({"some_path": ("some_value", "path")}) @@ -515,12 +423,14 @@ def test_parse_args_in_yunohost_format_path_optional_with_input_without_ask(): def test_parse_args_in_yunohost_format_path_no_input_default(): - questions = [{ - "name": "some_path", - "ask": "some question", - "type": "path", - "default": "some_value", - }] + questions = [ + { + "name": "some_path", + "ask": "some question", + "type": "path", + "default": "some_value", + } + ] answers = {} expected_result = OrderedDict({"some_path": ("some_value", "path")}) assert _parse_args_in_yunohost_format(answers, questions) == expected_result @@ -528,11 +438,7 @@ def test_parse_args_in_yunohost_format_path_no_input_default(): def test_parse_args_in_yunohost_format_path_input_test_ask(): ask_text = "some question" - questions = [{ - "name": "some_path", - "type": "path", - "ask": ask_text, - }] + questions = [{"name": "some_path", "type": "path", "ask": ask_text,}] answers = {} with patch.object(msignals, "prompt", return_value="some_value") as prompt: @@ -543,12 +449,9 @@ def test_parse_args_in_yunohost_format_path_input_test_ask(): def test_parse_args_in_yunohost_format_path_input_test_ask_with_default(): ask_text = "some question" default_text = "some example" - questions = [{ - "name": "some_path", - "type": "path", - "ask": ask_text, - "default": default_text, - }] + questions = [ + {"name": "some_path", "type": "path", "ask": ask_text, "default": default_text,} + ] answers = {} with patch.object(msignals, "prompt", return_value="some_value") as prompt: @@ -560,12 +463,9 @@ def test_parse_args_in_yunohost_format_path_input_test_ask_with_default(): def test_parse_args_in_yunohost_format_path_input_test_ask_with_example(): ask_text = "some question" example_text = "some example" - questions = [{ - "name": "some_path", - "type": "path", - "ask": ask_text, - "example": example_text, - }] + questions = [ + {"name": "some_path", "type": "path", "ask": ask_text, "example": example_text,} + ] answers = {} with patch.object(msignals, "prompt", return_value="some_value") as prompt: @@ -578,12 +478,9 @@ def test_parse_args_in_yunohost_format_path_input_test_ask_with_example(): def test_parse_args_in_yunohost_format_path_input_test_ask_with_help(): ask_text = "some question" help_text = "some_help" - questions = [{ - "name": "some_path", - "type": "path", - "ask": ask_text, - "help": help_text, - }] + questions = [ + {"name": "some_path", "type": "path", "ask": ask_text, "help": help_text,} + ] answers = {} with patch.object(msignals, "prompt", return_value="some_value") as prompt: @@ -593,53 +490,89 @@ def test_parse_args_in_yunohost_format_path_input_test_ask_with_help(): def test_parse_args_in_yunohost_format_boolean(): - questions = [{ - "name": "some_boolean", - "type": "boolean", - }] + questions = [{"name": "some_boolean", "type": "boolean",}] answers = {"some_boolean": "y"} expected_result = OrderedDict({"some_boolean": (1, "boolean")}) assert _parse_args_in_yunohost_format(answers, questions) == expected_result def test_parse_args_in_yunohost_format_boolean_all_yes(): - questions = [{ - "name": "some_boolean", - "type": "boolean", - }] + questions = [{"name": "some_boolean", "type": "boolean",}] expected_result = OrderedDict({"some_boolean": (1, "boolean")}) - assert _parse_args_in_yunohost_format({"some_boolean": "y"}, questions) == expected_result - assert _parse_args_in_yunohost_format({"some_boolean": "Y"}, questions) == expected_result - assert _parse_args_in_yunohost_format({"some_boolean": "yes"}, questions) == expected_result - assert _parse_args_in_yunohost_format({"some_boolean": "Yes"}, questions) == expected_result - assert _parse_args_in_yunohost_format({"some_boolean": "YES"}, questions) == expected_result - assert _parse_args_in_yunohost_format({"some_boolean": "1"}, questions) == expected_result - assert _parse_args_in_yunohost_format({"some_boolean": 1}, questions) == expected_result - assert _parse_args_in_yunohost_format({"some_boolean": True}, questions) == expected_result + assert ( + _parse_args_in_yunohost_format({"some_boolean": "y"}, questions) + == expected_result + ) + assert ( + _parse_args_in_yunohost_format({"some_boolean": "Y"}, questions) + == expected_result + ) + assert ( + _parse_args_in_yunohost_format({"some_boolean": "yes"}, questions) + == expected_result + ) + assert ( + _parse_args_in_yunohost_format({"some_boolean": "Yes"}, questions) + == expected_result + ) + assert ( + _parse_args_in_yunohost_format({"some_boolean": "YES"}, questions) + == expected_result + ) + assert ( + _parse_args_in_yunohost_format({"some_boolean": "1"}, questions) + == expected_result + ) + assert ( + _parse_args_in_yunohost_format({"some_boolean": 1}, questions) + == expected_result + ) + assert ( + _parse_args_in_yunohost_format({"some_boolean": True}, questions) + == expected_result + ) def test_parse_args_in_yunohost_format_boolean_all_no(): - questions = [{ - "name": "some_boolean", - "type": "boolean", - }] + questions = [{"name": "some_boolean", "type": "boolean",}] expected_result = OrderedDict({"some_boolean": (0, "boolean")}) - assert _parse_args_in_yunohost_format({"some_boolean": "n"}, questions) == expected_result - assert _parse_args_in_yunohost_format({"some_boolean": "N"}, questions) == expected_result - assert _parse_args_in_yunohost_format({"some_boolean": "no"}, questions) == expected_result - assert _parse_args_in_yunohost_format({"some_boolean": "No"}, questions) == expected_result - assert _parse_args_in_yunohost_format({"some_boolean": "No"}, questions) == expected_result - assert _parse_args_in_yunohost_format({"some_boolean": "0"}, questions) == expected_result - assert _parse_args_in_yunohost_format({"some_boolean": 0}, questions) == expected_result - assert _parse_args_in_yunohost_format({"some_boolean": False}, questions) == expected_result + assert ( + _parse_args_in_yunohost_format({"some_boolean": "n"}, questions) + == expected_result + ) + assert ( + _parse_args_in_yunohost_format({"some_boolean": "N"}, questions) + == expected_result + ) + assert ( + _parse_args_in_yunohost_format({"some_boolean": "no"}, questions) + == expected_result + ) + assert ( + _parse_args_in_yunohost_format({"some_boolean": "No"}, questions) + == expected_result + ) + assert ( + _parse_args_in_yunohost_format({"some_boolean": "No"}, questions) + == expected_result + ) + assert ( + _parse_args_in_yunohost_format({"some_boolean": "0"}, questions) + == expected_result + ) + assert ( + _parse_args_in_yunohost_format({"some_boolean": 0}, questions) + == expected_result + ) + assert ( + _parse_args_in_yunohost_format({"some_boolean": False}, questions) + == expected_result + ) # XXX apparently boolean are always False (0) by default, I'm not sure what to think about that def test_parse_args_in_yunohost_format_boolean_no_input(): - questions = [{ - "name": "some_boolean", - "type": "boolean", - }] + questions = [{"name": "some_boolean", "type": "boolean",}] answers = {} expected_result = OrderedDict({"some_boolean": (0, "boolean")}) @@ -647,10 +580,7 @@ def test_parse_args_in_yunohost_format_boolean_no_input(): def test_parse_args_in_yunohost_format_boolean_bad_input(): - questions = [{ - "name": "some_boolean", - "type": "boolean", - }] + questions = [{"name": "some_boolean", "type": "boolean",}] answers = {"some_boolean": "stuff"} with pytest.raises(YunohostError): @@ -658,11 +588,7 @@ def test_parse_args_in_yunohost_format_boolean_bad_input(): def test_parse_args_in_yunohost_format_boolean_input(): - questions = [{ - "name": "some_boolean", - "type": "boolean", - "ask": "some question", - }] + questions = [{"name": "some_boolean", "type": "boolean", "ask": "some question",}] answers = {} expected_result = OrderedDict({"some_boolean": (1, "boolean")}) @@ -676,10 +602,7 @@ def test_parse_args_in_yunohost_format_boolean_input(): @pytest.mark.skip # we should work def test_parse_args_in_yunohost_format_boolean_input_no_ask(): - questions = [{ - "name": "some_boolean", - "type": "boolean", - }] + questions = [{"name": "some_boolean", "type": "boolean",}] answers = {} expected_result = OrderedDict({"some_boolean": ("some_value", "boolean")}) @@ -688,23 +611,21 @@ def test_parse_args_in_yunohost_format_boolean_input_no_ask(): def test_parse_args_in_yunohost_format_boolean_no_input_optional(): - questions = [{ - "name": "some_boolean", - "type": "boolean", - "optional": True, - }] + questions = [{"name": "some_boolean", "type": "boolean", "optional": True,}] answers = {} expected_result = OrderedDict({"some_boolean": (0, "boolean")}) # default to false assert _parse_args_in_yunohost_format(answers, questions) == expected_result def test_parse_args_in_yunohost_format_boolean_optional_with_input(): - questions = [{ - "name": "some_boolean", - "ask": "some question", - "type": "boolean", - "optional": True, - }] + questions = [ + { + "name": "some_boolean", + "ask": "some question", + "type": "boolean", + "optional": True, + } + ] answers = {} expected_result = OrderedDict({"some_boolean": (1, "boolean")}) @@ -713,11 +634,7 @@ def test_parse_args_in_yunohost_format_boolean_optional_with_input(): def test_parse_args_in_yunohost_format_boolean_optional_with_input_without_ask(): - questions = [{ - "name": "some_boolean", - "type": "boolean", - "optional": True, - }] + questions = [{"name": "some_boolean", "type": "boolean", "optional": True,}] answers = {} expected_result = OrderedDict({"some_boolean": (0, "boolean")}) @@ -726,12 +643,14 @@ def test_parse_args_in_yunohost_format_boolean_optional_with_input_without_ask() def test_parse_args_in_yunohost_format_boolean_no_input_default(): - questions = [{ - "name": "some_boolean", - "ask": "some question", - "type": "boolean", - "default": 0, - }] + questions = [ + { + "name": "some_boolean", + "ask": "some question", + "type": "boolean", + "default": 0, + } + ] answers = {} expected_result = OrderedDict({"some_boolean": (0, "boolean")}) assert _parse_args_in_yunohost_format(answers, questions) == expected_result @@ -739,12 +658,14 @@ def test_parse_args_in_yunohost_format_boolean_no_input_default(): @pytest.mark.skip # we should raise def test_parse_args_in_yunohost_format_boolean_bad_default(): - questions = [{ - "name": "some_boolean", - "ask": "some question", - "type": "boolean", - "default": "bad default", - }] + questions = [ + { + "name": "some_boolean", + "ask": "some question", + "type": "boolean", + "default": "bad default", + } + ] answers = {} with pytest.raises(YunohostError): _parse_args_in_yunohost_format(answers, questions) @@ -752,11 +673,7 @@ def test_parse_args_in_yunohost_format_boolean_bad_default(): def test_parse_args_in_yunohost_format_boolean_input_test_ask(): ask_text = "some question" - questions = [{ - "name": "some_boolean", - "type": "boolean", - "ask": ask_text, - }] + questions = [{"name": "some_boolean", "type": "boolean", "ask": ask_text,}] answers = {} with patch.object(msignals, "prompt", return_value=0) as prompt: @@ -767,12 +684,14 @@ def test_parse_args_in_yunohost_format_boolean_input_test_ask(): def test_parse_args_in_yunohost_format_boolean_input_test_ask_with_default(): ask_text = "some question" default_text = 1 - questions = [{ - "name": "some_boolean", - "type": "boolean", - "ask": ask_text, - "default": default_text, - }] + questions = [ + { + "name": "some_boolean", + "type": "boolean", + "ask": ask_text, + "default": default_text, + } + ] answers = {} with patch.object(msignals, "prompt", return_value=1) as prompt: From 306f4e06ab0a40c568671c12b77ab45d5901ccb8 Mon Sep 17 00:00:00 2001 From: Laurent Peuch Date: Sun, 24 May 2020 01:11:30 +0200 Subject: [PATCH 30/62] [mod] add tests for domains --- .../tests/test_apps_arguments_parsing.py | 117 ++++++++++++++++++ 1 file changed, 117 insertions(+) diff --git a/src/yunohost/tests/test_apps_arguments_parsing.py b/src/yunohost/tests/test_apps_arguments_parsing.py index 641823506..61df50d87 100644 --- a/src/yunohost/tests/test_apps_arguments_parsing.py +++ b/src/yunohost/tests/test_apps_arguments_parsing.py @@ -4,6 +4,7 @@ from mock import patch from moulinette import msignals +from yunohost import domain from yunohost.app import _parse_args_in_yunohost_format from yunohost.utils.error import YunohostError @@ -697,3 +698,119 @@ def test_parse_args_in_yunohost_format_boolean_input_test_ask_with_default(): with patch.object(msignals, "prompt", return_value=1) as prompt: _parse_args_in_yunohost_format(answers, questions) prompt.assert_called_with("%s [yes | no] (default: yes)" % ask_text, False) + + +def test_parse_args_in_yunohost_format_domain_empty(): + questions = [{"name": "some_domain", "type": "domain",}] + answers = {} + + with patch.object( + domain, "_get_maindomain", return_value="my_main_domain.com" + ), patch.object( + domain, "domain_list", return_value={"domains": ["my_main_domain.com"]} + ): + with pytest.raises(YunohostError): + _parse_args_in_yunohost_format(answers, questions) + + +def test_parse_args_in_yunohost_format_domain(): + main_domain = "my_main_domain.com" + domains = [main_domain] + questions = [{"name": "some_domain", "type": "domain",}] + + answers = {"some_domain": main_domain} + expected_result = OrderedDict({"some_domain": (main_domain, "domain")}) + + with patch.object( + domain, "_get_maindomain", return_value=main_domain + ), patch.object(domain, "domain_list", return_value={"domains": domains}): + assert _parse_args_in_yunohost_format(answers, questions) == expected_result + + +def test_parse_args_in_yunohost_format_domain_two_domains(): + main_domain = "my_main_domain.com" + other_domain = "some_other_domain.tld" + domains = [main_domain, other_domain] + + questions = [{"name": "some_domain", "type": "domain",}] + answers = {"some_domain": other_domain} + expected_result = OrderedDict({"some_domain": (other_domain, "domain")}) + + with patch.object( + domain, "_get_maindomain", return_value=main_domain + ), patch.object(domain, "domain_list", return_value={"domains": domains}): + assert _parse_args_in_yunohost_format(answers, questions) == expected_result + + answers = {"some_domain": main_domain} + expected_result = OrderedDict({"some_domain": (main_domain, "domain")}) + + with patch.object( + domain, "_get_maindomain", return_value=main_domain + ), patch.object(domain, "domain_list", return_value={"domains": domains}): + assert _parse_args_in_yunohost_format(answers, questions) == expected_result + + +def test_parse_args_in_yunohost_format_domain_two_domains_wrong_answer(): + main_domain = "my_main_domain.com" + other_domain = "some_other_domain.tld" + domains = [main_domain, other_domain] + + questions = [{"name": "some_domain", "type": "domain",}] + answers = {"some_domain": "doesnt_exist.pouet"} + + with patch.object( + domain, "_get_maindomain", return_value=main_domain + ), patch.object(domain, "domain_list", return_value={"domains": domains}): + with pytest.raises(YunohostError): + _parse_args_in_yunohost_format(answers, questions) + + +@pytest.mark.skip # XXX should work +def test_parse_args_in_yunohost_format_domain_two_domains_default_no_ask(): + main_domain = "my_main_domain.com" + other_domain = "some_other_domain.tld" + domains = [main_domain, other_domain] + + questions = [{"name": "some_domain", "type": "domain",}] + answers = {} + expected_result = OrderedDict({"some_domain": (main_domain, "domain")}) + + with patch.object( + domain, "_get_maindomain", return_value=main_domain + ), patch.object(domain, "domain_list", return_value={"domains": domains}): + assert _parse_args_in_yunohost_format(answers, questions) == expected_result + + +def test_parse_args_in_yunohost_format_domain_two_domains_default(): + main_domain = "my_main_domain.com" + other_domain = "some_other_domain.tld" + domains = [main_domain, other_domain] + + questions = [{"name": "some_domain", "type": "domain", "ask": "choose a domain"}] + answers = {} + expected_result = OrderedDict({"some_domain": (main_domain, "domain")}) + + with patch.object( + domain, "_get_maindomain", return_value=main_domain + ), patch.object(domain, "domain_list", return_value={"domains": domains}): + assert _parse_args_in_yunohost_format(answers, questions) == expected_result + + +def test_parse_args_in_yunohost_format_domain_two_domains_default_input(): + main_domain = "my_main_domain.com" + other_domain = "some_other_domain.tld" + domains = [main_domain, other_domain] + + questions = [{"name": "some_domain", "type": "domain", "ask": "choose a domain"}] + answers = {} + + with patch.object( + domain, "_get_maindomain", return_value=main_domain + ), patch.object(domain, "domain_list", return_value={"domains": domains}): + expected_result = OrderedDict({"some_domain": (main_domain, "domain")}) + with patch.object(msignals, "prompt", return_value=main_domain): + assert _parse_args_in_yunohost_format(answers, questions) == expected_result + + expected_result = OrderedDict({"some_domain": (other_domain, "domain")}) + with patch.object(msignals, "prompt", return_value=other_domain): + assert _parse_args_in_yunohost_format(answers, questions) == expected_result From a8f8ee5e6cacc2a2e7248ffc081ffda2ac8e7b7f Mon Sep 17 00:00:00 2001 From: Laurent Peuch Date: Sun, 24 May 2020 04:22:34 +0200 Subject: [PATCH 31/62] [mod] add tests for user arguments parsing --- .../tests/test_apps_arguments_parsing.py | 175 +++++++++++++++++- 1 file changed, 174 insertions(+), 1 deletion(-) diff --git a/src/yunohost/tests/test_apps_arguments_parsing.py b/src/yunohost/tests/test_apps_arguments_parsing.py index 61df50d87..12ce9f693 100644 --- a/src/yunohost/tests/test_apps_arguments_parsing.py +++ b/src/yunohost/tests/test_apps_arguments_parsing.py @@ -4,7 +4,7 @@ from mock import patch from moulinette import msignals -from yunohost import domain +from yunohost import domain, user from yunohost.app import _parse_args_in_yunohost_format from yunohost.utils.error import YunohostError @@ -814,3 +814,176 @@ def test_parse_args_in_yunohost_format_domain_two_domains_default_input(): expected_result = OrderedDict({"some_domain": (other_domain, "domain")}) with patch.object(msignals, "prompt", return_value=other_domain): assert _parse_args_in_yunohost_format(answers, questions) == expected_result + + +def test_parse_args_in_yunohost_format_user_empty(): + users = { + "some_user": { + "ssh_allowed": False, + "username": "some_user", + "shell": "/bin/false", + "mailbox-quota": "0", + "mail": "p@ynh.local", + "fullname": "the first name the last name", + } + } + + questions = [{"name": "some_user", "type": "user",}] + answers = {} + + with patch.object(user, "user_list", return_value={"users": users}): + with pytest.raises(YunohostError): + _parse_args_in_yunohost_format(answers, questions) + + +def test_parse_args_in_yunohost_format_user(): + username = "some_user" + users = { + username: { + "ssh_allowed": False, + "username": "some_user", + "shell": "/bin/false", + "mailbox-quota": "0", + "mail": "p@ynh.local", + "fullname": "the first name the last name", + } + } + + questions = [{"name": "some_user", "type": "user",}] + answers = {"some_user": username} + + expected_result = OrderedDict({"some_user": (username, "user")}) + + with patch.object(user, "user_list", return_value={"users": users}): + assert _parse_args_in_yunohost_format(answers, questions) == expected_result + + +def test_parse_args_in_yunohost_format_user_two_users(): + username = "some_user" + other_user = "some_other_user" + users = { + username: { + "ssh_allowed": False, + "username": "some_user", + "shell": "/bin/false", + "mailbox-quota": "0", + "mail": "p@ynh.local", + "fullname": "the first name the last name", + }, + other_user: { + "ssh_allowed": False, + "username": "some_user", + "shell": "/bin/false", + "mailbox-quota": "0", + "mail": "z@ynh.local", + "fullname": "john doe", + }, + } + + questions = [{"name": "some_user", "type": "user",}] + answers = {"some_user": other_user} + expected_result = OrderedDict({"some_user": (other_user, "user")}) + + with patch.object(user, "user_list", return_value={"users": users}): + assert _parse_args_in_yunohost_format(answers, questions) == expected_result + + answers = {"some_user": username} + expected_result = OrderedDict({"some_user": (username, "user")}) + + with patch.object(user, "user_list", return_value={"users": users}): + assert _parse_args_in_yunohost_format(answers, questions) == expected_result + + +def test_parse_args_in_yunohost_format_user_two_users_wrong_answer(): + username = "my_username.com" + other_user = "some_other_user" + users = { + username: { + "ssh_allowed": False, + "username": "some_user", + "shell": "/bin/false", + "mailbox-quota": "0", + "mail": "p@ynh.local", + "fullname": "the first name the last name", + }, + other_user: { + "ssh_allowed": False, + "username": "some_user", + "shell": "/bin/false", + "mailbox-quota": "0", + "mail": "z@ynh.local", + "fullname": "john doe", + }, + } + + questions = [{"name": "some_user", "type": "user",}] + answers = {"some_user": "doesnt_exist.pouet"} + + with patch.object(user, "user_list", return_value={"users": users}): + with pytest.raises(YunohostError): + _parse_args_in_yunohost_format(answers, questions) + + +def test_parse_args_in_yunohost_format_user_two_users_no_default(): + username = "my_username.com" + other_user = "some_other_user.tld" + users = { + username: { + "ssh_allowed": False, + "username": "some_user", + "shell": "/bin/false", + "mailbox-quota": "0", + "mail": "p@ynh.local", + "fullname": "the first name the last name", + }, + other_user: { + "ssh_allowed": False, + "username": "some_user", + "shell": "/bin/false", + "mailbox-quota": "0", + "mail": "z@ynh.local", + "fullname": "john doe", + }, + } + + questions = [{"name": "some_user", "type": "user", "ask": "choose a user"}] + answers = {} + + with patch.object(user, "user_list", return_value={"users": users}): + with pytest.raises(YunohostError): + _parse_args_in_yunohost_format(answers, questions) + + +def test_parse_args_in_yunohost_format_user_two_users_default_input(): + username = "my_username.com" + other_user = "some_other_user.tld" + users = { + username: { + "ssh_allowed": False, + "username": "some_user", + "shell": "/bin/false", + "mailbox-quota": "0", + "mail": "p@ynh.local", + "fullname": "the first name the last name", + }, + other_user: { + "ssh_allowed": False, + "username": "some_user", + "shell": "/bin/false", + "mailbox-quota": "0", + "mail": "z@ynh.local", + "fullname": "john doe", + }, + } + + questions = [{"name": "some_user", "type": "user", "ask": "choose a user"}] + answers = {} + + with patch.object(user, "user_list", return_value={"users": users}): + expected_result = OrderedDict({"some_user": (username, "user")}) + with patch.object(msignals, "prompt", return_value=username): + assert _parse_args_in_yunohost_format(answers, questions) == expected_result + + expected_result = OrderedDict({"some_user": (other_user, "user")}) + with patch.object(msignals, "prompt", return_value=other_user): + assert _parse_args_in_yunohost_format(answers, questions) == expected_result From cf4580609807eb4800131967bdd814cf38237451 Mon Sep 17 00:00:00 2001 From: Vincent Rubiolo Date: Sun, 24 May 2020 16:41:49 +0200 Subject: [PATCH 32/62] Typo fix for error or diagnostics messages We are talking about expectations, not exceptions :-) --- locales/en.json | 2 +- src/yunohost/hook.py | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/locales/en.json b/locales/en.json index 851656532..d18870d89 100644 --- a/locales/en.json +++ b/locales/en.json @@ -171,7 +171,7 @@ "diagnosis_dns_good_conf": "DNS records are correctly configured for domain {domain} (category {category})", "diagnosis_dns_bad_conf": "Some DNS records are missing or incorrect for domain {domain} (category {category})", "diagnosis_dns_missing_record": "According to the recommended DNS configuration, you should add a DNS record with the following info.
Type: {type}
Name: {name}
Value: {value}", - "diagnosis_dns_discrepancy": "The following DNS record does not seem to follow the recommended configuration:
Type: {type}
Name: {name}
Current value: {current}
Excepted value: {value}", + "diagnosis_dns_discrepancy": "The following DNS record does not seem to follow the recommended configuration:
Type: {type}
Name: {name}
Current value: {current}
Expected value: {value}", "diagnosis_dns_point_to_doc": "Please check the documentation at https://yunohost.org/dns_config if you need help about configuring DNS records.", "diagnosis_domain_expiration_not_found": "Unable to check the expiration date for some domains", "diagnosis_domain_not_found_details": "The domain {domain} doesn't exist in WHOIS database or is expired!", diff --git a/src/yunohost/hook.py b/src/yunohost/hook.py index dbfd7eceb..b57300f54 100644 --- a/src/yunohost/hook.py +++ b/src/yunohost/hook.py @@ -432,7 +432,7 @@ def _hook_exec_bash(path, args, no_trace, chdir, env, user, return_format, logge returncontent[key] = value else: - raise YunohostError("Excepted value for return_format is either 'json' or 'plain_dict', got '%s'" % return_format) + raise YunohostError("Expected value for return_format is either 'json' or 'plain_dict', got '%s'" % return_format) finally: stdreturndir = os.path.split(stdreturn)[0] os.remove(stdreturn) From dc2214953d8e90af0ab4fe2fac009417729904a8 Mon Sep 17 00:00:00 2001 From: Alexandre Aubin Date: Mon, 25 May 2020 00:22:28 +0200 Subject: [PATCH 33/62] Bigger time window for auto diagnosis to avoid server overload --- data/hooks/conf_regen/01-yunohost | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/data/hooks/conf_regen/01-yunohost b/data/hooks/conf_regen/01-yunohost index 02f191c29..f699f105c 100755 --- a/data/hooks/conf_regen/01-yunohost +++ b/data/hooks/conf_regen/01-yunohost @@ -55,12 +55,12 @@ do_pre_regen() { fi # add cron job for diagnosis to be ran at 7h and 19h + a random delay between - # 0 and 10min, meant to avoid every instances running their diagnosis at + # 0 and 20min, meant to avoid every instances running their diagnosis at # exactly the same time, which may overload the diagnosis server. mkdir -p $pending_dir/etc/cron.d/ cat > $pending_dir/etc/cron.d/yunohost-diagnosis << EOF SHELL=/bin/bash -0 7,19 * * * root : YunoHost Automatic Diagnosis; sleep \$((RANDOM\\%600)); yunohost diagnosis run --email > /dev/null 2>/dev/null || echo "Running the automatic diagnosis failed miserably" +0 7,19 * * * root : YunoHost Automatic Diagnosis; sleep \$((RANDOM\\%1200)); yunohost diagnosis run --email > /dev/null 2>/dev/null || echo "Running the automatic diagnosis failed miserably" EOF } From 4c600125356ad4ec699c0ff9cc06214183034b09 Mon Sep 17 00:00:00 2001 From: Alexandre Aubin Date: Mon, 25 May 2020 04:46:49 +0200 Subject: [PATCH 34/62] Fix encoding bullshit --- src/yunohost/app.py | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/yunohost/app.py b/src/yunohost/app.py index 0b16123cb..7b5e8f031 100644 --- a/src/yunohost/app.py +++ b/src/yunohost/app.py @@ -1867,6 +1867,9 @@ def _get_app_settings(app_id): with open(os.path.join( APPS_SETTING_PATH, app_id, 'settings.yml')) as f: settings = yaml.load(f) + # If label contains unicode char, this may later trigger issues when building strings... + # FIXME: this should be propagated to read_yaml so that this fix applies everywhere I think... + settings = {k:_encode_string(v) for k,v in settings.items()} if app_id == settings['id']: return settings except (IOError, TypeError, KeyError): From 61e539f4ea9ba8db031d0c861d5eeb795c032edd Mon Sep 17 00:00:00 2001 From: Laurent Peuch Date: Mon, 25 May 2020 06:10:57 +0200 Subject: [PATCH 35/62] [mod] add tests for apps arguments parsing --- .../tests/test_apps_arguments_parsing.py | 199 +++++++++++++++++- 1 file changed, 198 insertions(+), 1 deletion(-) diff --git a/src/yunohost/tests/test_apps_arguments_parsing.py b/src/yunohost/tests/test_apps_arguments_parsing.py index 12ce9f693..491d7c512 100644 --- a/src/yunohost/tests/test_apps_arguments_parsing.py +++ b/src/yunohost/tests/test_apps_arguments_parsing.py @@ -4,7 +4,7 @@ from mock import patch from moulinette import msignals -from yunohost import domain, user +from yunohost import domain, user, app from yunohost.app import _parse_args_in_yunohost_format from yunohost.utils.error import YunohostError @@ -987,3 +987,200 @@ def test_parse_args_in_yunohost_format_user_two_users_default_input(): expected_result = OrderedDict({"some_user": (other_user, "user")}) with patch.object(msignals, "prompt", return_value=other_user): assert _parse_args_in_yunohost_format(answers, questions) == expected_result + + +def test_parse_args_in_yunohost_format_app_empty(): + apps = [ + { + "id": "my_webapp", + "version": "1.0~ynh2", + "description": "Custom Web app with SFTP access", + "name": "Custom Webapp", + } + ] + + questions = [{"name": "some_app", "type": "app",}] + answers = {} + + with patch.object(app, "app_list", return_value={"apps": apps}): + with pytest.raises(YunohostError): + _parse_args_in_yunohost_format(answers, questions) + + +def test_parse_args_in_yunohost_format_app_no_apps(): + apps = [] + questions = [{"name": "some_app", "type": "app",}] + answers = {} + + with patch.object(app, "app_list", return_value={"apps": apps}): + with pytest.raises(YunohostError): + _parse_args_in_yunohost_format(answers, questions) + + +@pytest.mark.skip # XXX should work +def test_parse_args_in_yunohost_format_app_no_apps_optional(): + apps = [] + questions = [{"name": "some_app", "type": "app", "optional": True}] + answers = {} + + with patch.object(app, "app_list", return_value={"apps": apps}): + assert _parse_args_in_yunohost_format(answers, questions) == [] + + +def test_parse_args_in_yunohost_format_app(): + app_name = "my_webapp" + apps = [ + { + "id": app_name, + "version": "1.0~ynh2", + "description": "Custom Web app with SFTP access", + "name": "Custom Webapp", + } + ] + + questions = [{"name": "some_app", "type": "app",}] + answers = {"some_app": app_name} + + expected_result = OrderedDict({"some_app": (app_name, "app")}) + + with patch.object(app, "app_list", return_value={"apps": apps}), patch.object( + app, + "_is_installed", + new_callable=lambda: lambda app_id: app_id in {x["id"] for x in apps}, + ): + assert _parse_args_in_yunohost_format(answers, questions) == expected_result + + +def test_parse_args_in_yunohost_format_app_two_apps(): + app_name = "my_webapp" + other_app = "some_other_app" + apps = [ + { + "id": app_name, + "version": "1.0~ynh2", + "description": "Custom Web app with SFTP access", + "name": "Custom Webapp", + }, + { + "id": other_app, + "version": "1.0", + "description": "blabla", + "name": "stuff", + }, + ] + + questions = [{"name": "some_app", "type": "app",}] + answers = {"some_app": other_app} + expected_result = OrderedDict({"some_app": (other_app, "app")}) + + with patch.object(app, "app_list", return_value={"apps": apps}), patch.object( + app, + "_is_installed", + new_callable=lambda: lambda app_id: app_id in {x["id"] for x in apps}, + ): + assert _parse_args_in_yunohost_format(answers, questions) == expected_result + + answers = {"some_app": app_name} + expected_result = OrderedDict({"some_app": (app_name, "app")}) + + with patch.object(app, "app_list", return_value={"apps": apps}), patch.object( + app, + "_is_installed", + new_callable=lambda: lambda app_id: app_id in {x["id"] for x in apps}, + ): + assert _parse_args_in_yunohost_format(answers, questions) == expected_result + + +def test_parse_args_in_yunohost_format_app_two_apps_wrong_answer(): + app_name = "my_webapp" + other_app = "some_other_app" + apps = [ + { + "id": app_name, + "version": "1.0~ynh2", + "description": "Custom Web app with SFTP access", + "name": "Custom Webapp", + }, + { + "id": other_app, + "version": "1.0", + "description": "blabla", + "name": "stuff", + }, + ] + + questions = [{"name": "some_app", "type": "app",}] + answers = {"some_app": "doesnt_exist"} + + with pytest.raises(YunohostError): + with patch.object(app, "app_list", return_value={"apps": apps}), patch.object( + app, + "_is_installed", + new_callable=lambda: lambda app_id: app_id in {x["id"] for x in apps}, + ): + _parse_args_in_yunohost_format(answers, questions) + + +def test_parse_args_in_yunohost_format_app_two_apps_no_default(): + app_name = "my_app_name.com" + other_app = "some_other_app" + apps = [ + { + "id": app_name, + "version": "1.0~ynh2", + "description": "Custom Web app with SFTP access", + "name": "Custom Webapp", + }, + { + "id": other_app, + "version": "1.0", + "description": "blabla", + "name": "stuff", + }, + ] + + questions = [{"name": "some_app", "type": "app", "ask": "choose a app"}] + answers = {} + + with patch.object(app, "app_list", return_value={"apps": apps}), patch.object( + app, + "_is_installed", + new_callable=lambda: lambda app_id: app_id in {x["id"] for x in apps}, + ): + with pytest.raises(YunohostError): + _parse_args_in_yunohost_format(answers, questions) + + +def test_parse_args_in_yunohost_format_app_two_apps_default_input(): + app_name = "my_app_name.com" + other_app = "some_other_app" + apps = [ + { + "id": app_name, + "version": "1.0~ynh2", + "description": "Custom Web app with SFTP access", + "name": "Custom Webapp", + }, + { + "id": other_app, + "version": "1.0", + "description": "blabla", + "name": "stuff", + }, + ] + + questions = [{"name": "some_app", "type": "app", "ask": "choose a app"}] + answers = {} + + with patch.object(app, "app_list", return_value={"apps": apps}), patch.object( + app, + "_is_installed", + new_callable=lambda: lambda app_id: app_id in {x["id"] for x in apps}, + ): + expected_result = OrderedDict({"some_app": (app_name, "app")}) + with patch.object(msignals, "prompt", return_value=app_name): + assert _parse_args_in_yunohost_format(answers, questions) == expected_result + + expected_result = OrderedDict({"some_app": (other_app, "app")}) + with patch.object(msignals, "prompt", return_value=other_app): + assert _parse_args_in_yunohost_format(answers, questions) == expected_result From 0aebd575f7215174bf9a11b80a99c0aeb38898bb Mon Sep 17 00:00:00 2001 From: Laurent Peuch Date: Mon, 25 May 2020 06:33:19 +0200 Subject: [PATCH 36/62] [mod] add tests for display_text arguments parsing --- src/yunohost/tests/test_apps_arguments_parsing.py | 14 +++++++++++++- 1 file changed, 13 insertions(+), 1 deletion(-) diff --git a/src/yunohost/tests/test_apps_arguments_parsing.py b/src/yunohost/tests/test_apps_arguments_parsing.py index 491d7c512..a3d5b7f09 100644 --- a/src/yunohost/tests/test_apps_arguments_parsing.py +++ b/src/yunohost/tests/test_apps_arguments_parsing.py @@ -1,6 +1,9 @@ +import sys import pytest -from collections import OrderedDict + from mock import patch +from StringIO import StringIO +from collections import OrderedDict from moulinette import msignals @@ -1184,3 +1187,12 @@ def test_parse_args_in_yunohost_format_app_two_apps_default_input(): expected_result = OrderedDict({"some_app": (other_app, "app")}) with patch.object(msignals, "prompt", return_value=other_app): assert _parse_args_in_yunohost_format(answers, questions) == expected_result + + +def test_parse_args_in_yunohost_format_display_text(): + questions = [{"name": "some_app", "type": "display_text", "ask": "foobar"}] + answers = {} + + with patch.object(sys, "stdout", new_callable=StringIO) as stdout: + _parse_args_in_yunohost_format(answers, questions) + assert "foobar" in stdout.getvalue() From 6db0879bb748b91e496171b72782b528a1734225 Mon Sep 17 00:00:00 2001 From: Kayou Date: Thu, 21 May 2020 10:25:27 +0000 Subject: [PATCH 37/62] Translated using Weblate (French) Currently translated at 99.7% (637 of 639 strings) Translation: YunoHost/core Translate-URL: https://translate.yunohost.org/projects/yunohost/core/fr/ --- locales/fr.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/locales/fr.json b/locales/fr.json index b92c828a2..6f2672b70 100644 --- a/locales/fr.json +++ b/locales/fr.json @@ -637,7 +637,7 @@ "diagnosis_http_hairpinning_issue_details": "C'est probablement à cause de la box/routeur de votre fournisseur d'accès internet. Par conséquent, les personnes extérieures à votre réseau local pourront accéder à votre serveur comme prévu, mais pas les personnes internes au réseau local (comme vous, probablement ?) si elles utilisent le nom de domaine ou l'IP globale. Vous pourrez peut-être améliorer la situation en consultant https://yunohost.org/dns_local_network", "diagnosis_http_partially_unreachable": "Le domaine {domain} semble inaccessible en HTTP depuis l’extérieur du réseau local en IPv{failed}, bien qu’il fonctionne en IPv{passed}.", "diagnosis_http_nginx_conf_not_up_to_date": "La configuration Nginx de ce domaine semble avoir été modifiée manuellement et empêche YunoHost de diagnostiquer si elle est accessible en HTTP.", - "diagnosis_http_nginx_conf_not_up_to_date_details": "Pour corriger la situation, inspectez la différence avec la ligne de commande en utilisant les outils yunohost regen-conf nginx --dry-run --with-diff et si vous êtes d’accord, appliquez les modifications avec yunohost tools regen-conf nginx --force.", + "diagnosis_http_nginx_conf_not_up_to_date_details": "Pour corriger la situation, inspectez la différence avec la ligne de commande en utilisant les outils yunohost tools regen-conf nginx --dry-run --with-diff et si vous êtes d’accord, appliquez les modifications avec yunohost tools regen-conf nginx --force.", "backup_archive_cant_retrieve_info_json": "Impossible d'avoir des informations sur l'archive '{archive}' ... Le fichier info.json ne peut pas être trouvé (ou n'est pas un fichier json valide).", "backup_archive_corrupted": "Il semble que l'archive de la sauvegarde '{archive}' est corrompue : {error}", "diagnosis_ip_no_ipv6_tip": "L'utilisation de IPv6 n'est pas obligatoire pour le fonctionnement de votre serveur, mais cela contribue à la santé d'Internet dans son ensemble. IPv6 généralement configuré automatiquement par votre système ou votre FAI s'il est disponible. Autrement, vous devrez prendre quelque minutes pour le configurer manuellement à l'aide de cette documentation: https://yunohost.org/#/ipv6. Si vous ne pouvez pas activer IPv6 ou si c'est trop technique pour vous, vous pouvez aussi ignorer cet avertissement sans que cela pose problème.", From f287c45f096cb18d9e8e14a7adcac5ee6667cd50 Mon Sep 17 00:00:00 2001 From: xaloc33 Date: Wed, 20 May 2020 21:53:12 +0000 Subject: [PATCH 38/62] Translated using Weblate (Catalan) Currently translated at 100.0% (639 of 639 strings) Translation: YunoHost/core Translate-URL: https://translate.yunohost.org/projects/yunohost/core/ca/ --- locales/ca.json | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/locales/ca.json b/locales/ca.json index 64ee60477..52f2e7f87 100644 --- a/locales/ca.json +++ b/locales/ca.json @@ -127,7 +127,7 @@ "confirm_app_install_thirdparty": "PERILL! Aquesta aplicació no es part del catàleg d'aplicacions de YunoHost. La instal·lació d'aplicacions de terceres parts pot comprometre la integritat i seguretat del seu sistema. No hauríeu d'instal·lar-ne a no ser que sapigueu el que feu. No obtindreu CAP AJUDA si l'aplicació no funciona o trenca el sistema… Si accepteu el risc, escriviu «{answers:s}»", "custom_app_url_required": "Heu de especificar una URL per actualitzar la vostra aplicació personalitzada {app:s}", "admin_password_too_long": "Trieu una contrasenya de menys de 127 caràcters", - "dpkg_is_broken": "No es pot fer això en aquest instant perquè dpkg/APT (els gestors de paquets del sistema) sembla estar mal configurat… Podeu intentar solucionar-ho connectant-vos per SSH i executant «sudo dpkg --configure -a».", + "dpkg_is_broken": "No es pot fer això en aquest instant perquè dpkg/APT (els gestors de paquets del sistema) sembla estar mal configurat… Podeu intentar solucionar-ho connectant-vos per SSH i executant «sudo apt install --fix-broken» i/o «sudo dpkg --configure -a».", "domain_cannot_remove_main": "No es pot eliminar «{domain:s}» ja que és el domini principal, primer s'ha d'establir un nou domini principal utilitzant «yunohost domain main-domain -n »; aquí hi ha una llista dels possibles dominis: {other_domains:s}", "domain_cert_gen_failed": "No s'ha pogut generar el certificat", "domain_created": "S'ha creat el domini", @@ -390,7 +390,7 @@ "ssowat_conf_updated": "S'ha actualitzat la configuració SSOwat", "system_upgraded": "S'ha actualitzat el sistema", "system_username_exists": "El nom d'usuari ja existeix en la llista d'usuaris de sistema", - "this_action_broke_dpkg": "Aquesta acció a trencat dpkg/APT (els gestors de paquets del sistema)… Podeu intentar resoldre el problema connectant-vos amb SSH i executant «sudo dpkg --configure -a».", + "this_action_broke_dpkg": "Aquesta acció a trencat dpkg/APT (els gestors de paquets del sistema)… Podeu intentar resoldre el problema connectant-vos amb SSH i executant «sudo apt install --fix-broken» i/o «sudo dpkg --configure -a».", "tools_upgrade_at_least_one": "Especifiqueu «--apps», o «--system»", "tools_upgrade_cant_both": "No es poden actualitzar tant el sistema com les aplicacions al mateix temps", "tools_upgrade_cant_hold_critical_packages": "No es poden mantenir els paquets crítics…", @@ -648,5 +648,6 @@ "diagnosis_domain_expiration_warning": "Alguns dominis expiraran properament!", "diagnosis_domain_expiration_error": "Alguns dominis expiraran EN BREUS!", "diagnosis_domain_expires_in": "{domain} expirarà en {days} dies.", - "diagnosis_swap_tip": "Vigileu i tingueu en compte que els servidor està allotjant memòria d'intercanvi en una targeta SD o en l'emmagatzematge SSD, això pot reduir dràsticament l'esperança de vida del dispositiu." + "diagnosis_swap_tip": "Vigileu i tingueu en compte que els servidor està allotjant memòria d'intercanvi en una targeta SD o en l'emmagatzematge SSD, això pot reduir dràsticament l'esperança de vida del dispositiu.", + "restore_already_installed_apps": "No s'han pogut restaurar les següents aplicacions perquè ja estan instal·lades: {apps}" } From b4730751bf853c135cb96fcafea674d9d8c80501 Mon Sep 17 00:00:00 2001 From: Kayou Date: Thu, 21 May 2020 10:40:57 +0000 Subject: [PATCH 39/62] Translated using Weblate (French) Currently translated at 99.7% (637 of 639 strings) Translation: YunoHost/core Translate-URL: https://translate.yunohost.org/projects/yunohost/core/fr/ --- locales/fr.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/locales/fr.json b/locales/fr.json index 6f2672b70..36fb1684b 100644 --- a/locales/fr.json +++ b/locales/fr.json @@ -618,7 +618,7 @@ "diagnosis_mail_queue_too_big": "Trop d’e-mails en attente dans la file d'attente ({nb_pending} e-mails)", "global_settings_setting_smtp_allow_ipv6": "Autoriser l'utilisation d’IPv6 pour recevoir et envoyer du courrier", "diagnosis_security_all_good": "Aucune vulnérabilité de sécurité critique n’a été trouvée.", - "diagnosis_display_tip": "Pour voir les problèmes détectés, vous pouvez accéder à la section Diagnostic du webadmin ou exécuter « yunohost diagnostic show --issues » à partir de la ligne de commande.", + "diagnosis_display_tip": "Pour voir les problèmes détectés, vous pouvez accéder à la section Diagnostic du webadmin ou exécuter « yunohost diagnosis show --issues » à partir de la ligne de commande.", "diagnosis_ip_global": "IP globale : {global}", "diagnosis_ip_local": "IP locale : {local}", "diagnosis_dns_point_to_doc": "Veuillez consulter la documentation sur https://yunohost.org/dns_config si vous avez besoin d’aide pour configurer les enregistrements DNS.", From 316da69c6d64f19b0e1bf04016752a77711e274d Mon Sep 17 00:00:00 2001 From: ButterflyOfFire Date: Thu, 21 May 2020 12:57:33 +0000 Subject: [PATCH 40/62] Translated using Weblate (Arabic) Currently translated at 12.8% (82 of 639 strings) Translation: YunoHost/core Translate-URL: https://translate.yunohost.org/projects/yunohost/core/ar/ --- locales/ar.json | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/locales/ar.json b/locales/ar.json index 9c1e67fe0..ca77f0d84 100644 --- a/locales/ar.json +++ b/locales/ar.json @@ -172,5 +172,7 @@ "apps_already_up_to_date": "كافة التطبيقات مُحدّثة", "app_remove_after_failed_install": "جارٍ حذف التطبيق بعدما فشل تنصيبها…", "apps_catalog_updating": "جارٍ تحديث فهرس التطبيقات…", - "apps_catalog_update_success": "تم تحديث فهرس التطبيقات!" + "apps_catalog_update_success": "تم تحديث فهرس التطبيقات!", + "diagnosis_domain_expiration_error": "ستنتهي مدة صلاحية بعض النطاقات في القريب العاجل!", + "diagnosis_domain_expiration_warning": "ستنتهي مدة صلاحية بعض النطاقات قريبًا!" } From b051e56ce640b467e25dce16a87d10cc2a818f07 Mon Sep 17 00:00:00 2001 From: Yasss Gurl Date: Sun, 24 May 2020 13:27:01 +0000 Subject: [PATCH 41/62] Translated using Weblate (German) Currently translated at 33.8% (216 of 639 strings) Translation: YunoHost/core Translate-URL: https://translate.yunohost.org/projects/yunohost/core/de/ --- locales/de.json | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/locales/de.json b/locales/de.json index 5b372edfc..c8a0246e9 100644 --- a/locales/de.json +++ b/locales/de.json @@ -183,7 +183,7 @@ "certmanager_conflicting_nginx_file": "Die Domain konnte nicht für die ACME challenge vorbereitet werden: Die nginx Konfigurationsdatei {filepath:s} verursacht Probleme und sollte vorher entfernt werden", "domain_cannot_remove_main": "Die primäre Domain konnten nicht entfernt werden. Lege zuerst einen neue primäre Domain fest", "certmanager_self_ca_conf_file_not_found": "Die Konfigurationsdatei der Zertifizierungsstelle für selbstsignierte Zertifikate wurde nicht gefunden (Datei {file:s})", - "certmanager_acme_not_configured_for_domain": "Das Zertifikat für die Domain '{domain:s}' scheint nicht richtig installiert zu sein. Bitte führe den Befehl cert-install für diese Domain nochmals aus.", + "certmanager_acme_not_configured_for_domain": "Die ACME Challenge kann im Moment nicht für {domain} ausgeführt werden, weil in ihrer nginx conf das entsprechende Code-Snippet fehlt... Bitte stellen Sie sicher, dass Ihre nginx-Konfiguration mit 'yunohost tools regen-conf nginx --dry-run --with-diff' auf dem neuesten Stand ist.", "certmanager_unable_to_parse_self_CA_name": "Der Name der Zertifizierungsstelle für selbstsignierte Zertifikate konnte nicht analysiert werden (Datei: {file:s})", "certmanager_http_check_timeout": "Eine Zeitüberschreitung ist aufgetreten, als der Server versuchte sich selbst über HTTP mit der öffentlichen IP (Domain '{domain:s}' mit der IP '{ip:s}') zu erreichen. Möglicherweise ist dafür hairpinning oder eine falsch konfigurierte Firewall/Router deines Servers dafür verantwortlich.", "certmanager_couldnt_fetch_intermediate_cert": "Eine Zeitüberschreitung ist aufgetreten als der Server versuchte die Teilzertifikate von Let's Encrypt zusammenzusetzen. Die Installation/Erneuerung des Zertifikats wurde abgebrochen — bitte versuche es später erneut.", @@ -338,5 +338,7 @@ "diagnosis_found_warnings": "Habe {warnings} Ding(e) gefunden, die verbessert werden könnten für {category}.", "diagnosis_ip_dnsresolution_working": "Domänen-Namens-Auflösung funktioniert!", "diagnosis_ip_weird_resolvconf": "DNS Auflösung scheint zu funktionieren, aber sei vorsichtig wenn du eine eigene /etc/resolv.conf verwendest.", - "diagnosis_display_tip": "Um die gefundenen Probleme zu sehen, kannst Du zum Diagnose-Bereich des webadmin gehen, oder 'yunohost diagnosis show --issues' in der Kommandozeile ausführen." + "diagnosis_display_tip": "Um die gefundenen Probleme zu sehen, kannst Du zum Diagnose-Bereich des webadmin gehen, oder 'yunohost diagnosis show --issues' in der Kommandozeile ausführen.", + "backup_archive_corrupted": "Das Backup-Archiv '{archive}' scheint beschädigt: {error}", + "backup_archive_cant_retrieve_info_json": "Die Informationen für das Archiv '{archive}' konnten nicht geladen werden... Die Datei info.json wurde nicht gefunden (oder ist kein gültiges json)." } From a81489815843d6e35029a736320b0b5e48c7d4ce Mon Sep 17 00:00:00 2001 From: ButterflyOfFire Date: Sun, 24 May 2020 08:36:58 +0000 Subject: [PATCH 42/62] Translated using Weblate (Arabic) Currently translated at 14.2% (91 of 639 strings) Translation: YunoHost/core Translate-URL: https://translate.yunohost.org/projects/yunohost/core/ar/ --- locales/ar.json | 13 +++++++++++-- 1 file changed, 11 insertions(+), 2 deletions(-) diff --git a/locales/ar.json b/locales/ar.json index ca77f0d84..cbfb7232c 100644 --- a/locales/ar.json +++ b/locales/ar.json @@ -164,7 +164,7 @@ "diagnosis_basesystem_kernel": "هذا الخادم يُشغّل نواة لينكس {kernel_version}", "diagnosis_basesystem_ynh_single_version": "{package} الإصدار: {version} ({repo})", "diagnosis_basesystem_ynh_main_version": "هذا الخادم يُشغّل YunoHost {main_version} ({repo})", - "diagnosis_everything_ok": "كل شيء على ما يرام في {category}!", + "diagnosis_everything_ok": "كل شيء يبدو على ما يرام في {category}!", "diagnosis_ip_connected_ipv4": "الخادم مُتّصل بالإنترنت عبر IPv4!", "diagnosis_ip_connected_ipv6": "الخادم مُتّصل بالإنترنت عبر IPv6!", "diagnosis_ip_not_connected_at_all": "يبدو أنّ الخادم غير مُتّصل بتاتا بالإنترنت!؟", @@ -174,5 +174,14 @@ "apps_catalog_updating": "جارٍ تحديث فهرس التطبيقات…", "apps_catalog_update_success": "تم تحديث فهرس التطبيقات!", "diagnosis_domain_expiration_error": "ستنتهي مدة صلاحية بعض النطاقات في القريب العاجل!", - "diagnosis_domain_expiration_warning": "ستنتهي مدة صلاحية بعض النطاقات قريبًا!" + "diagnosis_domain_expiration_warning": "ستنتهي مدة صلاحية بعض النطاقات قريبًا!", + "diagnosis_ports_could_not_diagnose_details": "خطأ: {error}", + "diagnosis_description_regenconf": "إعدادات النظام", + "diagnosis_description_mail": "البريد الإلكتروني", + "diagnosis_description_web": "الويب", + "diagnosis_description_systemresources": "موارد النظام", + "diagnosis_description_services": "حالة الخدمات", + "diagnosis_description_dnsrecords": "تسجيلات خدمة DNS", + "diagnosis_description_ip": "الإتصال بالإنترنت", + "diagnosis_description_basesystem": "النظام الأساسي" } From 0821f8e046701aadbdbb76f8714dfe4a18d46abc Mon Sep 17 00:00:00 2001 From: rynas Date: Sun, 24 May 2020 13:44:28 +0000 Subject: [PATCH 43/62] Translated using Weblate (German) Currently translated at 34.6% (221 of 639 strings) Translation: YunoHost/core Translate-URL: https://translate.yunohost.org/projects/yunohost/core/de/ --- locales/de.json | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/locales/de.json b/locales/de.json index c8a0246e9..0c5b031ce 100644 --- a/locales/de.json +++ b/locales/de.json @@ -167,16 +167,16 @@ "certmanager_attempt_to_replace_valid_cert": "Du versuchst gerade eine richtiges und gültiges Zertifikat der Domain {domain:s} zu überschreiben! (Benutze --force , um diese Nachricht zu umgehen)", "certmanager_domain_unknown": "Unbekannte Domain '{domain:s}'", "certmanager_domain_cert_not_selfsigned": "Das Zertifikat der Domain {domain:s} ist kein selbstsigniertes Zertifikat. Bist du dir sicher, dass du es ersetzen willst? (Benutze dafür '--force')", - "certmanager_certificate_fetching_or_enabling_failed": "Es scheint so als wäre die Aktivierung des Zertifikats für die Domain {domain:s} fehlgeschlagen...", + "certmanager_certificate_fetching_or_enabling_failed": "Die Aktivierung des neuen Zertifikats für die Domain {domain:s} ist fehlgeschlagen…", "certmanager_attempt_to_renew_nonLE_cert": "Das Zertifikat der Domain '{domain:s}' wurde nicht von Let's Encrypt ausgestellt. Es kann nicht automatisch erneuert werden!", "certmanager_attempt_to_renew_valid_cert": "Das Zertifikat der Domain {domain:s} läuft nicht in Kürze ab! (Benutze --force um diese Nachricht zu umgehen)", "certmanager_domain_http_not_working": "Es scheint so, dass die Domain {domain:s} nicht über HTTP erreicht werden kann. Bitte überprüfe, ob deine DNS und nginx Konfiguration in Ordnung ist", "certmanager_error_no_A_record": "Kein DNS 'A' Eintrag für die Domain {domain:s} gefunden. Dein Domainname muss auf diese Maschine weitergeleitet werden, um ein Let's Encrypt Zertifikat installieren zu können! (Wenn du weißt was du tust, kannst du --no-checks benutzen, um diese Überprüfung zu überspringen. )", "certmanager_domain_dns_ip_differs_from_public_ip": "Der DNS 'A' Eintrag der Domain {domain:s} unterscheidet sich von dieser Server-IP. Wenn du gerade deinen A Eintrag verändert hast, warte bitte etwas, damit die Änderungen wirksam werden (du kannst die DNS Propagation mittels Website überprüfen) (Wenn du weißt was du tust, kannst du --no-checks benutzen, um diese Überprüfung zu überspringen. )", "certmanager_cannot_read_cert": "Es ist ein Fehler aufgetreten, als es versucht wurde das aktuelle Zertifikat für die Domain {domain:s} zu öffnen (Datei: {file:s}), Grund: {reason:s}", - "certmanager_cert_install_success_selfsigned": "Ein selbstsigniertes Zertifikat für die Domain {domain:s} wurde erfolgreich installiert!", - "certmanager_cert_install_success": "Für die Domain {domain:s} wurde erfolgreich ein Let's Encrypt installiert!", - "certmanager_cert_renew_success": "Das Let's Encrypt Zertifikat für die Domain {domain:s} wurde erfolgreich erneuert!", + "certmanager_cert_install_success_selfsigned": "Ein selbstsigniertes Zertifikat für die Domain {domain:s} wurde erfolgreich installiert", + "certmanager_cert_install_success": "Für die Domain {domain:s} wurde erfolgreich ein Let's Encrypt Zertifikat installiert.", + "certmanager_cert_renew_success": "Das Let's Encrypt Zertifikat für die Domain {domain:s} wurde erfolgreich erneuert.", "certmanager_hit_rate_limit": "Es wurden innerhalb kurzer Zeit schon zu viele Zertifikate für die exakt gleiche Domain {domain:s} ausgestellt. Bitte versuche es später nochmal. Besuche https://letsencrypt.org/docs/rate-limits/ für mehr Informationen", "certmanager_cert_signing_failed": "Das neue Zertifikat konnte nicht signiert werden", "certmanager_no_cert_file": "Die Zertifikatsdatei für die Domain {domain:s} (Datei: {file:s}) konnte nicht gelesen werden", From 7b9e5ee8c15cc39c7d52b2f6779db6a5d252f3e6 Mon Sep 17 00:00:00 2001 From: Leandro Noferini Date: Sun, 24 May 2020 22:52:28 +0000 Subject: [PATCH 44/62] Translated using Weblate (Italian) Currently translated at 17.8% (114 of 639 strings) Translation: YunoHost/core Translate-URL: https://translate.yunohost.org/projects/yunohost/core/it/ --- locales/it.json | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/locales/it.json b/locales/it.json index 79204320b..f254d3407 100644 --- a/locales/it.json +++ b/locales/it.json @@ -45,8 +45,8 @@ "ask_new_admin_password": "Nuova password dell'amministrazione", "backup_app_failed": "Non è possibile fare il backup dell'applicazione '{app:s}'", "backup_archive_app_not_found": "L'applicazione '{app:s}' non è stata trovata nel archivio di backup", - "app_argument_choice_invalid": "Scelta non valida per l'argomento '{name:s}', deve essere uno di {choices:s}", - "app_argument_invalid": "Valore non valido per '{name:s}': {error:s}", + "app_argument_choice_invalid": "Usa una delle seguenti scelte '{choices:s}' per il parametro '{name:s}'", + "app_argument_invalid": "Scegli un valore valido per il parametro '{name:s}': {error:s}", "app_argument_required": "L'argomento '{name:s}' è requisito", "app_id_invalid": "Identificativo dell'applicazione non valido", "app_unsupported_remote_type": "Il tipo remoto usato per l'applicazione non è supportato", @@ -171,9 +171,9 @@ "certmanager_attempt_to_renew_nonLE_cert": "Il certificato per il dominio {domain:s} non è emesso da Let's Encrypt. Impossibile rinnovarlo automaticamente!", "certmanager_attempt_to_renew_valid_cert": "Il certificato per il dominio {domain:s} non è a scadere! Usa --force per ignorare", "certmanager_domain_http_not_working": "Sembra che non sia possibile accedere al dominio {domain:s} attraverso HTTP. Verifica la configurazione del DNS e di nginx", - "app_already_installed_cant_change_url": "Questa applicazione è già installata. L'URL non può essere cambiato solo da questa funzione. Guarda se `app changeurl` è disponibile.", + "app_already_installed_cant_change_url": "Questa applicazione è già installata. L'URL non può essere cambiato solo da questa funzione. Controlla se `app changeurl` è disponibile.", "app_already_up_to_date": "{app:s} è già aggiornata", - "app_change_url_failed_nginx_reload": "Riavvio di nginx fallito. Questo è il risultato di 'nginx -t':\n{nginx_errors:s}", + "app_change_url_failed_nginx_reload": "Non riesco a riavviare NGINX. Questo è il risultato di 'nginx -t':\n{nginx_errors:s}", "app_change_url_identical_domains": "Il vecchio ed il nuovo dominio/percorso_url sono identici ('{domain:s}{path:s}'), nessuna operazione necessaria.", "app_change_url_no_script": "L'applicazione '{app_name:s}' non supporta ancora la modifica dell'URL. Forse dovresti aggiornare l'applicazione.", "app_change_url_success": "URL dell'applicazione {app:s} cambiato con successo in {domain:s}{path:s}", @@ -233,7 +233,7 @@ "password_too_simple_4": "La password deve essere lunga almeno 12 caratteri e contenere numeri, maiuscole e minuscole", "users_available": "Utenti disponibili:", "yunohost_ca_creation_success": "L'autorità di certificazione locale è stata creata.", - "app_action_cannot_be_ran_because_required_services_down": "Questa app richiede alcuni servizi che attualmente non sono attivi. Prima di continuare, dovresti provare a riavviare i seguenti servizi (e possibilmente capire perchè questi non siano attivi) : {services}", + "app_action_cannot_be_ran_because_required_services_down": "I seguenti servizi dovrebbero essere in funzione per completare questa azione: {services}. Prova a riavviarli per proseguire (e possibilmente cercare di capire come ma non funzionano più).", "backup_output_symlink_dir_broken": "Hai un collegamento errato alla tua cartella di archiviazione '{path:s}'. Potresti avere delle impostazioni particolari per salvare i tuoi dati su un altro spazio, in questo caso probabilmente ti sei scordato di rimontare o collegare il tuo hard disk o la chiavetta usb.", "certmanager_conflicting_nginx_file": "Impossibile preparare il dominio per il controllo ACME: il file di configurazione nginx {filepath:s} è in conflitto e dovrebbe essere prima rimosso", "certmanager_couldnt_fetch_intermediate_cert": "Tempo scaduto durante il tentativo di recupero di un certificato intermedio da Let's Encrypt. Installazione/rinnovo non riuscito - per favore riprova più tardi.", @@ -335,5 +335,5 @@ "migration_0003_not_jessie": "La distribuzione attuale non è Jessie!", "migration_0003_system_not_fully_up_to_date": "Il tuo sistema non è completamente aggiornato. Per favore prima esegui un aggiornamento normale prima di migrare a stretch.", "this_action_broke_dpkg": "Questa azione ha danneggiato dpkg/apt (i gestori di pacchetti del sistema)… Puoi provare a risolvere questo problema connettendoti via SSH ed eseguendo `sudo dpkg --configure -a`.", - "app_action_broke_system": "Questa azione sembra avere roto servizi importanti: {services}" -} \ No newline at end of file + "app_action_broke_system": "Questa azione sembra avere rotto questi servizi importanti: {services}" +} From b8f8ea147dff0fd27a8145a6f3756eed05f3ad9c Mon Sep 17 00:00:00 2001 From: Alexandre Aubin Date: Tue, 26 May 2020 00:01:19 +0200 Subject: [PATCH 45/62] Fix fr translation format for DNS record missing / discrepancy --- locales/fr.json | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/locales/fr.json b/locales/fr.json index 36fb1684b..38a9ad5a7 100644 --- a/locales/fr.json +++ b/locales/fr.json @@ -509,7 +509,7 @@ "diagnosis_ip_not_connected_at_all": "Le serveur ne semble pas du tout connecté à Internet !?", "diagnosis_ip_weird_resolvconf": "La résolution DNS semble fonctionner, mais il semble que vous utilisez un /etc/resolv.conf personnalisé.", "diagnosis_ip_weird_resolvconf_details": "Le fichier /etc/resolv.conf doit être un lien symbolique vers /etc/resolvconf/run/resolv.conf lui-même pointant vers 127.0.0.1 (dnsmasq). Si vous souhaitez configurer manuellement les résolveurs DNS, veuillez modifier /etc/resolv.dnsmasq.conf.", - "diagnosis_dns_missing_record": "Selon la configuration DNS recommandée, vous devez ajouter un enregistrement DNS\nType : {type}\nNom : {name}\nValeur : {value}", + "diagnosis_dns_missing_record": "Selon la configuration DNS recommandée, vous devez ajouter un enregistrement DNS
Type : {type}
Nom : {name}
Valeur: {value}", "diagnosis_diskusage_ok": "L’espace de stockage {mountpoint} (sur le périphérique {device}) a encore {free} ({free_percent}%) espace restant (sur {total}) !", "diagnosis_ram_ok": "Le système dispose encore de {available} ({available_percent}%) de RAM sur {total}.", "diagnosis_regenconf_allgood": "Tous les fichiers de configuration sont conformes à la configuration recommandée !", @@ -535,7 +535,7 @@ "diagnosis_ip_broken_resolvconf": "La résolution du nom de domaine semble être cassée sur votre serveur, ce qui semble lié au fait que /etc/resolv.conf ne pointe pas vers 127.0.0.1.", "diagnosis_dns_good_conf": "Les enregistrements DNS sont correctement configurés pour le domaine {domain} (catégorie {category})", "diagnosis_dns_bad_conf": "Certains enregistrements DNS sont manquants ou incorrects pour le domaine {domain} (catégorie {category})", - "diagnosis_dns_discrepancy": "L’enregistrement DNS de type {type} et nom {name} ne correspond pas à la configuration recommandée.\nValeur actuelle : {current}\nValeur attendue : {value}", + "diagnosis_dns_discrepancy": "Cet enregistrement DNS ne semble pas correspondre à la configuration recommandée :
Type : {type}
Nom : {name}
Valeur actuelle : {current}
Valeur attendue : {value}", "diagnosis_services_bad_status": "Le service {service} est {status} :-(", "diagnosis_diskusage_verylow": "L'espace de stockage {mountpoint} (sur l’appareil {device}) ne dispose que de {free} ({free_percent}%) espace restant (sur {total}). Vous devriez vraiment envisager de nettoyer de l’espace !", "diagnosis_diskusage_low": "L'espace de stockage {mountpoint} (sur l'appareil {device}) ne dispose que de {free} ({free_percent}%) espace restant (sur {total}). Faites attention.", From 5a3b382fc9652f541778178d89e6496e7d8caad8 Mon Sep 17 00:00:00 2001 From: Alexandre Aubin Date: Tue, 26 May 2020 00:11:16 +0200 Subject: [PATCH 46/62] Flag old etckeeper.conf as 'should not exist' in regenconf --- data/hooks/conf_regen/01-yunohost | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/data/hooks/conf_regen/01-yunohost b/data/hooks/conf_regen/01-yunohost index f699f105c..abc6f3780 100755 --- a/data/hooks/conf_regen/01-yunohost +++ b/data/hooks/conf_regen/01-yunohost @@ -63,6 +63,10 @@ SHELL=/bin/bash 0 7,19 * * * root : YunoHost Automatic Diagnosis; sleep \$((RANDOM\\%1200)); yunohost diagnosis run --email > /dev/null 2>/dev/null || echo "Running the automatic diagnosis failed miserably" EOF + # legacy stuff to avoid yunohost reporting etckeeper as manually modified + # (this make sure that the hash is null / file is flagged as to-delete) + mkdir -p $pending_dir/etc/etckeeper + touch $pending_dir/etc/etckeeper/etckeeper.conf } do_post_regen() { From 8b169f138c81d4e616faef7f98cfca2080ae6521 Mon Sep 17 00:00:00 2001 From: Alexandre Aubin Date: Tue, 26 May 2020 00:32:53 +0200 Subject: [PATCH 47/62] Detect dyndns-domains managed by yunohost and advice to use yunohost dyndns update --force --- data/hooks/diagnosis/12-dnsrecords.py | 14 +++++++++----- locales/en.json | 1 + 2 files changed, 10 insertions(+), 5 deletions(-) diff --git a/data/hooks/diagnosis/12-dnsrecords.py b/data/hooks/diagnosis/12-dnsrecords.py index 560127bb0..91dec7006 100644 --- a/data/hooks/diagnosis/12-dnsrecords.py +++ b/data/hooks/diagnosis/12-dnsrecords.py @@ -12,9 +12,7 @@ from yunohost.utils.network import dig from yunohost.diagnosis import Diagnoser from yunohost.domain import domain_list, _build_dns_conf, _get_maindomain -# We put here domains we know has dyndns provider, but that are not yet -# registered in the public suffix list -PENDING_SUFFIX_LIST = ['ynh.fr', 'netlib.re'] +YNH_DYNDNS_DOMAINS = ['nohost.me', 'noho.st', 'ynh.fr'] class DNSRecordsDiagnoser(Diagnoser): @@ -38,7 +36,7 @@ class DNSRecordsDiagnoser(Diagnoser): psl = PublicSuffixList() domains_from_registrar = [psl.get_public_suffix(domain) for domain in all_domains] domains_from_registrar = [domain for domain in domains_from_registrar if "." in domain] - domains_from_registrar = set(domains_from_registrar) - set(PENDING_SUFFIX_LIST) + domains_from_registrar = set(domains_from_registrar) - set(YNH_DYNDNS_DOMAINS + ["netlib.re"]) for report in self.check_expiration_date(domains_from_registrar): yield report @@ -100,7 +98,13 @@ class DNSRecordsDiagnoser(Diagnoser): summary=summary) if discrepancies: - output["details"] = ["diagnosis_dns_point_to_doc"] + discrepancies + # For ynh-managed domains (nohost.me etc...), tell people to try to "yunohost dyndns update --force" + if any(domain.endswith(ynh_dyndns_domain) for ynh_dyndns_domain in YNH_DYNDNS_DOMAINS): + output["details"] = ["diagnosis_dns_try_dyndns_update_force"] + # Otherwise point to the documentation + else: + output["details"] = ["diagnosis_dns_point_to_doc"] + output["details"] += discrepancies yield output diff --git a/locales/en.json b/locales/en.json index d18870d89..05f097345 100644 --- a/locales/en.json +++ b/locales/en.json @@ -173,6 +173,7 @@ "diagnosis_dns_missing_record": "According to the recommended DNS configuration, you should add a DNS record with the following info.
Type: {type}
Name: {name}
Value: {value}", "diagnosis_dns_discrepancy": "The following DNS record does not seem to follow the recommended configuration:
Type: {type}
Name: {name}
Current value: {current}
Expected value: {value}", "diagnosis_dns_point_to_doc": "Please check the documentation at https://yunohost.org/dns_config if you need help about configuring DNS records.", + "diagnosis_dns_try_dyndns_update_force": "This domain's DNS configuration should automatically be managed by Yunohost. If that's not the case, you can try to force an update using yunohost dyndns update --force.", "diagnosis_domain_expiration_not_found": "Unable to check the expiration date for some domains", "diagnosis_domain_not_found_details": "The domain {domain} doesn't exist in WHOIS database or is expired!", "diagnosis_domain_expiration_not_found_details": "The WHOIS information for domain {domain} doesn't seem to contain the information about the expiration date?", From a23f02dbab2a751b3f40c009efe48d98d1c2464e Mon Sep 17 00:00:00 2001 From: Alexandre Aubin Date: Tue, 26 May 2020 00:56:27 +0200 Subject: [PATCH 48/62] Complain if apps savagely edit system configurations --- src/yunohost/app.py | 22 ++++++++++++++++++++-- 1 file changed, 20 insertions(+), 2 deletions(-) diff --git a/src/yunohost/app.py b/src/yunohost/app.py index 7b5e8f031..0cb420d16 100644 --- a/src/yunohost/app.py +++ b/src/yunohost/app.py @@ -451,6 +451,7 @@ def app_upgrade(app=[], url=None, file=None): """ from yunohost.hook import hook_add, hook_remove, hook_exec, hook_callback from yunohost.permission import permission_sync_to_user + from yunohost.regenconf import manually_modified_files apps = app # If no app is specified, upgrade all apps @@ -513,6 +514,9 @@ def app_upgrade(app=[], url=None, file=None): env_dict["YNH_APP_INSTANCE_NAME"] = app_instance_name env_dict["YNH_APP_INSTANCE_NUMBER"] = str(app_instance_nb) + # We'll check that the app didn't brutally edit some system configuration + manually_modified_files_before_install = manually_modified_files() + # Attempt to patch legacy helpers ... _patch_legacy_helpers(extracted_app_folder) @@ -563,6 +567,12 @@ def app_upgrade(app=[], url=None, file=None): logger.error(m18n.n("app_upgrade_failed", app=app_instance_name, error=str(e))) failure_message_with_debug_instructions = operation_logger.error(str(e)) + # We'll check that the app didn't brutally edit some system configuration + manually_modified_files_after_install = manually_modified_files() + manually_modified_files_by_app = set(manually_modified_files_after_install) - set(manually_modified_files_before_install) + if manually_modified_files_by_app: + logger.error("Packagers /!\\ This app manually modified some system configuration files! This should not happen! If you need to do so, you should implement a proper conf_regen hook. Those configuration were affected:\n - " + '\n -'.join(manually_modified_files_by_app)) + # If upgrade failed or broke the system, # raise an error and interrupt all other pending upgrades if upgrade_failed or broke_the_system: @@ -626,6 +636,7 @@ def app_install(operation_logger, app, label=None, args=None, no_remove_on_failu from yunohost.hook import hook_add, hook_remove, hook_exec, hook_callback from yunohost.log import OperationLogger from yunohost.permission import user_permission_list, permission_create, permission_url, permission_delete, permission_sync_to_user, user_permission_update + from yunohost.regenconf import manually_modified_files # Fetch or extract sources if not os.path.exists(INSTALL_TMP): @@ -732,10 +743,11 @@ def app_install(operation_logger, app, label=None, args=None, no_remove_on_failu env_dict["YNH_APP_ID"] = app_id env_dict["YNH_APP_INSTANCE_NAME"] = app_instance_name env_dict["YNH_APP_INSTANCE_NUMBER"] = str(instance_number) - - # Start register change on system operation_logger.extra.update({'env': env_dict}) + # We'll check that the app didn't brutally edit some system configuration + manually_modified_files_before_install = manually_modified_files() + # Tell the operation_logger to redact all password-type args # Also redact the % escaped version of the password that might appear in # the 'args' section of metadata (relevant for password with non-alphanumeric char) @@ -820,6 +832,12 @@ def app_install(operation_logger, app, label=None, args=None, no_remove_on_failu logger.error(m18n.n("app_install_failed", app=app_id, error=str(e))) failure_message_with_debug_instructions = operation_logger.error(str(e)) + # We'll check that the app didn't brutally edit some system configuration + manually_modified_files_after_install = manually_modified_files() + manually_modified_files_by_app = set(manually_modified_files_after_install) - set(manually_modified_files_before_install) + if manually_modified_files_by_app: + logger.error("Packagers /!\\ This app manually modified some system configuration files! This should not happen! If you need to do so, you should implement a proper conf_regen hook. Those configuration were affected:\n - " + '\n -'.join(manually_modified_files_by_app)) + # If the install failed or broke the system, we remove it if install_failed or broke_the_system: From 64596bc166165573d7ae6cd60e466f400e88dd07 Mon Sep 17 00:00:00 2001 From: Alexandre Aubin Date: Tue, 26 May 2020 03:17:51 +0200 Subject: [PATCH 49/62] Get rid of unicode warning --- src/yunohost/diagnosis.py | 2 +- src/yunohost/service.py | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/yunohost/diagnosis.py b/src/yunohost/diagnosis.py index 035e1a889..76c4d1243 100644 --- a/src/yunohost/diagnosis.py +++ b/src/yunohost/diagnosis.py @@ -452,7 +452,7 @@ class Diagnoser(): key = "diagnosis_description_" + id_ descr = m18n.n(key) # If no description available, fallback to id - return descr if descr != key else id_ + return descr if descr.decode('utf-8') != key else id_ @staticmethod def i18n(report, force_remove_html_tags=False): diff --git a/src/yunohost/service.py b/src/yunohost/service.py index fd65cbc0c..faaf70cdc 100644 --- a/src/yunohost/service.py +++ b/src/yunohost/service.py @@ -354,7 +354,7 @@ def _get_and_format_service_status(service, infos): # that mean that we don't have a translation for this string # that's the only way to test for that for now # if we don't have it, uses the one provided by systemd - if description == translation_key: + if description.decode('utf-8') == translation_key: description = str(raw_status.get("Description", "")) output = { From 056df9873c977da3afaeb7269caa69116b324bfc Mon Sep 17 00:00:00 2001 From: Alexandre Aubin Date: Tue, 26 May 2020 03:28:02 +0200 Subject: [PATCH 50/62] Update changelog for 3.8.4.5 --- debian/changelog | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) diff --git a/debian/changelog b/debian/changelog index ab7b110a3..bf391afb1 100644 --- a/debian/changelog +++ b/debian/changelog @@ -1,3 +1,21 @@ +yunohost (3.8.4.5) stable; urgency=low + + - [enh] Tell systemctl to stfu about creating symlinks when enabling/disabling services (6637c8a8) + - [enh] Add maindomain in diagnosis email subject (e30e25fa) + - [fix] Webpath should also be normalized for args_list, so that we can get rid of the 'malformed path' check of the CI... (58ce6e5e) + - [fix] Increase time window for auto diagnosis cron to avoid remote diagnosis server overload (dc221495) + - [fix] encoding bullshit (4c600125, 64596bc1) + - [fix] Typo in diagnosis message + fix FR translation report format of bad DNS conf (#1002, b8f8ea14) + - [fix] Flag old etckeeper.conf as 'should not exist' in regenconf (5a3b382f) + - [enh] Detect dyndns-domains managed by yunohost and advice to use yunohost dyndns update --force (8b169f13) + - [enh] Complain if apps savagely edit system configurations during install and upgrade (a23f02db) + - [i18n] Translations updated for Arabic, Catalan, French, German, Italian + - [tests] CI V2 : Rework CI workflow (#991) + + Thanks to all contributors <3 ! (ButterflyOfFire, Kay0u, L. Noferini, rynas, V. Rubiolo, xaloc33, Yasss Gurl) + + -- Alexandre Aubin Tue, 26 May 2020 03:20:39 +0200 + yunohost (3.8.4.4) stable; urgency=low - [fix] Crash when the services file is empty (85f1802) From 77bd9ae33f961d8f7081504fb57366692b2d2fae Mon Sep 17 00:00:00 2001 From: Alexandre Aubin Date: Tue, 26 May 2020 04:20:56 +0200 Subject: [PATCH 51/62] Stop trying to fetch log categories that are not implemented yet T.T --- src/yunohost/log.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/yunohost/log.py b/src/yunohost/log.py index de84280f0..5e3a1f411 100644 --- a/src/yunohost/log.py +++ b/src/yunohost/log.py @@ -40,8 +40,8 @@ from moulinette.utils.filesystem import read_file, read_yaml CATEGORIES_PATH = '/var/log/yunohost/categories/' OPERATIONS_PATH = '/var/log/yunohost/categories/operation/' -CATEGORIES = ['operation', 'history', 'package', 'system', 'access', 'service', - 'app'] +#CATEGORIES = ['operation', 'history', 'package', 'system', 'access', 'service', 'app'] +CATEGORIES = ['operation'] METADATA_FILE_EXT = '.yml' LOG_FILE_EXT = '.log' RELATED_CATEGORIES = ['app', 'domain', 'group', 'service', 'user'] @@ -63,7 +63,7 @@ def log_list(category=[], limit=None, with_details=False): # In cli we just display `operation` logs by default if not categories: - categories = ["operation"] if not is_api else CATEGORIES + categories = CATEGORIES result = collections.OrderedDict() for category in categories: From d80acdb198f263af27bec881318dd11750723ae8 Mon Sep 17 00:00:00 2001 From: Alexandre Aubin Date: Tue, 26 May 2020 04:29:19 +0200 Subject: [PATCH 52/62] Attempt to yolofix the tests --- .gitlab/ci/install.gitlab-ci.yml | 2 ++ 1 file changed, 2 insertions(+) diff --git a/.gitlab/ci/install.gitlab-ci.yml b/.gitlab/ci/install.gitlab-ci.yml index 8363b6e58..20a191757 100644 --- a/.gitlab/ci/install.gitlab-ci.yml +++ b/.gitlab/ci/install.gitlab-ci.yml @@ -16,6 +16,7 @@ upgrade: extends: .install-stage image: "after-install" script: + - apt update - DEBIAN_FRONTEND=noninteractive SUDO_FORCE_REMOVE=yes apt --assume-yes -o Dpkg::Options::="--force-confold" --allow-downgrades install ./$YNH_BUILD_DIR/*.deb @@ -23,5 +24,6 @@ install-postinstall: extends: .install-stage image: "before-install" script: + - apt update - DEBIAN_FRONTEND=noninteractive SUDO_FORCE_REMOVE=yes apt --assume-yes -o Dpkg::Options::="--force-confold" --allow-downgrades install ./$YNH_BUILD_DIR/*.deb - yunohost tools postinstall -d domain.tld -p the_password --ignore-dyndns From d24f317d58e1f1a93b3780de3320f22f76eb464a Mon Sep 17 00:00:00 2001 From: Alexandre Aubin Date: Tue, 26 May 2020 04:53:57 +0200 Subject: [PATCH 53/62] Moar test fixing --- .gitlab/ci/test.gitlab-ci.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/.gitlab/ci/test.gitlab-ci.yml b/.gitlab/ci/test.gitlab-ci.yml index b52e08085..06e9eeed6 100644 --- a/.gitlab/ci/test.gitlab-ci.yml +++ b/.gitlab/ci/test.gitlab-ci.yml @@ -1,4 +1,5 @@ .install_debs: &install_debs + - apt update - DEBIAN_FRONTEND=noninteractive SUDO_FORCE_REMOVE=yes apt --assume-yes -o Dpkg::Options::="--force-confold" --allow-downgrades install ./$YNH_BUILD_DIR/*.deb .test-stage: From 6b7f299dc68221c1baac43911b85e4b397defdbf Mon Sep 17 00:00:00 2001 From: Kay0u Date: Tue, 26 May 2020 18:12:07 +0200 Subject: [PATCH 54/62] Revert "Ugly hack to workaround sury pinning issues when installing dependencies" This reverts commit fc30d82df5a6aaae305489021c26b225530b398b. --- data/helpers.d/apt | 24 ++---------------------- 1 file changed, 2 insertions(+), 22 deletions(-) diff --git a/data/helpers.d/apt b/data/helpers.d/apt index c6621d814..e64a54058 100644 --- a/data/helpers.d/apt +++ b/data/helpers.d/apt @@ -193,37 +193,17 @@ ynh_package_install_from_equivs () { LC_ALL=C equivs-build ./control 1> /dev/null dpkg --force-depends --install "./${pkgname}_${pkgversion}_all.deb" 2>&1) - # Let's try to see if install will work using dry-run. It it fails, - # it could be because the pinning of sury is blocking some package install - # c.f. for example: https://github.com/YunoHost/issues/issues/1563#issuecomment-623406509 - # ... In that case, we use an ugly hack were we'll use a tweaked - # preferences.d directory with looser contrains for sury... - if ! ynh_package_install --fix-broken --dry-run >/dev/null 2>&1 && [ -e /etc/apt/preferences.d/extra_php_version ] - then - cp -r /etc/apt/preferences.d/ /etc/apt/preferences.d.tmp/ - sed 's/^Pin-Priority: .*/Pin-Priority: 600/g' -i /etc/apt/preferences.d.tmp/extra_php_version - local apt_tweaks='--option Dir::Etc::preferencesparts=preferences.d.tmp' - # Try a dry-run again to see if that fixes the issue ... - # If it did not, then that's probably not related to sury. - ynh_package_install $apt_tweaks --fix-broken --dry-run >/dev/null 2>&1 || apt_tweaks="" - else - local apt_tweaks="" - fi - - # Try to install for real - ynh_package_install $apt_tweaks --fix-broken || \ + ynh_package_install --fix-broken || \ { # If the installation failed # (the following is ran inside { } to not start a subshell otherwise ynh_die wouldnt exit the original process) - rm --recursive --force /etc/apt/preferences.d.tmp/ # Get the list of dependencies from the deb local dependencies="$(dpkg --info "$TMPDIR/${pkgname}_${pkgversion}_all.deb" | grep Depends | \ sed 's/^ Depends: //' | sed 's/,//g')" # Fake an install of those dependencies to see the errors # The sed command here is, Print only from '--fix-broken' to the end. - ynh_package_install $apt_tweaks $dependencies --dry-run | sed --quiet '/--fix-broken/,$p' >&2 + ynh_package_install $dependencies --dry-run | sed --quiet '/--fix-broken/,$p' >&2 ynh_die --message="Unable to install dependencies"; } [[ -n "$TMPDIR" ]] && rm --recursive --force $TMPDIR # Remove the temp dir. - rm --recursive --force /etc/apt/preferences.d.tmp/ # check if the package is actually installed ynh_package_is_installed "$pkgname" From a64dfd5676cc530dabcaa7124aa14d19d7b834f5 Mon Sep 17 00:00:00 2001 From: Kay0u Date: Tue, 26 May 2020 18:17:49 +0200 Subject: [PATCH 55/62] A better Pin for sury --- data/helpers.d/apt | 6 ++++-- data/helpers.d/php | 6 ++++-- 2 files changed, 8 insertions(+), 4 deletions(-) diff --git a/data/helpers.d/apt b/data/helpers.d/apt index e64a54058..31f7d4ffe 100644 --- a/data/helpers.d/apt +++ b/data/helpers.d/apt @@ -267,8 +267,10 @@ ynh_install_app_dependencies () { ynh_install_extra_repo --repo="https://packages.sury.org/php/ $(ynh_get_debian_release) main" --key="https://packages.sury.org/php/apt.gpg" --name=extra_php_version # Pin this sury repository to prevent sury of doing shit - ynh_pin_repo --package="*" --pin="origin \"packages.sury.org\"" --priority=200 --name=extra_php_version - ynh_pin_repo --package="php${YNH_DEFAULT_PHP_VERSION}*" --pin="origin \"packages.sury.org\"" --priority=600 --name=extra_php_version --append + for package_to_not_upgrade in "php" "php-fpm" "php-mysql" "php-xml" "php-zip" "php-mbstring" "php-ldap" "php-gd" "php-curl" "php-bz2" "php-json" "php-sqlite3" "php-intl" "openssl" "libssl1.1" "libssl-dev" + do + ynh_pin_repo --package="$package_to_not_upgrade" --pin="origin \"packages.sury.org\"" --priority="-1" --name=extra_php_version --append + done fi fi fi diff --git a/data/helpers.d/php b/data/helpers.d/php index 9b9df64f9..5d7b0b1e2 100644 --- a/data/helpers.d/php +++ b/data/helpers.d/php @@ -359,8 +359,10 @@ ynh_install_php () { update-alternatives --set php /usr/bin/php$YNH_DEFAULT_PHP_VERSION # Pin this extra repository after packages are installed to prevent sury of doing shit - ynh_pin_repo --package="*" --pin="origin \"packages.sury.org\"" --priority=200 --name=extra_php_version - ynh_pin_repo --package="php${YNH_DEFAULT_PHP_VERSION}*" --pin="origin \"packages.sury.org\"" --priority=600 --name=extra_php_version --append + for package_to_not_upgrade in "php" "php-fpm" "php-mysql" "php-xml" "php-zip" "php-mbstring" "php-ldap" "php-gd" "php-curl" "php-bz2" "php-json" "php-sqlite3" "php-intl" "openssl" "libssl1.1" "libssl-dev" + do + ynh_pin_repo --package="$package_to_not_upgrade" --pin="origin \"packages.sury.org\"" --priority="-1" --name=extra_php_version --append + done # Advertise service in admin panel yunohost service add php${phpversion}-fpm --log "/var/log/php${phpversion}-fpm.log" From a2b85b752384cd60055799578ff6afe31967e416 Mon Sep 17 00:00:00 2001 From: Gabriel Date: Tue, 26 May 2020 19:07:09 +0100 Subject: [PATCH 56/62] Add logging and persistent as default config for new muc room --- data/templates/metronome/domain.tpl.cfg.lua | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/data/templates/metronome/domain.tpl.cfg.lua b/data/templates/metronome/domain.tpl.cfg.lua index aa2f45e5a..e5e169791 100644 --- a/data/templates/metronome/domain.tpl.cfg.lua +++ b/data/templates/metronome/domain.tpl.cfg.lua @@ -47,6 +47,10 @@ Component "muc.{{ domain }}" "muc" muc_event_rate = 0.5 muc_burst_factor = 10 + room_default_config = { + logging = true, + persistent = true + }; ---Set up a PubSub server Component "pubsub.{{ domain }}" "pubsub" From b3db4d92fcac914f0eb50d41ceee9b89b3979f2c Mon Sep 17 00:00:00 2001 From: Alexandre Aubin Date: Wed, 27 May 2020 17:10:39 +0200 Subject: [PATCH 57/62] Bump server_names_hash_bucket_size to 128 to avoid nginx exploding for stupid reasons --- data/templates/nginx/plain/ssowat.conf | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/data/templates/nginx/plain/ssowat.conf b/data/templates/nginx/plain/ssowat.conf index c82cd40ea..bd8d5a73a 100644 --- a/data/templates/nginx/plain/ssowat.conf +++ b/data/templates/nginx/plain/ssowat.conf @@ -1,3 +1,3 @@ lua_shared_dict cache 10m; init_by_lua_file /usr/share/ssowat/init.lua; -server_names_hash_bucket_size 64; +server_names_hash_bucket_size 128; From 6ee6e78ead8e2dc9002b1e6bd903b3ab47ab3bee Mon Sep 17 00:00:00 2001 From: Alexandre Aubin Date: Thu, 28 May 2020 00:24:46 +0200 Subject: [PATCH 58/62] Update changelog for 3.8.4.6 --- debian/changelog | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/debian/changelog b/debian/changelog index bf391afb1..91f03aec8 100644 --- a/debian/changelog +++ b/debian/changelog @@ -1,3 +1,15 @@ +yunohost (3.8.4.6) stable; urgency=low + + - [fix] Bump server_names_hash_bucket_size to 128 to avoid nginx exploding for stupid reasons (b3db4d92) + - [fix] More sensible strategy for sury pinning ([#1006](https://github.com/YunoHost/yunohost/pull/1006)) + - [fix] Stop trying to fetch log categories that are not implemented yet T.T (77bd9ae3) + - [enh] Add logging and persistent as default config for new muc room ([#1008](https://github.com/YunoHost/yunohost/pull/1008)) + - [tests] Moar tests for app args parsing ([#1004](https://github.com/YunoHost/yunohost/pull/1004)) + + Thanks to all contributors <3 ! (Gabriel, Kay0u, Bram) + + -- Alexandre Aubin Thu, 28 May 2020 00:22:10 +0200 + yunohost (3.8.4.5) stable; urgency=low - [enh] Tell systemctl to stfu about creating symlinks when enabling/disabling services (6637c8a8) From 8ecd8fe6a334e578709120765468a5e8cb6ebd23 Mon Sep 17 00:00:00 2001 From: Alexandre Aubin Date: Thu, 28 May 2020 00:26:14 +0200 Subject: [PATCH 59/62] Clean markdown links in changelog --- debian/changelog | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/debian/changelog b/debian/changelog index 91f03aec8..2916f1b8f 100644 --- a/debian/changelog +++ b/debian/changelog @@ -1,10 +1,10 @@ yunohost (3.8.4.6) stable; urgency=low - [fix] Bump server_names_hash_bucket_size to 128 to avoid nginx exploding for stupid reasons (b3db4d92) - - [fix] More sensible strategy for sury pinning ([#1006](https://github.com/YunoHost/yunohost/pull/1006)) + - [fix] More sensible strategy for sury pinning (#1006) - [fix] Stop trying to fetch log categories that are not implemented yet T.T (77bd9ae3) - - [enh] Add logging and persistent as default config for new muc room ([#1008](https://github.com/YunoHost/yunohost/pull/1008)) - - [tests] Moar tests for app args parsing ([#1004](https://github.com/YunoHost/yunohost/pull/1004)) + - [enh] Add logging and persistent as default config for new muc room (#1008) + - [tests] Moar tests for app args parsing (#1004) Thanks to all contributors <3 ! (Gabriel, Kay0u, Bram) @@ -63,8 +63,8 @@ yunohost (3.8.4.2) testing; urgency=low - [fix] Diagnosis: Try to not have weird warnings if no diagnosis ran yet... (65c87d55) - [fix] Diagnosis: Change logic of --email to avoid sending empty mail if some issues are found but ignored (4cd4938e) - [enh] Diagnosis/services: Report the service status as warning/unknown if service type is oneshot and status exited (dd09758f, 1cd7ffea) - - [fix] Rework ynh_psql_test_if_first_run ([#993](https://github.com/yunohost/yunohost/pull/993)) - - [tests] Tests for args parsing ([#989](https://github.com/yunohost/yunohost/pull/989), 108a3ca4) + - [fix] Rework ynh_psql_test_if_first_run (#993) + - [tests] Tests for args parsing (#989, 108a3ca4) Thanks to all contributors <3 ! (Bram, Kayou) @@ -1743,7 +1743,7 @@ yunohost (2.5.2) testing; urgency=low Other fixes and improvements: * [enh] remove timeout from cli interface - * [fix] [#662](https://dev.yunohost.org/issues/662): missing 'python-openssl' dependency for Let's Encrypt integration. + * [fix] #662: missing 'python-openssl' dependency for Let's Encrypt integration. * [fix] --no-remove-on-failure for app install should behave as a flag. * [fix] don't remove trailing char if it's not a slash From 17eec25ed2b95994f464bbedda09f0d4d59fb292 Mon Sep 17 00:00:00 2001 From: Alexandre Aubin Date: Thu, 28 May 2020 15:03:23 +0200 Subject: [PATCH 60/62] Buuuurn glances --- data/hooks/conf_regen/40-glances | 36 -------------------------------- src/yunohost/regenconf.py | 5 +++++ 2 files changed, 5 insertions(+), 36 deletions(-) delete mode 100755 data/hooks/conf_regen/40-glances diff --git a/data/hooks/conf_regen/40-glances b/data/hooks/conf_regen/40-glances deleted file mode 100755 index 70b8f4b5a..000000000 --- a/data/hooks/conf_regen/40-glances +++ /dev/null @@ -1,36 +0,0 @@ -#!/bin/bash - -set -e - -do_pre_regen() { - pending_dir=$1 - - cd /usr/share/yunohost/templates/glances - - install -D -m 644 glances.default "${pending_dir}/etc/default/glances" -} - -do_post_regen() { - regen_conf_files=$1 - - [[ -z "$regen_conf_files" ]] \ - || service glances restart -} - -FORCE=${2:-0} -DRY_RUN=${3:-0} - -case "$1" in - pre) - do_pre_regen $4 - ;; - post) - do_post_regen $4 - ;; - *) - echo "hook called with unknown argument \`$1'" >&2 - exit 1 - ;; -esac - -exit 0 diff --git a/src/yunohost/regenconf.py b/src/yunohost/regenconf.py index d1c90ceee..53deb7073 100644 --- a/src/yunohost/regenconf.py +++ b/src/yunohost/regenconf.py @@ -346,6 +346,11 @@ def _save_regenconf_infos(infos): Keyword argument: categories -- A dict containing the regenconf infos """ + + # Ugly hack to get rid of legacy glances stuff + if "glances" in infos: + del infos["glances"] + try: with open(REGEN_CONF_FILE, 'w') as f: yaml.safe_dump(infos, f, default_flow_style=False) From 852cd14c4bf1301e197fe2b37d077bbed386420f Mon Sep 17 00:00:00 2001 From: Alexandre Aubin Date: Tue, 2 Jun 2020 16:48:19 +0200 Subject: [PATCH 61/62] Force external resolution for reverse DNS dig --- data/hooks/diagnosis/24-mail.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/data/hooks/diagnosis/24-mail.py b/data/hooks/diagnosis/24-mail.py index bc159c3b7..a483e676d 100644 --- a/data/hooks/diagnosis/24-mail.py +++ b/data/hooks/diagnosis/24-mail.py @@ -126,7 +126,7 @@ class MailDiagnoser(Diagnoser): query += '.ip6.arpa' # Do the DNS Query - status, value = dig(query, 'PTR') + status, value = dig(query, 'PTR', resolvers="force_external") if status == "nok": yield dict(meta={"test": "mail_fcrdns", "ipversion": ipversion}, data={"ip": ip, "ehlo_domain": self.ehlo_domain}, From e24191ce643772b785b793231b466bc51c902f9a Mon Sep 17 00:00:00 2001 From: Alexandre Aubin Date: Tue, 2 Jun 2020 17:00:52 +0200 Subject: [PATCH 62/62] Make sure mysql is an alias to mariadb --- data/hooks/conf_regen/34-mysql | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/data/hooks/conf_regen/34-mysql b/data/hooks/conf_regen/34-mysql index 43f9fdde1..74bafbf71 100755 --- a/data/hooks/conf_regen/34-mysql +++ b/data/hooks/conf_regen/34-mysql @@ -15,6 +15,16 @@ do_pre_regen() { do_post_regen() { regen_conf_files=$1 + # mysql is supposed to be an alias to mariadb... but in some weird case is not + # c.f. https://forum.yunohost.org/t/mysql-ne-fonctionne-pas/11661 + # Playing with enable/disable allows to recreate the proper symlinks. + if [ ! -e /etc/systemd/system/mysql.service ] + then + systemctl disable mysql -q + systemctl disable mariadb -q + systemctl enable mariadb -q + fi + if [ ! -f /etc/yunohost/mysql ]; then # ensure that mysql is running