diff --git a/roles/ensure-twine/README.rst b/roles/ensure-twine/README.rst index 9f0a62bb5..f19ee85e9 100644 --- a/roles/ensure-twine/README.rst +++ b/roles/ensure-twine/README.rst @@ -1,27 +1,42 @@ Ensure twine is installed. -This role is designed to run without permissions, so assumes a working -Python 3 ``pip`` environment (i.e. it will not install system -packages). +Look for ``twine``, and if not found, install it via ``pip`` into a +virtual environment for the current user. **Role Variables** -.. zuul:rolevar:: twine_python - :default: python +.. zuul:rolevar:: ensure_twine_version + :default: '' - The python interpreter to use to install twine if it is not already - installed. Set it to "python3" to use python 3, for example. + Version specifier to select the version of Twine. The default is the + latest version. + +.. zuul:rolevar:: ensure_twine_venv_path + :default: {{ ansible_user_dir }}/.local/twine + + Directory for the Python venv where Twine will be installed. + +.. zuul:rolevar:: ensure_twine_global_symlink + :default: False + + Install a symlink to the twine executable into ``/usr/local/bin/twine``. + This can be useful when scripts need to be run that expect to find + Twine in a more standard location and plumbing through the value + of ``pypi_twine_executable`` would be onerous. + + Setting this requires root access, so should only be done in + circumstances where root access is available. **Output Variables** -.. zuul:rolevar:: twine_excutable +.. zuul:rolevar:: pypi_twine_executable :default: twine - After running this role, ``twine_executable`` will be set as the path + After running this role, ``pypi_twine_executable`` will be set as the path to a valid ``twine``. At role runtime, look for an existing ``twine`` at this specific - path. Note the default (``twine``) effectively means to find tox in + path. Note the default (``twine``) effectively means to find twine in the current ``$PATH``. For example, if your base image pre-installs twine in an out-of-path environment, set this so the role does not attempt to install the user version. diff --git a/roles/ensure-twine/defaults/main.yaml b/roles/ensure-twine/defaults/main.yaml index 6c1ecf3a5..160d497ac 100644 --- a/roles/ensure-twine/defaults/main.yaml +++ b/roles/ensure-twine/defaults/main.yaml @@ -1,3 +1,5 @@ ---- -twine_python: python3 -twine_executable: twine +ensure_twine_global_symlink: false +# version 6.1.0 is breaking test-release-openstack CI job +ensure_twine_version: ">1.12.0,!=6.1.0" +pypi_twine_executable: twine +ensure_twine_venv_path: "{{ ansible_user_dir }}/.local/twine" diff --git a/roles/ensure-twine/tasks/main.yaml b/roles/ensure-twine/tasks/main.yaml index 2c5bc6f84..3727fc4ab 100644 --- a/roles/ensure-twine/tasks/main.yaml +++ b/roles/ensure-twine/tasks/main.yaml @@ -1,22 +1,44 @@ -- name: Check for twine install +- name: Install pip + include_role: + name: ensure-pip + +- name: Check if twine is installed shell: | - command -v {{ twine_executable }} ~/.local/bin/twine || exit 1 + command -v {{ pypi_twine_executable }} {{ ensure_twine_venv_path }}/bin/twine || exit 1 args: executable: /bin/bash + register: twine_preinstalled failed_when: false - register: register_twine -- name: Set pypi_twine_executable +- name: Export preinstalled pypi_twine_executable set_fact: - pypi_twine_executable: "{{ register_twine.stdout_lines[0] }}" - when: register_twine.rc == 0 + pypi_twine_executable: "{{ twine_preinstalled.stdout_lines[0] }}" + cacheable: true + when: twine_preinstalled.rc == 0 -- name: Ensure twine is installed - when: register_twine.rc != 0 +- name: Install twine to local env + when: twine_preinstalled.rc != 0 block: - - name: Ensure twine is installed - command: "{{ twine_python }} -m pip install twine!=1.12.0,!=6.1.0 requests-toolbelt!=0.9.0 --user" + - name: Create local venv + command: "{{ ensure_pip_virtualenv_command }} {{ ensure_twine_venv_path }}" - - name: Set pypi_twine_executable + - name: Install twine to local venv + command: "{{ ensure_twine_venv_path }}/bin/pip install twine{{ ensure_twine_version }}" + + - name: Export installed pypi_twine_executable path set_fact: - pypi_twine_executable: ~/.local/bin/twine + pypi_twine_executable: "{{ ensure_twine_venv_path }}/bin/twine" + cacheable: true + +- name: Output twine version + command: "{{ pypi_twine_executable }} --version" + +- name: Make global symlink + when: + - ensure_twine_global_symlink + - pypi_twine_executable != '/usr/local/bin/twine' + file: + state: link + src: "{{ pypi_twine_executable }}" + dest: /usr/local/bin/twine + become: yes diff --git a/test-playbooks/ensure-twine.yaml b/test-playbooks/ensure-twine.yaml new file mode 100644 index 000000000..5a47d480f --- /dev/null +++ b/test-playbooks/ensure-twine.yaml @@ -0,0 +1,35 @@ +- hosts: all + name: Test ensure-twine installs into user environment + tasks: + - name: Verify twine is not installed + command: "twine --version" + register: result + failed_when: result.rc == 0 + - name: Run ensure-twine with twine not installed + include_role: + name: ensure-twine + - name: Verify pypi_twine_executable is set + assert: + that: + - pypi_twine_executable == ansible_user_dir + '/.local/twine/bin/twine' + - name: Verify twine is installed + command: "{{ pypi_twine_executable }} --version" + register: result + failed_when: result.rc != 0 + +- hosts: all + name: Test ensure-twine when pypi_twine_executable is set to an already installed twine + tasks: + - name: Create a virtualenv + command: '{{ ensure_pip_virtualenv_command }} {{ ansible_user_dir }}/twine-venv' + - name: Install twine to local venv + command: '{{ ansible_user_dir }}/twine-venv/bin/pip install twine' + - name: Run ensure-twine pointing to an already installed twine + include_role: + name: ensure-twine + vars: + pypi_twine_executable: "{{ ansible_user_dir }}/twine-venv/bin/twine" + - name: Verify pypi_twine_executable is set to the virtualenv twine + assert: + that: + - pypi_twine_executable == ansible_user_dir + '/twine-venv/bin/twine' diff --git a/zuul-tests.d/python-jobs.yaml b/zuul-tests.d/python-jobs.yaml index c31e907e9..61270afa4 100644 --- a/zuul-tests.d/python-jobs.yaml +++ b/zuul-tests.d/python-jobs.yaml @@ -282,6 +282,75 @@ - name: ubuntu-noble label: ubuntu-noble +- job: + name: zuul-jobs-test-ensure-twine + description: Test the ensure-twine role + files: + - roles/ensure-twine/.* + - test-playbooks/ensure-twine.yaml + run: test-playbooks/ensure-twine.yaml + tags: all-platforms + +- job: + name: zuul-jobs-test-ensure-twine-centos-9-stream + description: Test the ensure-twine role on centos-9-stream + parent: zuul-jobs-test-ensure-twine + tags: auto-generated + nodeset: + nodes: + - name: centos-9-stream + label: centos-9-stream + +- job: + name: zuul-jobs-test-ensure-twine-debian-bookworm + description: Test the ensure-twine role on debian-bookworm + parent: zuul-jobs-test-ensure-twine + tags: auto-generated + nodeset: + nodes: + - name: debian-bookworm + label: debian-bookworm + +- job: + name: zuul-jobs-test-ensure-twine-debian-bullseye + description: Test the ensure-twine role on debian-bullseye + parent: zuul-jobs-test-ensure-twine + tags: auto-generated + nodeset: + nodes: + - name: debian-bullseye + label: debian-bullseye + +- job: + name: zuul-jobs-test-ensure-twine-ubuntu-focal + description: Test the ensure-twine role on ubuntu-focal + parent: zuul-jobs-test-ensure-twine + tags: auto-generated + nodeset: + nodes: + - name: ubuntu-focal + label: ubuntu-focal + +- job: + name: zuul-jobs-test-ensure-twine-ubuntu-jammy + description: Test the ensure-twine role on ubuntu-jammy + parent: zuul-jobs-test-ensure-twine + tags: auto-generated + nodeset: + nodes: + - name: ubuntu-jammy + label: ubuntu-jammy + +- job: + name: zuul-jobs-test-ensure-twine-ubuntu-noble + description: Test the ensure-twine role on ubuntu-noble + parent: zuul-jobs-test-ensure-twine + tags: auto-generated + nodeset: + nodes: + - name: ubuntu-noble + label: ubuntu-noble + - job: name: zuul-jobs-test-ensure-sphinx description: Test the ensure-sphinx role @@ -570,6 +639,12 @@ - zuul-jobs-test-ensure-pyproject-build-ubuntu-focal - zuul-jobs-test-ensure-pyproject-build-ubuntu-jammy - zuul-jobs-test-ensure-pyproject-build-ubuntu-noble + - zuul-jobs-test-ensure-twine-centos-9-stream + - zuul-jobs-test-ensure-twine-debian-bookworm + - zuul-jobs-test-ensure-twine-debian-bullseye + - zuul-jobs-test-ensure-twine-ubuntu-focal + - zuul-jobs-test-ensure-twine-ubuntu-jammy + - zuul-jobs-test-ensure-twine-ubuntu-noble - zuul-jobs-test-ensure-sphinx - zuul-jobs-test-ensure-tox-centos-9-stream - zuul-jobs-test-ensure-tox-debian-bookworm