Merge forward 3008.x into master#69491
Merged
Merged
Conversation
After the requirements .txt -> .in rename, MANIFEST.in still only included requirements/*.txt, so the PyPI sdist no longer shipped the files setup.py reads to populate install_requires. The build backend silently returned an empty list, and `pip install salt==3008.0` installed salt with zero dependencies. Add *.in and *.lock to the recursive-include so the dependency manifests (and the locked variants used when USE_STATIC_REQUIREMENTS=1) end up in the sdist again.
doc/conf.py hard-coded "version_match": "master", so every published
build (including the 3008.0 release at /en/latest/) emitted
DOCUMENTATION_OPTIONS.theme_switcher_version_match = 'master' and the
dropdown always highlighted "Master (Dev)" as the current version.
Make version_match dynamic so it matches a versions.json entry by
BUILD_TYPE:
- master / next -> "master"
- latest -> "latest"
- previous / other -> release.split(".", 1)[0] (e.g. "3006")
Also fix the dropdown URLs in doc/_static/versions.json. The 3006.24
entry pointed at /en/3006.24/ which returns 404; the served URL pattern
is /en/<major>/ (e.g. /en/3006/, /en/3008/). Rewrite the entries to use
major-only paths and add a 3008 entry, since the latest release at
docs.saltproject.io is now 3008.0.
Note: doc/conf.py points every build at the absolute json_url
https://docs.saltproject.io/en/latest/_static/versions.json, so the
served versions.json is whichever branch publishes /en/latest/. Updating
versions.json here is harmless on 3006.x but only takes effect site-wide
when the same change reaches the branch that builds /en/latest/.
Verified locally with the CI invocation under a python3.14 venv built
from requirements/static/ci/py3.14/docs.lock:
cd doc && make clean && make html SPHINXOPTS='-W -j auto --keep-going --color'
cd doc && make clean && BUILD_TYPE=latest make html SPHINXOPTS='-W -j auto --keep-going --color'
Rendered contents.html emits:
theme_switcher_version_match = 'master' (default)
theme_switcher_version_match = 'latest' (BUILD_TYPE=latest)
`test_master_minion_start` installs from the source directory, so pip builds a wheel in place and `setup.py` reads requirements files directly off disk. That path never consults MANIFEST.in, so it can't catch a regression where the published sdist is missing the files `setup.py` needs to populate install_requires -- which is precisely how saltstack#69244 reached PyPI undetected. Add a sibling fixture that runs `python -m build --sdist` first, then pip-installs the resulting tarball into a fresh venv. The existing master/minion startup + salt-call test.ping assertions then catch a dependency-less install because salt-master crashes on tornado import. Verified against the unpatched 3008.x: the new fixture's pip install produces a salt with no dependencies (`import tornado` raises ModuleNotFoundError), reproducing the user-reported failure.
pkg.list_patches in yumpkg.py parses tdnf output on Photon OS
Ship requirements/*.in and *.lock in sdist
Fix docs version switcher selecting the wrong active version
Add sdist-roundtrip sibling test for pip install salt (saltstack#69244)
After the requirements .txt -> .in rename, MANIFEST.in still only included requirements/*.txt, so the PyPI sdist no longer shipped the files setup.py reads to populate install_requires. The build backend silently returned an empty list, and `pip install salt` from a sdist built off this branch would install salt with zero dependencies. Add *.in and *.lock to the recursive-include so the dependency manifests (and the locked variants used when USE_STATIC_REQUIREMENTS=1) end up in the sdist again. Backport of the 3008.x fix; changelog lives on the forward branch.
After the requirements .txt -> .in rename, MANIFEST.in still only included requirements/*.txt, so the PyPI sdist no longer shipped the files setup.py reads to populate install_requires. The build backend silently returned an empty list, and `pip install salt` from a sdist built off this branch would install salt with zero dependencies. Add *.in and *.lock to the recursive-include so the dependency manifests (and the locked variants used when USE_STATIC_REQUIREMENTS=1) end up in the sdist again. Backport of the 3008.x fix; changelog lives on the forward branch.
Revert requirement source files to .txt to fix Dependabot sync
Revert requirement source files to .txt to fix Dependabot sync
After the requirements .txt -> .in rename, MANIFEST.in still only included requirements/*.txt, so the PyPI sdist no longer shipped the files setup.py reads to populate install_requires. The build backend silently returned an empty list, and `pip install salt` from a sdist built off this branch would install salt with zero dependencies. Add *.in and *.lock to the recursive-include so the dependency manifests (and the locked variants used when USE_STATIC_REQUIREMENTS=1) end up in the sdist again. Backport of the 3008.x fix; changelog lives on the forward branch. # Conflicts: # requirements/static/ci/py3.10/cloud.lock # requirements/static/ci/py3.10/darwin.lock # requirements/static/ci/py3.10/freebsd.lock # requirements/static/ci/py3.10/lint.lock # requirements/static/ci/py3.10/linux.lock # requirements/static/ci/py3.10/windows.lock # requirements/static/ci/py3.11/cloud.lock # requirements/static/ci/py3.11/darwin.lock # requirements/static/ci/py3.11/freebsd.lock # requirements/static/ci/py3.11/lint.lock # requirements/static/ci/py3.11/linux.lock # requirements/static/ci/py3.11/windows.lock # requirements/static/ci/py3.12/cloud.lock # requirements/static/ci/py3.12/darwin.lock # requirements/static/ci/py3.12/freebsd.lock # requirements/static/ci/py3.12/lint.lock # requirements/static/ci/py3.12/linux.lock # requirements/static/ci/py3.12/windows.lock # requirements/static/ci/py3.13/cloud.lock # requirements/static/ci/py3.13/darwin.lock # requirements/static/ci/py3.13/freebsd.lock # requirements/static/ci/py3.13/lint.lock # requirements/static/ci/py3.13/linux.lock # requirements/static/ci/py3.13/windows.lock # requirements/static/ci/py3.14/cloud.lock # requirements/static/ci/py3.14/darwin.lock # requirements/static/ci/py3.14/freebsd.lock # requirements/static/ci/py3.14/lint.lock # requirements/static/ci/py3.14/linux.lock # requirements/static/ci/py3.14/windows.lock # requirements/static/ci/py3.9/cloud.lock # requirements/static/ci/py3.9/darwin.lock # requirements/static/ci/py3.9/freebsd.lock # requirements/static/ci/py3.9/lint.lock # requirements/static/ci/py3.9/linux.lock # requirements/static/ci/py3.9/windows.lock
``dynamic_context = test_function`` forces coverage.py off the sys.monitoring (sysmon) measurement core — sysmon does not yet implement dynamic contexts. On Python 3.14 sysmon is the default and is dramatically faster than the PyTracer / CTracer fallbacks. With the coverage pin we currently carry (7.3.1), no CTracer wheel ships for 3.14 either, so dynamic_context drops the test suite all the way down to the pure-Python PyTracer. That combination — the slow PyTracer plus relenv's runtime wrappers around sysconfig — makes every forked subprocess's ``cov.start()`` take minutes, which the functional zeromq 4 shard surfaces as 12 timing-out tests and a leaked non-daemon-child subprocess that blocks Python interpreter exit until GHA's 3-hour step timeout kills the job. Commenting the setting out unblocks sysmon (or at least CTracer on versions that ship a 3.14 wheel) so subprocess startup pays sub-millisecond per-line trace cost instead of multi-second. The inline comment in ``.coveragerc`` captures the symptoms and the re-enable condition. Refs: coveragepy/coveragepy#2082 https://coverage.readthedocs.io/en/latest/contexts.html https://coverage.readthedocs.io/en/latest/faq.html
Salt is now running on a Python 3.14 onedir and the prior coverage pin (7.3.1) ships no CTracer wheel for 3.14 — coverage falls back to the pure-Python PyTracer. PyTracer is several orders of magnitude slower than CTracer and, combined with the relenv runtime's wrappers around ``sysconfig.get_paths`` / ``get_config_vars`` (each forked subprocess hits them from ``coverage.start()`` → ``add_third_party_paths``), pushes the functional zeromq 4 shard into a state where 12 subprocess-heavy tests blow past their internal asyncio / queue / loop timeouts and leak non-daemon children, which then blocks Python interpreter exit and trips the GHA 3-hour step timeout. 7.14.0 is the current latest release where the 3.14 CTracer wheel is mature. Skip the 7.11.1–7.11.3 window — those have a known 2x perf regression on Python 3.14 (coveragepy issue saltstack#2082). The companion ``.coveragerc`` change in 6636a19 disables ``dynamic_context = test_function`` so coverage can pick the fastest core (sysmon on 3.14 when available, CTracer otherwise) instead of being forced down the slow path. Refs: coveragepy/coveragepy#2082 https://coverage.readthedocs.io/en/latest/changes.html
Previous commit put the ``a1_coverage.pth`` removal inside the
``if SKIP_REQUIREMENTS_INSTALL is False`` branch of
``_install_coverage_requirement``. CI sets
``SKIP_REQUIREMENTS_INSTALL=1`` on the actual test step (the venv was
populated in a separate earlier step), so my cleanup never fired and
the ``.pth`` from the prior install still ran at site init — the
Photon FIPS shards stayed broken with the same
``LIBRARY_HAS_NO_CIPHERS`` import error.
Move the ``.pth`` removal out of the install branch so it runs every
time ``_install_coverage_requirement`` is called. The unlink is
idempotent (no-op once the file is gone) so running it on every nox
session that touches coverage is harmless.
Confirmed in the failing job 26262301538 logs that the install branch
was skipped::
nox > Skipping Python Requirements because SKIP_REQUIREMENTS_INSTALL
was found in the environ
ImportError while loading conftest '/__w/salt/salt/tests/conftest.py'
...
ssl.SSLError: [SSL: LIBRARY_HAS_NO_CIPHERS] library has no ciphers
The Linux fork-path threshold of 4 ms was set in an era when the parallel-state path was un-traced; under coverage 7.14 + sysmon on Python 3.14 the forked child's loader lookup + ``file.exists`` call measures ~60-100 ms on GHA's 2-vCPU runners — comfortably under the 2000 ms retry interval, but well over the 4 ms ceiling. This test asserts two things: - ``state_return.result is True`` (operation succeeded) - ``state_return.full_return["duration"] < N`` (no retry interval fired) - ``"Attempt 2" not in state_return.comment`` (no retry attempt) The middle assert is a sanity check against the 2000 ms retry interval, not a microbenchmark of the fork path. Bump the threshold to a value that still catches a real retry firing while tolerating realistic GHA-runner-under-coverage latency: - fork (Linux): 4 ms -> 500 ms - spawn: 30 ms -> 1500 ms - spawn + darwin: +15 ms -> +500 ms The Linux fork failure pattern in CI run 26271348038 was the universal cause of ``functional zeromq 1`` shard failures across every distro (Debian 11/12/13, Amazon, Fedora, Rocky, Ubuntu, Photon 4/5 + FIPS).
salt:///foo (RFC 3986 empty authority + absolute path) was historically accepted as an equivalent spelling of salt://foo, but on 3008.x cp.get_file salt:///path/to/file fails because the surplus leading slash propagates through parse() to the master fileserver, which rejects absolute paths in find_file (CVE-2024-22231 / CVE-2024-22232 hardening). On older releases the leading slash was laundered away by the file:/// round-trip in salt.utils.url.create(); once that round-trip was removed for Python 3.13 compatibility (4cdd334, ce02842) the bug became user-visible end-to-end. Strip leading slashes from the parsed path so both URL spellings behave identically. The fileserver always interprets salt:// paths as relative to a file_roots entry, so a leading / was never meaningful. Fixes saltstack#69472
…t-3slash-url Accept salt:/// (3-slash) URLs in salt.utils.url.parse
`pillar.get`, `pillar.items`, `pillar.item`, and `pillar.data` accept an
`unmask` kwarg added in 3008.0. This applies the same parameter to
`pillar.ls`, `pillar.raw`, `pillar.ext`, `pillar.keys`, and
`pillar.obfuscate` so callers have a uniform API across the module.
Default semantics are preserved:
* `ls`, `obfuscate` forward `unmask` to `items` (whose default is
auto-detect via the `mask_pillar` ContextVar).
* `ext` mirrors `items`: auto-detect when `unmask=None`.
* `raw` preserves its historical always-unmask default; setting
`unmask=False` now lets callers obtain masked values.
* `keys` accepts `unmask` for API uniformity; nested pillar keys are
never masked, so the parameter is a no-op for this function.
Refs saltstack#69453
…ack#69228) When the master returns a bare-string error payload such as "bad load", "Some exception handling minion payload", or "Server-side exception handling payload" for a pillar request, the minion's AsyncReqChannel.crypted_transfer_decode_dictentry could crash with "TypeError: string indices must be integers" at ret["key"]. The pre-2efc32ea883 guard ("key" not in ret) silently passed for strings because Python interprets it as a substring check, then the post-reauth retry returned the same string and the dict-style indexing blew up. Master already carries the fix from commit 2efc32e ("Unblock raft heartbeats and harden pillar decode against cluster_retry"), which adds layered isinstance(ret, dict) guards and raises a clean AuthenticationError when the master keeps returning a non-dict. That fix covers this scenario as a side effect of the cluster_retry hardening but had no dedicated regression test. Add a parametrized test that mocks the transport to return each of the three observed bare-string error payloads and asserts the channel raises salt.crypt.AuthenticationError rather than crashing with TypeError. Verified the test fails on the pre-2efc32ea883 code path with the exact stacktrace reported in the issue, and passes on current master. Fixes saltstack#69228
Two bugs introduced in saltstack#68039 combined to delete every auth token from the default localfs cache backend within one master ``loop_interval`` (default 60s): 1. ``Cache.clean_expired``'s fallback (for drivers without a native ``clean_expired``) compared the driver's ``updated()`` value -- for localfs the file mtime, an epoch in the past -- with ``time.time()`` and flushed every key whose mtime had passed. That is true for every file on disk, so the entire bank was wiped on every sweep. 2. ``LoadAuth.mk_token`` passed ``expires=tdata["expire"]`` to ``Cache.store``, where ``tdata["expire"]`` is the absolute epoch ``time.time() + token_expire``. ``Cache.store``'s ``expires`` parameter is documented as a relative duration in seconds, so the envelope ``_expires`` was being written as ``now + (now + token_expire)`` -- roughly year 4090. Replace the fallback with one that consults the ``_expires`` envelope ``Cache.store`` writes (entries with no envelope have no cache-level expiry and are left alone), and pass the relative ``token_expire`` duration from ``mk_token``. Adds regression coverage at both the cache-driver and ``LoadAuth`` layers. Fixes saltstack#69307
sujitdb
reviewed
Jun 19, 2026
| - Improved documentation for the `runas` and `password` parameters in `cmd.run`, `cmd.script`, and all `salt.modules.cmdmod` execution functions on Windows. The docs now accurately describe when a password is required: only when the salt-minion is **not** running as SYSTEM or as an elevated Administrator. Removed the inaccurate claim that the target user account must be in the Administrators group. Also changed `cmd.script` to log a warning instead of hard-failing when `runas` is used without a password on Windows, since a password is not always required. [#57951](https://github.com/saltstack/salt/issues/57951) | ||
| - Fixed `SSL: DECRYPTION_FAILED_OR_BAD_RECORD_MAC` errors in the VMware cloud driver by reconnecting when a cached vCenter service instance is found to be stale or corrupted (for example when inherited across a fork by salt-cloud's parallel provider queries). [#61983](https://github.com/saltstack/salt/issues/61983) | ||
| - Fixed event signature verification failing under ``minion_sign_messages``. The minion was signing the return load before ``salt.channel.client.AsyncReqChannel._package_load`` attached transport metadata (``nonce``, ``ts``, ``tok``, ``id``), so the bytes the master re-serialized to verify did not match what was signed and every signed return was dropped. Signing is now performed inside ``_package_load`` after the metadata is attached, against the same bytes the master verifies. [#68181](https://github.com/saltstack/salt/issues/68181) | ||
| - Fixed two distinct bugs in the `salt.engines.redis_sentinel` engine that [#69031](https://github.com/saltstack/salt/issues/69031) |
Collaborator
There was a problem hiding this comment.
We had the feedback about this showing multiple commits together
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.
No description provided.