forked from heroku/heroku-buildpack-python
-
Notifications
You must be signed in to change notification settings - Fork 6
Expand file tree
/
Copy pathcompile
More file actions
executable file
·246 lines (190 loc) · 6.53 KB
/
Copy pathcompile
File metadata and controls
executable file
·246 lines (190 loc) · 6.53 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
#!/usr/bin/env bash
# Usage:
#
# $ bin/compile <build-dir> <cache-dir>
# Fail fast and fail hard.
set -eo pipefail
# Prepend proper path for virtualenv hackery. This will be deprecated soon.
export PATH=:/usr/local/bin:$PATH
# Paths.
BIN_DIR=$(cd $(dirname $0); pwd) # absolute path
ROOT_DIR=$(dirname $BIN_DIR)
BUILD_DIR=$1
CACHE_DIR=$2
. "$BIN_DIR/configs"
APP_PAAS_DIR="$APP_DIR/$PAASPROVIDER_DIR"
APP_PYTHON_HOME_DIR="$APP_PAAS_DIR/python"
CACHED_DIRS="$PAASPROVIDER_DIR"
# Static configurations for virtualenv caches.
VIRTUALENV_LOC="$PAASPROVIDER_DIR/venv"
LEGACY_TRIGGER="lib/python2.7"
PROFILE_PATH="$BUILD_DIR/.profile.d/python.sh"
# Python version. This will be used in the future to specify custom Pythons.
DEFAULT_PYTHON_VERSION="python-2.7.3"
PYTHON_EXE="$APP_PYTHON_HOME_DIR/bin/python"
PIP_VERSION="1.3.1"
DISTRIBUTE_VERSION="0.6.36"
# Setup bpwatch
export PATH=$PATH:$ROOT_DIR/vendor/bpwatch
LOGPLEX_KEY="t.b396af7f-ad75-4643-8b9e-ebb288acc624"
export BPWATCH_STORE_PATH=$CACHE_DIR/bpwatch.json
BUILDPACK_VERSION=v25
# Support Anvil Build_IDs
[ ! "$REQUEST_ID" ] && REQUEST_ID=$SLUG_ID
# Sanitizing environment variables.
unset GIT_DIR PYTHONHOME PYTHONPATH LD_LIBRARY_PATH LIBRARY_PATH
bpwatch init $LOGPLEX_KEY
bpwatch build python $BUILDPACK_VERSION $REQUEST_ID
TMP_APP_DIR=$CACHE_DIR/tmp_app_dir
bpwatch start compile
# We'll need to send these statics to other scripts we `source`.
export BUILD_DIR CACHE_DIR BIN_DIR PROFILE_PATH
# Syntax sugar.
source $BIN_DIR/utils
# Directory Hacks for path consistiency.
APP_DIR='$APP_DIR'
TMP_APP_DIR=$CACHE_DIR/tmp_app_dir
# Set new context.
ORIG_BUILD_DIR=$BUILD_DIR
LIBRARY_DIR="$APP_PAAS_DIR/vendor/lib"
BUILDPACK_PYTHON_HOME=$BUILD_DIR/$PAASPROVIDER_DIR/python
# Prepend proper path buildpack use.
export PATH=$BUILDPACK_PYTHON_HOME/bin:$PATH
export PYTHONUNBUFFERED=1
export LANG=en_US.UTF-8
export LIBRARY_PATH=$LIBRARY_DIR
export LD_LIBRARY_PATH=$LIBRARY_DIR
# Switch to the repo's context.
cd $BUILD_DIR
# Experimental pre_compile hook.
bpwatch start pre_compile
source $BIN_DIR/steps/hooks/pre_compile
bpwatch stop pre_compile
# If no requirements given, assume `setup.py develop`.
if [ ! -f requirements.txt ]; then
puts-step "No requirements.txt provided; assuming dist package."
echo "-e ." > requirements.txt
fi
# If no runtime given, assume default version.
if [ ! -f runtime.txt ]; then
puts-step "No runtime.txt provided; assuming $DEFAULT_PYTHON_VERSION."
echo $DEFAULT_PYTHON_VERSION > runtime.txt
fi
# ### The Cache
mkdir -p $CACHE_DIR
# Purge "old-style" virtualenvs.
bpwatch start clear_old_venvs
[ -d $CACHE_DIR/$LEGACY_TRIGGER ] && rm -fr $CACHE_DIR/$PAASPROVIDER_DIR/bin $CACHE_DIR/$PAASPROVIDER_DIR/lib $CACHE_DIR/$PAASPROVIDER_DIR/include
[ -d $CACHE_DIR/$VIRTUALENV_LOC ] && rm -fr $CACHE_DIR/$PAASPROVIDER_DIR/venv $CACHE_DIR/$PAASPROVIDER_DIR/src
bpwatch stop clear_old_venvs
# Restore old artifacts from the cache.
bpwatch start restore_cache
for dir in $CACHED_DIRS; do
cp -R $CACHE_DIR/$dir . &> /dev/null || true
done
bpwatch stop restore_cache
set +e
# Create set-aside `$PAASPROVIDER_DIR` folder.
mkdir $PAASPROVIDER_DIR &> /dev/null
set -e
mkdir -p $(dirname $PROFILE_PATH)
set +e
PYTHON_VERSION=$(cat runtime.txt)
# Install Python.
if [ -f $PAASPROVIDER_DIR/python-version ]; then
if [ ! $(cat $PAASPROVIDER_DIR/python-version) = $PYTHON_VERSION ]; then
bpwatch start uninstall_python
puts-step "Found $(cat $PAASPROVIDER_DIR/python-version), removing."
rm -fr $PAASPROVIDER_DIR/python
bpwatch stop uninstall_python
else
SKIP_INSTALL=1
fi
fi
if [ ! "$SKIP_INSTALL" ]; then
bpwatch start install_python
puts-step "Preparing Python runtime ($PYTHON_VERSION)"
curl "$ARTIFACT_SOURCE_URL/$PYTHON_VERSION.tar.bz2" -s | tar jx &> /dev/null
if [[ $? != 0 ]] ; then
puts-warn "Requested runtime ($PYTHON_VERSION) was not found."
puts-warn "Aborting."
exit 1
fi
mv python $PAASPROVIDER_DIR/python
bpwatch stop install_python
# Record for future reference.
echo $PYTHON_VERSION > $PAASPROVIDER_DIR/python-version
FRESH_PYTHON=true
hash -r
else
puts-step "Using Python runtime ($PYTHON_VERSION)"
fi
# If Pip isn't up to date:
if [ "$FRESH_PYTHON" ] || [[ ! $(pip --version) == *$PIP_VERSION* ]]; then
WORKING_DIR=$(pwd)
bpwatch start prepare_environment
bpwatch start install_distribute
# Prepare it for the real world
puts-step "Installing Distribute ($DISTRIBUTE_VERSION)"
cd $ROOT_DIR/vendor/distribute-$DISTRIBUTE_VERSION/
python setup.py install &> /dev/null
cd $WORKING_DIR
bpwatch stop install_distribute
bpwatch start install_pip
puts-step "Installing Pip ($PIP_VERSION)"
cd $ROOT_DIR/vendor/pip-$PIP_VERSION/
python setup.py install &> /dev/null
cd $WORKING_DIR
bpwatch stop install_pip
bpwatch stop prepare_environment
fi
set -e
hash -r
# Pylibmc support.
# See [`bin/steps/pylibmc`](pylibmc.html).
bpwatch start pylibmc_install
source $BIN_DIR/steps/pylibmc
bpwatch stop pylibmc_install
# Install Mercurial if it appears to be required.
if (grep -Fiq "hg+" requirements.txt) then
bpwatch start mercurial_install
$BUILDPACK_PYTHON_HOME/bin/pip install --use-mirrors mercurial | cleanup | indent
bpwatch stop mercurial_install
fi
# Install dependencies with Pip.
puts-step "Installing dependencies using Pip ($PIP_VERSION)"
[ ! "$FRESH_PYTHON" ] && bpwatch start pip_install
[ "$FRESH_PYTHON" ] && bpwatch start pip_install_first
echo "DEBUG $PYTHON_EXE"
ln $BUILDPACK_PYTHON_HOME/bin/python $PYTHON_EXE
$PYTHON_EXE $BUILDPACK_PYTHON_HOME/bin/pip install --use-mirrors -r requirements.txt --exists-action=w --src=./$PAASPROVIDER_DIR/src | indent
[ ! "$FRESH_PYTHON" ] && bpwatch stop pip_install
[ "$FRESH_PYTHON" ] && bpwatch stop pip_install_first
# Django collectstatic support.
bpwatch start collectstatic
source $BIN_DIR/steps/collectstatic
bpwatch stop collectstatic
# ### Finalize
#
# Set context environment variables.
set-env PYTHONUNBUFFERED true
set-env PYTHONHOME $APP_PYTHON_HOME_DIR
set-env PATH '$PYTHONHOME/bin:$PATH'
set-default-env LIBRARY_PATH $LIBRARY_DIR
set-default-env LD_LIBRARY_PATH $LIBRARY_DIR
set-default-env LANG en_US.UTF-8
set-default-env PYTHONHASHSEED random
set-default-env PYTHONPATH $APP_DIR/
# Experimental post_compile hook.
bpwatch start post_compile
source $BIN_DIR/steps/hooks/post_compile
bpwatch stop post_compile
# Store new artifacts in cache.
bpwatch start dump_cache
for dir in $CACHED_DIRS; do
rm -rf $CACHE_DIR/$dir
cp -R $dir $CACHE_DIR/
done
bpwatch stop dump_cache
# ### Fin.
bpwatch stop compile