Skip to content

[Bugfix] Core packager to always keep __main_ at the end#360

Open
rane-rajasi wants to merge 1 commit into
masterfrom
rarane/bugfix/package_core
Open

[Bugfix] Core packager to always keep __main_ at the end#360
rane-rajasi wants to merge 1 commit into
masterfrom
rarane/bugfix/package_core

Conversation

@rane-rajasi

@rane-rajasi rane-rajasi commented Jul 7, 2026

Copy link
Copy Markdown
Contributor

Bug:

  • Title: Package-Core.py can place TdnfPackageManager.py after main.py during merge
  • Area: Core packager (src/tools/packager/Package-Core.py)
  • Description:

As a part of the build process, packager classes (Package-All.py and Package-Core.py), package all modules within extension and core directories into MsftLinuxPatchExt,py and MsftLinuxPatchCore.py respectively, which are then used to perform different patching operations. Since MsftLinuxPatchExt.py and MsftLinuxPatchCore.py contain multiple extension and core modules, the order in which these modules are added is important during patch process execution in python. Especially, main() should always be added at the very end, since it will start the execution flow and will only consider modules that were loaded before it. So, if a module is added after main, it will raise a Not found error.

This issue was observed in one of the recent builds where TdnfPackageManager (and some other modules) were inserted after main(), due to the code in Package-Core.py handling the special case for TdnfPackageManager. This led those modules marked as not found during execution

image

Below is the packager log for Core modules (Notice main.py is in between with TdnfPackageManager.py right after it):

          =============================== (1/3) GENERATING MsftLinuxPatchCore.py... ===============================
          
          ------------- Delete old core file if it exists.
          ------------- Merging modules:
          LifecycleManager.py, PackageManager.py, Constants.py, SystemctlManager.py, CoreMain.py, FileLogger.py, CompositeLogger.py, StdOutFileMirror.py, Stopwatch.py, PatchAssessor.py, PackageFilter.py, ServiceManager.py, RebootManager.py, ExecutionConfig.py, VersionComparator.py, MaintenanceWindow.py, PatchInstaller.py, ConfigurePatchingProcessor.py, TimerManager.py, EnvLayer.py, Bootstrapper.py, ConfigurationFactory.py, Container.py, YumPackageManager.py, **__main__.py, TdnfPackageManager.py**, AzL3TdnfPackageManager.py, ZypperPackageManager.py, UbuntuProClient.py, Dnf5PackageManager.py, AptitudePackageManager.py, LifecycleManagerArc.py, LifecycleManagerAzure.py, TelemetryWriter.py, StatusHandler.py, <end>
          ------------- Prepend all import statements
          ------------- Set Copyright, Version and Environment. Also enforce UNIX-style line endings.
          ------------- Merged core code was saved to:
          /__w/1/s/src/LinuxPatchExtension/codesrc/src/out/MsftLinuxPatchCore.py

Expected Behavior:
main.py should be last (or near-last entrypoint), and package manager modules should appear before it.
TdnfPackageManager.py should be before AzL3TdnfPackageManager.py, and both should be before main.py.
Impact
The merged file order becomes inconsistent and can violate intended initialization/dependency sequencing.
Behavior is traversal-order sensitive (depends on os.walk() encounter order), so it may appear intermittently across environments.

Root Cause:
In src/tools/packager/Package-Core.py, branch for TdnfPackageManager.py does:
Insert before AzL3TdnfPackageManager.py if already present
Else append unconditionally
If main.py is already appended, fallback append puts TdnfPackageManager.py after main.py.
The generic fallback logic for other files already handles this correctly using:
modules_to_be_merged.insert(-1, file_path) when main.py is last.

This isn't something introduced in recent commits, but the change in packager locations could have caused os.walk() to process modules in a different order triggering this

Proposed Fix:
In Package-Core.py, for the special case handling TdnfPackageManager, add a fallback, use same guard as generic path:
If last module is main.py, insert at -1; else append.
This preserves both constraints:
TdnfPackageManager.py before AzL3TdnfPackageManager.py when possible
Neither ends up after main.py.

Acceptance Criteria:
Packager output order always satisfies:
TdnfPackageManager.py appears before AzL3TdnfPackageManager.py
main.py appears after both
Behavior remains stable regardless of os.walk() traversal order.

@rane-rajasi rane-rajasi requested review from a team, kjohn-msft, michellemcdaniel, najams, nikhim-um and sadiksubhani9-sudo and removed request for a team July 7, 2026 22:11
@rane-rajasi rane-rajasi requested a review from kjohn-msft as a code owner July 7, 2026 22:11
@rane-rajasi rane-rajasi requested a review from najams as a code owner July 7, 2026 22:11

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Fixes core packager module-merge ordering so __main__.py remains the (near-)final entrypoint and package manager modules are not accidentally appended after it, preventing intermittent “module not found” failures caused by os.walk() traversal order.

Changes:

  • Adjusts TdnfPackageManager.py special-case logic to insert before __main__.py when __main__.py is already last, instead of unconditionally appending.
  • Updates the in-code comment to reflect the intended ordering behavior relative to AzL3TdnfPackageManager.py and __main__.py.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment thread src/tools/packager/Package-Core.py
@codecov

codecov Bot commented Jul 7, 2026

Copy link
Copy Markdown

Codecov Report

✅ All modified and coverable lines are covered by tests.
✅ Project coverage is 94.04%. Comparing base (f14a3a9) to head (34b8a2c).

Additional details and impacted files
@@           Coverage Diff           @@
##           master     #360   +/-   ##
=======================================
  Coverage   94.04%   94.04%           
=======================================
  Files         109      109           
  Lines       19967    19967           
=======================================
  Hits        18778    18778           
  Misses       1189     1189           
Flag Coverage Δ
python27 94.04% <ø> (ø)
python312 94.04% <ø> (ø)

Flags with carried forward coverage won't be shown. Click here to find out more.

☔ View full report in Codecov by Harness.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants