Skip to content

Commit 33d3689

Browse files
author
Benjamin Moody
committed
update: install python libraries atomically.
We want to avoid "upgrading" python libraries using pip, because this may not give predictable results, and if installation fails it can leave the system in a broken half-installed state. Consequently, instead of installing packages into /physionet/python-env/physionet, install them into a directory named for the MD5 hash of requirements.txt. Installation may produce a lot of output (e.g. when compiling extension modules from source), so store the log in the installation directory rather than further cluttering update.log. After the pip command is successful, copy requirements.txt to a new file installed.txt. This serves as a flag to indicate that the packages were installed successfully, and also provides documentation of what was supposedly installed. If requirements.txt matches installed.txt, then we know that we don't need to reinstall anything. After the packages have been successfully installed and we have tested that they're working (at least well enough to invoke getmigrationtargets), then update the symlink /physionet/python-env/physionet to point to the new prefix.
1 parent 3e1e03d commit 33d3689

File tree

1 file changed

+24
-8
lines changed

1 file changed

+24
-8
lines changed

deploy/update

Lines changed: 24 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,8 @@ set -e
44

55
install_dir=/physionet/physionet-build
66
working_dir=/physionet/physionet-build.new
7-
venv_dir=/physionet/python-env/physionet
7+
venv_prefix=/physionet/python-env
8+
venv_dir=$venv_prefix/physionet
89
log_file=/data/log/pn/update.log
910
branch=$(cat /physionet/deploy-branch) # production or staging
1011

@@ -76,18 +77,28 @@ mkdir -p $working_dir
7677
git archive "$newrev" | tar -x -C $working_dir
7778
ln -s $install_dir/.env $working_dir/.env
7879

79-
. $venv_dir/bin/activate
80-
81-
# Install new dependencies from 'requirements.txt' into $venv_dir
80+
# Install new dependencies from 'requirements.txt' into $new_venv_dir
8281
if [ -n "$no_pip" ]; then
8382
echo "- SKIPPING requirements due to --push-option=no-pip"
83+
new_venv_dir=$venv_dir
8484
else
85-
echo "* Installing new requirements..."
86-
pip3 install -r $working_dir/requirements.txt \
87-
--quiet --require-hashes --log $log_file
88-
echo >> $log_file
85+
hash=$(md5sum "$working_dir/requirements.txt" | cut -d' ' -f1)
86+
new_venv_dir=$venv_prefix/$hash
87+
if [ -d "$new_venv_dir" ] && cmp -s "$working_dir/requirements.txt" \
88+
"$new_venv_dir/installed.txt"; then
89+
echo "- Requirements previously installed ($hash)."
90+
else
91+
echo "* Installing new requirements ($hash)..."
92+
virtualenv -ppython3 --quiet --clear --no-download "$new_venv_dir"
93+
pip_log=$new_venv_dir/pip-install.log
94+
"$new_venv_dir/bin/pip3" install -r "$working_dir/requirements.txt" \
95+
--quiet --require-hashes --log $pip_log
96+
cp "$working_dir/requirements.txt" "$new_venv_dir/installed.txt"
97+
fi
8998
fi
9099

100+
. $new_venv_dir/bin/activate
101+
91102
# Run 'getmigrationtargets' to check whether migrations make sense
92103
# (e.g. broken dependencies, ghost migrations)
93104
echo "* Checking migrations..."
@@ -98,4 +109,9 @@ echo "* Checking migrations..."
98109
./manage.py getmigrationtargets > /dev/null
99110
)
100111

112+
# Update $venv_dir to point to $new_venv_dir
113+
if [ "$venv_dir" != "$new_venv_dir" ]; then
114+
ln -s -f -T "$new_venv_dir" "$venv_dir"
115+
fi
116+
101117
echo "$(date '+%F %T %z'): $branch: update finished" >> $log_file

0 commit comments

Comments
 (0)