Skip to content

Commit 33f6cf3

Browse files
committed
RHOAIENG-10972: Create a script to automate library upgrades
1 parent 38a8d17 commit 33f6cf3

File tree

2 files changed

+225
-0
lines changed

2 files changed

+225
-0
lines changed

scripts/README.md

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
# Scripts
2+
3+
## update_library_version.sh
4+
5+
This script updates the version of a specified library in Pipfile and requirements-elyra.txt files, only if the new version is higher. It can optionally run `pipenv lock` after updating the version.
6+
7+
### Examples
8+
9+
Update the `numpy` library to version `2.0.1` in all files under `./myproject`, and run `pipenv lock`:
10+
11+
```sh
12+
./update_library_version.sh ./myproject numpy 2.0.1 '' '' true
13+
```
14+
15+
Update the `pandas` library to version `2.2.2` in all files under `./myproject` where the directory contains `include` or `this`, excluding directories containing `exclude` or `that`, and do not run `pipenv lock`:
16+
17+
```sh
18+
./update_library_version.sh ./myproject pandas 2.2.2 'include|this' 'exclude|that' false
19+
```
20+

scripts/update_library_version.sh

Lines changed: 205 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,205 @@
1+
#!/bin/bash
2+
3+
# Check if the script is running on Linux
4+
if [[ "$OSTYPE" != "linux-gnu"* ]]; then
5+
echo "Error: This script can only be run on Linux."
6+
exit 1
7+
fi
8+
9+
# Detailed help message
10+
print_help() {
11+
echo "Usage: $0 <directory> <library_name> <new_version> <include_paths_with> <exclude_paths_with> <lock_files>"
12+
echo
13+
echo "Parameters:"
14+
echo " directory The root directory to start searching for Pipfile and requirements-elyra.txt files."
15+
echo " library_name The name of the library to update."
16+
echo " new_version The new version to set for the library."
17+
echo " include_paths_with A pipe-separated list of substrings; only files in directories containing at least one of these substrings will be processed."
18+
echo " exclude_paths_with A pipe-separated list of substrings; files in directories containing any of these substrings will be excluded."
19+
echo " lock_files Whether to run 'pipenv lock' after updating the library version (true or false)."
20+
echo
21+
echo "Examples:"
22+
echo " $0 ./myproject numpy 2.0.1 '' '' true"
23+
echo " $0 ./myproject pandas 2.2.2 'include|this' 'exclude|that' false"
24+
}
25+
26+
# Check if the correct number of arguments are passed
27+
if [ "$#" -ne 6 ]; then
28+
print_help
29+
exit 1
30+
fi
31+
32+
# Arguments
33+
directory=$1
34+
library_name=$2
35+
new_version=$3
36+
include_paths_with=$4
37+
exclude_paths_with=$5
38+
lock_files=$6
39+
40+
# Print arguments
41+
echo "Arguments:"
42+
echo " directory = $directory"
43+
echo " library_name = $library_name"
44+
echo " new_version = $new_version"
45+
echo " include_paths_with = $include_paths_with"
46+
echo " exclude_paths_with = $exclude_paths_with"
47+
echo " lock_files = $lock_files"
48+
49+
# Function to check if one version is higher than the other
50+
# Returns 0 if the first version is greater and 1 if the second is greater or equal
51+
is_version_higher() {
52+
local ver1=$1
53+
local ver2=$2
54+
55+
# Remove any non-numeric, non-dot characters from the beginning (before the first number, which represents the version specifier)
56+
ver1=$(echo "$ver1" | sed 's/^[^0-9.]*//')
57+
ver2=$(echo "$ver2" | sed 's/^[^0-9.]*//')
58+
59+
# Split each segment of the version numbers
60+
IFS='.' read -r -a ver1_parts <<< "$ver1"
61+
IFS='.' read -r -a ver2_parts <<< "$ver2"
62+
63+
for ((i = 0; i < ${#ver1_parts[@]} || i < ${#ver2_parts[@]}; i++)); do
64+
# Use 0 if a part is missing
65+
v1=${ver1_parts[i]:-0}
66+
v2=${ver2_parts[i]:-0}
67+
68+
# Compare the parts
69+
if ((v1 > v2)); then
70+
return 0
71+
fi
72+
done
73+
74+
return 1
75+
}
76+
77+
# Function to update the library version in Pipfile files, only if the new version is higher
78+
update_library_version_pipfile() {
79+
local file=$1
80+
local lib=$2
81+
local new_ver=$3
82+
local include_paths_with=$4
83+
local exclude_paths_with=$5
84+
local lock_files=$6
85+
local directory=$(dirname "$file")
86+
local filename=$(basename "$file")
87+
88+
# Determine if this is an architecture-specific Pipfile (with the "gpu" or "cpu" suffixes) and determine the corresponding lock file name
89+
local is_specific=false
90+
local lockfile=""
91+
if [[ "$filename" == Pipfile.gpu ]]; then
92+
is_specific=true
93+
lockfile="Pipfile.lock.gpu"
94+
elif [[ "$filename" == Pipfile.cpu ]]; then
95+
is_specific=true
96+
lockfile="Pipfile.lock.cpu"
97+
else
98+
lockfile="Pipfile.lock"
99+
fi
100+
101+
# Check if the file directory has at least one of the substrings (separated by "|") in $include_paths_with
102+
# and does not contain any of the substrings (separated by "|") in $exclude_paths_with
103+
if { [[ -z "$include_paths_with" ]] || [[ "$directory" =~ $include_paths_with ]]; } && { [[ -z "$exclude_paths_with" ]] || [[ ! "$directory" =~ $exclude_paths_with ]]; }; then
104+
echo "Processing $file (directory matches the pattern)"
105+
else
106+
echo "Skipping $file (directory does not match the pattern)"
107+
return
108+
fi
109+
110+
# Extract the current version and qualifier from the Pipfile
111+
current_line=$(grep -E "^\"?$lib\"? = " "$file")
112+
if [[ $current_line =~ ^\"?$lib\"?[[:space:]]*=[[:space:]]*\"?([=><!~]*)?([0-9]+(\.[0-9]+)*)\"?$ ]]; then
113+
current_qualifier="${BASH_REMATCH[1]}"
114+
current_ver="${BASH_REMATCH[2]}"
115+
116+
# Compare the current and new versions
117+
is_version_higher "$new_ver" "$current_ver"
118+
comparison_result=$?
119+
120+
if [ "$comparison_result" -eq 0 ]; then
121+
# Keep the original qualifier and update to the new version if it is higher
122+
new_line="${lib} = \"${current_qualifier}${new_ver}\""
123+
sed -i -E "s/^\"?$lib\"?[[:space:]]*=[[:space:]]*\"?[=><!~]*[0-9]+(\.[0-9]+)*\"?/${new_line}/" "$file"
124+
echo "Updated $lib in $file to version ${current_qualifier}${new_ver}"
125+
126+
# Handle renaming and pipenv lock, if necessary
127+
if [ "$lock_files" == "true" ]; then
128+
if [ "$is_specific" = true ]; then
129+
mv "$file" "${directory}/Pipfile"
130+
mv "${directory}/$lockfile" "${directory}/Pipfile.lock"
131+
(cd "$directory" && pipenv lock)
132+
mv "${directory}/Pipfile" "$file"
133+
mv "${directory}/Pipfile.lock" "${directory}/$lockfile"
134+
else
135+
(cd "$directory" && pipenv lock)
136+
fi
137+
fi
138+
else
139+
echo "$lib in $file is already up-to-date or has a higher version ($current_ver)."
140+
fi
141+
else
142+
echo "$lib not found in $file."
143+
fi
144+
}
145+
146+
# Function to update the library version in requirements-elyra.txt files, only if the new version is higher
147+
update_library_version_requirements() {
148+
local file=$1
149+
local lib=$2
150+
local new_ver=$3
151+
local include_paths_with=$4
152+
local exclude_paths_with=$5
153+
local directory=$(dirname "$file")
154+
155+
# Check if the file directory has at least one of the substrings (separated by "|") in $include_paths_with
156+
# and does not contain any of the substrings (separated by "|") in $exclude_paths_with
157+
if { [[ -z "$include_paths_with" ]] || [[ "$directory" =~ $include_paths_with ]]; } && { [[ -z "$exclude_paths_with" ]] || [[ ! "$directory" =~ $exclude_paths_with ]]; }; then
158+
echo "Processing $file (directory matches the pattern)"
159+
else
160+
echo "Skipping $file (directory does not match the pattern)"
161+
return
162+
fi
163+
164+
# Extract the current version from the requirements file
165+
current_line=$(grep -E "^$lib==[0-9]+(\.[0-9]+)*$" "$file")
166+
if [[ $current_line =~ ^$lib==([0-9]+(\.[0-9]+)*)$ ]]; then
167+
current_ver="${BASH_REMATCH[1]}"
168+
169+
# Compare the current and new versions
170+
is_version_higher "$new_ver" "$current_ver"
171+
comparison_result=$?
172+
173+
if [ "$comparison_result" -eq 0 ]; then
174+
# Update to the new version if it is higher
175+
new_line="${lib}==${new_ver}"
176+
sed -i -E "s/^$lib==[0-9]+(\.[0-9]+)*/${new_line}/" "$file"
177+
echo "Updated $lib in $file to version ${new_ver}"
178+
else
179+
echo "$lib in $file is already up-to-date or has a higher version ($current_ver)."
180+
fi
181+
else
182+
echo "$lib not found in $file."
183+
fi
184+
}
185+
186+
# Export the functions so they are available in the subshell
187+
export -f is_version_higher
188+
export -f update_library_version_pipfile
189+
export -f update_library_version_requirements
190+
191+
# Find and update Pipfile files and requirements-elyra.txt files
192+
find "$directory" -type f \( -name "Pipfile" -o -name "Pipfile.gpu" -o -name "Pipfile.cpu" -o -name "requirements-elyra.txt" \) -exec bash -c '
193+
file=$0
194+
lib=$1
195+
new_ver=$2
196+
include_paths_with=$3
197+
exclude_paths_with=$4
198+
lock_files=$5
199+
200+
case "$file" in
201+
*Pipfile* ) update_library_version_pipfile "$file" "$lib" "$new_ver" "$include_paths_with" "$exclude_paths_with" "$lock_files" ;;
202+
*requirements-elyra.txt* ) update_library_version_requirements "$file" "$lib" "$new_ver" "$include_paths_with" "$exclude_paths_with" ;;
203+
esac
204+
' {} "$library_name" "$new_version" "$include_paths_with" "$exclude_paths_with" "$lock_files" \;
205+

0 commit comments

Comments
 (0)