pw_env_setup: Add compatibility.json

Add compatibility.json file to allow testing Pigweed against older
versions of tools. For now we only support one old version of any
specific tool, and each old version is tested alongside all other old
versions.

To use, set
PW_CIPD_PACKAGE_FILES="$PW_ROOT/pw_env_setup/py/pw_env_setup/cipd_setup/compatibility.json"
and then run '. ./bootstrap.sh'.

Change-Id: I96c37a6e0f48a93dd955d4144ad32e01a55627e4
Bug: 226
Reviewed-on: https://pigweed-review.googlesource.com/c/pigweed/pigweed/+/14600
Reviewed-by: Keir Mierle <keir@google.com>
Commit-Queue: Rob Mohr <mohrr@google.com>
diff --git a/bootstrap.bat b/bootstrap.bat
index ed38285..124c1ec 100644
--- a/bootstrap.bat
+++ b/bootstrap.bat
@@ -67,7 +67,7 @@
 set _PW_OLD_VIRTUALENV_SETUP_PY_ROOTS=%PW_VIRTUALENV_SETUP_PY_ROOTS%
 set _PW_OLD_CARGO_PACKAGE_FILES=%PW_CARGO_PACKAGE_FILES%
 
-set PW_CIPD_PACKAGE_FILES=%PW_ROOT%\pw_env_setup\py\pw_env_setup\cipd_setup\*.json;%PW_CIPD_PACKAGE_FILES%
+set PW_CIPD_PACKAGE_FILES=%PW_ROOT%\pw_env_setup\py\pw_env_setup\cipd_setup\pigweed.json;%PW_ROOT%\pw_env_setup\py\pw_env_setup\cipd_setup\luci.json;%PW_CIPD_PACKAGE_FILES%
 set PW_VIRTUALENV_REQUIREMENTS=%PW_ROOT%\pw_env_setup\py\pw_env_setup\virtualenv_setup\requirements.txt;%PW_VIRTUALENV_REQUIREMENTS%
 set PW_VIRTUALENV_SETUP_PY_ROOTS=%PW_ROOT%;%PW_VIRTUALENV_SETUP_PY_ROOTS%
 set PW_CARGO_PACKAGE_FILES=%PW_ROOT%\pw_env_setup\py\pw_env_setup\cargo_setup\packages.txt;%PW_CARGO_PACKAGE_FILES%
diff --git a/bootstrap.sh b/bootstrap.sh
index 761dcae..cf56121 100644
--- a/bootstrap.sh
+++ b/bootstrap.sh
@@ -203,7 +203,7 @@
   fi
 
   _PW_OLD_CIPD_PACKAGE_FILES="$PW_CIPD_PACKAGE_FILES"
-  PW_CIPD_PACKAGE_FILES="$PW_ROOT/pw_env_setup/py/pw_env_setup/cipd_setup/*.json:$PW_CIPD_PACKAGE_FILES"
+  PW_CIPD_PACKAGE_FILES="$PW_ROOT/pw_env_setup/py/pw_env_setup/cipd_setup/pigweed.json:$PW_ROOT/pw_env_setup/py/pw_env_setup/cipd_setup/luci.json:$PW_CIPD_PACKAGE_FILES"
   export PW_CIPD_PACKAGE_FILES
 
   _PW_OLD_VIRTUALENV_REQUIREMENTS="$PW_VIRTUALENV_REQUIREMENTS"
diff --git a/pw_doctor/py/pw_doctor/doctor.py b/pw_doctor/py/pw_doctor/doctor.py
index 74a4c87..42113be 100755
--- a/pw_doctor/py/pw_doctor/doctor.py
+++ b/pw_doctor/py/pw_doctor/doctor.py
@@ -164,12 +164,16 @@
     """Check the Python version is correct."""
     actual = sys.version_info
     expected = (3, 8)
-    if actual[0:2] < expected or actual[0] != expected[0]:
-        ctx.error('Python %d.%d.x required, got Python %d.%d.%d', *expected,
-                  *actual[0:3])
-    elif actual[0:2] > expected:
-        ctx.warning('Python %d.%d.x required, got Python %d.%d.%d', *expected,
-                    *actual[0:3])
+    if (actual[0:2] < expected or actual[0] != expected[0]
+            or actual[0:2] > expected):
+        # If we get the wrong version but it still came from CIPD print a
+        # warning but give it a pass.
+        if 'chromium' in sys.version:
+            ctx.warning('Python %d.%d.x expected, got Python %d.%d.%d',
+                        *expected, *actual[0:3])
+        else:
+            ctx.error('Python %d.%d.x required, got Python %d.%d.%d',
+                      *expected, *actual[0:3])
 
 
 @register_into(CHECKS)
diff --git a/pw_env_setup/py/pw_env_setup/cipd_setup/compatibility.json b/pw_env_setup/py/pw_env_setup/cipd_setup/compatibility.json
new file mode 100644
index 0000000..9132342
--- /dev/null
+++ b/pw_env_setup/py/pw_env_setup/cipd_setup/compatibility.json
@@ -0,0 +1,8 @@
+[
+  {
+    "path": "infra/3pp/tools/cpython3/${os}-${arch=amd64}",
+    "tags": [
+      "version:3.7.7.chromium.10"
+    ]
+  }
+]
diff --git a/pw_env_setup/py/pw_env_setup/virtualenv_setup/install.py b/pw_env_setup/py/pw_env_setup/virtualenv_setup/install.py
index cd881bd..f0e78c0 100644
--- a/pw_env_setup/py/pw_env_setup/virtualenv_setup/install.py
+++ b/pw_env_setup/py/pw_env_setup/virtualenv_setup/install.py
@@ -100,7 +100,8 @@
 
     version = subprocess.check_output(
         (python, '--version'), stderr=subprocess.STDOUT).strip().decode()
-    if '3.8' not in version:
+    # We expect Python 3.8, but if it came from CIPD let it pass anyway.
+    if '3.8' not in version and 'chromium' not in version:
         print('=' * 60, file=sys.stderr)
         print('Unexpected Python version:', version, file=sys.stderr)
         print('=' * 60, file=sys.stderr)