|
 |
ed28c0 |
#!/usr/bin/env python3
|
|
 |
ed28c0 |
|
|
 |
ed28c0 |
import argparse
|
|
 |
ed28c0 |
import logging
|
|
 |
ed28c0 |
import subprocess
|
|
 |
ed28c0 |
import sys
|
|
 |
ed28c0 |
from datetime import datetime
|
|
 |
ed28c0 |
from pathlib import Path
|
|
 |
ed28c0 |
from typing import Any, NoReturn, Optional, Sequence, Iterator
|
|
 |
ed28c0 |
import enum
|
|
 |
ed28c0 |
import contextlib
|
|
 |
ed28c0 |
import textwrap
|
|
 |
ed28c0 |
|
|
 |
ed28c0 |
SYSTEMD_REPO = "https://github.com/systemd/systemd"
|
|
 |
ed28c0 |
AUTHOR = "CentOS Hyperscale SIG <centos-devel@centos.org>"
|
|
 |
ed28c0 |
|
|
 |
ed28c0 |
|
|
 |
ed28c0 |
class LogFormatter(logging.Formatter):
|
|
 |
ed28c0 |
def __init__(self, fmt: Optional[str] = None, *args: Any, **kwargs: Any) -> None:
|
|
 |
ed28c0 |
fmt = fmt or "%(message)s"
|
|
 |
ed28c0 |
|
|
 |
ed28c0 |
bold = "\033[0;1;39m" if sys.stderr.isatty() else ""
|
|
 |
ed28c0 |
gray = "\x1b[38;20m" if sys.stderr.isatty() else ""
|
|
 |
ed28c0 |
red = "\033[31;1m" if sys.stderr.isatty() else ""
|
|
 |
ed28c0 |
yellow = "\033[33;1m" if sys.stderr.isatty() else ""
|
|
 |
ed28c0 |
reset = "\033[0m" if sys.stderr.isatty() else ""
|
|
 |
ed28c0 |
|
|
 |
ed28c0 |
self.formatters = {
|
|
 |
ed28c0 |
logging.DEBUG: logging.Formatter(f"‣ {gray}{fmt}{reset}"),
|
|
 |
ed28c0 |
logging.INFO: logging.Formatter(f"‣ {fmt}"),
|
|
 |
ed28c0 |
logging.WARNING: logging.Formatter(f"‣ {yellow}{fmt}{reset}"),
|
|
 |
ed28c0 |
logging.ERROR: logging.Formatter(f"‣ {red}{fmt}{reset}"),
|
|
 |
ed28c0 |
logging.CRITICAL: logging.Formatter(f"‣ {red}{bold}{fmt}{reset}"),
|
|
 |
ed28c0 |
}
|
|
 |
ed28c0 |
|
|
 |
ed28c0 |
super().__init__(fmt, *args, **kwargs)
|
|
 |
ed28c0 |
|
|
 |
ed28c0 |
def format(self, record: logging.LogRecord) -> str:
|
|
 |
ed28c0 |
return self.formatters[record.levelno].format(record)
|
|
 |
ed28c0 |
|
|
 |
ed28c0 |
|
|
 |
ed28c0 |
def run(cmd: Sequence[str], *args: Any, **kwargs: Any) -> subprocess.CompletedProcess:
|
|
 |
ed28c0 |
try:
|
|
 |
ed28c0 |
return subprocess.run(cmd, *args, **kwargs, check=True, text=True)
|
|
 |
ed28c0 |
except FileNotFoundError:
|
|
 |
ed28c0 |
die(f"{cmd[0]} not found in PATH.")
|
|
 |
ed28c0 |
except subprocess.CalledProcessError as e:
|
|
 |
ed28c0 |
logging.error(
|
|
 |
ed28c0 |
f'"{" ".join(str(s) for s in cmd)}" returned non-zero exit code {e.returncode}.'
|
|
 |
ed28c0 |
)
|
|
 |
ed28c0 |
raise e
|
|
 |
ed28c0 |
|
|
 |
ed28c0 |
|
|
 |
ed28c0 |
def die(message: str) -> NoReturn:
|
|
 |
ed28c0 |
logging.error(message)
|
|
 |
ed28c0 |
sys.exit(1)
|
|
 |
ed28c0 |
|
|
 |
ed28c0 |
|
|
 |
ed28c0 |
@contextlib.contextmanager
|
|
 |
ed28c0 |
def restore(path: Path) -> Iterator[None]:
|
|
 |
ed28c0 |
old = path.read_text()
|
|
 |
ed28c0 |
try:
|
|
 |
ed28c0 |
yield
|
|
 |
ed28c0 |
finally:
|
|
 |
ed28c0 |
path.write_text(old)
|
|
 |
ed28c0 |
|
|
 |
ed28c0 |
|
|
 |
ed28c0 |
def do_cd(args: argparse.Namespace) -> None:
|
|
 |
ed28c0 |
if not Path(".git").exists():
|
|
 |
ed28c0 |
die("The cd verb must be run from the rpm git repository")
|
|
 |
