Files
computer-playbook/utils/github/variant/label.py
T

95 lines
3.2 KiB
Python
Raw Blame History

This file contains invisible Unicode characters
This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
from __future__ import annotations
import re
from typing import TYPE_CHECKING, NamedTuple
from utils.github.variant.pools import DISTROS, FILESYSTEMS
from utils.roles.display import VARIANT_SEPARATOR
from utils.symbol_glossary import to_emoji, to_word
if TYPE_CHECKING:
from collections.abc import Sequence
MODES = ("compose", "swarm", "host")
LOCAL_GLYPH = to_emoji("test_host")
_AXIS_GLYPHS = (
"".join(
to_emoji(word)
for word in ("tor", "clearnet", "vpn", "direct", "priority", "instructions")
)
+ LOCAL_GLYPH
)
def _alternation(words: Sequence[str]) -> str:
"""A regex alternation over the glyphs of *words*."""
return "|".join(re.escape(to_emoji(word)) for word in words)
LABEL_RE = re.compile(
r"^.*(?P<mode>" + _alternation(MODES) + r")️?"
r"(?P<tor>" + re.escape(to_emoji("tor")) + r")?"
r"(?:" + re.escape(to_emoji("clearnet")) + r"|" + re.escape(LOCAL_GLYPH) + r")?️?"
r"(?P<vpn>" + re.escape(to_emoji("vpn")) + r")?️?"
r"(?:" + re.escape(to_emoji("direct")) + r")?️?"
r"(?P<distro>" + _alternation(DISTROS) + r")?️?"
r"(?P<filesystem>" + _alternation(FILESYSTEMS) + r")?️?"
r"[" + re.escape(_AXIS_GLYPHS) + r"️\s]*"
r"(?P<name>.+?)"
r"(?:" + re.escape(VARIANT_SEPARATOR) + r"(?P<variant>[0-9,]+))?"
r"[" + re.escape(_AXIS_GLYPHS) + r"️\s]*$"
)
"""The leading ``.*`` is greedy on purpose: it anchors on the LAST mode glyph.
A reusable-workflow caller path can carry a mode glyph of its own (``z / 💻
Host / 💻 sys-front-proxy``), and matching the first one would swallow the
caller name into the role."""
class Label(NamedTuple):
"""One deploy job title, taken apart."""
mode: str
name: str
variant: str
tor: bool
distro: str = ""
filesystem: str = ""
vpn: bool = False
def parse_label(name: str) -> Label | None:
"""Take a deploy job title apart.
The inverse of what :func:`assign` builds, kept next to it so the two
cannot drift: consumers that hand-rolled their own regex over raw role
ids silently matched nothing once job titles carried display names, and
every failure went unreported.
Args:
name: the job title, with or without a reusable-workflow caller path
in front of it.
Returns:
``None`` when the title carries no deploy row. ``name`` is the display
name, returned unresolved -- callers decode it through
``utils.roles.display``, which is what knows the role tree. ``tor``,
``distro`` and ``filesystem`` matter because a priority role runs the
same mode and variant several times over, and only the glyphs tell
those jobs apart -- a retrigger built from the title alone would
otherwise replay a different combination than the one that failed.
"""
match = LABEL_RE.match(name.strip())
if match is None:
return None
return Label(
to_word(match.group("mode")),
match.group("name").strip(),
match.group("variant") or "",
match.group("tor") is not None,
to_word(match.group("distro") or ""),
to_word(match.group("filesystem") or ""),
match.group("vpn") is not None,
)