@@ -15,10 +15,18 @@ blue=$(tput setaf 4 2>/dev/null || echo "")
1515reset=$( tput sgr0 2> /dev/null || echo " " )
1616
1717# =============================================
18- # CONFIGURATION - Edit versions here
18+ # CONFIGURATION
19+ # Defaults use the latest versions reported by mise at install time.
20+ # Override when needed, e.g.:
21+ # PYTHON_VERSION=3.12.7 NODE_VERSION=22 PNPM_VERSION=10 ./setup/devenv_install.sh
1922# =============================================
20- PYTHON_VERSION=" 3.12.7"
21- NODE_VERSION=" latest"
23+ PYTHON_VERSION=" ${PYTHON_VERSION:- latest} "
24+ NODE_VERSION=" ${NODE_VERSION:- latest} "
25+ PNPM_VERSION=" ${PNPM_VERSION:- latest} "
26+
27+ RESOLVED_PYTHON_VERSION=" "
28+ RESOLVED_NODE_VERSION=" "
29+ RESOLVED_PNPM_VERSION=" "
2230
2331# Python tools to install globally
2432PYTHON_TOOLS_ARRAY=(" poetry" " ipython" " pytest" " black" " ruff" " mypy" " requests" " colorama" " pipx" )
@@ -212,39 +220,91 @@ activate_mise() {
212220 log_success " mise activated"
213221}
214222
223+ # =============================================
224+ # RESOLVE TOOL VERSIONS
225+ # =============================================
226+ resolve_mise_version () {
227+ local tool=" $1 "
228+ local requested_version=" $2 "
229+ local latest_version=" "
230+
231+ if [[ " $requested_version " == " latest" ]]; then
232+ latest_version=$( mise latest " $tool " 2> /dev/null | awk ' NF {print $1; exit}' )
233+ if [[ -n " $latest_version " ]]; then
234+ echo " $latest_version "
235+ return 0
236+ fi
237+ fi
238+
239+ echo " $requested_version "
240+ }
241+
242+ resolve_tool_versions () {
243+ log_info " Resolving latest tool versions from mise..."
244+
245+ RESOLVED_PYTHON_VERSION=$( resolve_mise_version " python" " $PYTHON_VERSION " )
246+ RESOLVED_NODE_VERSION=$( resolve_mise_version " node" " $NODE_VERSION " )
247+ RESOLVED_PNPM_VERSION=$( resolve_mise_version " pnpm" " $PNPM_VERSION " )
248+
249+ log_info " Python: $PYTHON_VERSION -> $RESOLVED_PYTHON_VERSION "
250+ log_info " Node.js: $NODE_VERSION -> $RESOLVED_NODE_VERSION "
251+ log_info " pnpm: $PNPM_VERSION -> $RESOLVED_PNPM_VERSION "
252+ }
253+
254+ python_venv_name () {
255+ local version
256+ version=$( mise list python --current 2> /dev/null | awk ' NF {print $2; exit}' )
257+ version=" ${version:- ${RESOLVED_PYTHON_VERSION:- $PYTHON_VERSION } } "
258+ echo " tools${version% .* } "
259+ }
260+
215261# =============================================
216262# INSTALL PYTHON
217263# =============================================
218264install_python () {
219- log_info " Installing Python $PYTHON_VERSION via mise..."
265+ local version=" ${RESOLVED_PYTHON_VERSION:- $PYTHON_VERSION } "
266+ log_info " Installing Python $version via mise..."
220267
221- # Check if already installed
222- if mise list python 2> /dev/null | grep -q " $PYTHON_VERSION " ; then
223- log_warning " Python $PYTHON_VERSION already installed"
224- else
225- mise install python@$PYTHON_VERSION
226- log_success " Python $PYTHON_VERSION installed"
227- fi
268+ # mise install is idempotent and also fixes versions marked as missing.
269+ mise install python@$version
270+ log_success " Python $version installed"
228271
229272 # Set as global default
230- mise use --global python@$PYTHON_VERSION
231- log_success " Python $PYTHON_VERSION set as global default"
273+ mise use --global python@$version
274+ log_success " Python $version set as global default"
232275}
233276
234277# =============================================
235278# INSTALL NODE.JS
236279# =============================================
237280install_nodejs () {
238- log_info " Installing Node.js (latest) via mise..."
281+ local version=" ${RESOLVED_NODE_VERSION:- $NODE_VERSION } "
282+ log_info " Installing Node.js $version via mise..."
239283
240- mise install node@latest
241- mise use --global node@latest
284+ mise install node@$version
285+ mise use --global node@$version
242286
243287 local installed_version
244288 installed_version=$( mise list node --current 2> /dev/null | awk ' {print $2}' | head -1)
245289 log_success " Node.js $installed_version installed and set as global default"
246290}
247291
292+ # =============================================
293+ # INSTALL PNPM
294+ # =============================================
295+ install_pnpm () {
296+ local version=" ${RESOLVED_PNPM_VERSION:- $PNPM_VERSION } "
297+ log_info " Installing pnpm $version via mise..."
298+
299+ # pnpm is managed by mise directly so it is available as a shim alongside node/npm.
300+ mise install pnpm@$version
301+ mise use --global pnpm@$version
302+
303+ local installed_version
304+ installed_version=$( mise list pnpm --current 2> /dev/null | awk ' {print $2}' | head -1)
305+ log_success " pnpm $installed_version installed and set as global default"
306+ }
307+
248308# =============================================
249309# SETUP DIRECTORIES
250310# =============================================
@@ -267,7 +327,8 @@ setup_directories() {
267327setup_python_venv () {
268328 log_info " Setting up Python virtual environment..."
269329
270- local venv_name=" tools${PYTHON_VERSION% .* } "
330+ local venv_name
331+ venv_name=$( python_venv_name)
271332 local venv_path=" $VENVS /$venv_name "
272333
273334 if [[ -d " $venv_path " ]]; then
@@ -292,7 +353,8 @@ setup_python_venv() {
292353install_python_tools () {
293354 log_info " Installing Python tools..."
294355
295- local venv_name=" tools${PYTHON_VERSION% .* } "
356+ local venv_name
357+ venv_name=$( python_venv_name)
296358 local venv_path=" $VENVS /$venv_name "
297359 local pip_path=" $venv_path /bin/pip"
298360
@@ -317,14 +379,17 @@ create_global_tool_versions() {
317379 # Get actual installed versions
318380 local python_full=$( mise list python --current 2> /dev/null | awk ' {print $2}' | head -1)
319381 local node_full=$( mise list node --current 2> /dev/null | awk ' {print $2}' | head -1)
382+ local pnpm_full=$( mise list pnpm --current 2> /dev/null | awk ' {print $2}' | head -1)
320383
321384 # Fallback to requested versions if detection fails
322- python_full=" ${python_full:- $PYTHON_VERSION } "
323- node_full=" ${node_full:- $NODE_VERSION } "
385+ python_full=" ${python_full:- ${RESOLVED_PYTHON_VERSION:- $PYTHON_VERSION } } "
386+ node_full=" ${node_full:- ${RESOLVED_NODE_VERSION:- $NODE_VERSION } } "
387+ pnpm_full=" ${pnpm_full:- ${RESOLVED_PNPM_VERSION:- $PNPM_VERSION } } "
324388
325389 cat > " $tool_versions " << EOF
326390python $python_full
327391nodejs $node_full
392+ pnpm $pnpm_full
328393EOF
329394
330395 log_success " Global .tool-versions created"
@@ -380,8 +445,19 @@ check_installation() {
380445 warnings+=(" npm" )
381446 fi
382447
448+ # Check pnpm
449+ if command_exists pnpm; then
450+ local pnpm_version=$( pnpm --version 2>&1 )
451+ log_success " pnpm: $pnpm_version "
452+ checks+=(" pnpm" )
453+ else
454+ log_error " pnpm not found"
455+ warnings+=(" pnpm" )
456+ fi
457+
383458 # Check Python tools in virtualenv
384- local venv_name=" tools${PYTHON_VERSION% .* } "
459+ local venv_name
460+ venv_name=$( python_venv_name)
385461 local venv_path=" $VENVS /$venv_name "
386462 local tools=(" poetry" " black" " ruff" " pytest" )
387463
@@ -460,6 +536,7 @@ print_usage() {
460536 echo " # Install a specific version"
461537 echo " mise install python@3.13"
462538 echo " mise install node@20"
539+ echo " mise install pnpm@latest"
463540 echo " "
464541 echo " # Set global version"
465542 echo " mise use --global python@3.12"
@@ -470,8 +547,11 @@ print_usage() {
470547 echo " # Update mise itself"
471548 echo " mise self-update"
472549 echo " "
550+ echo " # Override default latest versions when needed"
551+ echo " PYTHON_VERSION=3.12.7 NODE_VERSION=22 PNPM_VERSION=10 ./setup/devenv_install.sh"
552+ echo " "
473553 echo " # Activate virtualenv for Python tools"
474- echo " source $VENVS /tools ${PYTHON_VERSION % . * } /bin/activate"
554+ echo " source $VENVS /$( python_venv_name ) /bin/activate"
475555 echo " "
476556}
477557
@@ -490,8 +570,10 @@ main() {
490570 install_mise
491571 configure_mise_shell
492572 activate_mise
573+ resolve_tool_versions
493574 install_python
494575 install_nodejs
576+ install_pnpm
495577 setup_directories
496578 setup_python_venv
497579 install_python_tools
0 commit comments