ed28c0 |
|
|
 |
ed28c0 |
logging.info("Downloading sources")
|
|
 |
ed28c0 |
run(
|
|
 |
ed28c0 |
[
|
|
 |
ed28c0 |
"spectool",
|
|
 |
ed28c0 |
"--define",
|
|
 |
ed28c0 |
f"_sourcedir {Path.cwd()}",
|
|
 |
ed28c0 |
"--define",
|
|
 |
ed28c0 |
"branch main",
|
|
 |
ed28c0 |
"--get-files",
|
|
 |
ed28c0 |
"systemd.spec",
|
|
 |
ed28c0 |
],
|
|
 |
ed28c0 |
)
|
|
 |
ed28c0 |
|
|
 |
ed28c0 |
# We can't determine the version dynamically in the spec so we retrieve it
|
|
 |
ed28c0 |
# up front and pass it in via a macro.
|
|
 |
ed28c0 |
version = run(
|
|
 |
ed28c0 |
[
|
|
 |
ed28c0 |
"tar",
|
|
 |
ed28c0 |
"--gunzip",
|
|
 |
ed28c0 |
"--extract",
|
|
 |
ed28c0 |
"--to-stdout",
|
|
 |
ed28c0 |
"--file=main.tar.gz",
|
|
 |
ed28c0 |
"systemd-main/meson.version",
|
|
 |
ed28c0 |
],
|
|
 |
ed28c0 |
stdout=subprocess.PIPE,
|
|
 |
ed28c0 |
).stdout.strip()
|
|
 |
ed28c0 |
|
|
 |
ed28c0 |
# The timestamp is to ensure the release is always monotonically increasing
|
|
 |
ed28c0 |
rpmrelease = datetime.now().strftime(r"%Y%m%d%H%M%S")
|
|
 |
ed28c0 |
|
|
 |
ed28c0 |
with restore(Path("systemd.spec")):
|
|
 |
ed28c0 |
Path("systemd.spec").write_text(
|
|
 |
ed28c0 |
textwrap.dedent(
|
|
 |
ed28c0 |
f"""\
|
|
 |
ed28c0 |
%bcond upstream 1
|
|
 |
ed28c0 |
%define version_override {version}
|
|
 |
ed28c0 |
%define release_override {rpmrelease}
|
|
 |
ed28c0 |
%define branch main
|
|
 |
ed28c0 |
"""
|
|
 |
ed28c0 |
)
|
|
 |
ed28c0 |
+ Path("systemd.spec").read_text()
|
|
 |
ed28c0 |
)
|
|
 |
ed28c0 |
|
|
 |
ed28c0 |
if args.repo == "main":
|
|
 |
ed28c0 |
root = f"centos-stream-hyperscale-{args.release}-x86_64"
|
|
 |
ed28c0 |
else:
|
|
 |
ed28c0 |
root = f"centos-stream-hyperscale-{args.repo}-{args.release}-x86_64"
|
|
 |
ed28c0 |
|
|
 |
ed28c0 |
logging.info("Building src.rpm")
|
|
 |
ed28c0 |
run(
|
|
 |
ed28c0 |
[
|
|
 |
ed28c0 |
"mock",
|
|
 |
ed28c0 |
"--root",
|
|
 |
ed28c0 |
root,
|
|
 |
ed28c0 |
"--sources=.",
|
|
 |
ed28c0 |
"--spec=systemd.spec",
|
|
 |
ed28c0 |
"--enable-network",
|
|
 |
ed28c0 |
"--define",
|
|
 |
ed28c0 |
"%_disable_source_fetch 0",
|
|
 |
ed28c0 |
"--buildsrpm",
|
|
 |
ed28c0 |
"--resultdir=.",
|
|
 |
ed28c0 |
],
|
|
 |
ed28c0 |
)
|
|
 |
ed28c0 |
|
|
 |
ed28c0 |
srcrpm = next(Path.cwd().glob("*.src.rpm"))
|
|
 |
ed28c0 |
logging.info(f"Wrote: {srcrpm}")
|
|
 |
ed28c0 |
|
|
 |
ed28c0 |
run(
|
|
 |
ed28c0 |
[
|
|
 |
ed28c0 |
"cbs",
|
|
 |
ed28c0 |
*(["--cert", args.cert] if args.cert else []),
|
|
 |
ed28c0 |
"build",
|
|
 |
ed28c0 |
"--wait",
|
|
 |
ed28c0 |
"--fail-fast",
|
|
 |
ed28c0 |
"--skip-tag",
|
|
 |
ed28c0 |
f"hyperscale{args.release}s-packages-{args.repo}-el{args.release}s",
|
|
 |
ed28c0 |
str(srcrpm),
|
|
 |
ed28c0 |
],
|
|
 |
ed28c0 |
)
|
|
 |
ed28c0 |
|
|
 |
ed28c0 |
if not args.publish:
|
|
 |
ed28c0 |
logging.info("Publishing not requested, not tagging builds in testing")
|
|
 |
