Publish complete signed module catalogs
This commit is contained in:
@@ -21,6 +21,10 @@ GIT_REQUIREMENT = re.compile(
|
||||
r"(?P<version>[A-Za-z0-9._+!-]+))$"
|
||||
)
|
||||
LOCAL_CORE = re.compile(r"^(?:-e\s+)?\.\./govoplan-core(?:\[(?P<extras>[^]]+)\])?$")
|
||||
EXACT_PACKAGE = re.compile(
|
||||
r"^(?P<package>govoplan(?:-[a-z0-9-]+)?)(?:\[(?P<extras>[^]]+)\])?=="
|
||||
r"(?P<version>[A-Za-z0-9._+!-]+)$"
|
||||
)
|
||||
|
||||
|
||||
class PackageSetError(ValueError):
|
||||
@@ -38,6 +42,17 @@ def build_parser() -> argparse.ArgumentParser:
|
||||
type=Path,
|
||||
default=META_ROOT / "requirements-release.txt",
|
||||
)
|
||||
parser.add_argument(
|
||||
"--profile",
|
||||
choices=("base", "full"),
|
||||
default="base",
|
||||
help="Base runtime roots or every package selected by govoplan[full].",
|
||||
)
|
||||
parser.add_argument(
|
||||
"--meta-package",
|
||||
type=Path,
|
||||
default=META_ROOT / "packages" / "govoplan-meta" / "pyproject.toml",
|
||||
)
|
||||
parser.add_argument("--workspace", type=Path, default=META_ROOT.parent)
|
||||
parser.add_argument("--output", type=Path, required=True)
|
||||
return parser
|
||||
@@ -79,11 +94,46 @@ def parse_release_requirements(path: Path, *, core_version: str) -> tuple[dict[s
|
||||
return tuple(values)
|
||||
|
||||
|
||||
def parse_meta_package(path: Path, *, core_version: str) -> tuple[dict[str, object], ...]:
|
||||
project = tomllib.loads(path.read_text(encoding="utf-8")).get("project")
|
||||
if not isinstance(project, dict):
|
||||
raise PackageSetError("developer meta-package has no [project] table")
|
||||
if str(project.get("name") or "") != "govoplan":
|
||||
raise PackageSetError("developer meta-package has an unexpected project name")
|
||||
if str(project.get("version") or "").removeprefix("v") != core_version.removeprefix("v"):
|
||||
raise PackageSetError("developer meta-package version does not match Core")
|
||||
optional = project.get("optional-dependencies")
|
||||
full = optional.get("full") if isinstance(optional, dict) else None
|
||||
dependencies = project.get("dependencies")
|
||||
if not isinstance(dependencies, list) or not isinstance(full, list):
|
||||
raise PackageSetError("developer meta-package must declare dependencies and the full extra")
|
||||
values: list[dict[str, object]] = []
|
||||
for raw in (*dependencies, *full):
|
||||
if not isinstance(raw, str) or (match := EXACT_PACKAGE.fullmatch(raw.strip())) is None:
|
||||
raise PackageSetError(f"developer meta-package requirement is not exact: {raw!r}")
|
||||
package = match.group("package")
|
||||
repository = "govoplan-core" if package == "govoplan-core" else package
|
||||
values.append(
|
||||
{
|
||||
"name": package,
|
||||
"version": match.group("version"),
|
||||
"repository": repository,
|
||||
"extras": _extras(match.group("extras")),
|
||||
}
|
||||
)
|
||||
names = [str(item["name"]) for item in values]
|
||||
if names.count("govoplan-core") != 1 or len(names) != len(set(names)):
|
||||
raise PackageSetError("developer meta-package must contain one Core and unique packages")
|
||||
return tuple(values)
|
||||
|
||||
|
||||
def generate_package_set(
|
||||
*,
|
||||
core_version: str,
|
||||
requirements: Path,
|
||||
workspace: Path,
|
||||
profile: str = "base",
|
||||
meta_package: Path | None = None,
|
||||
) -> dict[str, object]:
|
||||
core_version = core_version.removeprefix("v")
|
||||
if VERSION.fullmatch(core_version) is None:
|
||||
@@ -91,7 +141,17 @@ def generate_package_set(
|
||||
python_packages: list[dict[str, object]] = []
|
||||
webui_packages: list[dict[str, object]] = []
|
||||
seen_webui: set[str] = set()
|
||||
for requirement in parse_release_requirements(requirements, core_version=core_version):
|
||||
if profile not in {"base", "full"}:
|
||||
raise PackageSetError(f"unsupported release profile: {profile}")
|
||||
selected = (
|
||||
parse_meta_package(
|
||||
meta_package or META_ROOT / "packages" / "govoplan-meta" / "pyproject.toml",
|
||||
core_version=core_version,
|
||||
)
|
||||
if profile == "full"
|
||||
else parse_release_requirements(requirements, core_version=core_version)
|
||||
)
|
||||
for requirement in selected:
|
||||
repository = workspace / str(requirement["repository"])
|
||||
tag = f"v{requirement['version']}"
|
||||
if not (repository / ".git").is_dir():
|
||||
@@ -134,6 +194,7 @@ def generate_package_set(
|
||||
payload: dict[str, object] = {
|
||||
"schema_version": "1",
|
||||
"release_version": core_version,
|
||||
"profile": profile,
|
||||
"registries": {
|
||||
"python": "https://git.add-ideas.de/api/packages/GovOPlaN/pypi/simple",
|
||||
"npm": "https://git.add-ideas.de/api/packages/GovOPlaN/npm/",
|
||||
@@ -181,6 +242,8 @@ def main() -> int:
|
||||
core_version=version,
|
||||
requirements=args.requirements.expanduser().resolve(),
|
||||
workspace=workspace,
|
||||
profile=args.profile,
|
||||
meta_package=args.meta_package.expanduser().resolve(),
|
||||
)
|
||||
except (PackageSetError, OSError, ValueError, subprocess.CalledProcessError) as exc:
|
||||
print(f"error: {exc}")
|
||||
|
||||
Reference in New Issue
Block a user