
This role ensures that a specific pip-installable command is available. Example usage: - role: ensure-python-command vars: ensure_python_command_name: poetry ensure_python_command_version: ==1.8.5 # omit to install latest In this case, if the `poetry` command is not already available, pip will install it in a new venv. Either way, after running this role, the `ensure_python_command_executable` variable will hold the full path to the command. We already have similar roles for specific commands: - ensure-nox - ensure-poetry - ensure-pyproject-build - ensure-tox - ensure-twine - ensure-uv These roles are essentially copies of each other with different command names. This new role consolidates that code. The existing roles now act as wrappers that just set variables and call the new role. > Note: The `ensure-tox` role has not been refactored due to exclusive > legacy code related to Python 2, which must be removed first. The new role introduces three variables to replace the overloaded `ensure_<command>_executable` variable from the other roles: - `ensure_python_command_name` (input, command name) - `ensure_python_command_existing` (input, existing path for the command) - `ensure_python_command_executable` (output, detected/installed path) This separation avoids using the same variable as both input and output, which can cause issues due to Ansible's variable precedence rules: https://docs.ansible.com/ansible/latest/playbook_guide/playbooks_variables.html Understanding variable precedence ... 19. set_facts / registered vars 20. role (and include_role) params ... Since we use `set_fact` inside the role, it is ineffective when the same variable is also passed as a role parameter :/ I'm not adding tests for the new role because its functionality is already covered by the existing tests for all the refactored roles: - test-playbooks/ensure-nox.yaml - test-playbooks/ensure-poetry.yaml - test-playbooks/ensure-pyproject-build.yaml - test-playbooks/ensure-twine.yaml - test-playbooks/ensure-uv.yaml Change-Id: Idd970cb31bd928576bca3602ce96fbc491ecdb60
65 lines
2.4 KiB
YAML
65 lines
2.4 KiB
YAML
- name: Install pip
|
|
include_role:
|
|
name: ensure-pip
|
|
|
|
- name: Check if the command name is set and non-empty
|
|
fail:
|
|
msg: Required variable ensure_python_command_name is not set or empty
|
|
when: ensure_python_command_name is not defined or not ensure_python_command_name.strip()
|
|
|
|
# Part 1
|
|
# Check if the command is already available. If not, pip-install it to a local venv.
|
|
# Either way, save the command's full path to the output variable.
|
|
|
|
- name: Check if {{ ensure_python_command_name }} is available
|
|
# 1. Full path optionally informed by the role caller
|
|
# 2. Ansible user $PATH (bare command name)
|
|
# 3. Local venv (installed from a previous run for this role)
|
|
shell: |
|
|
command -v \
|
|
{{ ensure_python_command_existing }} \
|
|
{{ ensure_python_command_name | quote }} \
|
|
{{ ensure_python_command_venv_executable | quote }} \
|
|
|| exit 1
|
|
args:
|
|
executable: /bin/bash
|
|
register: ensure_python_command_preinstalled
|
|
failed_when: false
|
|
|
|
- name: Export preinstalled ensure_python_command_executable
|
|
set_fact:
|
|
ensure_python_command_executable: "{{ ensure_python_command_preinstalled.stdout_lines[0] }}"
|
|
cacheable: true
|
|
when: ensure_python_command_preinstalled.rc == 0
|
|
|
|
- name: Install {{ ensure_python_command_package }} to local env
|
|
when: ensure_python_command_preinstalled.rc != 0
|
|
block:
|
|
- name: Create local venv
|
|
command: "{{ ensure_pip_virtualenv_command }} {{ ensure_python_command_venv_path }}"
|
|
|
|
- name: Install {{ ensure_python_command_package }} to local venv
|
|
command: "{{ ensure_python_command_venv_path }}/bin/pip install {{ ensure_python_command_package }}{{ ensure_python_command_version }}"
|
|
|
|
- name: Export installed ensure_python_command_executable path
|
|
set_fact:
|
|
ensure_python_command_executable: "{{ ensure_python_command_venv_executable }}"
|
|
cacheable: true
|
|
|
|
# Part 2
|
|
# Try to show the command's version and maybe also create a symlink to it in /usr/local/bin
|
|
|
|
- name: Output {{ ensure_python_command_name }} version
|
|
command: "{{ ensure_python_command_executable }} --version"
|
|
failed_when: false
|
|
|
|
- name: Make global symlink
|
|
when:
|
|
- ensure_python_command_global_symlink
|
|
- ensure_python_command_executable != ensure_python_command_global_symlink_path
|
|
file:
|
|
state: link
|
|
src: "{{ ensure_python_command_executable }}"
|
|
dest: "{{ ensure_python_command_global_symlink_path }}"
|
|
become: yes
|