Skip to content

Merge foward 3006.x into 3007.x#68897

Open
dwoz wants to merge 54 commits into3007.xfrom
merge/3006.x/3007.x-26-04-04
Open

Merge foward 3006.x into 3007.x#68897
dwoz wants to merge 54 commits into3007.xfrom
merge/3006.x/3007.x-26-04-04

Conversation

@dwoz
Copy link
Copy Markdown
Contributor

@dwoz dwoz commented Apr 4, 2026

What does this PR do?

What issues does this PR fix or reference?

Fixes

Previous Behavior

Remove this section if not relevant

New Behavior

Remove this section if not relevant

Merge requirements satisfied?

[NOTICE] Bug fixes or features added to Salt require tests.

Commits signed with GPG?

Yes/No

cjriches and others added 30 commits March 11, 2026 17:00
The RPM specfile runs compileall in %post to byte-compile Python modules
under /opt/saltstack/salt/lib. This worked fine until commit 48c7d58
(Bump relenv version to 0.20.0).

In relenv >=0.20.0, the interpreter bootstrap actively imports ppbt and
extracts toolchains if available, rather than just checking if they're
already there. This should not have been a problem, as commit 4bd2832
(Remove ppbt after building the salt onedir) removed ppbt from the final
package so it never gets installed at runtime.

However, the subtleties of RPM scriptlet ordering cause issues on
upgrade. The %post scriptlet executes after the new version has been
installed, but before the stale files of the old version have been
removed. This means that ppbt is still present when the compileall runs,
so the bootstrap hooks extract the ppbt toolchain into
/root/.local/relenv.

This is usually harmless, but silently eats about 215 MiB of disk space,
which can be anywhere from mildly annoying to severely damaging
depending on how tight the root filesystem is.

Since both 48c7d58 and 4bd2832 went into 3006.15, any in-place
upgrade of salt that crosses this version will generate this spurious
toolchain.

Move the compileall into %posttrans, at which point we guarantee the old
package has been completely removed and we are only acting on the
correct python libraries.
When we regenerate the pycache on upgrade, stale files from removed
libraries may persist. Clear everything out first to avoid this.

For consistency, change the existing pycache clear-on-uninstall to use
the simpler -delete pattern instead of invoking xargs.
This change ensures that Salt file and directory ownership is correctly
detected and preserved during upgrades, and that salt-call and salt-pip
correctly honor the configured user for privilege dropping.

Core Changes:
- Update salt-pip to detect the configured user and drop privileges
  when run as root, ensuring files in the onedir 'extras' directory
  maintain correct ownership.
- Update salt-call to properly distinguish between the configured
  user (for environment verification/ownership) and the execution
  user (provided via --priv), preventing accidental ownership resets
  to root when running maintenance tasks.

RPM Changes:
- Implement robust ownership detection in %pre by checking runtime PID
  files, PKI directories, and cache paths.
- Restore ownership in %post and %posttrans for all critical Salt
  paths, including the onedir installation directory (/opt/saltstack/salt)
  and extras directories.
- Fix a bug in %posttrans where upgrades were incorrectly detected as
  fresh installs. A marker file is now used for reliable state transition.
- Clean up debug logging and fix shell logic errors in the spec file.

Debian Changes:
- Prevent usermod from resetting the salt user's shell in preinst,
  ensuring salt-call and salt-pip remain functional after upgrade.
- Ensure onedir installation paths are included in ownership management.
- Update service postinst scripts to only apply default ownership on
  fresh installs, preventing resets during upgrades.

Test and Tooling Changes:
- Update Debian upgrade tests to use exact version pinning.
- Add comprehensive upgrade tests to verify ownership preservation and
  the functionality of salt-call and salt-pip under non-root configurations.
- Remove temporary relenv runtime patches from build rules.

Fixes #68684
- Add ci_build_pkg and ci_test_pkg tools to salt-test MCP server
- Generalize MCP server launcher to work across different worktrees
- Update agents documentation for package building
- Add changelog entry and update work summary
When beacons_refresh() creates a new Beacon instance, the old instance's
beacon modules (e.g. inotify) held open file descriptors that were never
closed. Each new Beacon gets a fresh empty __context__ dict via LazyLoader,
so inotify's _get_notifier() creates a new pyinotify.Notifier while the
old one is orphaned with its fds still open. Over repeated refreshes, this
exhausts the inotify instance limit (default 128 on RHEL8), causing
"Too many open files (EMFILE)" errors.

Add close_beacons() to the Beacon class that calls close() on each beacon
module before the instance is replaced. Also add __del__() as a safety net
for garbage collection, and call close_beacons() explicitly from
Minion.beacons_refresh() before creating a new Beacon instance.

