Script 'mail_helper' called by obssrc
Hello community,

here is the log from the commit of package ansible-core for openSUSE:Factory 
checked in at 2026-06-19 16:37:16
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Comparing /work/SRC/openSUSE:Factory/ansible-core (Old)
 and      /work/SRC/openSUSE:Factory/.ansible-core.new.1956 (New)
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

Package is "ansible-core"

Fri Jun 19 16:37:16 2026 rev:61 rq:1360464 version:2.21.1

Changes:
--------
--- /work/SRC/openSUSE:Factory/ansible-core/ansible-core.changes        
2026-06-12 19:27:55.123180618 +0200
+++ /work/SRC/openSUSE:Factory/.ansible-core.new.1956/ansible-core.changes      
2026-06-19 17:12:22.691488324 +0200
@@ -1,0 +2,34 @@
+Fri Jun 19 05:28:06 UTC 2026 - Johannes Kastl 
<[email protected]>
+
+- update to 2.21.1:
+  * Security Fixes
+    - ansible-galaxy install - Ensure role requirements are passed
+      as positional arguments to :command:`git clone`. Previously,
+      a malicious role author could inject arbitrary git
+      configuration in role dependencies. (CVE-2026-11332)
+    - psrp - Do not log raw stdout/stderr on verbosity 5 when task
+      has no_log: true set
+    - winrm - Do not log raw stdout/stderr on verbosity 5 when task
+      has no_log: true set
+  * Bugfixes
+    - cli - handle empty value for PAGER (#86898).
+    - config - use correct key value for inject_invocation setting
+      (#86999).
+    - free strategy - Fix IndexError when hosts become unreachable
+      during playbook execution (#87027).
+    - meta pseudo-action - Fixed callback args passed to
+      v2_runner_on_skipped when any meta action was skipped by a
+      when condition; added test coverage. A previous regression
+      caused the callback dispatch to be omitted and a warning
+      issued.
+    - module_utils sanitize_keys and remove_value functions now
+      sort their input to ensure matching subsets are always
+      obscured.
+    - module_utils/basic.py - Fix AnsibleModule.run_command() to
+      handle None return from non-blocking pipe reads (#86920).
+    - wait_for - use errno.ENOENT symbolic constant instead of
+      hardcoded value for improved code portability.
+- remove patch ansible-core-CVE-2026-11332.patch as this is
+  included in the release
+
+-------------------------------------------------------------------

Old:
----
  ansible-core-CVE-2026-11332.patch
  ansible_core-2.21.0.tar.gz
  ansible_core-2.21.0.tar.gz.sha256

New:
----
  ansible_core-2.21.1.tar.gz
  ansible_core-2.21.1.tar.gz.sha256

----------(Old B)----------
  Old:      hardcoded value for improved code portability.
- remove patch ansible-core-CVE-2026-11332.patch as this is
  included in the release
----------(Old E)----------

++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

Other differences:
------------------
++++++ ansible-core.spec ++++++
--- /var/tmp/diff_new_pack.Ms3d65/_old  2026-06-19 17:12:24.655555367 +0200
+++ /var/tmp/diff_new_pack.Ms3d65/_new  2026-06-19 17:12:24.655555367 +0200
@@ -43,15 +43,13 @@
 %endif
 
 Name:           ansible-core
-Version:        2.21.0
+Version:        2.21.1
 Release:        0
 Summary:        Radically simple IT automation
 License:        GPL-3.0-or-later
 URL:            https://ansible.com/
 Source0:        
https://files.pythonhosted.org/packages/source/a/ansible-core/ansible_core-%{version}.tar.gz#/ansible_core-%{version}.tar.gz
 Source1:        ansible_core-%{version}.tar.gz.sha256
-# CVE-2026-11332 (bsc#1267822): argument injection in ansible-galaxy role 
install
-Patch0:         ansible-core-CVE-2026-11332.patch
 BuildArch:      noarch
 
 # cannot be installed with ansible < 3 or ansible-base

++++++ ansible_core-2.21.0.tar.gz -> ansible_core-2.21.1.tar.gz ++++++
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/ansible_core-2.21.0/PKG-INFO 
new/ansible_core-2.21.1/PKG-INFO
--- old/ansible_core-2.21.0/PKG-INFO    2026-05-18 21:18:02.000000000 +0200
+++ new/ansible_core-2.21.1/PKG-INFO    2026-06-18 21:33:01.000000000 +0200
@@ -1,6 +1,6 @@
 Metadata-Version: 2.4
 Name: ansible-core
-Version: 2.21.0
+Version: 2.21.1
 Summary: Radically simple IT automation
 Author: Ansible Project
 License-Expression: GPL-3.0-or-later
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/ansible_core-2.21.0/ansible_core.egg-info/PKG-INFO 
new/ansible_core-2.21.1/ansible_core.egg-info/PKG-INFO
--- old/ansible_core-2.21.0/ansible_core.egg-info/PKG-INFO      2026-05-18 
21:18:02.000000000 +0200
+++ new/ansible_core-2.21.1/ansible_core.egg-info/PKG-INFO      2026-06-18 
21:33:01.000000000 +0200
@@ -1,6 +1,6 @@
 Metadata-Version: 2.4
 Name: ansible-core
-Version: 2.21.0
+Version: 2.21.1
 Summary: Radically simple IT automation
 Author: Ansible Project
 License-Expression: GPL-3.0-or-later
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' 
old/ansible_core-2.21.0/ansible_core.egg-info/SOURCES.txt 
new/ansible_core-2.21.1/ansible_core.egg-info/SOURCES.txt
--- old/ansible_core-2.21.0/ansible_core.egg-info/SOURCES.txt   2026-05-18 
21:18:02.000000000 +0200
+++ new/ansible_core-2.21.1/ansible_core.egg-info/SOURCES.txt   2026-06-18 
21:33:01.000000000 +0200
@@ -1048,6 +1048,7 @@
 
test/integration/targets/ansible-galaxy-role/files/safe-symlinks/tasks/utils/suite.yml
 test/integration/targets/ansible-galaxy-role/meta/main.yml
 test/integration/targets/ansible-galaxy-role/tasks/dir-traversal.yml
+test/integration/targets/ansible-galaxy-role/tasks/git-config-injection.yml
 test/integration/targets/ansible-galaxy-role/tasks/main.yml
 test/integration/targets/ansible-galaxy-role/tasks/valid-role-symlinks.yml
 test/integration/targets/ansible-galaxy/files/testserver.py
@@ -3411,6 +3412,7 @@
 test/integration/targets/no_log/no_log_suboptions_invalid.yml
 test/integration/targets/no_log/runme.sh
 test/integration/targets/no_log/secretvars.yml
+test/integration/targets/no_log/sub_masking.yml
 test/integration/targets/no_log/action_plugins/action_sets_no_log.py
 test/integration/targets/no_log/library/module.py
 test/integration/targets/noexec/aliases
@@ -3982,6 +3984,8 @@
 test/integration/targets/strategy-external/runme.sh
 
test/integration/targets/strategy-external/ansible_collections/ns/col/plugins/strategy/external.py
 test/integration/targets/strategy_free/aliases
+test/integration/targets/strategy_free/free_hosts
+test/integration/targets/strategy_free/free_index_error.yml
 test/integration/targets/strategy_free/inventory
 test/integration/targets/strategy_free/last_include_tasks.yml
 test/integration/targets/strategy_free/runme.sh
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/ansible_core-2.21.0/changelogs/CHANGELOG-v2.21.rst 
new/ansible_core-2.21.1/changelogs/CHANGELOG-v2.21.rst
--- old/ansible_core-2.21.0/changelogs/CHANGELOG-v2.21.rst      2026-05-18 
21:18:02.000000000 +0200
+++ new/ansible_core-2.21.1/changelogs/CHANGELOG-v2.21.rst      2026-06-18 
21:33:01.000000000 +0200
@@ -4,6 +4,33 @@
 
 .. contents:: Topics
 
+v2.21.1
+=======
+
+Release Summary
+---------------
+
+| Release Date: 2026-06-18
+| `Porting Guide 
<https://docs.ansible.com/ansible-core/2.21/porting_guides/porting_guide_core_2.21.html>`__
+
+Security Fixes
+--------------
+
+- ansible-galaxy install - Ensure role requirements are passed as positional 
arguments to :command:`git clone`. Previously, a malicious role author could 
inject arbitrary git configuration in role dependencies. (CVE-2026-11332)
+- psrp - Do not log raw stdout/stderr on verbosity 5 when task has ``no_log: 
true`` set
+- winrm - Do not log raw stdout/stderr on verbosity 5 when task has ``no_log: 
true`` set
+
+Bugfixes
+--------
+
+- cli - handle empty value for PAGER 
(https://github.com/ansible/ansible/issues/86898).
+- config - use correct key value for inject_invocation setting 
(https://github.com/ansible/ansible/issues/86999).
+- free strategy - Fix ``IndexError`` when hosts become unreachable during 
playbook execution (https://github.com/ansible/ansible/issues/87027).
+- meta pseudo-action - Fixed callback args passed to ``v2_runner_on_skipped`` 
when any ``meta`` action was skipped by a ``when`` condition; added test 
coverage. A previous regression caused the callback dispatch to be omitted and 
a warning issued.
+- module_utils sanitize_keys and remove_value functions now sort their input 
to ensure matching subsets are always obscured.
+- module_utils/basic.py - Fix ``AnsibleModule.run_command()`` to handle 
``None`` return from non-blocking pipe reads 
(https://github.com/ansible/ansible/issues/86920).
+- wait_for - use ``errno.ENOENT`` symbolic constant instead of hardcoded value 
for improved code portability.
+
 v2.21.0
 =======
 
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/ansible_core-2.21.0/changelogs/changelog.yaml 
new/ansible_core-2.21.1/changelogs/changelog.yaml
--- old/ansible_core-2.21.0/changelogs/changelog.yaml   2026-05-18 
21:18:02.000000000 +0200
+++ new/ansible_core-2.21.1/changelogs/changelog.yaml   2026-06-18 
21:33:01.000000000 +0200
@@ -638,3 +638,57 @@
     - 2.21.0rc1_summary.yaml
     - 77691-git-track-submodules-branch.yml
     release_date: '2026-04-28'
+  2.21.1:
+    changes:
+      release_summary: '| Release Date: 2026-06-18
+
+        | `Porting Guide 
<https://docs.ansible.com/ansible-core/2.21/porting_guides/porting_guide_core_2.21.html>`__
+
+        '
+    codename: The Rain Song
+    fragments:
+    - 2.21.1_summary.yaml
+    release_date: '2026-06-18'
+  2.21.1rc1:
+    changes:
+      bugfixes:
+      - cli - handle empty value for PAGER 
(https://github.com/ansible/ansible/issues/86898).
+      - config - use correct key value for inject_invocation setting 
(https://github.com/ansible/ansible/issues/86999).
+      - free strategy - Fix ``IndexError`` when hosts become unreachable 
during playbook
+        execution (https://github.com/ansible/ansible/issues/87027).
+      - meta pseudo-action - Fixed callback args passed to 
``v2_runner_on_skipped``
+        when any ``meta`` action was skipped by a ``when`` condition; added 
test coverage.
+        A previous regression caused the callback dispatch to be omitted and a 
warning
+        issued.
+      - module_utils sanitize_keys and remove_value functions now sort their 
input
+        to ensure matching subsets are always obscured.
+      - module_utils/basic.py - Fix ``AnsibleModule.run_command()`` to handle 
``None``
+        return from non-blocking pipe reads 
(https://github.com/ansible/ansible/issues/86920).
+      - wait_for - use ``errno.ENOENT`` symbolic constant instead of hardcoded 
value
+        for improved code portability.
+      release_summary: '| Release Date: 2026-06-11
+
+        | `Porting Guide 
<https://docs.ansible.com/ansible-core/2.21/porting_guides/porting_guide_core_2.21.html>`__
+
+        '
+      security_fixes:
+      - ansible-galaxy install - Ensure role requirements are passed as 
positional
+        arguments to :command:`git clone`. Previously, a malicious role author 
could
+        inject arbitrary git configuration in role dependencies. 
(CVE-2026-11332)
+      - 'psrp - Do not log raw stdout/stderr on verbosity 5 when task has 
``no_log:
+        true`` set'
+      - 'winrm - Do not log raw stdout/stderr on verbosity 5 when task has 
``no_log:
+        true`` set'
+    codename: The Rain Song
+    fragments:
+    - 2.21.1rc1_summary.yaml
+    - 86920-fix-run-command-none-read.yml
+    - 87027-free-strategy-indexerror.yml
+    - 87087-wait_for-errno-constant.yml
+    - fix-cloning-malformed-role-requirements.yml
+    - inject_invocation.yml
+    - meta_skipped_callback_args.yml
+    - pager.yml
+    - sort_obfuscation.yml
+    - winrm-psrp-nolog.yml
+    release_date: '2026-06-11'
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/ansible_core-2.21.0/lib/ansible/cli/__init__.py 
new/ansible_core-2.21.1/lib/ansible/cli/__init__.py
--- old/ansible_core-2.21.0/lib/ansible/cli/__init__.py 2026-05-18 
21:18:02.000000000 +0200
+++ new/ansible_core-2.21.1/lib/ansible/cli/__init__.py 2026-06-18 
21:33:01.000000000 +0200
@@ -514,17 +514,19 @@
             p = subprocess.Popen('less --version', shell=True, 
stdout=subprocess.PIPE, stderr=subprocess.PIPE)
             p.communicate()
             if p.returncode == 0:
-                CLI.pager_pipe(text, 'less')
+                CLI.pager_pipe(text, pager='less')
             else:
                 display.display(text, screen_only=True)
 
     @staticmethod
-    def pager_pipe(text):
+    def pager_pipe(text, pager=None):
         """ pipe text through a pager """
-        if 'less' in CLI.PAGER:
+        pager_cmd = pager or CLI.PAGER
+
+        if 'less' in pager_cmd:
             os.environ['LESS'] = CLI.LESS_OPTS
         try:
-            cmd = subprocess.Popen(CLI.PAGER, shell=True, 
stdin=subprocess.PIPE, stdout=sys.stdout)
+            cmd = subprocess.Popen(pager_cmd, shell=True, 
stdin=subprocess.PIPE, stdout=sys.stdout)
             cmd.communicate(input=to_bytes(text))
         except (OSError, KeyboardInterrupt):
             pass
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/ansible_core-2.21.0/lib/ansible/config/base.yml 
new/ansible_core-2.21.1/lib/ansible/config/base.yml
--- old/ansible_core-2.21.0/lib/ansible/config/base.yml 2026-05-18 
21:18:02.000000000 +0200
+++ new/ansible_core-2.21.1/lib/ansible/config/base.yml 2026-06-18 
21:33:01.000000000 +0200
@@ -1677,7 +1677,7 @@
   env:
     - name: ANSIBLE_INJECT_INVOCATION
   ini:
-    - key: interpreter_python
+    - key: inject_invocation
       section: defaults
   vars:
     - name: ansible_inject_invocation
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' 
old/ansible_core-2.21.0/lib/ansible/module_utils/ansible_release.py 
new/ansible_core-2.21.1/lib/ansible/module_utils/ansible_release.py
--- old/ansible_core-2.21.0/lib/ansible/module_utils/ansible_release.py 
2026-05-18 21:18:02.000000000 +0200
+++ new/ansible_core-2.21.1/lib/ansible/module_utils/ansible_release.py 
2026-06-18 21:33:01.000000000 +0200
@@ -17,6 +17,6 @@
 
 from __future__ import annotations
 
-__version__ = '2.21.0'
+__version__ = '2.21.1'
 __author__ = 'Ansible, Inc.'
 __codename__ = "The Rain Song"
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' 
old/ansible_core-2.21.0/lib/ansible/module_utils/basic.py 
new/ansible_core-2.21.1/lib/ansible/module_utils/basic.py
--- old/ansible_core-2.21.0/lib/ansible/module_utils/basic.py   2026-05-18 
21:18:02.000000000 +0200
+++ new/ansible_core-2.21.1/lib/ansible/module_utils/basic.py   2026-06-18 
21:33:01.000000000 +0200
@@ -2092,7 +2092,13 @@
                 stdout_changed = False
                 for key, event in events:
                     b_chunk = key.fileobj.read(32768)
-                    if not b_chunk and b_chunk is not None:
+                    if b_chunk is None:
+                        # Non-blocking read returned None (no data currently 
available).
+                        # This can happen with certain file-like objects or in 
edge cases.
+                        # Skip this chunk and try again on next select 
iteration.
+                        continue
+                    if not b_chunk:
+                        # Empty bytes received, EOF reached
                         selector.unregister(key.fileobj)
                     elif key.fileobj == cmd.stdout:
                         stdout += b_chunk
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' 
old/ansible_core-2.21.0/lib/ansible/module_utils/common/parameters.py 
new/ansible_core-2.21.1/lib/ansible/module_utils/common/parameters.py
--- old/ansible_core-2.21.0/lib/ansible/module_utils/common/parameters.py       
2026-05-18 21:18:02.000000000 +0200
+++ new/ansible_core-2.21.1/lib/ansible/module_utils/common/parameters.py       
2026-06-18 21:33:01.000000000 +0200
@@ -500,7 +500,7 @@
     return no_log_values
 
 
-def _sanitize_keys_conditions(value, no_log_strings, ignore_keys, 
deferred_removals):
+def _sanitize_keys_conditions(value, deferred_removals):
     """ Helper method to :func:`sanitize_keys` to build ``deferred_removals`` 
and avoid deep recursion. """
     if isinstance(value, (str, bytes)):
         return value
@@ -868,8 +868,9 @@
 
     deferred_removals = deque()
 
-    no_log_strings = [to_native(s, errors='surrogate_or_strict') for s in 
no_log_strings]
-    new_value = _sanitize_keys_conditions(obj, no_log_strings, ignore_keys, 
deferred_removals)
+    # sort ensuring we always handle longer strings vs subsets
+    no_log_strings = sorted([to_native(s, errors='surrogate_or_strict') for s 
in no_log_strings], key=len, reverse=True)
+    new_value = _sanitize_keys_conditions(obj, deferred_removals)
 
     while deferred_removals:
         old_data, new_data = deferred_removals.popleft()
@@ -877,15 +878,15 @@
         if isinstance(new_data, Mapping):
             for old_key, old_elem in old_data.items():
                 if old_key in ignore_keys or old_key.startswith('_ansible'):
-                    new_data[old_key] = _sanitize_keys_conditions(old_elem, 
no_log_strings, ignore_keys, deferred_removals)
+                    new_data[old_key] = _sanitize_keys_conditions(old_elem, 
deferred_removals)
                 else:
                     # Sanitize the old key. We take advantage of the 
sanitizing code in
                     # _remove_values_conditions() rather than recreating it 
here.
                     new_key = _remove_values_conditions(old_key, 
no_log_strings, None)
-                    new_data[new_key] = _sanitize_keys_conditions(old_elem, 
no_log_strings, ignore_keys, deferred_removals)
+                    new_data[new_key] = _sanitize_keys_conditions(old_elem, 
deferred_removals)
         else:
             for elem in old_data:
-                new_elem = _sanitize_keys_conditions(elem, no_log_strings, 
ignore_keys, deferred_removals)
+                new_elem = _sanitize_keys_conditions(elem, deferred_removals)
                 if isinstance(new_data, MutableSequence):
                     new_data.append(new_elem)
                 elif isinstance(new_data, MutableSet):
@@ -908,7 +909,8 @@
 
     deferred_removals = deque()
 
-    no_log_strings = [to_native(s, errors='surrogate_or_strict') for s in 
no_log_strings]
+    # sort ensuring we always handle longer strings vs subsets
+    no_log_strings = sorted([to_native(s, errors='surrogate_or_strict') for s 
in no_log_strings], key=len, reverse=True)
     new_value = _remove_values_conditions(value, no_log_strings, 
deferred_removals)
 
     while deferred_removals:
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/ansible_core-2.21.0/lib/ansible/modules/wait_for.py 
new/ansible_core-2.21.1/lib/ansible/modules/wait_for.py
--- old/ansible_core-2.21.0/lib/ansible/modules/wait_for.py     2026-05-18 
21:18:02.000000000 +0200
+++ new/ansible_core-2.21.1/lib/ansible/modules/wait_for.py     2026-06-18 
21:33:01.000000000 +0200
@@ -581,7 +581,7 @@
                     os.stat(b_path)
                 except OSError as e:
                     # If anything except file not present, throw an error
-                    if e.errno != 2:
+                    if e.errno != errno.ENOENT:
                         elapsed = datetime.now(timezone.utc) - start
                         module.fail_json(msg=msg or "Failed to stat %s, %s" % 
(path, e.strerror), elapsed=elapsed.seconds)
                     # file doesn't exist yet, so continue
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' 
old/ansible_core-2.21.0/lib/ansible/plugins/connection/psrp.py 
new/ansible_core-2.21.1/lib/ansible/plugins/connection/psrp.py
--- old/ansible_core-2.21.0/lib/ansible/plugins/connection/psrp.py      
2026-05-18 21:18:02.000000000 +0200
+++ new/ansible_core-2.21.1/lib/ansible/plugins/connection/psrp.py      
2026-06-18 21:33:01.000000000 +0200
@@ -776,9 +776,14 @@
             stderr_list += self.host.ui.stderr
         stderr = "".join([to_text(o) for o in stderr_list])
 
+        log_stdout = stdout
+        log_stderr = stderr
+        if self._play_context.no_log:
+            log_stdout = log_stderr = '<censored due to no log>'
+
         display.vvvvv("PSRP RC: %d" % rc, host=self._psrp_host)
-        display.vvvvv("PSRP STDOUT: %s" % stdout, host=self._psrp_host)
-        display.vvvvv("PSRP STDERR: %s" % stderr, host=self._psrp_host)
+        display.vvvvv(f"PSRP STDOUT: {log_stdout}", host=self._psrp_host)
+        display.vvvvv(f"PSRP STDERR: {log_stderr}", host=self._psrp_host)
 
         # reset the host back output back to defaults, needed if running
         # multiple pipelines on the same RunspacePool
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' 
old/ansible_core-2.21.0/lib/ansible/plugins/connection/winrm.py 
new/ansible_core-2.21.1/lib/ansible/plugins/connection/winrm.py
--- old/ansible_core-2.21.0/lib/ansible/plugins/connection/winrm.py     
2026-05-18 21:18:02.000000000 +0200
+++ new/ansible_core-2.21.1/lib/ansible/plugins/connection/winrm.py     
2026-06-18 21:33:01.000000000 +0200
@@ -634,11 +634,16 @@
             stdout = to_text(b_stdout)
             stderr = to_text(b_stderr)
 
+            log_stdout = stdout
+            log_stderr = stderr
+            if self._play_context.no_log:
+                log_stdout = log_stderr = '<censored due to no log>'
+
             if from_exec:
-                display.vvvvv('WINRM RESULT <Response code %d, out %r, err 
%r>' % (rc, stdout, stderr), host=self._winrm_host)
+                display.vvvvv(f'WINRM RESULT <Response code {rc}, out 
{log_stdout!r}, err {log_stderr!r}>', host=self._winrm_host)
             display.vvvvvv('WINRM RC %d' % rc, host=self._winrm_host)
-            display.vvvvvv('WINRM STDOUT %s' % stdout, host=self._winrm_host)
-            display.vvvvvv('WINRM STDERR %s' % stderr, host=self._winrm_host)
+            display.vvvvvv(f'WINRM STDOUT {log_stdout}', host=self._winrm_host)
+            display.vvvvvv(f'WINRM STDERR {log_stderr}', host=self._winrm_host)
 
             # This is done after logging so we can still see the raw stderr for
             # debugging purposes.
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' 
old/ansible_core-2.21.0/lib/ansible/plugins/strategy/__init__.py 
new/ansible_core-2.21.1/lib/ansible/plugins/strategy/__init__.py
--- old/ansible_core-2.21.0/lib/ansible/plugins/strategy/__init__.py    
2026-05-18 21:18:02.000000000 +0200
+++ new/ansible_core-2.21.1/lib/ansible/plugins/strategy/__init__.py    
2026-06-18 21:33:01.000000000 +0200
@@ -29,7 +29,6 @@
 import collections.abc as _c
 
 from collections import deque
-from sqlite3 import NotSupportedError
 
 from ansible import constants as C, constants
 from ansible import context
@@ -685,7 +684,7 @@
                                         for var_name, var_value in 
variables.items():
                                             
self._variable_manager.set_host_variable(target_host, var_name, var_value)
                                 case _:
-                                    raise NotSupportedError(f"Unsupported 
variable layer: {variable_layer}")
+                                    raise NotImplementedError(f"Unsupported 
variable layer: {variable_layer}")
 
                     if result_utr.stats is not None:
                         stats_data = result_utr.stats['data']
@@ -1017,10 +1016,12 @@
         else:
             display.vv(f"META: {header}")
 
+        htr = HostTaskResult(host=target_host, task=task, utr=utr)
+
         if skipped:
-            self._tqm.send_callback('v2_runner_on_skipped', target_host, task, 
utr)
+            self._tqm.send_callback('v2_runner_on_skipped', htr)
 
-        return [HostTaskResult(host=target_host, task=task, utr=utr)]
+        return [htr]
 
     def _get_cached_role(self, task, play):
         return play._get_cached_role(task._role)
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' 
old/ansible_core-2.21.0/lib/ansible/plugins/strategy/free.py 
new/ansible_core-2.21.1/lib/ansible/plugins/strategy/free.py
--- old/ansible_core-2.21.0/lib/ansible/plugins/strategy/free.py        
2026-05-18 21:18:02.000000000 +0200
+++ new/ansible_core-2.21.1/lib/ansible/plugins/strategy/free.py        
2026-06-18 21:33:01.000000000 +0200
@@ -92,6 +92,11 @@
                 result = False
                 break
 
+            # Reset last_host if it's out of bounds for the current hosts_left
+            # This can happen when hosts become unreachable between iterations
+            if last_host >= len(hosts_left):
+                last_host = 0
+
             work_to_do = False        # assume we have no more work to do
             starting_host = last_host  # save current position so we know when 
we've looped back around and need to break
 
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/ansible_core-2.21.0/lib/ansible/release.py 
new/ansible_core-2.21.1/lib/ansible/release.py
--- old/ansible_core-2.21.0/lib/ansible/release.py      2026-05-18 
21:18:02.000000000 +0200
+++ new/ansible_core-2.21.1/lib/ansible/release.py      2026-06-18 
21:33:01.000000000 +0200
@@ -17,6 +17,6 @@
 
 from __future__ import annotations
 
-__version__ = '2.21.0'
+__version__ = '2.21.1'
 __author__ = 'Ansible, Inc.'
 __codename__ = "The Rain Song"
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/ansible_core-2.21.0/lib/ansible/utils/galaxy.py 
new/ansible_core-2.21.1/lib/ansible/utils/galaxy.py
--- old/ansible_core-2.21.0/lib/ansible/utils/galaxy.py 2026-05-18 
21:18:02.000000000 +0200
+++ new/ansible_core-2.21.1/lib/ansible/utils/galaxy.py 2026-06-18 
21:33:01.000000000 +0200
@@ -72,7 +72,7 @@
         elif scm == 'hg':
             clone_cmd.append('--insecure')
 
-    clone_cmd.extend([src, name])
+    clone_cmd.extend(['--', src, name])
 
     run_scm_cmd(clone_cmd, tempdir)
 
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' 
old/ansible_core-2.21.0/test/integration/targets/ansible-doc/runme.sh 
new/ansible_core-2.21.1/test/integration/targets/ansible-doc/runme.sh
--- old/ansible_core-2.21.0/test/integration/targets/ansible-doc/runme.sh       
2026-05-18 21:18:02.000000000 +0200
+++ new/ansible_core-2.21.1/test/integration/targets/ansible-doc/runme.sh       
2026-06-18 21:33:01.000000000 +0200
@@ -59,6 +59,16 @@
 expected_out="$(sed '1 s/\(^> TEST testns\.testcol\.yolo\).*(.*)$/\1/' 
yolo-text.output)"
 test "$current_out" == "$expected_out"
 
+# PAGER is set to less by default, so we need to test with other pagers
+for pager in more cat; do
+    echo "testing with pager $pager"
+    PAGER=$pager ansible-doc --list testns.testcol --playbook-dir ./ 2>&1 | 
grep "${GREP_OPTS[@]}" -v "Invalid collection name"
+done
+
+# set pager to empty string
+echo "testing with pager empty"
+PAGER="" ansible-doc --list testns.testcol --playbook-dir ./ 2>&1 | grep 
"${GREP_OPTS[@]}" -v "Invalid collection name"
+
 # ensure we do work with valid collection name for list
 ansible-doc --list testns.testcol --playbook-dir ./ 2>&1 | grep -v "Invalid 
collection name"
 
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' 
old/ansible_core-2.21.0/test/integration/targets/ansible-galaxy-role/tasks/git-config-injection.yml
 
new/ansible_core-2.21.1/test/integration/targets/ansible-galaxy-role/tasks/git-config-injection.yml
--- 
old/ansible_core-2.21.0/test/integration/targets/ansible-galaxy-role/tasks/git-config-injection.yml
 1970-01-01 01:00:00.000000000 +0100
+++ 
new/ansible_core-2.21.1/test/integration/targets/ansible-galaxy-role/tasks/git-config-injection.yml
 2026-06-18 21:33:01.000000000 +0200
@@ -0,0 +1,52 @@
+- vars:
+    invalid_git_opts: '-ccore.sshCommand=sh -c "id > {{ remote_tmp_dir 
}}/role_exe"'
+    # use SSH protocol to test core.sshCommand is not configured
+    dummy_repo: [email protected]:ansible/nosuchrepo.git
+  block:
+    - name: Ensure git is installed
+      package:
+        name: git
+      when: ansible_distribution not in ["MacOSX", "Alpine"]
+      register: git_install
+
+    - name: Create invalid requirements file
+      copy:
+        dest: "{{ remote_tmp_dir }}/invalid-requirements.yml"
+        content: |
+          - src: {{ invalid_git_opts }}
+            scm: git
+            name: {{ dummy_repo }}
+          - src: {{ dummy_repo }}
+            scm: git
+            name: {{ invalid_git_opts }}
+
+    - name: Attempt to install invalid role requirements
+      command: ansible-galaxy install -r {{ remote_tmp_dir 
}}/invalid-requirements.yml --ignore-errors
+      register: result
+      environment:
+        ANSIBLE_NOCOLOR: True
+        ANSIBLE_FORCE_COLOR: False
+
+    - name: Validate git core.sshCommand did not run
+      stat:
+        path: "{{ remote_tmp_dir }}/role_exe"
+      register: stat_result
+      failed_when: stat_result.stat.exists
+
+    - name: Verify the invalid field is treated as a single positional 
argument (repo or dest)
+      assert:
+        that:
+          - stderr is search(error1)
+          - stderr is search(error2)
+          - (stderr | regex_findall("git clone") | length) == (stderr | 
regex_findall("git clone --") | length) == 2
+      vars:
+        stderr: "{{ result.stderr | regex_replace('\\n', ' ') }}"
+        error1: "repository '{{ invalid_git_opts }}' does not exist"
+        error2: "Cloning into '{{ invalid_git_opts }}'"
+
+  always:
+    - name: Uninstall git if it was installed
+      package:
+        name: git
+        state: absent
+      when: git_install is changed | default(false)
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' 
old/ansible_core-2.21.0/test/integration/targets/ansible-galaxy-role/tasks/main.yml
 
new/ansible_core-2.21.1/test/integration/targets/ansible-galaxy-role/tasks/main.yml
--- 
old/ansible_core-2.21.0/test/integration/targets/ansible-galaxy-role/tasks/main.yml
 2026-05-18 21:18:02.000000000 +0200
+++ 
new/ansible_core-2.21.1/test/integration/targets/ansible-galaxy-role/tasks/main.yml
 2026-06-18 21:33:01.000000000 +0200
@@ -70,3 +70,4 @@
 
 - import_tasks: dir-traversal.yml
 - import_tasks: valid-role-symlinks.yml
+- import_tasks: git-config-injection.yml
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' 
old/ansible_core-2.21.0/test/integration/targets/meta_tasks/runme.sh 
new/ansible_core-2.21.1/test/integration/targets/meta_tasks/runme.sh
--- old/ansible_core-2.21.0/test/integration/targets/meta_tasks/runme.sh        
2026-05-18 21:18:02.000000000 +0200
+++ new/ansible_core-2.21.1/test/integration/targets/meta_tasks/runme.sh        
2026-06-18 21:33:01.000000000 +0200
@@ -40,8 +40,10 @@
 
 # test end_play meta task
 for test_strategy in linear free; do
-  out="$(ansible-playbook test_end_play.yml -i inventory.yml -e 
test_strategy=$test_strategy -vv "$@")"
+  # $@ omitted to avoid additional verbosity, which will line-break and indent 
the JSON output we need to check
+  out="$(ansible-playbook test_end_play.yml -i inventory.yml -e 
test_strategy=$test_strategy -vv)"
 
+  grep -q "skipping:.*end_play conditional evaluated to False, continuing 
play" <<< "$out"
   grep -q "META: ending play" <<< "$out"
   grep -qv 'Failed to end using end_play' <<< "$out"
 
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' 
old/ansible_core-2.21.0/test/integration/targets/meta_tasks/test_end_play.yml 
new/ansible_core-2.21.1/test/integration/targets/meta_tasks/test_end_play.yml
--- 
old/ansible_core-2.21.0/test/integration/targets/meta_tasks/test_end_play.yml   
    2026-05-18 21:18:02.000000000 +0200
+++ 
new/ansible_core-2.21.1/test/integration/targets/meta_tasks/test_end_play.yml   
    2026-06-18 21:33:01.000000000 +0200
@@ -3,6 +3,10 @@
   gather_facts: no
   strategy: "{{ test_strategy | default('linear') }}"
   tasks:
+    - name: Skipped end_play
+      meta: end_play
+      when: false
+
     - debug:
         msg: "Testing end_play on host {{ inventory_hostname }}"
 
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' 
old/ansible_core-2.21.0/test/integration/targets/no_log/library/module.py 
new/ansible_core-2.21.1/test/integration/targets/no_log/library/module.py
--- old/ansible_core-2.21.0/test/integration/targets/no_log/library/module.py   
2026-05-18 21:18:02.000000000 +0200
+++ new/ansible_core-2.21.1/test/integration/targets/no_log/library/module.py   
2026-06-18 21:33:01.000000000 +0200
@@ -37,7 +37,7 @@
 
         }
     )
-    module.exit_json(msg='done')
+    module.exit_json(msg='done', values=', '.join([str(v) for v in 
module.params.values() if v]))
 
 
 if __name__ == '__main__':
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' 
old/ansible_core-2.21.0/test/integration/targets/no_log/runme.sh 
new/ansible_core-2.21.1/test/integration/targets/no_log/runme.sh
--- old/ansible_core-2.21.0/test/integration/targets/no_log/runme.sh    
2026-05-18 21:18:02.000000000 +0200
+++ new/ansible_core-2.21.1/test/integration/targets/no_log/runme.sh    
2026-06-18 21:33:01.000000000 +0200
@@ -33,3 +33,6 @@
 [ "$(ansible-playbook no_log_config.yml -i ../../inventory -vvvvv "$@" | grep 
-Ec 'the output has been hidden')" = "1" ]
 [ "$(ANSIBLE_NO_LOG=0 ansible-playbook no_log_config.yml -i ../../inventory 
-vvvvv "$@" | grep -Ec 'the output has been hidden')" = "1" ]
 [ "$(ANSIBLE_NO_LOG=1 ansible-playbook no_log_config.yml -i ../../inventory 
-vvvvv "$@" | grep -Ec 'the output has been hidden')" = "5" ]
+
+# Ensure module no_log masking handles secrets that are substrings of other 
secrets correctly
+ansible-playbook sub_masking.yml -i ../../inventory -vvvvv "$@"
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' 
old/ansible_core-2.21.0/test/integration/targets/no_log/secretvars.yml 
new/ansible_core-2.21.1/test/integration/targets/no_log/secretvars.yml
--- old/ansible_core-2.21.0/test/integration/targets/no_log/secretvars.yml      
2026-05-18 21:18:02.000000000 +0200
+++ new/ansible_core-2.21.1/test/integration/targets/no_log/secretvars.yml      
2026-06-18 21:33:01.000000000 +0200
@@ -30,3 +30,6 @@
 s211: SECRET211
 s212: SECRET212
 s213: SECRET213
+
+# substring
+sec: RET
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' 
old/ansible_core-2.21.0/test/integration/targets/no_log/sub_masking.yml 
new/ansible_core-2.21.1/test/integration/targets/no_log/sub_masking.yml
--- old/ansible_core-2.21.0/test/integration/targets/no_log/sub_masking.yml     
1970-01-01 01:00:00.000000000 +0100
+++ new/ansible_core-2.21.1/test/integration/targets/no_log/sub_masking.yml     
2026-06-18 21:33:01.000000000 +0200
@@ -0,0 +1,60 @@
+- name: Ensure no_log obfuscation does not mask on substrings
+  hosts: all
+  vars_files:
+    - secretvars.yml
+  gather_facts: no
+
+  tasks:
+    - name: test with option long
+      module:
+        secret: "{{ s101 }}"
+        subopt_dict:
+          str_sub_opt1: "{{ s102 }}"
+          nested_subopt:
+            n_subopt1: "{{ s103 }}"
+        subopt_list:
+            - subopt1: "{{sec}}"
+      register: long_first
+
+    - name: Task with suboptions long
+      module:
+        secret: "{{ sec }}"
+        subopt_dict: 
+          str_sub_opt1: '{{ s101 }}'
+          nested_subopt:
+            n_subopt1: "{{ s102 }}"
+        subopt_list:
+            - subopt1: "{{ s103 }}"
+      register: short_first 
+
+    - name: Task with suboptions long
+      module:
+        secret: "{{ s101 }}"
+        subopt_dict: 
+          str_sub_opt1: '{{ sec }}'
+          nested_subopt:
+            n_subopt1: "{{ s102 }}"
+        subopt_list:
+            - subopt1: "{{ s103 }}"
+      register: middle_top
+
+    - name: Task with suboptions long
+      module:
+        secret: "{{ s102}}"
+        subopt_dict: 
+          str_sub_opt1: '{{ s102 }}'
+          nested_subopt:
+            n_subopt1: "{{ sec }}"
+        subopt_list:
+            - subopt1: "{{ s103 }}"
+      register: middle_bottom
+
+    - name: check output
+      assert:
+        that:
+          - "'SEC' not in (q('vars', item)|to_json)"
+      loop:
+        - long_first
+        - short_first
+        - middle_top
+        - middle_bottom
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' 
old/ansible_core-2.21.0/test/integration/targets/strategy_free/free_hosts 
new/ansible_core-2.21.1/test/integration/targets/strategy_free/free_hosts
--- old/ansible_core-2.21.0/test/integration/targets/strategy_free/free_hosts   
1970-01-01 01:00:00.000000000 +0100
+++ new/ansible_core-2.21.1/test/integration/targets/strategy_free/free_hosts   
2026-06-18 21:33:01.000000000 +0200
@@ -0,0 +1,4 @@
+[local]
+host0 ansible_connection=local ansible_python_interpreter="{{ 
ansible_playbook_python }}"
+host1 ansible_connection=ssh ansible_host=127.0.0.1 ansible_port=1011  # IANA 
Reserved port
+host2 ansible_connection=local ansible_python_interpreter="{{ 
ansible_playbook_python }}"
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' 
old/ansible_core-2.21.0/test/integration/targets/strategy_free/free_index_error.yml
 
new/ansible_core-2.21.1/test/integration/targets/strategy_free/free_index_error.yml
--- 
old/ansible_core-2.21.0/test/integration/targets/strategy_free/free_index_error.yml
 1970-01-01 01:00:00.000000000 +0100
+++ 
new/ansible_core-2.21.1/test/integration/targets/strategy_free/free_index_error.yml
 2026-06-18 21:33:01.000000000 +0200
@@ -0,0 +1,11 @@
+---
+- hosts: host0, host1, host2
+  strategy: free
+  gather_facts: false
+  tasks:
+    - name: EXPECTED FAILURE - First ping
+      ping:
+      throttle: 2
+
+    - name: Second ping
+      ping:
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' 
old/ansible_core-2.21.0/test/integration/targets/strategy_free/runme.sh 
new/ansible_core-2.21.1/test/integration/targets/strategy_free/runme.sh
--- old/ansible_core-2.21.0/test/integration/targets/strategy_free/runme.sh     
2026-05-18 21:18:02.000000000 +0200
+++ new/ansible_core-2.21.1/test/integration/targets/strategy_free/runme.sh     
2026-06-18 21:33:01.000000000 +0200
@@ -8,3 +8,9 @@
 result="$(ansible-playbook test_last_include_in_always.yml -i inventory "$@" 
2>&1)"
 set -e
 grep -q "INCLUDED TASK EXECUTED" <<< "$result"
+
+set +e
+result="$(ansible-playbook free_index_error.yml -i free_hosts "$@" 2>&1)"
+set -e
+grep -q "\[host1\]: UNREACHABLE!" <<< "$result"
+! grep -q "IndexError: list index out of range" <<< "$result"
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' 
old/ansible_core-2.21.0/test/lib/ansible_test/_util/target/setup/bootstrap.sh 
new/ansible_core-2.21.1/test/lib/ansible_test/_util/target/setup/bootstrap.sh
--- 
old/ansible_core-2.21.0/test/lib/ansible_test/_util/target/setup/bootstrap.sh   
    2026-05-18 21:18:02.000000000 +0200
+++ 
new/ansible_core-2.21.1/test/lib/ansible_test/_util/target/setup/bootstrap.sh   
    2026-06-18 21:33:01.000000000 +0200
@@ -401,9 +401,13 @@
     # Instead, ansible-test will install it using pip.
     # packaging and resolvelib are missing for controller supported Python 
versions, so we just
     # skip them and let ansible-test install them from PyPI.
+    #
+    # sqlite-libs needs to be specified currently to get sqlite3 imports 
working
+    # https://redhat.atlassian.net/browse/RHEL-178008
     if [ "${controller}" ]; then
         packages="
             ${packages}
+            sqlite-libs
             ${py_pkg_prefix}-cryptography
             ${py_pkg_prefix}-pyyaml
             "
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' 
old/ansible_core-2.21.0/test/units/module_utils/basic/test_run_command.py 
new/ansible_core-2.21.1/test/units/module_utils/basic/test_run_command.py
--- old/ansible_core-2.21.0/test/units/module_utils/basic/test_run_command.py   
2026-05-18 21:18:02.000000000 +0200
+++ new/ansible_core-2.21.1/test/units/module_utils/basic/test_run_command.py   
2026-06-18 21:33:01.000000000 +0200
@@ -255,3 +255,81 @@
 
     assert subprocess_mock.Popen.call_args[1]['pass_fds'] == (101, 42)
     assert subprocess_mock.Popen.call_args[1]['close_fds'] is True
+
+
+class TestRunCommandNoneRead:
+    """
+    Test handling of read() returning None from non-blocking pipes.
+
+    This tests the fix for issue #86920 where read() can return None
+    in certain edge cases with non-blocking I/O, which would cause
+    TypeError when trying to concatenate None to bytes.
+    """
+
+    class NoneReturningBytesIO(SpecialBytesIO):
+        """
+        BytesIO that returns None on first read, then actual data.
+
+        This simulates edge cases where non-blocking read() returns None
+        to indicate "no data available right now" rather than empty bytes.
+        """
+
+        def __init__(self, *args, **kwargs):
+            # Pop 'data' before calling super().__init__() since BytesIO 
doesn't accept it
+            self.data = kwargs.pop('data', b'test output')
+            self.read_count = 0
+            super(TestRunCommandNoneRead.NoneReturningBytesIO, 
self).__init__(*args, **kwargs)
+
+        def read(self, size=-1):
+            self.read_count += 1
+            if self.read_count == 1:
+                # First read returns None (no data available)
+                return None
+            elif self.read_count == 2:
+                # Second read returns actual data
+                return self.data
+            else:
+                # Subsequent reads return empty bytes (EOF)
+                return b''
+
+    @pytest.mark.parametrize('stdin', [{}], indirect=['stdin'])
+    def test_none_from_stdout_read(self, mocker, rc_am):
+        """Test that None returned from stdout.read() doesn't cause 
TypeError."""
+        rc_am._subprocess._output = {
+            mocker.sentinel.stdout:
+                self.NoneReturningBytesIO(fh=mocker.sentinel.stdout, 
data=b'command output'),
+            mocker.sentinel.stderr:
+                SpecialBytesIO(b'', fh=mocker.sentinel.stderr)
+        }
+        (rc, stdout, stderr) = rc_am.run_command('/bin/test')
+        assert rc == 0
+        assert stdout == 'command output'
+        assert stderr == ''
+
+    @pytest.mark.parametrize('stdin', [{}], indirect=['stdin'])
+    def test_none_from_stderr_read(self, mocker, rc_am):
+        """Test that None returned from stderr.read() doesn't cause 
TypeError."""
+        rc_am._subprocess._output = {
+            mocker.sentinel.stdout:
+                SpecialBytesIO(b'', fh=mocker.sentinel.stdout),
+            mocker.sentinel.stderr:
+                self.NoneReturningBytesIO(fh=mocker.sentinel.stderr, 
data=b'error output')
+        }
+        (rc, stdout, stderr) = rc_am.run_command('/bin/test')
+        assert rc == 0
+        assert stdout == ''
+        assert stderr == 'error output'
+
+    @pytest.mark.parametrize('stdin', [{}], indirect=['stdin'])
+    def test_none_from_both_pipes(self, mocker, rc_am):
+        """Test that None returned from both pipes doesn't cause TypeError."""
+        rc_am._subprocess._output = {
+            mocker.sentinel.stdout:
+                self.NoneReturningBytesIO(fh=mocker.sentinel.stdout, 
data=b'stdout data'),
+            mocker.sentinel.stderr:
+                self.NoneReturningBytesIO(fh=mocker.sentinel.stderr, 
data=b'stderr data')
+        }
+        (rc, stdout, stderr) = rc_am.run_command('/bin/test')
+        assert rc == 0
+        assert stdout == 'stdout data'
+        assert stderr == 'stderr data'

++++++ ansible_core-2.21.0.tar.gz.sha256 -> ansible_core-2.21.1.tar.gz.sha256 
++++++
--- /work/SRC/openSUSE:Factory/ansible-core/ansible_core-2.21.0.tar.gz.sha256   
2026-06-03 20:27:21.449494128 +0200
+++ 
/work/SRC/openSUSE:Factory/.ansible-core.new.1956/ansible_core-2.21.1.tar.gz.sha256
 2026-06-19 17:12:22.795491874 +0200
@@ -1 +1 @@
-28ccd0e2d1849f1c7272cec39a74a8a5c83f3d51314658fa5ca57ea85a87f454  
ansible_core-2.21.0.tar.gz
+a5536ece95be84de15212b3644cdbbe9cbd9efd62e4e8a544cd6b0b27a083039  
ansible_core-2.21.1.tar.gz

Reply via email to