forked from github.com/pypiserver
df300de33d
Adds a new helper script to determine which docker tags are needed for a given ref going through CI, and uses those tags to populate the GH actions matrix for a docker deploy step.
89 lines
2.6 KiB
Python
Executable File
89 lines
2.6 KiB
Python
Executable File
#!/usr/bin/env python3
|
|
|
|
"""Output expected docker tags to build in CI."""
|
|
|
|
import json
|
|
import typing as t
|
|
import re
|
|
from argparse import ArgumentParser, Namespace
|
|
|
|
|
|
RELEASE_RE = re.compile(r"v[0-9]+\.[0-9]+\.[0-9]+(\.post[0-9]+)?")
|
|
PRE_RELEASE_RE = re.compile(r"v[0-9]+\.[0-9]+\.[0-9]+(a|b|c|\.?dev)[0-9]+")
|
|
|
|
|
|
def parse_args() -> Namespace:
|
|
"""Parse cmdline args."""
|
|
parser = ArgumentParser()
|
|
parser.add_argument(
|
|
"ref",
|
|
help=(
|
|
"The github ref for which CI is running. This may be a full ref "
|
|
"like refs/tags/v1.2.3 or refs/heads/master, or just a tag/branch "
|
|
"name like v1.2.3 or master."
|
|
),
|
|
)
|
|
parser.add_argument(
|
|
"action",
|
|
help=("The action to perform"),
|
|
choices=("docker_tags", "pypi_release", "has_tags"),
|
|
)
|
|
return parser.parse_args()
|
|
|
|
|
|
def strip_ref_to_name(ref: str) -> str:
|
|
"""Strip a full ref to a name."""
|
|
strips = ("refs/heads/", "refs/tags/")
|
|
for strip in strips:
|
|
if ref.startswith(strip):
|
|
return ref[len(strip) :]
|
|
return ref
|
|
|
|
|
|
def name_to_array(name: str) -> t.Tuple[str, ...]:
|
|
"""Convert a ref name to an array of tags to build."""
|
|
tags: t.Dict[str, t.Callable[[str], bool]] = {
|
|
# unstable for any master build
|
|
"unstable": lambda i: i == "master",
|
|
# latest goes for full releases
|
|
"latest": lambda i: RELEASE_RE.fullmatch(i) is not None,
|
|
# the tag itself for any release or pre-release tag
|
|
name: lambda i: (
|
|
RELEASE_RE.fullmatch(i) is not None
|
|
or PRE_RELEASE_RE.fullmatch(i) is not None
|
|
),
|
|
}
|
|
return tuple(tag for tag, test in tags.items() if test(name))
|
|
|
|
|
|
def ref_to_json(ref: str) -> str:
|
|
"""Convert a ref to a JSON array and return it as a string."""
|
|
array = name_to_array(strip_ref_to_name(ref))
|
|
return json.dumps(array)
|
|
|
|
|
|
def should_deploy_to_pypi(ref: str) -> str:
|
|
"""Return a JSON bool indicating whether we should deploy to PyPI."""
|
|
name = strip_ref_to_name(ref)
|
|
return json.dumps(
|
|
RELEASE_RE.fullmatch(name) is not None
|
|
or PRE_RELEASE_RE.fullmatch(name) is not None
|
|
)
|
|
|
|
|
|
def main() -> None:
|
|
"""Parse args and print the JSON array."""
|
|
args = parse_args()
|
|
action_switch: t.Dict[str, t.Callable[[], None]] = {
|
|
"docker_tags": lambda: print(ref_to_json(args.ref)),
|
|
"has_tags": lambda: print(
|
|
json.dumps(len(name_to_array(strip_ref_to_name(args.ref))) > 0)
|
|
),
|
|
"pypi_release": lambda: print(should_deploy_to_pypi(args.ref)),
|
|
}
|
|
action_switch[args.action]()
|
|
|
|
|
|
if __name__ == "__main__":
|
|
main()
|