%global upstream_name %{name} # Pinned: a benchmark whose result depends on what a mirror served that day is not # comparable between machines, and nothing here downloads at run time. %global clpeak_version 2.1.4 # One interpreter per release, supported for the rest of that release's lifecycle: # el8 python3.12 (AppStream; the platform 3.6 is below this suite's floor), el9 python3 # (3.9, the language floor), el10 python3 (3.12). %if 0%{?rhel} == 8 %global almacert_python_pkg python3.12 %else %global almacert_python_pkg python3 %endif %global almacert_python %{_bindir}/%{almacert_python_pkg} %global almacert_home %{_datadir}/%{name} # This package is byte-compiled by hand in %%install with the interpreter above. The # automatic pass must not also compile it with a different one: on el8 that is python3.6 # against 3.9+ syntax. %global _python_bytecompile_extra 0 %global __brp_python_bytecompile %{nil} Name: alma-cert Version: 0.1.0 Release: 50%{?dist} Summary: AlmaLinux hardware certification suite License: MIT URL: https://github.com/AlmaLinux/%{upstream_name} Source0: %{url}/archive/v%{version}/%{upstream_name}-%{version}.tar.xz Source1: https://github.com/krrishnarraj/clpeak/archive/%{clpeak_version}/clpeak-%{clpeak_version}.tar.gz BuildArch: noarch BuildRequires: %{almacert_python_pkg} BuildRequires: python3-rpm-macros Requires: %{almacert_python_pkg} %if 0%{?rhel} != 8 Requires: python3 >= 3.9 %endif # Result bundles are .tar.zst. Requires: zstd # clpeak's source ships in this package and is built on the machine under test. Provides: bundled(clpeak) = %{clpeak_version} # Collection stage. Requires: dmidecode Requires: pciutils Requires: usbutils Requires: util-linux Requires: ethtool Requires: smartmontools Requires: nvme-cli %description alma-cert runs three kinds of certification runs on AlmaLinux systems: hardware inventory collection, functional validation tests, and benchmarks. Results are written as a versioned JSON report plus raw artifacts, bundled into a tarball that can be submitted to the AlmaLinux certification web application (Lumina) online or uploaded manually offline. %package tui Summary: Rich full-screen (Textual) interface for %{name} Requires: %{name} = %{version}-%{release} Requires: %{almacert_python_pkg} # Vendored under almacert_tui/_vendor because Textual is not packaged across all EPEL # releases this suite targets. Regenerate the tree and this block with # packaging/vendor/update_vendor.py, which prints these Provides and the License. License: MIT AND PSF-2.0 Provides: bundled(python3dist(textual)) = 8.2.8 Provides: bundled(python3dist(rich)) = 15.0.0 Provides: bundled(python3dist(markdown-it-py)) = 3.0.0 Provides: bundled(python3dist(mdurl)) = 0.1.2 Provides: bundled(python3dist(mdit-py-plugins)) = 0.4.2 Provides: bundled(python3dist(linkify-it-py)) = 2.0.3 Provides: bundled(python3dist(uc-micro-py)) = 1.0.3 Provides: bundled(python3dist(platformdirs)) = 4.4.0 Provides: bundled(python3dist(typing-extensions)) = 4.16.0 %description tui An optional full-screen, mouse-driven interface for %{name}, built on Textual. It collects the run choices, prints the command they add up to, and hands off to the same commands as the CLI, with a richer display that also works well over SSH. The base package has no full-screen interface of its own; installing this adds `alma-cert tui`. Textual and its dependencies are bundled because they are not available as packages on every supported EPEL release. %prep %autosetup -n %{upstream_name}-%{version} # Source1 is the only supplier of the clpeak tarball; a stale one carried in the source # archive would ship alongside it. rm -f almacert/data/clpeak-*.tar.gz find almacert almacert_tui -name __pycache__ -type d -prune -exec rm -rf {} + 2>/dev/null || : %build %install install -d %{buildroot}%{almacert_home} cp -a almacert %{buildroot}%{almacert_home}/ # Traces a stored result back to the suite build that measured it. echo "%{version}-%{release}" > %{buildroot}%{almacert_home}/almacert/data/BUILDINFO install -p -m 0644 %{SOURCE1} \ %{buildroot}%{almacert_home}/almacert/data/clpeak-%{clpeak_version}.tar.gz # Installed privately here rather than into %%{python3_sitelib} by the pyproject macros, # because el9 cannot use them: this project's pyproject.toml is PEP 621, which needs # setuptools 61+ to read the [project] table, and el9 ships 53.0.0 for python3.9. # Pointing the macros at el9's python3.12 stack instead would package the suite for an # interpreter it is not meant to use there. One install layout on every release is worth # more than the macros on two of them. Undone only by setuptools 61+ for el9's python3.9. %py_byte_compile %{almacert_python} %{buildroot}%{almacert_home}/almacert # A sibling of almacert, not a submodule, so the base package stays stdlib-only. The # byte-compile is allowed to fail: an optional upstream module may use newer-than-floor # syntax and is never imported on el9. %%check is the real gate. cp -a almacert_tui %{buildroot}%{almacert_home}/ %py_byte_compile %{almacert_python} %{buildroot}%{almacert_home}/almacert_tui || : install -d %{buildroot}%{_bindir} # A launcher rather than a console script, because this package's interpreter is not the # default python3 on every supported release. -I (not -P, which does less and does not # exist before 3.11) keeps the working directory, PYTHONPATH, and user site off sys.path # for a tool that runs as root. cat > %{buildroot}%{_bindir}/%{name} <&2 exit 1 } done # Not the unit tests: pytest is not packaged for el8's python3.12 and a build must not # fetch it. This catches a module that will not import on the interpreter shipped against. %{almacert_python} -I -c 'import importlib, pkgutil, sys; \ sys.path.insert(0, "%{buildroot}%{almacert_home}"); \ import almacert; \ [importlib.import_module(module.name) \ for module in pkgutil.walk_packages(almacert.__path__, "almacert.")]' sh -n %{buildroot}%{_bindir}/%{name} grep -q -- ' -I -c ' %{buildroot}%{_bindir}/%{name} %{almacert_python} -I -c 'import sys; \ sys.path.insert(0, "%{buildroot}%{almacert_home}"); \ from almacert.cli import main; \ sys.exit(main(["--help"]))' >/dev/null # The vendored stack must import on this interpreter, and the modules that reach for # pygments must resolve to the in-tree shim rather than a real pygments on the builder. %{almacert_python} -I -c 'import sys; \ sys.path.insert(0, "%{buildroot}%{almacert_home}"); \ import almacert_tui, almacert_tui.app; \ import pygments; \ assert getattr(pygments, "__vendored_stub__", False), "not the pygments shim"; \ import textual.app, rich.traceback, textual.highlight; \ print("alma-cert-tui import check OK")' %files %license LICENSE %doc README.md docs/ %{_bindir}/%{name} %{_mandir}/man1/%{name}.1* # The .c and .cu files here are probe sources compiled on the machine under test, not # development files; rpmlint's devel-file-in-non-devel-package does not apply. # # Two entries rather than %%{almacert_home}/ so this package and -tui do not both claim # the same files. %dir %{almacert_home} %{almacert_home}/almacert/ %config(noreplace) %{_sysconfdir}/%{name}/%{name}.conf # 0750 deliberately: a run directory holds a full hardware inventory, including serial # numbers and DMI UUIDs, and reports for machines nobody has announced yet. %dir %attr(0750,root,root) %{_sharedstatedir}/%{name} %dir %attr(0750,root,root) %{_sharedstatedir}/%{name}/runs %files tui # Bundled dependencies' license texts ship in the tree under _vendor/licenses//. %license LICENSE %{almacert_home}/almacert_tui/ %changelog * Fri Sep 11 2026 Jonathan Wright - 0.1.0-50 - rebuilt * Fri Sep 11 2026 Jonathan Wright - 0.1.0-49 - rebuilt * Fri Sep 11 2026 AlmaLinux Certification SIG - 0.1.0-48 - Update bundled clpeak to 2.1.4 * Mon Jul 27 2026 AlmaLinux Certification SIG - 0.1.0-47 - Initial package: rewritten Python suite replacing the Ansible prototype