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 2025-11-06 18:12:52
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Comparing /work/SRC/openSUSE:Factory/ansible-core (Old)
 and      /work/SRC/openSUSE:Factory/.ansible-core.new.1980 (New)
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

Package is "ansible-core"

Thu Nov  6 18:12:52 2025 rev:49 rq:1315706 version:2.19.4

Changes:
--------
--- /work/SRC/openSUSE:Factory/ansible-core/ansible-core.changes        
2025-10-07 18:30:04.021764562 +0200
+++ /work/SRC/openSUSE:Factory/.ansible-core.new.1980/ansible-core.changes      
2025-11-06 18:13:58.129355750 +0100
@@ -1,0 +2,32 @@
+Wed Nov  5 10:18:14 UTC 2025 - Johannes Kastl 
<[email protected]>
+
+- update to 2.19.4:
+  * Bugfixes
+    - Fix issue where play tags prevented executing notified
+      handlers (#85475)
+    - Fix issues with keywords being incorrectly validated on
+      import_tasks (#85855, #85856)
+    - Fix traceback when trying to import non-existing file via
+      nested import_tasks (#69882)
+    - SIGINT/SIGTERM Handling - Make SIGINT/SIGTERM handling more
+      robust by splitting concerns between forks and the parent.
+    - Windows - ignore temporary file cleanup warning when using
+      AnsibleModule to compile C# utils. This should reduce the
+      number of warnings that can safely be ignored when running
+      PowerShell modules - #85976
+    - ansible-doc - prevent crash when scanning collections in
+      paths that have more than one ansible_collections in it
+      (#84909, #85361).
+    - callback plugins - improve consistency accessing the Task
+      object's resolved_action attribute.
+    - config lookup now properly factors in variables and
+      show_origin when checking entries from the global
+      configuration.
+    - option argument deprecations now have a proper alternative
+      help text.
+    - package_facts - typecast bytes to string while returning
+      facts (#85937).
+    - psrp - ReadTimeout exceptions now mark host as unreachable
+      instead of fatal (#85966)
+
+-------------------------------------------------------------------

Old:
----
  ansible_core-2.19.3.tar.gz
  ansible_core-2.19.3.tar.gz.sha256

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

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

Other differences:
------------------
++++++ ansible-core.spec ++++++
--- /var/tmp/diff_new_pack.J6eueE/_old  2025-11-06 18:13:59.141398735 +0100
+++ /var/tmp/diff_new_pack.J6eueE/_new  2025-11-06 18:13:59.145398905 +0100
@@ -43,7 +43,7 @@
 %endif
 
 Name:           ansible-core
-Version:        2.19.3
+Version:        2.19.4
 Release:        0
 Summary:        Radically simple IT automation
 License:        GPL-3.0-or-later

++++++ ansible_core-2.19.3.tar.gz -> ansible_core-2.19.4.tar.gz ++++++
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/ansible_core-2.19.3/PKG-INFO 
new/ansible_core-2.19.4/PKG-INFO
--- old/ansible_core-2.19.3/PKG-INFO    2025-10-06 19:22:06.000000000 +0200
+++ new/ansible_core-2.19.4/PKG-INFO    2025-11-05 00:27:03.000000000 +0100
@@ -1,6 +1,6 @@
 Metadata-Version: 2.4
 Name: ansible-core
-Version: 2.19.3
+Version: 2.19.4
 Summary: Radically simple IT automation
 Author: Ansible Project
 Project-URL: Homepage, https://ansible.com/
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/ansible_core-2.19.3/ansible_core.egg-info/PKG-INFO 
new/ansible_core-2.19.4/ansible_core.egg-info/PKG-INFO
--- old/ansible_core-2.19.3/ansible_core.egg-info/PKG-INFO      2025-10-06 
19:22:06.000000000 +0200
+++ new/ansible_core-2.19.4/ansible_core.egg-info/PKG-INFO      2025-11-05 
00:27:03.000000000 +0100
@@ -1,6 +1,6 @@
 Metadata-Version: 2.4
 Name: ansible-core
-Version: 2.19.3
+Version: 2.19.4
 Summary: Radically simple IT automation
 Author: Ansible Project
 Project-URL: Homepage, https://ansible.com/
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' 
old/ansible_core-2.19.3/ansible_core.egg-info/SOURCES.txt 
new/ansible_core-2.19.4/ansible_core.egg-info/SOURCES.txt
--- old/ansible_core-2.19.3/ansible_core.egg-info/SOURCES.txt   2025-10-06 
19:22:06.000000000 +0200
+++ new/ansible_core-2.19.4/ansible_core.egg-info/SOURCES.txt   2025-11-05 
00:27:03.000000000 +0100
@@ -876,6 +876,7 @@
 
test/integration/targets/ansible-doc/broken-docs/collections/ansible_collections/testns/testcol/plugins/modules/randommodule.py
 
test/integration/targets/ansible-doc/broken-docs/collections/ansible_collections/testns/testcol/plugins/vars/noop_vars_plugin.py
 
test/integration/targets/ansible-doc/collections/ansible_collections/testns/testcol/MANIFEST.json
+test/integration/targets/ansible-doc/collections/ansible_collections/testns/testcol/playbooks/collections/ansible_collections/ns/col/plugins/modules/test.py
 
test/integration/targets/ansible-doc/collections/ansible_collections/testns/testcol/plugins/__init__.py
 
test/integration/targets/ansible-doc/collections/ansible_collections/testns/testcol/plugins/cache/notjsonfile.py
 
test/integration/targets/ansible-doc/collections/ansible_collections/testns/testcol/plugins/filter/__init__.py
@@ -1800,6 +1801,7 @@
 test/integration/targets/collections/roles/standalone/tasks/main.yml
 test/integration/targets/collections/roles/testrole/tasks/main.yml
 
test/integration/targets/collections/test_plugins/override_formerly_core_masked_test.py
+test/integration/targets/collections/test_task_resolved_plugin/dynamic_action.yml
 test/integration/targets/collections/test_task_resolved_plugin/fqcn.yml
 test/integration/targets/collections/test_task_resolved_plugin/unqualified.yml
 
test/integration/targets/collections/test_task_resolved_plugin/unqualified_and_collections_kw.yml
@@ -2457,6 +2459,7 @@
 test/integration/targets/include_import/test_include_loop.yml
 test/integration/targets/include_import/test_include_loop_fqcn.yml
 test/integration/targets/include_import/test_loop_var_bleed.yaml
+test/integration/targets/include_import/test_nested_non_existent_tasks.yml
 test/integration/targets/include_import/test_nested_tasks.yml
 test/integration/targets/include_import/test_nested_tasks_fqcn.yml
 test/integration/targets/include_import/test_null_include_filename.yml
@@ -2558,6 +2561,9 @@
 test/integration/targets/include_import/roles/nested_include_task/meta/main.yml
 
test/integration/targets/include_import/roles/nested_include_task/tasks/main.yml
 
test/integration/targets/include_import/roles/nested_include_task/tasks/runa.yml
+test/integration/targets/include_import/roles/nested_tasks/tasks/bar.yml
+test/integration/targets/include_import/roles/nested_tasks/tasks/foo.yml
+test/integration/targets/include_import/roles/nested_tasks/tasks/main.yml
 test/integration/targets/include_import/roles/role1/tasks/canary1.yml
 test/integration/targets/include_import/roles/role1/tasks/canary2.yml
 test/integration/targets/include_import/roles/role1/tasks/canary3.yml
@@ -3761,6 +3767,9 @@
 test/integration/targets/shell/meta/main.yml
 test/integration/targets/shell/tasks/command-building.yml
 test/integration/targets/shell/tasks/main.yml
+test/integration/targets/signal_propagation/aliases
+test/integration/targets/signal_propagation/inventory
+test/integration/targets/signal_propagation/runme.sh
 test/integration/targets/slurp/aliases
 test/integration/targets/slurp/files/bar.bin
 test/integration/targets/slurp/meta/main.yml
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/ansible_core-2.19.3/changelogs/CHANGELOG-v2.19.rst 
new/ansible_core-2.19.4/changelogs/CHANGELOG-v2.19.rst
--- old/ansible_core-2.19.3/changelogs/CHANGELOG-v2.19.rst      2025-10-06 
19:22:06.000000000 +0200
+++ new/ansible_core-2.19.4/changelogs/CHANGELOG-v2.19.rst      2025-11-05 
00:27:03.000000000 +0100
@@ -4,6 +4,30 @@
 
 .. contents:: Topics
 
+v2.19.4
+=======
+
+Release Summary
+---------------
+
+| Release Date: 2025-11-04
+| `Porting Guide 
<https://docs.ansible.com/ansible-core/2.19/porting_guides/porting_guide_core_2.19.html>`__
+
+Bugfixes
+--------
+
+- Fix issue where play tags prevented executing notified handlers 
(https://github.com/ansible/ansible/issues/85475)
+- Fix issues with keywords being incorrectly validated on ``import_tasks`` 
(https://github.com/ansible/ansible/issues/85855, 
https://github.com/ansible/ansible/issues/85856)
+- Fix traceback when trying to import non-existing file via nested 
``import_tasks`` (https://github.com/ansible/ansible/issues/69882)
+- SIGINT/SIGTERM Handling - Make SIGINT/SIGTERM handling more robust by 
splitting concerns between forks and the parent.
+- Windows - ignore temporary file cleanup warning when using AnsibleModule to 
compile C# utils. This should reduce the number of warnings that can safely be 
ignored when running PowerShell modules - 
https://github.com/ansible/ansible/issues/85976
+- ansible-doc - prevent crash when scanning collections in paths that have 
more than one ``ansible_collections`` in it 
(https://github.com/ansible/ansible/issues/84909, 
https://github.com/ansible/ansible/pull/85361).
+- callback plugins - improve consistency accessing the Task object's 
resolved_action attribute.
+- config lookup now properly factors in variables and show_origin when 
checking entries from the global configuration.
+- option argument deprecations now have a proper alternative help text.
+- package_facts - typecast bytes to string while returning facts 
(https://github.com/ansible/ansible/issues/85937).
+- psrp - ReadTimeout exceptions now mark host as unreachable instead of fatal 
(https://github.com/ansible/ansible/issues/85966)
+
 v2.19.3
 =======
 
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/ansible_core-2.19.3/changelogs/changelog.yaml 
new/ansible_core-2.19.4/changelogs/changelog.yaml
--- old/ansible_core-2.19.3/changelogs/changelog.yaml   2025-10-06 
19:22:06.000000000 +0200
+++ new/ansible_core-2.19.4/changelogs/changelog.yaml   2025-11-05 
00:27:03.000000000 +0100
@@ -1354,3 +1354,57 @@
     - run_command_output_selector.yml
     - win_async-junk-output.yml
     release_date: '2025-09-29'
+  2.19.4:
+    changes:
+      release_summary: '| Release Date: 2025-11-04
+
+        | `Porting Guide 
<https://docs.ansible.com/ansible-core/2.19/porting_guides/porting_guide_core_2.19.html>`__
+
+        '
+    codename: What Is and What Should Never Be
+    fragments:
+    - 2.19.4_summary.yaml
+    release_date: '2025-11-04'
+  2.19.4rc1:
+    changes:
+      bugfixes:
+      - Fix issue where play tags prevented executing notified handlers 
(https://github.com/ansible/ansible/issues/85475)
+      - Fix issues with keywords being incorrectly validated on 
``import_tasks`` (https://github.com/ansible/ansible/issues/85855,
+        https://github.com/ansible/ansible/issues/85856)
+      - Fix traceback when trying to import non-existing file via nested 
``import_tasks``
+        (https://github.com/ansible/ansible/issues/69882)
+      - SIGINT/SIGTERM Handling - Make SIGINT/SIGTERM handling more robust by 
splitting
+        concerns between forks and the parent.
+      - Windows - ignore temporary file cleanup warning when using 
AnsibleModule to
+        compile C# utils. This should reduce the number of warnings that can 
safely
+        be ignored when running PowerShell modules - 
https://github.com/ansible/ansible/issues/85976
+      - ansible-doc - prevent crash when scanning collections in paths that 
have more
+        than one ``ansible_collections`` in it 
(https://github.com/ansible/ansible/issues/84909,
+        https://github.com/ansible/ansible/pull/85361).
+      - callback plugins - improve consistency accessing the Task object's 
resolved_action
+        attribute.
+      - config lookup now properly factors in variables and show_origin when 
checking
+        entries from the global configuration.
+      - option argument deprecations now have a proper alternative help text.
+      - package_facts - typecast bytes to string while returning facts 
(https://github.com/ansible/ansible/issues/85937).
+      - psrp - ReadTimeout exceptions now mark host as unreachable instead of 
fatal
+        (https://github.com/ansible/ansible/issues/85966)
+      release_summary: '| Release Date: 2025-10-29
+
+        | `Porting Guide 
<https://docs.ansible.com/ansible-core/2.19/porting_guides/porting_guide_core_2.19.html>`__
+
+        '
+    codename: What Is and What Should Never Be
+    fragments:
+    - 2.19.4rc1_summary.yaml
+    - 85361-collection-name-from-path-none.yml
+    - 85475-fix-flush_handlers-play-tags.yml
+    - 85524-resolve-task-resolved_action-early.yml
+    - 85966-psrp-readtimeout.yml
+    - add-type-warning.yml
+    - config_lookup_fix.yml
+    - fix-signal-propagation.yml
+    - import_tasks-fixes.yml
+    - option_deprecation_help.yml
+    - package_facts.yml
+    release_date: '2025-10-29'
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' 
old/ansible_core-2.19.3/lib/ansible/cli/arguments/option_helpers.py 
new/ansible_core-2.19.4/lib/ansible/cli/arguments/option_helpers.py
--- old/ansible_core-2.19.3/lib/ansible/cli/arguments/option_helpers.py 
2025-10-06 19:22:06.000000000 +0200
+++ new/ansible_core-2.19.4/lib/ansible/cli/arguments/option_helpers.py 
2025-11-05 00:27:03.000000000 +0100
@@ -44,6 +44,9 @@
     option: str | None = None
     """The specific option string that is deprecated; None applies to all 
options for this argument."""
 
+    alternatives: str | None = None
+    """The options to use instead."""
+
     def is_deprecated(self, option: str) -> bool:
         """Return True if the given option is deprecated, otherwise False."""
         return self.option is None or option == self.option
@@ -58,6 +61,7 @@
         Display().deprecated(  # pylint: 
disable=ansible-invalid-deprecated-version
             msg=f'The {option!r} argument is deprecated.',
             version=self.version,
+            help_text=f'Use {self.alternatives} instead.' if self.alternatives 
else None
         )
 
 
@@ -419,7 +423,7 @@
     """Add options for commands that utilize inventory"""
     parser.add_argument('-i', '--inventory', '--inventory-file', 
dest='inventory', action="append",
                         help="specify inventory host path or comma separated 
host list",
-                        deprecated=DeprecatedArgument(version='2.23', 
option='--inventory-file'))
+                        deprecated=DeprecatedArgument(version='2.23', 
option='--inventory-file', alternatives="-i or --inventory"))
     parser.add_argument('--list-hosts', dest='listhosts', action='store_true',
                         help='outputs a list of matching hosts; does not 
execute anything else')
     parser.add_argument('-l', '--limit', default=C.DEFAULT_SUBSET, 
dest='subset',
@@ -444,10 +448,10 @@
 
 def add_output_options(parser):
     """Add options for commands which can change their output"""
-    parser.add_argument('-o', '--one-line', dest='one_line', 
action='store_true',
-                        help='condense output', 
deprecated=DeprecatedArgument(version='2.23'))
-    parser.add_argument('-t', '--tree', dest='tree', default=None,
-                        help='log output to this directory', 
deprecated=DeprecatedArgument(version='2.23'))
+    parser.add_argument('-o', '--one-line', dest='one_line', 
action='store_true', help='condense output',
+                        deprecated=DeprecatedArgument(version='2.23', 
alternatives='callback configuration to enable the oneline callback'))
+    parser.add_argument('-t', '--tree', dest='tree', default=None, help='log 
output to this directory',
+                        deprecated=DeprecatedArgument(version='2.23', 
alternatives='callback configuration to enable the tree callback'))
 
 
 def add_runas_options(parser):
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/ansible_core-2.19.3/lib/ansible/cli/doc.py 
new/ansible_core-2.19.4/lib/ansible/cli/doc.py
--- old/ansible_core-2.19.3/lib/ansible/cli/doc.py      2025-10-06 
19:22:06.000000000 +0200
+++ new/ansible_core-2.19.4/lib/ansible/cli/doc.py      2025-11-05 
00:27:03.000000000 +0100
@@ -237,7 +237,9 @@
         b_colldirs = list_collection_dirs(coll_filter=collection_filter)
         for b_path in b_colldirs:
             path = to_text(b_path, errors='surrogate_or_strict')
-            collname = _get_collection_name_from_path(b_path)
+            if not (collname := _get_collection_name_from_path(b_path)):
+                display.debug(f'Skipping invalid path {b_path!r}')
+                continue
 
             roles_dir = os.path.join(path, 'roles')
             if os.path.exists(roles_dir):
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/ansible_core-2.19.3/lib/ansible/collections/list.py 
new/ansible_core-2.19.4/lib/ansible/collections/list.py
--- old/ansible_core-2.19.3/lib/ansible/collections/list.py     2025-10-06 
19:22:06.000000000 +0200
+++ new/ansible_core-2.19.4/lib/ansible/collections/list.py     2025-11-05 
00:27:03.000000000 +0100
@@ -17,8 +17,10 @@
 
     collections = {}
     for candidate in list_collection_dirs(search_paths=search_paths, 
coll_filter=coll_filter, artifacts_manager=artifacts_manager, dedupe=dedupe):
-        collection = _get_collection_name_from_path(candidate)
-        collections[collection] = candidate
+        if collection := _get_collection_name_from_path(candidate):
+            collections[collection] = candidate
+        else:
+            display.debug(f'Skipping invalid collection in path: 
{candidate!r}')
     return collections
 
 
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/ansible_core-2.19.3/lib/ansible/config/base.yml 
new/ansible_core-2.19.4/lib/ansible/config/base.yml
--- old/ansible_core-2.19.3/lib/ansible/config/base.yml 2025-10-06 
19:22:06.000000000 +0200
+++ new/ansible_core-2.19.4/lib/ansible/config/base.yml 2025-11-05 
00:27:03.000000000 +0100
@@ -2257,6 +2257,8 @@
         why: for testing
         version: '3.30'
         alternatives: nothing
+  vars:
+    - name: _z_test_entry
 _Z_TEST_ENTRY_2:
   version_added: '2.18'
   name: testentry
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' 
old/ansible_core-2.19.3/lib/ansible/executor/process/worker.py 
new/ansible_core-2.19.4/lib/ansible/executor/process/worker.py
--- old/ansible_core-2.19.3/lib/ansible/executor/process/worker.py      
2025-10-06 19:22:06.000000000 +0200
+++ new/ansible_core-2.19.4/lib/ansible/executor/process/worker.py      
2025-11-05 00:27:03.000000000 +0100
@@ -17,6 +17,7 @@
 
 from __future__ import annotations
 
+import errno
 import io
 import os
 import signal
@@ -103,11 +104,19 @@
         self._cliargs = cliargs
 
     def _term(self, signum, frame) -> None:
-        """
-        terminate the process group created by calling setsid when
-        a terminate signal is received by the fork
-        """
-        os.killpg(self.pid, signum)
+        """In child termination when notified by the parent"""
+        signal.signal(signum, signal.SIG_DFL)
+
+        try:
+            os.killpg(self.pid, signum)
+            os.kill(self.pid, signum)
+        except OSError as e:
+            if e.errno != errno.ESRCH:
+                signame = signal.strsignal(signum)
+                display.error(f'Unable to send {signame} to child[{self.pid}]: 
{e}')
+
+        # fallthrough, if we are still here, just die
+        os._exit(1)
 
     def start(self) -> None:
         """
@@ -121,11 +130,6 @@
         # FUTURE: this lock can be removed once a more generalized pre-fork 
thread pause is in place
         with display._lock:
             super(WorkerProcess, self).start()
-        # Since setsid is called later, if the worker is termed
-        # it won't term the new process group
-        # register a handler to propagate the signal
-        signal.signal(signal.SIGTERM, self._term)
-        signal.signal(signal.SIGINT, self._term)
 
     def _hard_exit(self, e: str) -> t.NoReturn:
         """
@@ -170,7 +174,6 @@
             # to give better errors, and to prevent fd 0 reuse
             sys.stdin.close()
         except Exception as e:
-            display.debug(f'Could not detach from stdio: 
{traceback.format_exc()}')
             display.error(f'Could not detach from stdio: {e}')
             os._exit(1)
 
@@ -187,6 +190,9 @@
         # Set the queue on Display so calls to Display.display are proxied 
over the queue
         display.set_queue(self._final_q)
         self._detach()
+        # propagate signals
+        signal.signal(signal.SIGINT, self._term)
+        signal.signal(signal.SIGTERM, self._term)
         try:
             with _task.TaskContext(self._task):
                 return self._run()
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' 
old/ansible_core-2.19.3/lib/ansible/executor/task_queue_manager.py 
new/ansible_core-2.19.4/lib/ansible/executor/task_queue_manager.py
--- old/ansible_core-2.19.3/lib/ansible/executor/task_queue_manager.py  
2025-10-06 19:22:06.000000000 +0200
+++ new/ansible_core-2.19.4/lib/ansible/executor/task_queue_manager.py  
2025-11-05 00:27:03.000000000 +0100
@@ -18,8 +18,10 @@
 from __future__ import annotations
 
 import dataclasses
+import errno
 import os
 import sys
+import signal
 import tempfile
 import threading
 import time
@@ -187,8 +189,48 @@
         # plugins for inter-process locking.
         self._connection_lockfile = tempfile.TemporaryFile()
 
+        self._workers: list[WorkerProcess | None] = []
+
+        # signal handlers to propagate signals to workers
+        signal.signal(signal.SIGTERM, self._signal_handler)
+        signal.signal(signal.SIGINT, self._signal_handler)
+
     def _initialize_processes(self, num: int) -> None:
-        self._workers: list[WorkerProcess | None] = [None] * num
+        # mutable update to ensure the reference stays the same
+        self._workers[:] = [None] * num
+
+    def _signal_handler(self, signum, frame) -> None:
+        """
+        terminate all running process groups created as a result of calling
+        setsid from within a WorkerProcess.
+
+        Since the children become process leaders, signals will not
+        automatically propagate to them.
+        """
+        signal.signal(signum, signal.SIG_DFL)
+
+        for worker in self._workers:
+            if worker is None or not worker.is_alive():
+                continue
+            if worker.pid:
+                try:
+                    # notify workers
+                    os.kill(worker.pid, signum)
+                except OSError as e:
+                    if e.errno != errno.ESRCH:
+                        signame = signal.strsignal(signum)
+                        display.error(f'Unable to send {signame} to 
child[{worker.pid}]: {e}')
+
+        if signum == signal.SIGINT:
+            # Defer to CLI handling
+            raise KeyboardInterrupt()
+
+        pid = os.getpid()
+        try:
+            os.kill(pid, signum)
+        except OSError as e:
+            signame = signal.strsignal(signum)
+            display.error(f'Unable to send {signame} to {pid}: {e}')
 
     def load_callbacks(self):
         """
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' 
old/ansible_core-2.19.3/lib/ansible/module_utils/ansible_release.py 
new/ansible_core-2.19.4/lib/ansible/module_utils/ansible_release.py
--- old/ansible_core-2.19.3/lib/ansible/module_utils/ansible_release.py 
2025-10-06 19:22:06.000000000 +0200
+++ new/ansible_core-2.19.4/lib/ansible/module_utils/ansible_release.py 
2025-11-05 00:27:03.000000000 +0100
@@ -17,6 +17,6 @@
 
 from __future__ import annotations
 
-__version__ = '2.19.3'
+__version__ = '2.19.4'
 __author__ = 'Ansible, Inc.'
 __codename__ = "What Is and What Should Never Be"
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' 
old/ansible_core-2.19.3/lib/ansible/module_utils/powershell/Ansible.ModuleUtils.AddType.psm1
 
new/ansible_core-2.19.4/lib/ansible/module_utils/powershell/Ansible.ModuleUtils.AddType.psm1
--- 
old/ansible_core-2.19.3/lib/ansible/module_utils/powershell/Ansible.ModuleUtils.AddType.psm1
        2025-10-06 19:22:06.000000000 +0200
+++ 
new/ansible_core-2.19.4/lib/ansible/module_utils/powershell/Ansible.ModuleUtils.AddType.psm1
        2025-11-05 00:27:03.000000000 +0100
@@ -278,10 +278,16 @@
         if ($PSCmdlet.ParameterSetName -eq "Module") {
             $temp_path = $AnsibleModule.Tmpdir
             $include_debug = $AnsibleModule.Verbosity -ge 3
+
+            # AnsibleModule will handle the cleanup after module execution
+            # which should be enough time for AVs or other processes to release
+            # any locks on the temp files.
+            $tmpdir_clean_is_error = $false
         }
         else {
             $temp_path = [System.IO.Path]::GetTempPath()
             $include_debug = $IncludeDebugInfo.IsPresent
+            $tmpdir_clean_is_error = $true
         }
         $temp_path = Join-Path -Path $temp_path -ChildPath 
([Guid]::NewGuid().Guid)
 
@@ -388,17 +394,13 @@
             }
             finally {
                 # Try to delete the temp path, if this fails and we are running
-                # with a module object write a warning instead of failing.
+                # with a module object, ignore and let it cleanup later.
                 try {
                     [System.IO.Directory]::Delete($temp_path, $true)
                 }
                 catch {
-                    $msg = "Failed to cleanup temporary directory '$temp_path' 
used for compiling C# code."
-                    if ($AnsibleModule) {
-                        $AnsibleModule.Warn("$msg Files may still be present 
after the task is complete. Error: $_")
-                    }
-                    else {
-                        throw "$msg Error: $_"
+                    if ($tmpdir_clean_is_error) {
+                        throw "Failed to cleanup temporary directory 
'$temp_path' used for compiling C# code. Error: $_"
                     }
                 }
             }
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' 
old/ansible_core-2.19.3/lib/ansible/modules/package_facts.py 
new/ansible_core-2.19.4/lib/ansible/modules/package_facts.py
--- old/ansible_core-2.19.3/lib/ansible/modules/package_facts.py        
2025-10-06 19:22:06.000000000 +0200
+++ new/ansible_core-2.19.4/lib/ansible/modules/package_facts.py        
2025-11-05 00:27:03.000000000 +0100
@@ -278,11 +278,11 @@
         return self._lib.TransactionSet().dbMatch()
 
     def get_package_details(self, package):
-        return dict(name=package[self._lib.RPMTAG_NAME],
-                    version=package[self._lib.RPMTAG_VERSION],
-                    release=package[self._lib.RPMTAG_RELEASE],
-                    epoch=package[self._lib.RPMTAG_EPOCH],
-                    arch=package[self._lib.RPMTAG_ARCH],)
+        return dict(name=to_text(package[self._lib.RPMTAG_NAME]),
+                    version=to_text(package[self._lib.RPMTAG_VERSION]),
+                    release=to_text(package[self._lib.RPMTAG_RELEASE]),
+                    epoch=to_text(package[self._lib.RPMTAG_EPOCH]),
+                    arch=to_text(package[self._lib.RPMTAG_ARCH]),)
 
 
 class APT(RespawningLibMgr):
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/ansible_core-2.19.3/lib/ansible/parsing/mod_args.py 
new/ansible_core-2.19.4/lib/ansible/parsing/mod_args.py
--- old/ansible_core-2.19.3/lib/ansible/parsing/mod_args.py     2025-10-06 
19:22:06.000000000 +0200
+++ new/ansible_core-2.19.4/lib/ansible/parsing/mod_args.py     2025-11-05 
00:27:03.000000000 +0100
@@ -130,6 +130,7 @@
         # HACK: why are these not FieldAttributes on task with a post-validate 
to check usage?
         self._task_attrs.update(['local_action', 'static'])
         self._task_attrs = frozenset(self._task_attrs)
+        self._resolved_action = None
 
     def _split_module_string(self, module_string: str) -> tuple[str, str]:
         """
@@ -344,6 +345,8 @@
                     raise e
 
                 is_action_candidate = context.resolved and 
bool(context.redirect_list)
+                if is_action_candidate:
+                    self._resolved_action = context.resolved_fqcn
 
             if is_action_candidate:
                 # finding more than one module name is a problem
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/ansible_core-2.19.3/lib/ansible/playbook/block.py 
new/ansible_core-2.19.4/lib/ansible/playbook/block.py
--- old/ansible_core-2.19.3/lib/ansible/playbook/block.py       2025-10-06 
19:22:06.000000000 +0200
+++ new/ansible_core-2.19.4/lib/ansible/playbook/block.py       2025-11-05 
00:27:03.000000000 +0100
@@ -17,7 +17,6 @@
 
 from __future__ import annotations
 
-import ansible.constants as C
 from ansible.errors import AnsibleParserError
 from ansible.module_utils.common.sentinel import Sentinel
 from ansible.playbook.attribute import NonInheritableFieldAttribute
@@ -376,8 +375,7 @@
                     filtered_block = evaluate_block(task)
                     if filtered_block.has_tasks():
                         tmp_list.append(filtered_block)
-                elif ((task.action in C._ACTION_META and task.implicit) or
-                        task.evaluate_tags(self._play.only_tags, 
self._play.skip_tags, all_vars=all_vars)):
+                elif task.evaluate_tags(self._play.only_tags, 
self._play.skip_tags, all_vars=all_vars):
                     tmp_list.append(task)
             return tmp_list
 
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/ansible_core-2.19.3/lib/ansible/playbook/helpers.py 
new/ansible_core-2.19.4/lib/ansible/playbook/helpers.py
--- old/ansible_core-2.19.3/lib/ansible/playbook/helpers.py     2025-10-06 
19:22:06.000000000 +0200
+++ new/ansible_core-2.19.4/lib/ansible/playbook/helpers.py     2025-11-05 
00:27:03.000000000 +0100
@@ -165,17 +165,29 @@
                     subdir = 'tasks'
                     if use_handlers:
                         subdir = 'handlers'
+                    try:
+                        include_target = 
templar.template(task.args['_raw_params'])
+                    except AnsibleUndefinedVariable as ex:
+                        raise AnsibleParserError(
+                            message=f"Error when evaluating variable in import 
path {task.args['_raw_params']!r}.",
+                            help_text="When using static imports, ensure that 
any variables used in their names are defined in vars/vars_files\n"
+                                      "or extra-vars passed in from the 
command line. Static imports cannot use variables from facts or inventory\n"
+                                      "sources like group or host vars.",
+                            obj=task_ds,
+                        ) from ex
+                    # FIXME this appears to be (almost?) duplicate code as in 
IncludedFile for include_tasks
                     while parent_include is not None:
                         if not isinstance(parent_include, TaskInclude):
                             parent_include = parent_include._parent
                             continue
-                        parent_include.post_validate(templar=templar)
-                        parent_include_dir = 
os.path.dirname(parent_include.args.get('_raw_params'))
+                        if isinstance(parent_include, IncludeRole):
+                            parent_include_dir = parent_include._role_path
+                        else:
+                            parent_include_dir = 
os.path.dirname(templar.template(parent_include.args.get('_raw_params')))
                         if cumulative_path is None:
                             cumulative_path = parent_include_dir
                         elif not os.path.isabs(cumulative_path):
                             cumulative_path = os.path.join(parent_include_dir, 
cumulative_path)
-                        include_target = 
templar.template(task.args['_raw_params'])
                         if task._role:
                             new_basedir = os.path.join(task._role._role_path, 
subdir, cumulative_path)
                             include_file = 
loader.path_dwim_relative(new_basedir, subdir, include_target)
@@ -189,16 +201,6 @@
                             parent_include = parent_include._parent
 
                     if not found:
-                        try:
-                            include_target = 
templar.template(task.args['_raw_params'])
-                        except AnsibleUndefinedVariable as ex:
-                            raise AnsibleParserError(
-                                message=f"Error when evaluating variable in 
import path {task.args['_raw_params']!r}.",
-                                help_text="When using static imports, ensure 
that any variables used in their names are defined in vars/vars_files\n"
-                                "or extra-vars passed in from the command 
line. Static imports cannot use variables from facts or inventory\n"
-                                "sources like group or host vars.",
-                                obj=task_ds,
-                            ) from ex
                         if task._role:
                             include_file = 
loader.path_dwim_relative(task._role._role_path, subdir, include_target)
                         else:
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/ansible_core-2.19.3/lib/ansible/playbook/play.py 
new/ansible_core-2.19.4/lib/ansible/playbook/play.py
--- old/ansible_core-2.19.3/lib/ansible/playbook/play.py        2025-10-06 
19:22:06.000000000 +0200
+++ new/ansible_core-2.19.4/lib/ansible/playbook/play.py        2025-11-05 
00:27:03.000000000 +0100
@@ -303,23 +303,13 @@
 
         t = Task(block=flush_block)
         t.action = 'meta'
-        t.resolved_action = 'ansible.builtin.meta'
+        t._resolved_action = 'ansible.builtin.meta'
         t.args['_raw_params'] = 'flush_handlers'
         t.implicit = True
         t.set_loader(self._loader)
+        t.tags = ['always']
 
-        if self.tags:
-            # Avoid calling flush_handlers in case the whole play is skipped 
on tags,
-            # this could be performance improvement since calling 
flush_handlers on
-            # large inventories could be expensive even if no hosts are 
notified
-            # since we call flush_handlers per host.
-            # Block.filter_tagged_tasks ignores evaluating tags on implicit 
meta
-            # tasks so we need to explicitly call Task.evaluate_tags here.
-            t.tags = self.tags
-            if t.evaluate_tags(self.only_tags, self.skip_tags, 
all_vars=self.vars):
-                flush_block.block = [t]
-        else:
-            flush_block.block = [t]
+        flush_block.block = [t]
 
         # NOTE keep flush_handlers tasks even if a section has no regular 
tasks,
         #      there may be notified handlers from the previous section
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/ansible_core-2.19.3/lib/ansible/playbook/task.py 
new/ansible_core-2.19.4/lib/ansible/playbook/task.py
--- old/ansible_core-2.19.3/lib/ansible/playbook/task.py        2025-10-06 
19:22:06.000000000 +0200
+++ new/ansible_core-2.19.4/lib/ansible/playbook/task.py        2025-11-05 
00:27:03.000000000 +0100
@@ -41,7 +41,7 @@
 from ansible.playbook.taggable import Taggable
 from ansible._internal import _task
 from ansible._internal._templating import _marker_behaviors
-from ansible._internal._templating._jinja_bits import is_possibly_all_template
+from ansible._internal._templating._jinja_bits import 
is_possibly_all_template, is_possibly_template
 from ansible._internal._templating._engine import TemplateEngine, 
TemplateOptions
 from ansible.utils.collection_loader import AnsibleCollectionConfig
 from ansible.utils.display import Display
@@ -101,7 +101,7 @@
         self._role = role
         self._parent = None
         self.implicit = False
-        self.resolved_action: str | None = None
+        self._resolved_action: str | None = None
 
         if task_include:
             self._parent = task_include
@@ -110,6 +110,38 @@
 
         super(Task, self).__init__()
 
+    _resolved_action_warning = (
+        "A plugin is sampling the task's resolved_action when it is not 
resolved. "
+        "This can be caused by callback plugins using the resolved_action 
attribute too "
+        "early (such as in v2_playbook_on_task_start for a task using the 
action/local_action "
+        "keyword), or too late (such as in v2_runner_on_ok for a task with a 
loop). "
+        "To maximize compatibility with user features, callback plugins should 
"
+        "only use this attribute in v2_runner_on_ok/v2_runner_on_failed for 
tasks "
+        "without a loop, and v2_runner_item_on_ok/v2_runner_item_on_failed 
otherwise."
+    )
+
+    @property
+    def resolved_action(self) -> str | None:
+        """The templated and resolved FQCN of the task action or None.
+
+        If the action is a template, callback plugins can only use this value 
in certain methods.
+        - v2_runner_on_ok and v2_runner_on_failed if there's no task loop
+        - v2_runner_item_on_ok and v2_runner_item_on_failed if there is a task 
loop
+        """
+        # Consider deprecating this because it's difficult to use?
+        # Moving it to the task result would improve the no-loop limitation on 
v2_runner_on_ok
+        # but then wouldn't be accessible to v2_playbook_on_task_start, 
*_on_skipped, etc.
+        if self._resolved_action is not None:
+            return self._resolved_action
+        if not is_possibly_template(self.action):
+            try:
+                return self._resolve_action(self.action)
+            except AnsibleParserError:
+                display.warning(self._resolved_action_warning, obj=self.action)
+        else:
+            display.warning(self._resolved_action_warning, obj=self.action)
+        return None
+
     def get_name(self, include_role_fqcn=True):
         """ return the name of the task """
 
@@ -168,7 +200,7 @@
         else:
             module_or_action_context = action_context.plugin_load_context
 
-        self.resolved_action = module_or_action_context.resolved_fqcn
+        self._resolved_action = module_or_action_context.resolved_fqcn
 
         action_type: type[ActionBase] = action_context.object
 
@@ -282,6 +314,9 @@
             # But if it wasn't, we can add the yaml object now to get more 
detail
             raise AnsibleParserError("Error parsing task arguments.", obj=ds) 
from ex
 
+        if args_parser._resolved_action is not None:
+            self._resolved_action = args_parser._resolved_action
+
         new_ds['action'] = action
         new_ds['args'] = args
         new_ds['delegate_to'] = delegate_to
@@ -465,7 +500,7 @@
             new_me._role = self._role
 
         new_me.implicit = self.implicit
-        new_me.resolved_action = self.resolved_action
+        new_me._resolved_action = self._resolved_action
         new_me._uuid = self._uuid
 
         return new_me
@@ -482,7 +517,7 @@
                 data['role'] = self._role.serialize()
 
             data['implicit'] = self.implicit
-            data['resolved_action'] = self.resolved_action
+            data['_resolved_action'] = self._resolved_action
 
         return data
 
@@ -513,7 +548,7 @@
             del data['role']
 
         self.implicit = data.get('implicit', False)
-        self.resolved_action = data.get('resolved_action')
+        self._resolved_action = data.get('_resolved_action')
 
         super(Task, self).deserialize(data)
 
@@ -591,7 +626,7 @@
     def dump_attrs(self):
         """Override to smuggle important non-FieldAttribute values back to the 
controller."""
         attrs = super().dump_attrs()
-        attrs.update(resolved_action=self.resolved_action)
+        attrs.update(_resolved_action=self._resolved_action)
         return attrs
 
     def _resolve_conditional(
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' 
old/ansible_core-2.19.3/lib/ansible/plugins/connection/psrp.py 
new/ansible_core-2.19.4/lib/ansible/plugins/connection/psrp.py
--- old/ansible_core-2.19.3/lib/ansible/plugins/connection/psrp.py      
2025-10-06 19:22:06.000000000 +0200
+++ new/ansible_core-2.19.4/lib/ansible/plugins/connection/psrp.py      
2025-11-05 00:27:03.000000000 +0100
@@ -331,7 +331,7 @@
     from pypsrp.host import PSHost, PSHostUserInterface
     from pypsrp.powershell import PowerShell, RunspacePool
     from pypsrp.wsman import WSMan
-    from requests.exceptions import ConnectionError, ConnectTimeout
+    from requests.exceptions import ConnectionError, ConnectTimeout, 
ReadTimeout
 except ImportError as err:
     HAS_PYPSRP = False
     PYPSRP_IMP_ERR = err
@@ -479,11 +479,16 @@
             pwsh_in_data = in_data
             display.vvv(u"PSRP: EXEC %s" % script, host=self._psrp_host)
 
-        rc, stdout, stderr = self._exec_psrp_script(
-            script=script,
-            input_data=pwsh_in_data.splitlines() if pwsh_in_data else None,
-            arguments=script_args,
-        )
+        try:
+            rc, stdout, stderr = self._exec_psrp_script(
+                script=script,
+                input_data=pwsh_in_data.splitlines() if pwsh_in_data else None,
+                arguments=script_args,
+            )
+        except ReadTimeout as e:
+            raise AnsibleConnectionFailure(
+                "HTTP read timeout during PSRP script execution"
+            ) from e
         return rc, stdout, stderr
 
     def put_file(self, in_path: str, out_path: str) -> None:
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' 
old/ansible_core-2.19.3/lib/ansible/plugins/lookup/config.py 
new/ansible_core-2.19.4/lib/ansible/plugins/lookup/config.py
--- old/ansible_core-2.19.3/lib/ansible/plugins/lookup/config.py        
2025-10-06 19:22:06.000000000 +0200
+++ new/ansible_core-2.19.4/lib/ansible/plugins/lookup/config.py        
2025-11-05 00:27:03.000000000 +0100
@@ -88,31 +88,6 @@
 from ansible.plugins.lookup import LookupBase
 
 
-def _get_plugin_config(pname, ptype, config, variables):
-    # plugin creates settings on load, this is cached so not too expensive to 
redo
-    loader = getattr(plugin_loader, '%s_loader' % ptype)
-    p = loader.get(pname, class_only=True)
-
-    if p is None:
-        raise AnsibleError(f"Unable to load {ptype} plugin {pname!r}.")
-
-    result, origin = C.config.get_config_value_and_origin(config, 
plugin_type=ptype, plugin_name=p._load_name, variables=variables)
-
-    return result, origin
-
-
-def _get_global_config(config):
-    try:
-        result = getattr(C, config)
-    except AttributeError:
-        raise AnsibleUndefinedConfigEntry(f"Setting {config!r} does not 
exist.") from None
-
-    if callable(result):
-        raise ValueError(f"Invalid setting {config!r} attempted.")
-
-    return result
-
-
 class LookupModule(LookupBase):
 
     def run(self, terms, variables=None, **kwargs):
@@ -135,18 +110,26 @@
 
             result = Sentinel
             origin = None
+
+            # plugin creates settings on load, we ensure that happens here
+            if pname:
+                # this is cached so not too expensive
+                loader = getattr(plugin_loader, f'{ptype}_loader')
+                p = loader.get(pname, class_only=True)
+                if p is None:
+                    raise AnsibleError(f"Unable to load {ptype} plugin 
{pname!r}.")
             try:
-                if pname:
-                    result, origin = _get_plugin_config(pname, ptype, term, 
variables)
-                else:
-                    result = _get_global_config(term)
-            except AnsibleUndefinedConfigEntry:
-                if missing == 'error':
-                    raise
-                elif missing == 'warn':
-                    self._display.warning(f"Skipping, did not find setting 
{term!r}.")
-                elif missing == 'skip':
-                    pass  # this is not needed, but added to have all 3 
options stated
+                result, origin = C.config.get_config_value_and_origin(term, 
plugin_type=ptype, plugin_name=pname, variables=variables)
+            except AnsibleUndefinedConfigEntry as e:
+                match missing:
+                    case 'error':
+                        raise
+                    case 'skip':
+                        pass
+                    case 'warn':
+                        self._display.error_as_warning(msg=f"Skipping 
{term}.", exception=e)
+                    case _:
+                        raise AnsibleError(f"Invalid option for error 
handling, missing must be error, warn or skip, got: {missing}.") from e
 
             if result is not Sentinel:
                 if show_origin:
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' 
old/ansible_core-2.19.3/lib/ansible/plugins/strategy/__init__.py 
new/ansible_core-2.19.4/lib/ansible/plugins/strategy/__init__.py
--- old/ansible_core-2.19.3/lib/ansible/plugins/strategy/__init__.py    
2025-10-06 19:22:06.000000000 +0200
+++ new/ansible_core-2.19.4/lib/ansible/plugins/strategy/__init__.py    
2025-11-05 00:27:03.000000000 +0100
@@ -900,7 +900,7 @@
         display.warning("%s task does not support when conditional" % 
task_name)
 
     def _execute_meta(self, task: Task, play_context, iterator, target_host: 
Host):
-        task.resolved_action = 'ansible.builtin.meta'  # _post_validate_args 
is never called for meta actions, so resolved_action hasn't been set
+        task._resolved_action = 'ansible.builtin.meta'  # _post_validate_args 
is never called for meta actions, so resolved_action hasn't been set
 
         # meta tasks store their args in the _raw_params field of args,
         # since they do not use k=v pairs, so get that
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/ansible_core-2.19.3/lib/ansible/release.py 
new/ansible_core-2.19.4/lib/ansible/release.py
--- old/ansible_core-2.19.3/lib/ansible/release.py      2025-10-06 
19:22:06.000000000 +0200
+++ new/ansible_core-2.19.4/lib/ansible/release.py      2025-11-05 
00:27:03.000000000 +0100
@@ -17,6 +17,6 @@
 
 from __future__ import annotations
 
-__version__ = '2.19.3'
+__version__ = '2.19.4'
 __author__ = 'Ansible, Inc.'
 __codename__ = "What Is and What Should Never Be"
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' 
old/ansible_core-2.19.3/test/integration/targets/ansible-doc/runme.sh 
new/ansible_core-2.19.4/test/integration/targets/ansible-doc/runme.sh
--- old/ansible_core-2.19.3/test/integration/targets/ansible-doc/runme.sh       
2025-10-06 19:22:06.000000000 +0200
+++ new/ansible_core-2.19.4/test/integration/targets/ansible-doc/runme.sh       
2025-11-05 00:27:03.000000000 +0100
@@ -211,6 +211,13 @@
 output=$(ANSIBLE_LIBRARY='./nolibrary' ansible-doc --metadata-dump 
--playbook-dir broken-docs testns.testcol 2>&1 | grep -c 'ERROR' || true)
 test "${output}" -eq 1
 
+# ensure --metadata-dump does not crash if the ansible_collections is nested 
(https://github.com/ansible/ansible/issues/84909)
+testdir="$(pwd)"
+pbdir="collections/ansible_collections/testns/testcol/playbooks"
+cd "$pbdir"
+ANSIBLE_COLLECTIONS_PATH="$testdir/$pbdir/collections" ansible-doc -vvv 
--metadata-dump --no-fail-on-errors
+cd "$testdir"
+
 echo "test doc list on broken role metadata"
 # ensure that role doc does not fail when --no-fail-on-errors is supplied
 ANSIBLE_LIBRARY='./nolibrary' ansible-doc --no-fail-on-errors --playbook-dir 
broken-docs testns.testcol.testrole -t role 1>/dev/null 2>&1
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' 
old/ansible_core-2.19.3/test/integration/targets/collections/test_task_resolved_plugin/callback_plugins/display_resolved_action.py
 
new/ansible_core-2.19.4/test/integration/targets/collections/test_task_resolved_plugin/callback_plugins/display_resolved_action.py
--- 
old/ansible_core-2.19.3/test/integration/targets/collections/test_task_resolved_plugin/callback_plugins/display_resolved_action.py
  2025-10-06 19:22:06.000000000 +0200
+++ 
new/ansible_core-2.19.4/test/integration/targets/collections/test_task_resolved_plugin/callback_plugins/display_resolved_action.py
  2025-11-05 00:27:03.000000000 +0100
@@ -9,6 +9,12 @@
     short_description: Displays the requested and resolved actions at the end 
of a playbook.
     description:
         - Displays the requested and resolved actions in the format "requested 
== resolved".
+    options:
+      test_on_task_start:
+        description: Test using task.resolved_action before it is reliably 
resolved.
+        default: False
+        env:
+          - name: ANSIBLE_TEST_ON_TASK_START
     requirements:
       - Enable in configuration.
 """
@@ -25,11 +31,14 @@
 
     def __init__(self, *args, **kwargs):
         super(CallbackModule, self).__init__(*args, **kwargs)
-        self.requested_to_resolved = {}
 
-    def v2_runner_on_ok(self, result):
-        self.requested_to_resolved[result.task.action] = 
result.task.resolved_action
+    def v2_playbook_on_task_start(self, task, is_conditional):
+        if self.get_option("test_on_task_start"):
+            self._display.display(f"v2_playbook_on_task_start: {task.action} 
== {task.resolved_action}")
+
+    def v2_runner_item_on_ok(self, result):
+        self._display.display(f"v2_runner_item_on_ok: {result.task.action} == 
{result.task.resolved_action}")
 
-    def v2_playbook_on_stats(self, stats):
-        for requested, resolved in self.requested_to_resolved.items():
-            self._display.display("%s == %s" % (requested, resolved), 
screen_only=True)
+    def v2_runner_on_ok(self, result):
+        if not result.task.loop:
+            self._display.display(f"v2_runner_on_ok: {result.task.action} == 
{result.task.resolved_action}")
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' 
old/ansible_core-2.19.3/test/integration/targets/collections/test_task_resolved_plugin/dynamic_action.yml
 
new/ansible_core-2.19.4/test/integration/targets/collections/test_task_resolved_plugin/dynamic_action.yml
--- 
old/ansible_core-2.19.3/test/integration/targets/collections/test_task_resolved_plugin/dynamic_action.yml
   1970-01-01 01:00:00.000000000 +0100
+++ 
new/ansible_core-2.19.4/test/integration/targets/collections/test_task_resolved_plugin/dynamic_action.yml
   2025-11-05 00:27:03.000000000 +0100
@@ -0,0 +1,10 @@
+---
+- hosts: all
+  gather_facts: no
+  tasks:
+    - name: Run dynamic action
+      action: "{{ inventory_hostname }}"
+
+    - name: Run dynamic action in loop
+      action: "{{ inventory_hostname }}"
+      loop: [1]
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' 
old/ansible_core-2.19.3/test/integration/targets/collections/test_task_resolved_plugin/unqualified.yml
 
new/ansible_core-2.19.4/test/integration/targets/collections/test_task_resolved_plugin/unqualified.yml
--- 
old/ansible_core-2.19.3/test/integration/targets/collections/test_task_resolved_plugin/unqualified.yml
      2025-10-06 19:22:06.000000000 +0200
+++ 
new/ansible_core-2.19.4/test/integration/targets/collections/test_task_resolved_plugin/unqualified.yml
      2025-11-05 00:27:03.000000000 +0100
@@ -4,5 +4,5 @@
   tasks:
     - legacy_action:
     - legacy_module:
-    - debug:
-    - ping:
+    - local_action: debug
+    - action: ping
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' 
old/ansible_core-2.19.3/test/integration/targets/collections/test_task_resolved_plugin.sh
 
new/ansible_core-2.19.4/test/integration/targets/collections/test_task_resolved_plugin.sh
--- 
old/ansible_core-2.19.3/test/integration/targets/collections/test_task_resolved_plugin.sh
   2025-10-06 19:22:06.000000000 +0200
+++ 
new/ansible_core-2.19.4/test/integration/targets/collections/test_task_resolved_plugin.sh
   2025-11-05 00:27:03.000000000 +0100
@@ -15,6 +15,22 @@
     grep -q out.txt -e "$result"
 done
 
+# Test local_action/action warning
+export ANSIBLE_TEST_ON_TASK_START=True
+ansible-playbook -i debug, test_task_resolved_plugin/dynamic_action.yml "$@" 
2>&1 | tee out.txt
+grep -q out.txt -e "A plugin is sampling the task's resolved_action when it is 
not resolved"
+grep -q out.txt -e "v2_playbook_on_task_start: {{ inventory_hostname }} == 
None"
+grep -q out.txt -e "v2_runner_on_ok: debug == ansible.builtin.debug"
+grep -q out.txt -e "v2_runner_item_on_ok: debug == ansible.builtin.debug"
+
+# Test static actions don't cause a warning
+ansible-playbook test_task_resolved_plugin/unqualified.yml "$@" 2>&1 | tee 
out.txt
+grep -v out.txt -e "A plugin is sampling the task's resolved_action when it is 
not resolved"
+for result in "${action_resolution[@]}"; do
+    grep -q out.txt -e "v2_playbook_on_task_start: $result"
+done
+unset ANSIBLE_TEST_ON_TASK_START
+
 ansible-playbook test_task_resolved_plugin/unqualified_and_collections_kw.yml 
"$@" | tee out.txt
 action_resolution=(
     "legacy_action == legacy_action"
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' 
old/ansible_core-2.19.3/test/integration/targets/connection_ssh/aliases 
new/ansible_core-2.19.4/test/integration/targets/connection_ssh/aliases
--- old/ansible_core-2.19.3/test/integration/targets/connection_ssh/aliases     
2025-10-06 19:22:06.000000000 +0200
+++ new/ansible_core-2.19.4/test/integration/targets/connection_ssh/aliases     
2025-11-05 00:27:03.000000000 +0100
@@ -2,4 +2,5 @@
 shippable/posix/group3
 needs/target/connection
 needs/target/setup_test_user
+needs/target/test_utils
 setup/always/setup_passlib_controller  # required for setup_test_user
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' 
old/ansible_core-2.19.3/test/integration/targets/connection_ssh/runme.sh 
new/ansible_core-2.19.4/test/integration/targets/connection_ssh/runme.sh
--- old/ansible_core-2.19.3/test/integration/targets/connection_ssh/runme.sh    
2025-10-06 19:22:06.000000000 +0200
+++ new/ansible_core-2.19.4/test/integration/targets/connection_ssh/runme.sh    
2025-11-05 00:27:03.000000000 +0100
@@ -17,7 +17,7 @@
         # ansible with timeout. If we time out, our custom prompt was 
successfully
         # searched for. It's a weird way of doing things, but it does ensure
         # that the flag gets passed to sshpass.
-        timeout 5 ansible -m ping \
+        ../test_utils/scripts/timeout.py 5 -- ansible -m ping \
             -e ansible_connection=ssh \
             -e ansible_ssh_password_mechanism=sshpass \
             -e ansible_sshpass_prompt=notThis: \
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' 
old/ansible_core-2.19.3/test/integration/targets/deprecations/runme.sh 
new/ansible_core-2.19.4/test/integration/targets/deprecations/runme.sh
--- old/ansible_core-2.19.3/test/integration/targets/deprecations/runme.sh      
2025-10-06 19:22:06.000000000 +0200
+++ new/ansible_core-2.19.4/test/integration/targets/deprecations/runme.sh      
2025-11-05 00:27:03.000000000 +0100
@@ -25,8 +25,9 @@
 # check for entry key deprecation including the name of the option, must be 
defined to trigger
 [ "$(ANSIBLE_CONFIG='entry_key_deprecated.cfg' ansible -m meta -a 'noop' 
localhost 2>&1 | grep -c "\[DEPRECATION WARNING\]: \[testing\]deprecated 
option.")" -eq "1" ]
 
+# DTFIX: fix issue with x2 deprecation and wrong pllugin attribution
 # check for deprecation of entry itself, must be consumed to trigger
-[ "$(ANSIBLE_TEST_ENTRY2=1 ansible -m debug -a 'msg={{q("config", 
"_Z_TEST_ENTRY_2")}}' localhost  2>&1 | grep -c 'DEPRECATION')" -eq "1" ]
+[ "$(ANSIBLE_TEST_ENTRY2=1 ansible -m debug -a 'msg={{q("config", 
"_Z_TEST_ENTRY_2")}}' localhost  2>&1 | grep -c 'DEPRECATION')" -eq "2" ]
 
 # check for entry deprecation, just need key defined to trigger
 [ "$(ANSIBLE_CONFIG='entry_key_deprecated2.cfg' ansible -m meta -a 'noop'  
localhost 2>&1 | grep -c 'DEPRECATION')" -eq "1" ]
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' 
old/ansible_core-2.19.3/test/integration/targets/get_url/tasks/main.yml 
new/ansible_core-2.19.4/test/integration/targets/get_url/tasks/main.yml
--- old/ansible_core-2.19.3/test/integration/targets/get_url/tasks/main.yml     
2025-10-06 19:22:06.000000000 +0200
+++ new/ansible_core-2.19.4/test/integration/targets/get_url/tasks/main.yml     
2025-11-05 00:27:03.000000000 +0100
@@ -396,6 +396,8 @@
     src: "testserver.py"
     dest: "{{ remote_tmp_dir }}/testserver.py"
 
+# NOTE: This http test server will live for only the timeout specified in 
"async", so all uses
+# of it must be grouped relatively close together.
 - name: start SimpleHTTPServer for issues 27617
   shell: cd {{ files_dir }} && {{ ansible_python.executable }} {{ 
remote_tmp_dir}}/testserver.py {{ http_port }}
   async: 90
@@ -578,6 +580,19 @@
       - "stat_result_sha256_with_file_scheme_71420.stat.exists == true"
       - "stat_result_sha256_checksum_only.stat.exists == true"
 
+- name: Test for incomplete data read (issue 85164)
+  get_url:
+    url: 'http://localhost:{{ http_port }}/incompleteRead'
+    dest: '{{ remote_tmp_dir }}/85164.txt'
+  ignore_errors: true
+  register: result
+
+- name: Assert we have an incomplete read failure
+  assert:
+    that:
+      - result is failed
+      - '"Incomplete read" in result.msg'
+
 #https://github.com/ansible/ansible/issues/16191
 - name: Test url split with no filename
   get_url:
@@ -761,16 +776,3 @@
 - assert:
     that:
       - get_dir_filename.dest == remote_tmp_dir ~ "/filename.json"
-
-- name: Test for incomplete data read (issue 85164)
-  get_url:
-    url: 'http://localhost:{{ http_port }}/incompleteRead'
-    dest: '{{ remote_tmp_dir }}/85164.txt'
-  ignore_errors: true
-  register: result
-
-- name: Assert we have an incomplete read failure
-  assert:
-    that:
-      - result is failed
-      - '"Incomplete read" in result.msg'
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' 
old/ansible_core-2.19.3/test/integration/targets/handlers/runme.sh 
new/ansible_core-2.19.4/test/integration/targets/handlers/runme.sh
--- old/ansible_core-2.19.3/test/integration/targets/handlers/runme.sh  
2025-10-06 19:22:06.000000000 +0200
+++ new/ansible_core-2.19.4/test/integration/targets/handlers/runme.sh  
2025-11-05 00:27:03.000000000 +0100
@@ -229,6 +229,13 @@
 
 ANSIBLE_DEBUG=1 ansible-playbook tagged_play.yml --skip-tags the_whole_play 
"$@" 2>&1 | tee out.txt
 [ "$(grep out.txt -ce 'META: triggered running handlers')" = "0" ]
+[ "$(grep out.txt -ce 'No handler notifications for')" = "0" ]
 [ "$(grep out.txt -ce 'handler_ran')" = "0" ]
+[ "$(grep out.txt -ce 'handler1_ran')" = "0" ]
 
 ansible-playbook rescue_flush_handlers.yml "$@"
+
+ANSIBLE_DEBUG=1 ansible-playbook tagged_play.yml --tags task_tag "$@" 2>&1 | 
tee out.txt
+[ "$(grep out.txt -ce 'META: triggered running handlers')" = "1" ]
+[ "$(grep out.txt -ce 'handler_ran')" = "0" ]
+[ "$(grep out.txt -ce 'handler1_ran')" = "1" ]
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' 
old/ansible_core-2.19.3/test/integration/targets/handlers/tagged_play.yml 
new/ansible_core-2.19.4/test/integration/targets/handlers/tagged_play.yml
--- old/ansible_core-2.19.3/test/integration/targets/handlers/tagged_play.yml   
2025-10-06 19:22:06.000000000 +0200
+++ new/ansible_core-2.19.4/test/integration/targets/handlers/tagged_play.yml   
2025-11-05 00:27:03.000000000 +0100
@@ -2,9 +2,19 @@
   gather_facts: false
   tags: the_whole_play
   tasks:
-    - command: echo
+    - debug:
+      changed_when: true
       notify: h
+
+    - debug:
+      changed_when: true
+      notify: h1
+      tags: task_tag
   handlers:
     - name: h
       debug:
         msg: handler_ran
+
+    - name: h1
+      debug:
+        msg: handler1_ran
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' 
old/ansible_core-2.19.3/test/integration/targets/include_import/roles/nested_tasks/tasks/bar.yml
 
new/ansible_core-2.19.4/test/integration/targets/include_import/roles/nested_tasks/tasks/bar.yml
--- 
old/ansible_core-2.19.3/test/integration/targets/include_import/roles/nested_tasks/tasks/bar.yml
    1970-01-01 01:00:00.000000000 +0100
+++ 
new/ansible_core-2.19.4/test/integration/targets/include_import/roles/nested_tasks/tasks/bar.yml
    2025-11-05 00:27:03.000000000 +0100
@@ -0,0 +1 @@
+- import_tasks: does-not-exist.yml
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' 
old/ansible_core-2.19.3/test/integration/targets/include_import/roles/nested_tasks/tasks/foo.yml
 
new/ansible_core-2.19.4/test/integration/targets/include_import/roles/nested_tasks/tasks/foo.yml
--- 
old/ansible_core-2.19.3/test/integration/targets/include_import/roles/nested_tasks/tasks/foo.yml
    1970-01-01 01:00:00.000000000 +0100
+++ 
new/ansible_core-2.19.4/test/integration/targets/include_import/roles/nested_tasks/tasks/foo.yml
    2025-11-05 00:27:03.000000000 +0100
@@ -0,0 +1 @@
+- include_tasks: bar.yml
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' 
old/ansible_core-2.19.3/test/integration/targets/include_import/roles/nested_tasks/tasks/main.yml
 
new/ansible_core-2.19.4/test/integration/targets/include_import/roles/nested_tasks/tasks/main.yml
--- 
old/ansible_core-2.19.3/test/integration/targets/include_import/roles/nested_tasks/tasks/main.yml
   1970-01-01 01:00:00.000000000 +0100
+++ 
new/ansible_core-2.19.4/test/integration/targets/include_import/roles/nested_tasks/tasks/main.yml
   2025-11-05 00:27:03.000000000 +0100
@@ -0,0 +1 @@
+- import_tasks: foo.yml
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' 
old/ansible_core-2.19.3/test/integration/targets/include_import/runme.sh 
new/ansible_core-2.19.4/test/integration/targets/include_import/runme.sh
--- old/ansible_core-2.19.3/test/integration/targets/include_import/runme.sh    
2025-10-06 19:22:06.000000000 +0200
+++ new/ansible_core-2.19.4/test/integration/targets/include_import/runme.sh    
2025-11-05 00:27:03.000000000 +0100
@@ -155,3 +155,9 @@
 test "$(grep -c 'No file specified for ansible.builtin.include_tasks' 
test_null_include_filename.out)" = 1
 test "$(grep -c '.*/include_import/null_filename/tasks.yml:4:3.*' 
test_null_include_filename.out)" = 1
 test "$(grep -c '\- name: invalid include_task definition' 
test_null_include_filename.out)" = 1
+
+# https://github.com/ansible/ansible/issues/69882
+set +e
+ansible-playbook test_nested_non_existent_tasks.yml 2>&1 | tee 
test_nested_non_existent_tasks.out
+set -e
+test "$(grep -c 'Could not find or access' 
test_nested_non_existent_tasks.out)" = 3
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' 
old/ansible_core-2.19.3/test/integration/targets/include_import/test_nested_non_existent_tasks.yml
 
new/ansible_core-2.19.4/test/integration/targets/include_import/test_nested_non_existent_tasks.yml
--- 
old/ansible_core-2.19.3/test/integration/targets/include_import/test_nested_non_existent_tasks.yml
  1970-01-01 01:00:00.000000000 +0100
+++ 
new/ansible_core-2.19.4/test/integration/targets/include_import/test_nested_non_existent_tasks.yml
  2025-11-05 00:27:03.000000000 +0100
@@ -0,0 +1,5 @@
+- hosts: localhost
+  gather_facts: false
+  tasks:
+    - include_role:
+        name: nested_tasks
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' 
old/ansible_core-2.19.3/test/integration/targets/include_import_tasks_nested/tasks/main.yml
 
new/ansible_core-2.19.4/test/integration/targets/include_import_tasks_nested/tasks/main.yml
--- 
old/ansible_core-2.19.3/test/integration/targets/include_import_tasks_nested/tasks/main.yml
 2025-10-06 19:22:06.000000000 +0200
+++ 
new/ansible_core-2.19.4/test/integration/targets/include_import_tasks_nested/tasks/main.yml
 2025-11-05 00:27:03.000000000 +0100
@@ -10,4 +10,9 @@
     that:
       - nested_adjacent_count|int == 2
 
+- set_fact:
+    not_available_at_parsing: root
+
 - import_tasks: "{{ role_path }}/tests/main.yml"
+  become: true
+  become_user: "{{ not_available_at_parsing }}"
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' 
old/ansible_core-2.19.3/test/integration/targets/include_import_tasks_nested/tests/tests_relative.yml
 
new/ansible_core-2.19.4/test/integration/targets/include_import_tasks_nested/tests/tests_relative.yml
--- 
old/ansible_core-2.19.3/test/integration/targets/include_import_tasks_nested/tests/tests_relative.yml
       2025-10-06 19:22:06.000000000 +0200
+++ 
new/ansible_core-2.19.4/test/integration/targets/include_import_tasks_nested/tests/tests_relative.yml
       2025-11-05 00:27:03.000000000 +0100
@@ -0,0 +1,6 @@
+- command: whoami
+  register: r
+
+- assert:
+    that:
+      - r.stdout == not_available_at_parsing
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' 
old/ansible_core-2.19.3/test/integration/targets/lookup_config/tasks/main.yml 
new/ansible_core-2.19.4/test/integration/targets/lookup_config/tasks/main.yml
--- 
old/ansible_core-2.19.3/test/integration/targets/lookup_config/tasks/main.yml   
    2025-10-06 19:22:06.000000000 +0200
+++ 
new/ansible_core-2.19.4/test/integration/targets/lookup_config/tasks/main.yml   
    2025-11-05 00:27:03.000000000 +0100
@@ -83,14 +83,26 @@
   ignore_errors: yes
   register: lookup_config_12
 
+- name: origins
+  set_fact:
+    config_origin1: "{{ lookup('config', '_Z_TEST_ENTRY', show_origin=True) }}"
+  ignore_errors: yes
+
+- name: var sets it
+  set_fact:
+    config_origin2: "{{ lookup('config', '_Z_TEST_ENTRY', show_origin=True) }}"
+  ignore_errors: yes
+  vars:
+    _z_test_entry: yolo
+
 - name: Verify lookup_config
   assert:
     that:
       - '"meow" in lookup("config", "ANSIBLE_COW_ACCEPTLIST")'
       - lookup_config_1 is failed
-      - lookup_config_1.msg is contains "Setting 'THIS_DOES_NOT_EXIST' does 
not exist."
+      - lookup_config_1.msg is contains "No config definition exists for 
'THIS_DOES_NOT_EXIST'"
       - lookup_config_2 is failed
-      - lookup_config_2.msg is contains "Setting 'THIS_DOES_NOT_EXIST' does 
not exist."
+      - lookup_config_2.msg is contains "No config definition exists for 
'THIS_DOES_NOT_EXIST'"
       - lookup_config_3 is success
       - 'lookup3|length == 0'
       - lookup_config_4 is success
@@ -100,7 +112,7 @@
       - lookup_config_6 is failed
       - '"Invalid setting identifier" in lookup_config_6.msg'
       - lookup_config_7 is failed
-      - '"Invalid setting" in lookup_config_7.msg'
+      - lookup_config_7.msg is contains "No config definition exists for 
'ConfigManager'"
       - lookup_config_8 is failed
       - '"Both plugin_type and plugin_name" in lookup_config_8.msg'
       - lookup_config_9 is failed
@@ -114,3 +126,6 @@
       - ssh_user_and_port == ['lola', 2022]
       - "ssh_user_and_port_and_origin == [['lola', 'var: ansible_ssh_user'], 
[2022, 'var: ansible_ssh_port']]"
       - yolo_remote == ["yolo"]
+      - config_origin1[1] == "default"
+      - config_origin2[0] == 'yolo'
+      - 'config_origin2[1] == "var: _z_test_entry"'
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' 
old/ansible_core-2.19.3/test/integration/targets/signal_propagation/aliases 
new/ansible_core-2.19.4/test/integration/targets/signal_propagation/aliases
--- old/ansible_core-2.19.3/test/integration/targets/signal_propagation/aliases 
1970-01-01 01:00:00.000000000 +0100
+++ new/ansible_core-2.19.4/test/integration/targets/signal_propagation/aliases 
2025-11-05 00:27:03.000000000 +0100
@@ -0,0 +1,3 @@
+shippable/posix/group4
+context/controller
+needs/target/test_utils
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' 
old/ansible_core-2.19.3/test/integration/targets/signal_propagation/inventory 
new/ansible_core-2.19.4/test/integration/targets/signal_propagation/inventory
--- 
old/ansible_core-2.19.3/test/integration/targets/signal_propagation/inventory   
    1970-01-01 01:00:00.000000000 +0100
+++ 
new/ansible_core-2.19.4/test/integration/targets/signal_propagation/inventory   
    2025-11-05 00:27:03.000000000 +0100
@@ -0,0 +1,14 @@
+localhost0
+localhost1
+localhost2
+localhost3
+localhost4
+localhost5
+localhost6
+localhost7
+localhost8
+localhost9
+
+[all:vars]
+ansible_connection=local
+ansible_python_interpreter={{ansible_playbook_python}}
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' 
old/ansible_core-2.19.3/test/integration/targets/signal_propagation/runme.sh 
new/ansible_core-2.19.4/test/integration/targets/signal_propagation/runme.sh
--- 
old/ansible_core-2.19.3/test/integration/targets/signal_propagation/runme.sh    
    1970-01-01 01:00:00.000000000 +0100
+++ 
new/ansible_core-2.19.4/test/integration/targets/signal_propagation/runme.sh    
    2025-11-05 00:27:03.000000000 +0100
@@ -0,0 +1,21 @@
+#!/usr/bin/env bash
+
+set -x
+
+../test_utils/scripts/timeout.py -s SIGINT 3 -- \
+    ansible all -i inventory -m debug -a 'msg={{lookup("pipe", "sleep 33")}}' 
-f 10
+if [[ "$?" != "124" ]]; then
+    echo "Process was not terminated due to timeout"
+    exit 1
+fi
+
+# a short sleep to let processes die
+sleep 2
+
+sleeps="$(pgrep -alf 'sleep\ 33')"
+rc="$?"
+if [[ "$rc" == "0" ]]; then
+    echo "Found lingering processes:"
+    echo "$sleeps"
+    exit 1
+fi
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' 
old/ansible_core-2.19.3/test/integration/targets/ssh_agent/tasks/tests.yml 
new/ansible_core-2.19.4/test/integration/targets/ssh_agent/tasks/tests.yml
--- old/ansible_core-2.19.3/test/integration/targets/ssh_agent/tasks/tests.yml  
2025-10-06 19:22:06.000000000 +0200
+++ new/ansible_core-2.19.4/test/integration/targets/ssh_agent/tasks/tests.yml  
2025-11-05 00:27:03.000000000 +0100
@@ -29,15 +29,17 @@
   vars:
     pid: '{{ auto.stdout|regex_findall("ssh-agent\[(\d+)\]")|first }}'
 
-- command: ssh-agent -D -s -a '{{ output_dir }}/agent.sock'
-  async: 30
-  poll: 0
+- shell: ssh-agent -D -s -a '{{ output_dir }}/agent.sock' &
+  register: ssh_agent_result
 
-- command: ansible-playbook -i {{ ansible_inventory_sources|first|quote }} 
-vvv {{ role_path }}/auto.yml
-  environment:
-    ANSIBLE_CALLBACK_RESULT_FORMAT: yaml
-    ANSIBLE_SSH_AGENT: '{{ output_dir }}/agent.sock'
-  register: existing
+- block:
+  - command: ansible-playbook -i {{ ansible_inventory_sources|first|quote }} 
-vvv {{ role_path }}/auto.yml
+    environment:
+      ANSIBLE_CALLBACK_RESULT_FORMAT: yaml
+      ANSIBLE_SSH_AGENT: '{{ output_dir }}/agent.sock'
+    register: existing
+  always:
+    - command: "kill {{ ssh_agent_result.stdout | regex_search('Agent pid 
([0-9]+)', '\\1') | first }}"
 
 - assert:
     that:
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' 
old/ansible_core-2.19.3/test/integration/targets/test_utils/scripts/timeout.py 
new/ansible_core-2.19.4/test/integration/targets/test_utils/scripts/timeout.py
--- 
old/ansible_core-2.19.3/test/integration/targets/test_utils/scripts/timeout.py  
    2025-10-06 19:22:06.000000000 +0200
+++ 
new/ansible_core-2.19.4/test/integration/targets/test_utils/scripts/timeout.py  
    2025-11-05 00:27:03.000000000 +0100
@@ -2,21 +2,32 @@
 from __future__ import annotations
 
 import argparse
+import signal
 import subprocess
 import sys
 
+
+def signal_type(v: str) -> signal.Signals:
+    if v.isdecimal():
+        return signal.Signals(int(v))
+    if not v.startswith('SIG'):
+        v = f'SIG{v}'
+    return getattr(signal.Signals, v)
+
+
 parser = argparse.ArgumentParser()
 parser.add_argument('duration', type=int)
+parser.add_argument('--signal', '-s', default=signal.SIGTERM, type=signal_type)
 parser.add_argument('command', nargs='+')
 args = parser.parse_args()
 
+p: subprocess.Popen | None = None
 try:
-    p = subprocess.run(
-        ' '.join(args.command),
-        shell=True,
-        timeout=args.duration,
-        check=False,
-    )
+    p = subprocess.Popen(args.command)
+    p.wait(timeout=args.duration)
     sys.exit(p.returncode)
 except subprocess.TimeoutExpired:
+    if p and p.poll() is None:
+        p.send_signal(args.signal)
+        p.wait()
     sys.exit(124)
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' 
old/ansible_core-2.19.3/test/integration/targets/win_exec_wrapper/tasks/main.yml
 
new/ansible_core-2.19.4/test/integration/targets/win_exec_wrapper/tasks/main.yml
--- 
old/ansible_core-2.19.3/test/integration/targets/win_exec_wrapper/tasks/main.yml
    2025-10-06 19:22:06.000000000 +0200
+++ 
new/ansible_core-2.19.4/test/integration/targets/win_exec_wrapper/tasks/main.yml
    2025-11-05 00:27:03.000000000 +0100
@@ -268,14 +268,6 @@
       <<: *become_vars
       ansible_remote_tmp: C:\Windows\TEMP\test-dir
 
-  - name: assert warning about tmpdir deletion is present
-    assert:
-      that:
-      - temp_deletion_warning.warnings | count == 1
-      - >-
-        temp_deletion_warning.warnings[0] is
-        regex("(?i).*Failed to cleanup temporary directory 
'C:\\\\Windows\\\\TEMP\\\\test-dir\\\\.*' used for compiling C# code\\. Files 
may still be present after the task is complete\\..*")
-
   always:
   - name: ensure test user is deleted
     win_user:

++++++ ansible_core-2.19.3.tar.gz.sha256 -> ansible_core-2.19.4.tar.gz.sha256 
++++++
--- /work/SRC/openSUSE:Factory/ansible-core/ansible_core-2.19.3.tar.gz.sha256   
2025-10-07 18:30:04.145769808 +0200
+++ 
/work/SRC/openSUSE:Factory/.ansible-core.new.1980/ansible_core-2.19.4.tar.gz.sha256
 2025-11-06 18:13:58.325364076 +0100
@@ -1 +1 @@
-243a69669a007be0794360bc4477f70e0128ce0091dc3af4c5cb81c6a466f573 
ansible_core-2.19.3.tar.gz
+888db6593f2fd42cd05bdbe546704d9c969dce99e3373a54498f6dbefcfa1917  
ansible_core-2.19.4.tar.gz

Reply via email to