ed28c0 |
return
|
|
 |
ed28c0 |
|
|
 |
ed28c0 |
prefix = "hs+fb" if args.repo == "facebook" else "hs"
|
|
 |
ed28c0 |
|
|
 |
ed28c0 |
run(
|
|
 |
ed28c0 |
[
|
|
 |
ed28c0 |
"cbs",
|
|
 |
ed28c0 |
*(["--cert", args.cert] if args.cert else []),
|
|
 |
ed28c0 |
"tag-build",
|
|
 |
ed28c0 |
f"hyperscale{args.release}s-packages-{args.repo}-testing",
|
|
 |
ed28c0 |
f"systemd-{version}-{rpmrelease}.{prefix}.el{args.release}",
|
|
 |
ed28c0 |
]
|
|
 |
ed28c0 |
)
|
|
 |
ed28c0 |
|
|
 |
ed28c0 |
|
|
 |
ed28c0 |
class Verb(enum.Enum):
|
|
 |
ed28c0 |
cd = "cd"
|
|
 |
ed28c0 |
|
|
 |
ed28c0 |
def __str__(self) -> str:
|
|
 |
ed28c0 |
return self.value
|
|
 |
ed28c0 |
|
|
 |
ed28c0 |
def run(self, args: argparse.Namespace) -> None:
|
|
 |
ed28c0 |
{Verb.cd: do_cd}[self](args)
|
|
 |
ed28c0 |
|
|
 |
ed28c0 |
|
|
 |
ed28c0 |
def main() -> None:
|
|
 |
ed28c0 |
handler = logging.StreamHandler(stream=sys.stderr)
|
|
 |
ed28c0 |
handler.setFormatter(LogFormatter())
|
|
 |
ed28c0 |
logging.getLogger().addHandler(handler)
|
|
 |
ed28c0 |
logging.getLogger().setLevel("INFO")
|
|
 |
ed28c0 |
|
|
 |
ed28c0 |
parser = argparse.ArgumentParser()
|
|
 |
ed28c0 |
|
|
 |
ed28c0 |
parser.add_argument(
|
|
 |
ed28c0 |
"--release",
|
|
 |
ed28c0 |
help="CentOS Stream release to use (e.g 9)",
|
|
 |
ed28c0 |
metavar="RELEASE",
|
|
 |
ed28c0 |
default=9,
|
|
 |
ed28c0 |
choices=[9, 10],
|
|
 |
ed28c0 |
type=int,
|
|
 |
ed28c0 |
)
|
|
 |
ed28c0 |
parser.add_argument(
|
|
 |
ed28c0 |
"--repo",
|
|
 |
ed28c0 |
help="Hyperscale repository to build against",
|
|
 |
ed28c0 |
choices=["main", "facebook"],
|
|
 |
ed28c0 |
default="main",
|
|
 |
ed28c0 |
)
|
|
 |
ed28c0 |
parser.add_argument(
|
|
 |
ed28c0 |
"--cert",
|
|
 |
ed28c0 |
help="Path to the CentOS certificate to use",
|
|
 |
ed28c0 |
metavar="PATH",
|
|
 |
ed28c0 |
type=Path,
|
|
 |
ed28c0 |
default=None,
|
|
 |
ed28c0 |
)
|
|
 |
ed28c0 |
parser.add_argument(
|
|
 |
ed28c0 |
"--publish",
|
|
 |
ed28c0 |
action="store_true",
|
|
 |
ed28c0 |
help="Publish results of operation (by default only a dry-run is done)",
|
|
 |
ed28c0 |
)
|
|
 |
ed28c0 |
parser.add_argument(
|
|
 |
ed28c0 |
"verb",
|
|
 |
ed28c0 |
type=Verb,
|
|
 |
ed28c0 |
choices=list(Verb),
|
|
 |
ed28c0 |
help=argparse.SUPPRESS,
|
|
 |
ed28c0 |
)
|
|
 |
ed28c0 |
|
|
 |
ed28c0 |
args = parser.parse_args()
|
|
 |
ed28c0 |
|
|
 |
ed28c0 |
if args.cert:
|
|
 |
ed28c0 |
args.cert = args.cert.absolute()
|
|
 |
ed28c0 |
|
|
 |
ed28c0 |
try:
|
|
 |
ed28c0 |
args.verb.run(args)
|
|
 |
ed28c0 |
except SystemExit as e:
|
|
 |
ed28c0 |
sys.exit(e.code)
|
|
 |
ed28c0 |
except KeyboardInterrupt:
|
|
 |
ed28c0 |
logging.error("Interrupted")
|
|
 |
ed28c0 |
sys.exit(1)
|
|
 |
ed28c0 |
except subprocess.CalledProcessError as e:
|
|
 |
ed28c0 |
sys.exit(e.returncode)
|
|
 |
ed28c0 |
|
|
 |
ed28c0 |
|
|
 |
ed28c0 |
if __name__ == "__main__":
|
|
 |
ed28c0 |
main()
|