Handle request for partial git tags

This commit is contained in:
Simon Li
2022-06-16 23:32:35 +01:00
parent 8324e49ed9
commit 3340ac8417
2 changed files with 199 additions and 4 deletions

View File

@@ -42,6 +42,7 @@ from argparse import ArgumentParser
import os
from http.server import SimpleHTTPRequestHandler, HTTPServer
import multiprocessing
import re
import subprocess
import sys
import logging
@@ -166,9 +167,11 @@ def run_subprocess(cmd, *args, **kwargs):
command=printable_command, code=proc.returncode
)
)
output = proc.stdout.decode()
# This produces multi line log output, unfortunately. Not sure how to fix.
# For now, prioritizing human readability over machine readability.
logger.debug(proc.stdout.decode())
logger.debug(output)
return output
def ensure_host_system_can_install_tljh():
@@ -251,6 +254,73 @@ class ProgressPageRequestHandler(SimpleHTTPRequestHandler):
SimpleHTTPRequestHandler.send_error(self, code=403)
def _find_matching_version(all_versions, requested):
"""
Find the latest version that is less than or equal to requested.
all_versions must be int-tuples.
requested must be an int-tuple or "latest"
Returns None if no version is found.
"""
sorted_versions = sorted(all_versions, reverse=True)
if requested == "latest":
return sorted_versions[0]
components = len(requested)
for v in sorted_versions:
if v[:components] == requested:
return v
return None
def _resolve_git_version(version):
"""
Resolve the version argument to a git ref using git ls-remote
- If version looks like MAJOR.MINOR.PATCH or a partial tag then fetch all tags
and return the most latest tag matching MAJOR.MINOR.PATCH
(e.g. version=0.1 -> 0.1.PATCH). This should ignore dev tags
- If version='latest' then return the latest release tag
- Otherwise assume version is a branch or hash and return it without checking
"""
if version != "latest" and not re.match(r"\d+(\.\d+)?(\.\d+)?$", version):
return version
all_versions = set()
out = run_subprocess(
[
"git",
"ls-remote",
"--tags",
"--refs",
"https://github.com/jupyterhub/the-littlest-jupyterhub.git",
]
)
for line in out.splitlines():
m = re.match(r"(?P<sha>[a-f0-9]+)\s+refs/tags/(?P<tag>[\S]+)$", line)
if not m:
raise Exception("Unexpected git ls-remote output: {}".format(line))
tag = m.group("tag")
if tag == version:
return tag
if re.match(r"\d+\.\d+\.\d+$", tag):
all_versions.add(tuple(int(v) for v in tag.split(".")))
if not all_versions:
raise Exception("No MAJOR.MINOR.PATCH git tags found")
if version == "latest":
requested = "latest"
else:
requested = tuple(int(v) for v in version.split("."))
found = _find_matching_version(all_versions, requested)
if not found:
raise Exception(
"No version matching {} found {}".format(version, sorted(all_versions))
)
return ".".join(str(f) for f in found)
def main():
"""
This bootstrap script intercepts some command line flags, everything else is
@@ -265,7 +335,7 @@ def main():
parser = ArgumentParser()
parser.add_argument("--show-progress-page", action="store_true")
parser.add_argument(
"--version", default="main", help="TLJH version (Git reference)"
"--version", default="main", help="TLJH version or Git reference"
)
args, tljh_installer_flags = parser.parse_known_args()
@@ -378,11 +448,13 @@ def main():
if os.environ.get("TLJH_BOOTSTRAP_DEV", "no") == "yes":
logger.info("Selected TLJH_BOOTSTRAP_DEV=yes...")
tljh_install_cmd.append("--editable")
version = _resolve_git_version(args.version)
tljh_install_cmd.append(
os.environ.get(
"TLJH_BOOTSTRAP_PIP_SPEC",
"git+https://github.com/jupyterhub/the-littlest-jupyterhub.git@{version}".format(
version=args.version
"git+https://github.com/jupyterhub/the-littlest-jupyterhub.git@{}".format(
version
),
)
)