Repository: Azure/LinuxPatchExtension
Pull request #298: BugFix: CentOS VMs not installing patches during Auto Patching
Author: login: rane-rajasi
Labels: name: bug
description: Something isn't working
Created: 2025-03-18T22:00:23Z | Merged: 2025-03-24T22:14:55Z

Fixes included in this PR:
1. Do not use MaintenanceRunId to validate an incoming Auto Patching request
2. MaxPatchPublishDate fails if healthstoreid contains additional '_'. For eg: Ideal healthstoreid "pub_off_sku_2020.09.29" is supported currently but if a healthstoreid, say "pub_off_sk_u_2020.09.29", comes in, maxpatchpublishdate calculation fails



Diff:
diff --git a/src/core/src/core_logic/ExecutionConfig.py b/src/core/src/core_logic/ExecutionConfig.py
index cfff4d7d..04cec562 100644
--- a/src/core/src/core_logic/ExecutionConfig.py
+++ b/src/core/src/core_logic/ExecutionConfig.py
@@ -108,9 +108,9 @@ def __get_max_patch_publish_date(self, health_store_id):
         """ Obtains implicit date ceiling for published date - converts pub_off_sku_2024.04.01 to 20240401T000000Z """
         max_patch_publish_date = str()
         if health_store_id is not None and health_store_id != "":
-            split = health_store_id.split("_")
-            if len(split) == 4 and len(split[3]) == 10:
-                max_patch_publish_date = "{0}T000000Z".format(split[3].replace(".", ""))
+            date_candidate = str(health_store_id)[-10:].replace(".", "")  # last 10 characters and remove '.'
+            if len(date_candidate) == 8 and date_candidate.isdigit() and str(health_store_id)[-11:-10] == "_":
+                max_patch_publish_date = date_candidate + "T000000Z"
 
         self.composite_logger.log_debug("[EC] Getting max patch publish date. [MaxPatchPublishDate={0}][HealthStoreId={1}]".format(str(max_patch_publish_date), str(health_store_id)))
         return max_patch_publish_date
