FIX: Enforce bundled native compatibility in Conda packages - #781
FIX: Enforce bundled native compatibility in Conda packages#781Jahnvi Thakkar (jahnvi480) wants to merge 15 commits into
Conversation
Port focused native inventory, architecture, ABI and glibc guards; retain the required core and independently probe its load. Preserve newer main cross-build behavior and existing RPATHs. Move the six existing-file prerequisites out of the dependent release layer, including local SQL CI login permissions and test dependencies. Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
There was a problem hiding this comment.
🟡 Changes recommended
Three moderate packaging and validation gaps remain unresolved.
Once you've addressed the issues Copilot identified, you can request another Copilot review.
Pull request overview
This PR hardens Conda packaging and native compatibility for bundled ODBC and bulk-copy components.
Changes:
- Adds ELF, PE, Mach-O, ABI, glibc, and native-core validation.
- Updates Conda recipes for glibc 2.34, Windows ARM64 CPython 3.12, and macOS wheel selection.
- Updates CI permissions, documentation, tests, and locked PyYAML dependencies.
File summaries
| File | Reviewed changes |
|---|---|
tests/test_035_conda_macho_assert.py |
Mach-O architecture and payload validation tests. |
tests/test_034_conda_verify_cwd.py |
Core probing and Conda orchestration tests. |
tests/test_030_pe_machine_assert.py |
PE machine and Windows payload validation tests. |
tests/test_029_bundled_binary_audit.py |
ELF, glibc, ABI, and bundled-binary audit tests. |
requirements.txt |
Adds PyYAML. |
README.md |
Adds Conda installation and release guidance. |
OneBranchPipelines/scripts/build_conda_packages.py |
Builds packages and orchestrates audits and core probes. |
eng/scripts/audit_bundled_binaries.py |
Audits ELF metadata and glibc compatibility. Moderate (1 vote): enforce the fixed 2.34 floor. |
eng/scripts/assert_pe_machine.py |
Validates Windows native payload architecture. |
eng/scripts/assert_macho_arch.py |
Validates macOS native payload architecture. |
eng/scripts/_conda_pkg.py |
Shared native contract checks. Moderate (2 votes): align accepted stable-ABI names with packaging. Moderate (1 vote): require the core package initializer for cross-target validation. |
eng/requirements-test-linux.txt |
Adds locked PyYAML dependency. |
eng/requirements-build-macos.txt |
Adds locked PyYAML dependency. |
eng/pipelines/pr-validation-pipeline.yml |
Grants and verifies SQL Server DMV permissions. |
conda/README.md |
Documents Conda candidate guidance. |
conda/mssql-python/meta.yaml |
Adds glibc and Windows ARM64 ABI constraints. |
conda/mssql-python/build.sh |
Selects the appropriate macOS wheel. |
conda/mssql-python/bld.bat |
Enforces Windows bulk-copy core presence. |
Review details
Suppressed comments (2)
eng/scripts/_conda_pkg.py:58
- For non-executable cross targets the orchestrator skips
_core_probeand relies on this static contract. Because only the extension filename is required, a payload containingmssql_py_core/...sobut nomssql_py_core/__init__.pypasses the PE/Mach-O audits even thoughimport mssql_py_corecannot provide the bulk-copy package; require the package initializer and cover it in the fixtures, or fail closed on the cross-target path.
cores = [
name
for name in names
if re.fullmatch(
rf"{re.escape(root)}mssql_py_core/mssql_py_core(?:\.[^/]+)?\.{suffix}", name
)
eng/scripts/audit_bundled_binaries.py:297
- The fixed contract is
__glibc >=2.34, but this parser only checks that the declared floor is no lower than the symbols it happens to observe. A rebuilt payload whose core requires only GLIBC_2.28 and whose metadata says__glibc >=2.28would therefore pass the release audit, contradicting the advertised Linux floor. Reject parsed floors below 2.34 here as well as checking symbol compatibility.
match = re.fullmatch(r"__glibc\s+>=(\d+(?:\.\d+)+)", specs[0])
if match is None:
raise ValueError(f"unsupported __glibc dependency: {specs[0]!r}")
return tuple(map(int, match[1].split(".")))
- Files reviewed: 17/18 changed files
- Comments generated: 1
- Review effort level: Lite
💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.
Delete the release dependency workflow and lockfile text test module. Remove YAML-only Conda cases and a recipe wording assertion while preserving native audit, ABI, core-load, subprocess error handling, and security coverage. Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
Keep native packaging and release tooling independently mergeable to main without a stack or required merge order. Preserve candidate availability and production prerequisite caveats. Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
Restore the explicitly separated existing-file changes to main and remove the lower-only Conda guide. Keep the eleven new release files independent of PR #781 by removing the last YAML-only source test and unused PyYAML install. Release behavior and production guards remain unchanged. Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
The remaining tests and release tooling no longer consume PyYAML. Restore the three requirements files exactly to main, retaining all native packaging fixes and pipeline-only test removals. Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
Include exact stable-ABI core filenames in wheels and require the core package initializer in cross-platform archive audits. Add focused behavioral regressions and trim unrelated release administration detail. Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
There was a problem hiding this comment.
🔵 Needs a closer look
The unresolved inherited Conda environment behavior and broad native-packaging changes require human review.
Review details
Suppressed comments (1)
OneBranchPipelines/scripts/build_conda_packages.py:307
build_envstarts fromdict(os.environ), so removing an explicit assignment does not guarantee that Conda will stop receivingCONDA_PLUGINS_AUTO_ACCEPT_TOS: a runner or parent process that already exports it will be propagated to every invocation. Since this change is intended to remove automatic terms acceptance, explicitly remove the variable from the copied environment and cover the inherited-value case.
if cross_target_subdir:
# conda-build AND the verify `conda create` honor CONDA_SUBDIR -> the packages are
# stamped for the target subdir and the import check runs the target Python where the
# host can execute it (natively / Rosetta 2 / QEMU binfmt).
env["CONDA_SUBDIR"] = cross_target_subdir
- Files reviewed: 17/17 changed files
- Comments generated: 0 new
- Review effort level: Lite
Remove the recipe's unrelated release-version fallback. Preserve the orchestrator's selected-wheel version input and verify strict recipe rendering fails clearly when it is missing. Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
There was a problem hiding this comment.
🔵 Needs a closer look
The new .conda test needs the same zstandard-backend skip guard as the other archive-based tests.
Review details
Suppressed comments (1)
tests/test_035_conda_macho_assert.py:203
- This new
.condatest calls_make_conda, which requires a zstandard backend, but it is not guarded like the other archive-based tests in this file (for example, lines 190 and 222). A direct/source-only run without that optional backend now fails withModuleNotFoundErrorinstead of skipping; add the sameskipifmarker.
@pytest.mark.parametrize("state", ["missing", "missing-init", "wrong-arch", "wrong-tag", "abi3"])
def test_required_core_contract(tmp_path, state):
- Files reviewed: 17/17 changed files
- Comments generated: 0 new
- Review effort level: Lite
Remove the opt-in variable from the copied build environment while preserving the caller's environment. Cover both unset and inherited opt-in states with the existing behavioral regression. Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
Apply the existing archive-backend skip guard to the core contract cases. All 25 Mach-O cases execute with zstandard; without a backend, seven parser cases pass and eighteen archive cases skip consistently. Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
There was a problem hiding this comment.
🔵 Needs a closer look
The shared validator must handle malformed non-list depends metadata without aborting the platform audits.
Review details
Suppressed comments (1)
eng/scripts/_conda_pkg.py:35
validate_native_contractiteratesindex.get("depends", [])without validating its type. For a readable but malformed package withdepends: null(or another non-list), this raisesTypeError; all three platform audits call this outside a catch, soaudit_package()aborts instead of returning the fail-closed violation used for malformed package metadata. Normalize or validatedependsbefore scanning it.
pins = [
d
for d in index.get("depends", [])
if isinstance(d, str) and d.split()[:1] == ["python_abi"]
- Files reviewed: 17/17 changed files
- Comments generated: 0 new
- Review effort level: Lite
Driver-test environments do not all install the wheel build backend. Keep the real archive assertion active where wheel is available, including verified Windows and Ubuntu CI legs, without adding build dependencies to driver-only tests. Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
📊 Code Coverage Report
Diff CoverageDiff: main...HEAD, staged and unstaged changesNo lines with coverage information in this diff. 📋 Files Needing Attention📉 Files with overall lowest coverage (click to expand)mssql_python.pybind.performance_counter.hpp: 0.7%
mssql_python.pybind.logger_bridge.cpp: 57.9%
mssql_python.pybind.ddbc_bindings.h: 61.5%
mssql_python.pybind.logger_bridge.hpp: 70.8%
mssql_python.row.py: 77.6%
mssql_python.pybind.ddbc_bindings.cpp: 77.7%
mssql_python.pybind.connection.connection_pool.cpp: 82.4%
mssql_python.logging.py: 85.5%
mssql_python.helpers.py: 89.3%
mssql_python.pooling.py: 90.1%🔗 Quick Links
|
Check the existing producer bootstrap before deciding that the wheel backend is unavailable. This retains real archive coverage with setuptools-vendored wheel without adding a dependency. Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
There was a problem hiding this comment.
🔵 Needs a closer look
Four unresolved moderate findings affect fail-closed packaging and remove dependency or pipeline regression coverage.
Review details
Suppressed comments (4)
Previously missed (4) — in code that hasn't changed since the last review.
tests/test_release_build_dependencies.py:1
- Deleting this entire test module removes the only automated checks for the locked dependency files and refresh workflow (exact pins/hashes, pipeline
--require-hashesinstalls, PR-safe triggers/action SHAs, and the validation matrix). Those files and the workflow remain in the repository, and this PR adds no replacement assertions, so dependency or pipeline regressions can now pass silently. Restore this module or move equivalent checks into a maintained test file.
conda/mssql-python/bld.bat:46 - This guard is nested only in the non-executable/cross-build branch. Native Windows builds take the
elsepip-install path and skip the check, so a wheel withoutmssql_py_corecan still produce a successful reduced package whenbld.batis invoked directly; the recipe import test only importsmssql_python. Move the guard after the branch (or apply it to both paths) so every build fails closed, retaining the PE audit for actual machine type.
conda/mssql-python/build.sh:31 - This macOS cross-extraction path only selects the code wheel; it never verifies that the extracted wheel contains the required
mssql_py_coreextension. A malformed or legacy wheel can therefore produce a reduced package when the recipe is run without the orchestrator's later audit, unlike the new Windows cross guard. Add a required-core check before staging this package.
tests/test_034_conda_verify_cwd.py:31 - This deletion removes the three regression tests covering best-effort Conda consolidation, official wheel provenance gating, and the Windows pool demand indentation. The corresponding pipeline/template blocks still exist, and no replacement assertions were added, so future YAML edits can break release safety without CI detecting it. Keep these tests or rehome equivalent assertions while adding the new cases.
- Files reviewed: 17/17 changed files
- Comments generated: 0 new
- Review effort level: Lite
There was a problem hiding this comment.
🔵 Needs a closer look
Address malformed dependency-field handling and retain or relocate the dependency workflow regression coverage.
Review details
Suppressed comments (2)
eng/scripts/_conda_pkg.py:37
- If a malformed
info/index.jsoncontains"depends": null(or another non-list value), this comprehension can raiseTypeErrorbefore any audit error is returned. The callers promise malformed packages fail through their violation lists, so validate/normalize the dependency field before iterating it.
pins = [
d
for d in index.get("depends", [])
if isinstance(d, str) and d.split()[:1] == ["python_abi"]
]
abi = re.fullmatch(r"python_abi (3\.\d+)\.\* \*_cp(3\d+)", pins[0]) if len(pins) == 1 else None
tests/test_release_build_dependencies.py:1
- Deleting this file removes the only repository tests that validate the still-active
refresh-build-dependencies.ymlcontract: exact pinned/hash-locked requirements, pipeline--require-hashesinstalls, the supported matrix, and the workflow's PR-safety/update behavior. With that workflow still present, future lock or pipeline drift can now pass the Python test suite unnoticed; please retain or relocate this regression suite rather than removing it.
- Files reviewed: 17/17 changed files
- Comments generated: 0 new
- Review effort level: Lite
There was a problem hiding this comment.
🟡 Changes recommended
Unresolved native-core validation and audit issues remain, and important regression-test coverage was removed.
Once you've addressed the issues Copilot identified, you can request another Copilot review.
Review details
Suppressed comments (3)
conda/mssql-python/build.sh:31
- This cross-build path now filters the macOS code wheel, but it still verifies only
ddbc_bindings; neither this path nor the nativepip installpath checks thatmssql_py_corewas extracted. Becausemeta.yamltests only importmssql_pythonand bulk copy loads the core lazily, a directconda buildcan still produce a package with bulk copy silently removed. Add a target-aware core presence/compatibility check to both paths instead of relying only on the later orchestrator audit.
for w in "$WHEELS_DIR/${pkg_underscore}-${PKG_VERSION}-cp${CONDA_PY}-"*macosx*.whl; do
eng/scripts/_conda_pkg.py:36
index.get("depends", [])can returnNone(or another non-iterable) for malformedinfo/index.json; the list comprehension then raisesTypeErrorbefore any audit can return its normal violation list. All three callers invoke this function without catching that exception, so malformed packages crash the audit instead of failing closed with a diagnostic. Validate/normalizedependsbefore iterating it.
pins = [
d
for d in index.get("depends", [])
if isinstance(d, str) and d.split()[:1] == ["python_abi"]
]
tests/test_release_build_dependencies.py:1
- This entire regression-test module is removed, but its contracts still cover active files such as
.github/workflows/refresh-build-dependencies.yml, the hashedeng/requirements-*.txtlocks, and the OneBranch build stages. Deleting it removes coverage for exact pin/hash validation,--require-hashesinstallation, the supported Python/platform matrix, and the immutable refresh-PR workflow, so later dependency or pipeline drift can pass CI unnoticed. Please retain this module or replace it with equivalent tests.
- Files reviewed: 17/17 changed files
- Comments generated: 2
- Review effort level: Lite
…loads Validate dependency field shape through the shared package reader. Require the core initializer and compatible extension after native and cross installation paths, while retaining the separate native header audits. Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
There was a problem hiding this comment.
🟡 Changes recommended
Unresolved findings concern ToS handling and removed dependency and pipeline regression coverage.
Once you've addressed the issues Copilot identified, you can request another Copilot review.
Review details
Suppressed comments (2)
Previously missed (1) — in code that hasn't changed since the last review.
tests/test_release_build_dependencies.py:1
- This removes the only automated suite that checks the release build requirement locks for exact pins, SHA-256 hashes, direct requirements, and their pipeline consumption. The refresh workflow and release-stage installs are still present, so future dependency or pipeline edits can now silently break the locked build path; restore this suite or replace it with equivalent assertions.
tests/test_034_conda_verify_cwd.py:31
- These deletions remove coverage for the still-present Conda pipeline contracts: platform stages depending on
ValidateWheelProvenance, best-effortsucceededOrFailed()consolidation, and the Official main-wheel provenance gate. Those behaviors remain inOneBranchPipelines/conda-build-pipeline.ymlandjobs/consolidate-conda-artifacts-job.yml, so retain or update these regression tests instead of dropping them.
)
- Files reviewed: 17/17 changed files
- Comments generated: 1
- Review effort level: Lite
Document approved agent provisioning before defaults-backed Windows ARM64 solves. Keep automatic terms acceptance disabled and preserve explicit Conda failure diagnostics. Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
There was a problem hiding this comment.
🔵 Needs a closer look
Dependency-lock contract tests were removed without replacement coverage.
Review details
Suppressed comments (1)
Previously missed (1) — in code that hasn't changed since the last review.
tests/test_release_build_dependencies.py:1
- Deleting this entire test module removes the only automated coverage for the committed dependency-lock contracts, including exact pins/hashes, pipeline
--require-hashesusage, and the immutable refresh workflow. Those files and workflows still exist and are used by CI, and this PR does not add replacement coverage; please retain or relocate these tests rather than deleting them.
- Files reviewed: 17/17 changed files
- Comments generated: 0 new
- Review effort level: Lite
There was a problem hiding this comment.
🔵 Needs a closer look
Add the missing Windows ARM64 and macOS wheel-selection coverage, and retain equivalent release-dependency contract tests.
Review details
Suppressed comments (3)
tests/test_030_pe_machine_assert.py:178
cross_build=Trueonly swapsPYTHONfor a non-executable path; on the x64 Windows CI host,sysconfig.get_platform()still selectswin_64andtarget_platformremainswin-64. Consequently this regression never exercises the newbld.batpath withODBC_ARCH=win_arm64, so the target-dependent core filename check can regress unnoticed. Parameterize the fixture's target subdir/architecture (or explicitly force a win-arm64 target) so both Windows targets are covered.
@pytest.mark.parametrize("cross_build", [False, True])
@pytest.mark.parametrize("state", ["valid", "missing", "missing-init", "wrong-tag", "abi3"])
def test_windows_recipe_requires_core_on_both_install_paths(tmp_path, cross_build, state):
tests/test_035_conda_macho_assert.py:229
- This cross-build fixture creates only the macOS code wheel, so the previous broad
cp${CONDA_PY}-*glob would select the same file and the test would pass before the*macosx*restriction. Add a Linux cp312 wheel in the same directory (with a distinguishable or invalid payload) and assert the macOS wheel is the one extracted, otherwise the new wheel-selection guard is untested.
with zipfile.ZipFile(wheels / f"mssql_python-1.13.0-{code_tag}.whl", "w") as wheel:
for name, data in payload.items():
if "/mssql_python_odbc/" not in name:
wheel.writestr(name.removeprefix("lib/python3.12/site-packages/"), data)
tests/test_release_build_dependencies.py:1
- Deleting this entire test module removes the repository's only contract coverage for the locked release dependencies and refresh workflow (hashes, direct requirements, pipeline
--require-hashesusage, target matrix, pinned actions, and immutable update-PR behavior). None of those invariants are replaced by the Conda tests in this PR, so a future lock or workflow change can silently break release builds; please retain or port equivalent coverage rather than deleting the module.
- Files reviewed: 17/17 changed files
- Comments generated: 0 new
- Review effort level: Lite
Work Item / Issue Reference
Summary
This pull request introduces significant improvements to the Conda packaging and validation workflow for
mssql-python, clarifies the installation and release process for Conda candidates, and strengthens platform compatibility and auditing. The most important changes are grouped below.Conda Packaging and Platform Compatibility
MSSQL_PYTHON_VERSIONto be explicitly set, preventing accidental builds with the wrong code version. The combined Conda package now includes both the code and ODBC payload, eliminating the need for a separate ODBC package as required by pip installations.__glibcdependency is raised to >=2.34 to ensure compatibility with the full native payload, including the bulk-copy core.macosxwheels to avoid accidentally using Linux wheels in cross-build scenarios.python_abipin for Python 3.12 to ensure ABI compatibility, and the documentation clarifies that dependencies resolve from thedefaultschannel without automatic terms acceptance.Validation and Auditing Enhancements
win-64andwin-arm64packages, and always uses the actual target subdir for checks.Testing and CI Improvements
testuserlogin withVIEW SERVER PERFORMANCE STATEpermission, enabling pool eviction tests to observe physical connections in SQL Server 2022 and 2025 jobs.Documentation Updates
README.mdand a newconda/README.mdclarify the temporary nature of the combined Conda candidate, its installation instructions, platform requirements, and that these changes do not constitute a public release or certification.Validation Logic Hardening
mssql_py_core) is present and loaded from the correct environment, with improved error messaging and isolation.These changes collectively improve the reliability, clarity, and platform compliance of the Conda packaging and validation process for
mssql-python.