pgAdmin 4 for UBI-9: SP1 node_modules tooling + SP2 local-npm-registry + SP3 Python 3.12 stack - #12
Open
rjd15372 wants to merge 51 commits into
Open
pgAdmin 4 for UBI-9: SP1 node_modules tooling + SP2 local-npm-registry + SP3 Python 3.12 stack#12rjd15372 wants to merge 51 commits into
rjd15372 wants to merge 51 commits into
Conversation
OBS Build Check — ❌ Sync failedThe OBS sync step failed. See the workflow run for details.
|
rjd15372
added a commit
that referenced
this pull request
Aug 26, 2026
…rendered macros Two --branch-from decision fixes (PR #12 CI analysis, 2026-08-26): 1. _content_matches_branch caught SystemExit from a failed local service run and returned False ("content differs"), so a transient obs_scm clone error (curl 56 Connection reset by peer) promoted an unrelated, unchanged package. A failed run says nothing about the content: the services are now retried once (_run_services_for_check) and a second failure aborts the whole sync with the service's error. 2. _macros_changed_since compared inherited macros.yaml at file level (git diff --name-only <sha>..HEAD). Commit 146694c moved macros between staging/17/extras, staging/17 and staging/macros.yaml with identical rendered values, which flagged every ppg/staging package as "inherited macros changed" and sent ~120 of them through the service-running content check on every PR run. The check now compares the rendered values of the %!{NAME} macros the package actually references (obs/, debian/, rpm/ files) between the synced SHA (via git show) and the working tree. load_macros is split into _macros_chain_files + resolve_macros so both trees resolve through the same parser. Against the legacy production SHA 6440e48 this drops ppg/staging from 315/315 flagged packages to 4, all genuine version bumps (pg_tde x3, 19/haproxy). Tests: tests/test_content_check_retry.py, tests/test_macros_changed_since.py (real temporary git repo, no git mocking). Signed-off-by: Ricardo Dias <ricardo.dias@percona.com>
rjd15372
added a commit
that referenced
this pull request
Aug 27, 2026
Design for the ~75 python3.12-* packages percona-pgadmin4 needs on UBI-9: closure resolution, reuse policy (RHEL 9 + ppg:common:deps), dnspython bump + shared hatchling build stack in ppg:common:deps, the shared EL spec template (pyproject / setup.py / self-hosting families), inventory, verification via PR #12, risks. Signed-off-by: Ricardo Dias <ricardo.dias@percona.com>
rjd15372
added a commit
that referenced
this pull request
Aug 27, 2026
Six tasks: render the 77 python3-* package directories with a throwaway scratchpad script (embedded as appendices with its data), commit them in three bottom-up batches (ppg:common:deps backend stack + dnspython bump; pgadmin build tools + leaves; dependents), document the Python 3.12 spec template in PACKAGING_HOWTO, build everything in PR #12's OBS project with a fix loop, and record outcomes in PR #12 and the spec. Signed-off-by: Ricardo Dias <ricardo.dias@percona.com>
rjd15372
added a commit
that referenced
this pull request
Aug 28, 2026
…-9_17) Package layout and spec design for percona-pgadmin4 with -gunicorn (container runtime, systemd unit), -httpd (mod_wsgi conf + setup helper) and -doc (rst sources) subpackages; obs_scm(REL-9_17) → npm_lockfile → node_modules source chain; config_distro.py with Percona defaults and PGADMIN_CONFIG_* env overrides; the SP3 stack changes for 9.17 (libpass replaces passlib, certifi, annotated-doc, gunicorn, bumps; Authlib kept at 1.6.12); verification via PR #12 plus a container smoke test with the OBS-built RPMs. Signed-off-by: Ricardo Dias <ricardo.dias@percona.com>
rjd15372
added a commit
that referenced
this pull request
Aug 28, 2026
Bake the repo-owned npm_lockfile OBS-style service (tools/obs-services/) into ghcr.io/percona/obs-tools together with Node.js 22 + npm, cpio and obs-service-node-modules, so percona-obs can generate package-lock.json and vendor npm dependencies for packages whose upstream ships no npm lockfile (pgAdmin 4). build-obs-image.yml now also rebuilds the image when tools/obs-services/ changes. Split out of the pgadmin-sp1 branch (PR #12): the PR check runs inside obs-tools:latest, which is only rebuilt from main, so the service must land on main before PR #12 can sync. Signed-off-by: Ricardo Dias <ricardo.dias@percona.com>
Signed-off-by: Ricardo Dias <ricardo.dias@percona.com>
Signed-off-by: Ricardo Dias <ricardo.dias@percona.com>
Signed-off-by: Ricardo Dias <ricardo.dias@percona.com>
…ode_modules) Signed-off-by: Ricardo Dias <ricardo.dias@percona.com>
…ine errors Signed-off-by: Ricardo Dias <ricardo.dias@percona.com>
Signed-off-by: Ricardo Dias <ricardo.dias@percona.com>
Signed-off-by: Ricardo Dias <ricardo.dias@percona.com>
Signed-off-by: Ricardo Dias <ricardo.dias@percona.com>
…rift-tolerant artifacts Signed-off-by: Ricardo Dias <ricardo.dias@percona.com>
… a package) Signed-off-by: Ricardo Dias <ricardo.dias@percona.com>
Signed-off-by: Ricardo Dias <ricardo.dias@percona.com>
…re message The cpio extraction path had no equivalent to the tarball path's filter="data" (which rejects absolute paths and traversal), so a crafted .obscpio could write outside the temp dir. Add GNU cpio's --no-absolute-filenames to close that gap. Also include the last 5 non-empty lines of npm's stdout in the die() message on failure, so a failed npm install carries a real diagnostic instead of just the exit code. Signed-off-by: Ricardo Dias <ricardo.dias@percona.com>
Signed-off-by: Ricardo Dias <ricardo.dias@percona.com>
Drift tolerance only affects the --branch-from changed/unchanged decision; it does not affect what a non-skipped sync uploads. Make explicit that a regenerated drift-tolerant artifact (e.g. pgAdmin's ~220 MB node_modules.obscpio) still gets re-PUT and triggers a new OBS revision/rebuild when the package is synced for any other reason (or with --force); --skip-unchanged avoids this for tag-pinned packages, and --no-cache is the deliberate refresh. Also note that each new upstream commit of an npm-vendored package adds a .cache/services entry of roughly the cpio's size, bounded locally by prune_cache (7-day unused eviction) and in CI by actions/cache size limits. Signed-off-by: Ricardo Dias <ricardo.dias@percona.com>
…ring and friends The 35 remaining libraries of pgAdmin 4's Python 3.12 closure, which depend on part 1 / ppg:common:deps packages: Flask 3.1.3 and its extensions (Flask-Security-Too 5.6.2, Flask-SocketIO, Flask-Migrate, ...), SQLAlchemy 2.0.52 + alembic, Werkzeug/Jinja2, keyring 25.2.1 stack, paramiko/sshtunnel, psycopg 3.2.10, typer/rich, gssapi 1.10.1 (Cython 3), python-socketio/engineio, WTForms. Runtime dependencies are also BuildRequires so the %check import smoke test runs against the buildroot; OBS orders the builds accordingly. Design: docs/superpowers/specs/2026-08-26-pgadmin4-py312-stack-design.md Signed-off-by: Ricardo Dias <ricardo.dias@percona.com>
…duplicated by the preamble Signed-off-by: Ricardo Dias <ricardo.dias@percona.com>
…dmin Python stack Signed-off-by: Ricardo Dias <ricardo.dias@percona.com>
… the source tree, is imported Signed-off-by: Ricardo Dias <ricardo.dias@percona.com>
…e,wsproto}: patch PEP 639 licence fields for setuptools 68 Signed-off-by: Ricardo Dias <ricardo.dias@percona.com>
…rom PyPI metadata) Signed-off-by: Ricardo Dias <ricardo.dias@percona.com>
…port) Signed-off-by: Ricardo Dias <ricardo.dias@percona.com>
Signed-off-by: Ricardo Dias <ricardo.dias@percona.com>
…s.py Signed-off-by: Ricardo Dias <ricardo.dias@percona.com>
…fetching it Signed-off-by: Ricardo Dias <ricardo.dias@percona.com>
…bcrypt/Cargo.toml Signed-off-by: Ricardo Dias <ricardo.dias@percona.com>
Signed-off-by: Ricardo Dias <ricardo.dias@percona.com>
…tch build hook Signed-off-by: Ricardo Dias <ricardo.dias@percona.com>
Signed-off-by: Ricardo Dias <ricardo.dias@percona.com>
Signed-off-by: Ricardo Dias <ricardo.dias@percona.com>
Signed-off-by: Ricardo Dias <ricardo.dias@percona.com>
…thon RPM name Signed-off-by: Ricardo Dias <ricardo.dias@percona.com>
…-only closure edges) Signed-off-by: Ricardo Dias <ricardo.dias@percona.com>
…uires exception, aarch64 wording Signed-off-by: Ricardo Dias <ricardo.dias@percona.com>
…-9_17) Package layout and spec design for percona-pgadmin4 with -gunicorn (container runtime, systemd unit), -httpd (mod_wsgi conf + setup helper) and -doc (rst sources) subpackages; obs_scm(REL-9_17) → npm_lockfile → node_modules source chain; config_distro.py with Percona defaults and PGADMIN_CONFIG_* env overrides; the SP3 stack changes for 9.17 (libpass replaces passlib, certifi, annotated-doc, gunicorn, bumps; Authlib kept at 1.6.12); verification via PR #12 plus a container smoke test with the OBS-built RPMs. Signed-off-by: Ricardo Dias <ricardo.dias@percona.com>
…OBS loop, container smoke test) Signed-off-by: Ricardo Dias <ricardo.dias@percona.com>
…uires (pre-flight ruling) Signed-off-by: Ricardo Dias <ricardo.dias@percona.com>
Bump Flask-Security-Too 5.8.2, Flask-SocketIO 5.6.1, Flask-WTF 1.3.0, gssapi 1.11.1 (Cython 3.2.4), psycopg/psycopg-c 3.3.4, pytz 2026.3.post1, typer 0.26.8. Add annotated-doc 0.0.5, certifi 2026.6.17, libpass 1.9.3 (replaces passlib) and gunicorn 26.2.0 (container runtime). Drop passlib and importlib-resources. Aggregate the common:deps runtime packages (click, six, dateutil, psutil, dns) so the project repo is self-contained. Signed-off-by: Ricardo Dias <ricardo.dias@percona.com>
…s, certifi consumer Signed-off-by: Ricardo Dias <ricardo.dias@percona.com>
Ported from openSUSE's pgadmin4.spec to EL9/python3.12. Sources come from the upstream REL-9_17 tag through obs_scm -> npm_lockfile -> node_modules; webpack runs against local-npm-registry. Subpackages: -gunicorn (launcher + systemd unit, PGADMIN_CONFIG_* env mapping; the container runtime), -httpd (mod_wsgi conf + percona-pgadmin4-setup-web), -doc (rst sources; Help menu links to the online manual). Signed-off-by: Ricardo Dias <ricardo.dias@percona.com>
…aging, console scripts, httpd conf, timeout, typing-extensions Signed-off-by: Ricardo Dias <ricardo.dias@percona.com>
Signed-off-by: Ricardo Dias <ricardo.dias@percona.com>
Signed-off-by: Ricardo Dias <ricardo.dias@percona.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
This PR carries the pgAdmin 4 for UBI-9 effort sub-project by sub-project so every step is exercised by the OBS PR check before the whole lands. Design:
docs/superpowers/specs/2026-08-26-pgadmin4-tooling-design.md(includes the decomposition into SP2local-npm-registry, SP3python3.12-*stack ported from openSUSE:Factory, SP4percona-pgadmin4). Plan for SP1:docs/superpowers/plans/2026-08-26-pgadmin4-tooling.md.percona-obs(and the obs-tools CI image) work with the OBSnode_modulessource service, which vendors npm dependencies for offline builds, and create the emptyppg:devel:pgadminOBS project that will hold every pgAdmin package.local-npm-registry: the offline npm registry RPM thatpercona-pgadmin4willBuildRequiresat build time.SP1 — Changes
tools/obs-services/npm_lockfile(+.service, README) — repo-owned, stdlib-only OBS-style service: unpacks theobs_scmarchive, runsnpm install --package-lock-onlyin--subdir, validateslockfileVersion >= 2, writespackage-lock.jsonto--outdir. Declaredmode="manual"ahead ofnode_modules, sopercona-obsgenerates the lockfile at sync time (pgAdmin ships onlyyarn.lock). Params:archive,subdir,npm-flags.percona_obs/services.py—.obscpiofiles produced bymode="manual"services (e.g.node_modules.obscpio) are kept for upload instead of being extracted/deleted;obs_scmarchives are still extracted.percona_obs/services.py/cmd_sync.py— theignore_vendorspecial case (cargo_vendor→vendor.tar.*) becomes a table-drivendrift_tolerant_patterns()that also coversnode_modulesoutputs (node_modules.obscpio,node_modules.spec.inc,*package-lock.json): compared by presence only in the--branch-fromcontent check, so registry-driven byte drift never promotes a package by itself.cargo_vendorbehaviour unchanged.obs-service-node-modules(+python3-lxml), Node.js 22 + npm (NodeSource; matches thenodejs:22module the packages build against),cpio, and thenpm_lockfileservice;build-obs-image.ymlalso triggers ontools/obs-services/**.root/ppg/devel/pgadmin/project.yaml— newppg:devel:pgadminproject,UBI_9only (path list mirrors staging's UBI_9 entry) withExpandFlags: module:nodejs:22. No packages yet;root/README.mddocuments the version-independent devel project.docs/PERCONA_OBS_TOOL.md(prerequisites, "Vendoring npm dependencies" section, drift-tolerant table),.github/copilot-instructions.md,CLAUDE.md.SP2 — Changes
root/common/deps/build/local-npm-registry/— new RPM-only, noarch build-dep package ported from openSUSEdevel:languages:javascript/local-npm-registry(upstreamopenSUSE/npm-localhost-proxyv1.1.0, the latest release). Source is the upstream release tarball viadownload_url;dist/andnode_modules/(runtime depssri) are pre-bundled, so nothing is built. EL9 port of the spec:Requires: nodejs >= 20+npm(thenodejs:22module stream; EL has nonpm-default), same/usr/bin/local-npm-registrynode launcher,%license COPYING.root/macros.yaml—LOCAL_NPM_REGISTRY_VERSION: 1.1.0, following the pinned build-dep tool convention (bumps per "Bumping a Pinned Build-Dependency Tool Version" inPACKAGING_HOWTO.md).package.yamlbuild:flags (pgAdmin 4 is a UBI-9-only product);root/README.mdlists it undercommon/deps/build/.SP3 — Changes
root/ppg/devel/pgadmin/python3-*(71 new) — pgAdmin 4REL-9_9's Python 3.12 closure (cloud extras excluded), one EL spec template: PyPI sdist viadownload_url,pip wheel --no-build-isolation+pip install --root(legacysetup.pyfor 9 packages), import smoke test in%check, runtime deps doubled asBuildRequires. Build toolspython3-cython3.1.3,python3-poetry-core,python3-pdm-backend. bcrypt vendors its Rust crate withcargo_vendor.root/ppg/common/deps/—python3-dnsbumped 1.15.0 → dnspython 2.8.0 (email-validator ≥ 2.0; name kept,python3-etcd/percona-patronirebuilt by dep-cascade); new shared build-backend stackpython3-flit-core3.12.0,python3-packaging25.0,python3-pathspec,python3-trove-classifiers,python3-hatchling1.28.0 for EL8/EL9/UBI (RHEL's backends cannot build PEP 639 metadata; EL10/openSUSE use their distro ones via a spec conditional).python3.12-{cffi,cryptography 41,idna,pycparser,urllib3 1.26,setuptools 68}and common:deps'six/dateutil/psutil/click; pinned down where PEP 639 metadata would need setuptools ≥ 77 (keyring 25.2.1, jaraco.context 6.0.1, jaraco.functools 4.1.0, importlib-resources 6.5.2, Pillow 11.1.0), bidict 0.23.1, pyotp 2.9.0, ua-parser 0.18.0.docs/PACKAGING_HOWTO.md"Python 3.12 packages (pyproject builds)";root/README.md.docs/superpowers/specs/2026-08-26-pgadmin4-py312-stack-design.md.Verification
SP1
pytest: 147 passed (23 new tests: service with a fakenpm,_run_local_serviceswith fake service binaries + real cpio archive, drift-tolerant patterns);black+pyrightclean.node_modules,npm_lockfile,cpio,node v22.23.2,npm 10.9.8.obs_scm(pgAdminREL-9_9) →npm_lockfile→node_modulesviasync push --dry-run(isv-prprofile), twice: 5-file upload set (node_modules.obscpio197 MiB,node_modules.spec.inc1 439 Source lines,package-lock.jsonlockfileVersion 3 / 1 550 packages, tarball, obsinfo), artifact set matches the drift-tolerant table exactly, second run fully cached. Details recorded in the spec's §10.mainwith percona-obs: never promote on content-check service failure; compare rendered referenced macros #13): synced toisv:percona:PR:pr-12with 0 spurious promotes.SP2
sync push --dry-run -P isv-pr common:deps:build local-npm-registry:download_urlresolves; would-be upload is exactlylocal-npm-registry.spec+local_npm_registry-v1.1.0.tar.gz.rpmspec→local-npm-registry-1.1.0-1.el9.noarch.isv:percona:PR:pr-12:common:deps:build/local-npm-registryon UBI_9.SP3
sync push --dry-run -P isv-pr, allsync successful (dry run)):python3-hatchling,python3-trove-classifiers,python3-dns(common:deps);python3-bcrypt(download_url+cargo_vendor, 3 files),python3-psycopg-c,python3-flask,python3-wtforms,python3-paramiko,python3-typer,python3-rich.isv:percona:PR:pr-12(UBI_9 only, per the PR'sUBI_9label):ppg:devel:pgadmin142/142succeeded(71 packages × x86_64 + aarch64);ppg:common:deps12/12succeeded(python3-flit-core,-packaging,-pathspec,-trove-classifiers,-hatchling,-dns, × 2 arches). Board settled 2026-08-27 16:04 UTC.52d93bcall 77 specs —%checkimported the source tree instead of the buildroot (missing native extensions, e.g. gssapiNo module named gssapi.raw.creds) →%{__ospython} -P -c "import ...".176d706python3-{alembic,backports-zstd,greenlet,mako,markupsafe,secretstorage,wsproto} — RHEL setuptools 68 rejects PEP 639license = "…"+license-files→%prepsed tolicense = {text = "…"}, droplicense-files(kept RHEL setuptools rather than shipping setuptools 80).4441f17python3-flask-principal — Flask/blinker missing from PyPI metadata → added as BuildRequires/Requires.2b65469python3-psycopg — pure-Python pq wrapper needslibpqat import → BuildRequires/Requires libpq.3a385e0python3-psycopg-c —psycopg_crefuses import unlesspsycopgis imported first → BuildRequires python3.12-psycopg,%checkimports psycopg then psycopg_c.d8ade24python3-qrcode — ambiguous#!/usr/bin/env pythonshebang inqrcode/console_scripts.py→ removed in%prep.9836542python3-ua-parser —setup_requires=["pyyaml"]fetched from PyPI (offline build) → BuildRequires python3.12-pyyaml, dropsetup_requires.fce0164python3-bcrypt —cargo_vendorplacesvendor//.cargo/config.tomlundersrc/_bcrypt/, not the sdist root →CARGO_HOME=$PWD/src/_bcrypt/.cargo.abdc615python3-greenlet — wheel installs an unpackaged/usr/include/python3.12/greenlet/greenlet.h→ added to%files.5498b3epython3-wtforms — hatch build hook compiles translations with Babel (ModuleNotFoundError: babelduringpip wheel) → BuildRequires python3.12-babel._jobhistoryreason "meta change" (download-on-demand path repos for Rocky 9 / EPEL 9 refreshing) on a slow x86_64 scheduler — roughly 4 hours from first push to a settled board; not caused by our pushes (every sync logged= project meta/config).python3-etcd,percona-patroni) was not exercised in PR pgAdmin 4 for UBI-9: SP1 node_modules tooling + SP2 local-npm-registry + SP3 Python 3.12 stack #12 because it carries theno-dep-cascadelabel — the cascade rebuild happens on merge; and theppg:common:depspackages were only built on UBI_9 in the PR — RockyLinux_8/9/10, UBI_8, and openSUSE builds happen after merge.Notes / follow-ups
node_modules/npm) is only produced after merge (build-obs-image.ymltriggers onmain) and is needed before SP4's package lands.sync push --project-onlyrejects a package-less project (targets.py), soppg:devel:pgadminis created on OBS when its first package syncs (SP3/SP4).yarn.lockas a resolution hint — the generated lockfile resolves newer caret-satisfying versions than upstream tested (4 of 5 sampled packages). SP4 has to decide between pinning and accepting the drift. The real ~200 MB upload timing check is also left to SP4's real package.cmd_sync.py,obs_api.py) once a ~200 MB artifact actually exists.