diff --git a/roles/ensure-tox/README.rst b/roles/ensure-tox/README.rst index 60e0cac34..6ea07728d 100644 --- a/roles/ensure-tox/README.rst +++ b/roles/ensure-tox/README.rst @@ -2,3 +2,26 @@ Ensure tox is installed If tox is not already installed, it will be installed via pip in the user install directory (i.e., "pip install --user"). + +If tox is already installed and working and user does not specify a +``tox_condition`` or enable `tox_upgrade`, this task will not need network +access. + +**Role Variables** + +.. zuul:rolevar:: tox_upgrade + :default: false + + If you want the installation of latest tox, regardless of presence on the + system, define `tox_upgrade: true`. + +.. zuul:rolevar:: tox_condition + :default: tox + + Python requirements condition to be used when installing tox. You can define + it to "tox>=3.8.0" to force a minimal version. + +.. zuul:rolevar:: tox_executable + :default: {{ ansible_python.executable }} -m tox + + Location of the tox executable. diff --git a/roles/ensure-tox/defaults/main.yaml b/roles/ensure-tox/defaults/main.yaml new file mode 100644 index 000000000..d0c975755 --- /dev/null +++ b/roles/ensure-tox/defaults/main.yaml @@ -0,0 +1,5 @@ +# when set, it will always install latest version of tox using --user +# be aware that this may break /usr/bin/tox executable due to changed internals +tox_upgrade: false +tox_condition: tox +tox_executable: "{{ ansible_python.executable }} -m tox" \ No newline at end of file diff --git a/roles/ensure-tox/tasks/main.yaml b/roles/ensure-tox/tasks/main.yaml index b2b7487eb..c898c20be 100644 --- a/roles/ensure-tox/tasks/main.yaml +++ b/roles/ensure-tox/tasks/main.yaml @@ -1,2 +1,53 @@ -- name: Ensure tox is installed - shell: type tox || pip install --user tox +- name: Check if tox is accesiblsexx # noqa 305 + shell: | + set -eux + tox --version + {{ tox_executable }} --version + register: result + ignore_errors: true + changed_when: false + +# installing tox with --user will create tox script inside ~/.local/bin but +# this folder is *not* included PATH in all distros. If you want to call it as +# a script you may need to add it to the path like example below. Still calling +# it as a python module works in all cases. +# +# if [[ ":$PATH:" != *":${HOME}/.local/bin:"* ]] && [ -d "${HOME}/.local/bin" ]; then +# export PATH=${HOME}/.local/bin:$PATH +# fi +- name: install tox + when: result is failed or tox_upgrade or tox_condition != 'tox' + block: + + - name: Ensure tox is installed # noqa 305 + environment: + PIP_DISABLE_PIP_VERSION_CHECK: "1" + PIP_NO_WARN_SCRIPT_LOCATION: "1" + vars: + upgrade: "{% if result is failed or tox_upgrade %}--upgrade{% endif %}" + shell: | + set -eu + {{ ansible_python.executable }} -m pip install --user {{ upgrade }} '{{ tox_condition }}' + {{ tox_executable }} --version + args: + executable: /bin/bash + register: result + changed_when: result.stdout.find('Successfully installed') != -1 + + # We want to be sure that if someone calls 'tox' without having `~/.local/bin` + # in PATH, they still get a *working* copy of it. + - name: Ensure a system tox is also available + when: result is changed + become: true + environment: + PIP_DISABLE_PIP_VERSION_CHECK: "1" + PIP_NO_WARN_SCRIPT_LOCATION: "1" + shell: | + set -eu + type tox >/dev/null || { + {# -s is key here to prevent it from finding tox from userdir #} + {{ ansible_python.executable }} -s -m pip install '{{ tox_condition }}' + } + {{ tox_executable }} --version + args: + executable: /bin/bash diff --git a/roles/tox/README.rst b/roles/tox/README.rst index 215c3ff97..5397c9032 100644 --- a/roles/tox/README.rst +++ b/roles/tox/README.rst @@ -12,7 +12,7 @@ Runs tox for a project Which tox environment to run. .. zuul:rolevar:: tox_executable - :default: tox + :default: {{ ansible_python.executable }} -m tox Location of the tox executable. diff --git a/roles/tox/defaults/main.yaml b/roles/tox/defaults/main.yaml index 1178db533..513ee3913 100644 --- a/roles/tox/defaults/main.yaml +++ b/roles/tox/defaults/main.yaml @@ -1,7 +1,9 @@ --- tox_environment: {} tox_envlist: venv -tox_executable: tox +# Calling tox as a module in order to avoid case where tox script gets broken +# because user installed newer version of tox into user packages. +tox_executable: "{{ ansible_python.executable }} -m tox" tox_extra_args: -vv tox_install_siblings: true