12
12
13
13
set -eou pipefail
14
14
15
+ # an arbitrary number: bump when there's a change that someone might want to query for
16
+ # (e.g. checking $(PANTS_BOOTSTRAP_TOOLS=1 ./pants version) >= ...)
17
+ SCRIPT_VERSION=1
18
+
19
+ # Source any custom bootstrap settings for Pants from PANTS_BOOTSTRAP if it exists.
20
+ : ${PANTS_BOOTSTRAP:= " .pants.bootstrap" }
21
+ if [[ -f " ${PANTS_BOOTSTRAP} " ]]; then
22
+ source " ${PANTS_BOOTSTRAP} "
23
+ fi
24
+
15
25
# NOTE: To use an unreleased version of Pants from the pantsbuild/pants main branch,
16
26
# locate the main branch SHA, set PANTS_SHA=<SHA> in the environment, and run this script as usual.
17
27
#
18
28
# E.g., PANTS_SHA=725fdaf504237190f6787dda3d72c39010a4c574 ./pants --version
29
+ #
30
+ # You can also use PANTS_VERSION=<VERSION> to override the config version that is in the pants.toml file.
31
+ #
32
+ # E.g., PANTS_VERSION=2.13.0 ./pants --version
19
33
20
34
PYTHON_BIN_NAME=" ${PYTHON:- unspecified} "
21
35
34
48
35
49
PANTS_BOOTSTRAP=" ${PANTS_SETUP_CACHE} /bootstrap-$( uname -s) -$( uname -m) "
36
50
37
- _PEX_VERSION=2.1.42
51
+ _PEX_VERSION=2.1.103
38
52
_PEX_URL=" https://github.com/pantsbuild/pex/releases/download/v${_PEX_VERSION} /pex"
39
- _PEX_EXPECTED_SHA256=" 69d6b1b1009b00dd14a3a9f19b72cff818a713ca44b3186c9b12074b2a31e51f "
53
+ _PEX_EXPECTED_SHA256=" 4d45336511484100ae4e2bab24542a8b86b12c8cb89230463593c60d08c4b8d3 "
40
54
41
55
VIRTUALENV_VERSION=20.4.7
42
56
VIRTUALENV_REQUIREMENTS=$(
@@ -58,6 +72,8 @@ COLOR_GREEN="\x1b[32m"
58
72
COLOR_YELLOW=" \x1b[33m"
59
73
COLOR_RESET=" \x1b[0m"
60
74
75
+ INSTALL_URL=" https://www.pantsbuild.org/docs/installation"
76
+
61
77
function log() {
62
78
echo -e " $@ " 1>&2
63
79
}
@@ -87,13 +103,18 @@ function get_exe_path_or_die {
87
103
fi
88
104
}
89
105
90
- function get_pants_config_value {
106
+ function get_pants_config_string_value {
91
107
local config_key=" $1 "
92
108
local optional_space=" [[:space:]]*"
93
109
local prefix=" ^${config_key}${optional_space} =${optional_space} "
94
110
local raw_value
95
- raw_value=" $( sed -ne " /${prefix} / s#${prefix} ##p" " ${PANTS_TOML} " ) "
96
- echo " ${raw_value} " | tr -d \"\' && return 0
111
+ raw_value=" $( sed -ne " /${prefix} / s|${prefix} ||p" " ${PANTS_TOML} " ) "
112
+ local optional_suffix=" ${optional_space} (#.*)?$"
113
+ echo " ${raw_value} " \
114
+ | sed -E \
115
+ -e " s|^'([^']*)'${optional_suffix} |\1|" \
116
+ -e ' s|^"([^"]*)"' " ${optional_suffix} " ' $|\1|' \
117
+ && return 0
97
118
return 0
98
119
}
99
120
@@ -125,11 +146,16 @@ function determine_pants_version {
125
146
return
126
147
fi
127
148
128
- pants_version=" $( get_pants_config_value ' pants_version' ) "
149
+ if [ -n " ${PANTS_VERSION:- } " ]; then
150
+ echo " ${PANTS_VERSION} "
151
+ return
152
+ fi
153
+
154
+ pants_version=" $( get_pants_config_string_value ' pants_version' ) "
129
155
if [[ -z " ${pants_version} " ]]; then
130
156
die " Please explicitly specify the \` pants_version\` in your \` pants.toml\` under the \` [GLOBAL]\` scope.
131
157
See https://pypi.org/project/pantsbuild.pants/#history for all released versions
132
- and https://www.pantsbuild.org/docs/installation for more instructions."
158
+ and ${INSTALL_URL} for more instructions."
133
159
fi
134
160
pants_major_version=" $( echo " ${pants_version} " | cut -d ' .' -f1) "
135
161
pants_minor_version=" $( echo " ${pants_version} " | cut -d ' .' -f2) "
@@ -191,8 +217,8 @@ function determine_default_python_exe {
191
217
if [[ -z " ${interpreter_path} " ]]; then
192
218
continue
193
219
fi
194
- # Check if the Python version is installed via Pyenv but not activated .
195
- if [[ " $( " $ {interpreter_path}" --version 2>&1 > /dev/null) " == " pyenv: python ${version} " * ]] ; then
220
+ # Check if a version is shimmed by pyenv or asdf but not configured .
221
+ if ! " ${interpreter_path} " --version > /dev/null 2>&1 ; then
196
222
continue
197
223
fi
198
224
if [[ -n " $( check_python_exe_compatible_version " ${interpreter_path} " ) " ]]; then
@@ -248,9 +274,13 @@ function bootstrap_pex {
248
274
mkdir -p " ${PANTS_BOOTSTRAP} "
249
275
local staging_dir
250
276
staging_dir=$( tempdir " ${PANTS_BOOTSTRAP} " )
251
- cd " ${staging_dir} "
252
- curl -LO " ${_PEX_URL} "
253
- fingerprint=" $( compute_sha256 " ${python} " " pex" ) "
277
+ curl --proto " =https" \
278
+ --tlsv1.2 \
279
+ --silent \
280
+ --location \
281
+ -o " ${staging_dir} /pex" \
282
+ " ${_PEX_URL} "
283
+ fingerprint=" $( compute_sha256 " ${python} " " ${staging_dir} /pex" ) "
254
284
if [[ " ${_PEX_EXPECTED_SHA256} " != " ${fingerprint} " ]]; then
255
285
die " SHA256 of ${_PEX_URL} is not as expected. Aborting."
256
286
fi
@@ -263,12 +293,22 @@ function bootstrap_pex {
263
293
echo " ${bootstrapped} "
264
294
}
265
295
266
- function scrub_PEX_env_vars {
296
+ function scrub_env_vars {
267
297
# Ensure the virtualenv PEX runs as shrink-wrapped.
268
298
# See: https://github.com/pantsbuild/setup/issues/105
269
- if [[ -n " ${! PEX_@ } " ]]; then
270
- warn " Scrubbing ${! PEX_@ } "
271
- unset " ${! PEX_@ } "
299
+ local -r pex_env_vars=(${! PEX_@ } )
300
+ if [[ ! ${# pex_env_vars[@]} -eq 0 ]]; then
301
+ local -r pex_env_vars_to_scrub=" ${pex_env_vars[@]/ PEX_ROOT} "
302
+ if [[ -n " ${pex_env_vars_to_scrub[@]} " ]]; then
303
+ warn " Scrubbing ${pex_env_vars_to_scrub[@]} "
304
+ unset ${pex_env_vars_to_scrub[@]}
305
+ fi
306
+ fi
307
+ # Also ensure pip doesn't think packages on PYTHONPATH
308
+ # are already installed.
309
+ if [ -n " ${PYTHONPATH:- } " ]; then
310
+ warn " Scrubbing PYTHONPATH"
311
+ unset PYTHONPATH
272
312
fi
273
313
}
274
314
@@ -282,11 +322,10 @@ function bootstrap_virtualenv {
282
322
mkdir -p " ${PANTS_BOOTSTRAP} "
283
323
local staging_dir
284
324
staging_dir=$( tempdir " ${PANTS_BOOTSTRAP} " )
285
- cd " ${staging_dir} "
286
- echo " ${VIRTUALENV_REQUIREMENTS} " > requirements.txt
325
+ echo " ${VIRTUALENV_REQUIREMENTS} " > " ${staging_dir} /requirements.txt"
287
326
(
288
- scrub_PEX_env_vars
289
- " ${python} " " ${pex_path} " -r requirements.txt -c virtualenv -o virtualenv.pex
327
+ scrub_env_vars
328
+ " ${python} " " ${pex_path} " -r " ${staging_dir} / requirements.txt" -c virtualenv -o " ${staging_dir} / virtualenv.pex"
290
329
)
291
330
mkdir -p " $( dirname " ${bootstrapped} " ) "
292
331
mv -f " ${staging_dir} /virtualenv.pex" " ${bootstrapped} "
@@ -307,7 +346,12 @@ function get_version_for_sha {
307
346
308
347
# Retrieve the Pants version associated with this commit.
309
348
local pants_version
310
- pants_version=" $( curl --fail -sL " https://raw.githubusercontent.com/pantsbuild/pants/${sha} /src/python/pants/VERSION" ) "
349
+ pants_version=" $( curl --proto " =https" \
350
+ --tlsv1.2 \
351
+ --fail \
352
+ --silent \
353
+ --location \
354
+ " https://raw.githubusercontent.com/pantsbuild/pants/${sha} /src/python/pants/VERSION" ) "
311
355
312
356
# Construct the version as the release version from src/python/pants/VERSION, plus the string `+gitXXXXXXXX`,
313
357
# where the XXXXXXXX is the first 8 characters of the SHA.
@@ -318,17 +362,27 @@ function bootstrap_pants {
318
362
local pants_version=" $1 "
319
363
local python=" $2 "
320
364
local pants_sha=" ${3:- } "
365
+ local pants_debug=" ${4:- } "
321
366
322
- local pants_requirement= " pantsbuild.pants==${pants_version} "
367
+ local pants_requirements=( pantsbuild.pants==${pants_version} )
323
368
local maybe_find_links
324
369
if [[ -z " ${pants_sha} " ]]; then
325
370
maybe_find_links=" "
326
371
else
327
372
maybe_find_links=" --find-links=$( find_links_url " ${pants_version} " " ${pants_sha} " ) "
328
- fi
373
+ fi
374
+
375
+ local debug_suffix
376
+ if [[ -z " ${pants_debug} " ]]; then
377
+ debug_suffix=" "
378
+ else
379
+ debug_suffix=" -debug"
380
+ pants_requirements+=(debugpy==1.6.0)
381
+ fi
382
+
329
383
local python_major_minor_version
330
384
python_major_minor_version=" $( get_python_major_minor_version " ${python} " ) "
331
- local target_folder_name=" ${pants_version} _py${python_major_minor_version} "
385
+ local target_folder_name=" ${pants_version} _py${python_major_minor_version}${debug_suffix} "
332
386
local bootstrapped=" ${PANTS_BOOTSTRAP} /${target_folder_name} "
333
387
334
388
if [[ ! -d " ${bootstrapped} " ]]; then
@@ -338,13 +392,15 @@ function bootstrap_pants {
338
392
staging_dir=$( tempdir " ${PANTS_BOOTSTRAP} " )
339
393
local virtualenv_path
340
394
virtualenv_path=" $( bootstrap_virtualenv " ${python} " ) " || exit 1
341
- green " Installing ${pants_requirement } into a virtual environment at ${bootstrapped} "
395
+ green " Installing ${pants_requirements[@] } into a virtual environment at ${bootstrapped} "
342
396
(
343
- scrub_PEX_env_vars
397
+ scrub_env_vars
344
398
# shellcheck disable=SC2086
345
- " ${python} " " ${virtualenv_path} " --no-download " ${staging_dir} /install" && \
346
- " ${staging_dir} /install/bin/pip" install -U pip && \
347
- " ${staging_dir} /install/bin/pip" install ${maybe_find_links} --progress-bar off " ${pants_requirement} "
399
+ " ${python} " " ${virtualenv_path} " --quiet --no-download " ${staging_dir} /install" && \
400
+ # Grab the latest pip, but don't advance setuptools past 58 which drops support for the
401
+ # `setup` kwarg `use_2to3` which Pants 1.x sdist dependencies (pystache) use.
402
+ " ${staging_dir} /install/bin/pip" install --quiet -U pip " setuptools<58" && \
403
+ " ${staging_dir} /install/bin/pip" install ${maybe_find_links} --quiet --progress-bar off " ${pants_requirements[@]} "
348
404
) && \
349
405
ln -s " ${staging_dir} /install" " ${staging_dir} /${target_folder_name} " && \
350
406
mv " ${staging_dir} /${target_folder_name} " " ${bootstrapped} " && \
@@ -354,19 +410,101 @@ function bootstrap_pants {
354
410
echo " ${bootstrapped} "
355
411
}
356
412
413
+ function run_bootstrap_tools {
414
+ # functionality for introspecting the bootstrapping process, without actually doing it
415
+ if [[ " ${PANTS_BOOTSTRAP_TOOLS} " -gt " ${SCRIPT_VERSION} " ]]; then
416
+ die " $0 script (bootstrap version ${SCRIPT_VERSION} ) is too old for this invocation (with PANTS_BOOTSTRAP_TOOLS=${PANTS_BOOTSTRAP_TOOLS} ).
417
+ Please update it by following ${INSTALL_URL} "
418
+ fi
419
+
420
+ case " ${1:- } " in
421
+ bootstrap-cache-key)
422
+ local pants_version=$( determine_pants_version)
423
+ local python=" $( determine_python_exe " ${pants_version} " ) "
424
+ # the python above may be a shim (e.g. pyenv or homebrew), so let's get an estimate of the
425
+ # actual path, as will be symlinked in the virtualenv. (NB. virtualenv does more complicated
426
+ # things, but we at least emulate the symlink-resolution that it does.)
427
+ local python_executable_path=" $( " ${python} " -c ' import os, sys; print(os.path.realpath(sys.executable))' ) "
428
+
429
+ local requirements_file=" $( mktemp) "
430
+ echo " ${VIRTUALENV_REQUIREMENTS} " > " ${requirements_file} "
431
+ local virtualenv_requirements_sha256=" $( compute_sha256 " ${python} " " ${requirements_file} " ) "
432
+ rm " ${requirements_file} "
433
+
434
+ local parts=(
435
+ " os_name=$( uname -s) "
436
+ " arch=$( uname -m) "
437
+ " python_path=${python} "
438
+ " python_executable_path=${python_executable_path} "
439
+ # the full interpreter information, for maximum compatibility
440
+ " python_version=$( " $python " --version) "
441
+ " pex_version=${_PEX_VERSION} "
442
+ " virtualenv_requirements_sha256=${virtualenv_requirements_sha256} "
443
+ " pants_version=${pants_version} "
444
+ )
445
+ echo " ${parts[*]} "
446
+ ;;
447
+ bootstrap-version)
448
+ echo " ${SCRIPT_VERSION} "
449
+ ;;
450
+ help|" " )
451
+ cat << EOF
452
+ Usage: PANTS_BOOTSTRAP_TOOLS=1 $0 ...
453
+
454
+ Subcommands:
455
+ bootstrap-cache-key
456
+ Print an opaque that can be used as a key for accurate and safe caching of
457
+ the pants bootstrap directories.
458
+
459
+ (Added in bootstrap version 1.)
460
+
461
+ bootstrap-version
462
+ Print a version number for the bootstrap script itself.
463
+
464
+ Distributed scripts (such as reusable CI formulae) that use these bootstrap
465
+ tools should set PANTS_BOOTSTRAP_TOOLS to the minimum script version for the
466
+ features they require. For example, if 'some-tool' was added in version 123:
467
+
468
+ PANTS_BOOTSTRAP_TOOLS=123 ./pants some-tool
469
+
470
+ (Added in bootstrap version 1.)
471
+ EOF
472
+ ;;
473
+ * )
474
+ die " Unknown subcommand for bootstrap tools: $1 . Do you mean to run without PANTS_BOOTSTRAP_TOOLS=1? Or, update this script ($INSTALL_URL )?"
475
+ esac
476
+ }
477
+
478
+ if [[ " ${PANTS_BOOTSTRAP_TOOLS:- } " -gt 0 ]]; then
479
+ run_bootstrap_tools " $@ "
480
+ exit 0
481
+ fi
482
+
357
483
# Ensure we operate from the context of the ./pants buildroot.
358
484
cd " $( cd " $( dirname " ${BASH_SOURCE[0]} " ) " && pwd -P) "
359
485
pants_version=" $( determine_pants_version) "
360
486
python=" $( determine_python_exe " ${pants_version} " ) "
361
- pants_dir=" $( bootstrap_pants " ${pants_version} " " ${python} " " ${PANTS_SHA:- } " ) " || exit 1
487
+ pants_dir=" $( bootstrap_pants " ${pants_version} " " ${python} " " ${PANTS_SHA:- } " " ${PANTS_DEBUG :- } " ) " || exit 1
362
488
363
489
pants_python=" ${pants_dir} /bin/python"
364
- pants_binary=" ${pants_dir} /bin/pants"
490
+ pants_binary=( ${pants_dir} /bin/pants)
365
491
pants_extra_args=" "
366
492
if [[ -n " ${PANTS_SHA:- } " ]]; then
367
493
pants_extra_args=" ${pants_extra_args} --python-repos-repos=$( find_links_url " $pants_version " " $PANTS_SHA " ) "
368
494
fi
369
495
496
+ pants_debug_args=()
497
+ if [ -n " ${PANTS_DEBUG:- } " ]; then
498
+ if [[ " $* " != * " --no-pantsd" * ]]; then
499
+ echo " Error! Must pass '--no-pantsd' when using PANTS_DEBUG"
500
+ exit 1
501
+ fi
502
+ # NB: We can't invoke `-m debugpy` as that'll prepend CWD to sys.path which might have unintended side-effects.
503
+ # `-c` also prepends, but we strip that ourselves.
504
+ pants_binary=(-c " __import__(\" sys\" ).path.pop(0);__import__(\" debugpy.server.cli\" ).server.cli.main()" --listen 127.0.0.1:5678 --wait-for-client " ${pants_binary[@]} " )
505
+ echo " Will launch debugpy server at '127.0.0.1:5678' waiting for client connection."
506
+ fi
507
+
370
508
# shellcheck disable=SC2086
371
- exec " ${pants_python} " " ${pants_binary} " ${pants_extra_args} \
509
+ exec " ${pants_python} " " ${pants_binary[@] } " ${pants_extra_args} \
372
510
--pants-bin-name=" ${PANTS_BIN_NAME} " --pants-version=${pants_version} " $@ "
0 commit comments