Fixes: #66449
Fixes: #58907
Made-with: Cursor
This change moves core metadata to the [project] table in pyproject.toml, cleans up requirement files for PEP 517 compatibility, ensures dependencies are dynamically discovered from .txt files, updates static requirement files via pre-commit hooks, and inhibits automatic code rewriting hooks to maintain scope.
Tornado remains vendored as salt.ext.tornado on the 3006.x branch. This change removes the erroneous external dependency and updates static requirement files.
The documentation build needs all Salt dependencies to correctly import
modules for autodoc. Adding requirements/crypto.txt ensures that
cryptographic dependencies (like pycryptodomex) are available.
Update *-crypto.txt files across all platforms and Python versions to
ensure version consistency and resolve pre-commit hook discrepancies.
Synchronize with CI environment by applying formatting changes made by
the black pre-commit hook.
Include base.txt and zeromq.txt in the Windows packaging requirement
compilation hooks. This ensures that the static windows.txt requirement
files contain all necessary dependencies for onedir builds, resolving
failures in install_salt.ps1.
The myst-parser requirement for documentation builds on Python 3.9
requires mdit-py-plugins which in turn requires markdown-it-py < 3.0.0.
Other packages like rich were pulling in markdown-it-py >= 3.0.0 on
some platforms, causing resolution failures.

This commit adds a Python version-specific constraint and regenerates
the affected static requirement files.
…ures

Move Salt's dynamic metadata and dependency logic from setup.py to a custom PEP 517 build backend (tools/pkg/salt_build_backend.py). This modernizes the build system while preserving Salt's complex multi-platform requirement selection logic.

Fix installation failures in compiler-less environments by moving timelib and linode-python out of core base requirements. These packages require compilation on Linux and are now only included in packaging-specific static requirement sets where pre-built wheels are verified.

Key changes:
- Implement tools/pkg/salt_build_backend.py to handle dynamic versioning, requirements, and entry points.
- Refactor setup.py to delegate dynamic properties to the new backend.
- Move timelib and linode-python from requirements/base.txt to platform-specific .in files in requirements/static/pkg/.
- Restore pycryptodomex>=3.9.8 as a core base requirement.
- Fully regenerate all static packaging pins for Python 3.9-3.13.
- Update tests/pytests/functional/test_pip_install.py to skip on Linux systems without a C compiler.
Add hatchling to --only-binary in onedir_dependencies() so pip installs
it from its universal wheel instead of attempting a source build.
When --no-binary :all: is active (Linux builds), pip 25.2 tries to
source-build hatchling but hatchling lists itself as its own PEP 517
build backend, causing pip's build tracker to raise:

  LookupError: hatchling is already being built

Fixes #68858

Made-with: Cursor

Fix locale.set_locale failing on containers without systemd-localed

On updated Amazon Linux 2023 and Photon OS 5 containers, localectl
set-locale fails with a non-zero exit code because systemd-localed is
not running (D-Bus write access unavailable), while localectl status
continues to work by reading /etc/locale.conf directly.

_localectl_set() now falls back to writing /etc/locale.conf directly
when localectl set-locale returns non-zero.  Modern systemd's localectl
status reads that file without D-Bus, so a subsequent get_locale() call
immediately reflects the change.

_check_systemctl() in the integration test is hardened to skip the test
for the full range of D-Bus connection error messages (Connection refused,
Failed to connect to bus, Failed to get D-Bus connection) and guards
against FileNotFoundError when localectl is absent.

Fixes test_localemod.py::LocaleModuleTest::test_set_locale on:
  - Amazon Linux 2023 Arm64
  - Photon OS 5 Arm64 (fips)
  - Photon OS 5

Made-with: Cursor

Provide a generous timeout for traceroute

Fix pre-commit whoops

The "Parallel cache failure" test failure

this had two root causes, both related to Python 3.14's new default
multiprocessing start method (forkserver, via PEP 741):

Root Cause 1: `spawning_platform()` didn't recognize `forkserver`

salt/utils/platform.py only checked for "spawn", not "forkserver". This
caused AttributeError: 'Process' object has no attribute
'_args_for_getstate' because Process.__new__ didn't set up pickling
support for forkserver-spawned children.  Fix: Changed
spawning_platform() to return True for both "spawn" and "forkserver".

Root Cause 2: Circular import when `extmods/utils/platform.py` shadows
stdlib

In Python 3.14, the forkserver itself is a fresh Python process (spawned
via exec). When it creates child processes:
1. It sets sys.path from the parent salt-call process via
   preparation_data
2. The parent's sys.path had extmods/utils/ at index 0 (inserted by
   insert_system_path)
3. In the fresh child, import platform found extmods/utils/platform.py
   (salt's platform util) before stdlib's platform.py
4. extmods/utils/platform.py does from salt.utils.decorators import
   memoize which creates a circular import: • salt.utils.decorators →
   salt.utils.versions → salt.version → import platform → (itself) →
   salt.utils.decorators ♻️

Fix 1 (targeted): Replaced from salt.utils.decorators import memoize as
real_memoize in salt/utils/platform.py with
functools.lru_cache(maxsize=None) — a stdlib-only alternative that
breaks the circular dependency.  Fix 2 (defensive): Changed
insert_system_path() in salt/config/__init__.py from sys.path.insert(0,
...) to sys.path.append(...), so extension module directories never
appear before stdlib paths.

Use functools.cache for real_momoize

Update traceroute test
Fix inotify file descriptor leak during beacon refresh
This changes is to account for CVE fixes, so that scanning tools will
not flag false posisitves.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

test:full Run the full test suite

Projects

None yet

Development

Successfully merging this pull request may close these issues.

5 participants