diff --git a/src/core/src/package_managers/YumPackageManager.py b/src/core/src/package_managers/YumPackageManager.py
index d66a0976..33a5cf91 100644
--- a/src/core/src/package_managers/YumPackageManager.py
+++ b/src/core/src/package_managers/YumPackageManager.py
@@ -84,7 +84,7 @@ def __init__(self, env_layer, execution_config, composite_logger, telemetry_writ
 
         # if an Auto Patching request comes in on a CentOS machine with Security and/or Critical classifications selected, we need to install all patches
         installation_included_classifications = [] if execution_config.included_classifications_list is None else execution_config.included_classifications_list
-        if execution_config.maintenance_run_id is not None and execution_config.operation.lower() == Constants.INSTALLATION.lower() \
+        if execution_config.health_store_id is not str() and execution_config.operation.lower() == Constants.INSTALLATION.lower() \
                 and 'CentOS' in str(env_layer.platform.linux_distribution()) \
                 and 'Critical' in installation_included_classifications and 'Security' in installation_included_classifications:
             self.composite_logger.log_debug("Updating classifications list to install all patches for the Auto Patching request since classification based patching is not available on CentOS machines")
diff --git a/src/core/tests/Test_CoreMain.py b/src/core/tests/Test_CoreMain.py
index c815b420..682787d2 100644
--- a/src/core/tests/Test_CoreMain.py
+++ b/src/core/tests/Test_CoreMain.py
@@ -432,9 +432,7 @@ def test_install_all_packages_for_centos_autopatching(self):
         LegacyEnvLayerExtensions.LegacyPlatform.linux_distribution = self.mock_linux_distribution_to_return_centos
 
         argument_composer = ArgumentComposer()
-        maintenance_run_id = "9/28/2020 02:00:00 PM +00:00"
         classifications_to_include = ["Security", "Critical"]
-        argument_composer.maintenance_run_id = str(maintenance_run_id)
         argument_composer.health_store_id = str("pub_off_sku_2020.09.29")
         argument_composer.classifications_to_include = classifications_to_include
         argument_composer.reboot_setting = 'Always'
@@ -449,6 +447,7 @@ def test_install_all_packages_for_centos_autopatching(self):
         with runtime.env_layer.file_system.open(runtime.execution_config.status_file_path, 'r') as file_handle:
             substatus_file_data = json.load(file_handle)[0]["status"]["substatus"]
         self.assertEqual(len(substatus_file_data), 4)
+        self.assertTrue(runtime.execution_config.max_patch_publish_date == "20200929T000000Z")
         self.assertTrue(substatus_file_data[0]["name"] == Constants.PATCH_ASSESSMENT_SUMMARY)
         self.assertTrue(substatus_file_data[0]["status"].lower() == Constants.STATUS_SUCCESS.lower())
         self.assertTrue(substatus_file_data[1]["name"] == Constants.PATCH_INSTALLATION_SUMMARY)
diff --git a/src/core/tests/Test_ExecutionConfig.py b/src/core/tests/Test_ExecutionConfig.py
new file mode 100644
index 00000000..16756e2c
--- /dev/null
+++ b/src/core/tests/Test_ExecutionConfig.py
@@ -0,0 +1,49 @@
+# Copyright 2025 Microsoft Corporation
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+#     http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+# Requires Python 2.7+
+import unittest
+
+from core.src.bootstrap.Constants import Constants
+from core.tests.library.ArgumentComposer import ArgumentComposer
+from core.tests.library.RuntimeCompositor import RuntimeCompositor
+
+
+class TestExecutionConfig(unittest.TestCase):
+    def setUp(self):
+        pass
+
+    def tearDown(self):
+        pass
+
+    def test_get_max_patch_publish_date(self):
+        test_input_output_table = [
+            ["pub_off_sku_2020.09.29", "20200929T000000Z"],
+            ["pu_b_off_sk_u_2020.09.29", "20200929T000000Z"],
+            [str(), str()],
+            ["pub_off_sku_20.09.29", str()],
+            ["pub_off_sku_2020.9.29", str()],
+            ["pub_off_sk_u2020.09.29", str()],
+            ["x_2020.09.29", "20200929T000000Z"]  # theoretically okay
+        ]
+
+        argument_composer = ArgumentComposer()
+        runtime = RuntimeCompositor(argument_composer.get_composed_arguments(), True, Constants.YUM)
+        for row in test_input_output_table:
+            self.assertEqual(runtime.execution_config._ExecutionConfig__get_max_patch_publish_date(row[0]), row[1])
+        runtime.stop()
+
+
+if __name__ == '__main__':
+    unittest.main()


Reviews:
user: login: rane-rajasi
state: COMMENTED
author_association: CONTRIBUTOR
submitted_at: 2025-03-18T22:02:37Z
user: login: kjohn-msft
state: COMMENTED
author_association: COLLABORATOR
submitted_at: 2025-03-18T22:11:06Z
user: login: kjohn-msft
state: COMMENTED
author_association: COLLABORATOR
submitted_at: 2025-03-18T22:13:45Z
user: login: kjohn-msft
body: Comments inline
state: CHANGES_REQUESTED
author_association: COLLABORATOR
submitted_at: 2025-03-18T22:14:05Z
user: login: feng-j678
body: adding debug to ln 113 is not required, but nice to have in case of future failures relate to health_store_id format
state: DISMISSED
author_association: CONTRIBUTOR
submitted_at: 2025-03-18T23:17:02Z
user: login: rane-rajasi
state: COMMENTED
author_association: CONTRIBUTOR
submitted_at: 2025-03-20T16:41:45Z
user: login: rane-rajasi
state: COMMENTED
author_association: CONTRIBUTOR
submitted_at: 2025-03-20T16:48:49Z
user: login: rane-rajasi
state: COMMENTED
author_association: CONTRIBUTOR
submitted_at: 2025-03-20T16:51:21Z
user: login: kjohn-msft
state: COMMENTED
author_association: COLLABORATOR
submitted_at: 2025-03-20T20:37:32Z
user: login: feng-j678
state: DISMISSED
author_association: CONTRIBUTOR
submitted_at: 2025-03-20T20:46:00Z
user: login: kjohn-msft
state: COMMENTED
author_association: COLLABORATOR
submitted_at: 2025-03-20T20:48:48Z
user: login: michellemcdaniel
state: COMMENTED
author_association: NONE
submitted_at: 2025-03-20T20:58:25Z
user: login: kjohn-msft
state: COMMENTED
author_association: COLLABORATOR
submitted_at: 2025-03-20T21:34:21Z
user: login: kjohn-msft
state: COMMENTED
author_association: COLLABORATOR
submitted_at: 2025-03-20T21:49:18Z
user: login: michellemcdaniel
state: COMMENTED
author_association: NONE
submitted_at: 2025-03-20T22:47:31Z
user: login: feng-j678
state: COMMENTED
author_association: CONTRIBUTOR
submitted_at: 2025-03-20T23:03:11Z
user: login: kjohn-msft
state: APPROVED
author_association: COLLABORATOR
submitted_at: 2025-03-23T21:53:01Z
user: login: feng-j678
state: APPROVED
author_association: CONTRIBUTOR
submitted_at: 2025-03-24T21:32:17Z

Review comments:
diff_hunk: @@ -84,7 +84,7 @@ def __init__(self, env_layer, execution_config, composite_logger, telemetry_writ
 
         # if an Auto Patching request comes in on a CentOS machine with Security and/or Critical classifications selected, we need to install all patches
         installation_included_classifications = [] if execution_config.included_classifications_list is None else execution_config.included_classifications_list
-        if execution_config.maintenance_run_id is not None and execution_config.operation.lower() == Constants.INSTALLATION.lower() \
+        if execution_config.health_store_id is not str() and execution_config.operation.lower() == Constants.INSTALLATION.lower() \
path: src/core/src/package_managers/YumPackageManager.py
user: login: rane-rajasi
body: @kjohn-msft, I've used healthstoreid for auto patch validation instead of maxpatchpublishdate since the presence of healthstoreid indicates an AutoPatch request vs maxpatchpublishdate can also come in as an API input
created_at: 2025-03-18T22:02:37Z
author_association: CONTRIBUTOR
diff_hunk: @@ -108,9 +108,9 @@ def __get_max_patch_publish_date(self, health_store_id):
         """ Obtains implicit date ceiling for published date - converts pub_off_sku_2024.04.01 to 20240401T000000Z """
         max_patch_publish_date = str()
         if health_store_id is not None and health_store_id != "":
-            split = health_store_id.split("_")
-            if len(split) == 4 and len(split[3]) == 10:
-                max_patch_publish_date = "{0}T000000Z".format(split[3].replace(".", ""))
+            split = health_store_id.rsplit("_", 1)
+            if len(split) == 2 and len(split[1]) == 10:
+                max_patch_publish_date = "{0}T000000Z".format(split[1].replace(".", ""))
path: src/core/src/core_logic/ExecutionConfig.py
user: login: kjohn-msft
body: Can you please write a debug log if it reaches this far and the conditions to convert successfully aren't met. e.g. split happens and then the data doesn't look right.
created_at: 2025-03-18T22:11:06Z
author_association: COLLABORATOR
diff_hunk: @@ -526,6 +525,55 @@ def test_install_all_packages_for_centos_autopatching_as_warning_with_never_rebo
 
         LegacyEnvLayerExtensions.LegacyPlatform.linux_distribution = backup_envlayer_platform_linux_distribution
 
+    def test_install_all_packages_for_centos_autopatching_differentversionformat_in_healthstore(self):
path: src/core/tests/Test_CoreMain.py
user: login: kjohn-msft
body: Please unit test (in the appropriate test class / not core main) various call combinations (input->output) into the private method __get_max_patch_publish_date(self, health_store_id) 
created_at: 2025-03-18T22:13:45Z
author_association: COLLABORATOR
diff_hunk: @@ -108,9 +108,9 @@ def __get_max_patch_publish_date(self, health_store_id):
         """ Obtains implicit date ceiling for published date - converts pub_off_sku_2024.04.01 to 20240401T000000Z """
         max_patch_publish_date = str()
         if health_store_id is not None and health_store_id != "":
-            split = health_store_id.split("_")
-            if len(split) == 4 and len(split[3]) == 10:
-                max_patch_publish_date = "{0}T000000Z".format(split[3].replace(".", ""))
+            split = health_store_id.rsplit("_", 1)
+            if len(split) == 2 and len(split[1]) == 10:
path: src/core/src/core_logic/ExecutionConfig.py
user: login: feng-j678
body: is there a case if health_store_id is like this pub_off_sk_u2020.09.29, then wouldn't the rsplit produce [pub_off_sk_, u2020.09.29]?

is it possible to add a debug on ln 113 smth like "debug("Parse health_store_id into list. [HealthStoreIdList={0}]".format(str(split)))
created_at: 2025-03-18T23:15:46Z
author_association: CONTRIBUTOR
diff_hunk: @@ -108,9 +108,9 @@ def __get_max_patch_publish_date(self, health_store_id):
         """ Obtains implicit date ceiling for published date - converts pub_off_sku_2024.04.01 to 20240401T000000Z """
         max_patch_publish_date = str()
         if health_store_id is not None and health_store_id != "":
-            split = health_store_id.split("_")
-            if len(split) == 4 and len(split[3]) == 10:
-                max_patch_publish_date = "{0}T000000Z".format(split[3].replace(".", ""))
+            split = health_store_id.rsplit("_", 1)
+            if len(split) == 2 and len(split[1]) == 10:
+                max_patch_publish_date = "{0}T000000Z".format(split[1].replace(".", ""))
path: src/core/src/core_logic/ExecutionConfig.py
user: login: rane-rajasi
body: In this scenario, line 115 would log -> [EC] Getting max patch publish date. [MaxPatchPublishDate=][HealthStoreId=pub_off_sku_2020.9.29]
created_at: 2025-03-20T16:41:44Z
author_association: CONTRIBUTOR
diff_hunk: @@ -526,6 +525,55 @@ def test_install_all_packages_for_centos_autopatching_as_warning_with_never_rebo
 
         LegacyEnvLayerExtensions.LegacyPlatform.linux_distribution = backup_envlayer_platform_linux_distribution
 
+    def test_install_all_packages_for_centos_autopatching_differentversionformat_in_healthstore(self):
path: src/core/tests/Test_CoreMain.py
user: login: rane-rajasi
body: done
created_at: 2025-03-20T16:48:49Z
author_association: CONTRIBUTOR
diff_hunk: @@ -108,9 +108,9 @@ def __get_max_patch_publish_date(self, health_store_id):
         """ Obtains implicit date ceiling for published date - converts pub_off_sku_2024.04.01 to 20240401T000000Z """
         max_patch_publish_date = str()
         if health_store_id is not None and health_store_id != "":
-            split = health_store_id.split("_")
-            if len(split) == 4 and len(split[3]) == 10:
-                max_patch_publish_date = "{0}T000000Z".format(split[3].replace(".", ""))
+            split = health_store_id.rsplit("_", 1)
+            if len(split) == 2 and len(split[1]) == 10:
path: src/core/src/core_logic/ExecutionConfig.py
user: login: rane-rajasi
body: See my response to the other comment
created_at: 2025-03-20T16:51:21Z
author_association: CONTRIBUTOR
diff_hunk: @@ -108,9 +108,9 @@ def __get_max_patch_publish_date(self, health_store_id):
         """ Obtains implicit date ceiling for published date - converts pub_off_sku_2024.04.01 to 20240401T000000Z """
         max_patch_publish_date = str()
         if health_store_id is not None and health_store_id != "":
-            split = health_store_id.split("_")
-            if len(split) == 4 and len(split[3]) == 10:
-                max_patch_publish_date = "{0}T000000Z".format(split[3].replace(".", ""))
+            split = health_store_id.rsplit("_", 1)
+            if len(split) == 2 and len(split[1]) == 10:
+                max_patch_publish_date = "{0}T000000Z".format(split[1].replace(".", ""))
path: src/core/src/core_logic/ExecutionConfig.py
user: login: kjohn-msft
body: Sounds good - closing.
created_at: 2025-03-20T20:37:32Z
author_association: COLLABORATOR
diff_hunk: @@ -108,9 +108,9 @@ def __get_max_patch_publish_date(self, health_store_id):
         """ Obtains implicit date ceiling for published date - converts pub_off_sku_2024.04.01 to 20240401T000000Z """
         max_patch_publish_date = str()
         if health_store_id is not None and health_store_id != "":
-            split = health_store_id.split("_")
-            if len(split) == 4 and len(split[3]) == 10:
-                max_patch_publish_date = "{0}T000000Z".format(split[3].replace(".", ""))
+            split = health_store_id.rsplit("_", 1)
+            if len(split) == 2 and len(split[1]) == 10:
path: src/core/src/core_logic/ExecutionConfig.py
user: login: kjohn-msft
body: Mulling over it, I think this code should just be this:

date_candidate = str(health_store_id)[-10:].replace(".","")   # last 10 characters and remove '.'
if len(date_candidate) == 8 and date_candidate.isdigit():
     max_patch_publish_date = date_candidate + "T000000Z"

It should work for any kind of input for healthstoreid, and has more protections.
created_at: 2025-03-20T20:48:48Z
author_association: COLLABORATOR
diff_hunk: @@ -108,9 +108,9 @@ def __get_max_patch_publish_date(self, health_store_id):
         """ Obtains implicit date ceiling for published date - converts pub_off_sku_2024.04.01 to 20240401T000000Z """
         max_patch_publish_date = str()
         if health_store_id is not None and health_store_id != "":
-            split = health_store_id.split("_")
-            if len(split) == 4 and len(split[3]) == 10:
-                max_patch_publish_date = "{0}T000000Z".format(split[3].replace(".", ""))
+            split = health_store_id.rsplit("_", 1)
+            if len(split) == 2 and len(split[1]) == 10:
path: src/core/src/core_logic/ExecutionConfig.py
user: login: michellemcdaniel
body: wait, you want to use date_candadte if it's not a digit and not len 8?
created_at: 2025-03-20T20:58:25Z
author_association: NONE
diff_hunk: @@ -108,9 +108,9 @@ def __get_max_patch_publish_date(self, health_store_id):
         """ Obtains implicit date ceiling for published date - converts pub_off_sku_2024.04.01 to 20240401T000000Z """
         max_patch_publish_date = str()
         if health_store_id is not None and health_store_id != "":
-            split = health_store_id.split("_")
-            if len(split) == 4 and len(split[3]) == 10:
-                max_patch_publish_date = "{0}T000000Z".format(split[3].replace(".", ""))
+            split = health_store_id.rsplit("_", 1)
+            if len(split) == 2 and len(split[1]) == 10:
path: src/core/src/core_logic/ExecutionConfig.py
user: login: kjohn-msft
body: Sorry, was writing that comment out while in a call. @michellemcdaniel edited inline - updated line is if len(date_candidate) == 8 and date_candidate.isdigit():
created_at: 2025-03-20T21:34:21Z
author_association: COLLABORATOR
diff_hunk: @@ -526,6 +525,55 @@ def test_install_all_packages_for_centos_autopatching_as_warning_with_never_rebo
 
         LegacyEnvLayerExtensions.LegacyPlatform.linux_distribution = backup_envlayer_platform_linux_distribution
 
+    def test_install_all_packages_for_centos_autopatching_differentversionformat_in_healthstore(self):
path: src/core/tests/Test_CoreMain.py
user: login: kjohn-msft
body: What was meant by this (invoke private method, with call combinations) is in this PR to your branch --
https://github.com/Azure/LinuxPatchExtension/pull/300/files

We should try to use these techniques to make our test code more maintainable (existing test code - @feng-j678 for visibility). Specifically having the minimum code to exercise the unit being tested. Vastly helps with initial review, later changes, etc.

In aggregate, being surgical will also allow test code to run faster in full runs.
created_at: 2025-03-20T21:49:18Z
author_association: COLLABORATOR
diff_hunk: @@ -108,9 +108,9 @@ def __get_max_patch_publish_date(self, health_store_id):
         """ Obtains implicit date ceiling for published date - converts pub_off_sku_2024.04.01 to 20240401T000000Z """
         max_patch_publish_date = str()
         if health_store_id is not None and health_store_id != "":
-            split = health_store_id.split("_")
-            if len(split) == 4 and len(split[3]) == 10:
-                max_patch_publish_date = "{0}T000000Z".format(split[3].replace(".", ""))
+            split = health_store_id.rsplit("_", 1)
+            if len(split) == 2 and len(split[1]) == 10:
path: src/core/src/core_logic/ExecutionConfig.py
user: login: michellemcdaniel
body: That makes much more sense
created_at: 2025-03-20T22:47:31Z
author_association: NONE
diff_hunk: @@ -526,6 +525,55 @@ def test_install_all_packages_for_centos_autopatching_as_warning_with_never_rebo
 
         LegacyEnvLayerExtensions.LegacyPlatform.linux_distribution = backup_envlayer_platform_linux_distribution
 
+    def test_install_all_packages_for_centos_autopatching_differentversionformat_in_healthstore(self):
path: src/core/tests/Test_CoreMain.py
user: login: feng-j678
body: yes the coverage for this pr is high

![image](https://github.com/user-attachments/assets/0a983f54-fddd-42c7-9af8-fc29a28abf00)

created_at: 2025-03-20T23:03:11Z
author_association: CONTRIBUTOR

PR comments:
user: login: codecov[bot]
created_at: 2025-03-18T22:02:15Z
body: ## [Codecov](https://app.codecov.io/gh/Azure/LinuxPatchExtension/pull/298?dropdown=coverage&src=pr&el=h1&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=Azure) Report
Attention: Patch coverage is `95.65217%` with `1 line` in your changes missing coverage. Please review.
> Project coverage is 92.49%. Comparing base [(`af59b83`)](https://app.codecov.io/gh/Azure/LinuxPatchExtension/commit/af59b83544ab8daf275974c967b29ed82e69ca26?dropdown=coverage&el=desc&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=Azure) to head [(`ab78eb1`)](https://app.codecov.io/gh/Azure/LinuxPatchExtension/commit/ab78eb1586a9a4bba93e6365e6465e1d02e23192?dropdown=coverage&el=desc&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=Azure).
> Report is 1 commits behind head on master.

| [Files with missing lines](https://app.codecov.io/gh/Azure/LinuxPatchExtension/pull/298?dropdown=coverage&src=pr&el=tree&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=Azure) | Patch % | Lines |
|---|---|---|
| [src/core/tests/Test\_ExecutionConfig.py](https://app.codecov.io/gh/Azure/LinuxPatchExtension/pull/298?src=pr&el=tree&filepath=src%2Fcore%2Ftests%2FTest_ExecutionConfig.py&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=Azure#diff-c3JjL2NvcmUvdGVzdHMvVGVzdF9FeGVjdXRpb25Db25maWcucHk=) | 94.44% | [1 Missing :warning: ](https://app.codecov.io/gh/Azure/LinuxPatchExtension/pull/298?src=pr&el=tree&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=Azure) |

<details><summary>Additional details and impacted files</summary>


```diff
@@           Coverage Diff           @@
##           master     #298   +/-   ##
=======================================
  Coverage   92.49%   92.49%           
=======================================
  Files          99      100    +1     
  Lines       16287    16304   +17     
=======================================
+ Hits        15064    15080   +16     
- Misses       1223     1224    +1     
```

| [Flag](https://app.codecov.io/gh/Azure/LinuxPatchExtension/pull/298/flags?src=pr&el=flags&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=Azure) | Coverage Δ | |
|---|---|---|
| [python27](https://app.codecov.io/gh/Azure/LinuxPatchExtension/pull/298/flags?src=pr&el=flag&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=Azure) | `92.49% <95.65%> (+<0.01%)` | :arrow_up: |
| [python39](https://app.codecov.io/gh/Azure/LinuxPatchExtension/pull/298/flags?src=pr&el=flag&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=Azure) | `92.49% <95.65%> (+<0.01%)` | :arrow_up: |

Flags with carried forward coverage won't be shown. [Click here](https://docs.codecov.io/docs/carryforward-flags?utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=Azure#carryforward-flags-in-the-pull-request-comment) to find out more.

</details>

[:umbrella: View full report in Codecov by Sentry](https://app.codecov.io/gh/Azure/LinuxPatchExtension/pull/298?dropdown=coverage&src=pr&el=continue&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=Azure).   
:loudspeaker: Have feedback on the report? [Share it here](https://about.codecov.io/codecov-pr-comment-feedback/?utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=Azure).

<details><summary> :rocket: New features to boost your workflow: </summary>

- :snowflake: [Test Analytics](https://docs.codecov.com/docs/test-analytics): Detect flaky tests, report on failures, and find test suite problems.
</details>
author_association: NONE
user: login: rane-rajasi
created_at: 2025-03-20T18:06:57Z
body: @feng-j678, @kjohn-msft code coverage shows changes in this PR are missing coverage, however the detailed report does not have anything missing within these changes. Why is this happening?
<img width="383" alt="image" src="https://github.com/user-attachments/assets/ba67cbe3-47c9-441c-9497-b4b9cffeea0b" />

<img width="927" alt="image" src="https://github.com/user-attachments/assets/870619de-94b7-44ce-9243-87d08fd62d45" />


author_association: CONTRIBUTOR