diff --git a/CLAUDE.md b/CLAUDE.md index dede199..433fd95 100644 --- a/CLAUDE.md +++ b/CLAUDE.md @@ -33,7 +33,8 @@ Package lists are flat YAML arrays grouped by category: - **OS packages**: `homebrew_formulae` / `homebrew_casks` / `choco_packages` / `apt_packages` / `snap_packages` / `dnf_packages` / `flatpak_packages` / `appimage_packages` -- **Cross-platform**: `powershell_modules`, `pipx_packages`, `npm_global_packages`, `dotnet_tools`, `vscode_extensions` +- **Cross-platform**: `powershell_modules`, `pipx_packages`, `uv_tools`, + `npm_global_packages`, `dotnet_tools`, `vscode_extensions` - **Git config**: `git_user_email`, `git_user_name` - **Custom commands**: `custom_commands_user` (non-elevated), `custom_commands_elevated` (sudo) - **Custom script**: `custom_script` (path to a script run at the end) @@ -67,6 +68,12 @@ Package lists are flat YAML arrays grouped by category: Cursor is installed this way on Linux; macOS uses Homebrew cask `cursor`, Windows uses Chocolatey `cursoride`. All platforms reuse the `vscode_extensions` list for Cursor extension installation. +- **`uv_tools`** installs Python CLI tools via `uv tool install`. + On macOS/Windows, `pipx_packages` is empty (uv is available via Homebrew/Chocolatey); + on Linux, `pipx_packages` retains only `uv` (pipx bootstraps uv, + then uv manages the rest). + The uv tools step is guarded on uv being installed -- + if uv is not on PATH, the step is silently skipped. ## Running the Setup Scripts diff --git a/debian/README.md b/debian/README.md index 639cfbb..6c9a207 100644 --- a/debian/README.md +++ b/debian/README.md @@ -8,7 +8,7 @@ development environment. - **APT Package Management**: Installs essential development tools and applications - **Flatpak Package Management**: Installs GUI applications via Flatpak -- **Python Setup**: Installs Python packages via pipx +- **Python Setup**: Bootstraps uv via pipx and installs Python CLI tools via uv - **Node.js Setup**: Installs npm global packages - **VS Code Extensions**: Configures VS Code with essential development extensions - **Git Setup**: Configures Git with user information, Git LFS, and Git Credential Manager @@ -117,8 +117,12 @@ powershell_modules: - AWS.Tools.Common - Terminal-Icons -# Python packages via pipx +# Bootstrap uv via pipx pipx_packages: + - uv + +# Python CLI tools via uv +uv_tools: - poetry - ruff @@ -196,7 +200,8 @@ The playbook uses tags to allow selective execution of tasks: - `flatpak`: Flatpak package installation - `appimage`: AppImage package installation - `powershell`: PowerShell installation and module setup -- `pipx`: Python package installation via pipx +- `pipx`: Python package installation via pipx (bootstraps uv) +- `uv`: Python CLI tool installation via uv - `npm`: Node.js package installation - `dotnet`: .NET SDK and tools installation - `vscode`: VS Code extension installation diff --git a/debian/setup.yaml b/debian/setup.yaml index ceb7a25..41c9219 100644 --- a/debian/setup.yaml +++ b/debian/setup.yaml @@ -1,6 +1,6 @@ --- # Ansible playbook for Debian development machine setup -# Manages APT packages, Flatpak packages, PowerShell modules, pipx modules, VS Code extensions, and Git configuration +# Manages APT packages, Flatpak packages, PowerShell modules, pipx modules, uv tools, VS Code extensions, and Git configuration - name: Setup development environment on Debian hosts: localhost @@ -117,7 +117,7 @@ components: "{{ item.components }}" architectures: "{{ item.architectures }}" state: present - loop: "{{ external_apt_repositories }}" + loop: "{{ external_apt_repositories | default([], true) }}" loop_control: label: "Adding repository: {{ item.name }}" when: item.supported_architectures is not defined or deb_architecture in item.supported_architectures @@ -142,7 +142,7 @@ name: flatpak state: present become: yes - when: flatpak_packages | length > 0 + when: (flatpak_packages | default([], true)) | length > 0 tags: - flatpak - packages @@ -153,7 +153,7 @@ flatpakrepo_url: https://dl.flathub.org/repo/flathub.flatpakrepo state: present become: yes - when: flatpak_packages | length > 0 + when: (flatpak_packages | default([], true)) | length > 0 tags: - flatpak - packages @@ -164,7 +164,7 @@ state: present remote: flathub become: yes - loop: "{{ flatpak_packages }}" + loop: "{{ flatpak_packages | default([], true) }}" when: item.supported_architectures is not defined or deb_architecture in item.supported_architectures register: flatpak_install_result failed_when: false @@ -181,7 +181,7 @@ npm config set prefix ~/.local args: creates: ~/.local/lib/node_modules - when: npm_global_packages | length > 0 + when: (npm_global_packages | default([], true)) | length > 0 tags: - npm - packages @@ -194,7 +194,7 @@ register: npm_check_result changed_when: false failed_when: false - loop: "{{ npm_global_packages | default([]) }}" + loop: "{{ npm_global_packages | default([], true) }}" loop_control: label: "Checking npm package: {{ item }}" tags: @@ -206,7 +206,7 @@ ansible.builtin.shell: | export PATH=~/.local/bin:$PATH npm install -g {{ item.0 }} - loop: "{{ npm_global_packages | default([]) | zip(npm_check_result.results) | list }}" + loop: "{{ npm_global_packages | default([], true) | zip(npm_check_result.results) | list }}" when: "item.1.rc != 0" register: npm_install_result changed_when: "npm_install_result.rc == 0" @@ -243,7 +243,7 @@ - name: Ensure .NET global tools are installed ansible.builtin.command: cmd: dotnet tool install -g {{ item }} - loop: "{{ dotnet_tools | default([]) }}" + loop: "{{ dotnet_tools | default([], true) }}" register: dotnet_tool_install_result changed_when: "'already installed' not in dotnet_tool_install_result.stderr and dotnet_tool_install_result.rc == 0" failed_when: false @@ -287,7 +287,7 @@ cmd: pwsh -Command "Install-PSResource -Name {{ item }} -TrustRepository" environment: PATH: "{{ ansible_env.HOME }}/.dotnet/tools:{{ ansible_env.PATH }}" - loop: "{{ powershell_modules }}" + loop: "{{ powershell_modules | default([], true) }}" register: pwsh_install_result changed_when: "'is already installed' not in pwsh_install_result.stdout" loop_control: @@ -301,7 +301,7 @@ - name: Install pipx modules ansible.builtin.shell: | pipx install {{ item }} - loop: "{{ pipx_packages }}" + loop: "{{ pipx_packages | default([], true) }}" register: pipx_install_result changed_when: "'already installed' not in pipx_install_result.stdout" loop_control: @@ -310,11 +310,36 @@ - pipx - modules + # uv tool setup + - name: Check if uv is installed + ansible.builtin.command: + cmd: which uv + register: uv_check + changed_when: false + failed_when: false + tags: + - uv + - tools + + - name: Install uv tools + ansible.builtin.command: + cmd: uv tool install {{ item }} + when: uv_check.rc == 0 + loop: "{{ uv_tools | default([], true) }}" + ignore_errors: yes + register: uv_tool_install_result + changed_when: "'already installed' not in uv_tool_install_result.stderr" + loop_control: + label: "Installing uv tool: {{ item }}" + tags: + - uv + - tools + # VS Code extension setup - name: Ensure VS Code extensions are installed ansible.builtin.command: cmd: code --install-extension {{ item }} - loop: "{{ vscode_extensions }}" + loop: "{{ vscode_extensions | default([], true) }}" register: vscode_ext_result changed_when: "'already installed' not in vscode_ext_result.stdout" loop_control: @@ -329,7 +354,7 @@ path: "{{ appimage_install_dir }}" state: directory mode: '0755' - when: appimage_packages is defined and appimage_packages | length > 0 + when: (appimage_packages | default([], true)) | length > 0 tags: - appimage @@ -338,7 +363,7 @@ path: "{{ ansible_env.HOME }}/.local/share/applications" state: directory mode: '0755' - when: appimage_packages is defined and appimage_packages | length > 0 + when: (appimage_packages | default([], true)) | length > 0 tags: - appimage @@ -346,7 +371,7 @@ ansible.builtin.stat: path: "{{ appimage_install_dir }}/{{ item.name }}.AppImage" register: appimage_stat - loop: "{{ appimage_packages | default([]) }}" + loop: "{{ appimage_packages | default([], true) }}" when: item.supported_architectures is not defined or deb_architecture in item.supported_architectures loop_control: label: "Checking AppImage: {{ item.name }}" @@ -359,7 +384,7 @@ dest: "{{ appimage_install_dir }}/{{ item.0.name }}.AppImage" mode: '0755' checksum: "{{ item.0.checksum | default(omit) }}" - loop: "{{ appimage_packages | default([]) | zip(appimage_stat.results | default([])) | list }}" + loop: "{{ appimage_packages | default([], true) | zip(appimage_stat.results | default([], true)) | list }}" when: - item.1.stat is defined - not item.1.stat.exists @@ -383,7 +408,7 @@ MimeType={{ item.mime_types | default('') }} Categories={{ item.categories | default('Application;') }} mode: '0644' - loop: "{{ appimage_packages | default([]) }}" + loop: "{{ appimage_packages | default([], true) }}" when: item.supported_architectures is not defined or deb_architecture in item.supported_architectures loop_control: label: "Creating desktop entry: {{ item.name }}" @@ -396,7 +421,7 @@ dest: "{{ appimage_install_dir }}/{{ item.name }}" state: link force: true - loop: "{{ appimage_packages | default([]) }}" + loop: "{{ appimage_packages | default([], true) }}" when: item.supported_architectures is not defined or deb_architecture in item.supported_architectures loop_control: label: "Creating symlink: {{ item.name }}" @@ -423,7 +448,7 @@ environment: PATH: "{{ appimage_install_dir }}:{{ ansible_env.PATH }}" ignore_errors: yes - loop: "{{ vscode_extensions }}" + loop: "{{ vscode_extensions | default([], true) }}" register: cursor_ext_result changed_when: "'already installed' not in cursor_ext_result.stdout" when: @@ -470,7 +495,7 @@ # Custom user commands - name: Execute custom user commands ansible.builtin.shell: "{{ item.command }}" - loop: "{{ custom_commands_user }}" + loop: "{{ custom_commands_user | default([], true) }}" loop_control: label: "Executing: {{ item.description }}" tags: @@ -481,7 +506,7 @@ - name: Execute custom elevated commands ansible.builtin.shell: "{{ item.command }}" become: yes - loop: "{{ custom_commands_elevated }}" + loop: "{{ custom_commands_elevated | default([], true) }}" loop_control: label: "Executing: {{ item.description }}" tags: diff --git a/debian/vars.yaml b/debian/vars.yaml index ad6ae62..fca5e5f 100644 --- a/debian/vars.yaml +++ b/debian/vars.yaml @@ -184,12 +184,15 @@ powershell_modules: # pipx modules pipx_packages: + - uv + +# uv tools +uv_tools: - aws-sam-cli - cfn-lint - poetry - ruff - taskcat - - uv # npm global packages npm_global_packages: diff --git a/docs/architecture.md b/docs/architecture.md index ea0935b..73bc28a 100644 --- a/docs/architecture.md +++ b/docs/architecture.md @@ -109,7 +109,7 @@ graph LR subgraph "Package Managers" G --> L[brew install] H --> M[Install-PSResource] - I --> N[pipx install] + I --> N[uv tool install] J --> O[code --install-extension] end ``` @@ -140,7 +140,7 @@ graph LR subgraph "Package Managers" F --> K[choco install] G --> L[Install-PSResource] - H --> M[pipx install] + H --> M[uv tool install] I --> N[code --install-extension] end ``` @@ -172,7 +172,7 @@ graph LR G --> L[apt install] H --> M[snap install] I --> N[Install-PSResource] - J --> O[pipx install] + J --> O[uv tool install] K --> P[code --install-extension] end ``` @@ -206,7 +206,7 @@ graph LR G --> L[apt install] H --> M[flatpak install] I --> N[Install-PSResource] - J --> O[pipx install] + J --> O[uv tool install] K --> P[code --install-extension] end ``` @@ -240,7 +240,7 @@ graph LR G --> L[dnf install] H --> M[flatpak install] I --> N[Install-PSResource] - J --> O[pipx install] + J --> O[uv tool install] K --> P[code --install-extension] end ``` @@ -301,7 +301,7 @@ Each platform organizes packages into logical categories: | Applications | `homebrew_casks` | `choco_packages` | `snap_packages` | `flatpak_packages` | `flatpak_packages` | | VS Code Extensions | `vscode_extensions` | `vscode_extensions` | `vscode_extensions` | `vscode_extensions` | `vscode_extensions` | | PowerShell Modules | `powershell_modules` | `powershell_modules` | `powershell_modules` | `powershell_modules` | `powershell_modules` | -| Python Packages | `pipx_packages` | `pipx_packages` | `pipx_packages` | `pipx_packages` | `pipx_packages` | +| Python Packages | `uv_tools` | `uv_tools` | `uv_tools` | `uv_tools` | `uv_tools` | | Node.js Packages | `npm_global_packages` | `npm_global_packages` | `npm_global_packages` | `npm_global_packages` | `npm_global_packages` | | .NET Tools | `dotnet_tools` | `dotnet_tools` | `dotnet_tools` | `dotnet_tools` | `dotnet_tools` | diff --git a/docs/configuration-reference.md b/docs/configuration-reference.md index 3f209e8..a227476 100644 --- a/docs/configuration-reference.md +++ b/docs/configuration-reference.md @@ -28,8 +28,11 @@ vscode_extensions: [] # List of VS Code extensions # PowerShell modules (all platforms) powershell_modules: [] # List of PowerShell modules -# Python packages via pipx (all platforms) -pipx_packages: [] # List of Python CLI tools +# Python packages via pipx (bootstraps uv on Linux; empty on macOS/Windows) +pipx_packages: [] # List of Python packages + +# Python CLI tools via uv (all platforms) +uv_tools: [] # List of Python CLI tools ``` ## macOS Configuration Reference @@ -498,21 +501,22 @@ powershell_modules: - Microsoft.Graph.Authentication # Microsoft Graph ``` -### Python Packages (pipx) +### Python CLI Tools (uv) -Python CLI tools installed via pipx: +Python CLI tools installed via `uv tool install`. +On macOS and Windows, uv is available via the system package manager +(Homebrew/Chocolatey). +On Linux, pipx bootstraps uv, then uv manages the rest: ```yaml -pipx_packages: +uv_tools: # Development tools - poetry # Dependency management - - black # Code formatter - - flake8 # Linting - - mypy # Type checking + - ruff # Linting and formatting # AWS tools - taskcat # CloudFormation testing - - awscli-local # LocalStack CLI + - cfn-lint # CloudFormation linting # DevOps tools - ansible # Automation (where not system package) diff --git a/docs/customization.md b/docs/customization.md index 0fc2928..5e48095 100644 --- a/docs/customization.md +++ b/docs/customization.md @@ -331,10 +331,9 @@ homebrew_formulae: - pyenv - poetry -pipx_packages: +uv_tools: - poetry - - black - - flake8 + - ruff - mypy - pytest diff --git a/docs/design-principles.md b/docs/design-principles.md index 4be5ae1..4fe863f 100644 --- a/docs/design-principles.md +++ b/docs/design-principles.md @@ -52,7 +52,7 @@ Every package, tool, or application must be installed through a recognized packa - **Homebrew** for CLI tools (`homebrew_formulae`) - **Homebrew Casks** for GUI applications (`homebrew_casks`) -- **pipx** for Python tools (`pipx_packages`) +- **uv** for Python tools (`uv_tools`) - **npm** for Node.js packages (`npm_global_packages`) - **PowerShell Gallery** for PowerShell modules (`powershell_modules`) - **.NET CLI** for .NET tools (`dotnet_tools`) @@ -62,13 +62,14 @@ Every package, tool, or application must be installed through a recognized packa - **Chocolatey** for applications and tools (`choco_packages`) - **PowerShell Gallery** for PowerShell modules (`powershell_modules`) - **npm** for Node.js packages (`npm_global_packages`) -- **pipx** for Python tools (`pipx_packages`) +- **uv** for Python tools (`uv_tools`) #### Ubuntu - **APT** for system packages (`apt_packages`) - **Snap** for applications (`snap_packages`) -- **pipx** for Python tools (`pipx_packages`) +- **pipx** for bootstrapping uv (`pipx_packages`) +- **uv** for Python tools (`uv_tools`) - **npm** for Node.js packages (`npm_global_packages`) - **PowerShell Gallery** for PowerShell modules (`powershell_modules`) - **.NET CLI** for .NET tools (`dotnet_tools`) @@ -77,7 +78,8 @@ Every package, tool, or application must be installed through a recognized packa - **APT** for system packages (`apt_packages`) - **Flatpak** for applications (`flatpak_packages`) -- **pipx** for Python tools (`pipx_packages`) +- **pipx** for bootstrapping uv (`pipx_packages`) +- **uv** for Python tools (`uv_tools`) - **npm** for Node.js packages (`npm_global_packages`) - **PowerShell Gallery** for PowerShell modules (`powershell_modules`) - **.NET CLI** for .NET tools (`dotnet_tools`) @@ -86,7 +88,8 @@ Every package, tool, or application must be installed through a recognized packa - **DNF** for system packages (`dnf_packages`) - **Flatpak** for applications (`flatpak_packages`) -- **pipx** for Python tools (`pipx_packages`) +- **pipx** for bootstrapping uv (`pipx_packages`) +- **uv** for Python tools (`uv_tools`) - **npm** for Node.js packages (`npm_global_packages`) - **PowerShell Gallery** for PowerShell modules (`powershell_modules`) - **.NET CLI** for .NET tools (`dotnet_tools`) diff --git a/docs/package-management.md b/docs/package-management.md index 8f901f7..0803fd0 100644 --- a/docs/package-management.md +++ b/docs/package-management.md @@ -54,7 +54,7 @@ homebrew_casks: Additional package managers handle specific ecosystems: -- **pipx**: Python applications and CLI tools +- **uv**: Python applications and CLI tools (via `uv tool install`) - **npm**: Node.js packages and tools - **PowerShell Gallery**: PowerShell modules - **.NET CLI**: .NET global tools @@ -86,7 +86,7 @@ choco_packages: - **PowerShell Gallery**: PowerShell modules (built-in to Windows) - **npm**: Node.js packages (installed via Chocolatey) -- **pipx**: Python tools (installed via Chocolatey) +- **uv**: Python CLI tools (installed via Chocolatey) - **VS Code Marketplace**: Editor extensions **Why Chocolatey:** @@ -148,7 +148,8 @@ snap_packages: #### Specialized Package Managers -- **pipx**: Python applications +- **pipx**: Bootstraps uv +- **uv**: Python CLI tools (via `uv tool install`) - **PowerShell Gallery**: PowerShell modules (after PowerShell installation) - **VS Code Marketplace**: Editor extensions @@ -202,7 +203,8 @@ flatpak_packages: #### Specialized Package Managers -- **pipx**: Python applications +- **pipx**: Bootstraps uv +- **uv**: Python CLI tools (via `uv tool install`) - **PowerShell Gallery**: PowerShell modules (after PowerShell installation) - **VS Code Marketplace**: Editor extensions @@ -246,7 +248,8 @@ flatpak_packages: [] #### Specialized Package Managers -- **pipx**: Python applications +- **pipx**: Bootstraps uv +- **uv**: Python CLI tools (via `uv tool install`) - **PowerShell Gallery**: PowerShell modules (after PowerShell installation) - **VS Code Marketplace**: Editor extensions @@ -304,7 +307,8 @@ dnf_packages: [] # Fedora system packages # Cross-platform sections (consistent naming) vscode_extensions: [] # VS Code extensions powershell_modules: [] # PowerShell modules -pipx_packages: [] # Python applications +pipx_packages: [] # Python applications (bootstraps uv on Linux) +uv_tools: [] # Python CLI tools (via uv tool install) npm_global_packages: [] # Node.js global packages ``` @@ -347,7 +351,7 @@ npm_global_packages: [] # Node.js global packages Packages are installed in dependency order: 1. **System Prerequisites**: Basic system tools and libraries -2. **Package Managers**: Additional package managers (pipx, npm) +2. **Package Managers**: Additional package managers (pipx, uv, npm) 3. **Development Runtimes**: Language runtimes and frameworks 4. **Development Tools**: IDEs, version control, containers 5. **Applications**: GUI applications and end-user tools diff --git a/examples/debian_vars.yaml b/examples/debian_vars.yaml index 7f8b70d..fbef796 100644 --- a/examples/debian_vars.yaml +++ b/examples/debian_vars.yaml @@ -225,15 +225,18 @@ powershell_modules: - PSTcpIp - Terminal-Icons -# pipx modules +# pipx modules (bootstraps uv on Linux) pipx_packages: + - uv + +# uv tools +uv_tools: - ansible-lint - aws-sam-cli - cfn-lint - poetry - ruff - taskcat - - uv # npm global packages npm_global_packages: diff --git a/examples/fedora_vars.yaml b/examples/fedora_vars.yaml index cd9aa1f..417cc7a 100644 --- a/examples/fedora_vars.yaml +++ b/examples/fedora_vars.yaml @@ -210,15 +210,18 @@ powershell_modules: - PSTcpIp - Terminal-Icons -# pipx modules +# pipx modules (bootstraps uv on Linux) pipx_packages: + - uv + +# uv tools +uv_tools: - ansible-lint - aws-sam-cli - cfn-lint - poetry - ruff - taskcat - - uv # npm global packages npm_global_packages: diff --git a/examples/macOS_vars.yaml b/examples/macOS_vars.yaml index 992177c..d8732f5 100644 --- a/examples/macOS_vars.yaml +++ b/examples/macOS_vars.yaml @@ -164,6 +164,9 @@ powershell_modules: # pipx modules pipx_packages: + +# uv tools +uv_tools: - ansible-lint - poetry - taskcat diff --git a/examples/ubuntu_vars.yaml b/examples/ubuntu_vars.yaml index 4042391..ece4cf6 100644 --- a/examples/ubuntu_vars.yaml +++ b/examples/ubuntu_vars.yaml @@ -336,15 +336,18 @@ powershell_modules: - PSTcpIp - Terminal-Icons -# pipx modules +# pipx modules (bootstraps uv on Linux) pipx_packages: + - uv + +# uv tools +uv_tools: - ansible-lint - aws-sam-cli - cfn-lint - poetry - ruff - taskcat - - uv # npm global packages npm_global_packages: diff --git a/examples/windows_vars.yaml b/examples/windows_vars.yaml index 8f118f5..9056cec 100644 --- a/examples/windows_vars.yaml +++ b/examples/windows_vars.yaml @@ -116,6 +116,9 @@ windows_powershell_modules: # pipx modules pipx_packages: + +# uv tools +uv_tools: - ansible-lint - cfn-lint - poetry diff --git a/fedora/README.md b/fedora/README.md index 91cde70..a2f9005 100644 --- a/fedora/README.md +++ b/fedora/README.md @@ -10,7 +10,7 @@ development environment. - **Flatpak Package Management**: Installs GUI applications via Flatpak - **Docker Setup**: Installs Docker and adds the user to the Docker group - **PowerShell Setup**: Installs PowerShell and modules for development -- **Python Setup**: Installs Python versions via pyenv and pipx modules +- **Python Setup**: Installs Python versions via pyenv, bootstraps uv via pipx, and installs CLI tools via uv - **Ruby Setup**: Installs Ruby via chruby - **Node.js Setup**: Installs Node.js and npm global packages - **Rust Setup**: Installs Rust via rustup @@ -123,8 +123,12 @@ powershell_modules: - AWS.Tools.Common - Terminal-Icons -# Python packages via pipx +# Bootstrap uv via pipx pipx_packages: + - uv + +# Python CLI tools via uv +uv_tools: - poetry - ruff @@ -206,7 +210,8 @@ The playbook uses tags to allow selective execution of tasks: - `flatpak`: Flatpak package installation - `appimage`: AppImage package installation - `powershell`: PowerShell installation and module setup -- `pipx`: Python package installation via pipx +- `pipx`: Python package installation via pipx (bootstraps uv) +- `uv`: Python CLI tool installation via uv - `npm`: Node.js package installation - `dotnet`: .NET SDK and tools installation - `vscode`: VS Code extension installation diff --git a/fedora/setup.yaml b/fedora/setup.yaml index 09724eb..fa20ee5 100644 --- a/fedora/setup.yaml +++ b/fedora/setup.yaml @@ -1,6 +1,6 @@ --- # Ansible playbook for Fedora development machine setup -# Manages DNF packages, Flatpak packages, PowerShell modules, pipx modules, VS Code extensions, and Git configuration +# Manages DNF packages, Flatpak packages, PowerShell modules, pipx modules, uv tools, VS Code extensions, and Git configuration - name: Setup development environment on Fedora hosts: localhost @@ -107,7 +107,7 @@ gpgcheck: "{{ item.gpgcheck | default(true) }}" enabled: true state: present - loop: "{{ external_dnf_repositories }}" + loop: "{{ external_dnf_repositories | default([], true) }}" loop_control: label: "Adding repository: {{ item.name }}" when: item.supported_architectures is not defined or rpm_architecture in item.supported_architectures @@ -132,7 +132,7 @@ name: flatpak state: present become: yes - when: flatpak_packages | length > 0 + when: (flatpak_packages | default([], true)) | length > 0 tags: - flatpak - packages @@ -143,7 +143,7 @@ flatpakrepo_url: https://dl.flathub.org/repo/flathub.flatpakrepo state: present become: yes - when: flatpak_packages | length > 0 + when: (flatpak_packages | default([], true)) | length > 0 tags: - flatpak - packages @@ -154,7 +154,7 @@ state: present remote: flathub become: yes - loop: "{{ flatpak_packages }}" + loop: "{{ flatpak_packages | default([], true) }}" when: item.supported_architectures is not defined or rpm_architecture in item.supported_architectures register: flatpak_install_result failed_when: false @@ -171,7 +171,7 @@ npm config set prefix ~/.local args: creates: ~/.local/lib/node_modules - when: npm_global_packages | length > 0 + when: (npm_global_packages | default([], true)) | length > 0 tags: - npm - packages @@ -184,7 +184,7 @@ register: npm_check_result changed_when: false failed_when: false - loop: "{{ npm_global_packages | default([]) }}" + loop: "{{ npm_global_packages | default([], true) }}" loop_control: label: "Checking npm package: {{ item }}" tags: @@ -196,7 +196,7 @@ ansible.builtin.shell: | export PATH=~/.local/bin:$PATH npm install -g {{ item.0 }} - loop: "{{ npm_global_packages | default([]) | zip(npm_check_result.results) | list }}" + loop: "{{ npm_global_packages | default([], true) | zip(npm_check_result.results) | list }}" when: "item.1.rc != 0" register: npm_install_result changed_when: "npm_install_result.rc == 0" @@ -233,7 +233,7 @@ - name: Ensure .NET global tools are installed ansible.builtin.command: cmd: dotnet tool install -g {{ item }} - loop: "{{ dotnet_tools | default([]) }}" + loop: "{{ dotnet_tools | default([], true) }}" register: dotnet_tool_install_result changed_when: "'already installed' not in dotnet_tool_install_result.stderr and dotnet_tool_install_result.rc == 0" failed_when: false @@ -277,7 +277,7 @@ cmd: pwsh -Command "Install-PSResource -Name {{ item }} -TrustRepository" environment: PATH: "{{ ansible_env.HOME }}/.dotnet/tools:{{ ansible_env.PATH }}" - loop: "{{ powershell_modules }}" + loop: "{{ powershell_modules | default([], true) }}" register: pwsh_install_result changed_when: "'is already installed' not in pwsh_install_result.stdout" loop_control: @@ -291,7 +291,7 @@ - name: Install pipx modules ansible.builtin.shell: | pipx install {{ item }} - loop: "{{ pipx_packages }}" + loop: "{{ pipx_packages | default([], true) }}" register: pipx_install_result changed_when: "'already installed' not in pipx_install_result.stdout" loop_control: @@ -300,11 +300,36 @@ - pipx - modules + # uv tool setup + - name: Check if uv is installed + ansible.builtin.command: + cmd: which uv + register: uv_check + changed_when: false + failed_when: false + tags: + - uv + - tools + + - name: Install uv tools + ansible.builtin.command: + cmd: uv tool install {{ item }} + when: uv_check.rc == 0 + loop: "{{ uv_tools | default([], true) }}" + ignore_errors: yes + register: uv_tool_install_result + changed_when: "'already installed' not in uv_tool_install_result.stderr" + loop_control: + label: "Installing uv tool: {{ item }}" + tags: + - uv + - tools + # VS Code extension setup - name: Ensure VS Code extensions are installed ansible.builtin.command: cmd: code --install-extension {{ item }} - loop: "{{ vscode_extensions }}" + loop: "{{ vscode_extensions | default([], true) }}" register: vscode_ext_result changed_when: "'already installed' not in vscode_ext_result.stdout" loop_control: @@ -319,7 +344,7 @@ path: "{{ appimage_install_dir }}" state: directory mode: '0755' - when: appimage_packages is defined and appimage_packages | length > 0 + when: (appimage_packages | default([], true)) | length > 0 tags: - appimage @@ -328,7 +353,7 @@ path: "{{ ansible_env.HOME }}/.local/share/applications" state: directory mode: '0755' - when: appimage_packages is defined and appimage_packages | length > 0 + when: (appimage_packages | default([], true)) | length > 0 tags: - appimage @@ -336,7 +361,7 @@ ansible.builtin.stat: path: "{{ appimage_install_dir }}/{{ item.name }}.AppImage" register: appimage_stat - loop: "{{ appimage_packages | default([]) }}" + loop: "{{ appimage_packages | default([], true) }}" when: item.supported_architectures is not defined or rpm_architecture in item.supported_architectures loop_control: label: "Checking AppImage: {{ item.name }}" @@ -349,7 +374,7 @@ dest: "{{ appimage_install_dir }}/{{ item.0.name }}.AppImage" mode: '0755' checksum: "{{ item.0.checksum | default(omit) }}" - loop: "{{ appimage_packages | default([]) | zip(appimage_stat.results | default([])) | list }}" + loop: "{{ appimage_packages | default([], true) | zip(appimage_stat.results | default([], true)) | list }}" when: - item.1.stat is defined - not item.1.stat.exists @@ -373,7 +398,7 @@ MimeType={{ item.mime_types | default('') }} Categories={{ item.categories | default('Application;') }} mode: '0644' - loop: "{{ appimage_packages | default([]) }}" + loop: "{{ appimage_packages | default([], true) }}" when: item.supported_architectures is not defined or rpm_architecture in item.supported_architectures loop_control: label: "Creating desktop entry: {{ item.name }}" @@ -386,7 +411,7 @@ dest: "{{ appimage_install_dir }}/{{ item.name }}" state: link force: true - loop: "{{ appimage_packages | default([]) }}" + loop: "{{ appimage_packages | default([], true) }}" when: item.supported_architectures is not defined or rpm_architecture in item.supported_architectures loop_control: label: "Creating symlink: {{ item.name }}" @@ -413,7 +438,7 @@ environment: PATH: "{{ appimage_install_dir }}:{{ ansible_env.PATH }}" ignore_errors: yes - loop: "{{ vscode_extensions }}" + loop: "{{ vscode_extensions | default([], true) }}" register: cursor_ext_result changed_when: "'already installed' not in cursor_ext_result.stdout" when: @@ -460,7 +485,7 @@ # Custom user commands - name: Execute custom user commands ansible.builtin.shell: "{{ item.command }}" - loop: "{{ custom_commands_user }}" + loop: "{{ custom_commands_user | default([], true) }}" loop_control: label: "Executing: {{ item.description }}" tags: @@ -471,7 +496,7 @@ - name: Execute custom elevated commands ansible.builtin.shell: "{{ item.command }}" become: yes - loop: "{{ custom_commands_elevated }}" + loop: "{{ custom_commands_elevated | default([], true) }}" loop_control: label: "Executing: {{ item.description }}" tags: diff --git a/fedora/vars.yaml b/fedora/vars.yaml index 5597f46..a9061fe 100644 --- a/fedora/vars.yaml +++ b/fedora/vars.yaml @@ -115,12 +115,15 @@ powershell_modules: # pipx modules pipx_packages: + - uv + +# uv tools +uv_tools: - aws-sam-cli - cfn-lint - poetry - ruff - taskcat - - uv # npm global packages npm_global_packages: diff --git a/macOS/README.md b/macOS/README.md index a67b037..d4d11dc 100644 --- a/macOS/README.md +++ b/macOS/README.md @@ -8,7 +8,7 @@ development environment. - 🍺 **Homebrew Package Management**: Installs Homebrew taps, casks, and formulae - 🔧 **PowerShell Module Installation**: Sets up PowerShell modules for development -- 📦 **Python Package Management**: Installs pipx modules +- 📦 **Python Package Management**: Installs Python CLI tools via uv - 🧩 **Node.js Package Management**: Installs npm packages globally - ⚙️ **.NET Global Tools**: Installs .NET global tools (when .NET SDK is available) - 💻 **VS Code Extensions**: Configures VS Code with essential development extensions @@ -132,8 +132,11 @@ powershell_modules: - AWS.Tools.Common - Terminal-Icons -# Python packages via pipx +# Python packages via pipx (empty on macOS; uv is available via Homebrew) pipx_packages: + +# Python CLI tools via uv +uv_tools: - poetry - black @@ -229,6 +232,7 @@ The playbook uses tags to allow selective execution of tasks: - `formulae`: Only Homebrew formulae (CLI tools) - `powershell`: PowerShell module installation - `pipx`: Python package installation via pipx +- `uv`: Python CLI tool installation via uv - `npm`: Node.js package installation via npm - `dotnet`: .NET global tools installation - `vscode`: VS Code extension installation diff --git a/macOS/setup.yaml b/macOS/setup.yaml index 35b2960..923d43b 100644 --- a/macOS/setup.yaml +++ b/macOS/setup.yaml @@ -1,6 +1,6 @@ --- # Ansible playbook for macOS development machine setup -# Manages Homebrew packages, PowerShell modules, pipx modules, VS Code extensions, and Git configuration +# Manages Homebrew packages, PowerShell modules, pipx modules, uv tools, VS Code extensions, and Git configuration - name: Setup development environment on macOS hosts: localhost @@ -60,7 +60,7 @@ name: "{{ item }}" state: present ignore_errors: yes - loop: "{{ homebrew_taps }}" + loop: "{{ homebrew_taps | default([], true) }}" loop_control: label: "Adding tap: {{ item }}" tags: @@ -71,7 +71,7 @@ ansible.builtin.command: cmd: "brew list --cask {{ item }}" ignore_errors: yes - loop: "{{ homebrew_casks }}" + loop: "{{ homebrew_casks | default([], true) }}" register: brew_cask_check changed_when: false failed_when: false @@ -87,7 +87,7 @@ environment: SUDO_ASKPASS: "{{ lookup('env', 'SUDO_ASKPASS') }}" HOMEBREW_SUDO_ASKPASS: "{{ lookup('env', 'SUDO_ASKPASS') }}" - loop: "{{ homebrew_casks | zip(brew_cask_check.results) | list }}" + loop: "{{ homebrew_casks | default([], true) | zip(brew_cask_check.results) | list }}" when: item.1.rc != 0 register: brew_cask_install_result changed_when: brew_cask_install_result.rc == 0 @@ -104,7 +104,7 @@ state: present update_homebrew: yes ignore_errors: yes - loop: "{{ homebrew_formulae }}" + loop: "{{ homebrew_formulae | default([], true) }}" loop_control: label: "Installing formula: {{ item }}" tags: @@ -120,7 +120,7 @@ ansible.builtin.command: cmd: pwsh -Command "Install-PSResource -Name {{ item }} -TrustRepository" ignore_errors: yes - loop: "{{ powershell_modules }}" + loop: "{{ powershell_modules | default([], true) }}" register: pwsh_install_result changed_when: "'is already installed' not in pwsh_install_result.stdout" loop_control: @@ -134,7 +134,7 @@ ansible.builtin.command: cmd: pipx install {{ item }} ignore_errors: yes - loop: "{{ pipx_packages }}" + loop: "{{ pipx_packages | default([], true) }}" register: pipx_install_result changed_when: "'already installed' not in pipx_install_result.stdout" loop_control: @@ -143,6 +143,31 @@ - pipx - modules + # uv tool setup + - name: Check if uv is installed + ansible.builtin.command: + cmd: which uv + register: uv_check + changed_when: false + failed_when: false + tags: + - uv + - tools + + - name: Install uv tools + ansible.builtin.command: + cmd: uv tool install {{ item }} + when: uv_check.rc == 0 + loop: "{{ uv_tools | default([], true) }}" + ignore_errors: yes + register: uv_tool_install_result + changed_when: "'already installed' not in uv_tool_install_result.stderr" + loop_control: + label: "Installing uv tool: {{ item }}" + tags: + - uv + - tools + # npm global package setup - name: Check if npm packages are already installed ansible.builtin.command: @@ -150,7 +175,7 @@ register: npm_check_result changed_when: false failed_when: false - loop: "{{ npm_global_packages | default([]) }}" + loop: "{{ npm_global_packages | default([], true) }}" loop_control: label: "Checking npm package: {{ item }}" tags: @@ -161,7 +186,7 @@ ansible.builtin.command: cmd: npm install -g {{ item.0 }} ignore_errors: yes - loop: "{{ npm_global_packages | default([]) | zip(npm_check_result.results) | list }}" + loop: "{{ npm_global_packages | default([], true) | zip(npm_check_result.results) | list }}" when: "item.1.rc != 0" register: npm_install_result changed_when: "npm_install_result.rc == 0" @@ -197,7 +222,7 @@ ansible.builtin.command: cmd: dotnet tool install -g {{ item }} ignore_errors: yes - loop: "{{ dotnet_tools | default([]) }}" + loop: "{{ dotnet_tools | default([], true) }}" register: dotnet_tool_install_result changed_when: "'already installed' not in dotnet_tool_install_result.stderr and dotnet_tool_install_result.rc == 0" failed_when: false @@ -215,7 +240,7 @@ ansible.builtin.command: cmd: code --install-extension {{ item }} ignore_errors: yes - loop: "{{ vscode_extensions }}" + loop: "{{ vscode_extensions | default([], true) }}" register: vscode_ext_result changed_when: "'already installed' not in vscode_ext_result.stdout" loop_control: @@ -239,7 +264,7 @@ ansible.builtin.command: cmd: cursor --install-extension {{ item }} ignore_errors: yes - loop: "{{ vscode_extensions }}" + loop: "{{ vscode_extensions | default([], true) }}" register: cursor_ext_result changed_when: "'already installed' not in cursor_ext_result.stdout" when: cursor_cli_check.rc == 0 @@ -285,7 +310,7 @@ ansible.builtin.shell: cmd: "{{ item }}" executable: /bin/bash - loop: "{{ custom_commands_user | default([]) }}" + loop: "{{ custom_commands_user | default([], true) }}" register: custom_command_user_result changed_when: custom_command_user_result.rc == 0 ignore_errors: yes @@ -301,7 +326,7 @@ ansible.builtin.shell: cmd: "{{ item }}" executable: /bin/bash - loop: "{{ custom_commands_elevated | default([]) }}" + loop: "{{ custom_commands_elevated | default([], true) }}" register: custom_command_elevated_result changed_when: custom_command_elevated_result.rc == 0 ignore_errors: yes diff --git a/macOS/vars.yaml b/macOS/vars.yaml index ffc1a61..7069109 100644 --- a/macOS/vars.yaml +++ b/macOS/vars.yaml @@ -99,6 +99,9 @@ powershell_modules: # pipx modules pipx_packages: + +# uv tools +uv_tools: - poetry - taskcat diff --git a/tests/debian/vars.yaml b/tests/debian/vars.yaml index 13a1c27..e9320ac 100644 --- a/tests/debian/vars.yaml +++ b/tests/debian/vars.yaml @@ -15,7 +15,9 @@ flatpak_packages: [] powershell_modules: [] -pipx_packages: [] +pipx_packages: + +uv_tools: npm_global_packages: [] diff --git a/tests/fedora/vars.yaml b/tests/fedora/vars.yaml index 9b07a7a..edfb12f 100644 --- a/tests/fedora/vars.yaml +++ b/tests/fedora/vars.yaml @@ -15,7 +15,9 @@ flatpak_packages: [] powershell_modules: [] -pipx_packages: [] +pipx_packages: + +uv_tools: npm_global_packages: [] diff --git a/tests/macOS/vars.yaml b/tests/macOS/vars.yaml index d30d8c0..f9131d2 100644 --- a/tests/macOS/vars.yaml +++ b/tests/macOS/vars.yaml @@ -8,10 +8,13 @@ homebrew_casks: homebrew_formulae: - git-lfs - jq + - uv powershell_modules: [] pipx_packages: + +uv_tools: - ruff npm_global_packages: [] diff --git a/tests/macOS/verify.sh b/tests/macOS/verify.sh index 3d4ce43..b958b02 100755 --- a/tests/macOS/verify.sh +++ b/tests/macOS/verify.sh @@ -35,8 +35,8 @@ check "git-lfs installed (Homebrew formula)" command -v git-lfs # Homebrew cask check "iTerm2 installed (Homebrew cask)" test -d /Applications/iTerm.app -# pipx package -check "ruff installed (pipx package)" command -v ruff +# uv tool +check "ruff installed (uv tool)" command -v ruff # Git config check_equal "git user.email configured" \ diff --git a/tests/ubuntu/vars.yaml b/tests/ubuntu/vars.yaml index 97d377b..2d6b263 100644 --- a/tests/ubuntu/vars.yaml +++ b/tests/ubuntu/vars.yaml @@ -15,7 +15,9 @@ snap_packages: [] powershell_modules: [] -pipx_packages: [] +pipx_packages: + +uv_tools: npm_global_packages: [] diff --git a/tests/windows/vars.yaml b/tests/windows/vars.yaml index 288742a..4daf47a 100644 --- a/tests/windows/vars.yaml +++ b/tests/windows/vars.yaml @@ -8,7 +8,9 @@ powershell_modules: windows_powershell_modules: [] -pipx_packages: [] +pipx_packages: + +uv_tools: npm_global_packages: [] diff --git a/ubuntu/README.md b/ubuntu/README.md index e9b87ff..038678e 100644 --- a/ubuntu/README.md +++ b/ubuntu/README.md @@ -10,7 +10,7 @@ development environment. - 📱 **Snap Package Management**: Installs GUI applications via Snap - 🐳 **Docker Setup**: Installs Docker and adds the user to the Docker group - 🔧 **PowerShell Setup**: Installs PowerShell and modules for development -- 🐍 **Python Setup**: Installs Python versions via pyenv and pipx modules +- 🐍 **Python Setup**: Installs Python versions via pyenv, bootstraps uv via pipx, and installs CLI tools via uv - 💎 **Ruby Setup**: Installs Ruby via rbenv - 🟦 **Node.js Setup**: Installs Node.js and npm global packages - 🦀 **Rust Setup**: Installs Rust via rustup @@ -132,8 +132,12 @@ powershell_modules: - AWS.Tools.Common - Terminal-Icons -# Python packages via pipx +# Bootstrap uv via pipx pipx_packages: + - uv + +# Python CLI tools via uv +uv_tools: - poetry - black @@ -216,7 +220,8 @@ The playbook uses tags to allow selective execution of tasks: - `snap`: Snap package installation - `appimage`: AppImage package installation - `powershell`: PowerShell installation and module setup -- `pipx`: Python package installation via pipx +- `pipx`: Python package installation via pipx (bootstraps uv) +- `uv`: Python CLI tool installation via uv - `npm`: Node.js package installation via npm - `dotnet`: .NET SDK and tools installation - `vscode`: VS Code extension installation diff --git a/ubuntu/setup.yaml b/ubuntu/setup.yaml index 8fd97a6..1e23e72 100644 --- a/ubuntu/setup.yaml +++ b/ubuntu/setup.yaml @@ -1,6 +1,6 @@ --- # Ansible playbook for Ubuntu development machine setup -# Manages APT packages, Snap packages, PowerShell modules, pipx modules, VS Code extensions, and Git configuration +# Manages APT packages, Snap packages, PowerShell modules, pipx modules, uv tools, VS Code extensions, and Git configuration - name: Setup development environment on Ubuntu hosts: localhost @@ -117,7 +117,7 @@ components: "{{ item.components }}" architectures: "{{ item.architectures }}" state: present - loop: "{{ external_apt_repositories }}" + loop: "{{ external_apt_repositories | default([], true) }}" loop_control: label: "Adding repository: {{ item.name }}" when: item.supported_architectures is not defined or deb_architecture in item.supported_architectures @@ -141,7 +141,7 @@ ansible.builtin.command: cmd: snap install {{ item.name }} --classic become: yes - loop: "{{ snap_packages | selectattr('classic', 'defined') | selectattr('classic') | list }}" + loop: "{{ (snap_packages | default([], true)) | selectattr('classic', 'defined') | selectattr('classic') | list }}" when: item.supported_architectures is not defined or deb_architecture in item.supported_architectures register: snap_classic_result changed_when: "snap_classic_result.rc == 0 and 'already installed' not in snap_classic_result.stdout" @@ -157,7 +157,7 @@ ansible.builtin.command: cmd: snap install {{ item.name }} become: yes - loop: "{{ snap_packages | rejectattr('classic', 'defined') | list + snap_packages | selectattr('classic', 'defined') | rejectattr('classic') | list }}" + loop: "{{ (snap_packages | default([], true)) | rejectattr('classic', 'defined') | list + (snap_packages | default([], true)) | selectattr('classic', 'defined') | rejectattr('classic') | list }}" when: item.supported_architectures is not defined or deb_architecture in item.supported_architectures register: snap_regular_result changed_when: "snap_regular_result.rc == 0 and 'already installed' not in snap_regular_result.stdout" @@ -175,7 +175,7 @@ npm config set prefix ~/.local args: creates: ~/.local/lib/node_modules - when: npm_global_packages | length > 0 + when: (npm_global_packages | default([], true)) | length > 0 tags: - npm - packages @@ -188,7 +188,7 @@ register: npm_check_result changed_when: false failed_when: false - loop: "{{ npm_global_packages | default([]) }}" + loop: "{{ npm_global_packages | default([], true) }}" loop_control: label: "Checking npm package: {{ item }}" tags: @@ -200,7 +200,7 @@ ansible.builtin.shell: | export PATH=~/.local/bin:$PATH npm install -g {{ item.0 }} - loop: "{{ npm_global_packages | default([]) | zip(npm_check_result.results) | list }}" + loop: "{{ npm_global_packages | default([], true) | zip(npm_check_result.results) | list }}" when: "item.1.rc != 0" register: npm_install_result changed_when: "npm_install_result.rc == 0" @@ -237,7 +237,7 @@ - name: Ensure .NET global tools are installed ansible.builtin.command: cmd: dotnet tool install -g {{ item }} - loop: "{{ dotnet_tools | default([]) }}" + loop: "{{ dotnet_tools | default([], true) }}" register: dotnet_tool_install_result changed_when: "'already installed' not in dotnet_tool_install_result.stderr and dotnet_tool_install_result.rc == 0" failed_when: false @@ -281,7 +281,7 @@ cmd: pwsh -Command "Install-PSResource -Name {{ item }} -TrustRepository" environment: PATH: "{{ ansible_env.HOME }}/.dotnet/tools:{{ ansible_env.PATH }}" - loop: "{{ powershell_modules }}" + loop: "{{ powershell_modules | default([], true) }}" register: pwsh_install_result changed_when: "'is already installed' not in pwsh_install_result.stdout" loop_control: @@ -295,7 +295,7 @@ - name: Install pipx modules ansible.builtin.shell: | pipx install {{ item }} - loop: "{{ pipx_packages }}" + loop: "{{ pipx_packages | default([], true) }}" register: pipx_install_result changed_when: "'already installed' not in pipx_install_result.stdout" loop_control: @@ -304,11 +304,36 @@ - pipx - modules + # uv tool setup + - name: Check if uv is installed + ansible.builtin.command: + cmd: which uv + register: uv_check + changed_when: false + failed_when: false + tags: + - uv + - tools + + - name: Install uv tools + ansible.builtin.command: + cmd: uv tool install {{ item }} + when: uv_check.rc == 0 + loop: "{{ uv_tools | default([], true) }}" + ignore_errors: yes + register: uv_tool_install_result + changed_when: "'already installed' not in uv_tool_install_result.stderr" + loop_control: + label: "Installing uv tool: {{ item }}" + tags: + - uv + - tools + # VS Code extension setup - name: Ensure VS Code extensions are installed ansible.builtin.command: cmd: code --install-extension {{ item }} - loop: "{{ vscode_extensions }}" + loop: "{{ vscode_extensions | default([], true) }}" register: vscode_ext_result changed_when: "'already installed' not in vscode_ext_result.stdout" loop_control: @@ -323,7 +348,7 @@ path: "{{ appimage_install_dir }}" state: directory mode: '0755' - when: appimage_packages is defined and appimage_packages | length > 0 + when: (appimage_packages | default([], true)) | length > 0 tags: - appimage @@ -332,7 +357,7 @@ path: "{{ ansible_env.HOME }}/.local/share/applications" state: directory mode: '0755' - when: appimage_packages is defined and appimage_packages | length > 0 + when: (appimage_packages | default([], true)) | length > 0 tags: - appimage @@ -340,7 +365,7 @@ ansible.builtin.stat: path: "{{ appimage_install_dir }}/{{ item.name }}.AppImage" register: appimage_stat - loop: "{{ appimage_packages | default([]) }}" + loop: "{{ appimage_packages | default([], true) }}" when: item.supported_architectures is not defined or deb_architecture in item.supported_architectures loop_control: label: "Checking AppImage: {{ item.name }}" @@ -353,7 +378,7 @@ dest: "{{ appimage_install_dir }}/{{ item.0.name }}.AppImage" mode: '0755' checksum: "{{ item.0.checksum | default(omit) }}" - loop: "{{ appimage_packages | default([]) | zip(appimage_stat.results | default([])) | list }}" + loop: "{{ appimage_packages | default([], true) | zip(appimage_stat.results | default([], true)) | list }}" when: - item.1.stat is defined - not item.1.stat.exists @@ -377,7 +402,7 @@ MimeType={{ item.mime_types | default('') }} Categories={{ item.categories | default('Application;') }} mode: '0644' - loop: "{{ appimage_packages | default([]) }}" + loop: "{{ appimage_packages | default([], true) }}" when: item.supported_architectures is not defined or deb_architecture in item.supported_architectures loop_control: label: "Creating desktop entry: {{ item.name }}" @@ -390,7 +415,7 @@ dest: "{{ appimage_install_dir }}/{{ item.name }}" state: link force: true - loop: "{{ appimage_packages | default([]) }}" + loop: "{{ appimage_packages | default([], true) }}" when: item.supported_architectures is not defined or deb_architecture in item.supported_architectures loop_control: label: "Creating symlink: {{ item.name }}" @@ -417,7 +442,7 @@ environment: PATH: "{{ appimage_install_dir }}:{{ ansible_env.PATH }}" ignore_errors: yes - loop: "{{ vscode_extensions }}" + loop: "{{ vscode_extensions | default([], true) }}" register: cursor_ext_result changed_when: "'already installed' not in cursor_ext_result.stdout" when: @@ -464,7 +489,7 @@ # Custom user commands - name: Execute custom user commands ansible.builtin.shell: "{{ item.command }}" - loop: "{{ custom_commands_user }}" + loop: "{{ custom_commands_user | default([], true) }}" loop_control: label: "Executing: {{ item.description }}" tags: @@ -475,7 +500,7 @@ - name: Execute custom elevated commands ansible.builtin.shell: "{{ item.command }}" become: yes - loop: "{{ custom_commands_elevated }}" + loop: "{{ custom_commands_elevated | default([], true) }}" loop_control: label: "Executing: {{ item.description }}" tags: diff --git a/ubuntu/vars.yaml b/ubuntu/vars.yaml index 3a10302..3b7933e 100644 --- a/ubuntu/vars.yaml +++ b/ubuntu/vars.yaml @@ -295,12 +295,15 @@ powershell_modules: # pipx modules pipx_packages: + - uv + +# uv tools +uv_tools: - aws-sam-cli - cfn-lint - poetry - ruff - taskcat - - uv # npm global packages npm_global_packages: diff --git a/windows/README.md b/windows/README.md index 9e8aaf6..a95a7c8 100644 --- a/windows/README.md +++ b/windows/README.md @@ -11,6 +11,7 @@ The setup script (`setup.ps1`) automates the installation and configuration of: - [PowerShell](https://github.com/PowerShell/PowerShell) modules (via PSResourceGet) - Windows PowerShell modules (via PowerShellGet) - [pipx](https://pypa.github.io/pipx/) packages (Python tools) +- [uv](https://docs.astral.sh/uv/) tools (Python CLI tools) - [npm](https://www.npmjs.com/) global packages (Node.js tools) - [.NET Global Tools](https://docs.microsoft.com/en-us/dotnet/core/tools/global-tools) (when .NET SDK is available) - [Visual Studio Code](https://code.visualstudio.com/) extensions @@ -140,10 +141,20 @@ windows_powershell_modules: ### pipx Packages -Python tools installed in isolated environments: +Python tools installed in isolated environments +(empty on Windows; uv is available via Chocolatey): ```yaml pipx_packages: +``` + +### uv Tools + +Python CLI tools installed via `uv tool install`. +Skipped if uv is not installed: + +```yaml +uv_tools: - cfn-lint - poetry # etc. diff --git a/windows/setup.ps1 b/windows/setup.ps1 index a57bd08..aa64e33 100644 --- a/windows/setup.ps1 +++ b/windows/setup.ps1 @@ -602,6 +602,52 @@ if ($pipxPackages -and $pipxPackages.Count -gt 0) { #endregion Ensure pipx Packages from Vars file are Installed +#region Ensure uv Tools from Vars file are Installed + +$step++ +$stepText = 'Ensure uv Tools from Vars file are Installed' +Write-Progress -Activity $activity -Status (& $statusBlock) -PercentComplete ($step / $totalSteps * 100) +Write-Information -MessageData 'Checking for uv tools to install...' + +# Get +Write-Verbose -Message '[Get] uv...' +$uvCmd = Get-Command -Name uv -ErrorAction SilentlyContinue + +# Test +Write-Verbose -Message '[Test] uv...' +if ($null -eq $uvCmd) { + Write-Information -MessageData 'uv is not installed, skipping uv tool installations.' +} else { + # Get + Write-Verbose -Message '[Get] uv tools from Vars file import...' + $uvTools = $vars.uv_tools + + # Test + Write-Verbose -Message '[Test] uv tools from Vars file import...' + if ($uvTools -and $uvTools.Count -gt 0) { + foreach ($tool in $uvTools) { + Write-Progress -Activity $activity -Status ( + & $StatusBlock + ) -CurrentOperation $tool -PercentComplete ($step / $totalSteps * 100) + Write-Information -MessageData "Installing uv tool $tool..." + + # Set + Write-Verbose -Message "[Set] uv tool: $tool" + try { + uv tool install $tool + Write-Verbose -Message "[Set] uv tool $tool installation complete." + Write-Information -MessageData "Installed uv tool: $tool." + } catch { + Write-Error -Message "Failed to install uv tool: $tool. Error: $_" + } + } + } else { + Write-Information -MessageData 'No uv tools specified in vars.yaml file.' + } +} + +#endregion Ensure uv Tools from Vars file are Installed + #region Ensure npm global Packages from Vars file are Installed $step++ diff --git a/windows/vars.yaml b/windows/vars.yaml index 5a6435c..094a4f3 100644 --- a/windows/vars.yaml +++ b/windows/vars.yaml @@ -108,6 +108,9 @@ windows_powershell_modules: # pipx modules pipx_packages: + +# uv tools +uv_tools: - cfn-lint - poetry - taskcat