Merge forward 3006.x into 3007.x - #69880
Open
dwoz wants to merge 113 commits into
Open
Conversation
Two bugs kept the Sync .lock files job from running for 3006.x PRs, leaving lock files stale: - on.pull_request.branches omitted 3006.x (it only listed master and 3006.x), so the workflow never triggered for PRs targeting 3006.x. Add all four release branches. - The actor guard only matched 'dependabot', so it skipped whenever the salt-pr-bot rebase bot re-pushed a branch. Also fire for salt-pr-bot.
…c-fix-3006.x Fix dependabot lock-sync workflow triggering on 3006.x
state.orchestrate overwrites __opts__["user"] with __user__ (the publishing user, salt.utils.user.get_specific_user(), which returns "sudo_<login>" when salt-run was launched under sudo). The post-saltstack#67716 privilege-drop path in saltutil.runner/saltutil.wheel reads that value as the runas target and asks chugid to switch to it, which then raises KeyError from pwd.getpwnam wrapped in CommandExecutionError: Failed to run 'cache.grains' as user 'sudo_alice': KeyError: "getpwnam(): name not found: 'sudo_alice'" Validate the candidate against the passwd database in _master_user_runas and skip the privilege drop when it does not resolve to a real account, falling back to historical in-process behavior. Fixes saltstack#69600
SerializerExtension.load_yaml only guarded against a YAMLError whose problem_mark is absent. PyYAML's libyaml (C) loader populates problem_mark but leaves its buffer as None, so load_yaml took the else branch and passed buffer=None into salt.utils.stringutils.get_context(), which crashed with "AttributeError: 'NoneType' object has no attribute 'splitlines'" instead of raising the intended TemplateRuntimeError. Fall back to the stringified exception when the buffer is missing, and add a regression test. Fixes saltstack#69533
* Fix onchanges requisites hard-failing when their target fails
A failed onchanges/onchanges_any target was classified the same as a
failed require/watch target, causing the dependent state to hard-fail
instead of being skipped with result=True per the documented truth
table. Also relocates test_slots_documented.py so its `state` fixture
can resolve, and adds a regression test locking in prereq's already
correct skip-on-failed-target behavior.
* Fix inconsistent heading levels in highstate.rst breaking docs build
The "Highstate Output" section's eight subsections (state_output,
state_verbose, state_output_diff, state_output_pct, state_output_profile,
state_tabular, state_compress_ids, Choosing a mode) used "~" underlines,
which docutils resolves to heading level 4 since "~" had not appeared
earlier in the document. Their parent section is level 2 ("="), so this
skipped level 3 entirely, and Sphinx's man-page build (which runs with
-W, treating warnings as errors) failed with eight "Inconsistent title
style: skip from level 2 to 4" errors, breaking the "Generate MAN Pages"
CI job.
Change the eight subsection underlines from "~" to "-", matching the
level-3 convention already used by every other subsection in this file
(e.g. "Top file", "Include declaration"), restoring a consistent
level 1/2/3 hierarchy with no skipped level.
* Fix undefined :ref: label 'beacon' in standalone_minion.rst
The tutorial referenced :ref:`beacons <beacon>`, but no label named
"beacon" exists; the beacons index page defines the label "beacons"
(doc/topics/beacons/index.rst:1), matching how every other doc page
links to it (e.g. doc/topics/development/modules/index.rst:181). The
typo tripped Sphinx's -W (warnings-as-errors) html build with
"WARNING: undefined label: 'beacon' [ref.ref]".
* Fix IndexError in State.__eval_slot for non-dotted accessor
When a slot expression has no dotted post-`)` accessor but has trailing
whitespace, `return_get` was a truthy non-empty string that entered the
dict-traversal branch and crashed on `split(".", 1)[1]`. Guard the
branch on `.` being present instead.
Also strip surrounding matching quotes from `~`-appended text so that
documented examples like `~ "/suffix"` produce `/suffix`, not
`"/suffix"`.
Fixes saltstack#69661
* Replace macos-14 arm64 runner with macos-15
macos-14 begins deprecation on 2026-07-06 and is unsupported after
2026-11-02 per actions/runner-images#13518
Ref: actions/runner-images#13518
* Fix Windows slot documented tests dropping path backslashes
The two tests in tests/pytests/functional/states/test_slots_documented.py
embed a tmp_path directly into the SLS source, e.g.::
- name: __slot__:salt:test.echo(D:\a\_temp\...\slots_marker_arg)
State.__eval_slot dispatches the ``test.echo(...)`` call through
salt.utils.args.parse_function, which is built on top of
``shlex.shlex(posix=True)``. In POSIX mode shlex treats a backslash as a
generic escape character, so on Windows every backslash in the path was
consumed and the slot resolved to
``D:a_temppytest-of-...slots_marker_arg`` -- a relative path -- so
file.managed rejected it with "not an absolute path" and the assertion
that the marker file was created failed.
Format the paths through ``PurePath.as_posix()`` before splicing them
into the SLS. Windows accepts forward-slash separators for filesystem
paths, and shlex leaves ``/`` untouched, so the slot now resolves to the
same path the assertion checks. Behavior on Linux is unchanged (already
forward slashes).
---------
Co-authored-by: Daniel A. Wozniak <daniel.wozniak@broadcom.com>
* gitfs walkthrough: drop EOL Ubuntu 14/Debian Wheezy/CentOS 7.3 notes and pin pygit2>=1.13.1, GitPython>=3.1.50 (matches base.txt + CI lockfiles). Adds a GitLab subsection covering deploy tokens, project access tokens, PATs, and SSH deploy keys. * git_pillar docstring: enumerate supported remote URL forms (https://, ssh://, scp-style user@host:path, file://). The scp-style colon is the most common source of 'Failed to resolve address' errors. * s3fs docstring: document s3.location / s3.service_url / s3.https_enable / s3.path_style / s3.verify_ssl with a Regional endpoints section, citing the SigV4 redirect failure mode. * file_roots.rst: new section explaining why /srv/salt is the default. Update netconfig/napalm_network examples to use /srv/salt instead of /etc/salt/states so the example matches the recommendation. * New tests: tests/pytests/functional/fileserver/gitfs/ test_documented_providers.py and tests/pytests/unit/fileserver/test_s3fs_documented_options.py pin the docs to the loader. Closes saltstack#62260 Closes saltstack#56127 Closes saltstack#60809 Closes saltstack#60408 Closes saltstack#53746
…th tomllib) (saltstack#69607) (saltstack#69608) * Fix pkg.list_holds returning empty on dnf5 (onedir lacks 'toml') _list_holds_dnf5 parsed /etc/dnf/versionlock.toml via salt.serializers.tomlmod, which depends on the third-party 'toml' library. 'toml' is a CI-only dependency and is not bundled in the onedir packages, and the onedir ships Python 3.10 (no stdlib tomllib), so the parse failed silently and pkg.list_holds always returned []. With hold: True this made pkg.installed re-hold packages on every run. Parse with the standard-library tomllib (available once the onedir ships Python 3.11 in 3006.27, see saltstack#69526), falling back to the toml serializer on older interpreters where it is installed. Fixes saltstack#69607 * Add unit tests for yumpkg.version_cmp, group_diff, and list_repos Expand test coverage of salt/modules/yumpkg.py beyond the saltstack#69607 change, per the contributor policy of improving coverage in modules a PR touches: - version_cmp: assert it delegates to lowpkg.version_cmp with ignore_epoch - group_diff: assert group members are split into installed/not-installed - list_repos: assert .repo files are parsed, non-repo files skipped, and each repo records its source file
…ck#68961) * Use unique Docker container name for vault functional tests salt_factories.get_container used the fixed name "vault", which causes Docker 409 conflicts when a stale container remains (failed teardown, pytest --lf reruns, or runner reuse). Use random_string("vault-") like other CI container fixtures. Fixes nightly functional failures creating the vault test container. Made-with: Cursor * Add changelog for vault Docker container name fix --------- Co-authored-by: Daniel A. Wozniak <daniel.wozniak@broadcom.com>
* Fix chocolatey.installed forcing reinstall chocolatey.installed compared variables which are not the same type this behaviour causes chocolatey force package reinstall even when the target version is the same as current. * Add changelog * Add changelog content * Update changelog for chocolatey.installed fix * Add regression test for chocolatey.installed forcing reinstall (saltstack#68827) --------- Co-authored-by: AWRZN038 <filip.klocan@raiffeiseninformatik.sk> Co-authored-by: Daniel A. Wozniak <dwozniak@broadcom.com>
…altstack#69043) prep_jid() and get_jids() call salt.utils.jid.gen_jid() and salt.utils.jid.format_jid_instance() respectively, but the module removed `import salt.utils.jid` in 3006.x. Both calls work today only because salt.utils.args (transitively pulled in via salt.utils.data) imports salt.utils.jid as a side effect. Any refactor of that import chain silently breaks pgjsonb with: AttributeError: module 'salt.utils' has no attribute 'jid' prep_jid() in particular is called from master.py:_prep_jid() on every job publish, where the caller only handles KeyError/TypeError, so an AttributeError there would prevent the master from publishing jobs. Restore the explicit `import salt.utils.jid` and add behavioural unit tests for prep_jid() and get_jids() (none existed before): jid format, passed_jid pass-through, and end-to-end formatting of jids-table rows through the real salt.utils.jid.format_jid_instance(). Refs: saltstack#69042 Co-authored-by: co-cy <rzyw2xsfzm@privaterelay.appleid.com>
…saltstack#69049) `salt.returners.pgjsonb` had eight error-handling sites in `_get_serv`, `_purge_jobs` and `_archive_jobs` that wrote `psycopg2.DatabaseError` messages directly to `sys.stderr` and re-raised: except psycopg2.DatabaseError as err: error = err.args sys.stderr.write(str(error)) cursor.execute("ROLLBACK") raise err On a daemonized master `sys.stderr` is captured by systemd's journal (or worse, /dev/null), bypassing the configured `log_file` / `log_level_logfile` and syslog. Operators that scrape Salt's log file never see these errors, even though the rest of the file already uses `log.error` (e.g. `clean_old_jobs`). The local `error = err.args` assignment is dead -- only `str(err.args)` is written, then the variable is unused. Also drop `import sys`, which becomes unused after the migration. Replace each call with `log.exception(...)` carrying a description of the operation that failed, so the traceback is preserved in the log. Behaviour (rollback, re-raise) is unchanged. The asymmetric `except Exception` block on `_archive_jobs` jids-insert is updated to the same pattern but kept in place (its scope is PR-7, not this PR). Add three behavioural tests with `caplog`: one each for `_get_serv`, `_purge_jobs` and `_archive_jobs` confirming the error reaches Salt's logger, the transaction is rolled back, and the exception propagates. Refs: saltstack#69048 Co-authored-by: co-cy <rzyw2xsfzm@privaterelay.appleid.com>
…altstack#69679) (saltstack#69681) * Let virtualenv.create build stdlib venvs with a specific interpreter virtualenv.create's venv path always ran the venv module through sys.executable, which on a onedir minion is Salt's private relenv interpreter, and it rejected the python argument outright. That left no way to build an environment for a distro interpreter on systems whose virtualenv binary is too old to target one (EL8 ships virtualenv 15.1.0 bound to python 3.6 while 3.9/3.11/3.12 are installable alongside). Honour python on the venv path by running '<python> -m venv', accept a python interpreter directly as venv_bin, and pass prompt through to venv (supported since Python 3.6) instead of rejecting it. The virtualenv-binary path is unchanged, and venv_bin=venv without python keeps using sys.executable. Partially created environments are now removed when the creation command fails, so a failed '<python> -m venv' (e.g. target interpreter without ensurepip) no longer leaves a bin/python behind that the virtualenv.managed state mistakes for a working environment. The obsolete easy_install/ez_setup bootstrap is skipped for venv-module environments, where ensurepip already provides pip. The state module already forwarded python; its docs are updated to match. The legacy unit test file is migrated to the pytest suite with coverage for the new paths, and functional tests exercise the venv module end to end. Verified on AlmaLinux 8/9/10, Debian 11/12/13 and Ubuntu 22.04/24.04/26.04 containers, including cross-interpreter creation (3.11 minion python building 3.9/3.12/3.14 environments). Fixes saltstack#69679 * Skip the stdlib-venv functional tests when ensurepip is unavailable python -m venv bootstraps pip through ensurepip, which is stripped from the salt onedir/relenv interpreter the CI runners use, so the four venv-module tests failed with retcode 1 there. Skip them unless the interpreter has a working ensurepip; they still exercise the code path under any normal interpreter (verified across AlmaLinux/Debian/Ubuntu).
The forked child added in saltstack#69240 to run saltutil.runner/saltutil.wheel as the master's configured user had three robustness problems, all on the drop path (root process, master configured as a different real user): - daemon=True stopped runners/wheels that spawn their own processes from working (e.g. an orchestration containing a parallel:True state), with "daemonic processes are not allowed to have children" - queue.get() had no timeout and the child's liveness was never checked, so a child that died before returning a result (OOM kill, os._exit, a segfault in a C extension such as libgit2) hung the caller forever - every child exception was flattened to CommandExecutionError, so the drop path diverged from the in-process path -- in particular wheel()'s "except SaltInvocationError" could never fire Run the child non-daemonic and joined; poll the queue and the child's liveness so a dead child raises instead of hanging; guard the queue against unpicklable payloads; and re-raise the child's original exception type where possible.
…#66793) (saltstack#69537) When fileserver.update is invoked through saltutil.runner or an orchestration, the runner client injects publisher metadata into the runner function's kwargs as __pub_* keys (via load_args_and_kwargs). fileserver.update forwarded those kwargs verbatim to the fileserver backends, whose update() signatures (e.g. roots.update(), gitfs.update(remotes=None)) reject unknown keyword arguments, raising: Passed invalid arguments: update() got an unexpected keyword argument '__pub_user' Strip the __pub_* publisher metadata with salt.utils.args.clean_kwargs before forwarding to the backends. This keeps the runner-job user attribution added in saltstack#63148 intact (it is applied upstream in the runner client, not via these kwargs).
`_get_serv` calls `psycopg2.connect()` without `connect_timeout`. When the database is reachable on the network but does not respond (stalled standby, firewall drop, HAProxy mid-failover), the connect call blocks for tens of seconds on the system TCP timeout. Since `event_return` and `clean_old_jobs` both run inside the master event loop, one such stalled connect cascades into delayed events and returners across the whole master. Add `returner.pgjsonb.connect_timeout` (seconds) -- forwarded to `psycopg2.connect(connect_timeout=...)` only when set. Behaviour for existing deployments is unchanged: the kwarg is omitted by default, so libpq's default applies. Operators that need a hard cap opt in explicitly via master config or `--return_kwargs`. `_get_options` now also coerces a string-valued timeout (which can arrive via pillar / environment) to int, mirroring the existing treatment of `port`. Add three behavioural tests: - `test__get_serv_omits_connect_timeout_when_not_configured` pins the backwards-compatible default. - `test__get_serv_passes_connect_timeout_when_configured` verifies the kwarg reaches `psycopg2.connect`. - `test__get_options_coerces_string_connect_timeout_to_int` covers the type-coercion path. Refs: saltstack#69050 Co-authored-by: co-cy <rzyw2xsfzm@privaterelay.appleid.com>
…69616) (saltstack#69617) etcd_cache.ls() recursed through the whole bank subtree and returned the flattened leaf key names instead of the bank's immediate children. The minion data cache stores each minion under minions/<minion_id>, so cache.list("minions") returned ['data', 'mine', ...] instead of the minion IDs, and grain (-G), pillar, range, and compound targeting matched no minions with cache: etcd. Return only the immediate children, matching localfs and the other cache backends. Remove _walk(); fold its empty-folder self-reference guard (saltstack#57377) into ls().
- test_master.py: convert async publish tests to async def + await (ClearFuncs.publish is async on 3007.x+, was sync on 3006.x) - test_crypt.py::test_authenticate_missing_creds_attribute_67947: adopt the 3007.x gen_keys(keysize) signature + write PEMs to disk, and add keys.cache_driver to opts - test_jinja_custom_filters.py::test_regex_search/match_no_group: update expected value to match 3007.x's intentional filter change (ff28cd0, ungrouped matches return (match_str,) not ()) - test_client.py::test_do_transfer_serialized_by_lock: construct the Future() inside the coroutine (unbundled tornado requires a running loop) - test_cloud.py::test_vm_config_merger_with_overrides: wrap the overrides payload as {name: {...}} to match Cloud.vm_config's per-VM keying on 3007.x - salt/cluster/consensus/raft/scheduler.py: nudge colliding timeouts by 1e-9 s to prevent dict-key collision when two nodes' random follower_timeouts happen to land on the same millisecond (fixes pre-existing flake exposed by test_cluster_log_entry)
- rest_tornado/conftest.py app_mock: add __role=master (salt.key.get_key now instantiated on 3007.x+ via CkMinions rejects empty __role with ValueError). - test_documented_providers.py base_opts: add gitfs_proxy and gitfs_depth to satisfy PER_REMOTE_OVERRIDES on 3007.x (init_remotes hits failhard when either is missing from global opts).
twangboy
requested changes
Jul 27, 2026
Removes changelog entries whose fixes target files that no longer exist after the initial purge of community extensions (dc526dc) and the removal of the vendored tornado tree: Vendored tornado (salt/ext/tornado/ purged): - 69845: CVE-2026-49853 SimpleAsyncHTTPClient redirect header stripping - 69848: CVE-2026-49855 _GzipMessageDelegate gzip bomb protection Extension purge (files no longer in tree): - 52220: keystone_role_grant state - 54122: grafana4_datasource state - 55143: DigitalOcean cloud driver - 60408: s3fs fileserver docs - 61082: poudriere module - 63051: dockercompose module (python_on_whales backend) - 65233: metadata grain - 68961: vault functional test container - 69529: s3fs fileserver race
twangboy
approved these changes
Jul 28, 2026
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.