From bb4fa88c58d06a1c173ecec88240a2637202c2a4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?F=C3=A9lix-Antoine=20Fortin?= Date: Wed, 20 May 2026 11:54:02 -0400 Subject: [PATCH 1/3] Add support for python version change If uv::venv::python is changed, this allows the original environment to be cleared and a new one to be created in its place. --- manifests/venv.pp | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/manifests/venv.pp b/manifests/venv.pp index c9e5d89..99506ef 100644 --- a/manifests/venv.pp +++ b/manifests/venv.pp @@ -34,9 +34,11 @@ if $python =~ Stdlib::Absolutepath { $path = ["${uv_prefix}/bin", dirname($python),'/bin', '/usr/bin'] $environ = [] + $target = $python } else { $path = ["${uv_prefix}/bin"] $environ = ["XDG_DATA_HOME=${uv_prefix}/share"] + $target = "${uv_prefix}/share/uv/python/*/bin/python${python}" } if $system_site_packages { @@ -46,8 +48,8 @@ } exec { "${name}_venv": - command => "uv venv --seed -p ${python} ${ssp_flag} ${prefix}", - creates => "${prefix}/bin/python", + command => "uv venv --clear --seed -p ${python} ${ssp_flag} ${prefix}", + unless => "/usr/bin/test $(/usr/bin/readlink ${prefix}/bin/python) == ${target}", require => Class['uv::install'], path => $path, environment => $environ, @@ -89,6 +91,6 @@ environment => $pip_environ, timeout => 0, path => $pip_path, - require => Exec["${name}_venv"], + subscribe => Exec["${name}_venv"], } } From bf3ad66762ffdcb1d89ab34dca1901bdbf95d2c6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?F=C3=A9lix-Antoine=20Fortin?= Date: Thu, 21 May 2026 09:50:25 -0400 Subject: [PATCH 2/3] Clear the virtual environment when requirements change --- manifests/venv.pp | 26 +++++++++++++++++++++++--- 1 file changed, 23 insertions(+), 3 deletions(-) diff --git a/manifests/venv.pp b/manifests/venv.pp index 99506ef..4390603 100644 --- a/manifests/venv.pp +++ b/manifests/venv.pp @@ -49,7 +49,7 @@ exec { "${name}_venv": command => "uv venv --clear --seed -p ${python} ${ssp_flag} ${prefix}", - unless => "/usr/bin/test $(/usr/bin/readlink ${prefix}/bin/python) == ${target}", + unless => "/usr/bin/test $(/usr/bin/readlink ${prefix}/bin/python) == ${target} && /usr/bin/test -f ${prefix}/.pipfreeze", require => Class['uv::install'], path => $path, environment => $environ, @@ -71,7 +71,9 @@ if $requirements_path { File["${prefix}/${name}-requirements.1.txt"] { source => "file://${requirements_path}", - notify => Exec["${name}_pip_install"], + notify => [ + Exec["${name}_clear_pipfreeze"], + ], } } @@ -81,10 +83,20 @@ if $requirements { File["${prefix}/${name}-requirements.2.txt"] { content => $requirements, - notify => Exec["${name}_pip_install"], + notify => [ + Exec["${name}_clear_pipfreeze"], + ], } } + exec { "${name}_clear_pipfreeze": + command => "/bin/rm -f ${prefix}/.pipfreeze", + refreshonly => true, + before => [ + Exec["${name}_venv"], + ], + } + exec { "${name}_pip_install": command => "${pip_cmd} -r ${prefix}/${name}-requirements.1.txt -r ${prefix}/${name}-requirements.2.txt", refreshonly => true, @@ -93,4 +105,12 @@ path => $pip_path, subscribe => Exec["${name}_venv"], } + + exec { "${name}_pip_freeze": + command => "uv pip freeze > ${prefix}/.pipfreeze", + creates => "${prefix}/.pipfreeze", + environment => ["VIRTUAL_ENV=${prefix}"], + require => Exec["${name}_pip_install"], + path => ["${uv_prefix}/bin"], + } } From 8492e500a5579f794ba84bd02958b0f33f50be66 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?F=C3=A9lix-Antoine=20Fortin?= Date: Thu, 28 May 2026 10:00:38 -0400 Subject: [PATCH 3/3] Move requirements files under /opt/uv Avoid file being deleted by recreation of the venv --- manifests/install.pp | 1 + manifests/venv.pp | 55 ++++++++++++++++++++++++++------------------ 2 files changed, 33 insertions(+), 23 deletions(-) diff --git a/manifests/install.pp b/manifests/install.pp index c32dee1..1aae0ec 100644 --- a/manifests/install.pp +++ b/manifests/install.pp @@ -7,6 +7,7 @@ ) { ensure_resource('file', $prefix, { 'ensure' => 'directory' }) ensure_resource('file', "${prefix}/bin", { 'ensure' => 'directory', require => File[$prefix] }) + ensure_resource('file', "${prefix}/requirements", { 'ensure' => 'directory', require => File[$prefix] }) $arch = $::facts['os']['architecture'] archive { 'install_uv': path => '/tmp/uv', diff --git a/manifests/venv.pp b/manifests/venv.pp index 4390603..af88d86 100644 --- a/manifests/venv.pp +++ b/manifests/venv.pp @@ -47,29 +47,19 @@ $ssp_flag = '' } - exec { "${name}_venv": - command => "uv venv --clear --seed -p ${python} ${ssp_flag} ${prefix}", - unless => "/usr/bin/test $(/usr/bin/readlink ${prefix}/bin/python) == ${target} && /usr/bin/test -f ${prefix}/.pipfreeze", - require => Class['uv::install'], - path => $path, - environment => $environ, + $uv_req_prefix = "${uv_prefix}/requirements" + $requirement_prefix = "${uv_req_prefix}/${name}" + file { $requirement_prefix: + ensure => directory, + require => File[$uv_req_prefix], } - if 'PIP_CONFIG_FILE' in $pip_environment { - $pip_cmd = 'pip install' - $pip_environ = $pip_env_list - $pip_path = ["${prefix}/bin", '/usr/bin'] - } else { - $pip_cmd = 'uv pip install' - $pip_environ = $pip_env_list + ["VIRTUAL_ENV=${prefix}"] - $pip_path = ["${uv_prefix}/bin", '/usr/bin'] - } - - file { "${prefix}/${name}-requirements.1.txt": - ensure => file, + file { "${requirement_prefix}/requirements.1.txt": + ensure => file, + require => File[$requirement_prefix], } if $requirements_path { - File["${prefix}/${name}-requirements.1.txt"] { + File["${requirement_prefix}/requirements.1.txt"] { source => "file://${requirements_path}", notify => [ Exec["${name}_clear_pipfreeze"], @@ -77,11 +67,12 @@ } } - file { "${prefix}/${name}-requirements.2.txt": - ensure => file, + file { "${requirement_prefix}/requirements.2.txt": + ensure => file, + require => File[$requirement_prefix], } if $requirements { - File["${prefix}/${name}-requirements.2.txt"] { + File["${requirement_prefix}/requirements.2.txt"] { content => $requirements, notify => [ Exec["${name}_clear_pipfreeze"], @@ -97,8 +88,26 @@ ], } + exec { "${name}_venv": + command => "uv venv --clear --seed -p ${python} ${ssp_flag} ${prefix}", + unless => "/usr/bin/test $(/usr/bin/readlink ${prefix}/bin/python) == ${target} && /usr/bin/test -f ${prefix}/.pipfreeze", + require => Class['uv::install'], + path => $path, + environment => $environ, + } + + if 'PIP_CONFIG_FILE' in $pip_environment { + $pip_cmd = 'pip install' + $pip_environ = $pip_env_list + $pip_path = ["${prefix}/bin", '/usr/bin'] + } else { + $pip_cmd = 'uv pip install' + $pip_environ = $pip_env_list + ["VIRTUAL_ENV=${prefix}"] + $pip_path = ["${uv_prefix}/bin", '/usr/bin'] + } + exec { "${name}_pip_install": - command => "${pip_cmd} -r ${prefix}/${name}-requirements.1.txt -r ${prefix}/${name}-requirements.2.txt", + command => "${pip_cmd} -r ${requirement_prefix}/requirements.1.txt -r ${requirement_prefix}/requirements.2.txt", refreshonly => true, environment => $pip_environ, timeout => 0,