Repository navigation
Add installer tests for official Python wheels - #580
Conversation
📊 Code Coverage Report
Diff CoverageDiff: main...HEAD, staged and unstaged changesNo lines with coverage information in this diff. 🔗 Quick Links |
There was a problem hiding this comment.
🟡 Changes recommended
Driver selection does not reject incorrect package paths on Linux and Windows, allowing a wheel unusable by the consumer resolver to pass.
Get a fresh assessment by requesting another Copilot review.
Pull request overview
Adds installation and native-library smoke gates for all 44 official Python wheels before artifact publication.
Changes:
- Adds isolated wheel installation and ODBC ABI verification.
- Integrates platform-specific gates into official builds.
- Adds pipeline and helper-script tests.
File summaries
| File | Description |
|---|---|
scripts/test-python-wheel-installs-linux.sh |
Tests Linux wheels in mirrored stock images. |
scripts/test-python-wheel-install.py |
Installs and validates one wheel. |
scripts/test_release_pipeline.py |
Verifies gate placement and matrix parameters. |
scripts/test_python_wheel_install.py |
Tests installer helper behavior. |
.pipeline/templates/validation-stages.yml |
Runs the new tests in validation. |
.pipeline/templates/test-python-wheel-installs-template.yml |
Defines platform-specific installation steps. |
.pipeline/OneBranch/stages.yml |
Places gates before artifact publication. |
.pipeline/OneBranch/OfficialPythonWheelsBuild.yml |
Enables gates for official builds. |
Review details
- Files reviewed: 8/8 changed files
- Comments generated: 1
- Review effort level: Balanced
💡 Configure MCP servers for context-aware, tailored reviews. Learn more in the docs.
Saurabh Singh (saurabh500)
left a comment
There was a problem hiding this comment.
This review came from an unattended sweep; its findings were not checked by a human first.
Verdict: the existing driver-selection issue remains outstanding; no additional findings from this inspection. This is not an approval.
Reviewed the complete merge-base diff and the affected build, injection, installation and artifact-publication paths. The installer gates cover the intended 44-wheel matrix in configuration; this is source inspection, not confirmation that those wheels executed successfully at this head.
Blocking: No new findings. The existing unresolved concern is tracked in the driver-selection thread; I have not duplicated or reclassified it.
Suggestion: No new findings.
Nit: None.
The performance pass found no substantiated additional finding in the installer/setup paths; no timing or memory measurements were made. Independent critique produced scope clarifications, not additional findings: the macOS runner change also applies to non-official uses of the shared job, and Linux installs are sequential within each architecture job rather than across both jobs.
Vahid Beiranvand (Vahid-b)
left a comment
There was a problem hiding this comment.
Automated review — generated by GitHub Copilot on behalf of Vahid Beiranvand (@Vahid-b). This is not an approval and does not satisfy the human review requirement. Findings may be incomplete or wrong; push back on anything that looks off.
Summary
Reviewed the full merge-base diff (0185d708 → 0ea6599b, 8 files) plus the surrounding injection, repair/retag, and artifact-publication paths. The gate is placed correctly in all five build jobs, the expected package paths match the existing injection/verification contract, and the ODBC symbol contract matches what mssql-odbc actually exports. I found no blocking issues. Two suggestions below are about drift resistance and template reuse, not correctness of the current pipeline.
The driver-selection concern from the earlier Copilot review is addressed by the --wheel-name / expected_driver_path rework in 78882c46; I re-checked it and did not reclassify it.
Verification performed
- Confirmed repository
microsoft/mssql-rs, PR #580, head0ea6599bcac7f9f522baa1d20a0ab7c789e37e40, merge base0185d708561de0f8f64348fe515b96c8500280efagainstorigin/main. Reviewed in an isolated detached worktree. - Cross-checked every mapping in
expected_driver_pathagainst the two existing contracts —scripts/inject-odbc-into-wheels.py(_GLIBC_X64/_MUSL_ARM64/…) and.pipeline/scripts/verify-python-wheels.ps1(Get-ExpectedOdbcMembers). All eight platform → member mappings agree. - Cross-checked all 39 entries of
REQUIRED_ODBC_SYMBOLSagainstpub extern "C"symbols inmssql-odbc/src: all 39 are exported (50 exported in total), so the export contract cannot fail on a typo. - Verified step ordering in
stages.ymlfor all five jobs: the gate follows the ODBC injection, the glibc-2.28 injection, and bothauditwheel repair/ retag steps, and precedesPublishPipelineArtifact@1. - Confirmed
MACOSX_DEPLOYMENT_TARGET=15.0is set unconditionally inbuild-python-wheels-template.yml, so themacOS-14→macOS-15move is required forpip installto accept themacosx_15_0_universal2tag and for the dylib to load — not incidental. - Confirmed
architecture: 'arm64'forUsePythonVersion@0is an established pattern in this repo (PublishFeeds-Sandbox.yml), and that theWindows_ARM64job already runs the Node.js agent workaround before the new steps. - Confirmed
evaluate()intest_release_pipeline.pymapsand(...)to n-aryall_, so the new three-argument compile-time condition expands correctly. bash -n scripts/test-python-wheel-installs-linux.sh→ clean; also confirmed the empty-arrayprintf "${wheels[@]}"error path is safe underset -uon bash ≥ 4.4 (all three image families qualify).- Not run: the pytest suites. This machine has no non-stub Python interpreter, so I relied on static review plus the referenced build 175810 rather than installing one.
Findings
Blocking
None.
Suggestion
-
The Linux release matrix is asserted against itself, so drift is invisible.
scripts/test-python-wheel-installs-linux.shhardcodesPYTHON_TAGS=(cp310 … cp314)andPLATFORM_TAGS=(manylinux_2_34 manylinux_2_28 musllinux_1_2), andtest_linux_installs_cover_release_matrixverifies those by matching the same literal strings back out of the same file. The canonical matrix lives in.pipeline/scripts/verify-python-wheels.ps1($pythonTags/$platforms), which is what the release gates actually enforce. They agree today, but when a Python version is added there, the shell script silently stops covering it and both assertions still pass — exactly the class of gap this PR exists to close. Consider parsingverify-python-wheels.ps1(or a shared source) in that test instead of restating the literals.The same applies more weakly to the Linux rows of
test_python_wheel_install_gate_precedes_artifact_publication: they assertpythonVersionsfalls back to the template default, but the template documents that Linux ignores that parameter, so those particular assertions do not constrain Linux coverage. -
The new gate steps omit the PR-reason guard that every step producing their input carries. The injection, glibc-2.28 injection, repair, and retag steps are all
condition: and(succeeded(), ne(variables['Build.Reason'], 'PullRequest')); the template's steps have no runtime condition, and the compile-time${{ if }}keys only offtestPythonWheelInstalls/buildOdbcNative/buildPythonWheels. That is safe today solely becauseOfficialPythonWheelsBuild.ymlis the only consumer setting the flag and it declarespr: none. Butstages.ymlis shared withNonOfficialPythonWheelsPublish.yml, which runs on PRs intomainand on a nightly schedule — the natural place someone would enable this next. There, PR runs would hand the gate wheels with no injected driver and it would fail rather than skip. Adding the samene(Build.Reason, 'PullRequest')condition to the template's steps would make the gate self-consistent with everything it depends on.
Nit
scripts/test-python-wheel-installs-linux.shand.pipeline/templates/test-python-wheel-installs-template.ymlhave no trailing newline, while the other files added in this PR do. (git diff --checkdoes not catch this.)
Relevant required-CI failures
coverage-report fails with ❌ Timeout: coverage artifact not found within 75 minutes — the merged Cobertura artifact never appeared across 10 polls, while the per-platform coverage artifacts all published. Every other listed check passes, including the full mssql-rs Pull request validation pipeline, and the coverage bot already posted 100% diff coverage / 93.9% overall for this branch. This reads as artifact/timing infrastructure rather than anything in this change; a re-run should clear it. No CI failure traceable to the diff.
Shiwani Gupta (shiwanigupta0809)
left a comment
There was a problem hiding this comment.
Unattended automated review — this review was posted without human confirmation. It is a COMMENT only, not an approval.
Summary
Reviewed the full merge-base diff (0185d708 → 0ea6599b, 8 files), the linked AB#48227 task, all existing review threads/bodies/top-level comments, and the directly affected wheel injection, matrix verification, repair/retag, and artifact-publication paths. I found no genuine new findings beyond the current-head suggestions already recorded in review 5236091696, so I have not duplicated them.
Blocking
None.
Medium
None.
Low
None.
Suggestion
None new.
Nit
None new.
Validation
uv run --python 3.13 python -m py_compile scripts/test-python-wheel-install.py scripts/test_python_wheel_install.py scripts/test_release_pipeline.pybash -n scripts/test-python-wheel-installs-linux.shgit diff --check 0185d708561de0f8f64348fe515b96c8500280ef..HEAD- Focused pytest execution was attempted, but fetching pytest/PyYAML failed non-interactively with a PyPI TLS handshake error. The PR validation pipeline passes on this head.
- The sole failing check is
coverage-report, which timed out waiting for the merged coverage artifact; the existing coverage comment reports 100% diff coverage and 93.9% overall coverage.
|
Vahid Beiranvand (@Vahid-b) Thanks — addressed both suggestions in 9ed77aa:
Also fixed the trailing-newline nit on both files. Left the weaker Linux-coverage point on |
Shiwani Gupta (shiwanigupta0809)
left a comment
There was a problem hiding this comment.
Unattended automated review — posted without human confirmation. This is a COMMENT only, not an approval.
Summary
Reviewed the complete merge-base diff (0185d708 → 9ed77aa7, 8 files), all existing inline threads, review bodies, top-level comments, checks, and the directly affected wheel build, ODBC injection, repair/retag, installer, and artifact-publication paths. The latest commit addresses the previously posted matrix-drift, PR-guard, and newline feedback; I found no genuine new findings.
Blocking
None.
Medium
None.
Low
None.
Suggestion
None.
Nit
None.
Targeted validation
- Python 3.13
py_compilefor the three changed Python scripts bash -n scripts/test-python-wheel-installs-linux.shgit diff --check 0185d708561de0f8f64348fe515b96c8500280ef..HEAD- Focused pytest was attempted, but pytest/PyYAML retrieval failed non-interactively with a PyPI TLS handshake error; all current PR checks pass, including the packaging tests in PR validation.
|
Unattended automated code review posted: #580 (review) Category counts: Blocking 0, Medium 0, Low 0, Suggestion 0, Nit 0. |
Vahid Beiranvand (Vahid-b)
left a comment
There was a problem hiding this comment.
Unattended automated review — generated without human confirmation. This is a COMMENT only, not an approval, and does not satisfy the human review requirement. Findings may be wrong; push back on anything that looks off.
Summary
Reviewed the complete merge-base diff (0185d708 → 9ed77aa7, 8 files) in an isolated detached worktree, plus the surrounding ODBC injection, glibc-2.28 repair/retag, wheel-verification and artifact-publication paths. The gate is placed after every artifact-transforming step and before PublishPipelineArtifact@1 in all five build jobs, the expected package paths agree with the existing injection/verification contract, and the driver-selection concern from the earlier Copilot review is genuinely closed by the --wheel-name / expected_driver_path rework. No blocking issues. One suggestion about drift resistance that the latest commit fixed for Linux but not for Windows/macOS, and one nit.
I did not duplicate the already-answered driver-selection thread, nor the matrix-drift/PR-guard/newline items from review 5236091696 — all three are addressed in 9ed77aa7 and I re-verified the fixes rather than restating them.
Verification performed
- Confirmed
microsoft/mssql-rs, PR #580, authorTheekshna, head9ed77aa74503668820f7961a860223f4805f89c8, merge base0185d708561de0f8f64348fe515b96c8500280efagainst a freshly fetchedorigin/main. - Re-derived the drift-detection logic in
test_linux_installs_cover_release_matrixby hand against the actualverify-python-wheels.ps1:\$pythonTags\s*=\s*(.+)matches line 77 only (.excludes newlines, and the later$pythonTagsoccurrences on lines 89/94 are not assignments), and the DOTALL@\((.*?)\)capture terminates on line 87 because the array body contains no parentheses. Filtering to manylinux/musllinux and stripping the arch suffix yields exactly{manylinux_2_34, manylinux_2_28, musllinux_1_2}. Addingcp315to the canonical$pythonTagsdoes make the assertion fail. The fix is real and it now tracks the canonical source. - Checked step ordering in
stages.ymlfor all five jobs: the template is inserted after the ODBC injection, after the glibc-2.28 injection, and after bothauditwheel repair/ retag steps, immediately beforePublishPipelineArtifact@1. - Verified the Windows step's
python ... --wheel $wheels[0].FullNameactually passes the resolved path: PowerShell evaluates index and member access in native-command argument mode (tested locally — it is not subject to the"$a[0]"expandable-string gotcha). - Confirmed
select_drivermatchesstr(file)against a forward-slash path, which is whatimportlib.metadataRECORD entries use on Windows as well, so the Windows arms are not silently unmatchable. - Confirmed the unconditioned
UsePythonVersion@0tasks in the new template are not a new PR-build failure risk:build-python-wheels-template.ymlalready runs the identical version/architecture selections in the same jobs without a PR guard, includingarchitecture: arm64for 3.11-3.14. - Not run: the pytest suites. This machine has no non-stub Python interpreter (only the Microsoft Store
python.exealias; nopy,uv, or installed distribution), so I relied on static derivation plus the referenced build 175810. This is the same gap reported by the two prior unattended reviews. gh pr checks 580: all 19 checks pass, includingcoverage-reportand the fullmssql-rs Pull request validationpipeline. No CI failure to attribute to this diff.
Findings
Blocking
None.
Suggestion
- The Windows and macOS halves of the install matrix still restate literals, so the drift gap this PR exists to close remains open for 32 of the 44 wheels.
9ed77aa7fixed this for Linux, buttest-python-wheel-installs-template.ymlcarries its own hardcodedpythonVersionsdefault (3.10-3.14) that duplicates the independent default inbuild-python-wheels-template.yml, andtest_python_wheel_install_gate_precedes_artifact_publicationasserts the effective versions against the same literal list it is meant to constrain. Add 3.15 to the build template and to$pythonTagsinverify-python-wheels.ps1and the result is: Linux fails loudly (good), while Windows x64, Windows ARM64 and macOS silently keep install-testing only 3.10-3.14 — both assertions still pass and the new version's wheels ship without ever being clean-installed. Deriving the default from, or cross-checking it against,verify-python-wheels.ps1the way the Linux test now does would close the remaining two thirds. (Windows ARM64 is a third copy, sincestages.ymlpasses 3.11-3.14 explicitly to both templates.)
Nit
scripts/test-python-wheel-install.py:13—import sysis unused, and the correspondingmonkeypatch.setattr(wheel_install.sys, "platform", "darwin")intest_select_driver_uses_native_slice_for_universal2is dead setup:expected_driver_pathkeys off the wheel's platform tag andplatform.machine()and never readssys.platform. Theplatform.machinepatch alone is what makes that test meaningful.
Shiwani Gupta (shiwanigupta0809)
left a comment
There was a problem hiding this comment.
Unattended automated code review — this review was posted without human confirmation. It is a COMMENT only, not an approval.
Summary
Reviewed the complete merge-base diff (0185d708 → d7eb72a7), the linked AB#48227 task, all existing inline threads, review bodies, top-level comments, checks, and the directly affected wheel build, ODBC injection, repair/retag, installation, and artifact-publication paths. The latest commit closes the remaining Windows/macOS matrix-drift coverage and removes the dead macOS test setup; no genuine new findings were identified.
Blocking
None.
Medium
None.
Low
None.
Suggestion
None.
Nit
None.
Targeted validation
- All current PR checks pass, including the full PR validation pipeline and coverage-report; the existing coverage report states 100% diff coverage and 93.9% overall coverage.
uv run --python 3.13 --no-project python -m py_compilepassed for the three changed Python files.bash -n scripts/test-python-wheel-installs-linux.shpassed.git diff --check 0185d708561de0f8f64348fe515b96c8500280ef..HEADpassed.- Focused pytest execution was attempted, but dependency retrieval failed noninteractively with a PyPI TLS handshake error.
|
Unattended automated code review posted with no findings: #580 (review) Category counts: Blocking 0, Medium 0, Low 0, Suggestion 0, Nit 0. |
Vahid Beiranvand (Vahid-b)
left a comment
There was a problem hiding this comment.
Unattended automated review — generated by GitHub Copilot on behalf of Vahid Beiranvand (@Vahid-b), without human confirmation. This is a COMMENT only, not an approval, and does not satisfy the human review requirement. Findings may be wrong; push back on anything that looks off.
Summary
Reviewed the complete merge-base diff (0185d708 -> d7eb72a7, 8 files) in an isolated detached worktree, plus the surrounding ODBC injection, glibc-2.28 repair/retag, wheel-verification and artifact-publication paths, the AB#48227 reference in the description, every inline thread, all prior review bodies and top-level comments, and gh pr checks. The two items I raised at 9ed77aa7 are genuinely fixed at this head and I have not restated them: test_windows_and_macos_install_matrix_tracks_release_python_tags now cross-checks the template default and the Windows ARM64 override against verify-python-wheels.ps1, and the dead sys import plus its monkeypatch line are gone.
No blocking issues. One item is about the evidence backing the change rather than the code; one is a narrow residual of the drift-hardening work.
Verification performed
- Confirmed
microsoft/mssql-rs, PR #580, authorTheekshna, headd7eb72a724177a679f1fae7b5b158218cef3d97a, merge base0185d708561de0f8f64348fe515b96c8500280efagainst a freshly fetchedorigin/main. - Re-checked all 39 entries of
REQUIRED_ODBC_SYMBOLSagainstmssql-odbc/src/api/exports.rs: all 39 are exported unconditionally; the file's only#[cfg(...)]-gated export is the non-Windows ANSISQLSetConnectAttr, which is not in the list. The export contract cannot fail on a typo or a platform gate. - Confirmed
testPythonWheelInstallsis set byOfficialPythonWheelsBuild.ymlonly, and that all five${{ if }}sites instages.ymladditionally requirebuildOdbcNativeandbuildPythonWheels. - Re-verified gate placement in all five build jobs: the template lands after ODBC injection, after the glibc-2.28 injection, and after both
auditwheel repair/ retag /cpsteps, immediately beforePublishPipelineArtifact@1. - Re-derived
_canonical_python_versions()andtest_linux_installs_cover_release_matrixby hand against the actualverify-python-wheels.ps1:$pythonTagsyields{3.10..3.14}, and the DOTALL@\((.*?)\)capture of$platformsfiltered to manylinux/musllinux and stripped of the arch suffix yields exactly{manylinux_2_34, manylinux_2_28, musllinux_1_2}, matchingPLATFORM_TAGS. - Confirmed the Windows step's
python ... --wheel $wheels[0].FullNamepasses the resolved path: PowerShell evaluates index plus member access in native-command argument mode (retested locally on this host). - Confirmed
shopt -s nullglobis in effect for the macOSextensions=(...)glob, so a missing extension yields a count of 0 and a loud failure rather than a literal path. gh pr checks 580: all checks pass at this head, including the fullmssql-rs Pull request validationandcoverage-report. No CI failure attributable to the diff.- Not run: the pytest suites. This machine has no non-stub Python interpreter (only the Microsoft Store
python.exe/python3.exealiases; nopy, nouv, no installed distribution), so I relied on static derivation plus the packaging tests that PR validation runs viavalidation-stages.yml.
Findings
Blocking
None.
Suggestion
- The cited official-build evidence is five commits stale, and the parts of this gate it would exercise are unreachable from PR CI - see the inline comment on
.pipeline/OneBranch/OfficialPythonWheelsBuild.yml. - The Windows ARM64 half of the new drift guard re-hardcodes the
cp310exclusion instead of deriving it - see the inline comment onscripts/test_release_pipeline.py.
Nit
None.
Scope note (not a finding)
The "depends on libraries available only in the build image" class is closed for Linux only: those 30 wheels are installed in the stock PyPA manylinux/musllinux images, while the 9 Windows and 5 macOS installs run on the build agent itself, which carries the toolchain that produced the binaries. The description is explicit about the Linux rationale, so this is a stated scope boundary rather than a defect - worth keeping in mind if a future consumer-side load failure slips through this gate.
Shiwani Gupta (shiwanigupta0809)
left a comment
There was a problem hiding this comment.
Unattended automated code review — posted without human confirmation. This is a COMMENT only, not an approval.
Reviewed the complete merge-base diff, linked AB#48227, all existing discussions/checks, and the directly affected wheel build, injection, repair/retag, installation, and publication paths. No genuine new findings were identified. The PR description already records that the official 44-wheel validation must be rerun at the current head.
Blocking
None.
Medium
None.
Low
None.
Suggestion
None.
Nit
None.
Validation
- Python 3.13
py_compilepassed for the three changed Python files. bash -n scripts/test-python-wheel-installs-linux.shpassed.git diff --check 0185d708561de0f8f64348fe515b96c8500280ef..HEADpassed.- Focused pytest was attempted, but dependency retrieval failed non-interactively with a PyPI TLS handshake error.
- GitHub/CodeQL/coverage checks pass; the current Azure DevOps PR validation run remains pending.
|
Unattended automated code review completed with no findings: #580 (review) Category counts: Blocking 0, Medium 0, Low 0, Suggestion 0, Nit 0. |
Vahid Beiranvand (Vahid-b)
left a comment
There was a problem hiding this comment.
Unattended automated review — generated by GitHub Copilot on behalf of Vahid Beiranvand (@Vahid-b), without human confirmation. This is a COMMENT only, not an approval, and does not satisfy the human review requirement. Findings may be wrong; push back on anything that looks off.
Summary
Reviewed the complete merge-base diff (0185d708 -> 7891f723, 8 files) in an isolated detached worktree, plus the surrounding ODBC injection, glibc repair/retag, signing, and artifact-publication paths. Since the previous review at d7eb72a7, the only change is 7891f723, which replaces the hard-coded - {"3.10"} in test_windows_and_macos_install_matrix_tracks_release_python_tags with _canonical_win_arm64_python_versions(), derived from verify-python-wheels.ps1's own Where-Object filter.
No blocking, medium, or low findings.
Verification performed
- Re-ran the new
win_arm64filter regex against the live.pipeline/scripts/verify-python-wheels.ps1(.NET regex, same semantics asre.DOTALL): it matches, captures$_ -ne 'cp310', and yields exclusion{3.10}, soexpected_arm64_versionsresolves to{3.11, 3.12, 3.13, 3.14}— exactly theWindows_ARM64override instages.yml. If the filter is ever rewritten (e.g.-notin @(...)), theassert matchfires with the explicit message rather than silently passing. - Cross-checked every entry of
REQUIRED_ODBC_SYMBOLS(39) againstmssql-odbc/src/api/exports.rs(50 exported entry points): all 39 are present, none misspelled, no ANSI/Wvariant mismatch. - Cross-checked
expected_driver_path()against both sides of the contract —inject-odbc-into-wheels.py's_WIN_*/_GLIBC_*/_MUSL_*/_MACOS_*constants andGet-ExpectedOdbcMembersinverify-python-wheels.ps1— all eight platform/arch paths agree. - Confirmed
inject-odbc-into-wheels.pyregeneratesRECORD, sodistribution.filesreally can see the injected driver;select_driver's exact-path match is therefore meaningful rather than vacuous. - Confirmed the gate runs after ESRP driver/wheel signing (Windows) and after injection plus manylinux repair/retag (Linux) and before
PublishPipelineArtifact@1in all five jobs, matching the stated goal. - Confirmed the mirrored images the Linux script pulls (
import/python-build/{manylinux_2_34,manylinux_2_28,musllinux_1_2}_{x86_64,aarch64}) all exist in.pipeline/sync-container-images.yml. - Probed the PowerShell argument-mode expansion of
$wheels[0].FullName(index + property in command argument position) — expands correctly, no quoting bug. UsePythonVersion@0witharchitecture: arm64and no PR-build condition mirrors the existingbuild-python-wheels-template.ymlpattern on the sameRUST-ARM64-WUS3pool, so it introduces no new agent assumption.- Test-merged
origin/maininto7891f723: clean auto-merge, and the merged result still carries all five install-template call sites,macOS-15, andscripts/test_python_wheel_install.pyin the packaging pytest list. Both this branch andmaingrewscripts/test_release_pipeline.py, but in non-overlapping regions.
Blocking
None.
Suggestion
None.
Nit
None.
Merge readiness (not a code finding)
Two gating items are outside the diff itself:
- Required validation is red at this head.
gh pr checksreportsmssql-rs Pull request validationfailing (build 176490), specificallyBuild mssql-python mssql-python suite on mssql-odbc driver (cross-repo). Nothing in this diff touches driver code, and the packaging job that does exercise the newscripts/test_python_wheel_install.pypassed — so this looks unrelated. Note the same job passes on PRs #597/#599/#600, and this branch sits five commits behindorigin/main, which has since merged substantialmssql-odbc/mssql-tdschanges (#586, #602). A rebase ontomainand a re-run would confirm whether the failure is stale-base drift rather than a real regression. Per.github/instructions/pr-workflow.instructions.md, validation must be green on the latest commit. - The Official Python Wheels Build re-run is still outstanding, exactly as your own stale-validation note in the description says: 175810 ran at
757299c6, and none of the new install steps,test-python-wheel-installs-linux.sh, or the--wheel/--verify/--verify-driver-exportspaths execute underBuild.Reason == 'PullRequest'. Five commits have landed in that unexercised region since. Please re-run at7891f723(or later) and refresh the Validation section before merging.
With those two items resolved, the PR appears ready for human review. This is not an approval.
Shiwani Gupta (shiwanigupta0809)
left a comment
There was a problem hiding this comment.
Unattended automated code review — posted without human confirmation. This is a COMMENT only, not an approval.
Summary
Reviewed the complete merge-base diff (0185d708 → 7891f723, 8 files), linked AB#48227 (Task, New: “Add ODBC installer tests in official wheel pipeline”), all paginated inline comments/review bodies/top-level comments, checks, and the directly affected wheel build, injection, repair/retag, installation, and publication paths. The existing review threads are addressed, and the PR description explicitly records the remaining stale official-build validation; I found no genuine new code findings.
Blocking
None.
Medium
None.
Low
None.
Suggestion
None.
Nit
None.
Targeted validation
git diff --check 0185d708561de0f8f64348fe515b96c8500280ef..HEADpassed.bash -n scripts/test-python-wheel-installs-linux.shpassed.- Python 3.13
py_compilepassed for the three changed Python files. - Focused pytest was attempted, but pytest retrieval failed non-interactively with a PyPI TLS handshake error.
- Current PR validation is red only in the cross-repo
mssql-python suite on mssql-odbc driverjob; this diff does not change driver code, and that status was already discussed in prior review.
|
Unattended automated code review completed with no findings: #580 (review) Category counts: Blocking 0, Medium 0, Low 0, Suggestion 0, Nit 0. |
Vahid Beiranvand (Vahid-b)
left a comment
There was a problem hiding this comment.
Unattended automated review - generated without human confirmation. This is a COMMENT only, not an approval, and does not satisfy the human review requirement. Findings may be wrong; push back on anything that looks off.
Summary
Reviewed the complete merge-base diff (0185d708 -> 7891f723, 8 files) in an isolated detached worktree, plus the surrounding ODBC injection, glibc repair/retag, image-mirroring and artifact-publication paths, the AB#48227 reference, every inline thread, all prior review bodies and top-level comments, and gh pr checks. The previously raised driver-selection, matrix-drift, PR-guard, dead-sys-patch and win_arm64-exclusion items are all genuinely closed at this head; I re-verified each rather than restating them.
Unlike the three prior unattended passes I was able to obtain a real interpreter and run the suites, plus exercise the Windows install path end to end against a real ODBC-exporting DLL. No blocking findings. One suggestion about a property the new pipeline tests do not constrain.
Verification performed
- Confirmed
microsoft/mssql-rs, PR #580, authorTheekshna, head7891f723834b2638614f237f30f1735fef93887b, merge base0185d708561de0f8f64348fe515b96c8500280efagainst a freshly fetchedorigin/main. - Ran the tests. Bootstrapped Python 3.12.7 from the NuGet
pythonpackage plus pytest 9.1.1 / PyYAML 6.0.3, thenpython -m pytest scripts/test_python_wheel_install.py scripts/test_release_pipeline.py -q-> 164 passed. - Mutation-tested both drift guards and confirmed they are non-vacuous. Adding
'cp315'to$pythonTagsinverify-python-wheels.ps1fails bothtest_linux_installs_cover_release_matrixandtest_windows_and_macos_install_matrix_tracks_release_python_tags. Widening theWhere-Objectfilter to{ $_ -ne 'cp310' -and $_ -ne 'cp311' }fails the ARM64 half with{'3.11','3.12','3.13','3.14'} == {'3.12','3.13','3.14'}. Both mutations reverted; worktree clean. - Exercised the Windows runtime path end to end, which no check on this PR runs. Built a probe wheel with the real maturin layout (
mssql_py_core/__init__.py+mssql_py_core/libs/windows/x64/mssqlodbc.dll) whose payload isC:\Windows\System32\odbc32.dll, so the ODBC entry points genuinely exist, then ranpython scripts\test-python-wheel-install.py --wheel <probe>. Result: venv creation,pip install --no-index --no-deps, the-Ichild with--wheel-name, metadata/version check,select_driver,WinDLLload,SQLAllocHandle(SQL_HANDLE_ENV)andSQLFreeHandleall succeeded -Verified mssql-python-rs 0.1.0: ...\mssql_py_core\libs\windows\x64\mssqlodbc.dll, exit 0. A second probe with a non-PE payload failed loudly at import, as intended. - Confirmed
select_driver's exact-string match is valid on Windows. pip-installed a probe wheel and dumpedimportlib.metadata.distribution('mssql-python-rs').files: every entry is forward-slashed ('mssql_py_core/libs/windows/x64/mssqlodbc.dll'), so the posix-styleexpectednever silently fails to match on Windows. - Cross-checked
REQUIRED_ODBC_SYMBOLSprogrammatically, not by eye: parsed all 52no_manglesites undermssql-odbc/src(50 distinct entry points) with their surrounding#[cfg(...)]attributes. All 39 required symbols are exported, none is platform-gated (the only gated export, non-WindowsSQLSetConnectAttr, is correctly absent from the list). The macOSnm -gUgate cannot fail on a typo or a cfg gate. - Verified the mirrored image references resolve.
.pipeline/sync-container-images.ymlline 1349-1354 mirrors exactlyimport/python-build/{manylinux_2_34,manylinux_2_28,musllinux_1_2}_{x86_64,aarch64}:latestinto$(GHCR_NAMESPACE), and an anonymous GHCR manifest probe formanylinux_2_28_x86_64andmusllinux_1_2_aarch64returned HTTP 200 for both - so theghcr.io/microsoft/mssql-rs/import/python-build/...path (note theimport/segment, unlike the_rustimages already pulled instages.yml) is correct and anonymously pullable. - Confirmed
vmImage: macOS-15on Azure Pipelines is the Intel x64 image (themacOS-15-arm64preview label was withdrawn), matching the description's claim that the hosted runner validates installation and the x64 slice only; and that29e9747fintroduced themacOS-14 -> macOS-15move, so it was covered by build 175810. - Confirmed
expected_driver_path's eight platform/arch mappings match bothinject-odbc-into-wheels.py's_WIN_*/_GLIBC_*/_MUSL_*/_MACOS_*constants andGet-ExpectedOdbcMembersinverify-python-wheels.ps1. - Probed PowerShell argument-mode expansion of
$wheels[0].FullNameon this host: index plus property expands to a single correct argument; no quoting bug. - Confirmed
scripts/test_python_wheel_install.pyhas exactly one CI call site (validation-stages.yml:130) and that it was updated.
Findings
Blocking
None.
Suggestion
- The new pipeline tests constrain the gate's position relative to artifact publication but not relative to the steps that produce its input - see the inline comment on
scripts/test_release_pipeline.py.
Nit
None.
Merge readiness (not code findings)
- Required validation is red at this head.
mssql-rs Pull request validationfails (build 176490) inBuild mssql-python mssql-python suite on mssql-odbc driver (cross-repo). This diff changes no Rust or driver code, and the packaging job that actually runs the newscripts/test_python_wheel_install.pypasses, so it is not attributable to the change.origin/mainhas since merged #606, which pins both cross-repo Python jobs to an approved commit and removes the floating-mainfallbacks - the most likely cause of this failure. Mergingmaininto the branch and re-running should confirm. Per.github/instructions/pr-workflow.instructions.md, validation must be green on the latest commit. - The Official Python Wheels Build re-run is still outstanding, as your own staleness note says. I independently confirmed the exposure: every step in
test-python-wheel-installs-template.ymlcarriesne(variables['Build.Reason'], 'PullRequest')andtestPythonWheelInstallsis set only byOfficialPythonWheelsBuild.yml(which declarespr: none), sotest-python-wheel-installs-linux.shand the--wheel/--verify/--verify-driver-exportspaths never execute under any check here. Since the cited build 175810 at757299c6,PLATFORM_TAGS, the macOS extract/lipo/nmblock and the three runtimecondition:keys all changed. My end-to-end probe above covers the Windows leg on real code; the Linux and macOS legs still need the official run at7891f723or later.
With those two resolved, the PR looks ready for human review. This is not an approval.
Shiwani Gupta (shiwanigupta0809)
left a comment
There was a problem hiding this comment.
Unattended automated code review — posted without human confirmation. This is a COMMENT only, not an approval.
Summary
Reviewed the complete merge-base diff (0185d708 → 7891f723, 8 files), linked AB#48227, all paginated inline comments/review bodies/top-level comments, current checks, and the directly affected wheel build, injection, repair/retag, installation, and publication paths. I found no genuine new findings; the existing current-head suggestion about asserting that the gate follows every wheel-transforming step was not duplicated.
Blocking
None.
Medium
None.
Low
None.
Suggestion
None.
Nit
None.
Targeted validation
git diff --check 0185d708561de0f8f64348fe515b96c8500280ef..HEADpassed.bash -n scripts/test-python-wheel-installs-linux.shpassed.- Python 3.13
py_compilepassed for the three changed Python files. - Focused pytest was attempted, but PyYAML retrieval failed non-interactively with a PyPI TLS handshake error.
- Current checks remain red only in the previously discussed cross-repo
mssql-python suite on mssql-odbc driverjob; packaging, CodeQL, coverage, linked-issue, and other platform jobs pass.
|
Unattended automated code review completed with no new findings: #580 (review) Category counts: Blocking 0, Medium 0, Low 0, Suggestion 0, Nit 0. |
7891f72 to
c38149b
Compare
There was a problem hiding this comment.
Copilot review overview
🟡 Changes recommended
The macOS gate uses invalid lipo argument ordering, and the corrected current head still needs an official validation run.
Get a fresh assessment by requesting another Copilot review.
Review effort: Balanced
Findings: 1
Open (2)
Resolved since last review (1)
Vahid Beiranvand (Vahid-b)
left a comment
There was a problem hiding this comment.
Automated review — generated by GitHub Copilot on behalf of Vahid Beiranvand (@Vahid-b), without human confirmation. This is a COMMENT only, not an approval, and it does not satisfy the human review requirement. Findings may be incomplete or wrong; push back on anything that looks off.
Summary
Reviewed the complete merge-base diff (6a11b315 → 91392208, 8 files) in a detached isolated worktree, plus the surrounding ODBC injection / glibc repair / retag / artifact-publication steps, the AB#48227 reference, every review thread, all prior review bodies and top-level comments, and gh pr checks.
Note the merge base moved since the last automated pass: the branch was rebased onto newer main, so 7891f723..91392208 also drags in unrelated main work (C++ CodeQL, ODBC Miri legs, the Alpine 3.19/3.20 matrix trim). Restricted to the eight files this PR actually owns, the only change since the last reviewed head is 91392208, which adds the ordering assertion requested in the previous round.
No blocking findings, no suggestions, no nits. I re-derived the previously raised items rather than restating them, ran the suites, mutation-tested the new assertion, and adjudicated the one disputed thread — the author is correct there and the bot is wrong.
Verification performed
- Confirmed live repo
microsoft/mssql-rs, PR #580, authorTheekshna, head9139220866f05543e2bb568deb9ff33a0eeb87d4, not draft, OPEN; merge base6a11b315128cabd154f60bbc2024dc4396cd9e52against a freshly fetchedorigin/main. Revalidated immediately before posting. - Ran the suites. Bootstrapped Python 3.12.7 (NuGet) + pytest 9.1.1 / PyYAML 6.0.3, then
python -m pytest scripts/test_python_wheel_install.py scripts/test_release_pipeline.py -q→ 178 passed. - Mutation-tested
91392208's new assertion and confirmed it is non-vacuous. Moved the Linux x64 install-gate template from afterRepair glibc-2.28 wheels (Linux x64)to beforeRepair glibc wheels into manylinux (Linux x64). Result:test_python_wheel_install_gate_precedes_artifact_publication[Linux_x64-...]fails withassert 16 < 15 / where 16 = max([11, 13, 14, 16]); the other 4 parametrizations still pass. Reverted;git status --porcelainis empty. - Confirmed the assertion's anchors exist in every gated job, so
assert transform_indicescannot silently pass on an empty list: Windows x64/ARM64 and macOS matchInject ODBC driver into ...; Linux x64/ARM64 match bothInject ODBC driver into wheels (Linux …)andRepair glibc …(steps atstages.yml:367/383/396/414, gate at417). A rename of those steps fails loudly rather than degrading to a no-op. - Re-derived the ODBC export contract at this head (worth redoing — the rebase pulled real
mssql-odbcchanges in). Parsed every#[unsafe(no_mangle)] pub … extern "C" fnundermssql-odbc/src: 49 exports; all 39 entries ofREQUIRED_ODBC_SYMBOLSare present and none is#[cfg]-gated. The single gated export in the driver isSQLSetConnectAttrundernot(windows), correctly absent from the required list. So the macOSnm -gUgate cannot fail on a typo or a cfg gate. - Confirmed
maturin build --target universal2-apple-darwin(build-python-wheels-template.yml:106) makes the extension a genuine fat binary, whilestages.yml:14documents the ODBC driver slices as separate thin binaries — so-verify_arch x86_64 arm64on the extension and single-arch verifies on eachlibs/macos/<arch>/lib/mssqlodbc.dylibare each the right assertion for their target. - Checked
UsePythonVersion@0witharchitecture: arm64: already established in-repo practice (build-python-wheels-template.yml:172,PublishFeeds-Sandbox.yml:430), not a new risk. - Checked the
$(echo … | tr -d '.')command substitution inside the macOSscript:block against ADO macro syntax; the repo already relies on this exact behaviour ($(whoami)instages.yml), so it is consistent rather than novel. - Confirmed all review threads are currently resolved, and that no
copilot-auto-review v3marker exists for this head (prior markers:326af0e8,0ea6599b,9ed77aa7,7891f723).
Adjudication of the open lipo thread — the author is right
The bot finding on test-python-wheel-installs-template.yml:80-82 claimed the input file must follow -verify_arch. That is backwards, and applying the suggested reorder would break the macOS gate. From the lipo(1) man page:
-verify_arch arch_type ... — Take one input file and verify the specified arch_types are present in the file. … Because more than one arch_type can be verified at once, all of the input files must appear before the -verify_arch flag on the command-line.
with synopsis lipo input_file command [option...]. The current form — lipo "${extensions[0]}" -verify_arch x86_64 arm64 — is exactly the documented one. ttk (@Theekshna)'s rebuttal stands; no change needed. (Copilot's latest overview at 9139220 has already dropped this finding.)
Findings
Blocking
None.
Suggestion
None.
Nit
None.
Required CI
No required-CI failures. mssql-rs Pull request validation (build 176870) is still pending at this head — several Build Stage legs and coverage-report are mid-run; Build MacOS, Build Windows ARM, Kerberos, the cross-repo mssql-python suite on mssql-odbc driver, CodeQL and CLA are green. The cross-repo failure flagged in the previous round is resolved at this head. Per .github/instructions/pr-workflow.instructions.md, validation still needs to land green on the final commit.
Merge readiness (not a code finding)
The staleness note in your description is accurate and remains the one real residual risk, so I am not re-filing it as a finding — only confirming the exposure independently. Every step in test-python-wheel-installs-template.yml carries ne(variables['Build.Reason'], 'PullRequest'), and testPythonWheelInstalls: true is set only by OfficialPythonWheelsBuild.yml, which triggers on stable. So test-python-wheel-installs-linux.sh and the --wheel / --verify / --verify-driver-exports paths of test-python-wheel-install.py execute under no check on this PR — only the pytest units do. Since the cited build 175810 at 757299c6, the macOS extract/lipo/nm block, PLATFORM_TAGS, the driver-path resolver and the runtime condition: keys have all changed, so the macOS and Linux runtime legs have never executed as written. An Official Python Wheels Build at 9139220 (or later) before merge is the thing that closes it.
With the validation run refreshed and PR validation green, this PR appears ready for human review. It has not been approved.
Shiwani Gupta (shiwanigupta0809)
left a comment
There was a problem hiding this comment.
Unattended automated code review — posted without human confirmation. This is a COMMENT only, not an approval, and does not satisfy the human review requirement.
Summary
Reviewed the complete merge-base diff (6a11b315 → 91392208, 8 files) in a dedicated worktree, PR title/body, linked AB#48227, all paginated inline comments/reviews/top-level comments, current checks, and the directly affected wheel build, signing/injection, repair/retag, installation, and publication paths. Prior findings are addressed or already tracked; I found no new code findings.
Blocking
None.
Medium
None.
Low
None.
Suggestion
None.
Nit
None.
Validation
- All current GitHub and Azure DevOps PR checks pass at head
91392208, including PR validation, cross-repo jobs, CodeQL, and coverage. git diff --check 6a11b315128cabd154f60bbc2024dc4396cd9e52..HEADpassed.bash -n scripts/test-python-wheel-installs-linux.shpassed.- Python 3.12
py_compilepassed for the three changed Python files. - Focused pytest was attempted, but pytest/PyYAML retrieval failed non-interactively with a PyPI TLS handshake error. The same focused suites passed in current-head review evidence and PR validation.
- AB#48227 lookup succeeded: Task, New, “Add ODBC installer tests in official wheel pipeline”; the PR scope matches it and the work item links PR #580.
The PR description cites Official Python Wheels Build 176920 succeeding at the current head across all 44 final wheels, closing the previously documented end-to-end validation gap.
|
Unattended automated code review completed with no findings: #580 (review) Category counts: Blocking 0, Medium 0, Low 0, Suggestion 0, Nit 0. |
Vahid Beiranvand (Vahid-b)
left a comment
There was a problem hiding this comment.
Note
This is an automated review generated by GitHub Copilot. It is advisory only, has not been vetted by a human, and is not an approval. Please verify each point before acting on it.
Summary
This PR adds a release gate to the Official Python Wheels Build that clean-installs and smoke-exercises all 44 final wheels after signing, ODBC injection, and Linux repair/retagging, before each platform artifact is published. The design is sound: the gate runs in-job after every wheel-transforming step and before PublishPipelineArtifact@1, Linux testing uses stock PyPA manylinux/musllinux images (mirrored through Microsoft GHCR) rather than the custom build images so undeclared runtime dependencies cannot be masked, and the verifier drives a real SQLAllocHandle/SQLFreeHandle round trip through ctypes rather than only asserting file presence.
The PR-CI-side unit tests are the strongest part of the change, because the gate itself never executes in PR validation (every runtime step carries ne(variables['Build.Reason'], 'PullRequest')). I verified by mutation that the two cross-check tests added during review are non-vacuous. No blocking issues found. All three findings below are the same class those cross-check tests exist to close: literals in the new code that restate a canonical source without being derived from or checked against it. Each fails loudly in the Official build rather than shipping a bad wheel, so they are shift-left gaps, not correctness defects.
All 8 prior review threads are resolved, the Validation section has been refreshed to Official build 176920 at this exact head, and all required checks are green.
Verification performed
- Confirmed live repository
microsoft/mssql-rsand live authorTheekshnabefore reading the diff and again immediately before posting. Head SHA9139220866f05543e2bb568deb9ff33a0eeb87d4; not a draft. - Merge base against
origin/main(3248bcef):6a11b315128cabd154f60bbc2024dc4396cd9e52. Reviewed the full$BASE..HEADdiff (8 files, +992/-2) in a detached worktree, not the main checkout. - Read the PR title/body, all reviews, all issue comments, and all 8 review threads (
pulls/580/reviews,pulls/580/comments,issues/580/comments, plusreviewThreadsvia GraphQL for resolution state). Nothing below duplicates an existing thread. gh pr checks 580— 19/19 passing, includingmssql-rs Pull request validation(ADO build 176870),coverage-report,CodeQL, and both cross-repomssql-pythonlegs. No required failures.- Ran the PR's own tests:
python3 -m pytest scripts/test_python_wheel_install.py -q→ 20 passed;python3 -m pytest scripts/test_release_pipeline.py -q -k 'wheel_install_gate or install_matrix_tracks or macos_wheel_install_gate'→ 7 passed. bash -n scripts/test-python-wheel-installs-linux.sh→ clean.- Mutation, confirming the review-added drift tests are not vacuous: added
'cp315'to$pythonTagsin.pipeline/scripts/verify-python-wheels.ps1→test_linux_installs_cover_release_matrixfails andtest_windows_and_macos_install_matrix_tracks_release_python_tagsfails. Good. - Mutation behind finding 1: changed
libs/linux/glibc/x86_64/lib/mssqlodbc.so→libs/linux/glibc/x86_64/mssqlodbc.soin both canonical sources (Get-ExpectedOdbcMembersinverify-python-wheels.ps1and_GLIBC_X64ininject-odbc-into-wheels.py) → all 27 new tests still pass. - Mutation behind finding 2: changed
macosx_15_0_universal2→macosx_16_0_universal2inverify-python-wheels.ps1's$platforms→ all 27 new tests still pass. - Measured finding 3 by extracting
pub unsafe extern "C" fn SQL*frommssql-odbc/src/api/exports.rs(50 symbols) and diffing againstREQUIRED_ODBC_SYMBOLS(39): no required symbol is missing from the driver (so no false-failure risk), 11 exported entry points are outside the gate. - Verified in PowerShell that
$wheels[0].FullNameresolves correctly in native-command argument position (& cmd /c echo $wheels[0].FullName→ the path), so the Windows step is not affected by the argument-mode parsing trap. - Checked that the new template's unconditioned
UsePythonVersion@0matches the existing pattern inbuild-python-wheels-template.yml(lines 93-94, 167-172) — consistent with house style, not filed. - All mutations reverted;
git status --porcelainin the worktree is empty. - Not verified: the ADO work item AB#48227 and Official Python Wheels Build 176920 (no Azure DevOps access from this session), so the "44 wheels verified at this head" claim rests on the author's report. I also could not execute any of the pipeline-side code — the Linux Docker flow, the macOS
lipo/nmblock, and the--wheel/--verify/--verify-driver-exportsruntime paths are all PR-guarded and run only in the Official build. No msodbcsql or SqlClient checkout exists on this host; the diff contains no Rust or ODBC-surface changes, so parity review is not applicable.
Findings
Blocking
None.
Suggestion
1. scripts/test-python-wheel-install.py:84-108 — expected_driver_path restates the canonical package layout instead of deriving it, and nothing cross-checks the two.
The injected package paths now exist in three independent places: _GLIBC_X64/_MUSL_X64/etc. in scripts/inject-odbc-into-wheels.py:47-50, Get-ExpectedOdbcMembers in .pipeline/scripts/verify-python-wheels.ps1, and the new expected_driver_path. test_expected_driver_path_matches_consumer_resolver pins the third against its own transcribed literals, so a coordinated change to the first two goes unnoticed here.
Measured, not inferred: I changed the glibc x86_64 path in both canonical sources (dropping the /lib/ segment) and all 20 tests in scripts/test_python_wheel_install.py plus the 7 targeted test_release_pipeline.py tests still passed. Mutation reverted.
To be fair to the change: the failure mode is loud — select_driver raises ODBC driver not found at expected package path and the Official build fails, so no bad wheel ships. But this is exactly the argument that motivated test_linux_installs_cover_release_matrix and test_windows_and_macos_install_matrix_tracks_release_python_tags in this same PR: the layout change would be caught at release time instead of in PR CI, which is the only place this gate's wiring can be checked at all. Cheap to close in the same style — parse Get-ExpectedOdbcMembers's switch -Wildcard arms out of verify-python-wheels.ps1 and assert expected_driver_path agrees for each wheel-name pattern.
2. .pipeline/templates/test-python-wheel-installs-template.yml:74 and .pipeline/OneBranch/stages.yml:586 — the macOS platform tag is now a five-way literal coupling with no cross-check.
macosx_15_0_universal2 / 15.0 / macOS-15 must agree across: $platforms in verify-python-wheels.ps1, the wheel tags --platform-tag macosx_15_0_universal2 retag in build-python-wheels-template.yml, export MACOSX_DEPLOYMENT_TARGET=15.0 (same file, line 103), the new install template's wheel glob, and the vmImage: macOS-15 this PR bumps. Nothing ties them together.
Measured: bumping $platforms to macosx_16_0_universal2 in verify-python-wheels.ps1 leaves all 27 new tests green. The macOS gate would then match zero wheels and fail with Expected one cpXXX macOS universal2 wheel, found 0 — again loud, again only at release. Deriving the glob's platform tag from $platforms (the way the Linux script's PLATFORM_TAGS now is) would close it, and would also make the vmImage ↔ deployment-target coupling explicit.
3. scripts/test-python-wheel-install.py:22-59 — REQUIRED_ODBC_SYMBOLS has no provenance and no cross-check against the driver's actual export surface.
mssql-odbc/src/api/exports.rs declares 50 #[unsafe(no_mangle)] pub unsafe extern "C" fn SQL* entry points; this list names 39. I confirmed every one of the 39 does exist in exports.rs, so there is no false-failure risk today. The 11 excluded are SQLCloseCursor, SQLConnectW, SQLGetDescFieldW, SQLGetDescRecW, SQLGetDiagFieldW, SQLGetEnvAttr, SQLGetFunctions, SQLNativeSqlW, SQLNumParams, SQLSetConnectAttr, SQLSetDescRec.
A curated consumer-contract subset is a defensible choice, but the list carries no comment saying that is what it is or where it came from, so the next reader cannot tell a deliberate subset from a stale one — and an export silently disappearing from the driver (SQLCloseCursor or SQLNumParams, say) would pass this gate. Either add a one-line comment stating the list is the mssql-python consumer contract and naming its source, or derive it from exports.rs so additions/removals surface in PR CI.
Nit
4. .pipeline/OneBranch/stages.yml:586 — the macOS-14 → macOS-15 bump changes the toolchain for every shipped macOS artifact, not just the install-test runner.
The MacOS_universal2 job builds the wheels (build-python-wheels-template.yml) and both ODBC dylibs (build-odbc-macos-template.yml, x64 and ARM64) before it install-tests them, so this one line moves the Xcode/SDK used to produce the released macOS binaries. The change looks correct and necessary — pip rejects a macosx_15_0_universal2 wheel on a macOS 14 runner, so the gate cannot work otherwise, and MACOSX_DEPLOYMENT_TARGET=15.0 is already pinned so the ABI target is unchanged. It is mentioned in the description, but only as a test-runner detail; it is the only line in this diff that changes what ships, and is worth calling out as such for whoever reviews the next macOS regression.
5. scripts/test-python-wheel-installs-linux.sh:49-50 — the release gate pulls :latest image tags.
docker pull is explicit so there is no stale-cache problem, but a release-blocking gate whose six test environments can change between the validated run and the actual release is worth pinning by digest (or an immutable tag). Low risk given the images are Microsoft-mirrored, but the cost of pinning is one line each.
Required CI failures
None. All 19 checks on 9139220866f05543e2bb568deb9ff33a0eeb87d4 are passing, including mssql-rs Pull request validation (ADO 176870), coverage-report, CodeQL, Analyze, check, license/cla, and both cross-repo mssql-python legs. mergeStateStatus is BLOCKED pending review approval only.
The findings above are all shift-left suggestions; none of them should block. This PR appears ready for human review, but it has not been approved — a maintainer still needs to review and approve it.
… drift - Add Build.Reason != PullRequest condition to the three install-test steps in test-python-wheel-installs-template.yml, matching the pattern used for ODBC driver injection. Currently a no-op since the only caller passing testPythonWheelInstalls: true has pr: none, but protects the path if NonOfficialPythonWheelsPublish.yml starts opting in. - Rewrite test_linux_installs_cover_release_matrix to parse the canonical matrix from .pipeline/scripts/verify-python-wheels.ps1 and cross-check it against the bash script's PYTHON_TAGS/PLATFORM_TAGS, instead of asserting literals restated from the same file under test. - Add missing trailing newlines. Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
…ys patch - Add test_windows_and_macos_install_matrix_tracks_release_python_tags, cross-checking test-python-wheel-installs-template.yml's pythonVersions default and the Windows ARM64 override (in both build-python-wheels and install-test template calls) against verify-python-wheels.ps1's canonical \. Closes the same self-referential gap the Linux fix in 9ed77aa addressed, now for Windows x64/ARM64 and macOS. Verified non-vacuous: adding a fake cp315 to the ps1 matrix fails the new test. - Remove the unused sys import in test-python-wheel-install.py and the dead monkeypatch.setattr(wheel_install.sys, ...) in its test, since expected_driver_path selects the macOS slice from the wheel platform tag plus platform.machine() and never reads sys.platform. Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
test_windows_and_macos_install_matrix_tracks_release_python_tags previously subtracted a hardcoded '3.10' to get the expected Windows ARM64 matrix, reintroducing the literal-restatement pattern it was meant to remove. Parse the Where-Object filter in Get-ExpectedWheelNames's win_arm64 loop instead, so a change to that exclusion is caught rather than silently diverging from the canonical release matrix. Verified non-vacuous: widening the ps1 filter to also exclude cp311 (while stages.yml still ships 3.11 on Windows ARM64) fails the test. Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
Extends test_python_wheel_install_gate_precedes_artifact_publication to require every 'Inject ODBC driver into' / 'Repair glibc' step precede the install-test gate, not just the publish step. Previously the test only proved the gate ran before publish, so a misordered gate that install-tests an un-injected wheel would still pass. Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
PR #624 (merged to main) changed the Python wheel build from one wheel per Python version per platform to a single cp310-abi3 stable-ABI wheel per platform (Requires-Python >=3.10), forward-compatible with every supported interpreter. This broke the wheel-selection glob in the Windows/macOS install-test template and the Linux install script, both of which computed a per-version wheel filename that no longer exists, and invalidated the \\\-based drift-detection assertions in test_python_wheel_install.py and test_release_pipeline.py. The core test-python-wheel-install.py script needed no changes: it only ever inspects a wheel's platform-tag suffix, never its Python/ABI tag, and always runs against whichever interpreter set up the venv - selection of *which wheel* and *which interpreters test it* were already decoupled. - test-python-wheel-installs-template.yml (Windows/macOS): glob the fixed cp310-abi3-<platform> wheel instead of a computed per-version tag; pythonVersions still drives which interpreters install-test it. - test-python-wheel-installs-linux.sh: select the single cp310-abi3 wheel once per (platform, arch), then loop PYTHON_TAGS purely as interpreters to test that fixed wheel with. - test_python_wheel_install.py: wheel-name fixtures updated to cp310-abi3; test_linux_installs_cover_release_matrix now checks the interpreter floor against verify-python-wheels.ps1's Requires-Python assertion instead of a nonexistent \ list. - test_release_pipeline.py: replaced \_canonical_python_versions\/ \_canonical_win_arm64_python_versions\ with a \_wheel_requires_python_floor\ helper; the Windows/macOS matrix drift test now checks the pythonVersions floor and the win_arm64 exclusion against that floor. Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
9139220 to
f21884a
Compare
Vahid Beiranvand (Vahid-b)
left a comment
There was a problem hiding this comment.
Note
Unattended automated review generated by GitHub Copilot on behalf of Vahid Beiranvand (@Vahid-b), without human confirmation. This is a COMMENT only, not an approval, and does not satisfy the human review requirement. Findings may be wrong; push back on anything that looks off.
Summary
Delta re-review at f21884a8. My last pass was at 9139220; since then the branch merged main (which landed #624, the cp310-abi3 stable-ABI switch) and added f21884a8 to adapt this gate to it. The adaptation itself is correct and well-reasoned: the wheel-selection globs in the Windows/macOS template and the Linux script now target the fixed cp310-abi3-<platform> name, and PYTHON_TAGS/pythonVersions correctly degrade from "which wheels exist" to "which interpreters install-test the one wheel". The commit message's claim that test-python-wheel-install.py needed no changes holds — expected_driver_path only ever reads the trailing platform tag, never the Python/ABI tag.
Also resolved since my last pass: the Validation section now cites Official Python Wheels Build 177092 at this exact head, which closes the staleness finding from 2026-09-18.
No blocking issues. One suggestion, one nit — both new in this delta.
Verification
- Confirmed live repository
microsoft/mssql-rs(id1018255296) and live authorTheekshnabefore reading the diff and again immediately before posting. Headf21884a89dec0329b01edc627fa21c96ec479be5, open, not a draft. - Merge base against current
origin/main(b758050e) isb758050eitself — the branch is fully current withmain. Full PR diff is 8 files, +999/-2; reviewed in a detached worktree, not the main checkout. - Read the PR body, all 27 reviews, all 7 issue comments, and all review threads across
pulls/580/reviews,pulls/580/commentsandissues/580/comments. Nothing below restates an existing thread. gh pr checks 580— no failing checks at this head;Analyze,CodeQL,check,coverage-report,license/claand the ADO validation legs (build 177091) all pass.mergeStateStatusisBLOCKEDpending review approval only. Remaining ADO legs arepending, not failed.- Ran the PR's suites:
python3 -m pytest scripts/test_python_wheel_install.py -q→ 20 passed;python3 -m pytest scripts/test_release_pipeline.py -q -k 'wheel_install_gate or install_matrix_tracks or macos_wheel_install_gate'→ 7 passed. bash -n scripts/test-python-wheel-installs-linux.sh→ clean.- Mutation behind finding 1: narrowed
PYTHON_TAGSintest-python-wheel-installs-linux.shfrom(cp310 cp311 cp312 cp313 cp314)to(cp310 cp311 cp312)— i.e. the Linux release gate silently stops install-testing Python 3.13 and 3.14. All 20test_python_wheel_install.pytests and all 7 targetedtest_release_pipeline.pytests still passed. - Control mutation (confirms the gap is Linux-specific, not general): dropped
'3.14'from the install template'spythonVersionsdefault — 5 tests failed, includingtest_windows_and_macos_install_matrix_tracks_release_python_tagsand fourtest_python_wheel_install_gate_precedes_artifact_publicationparametrizations. So Windows/macOS narrowing is caught; only the Linux list is unguarded. - All mutations reverted;
git status --porcelainin the worktree is empty and both suites re-verified green afterwards. - Not verified: ADO work item AB#48227 and Official build 177092 (no Azure DevOps access from this session), so the "9 wheels verified at this head" claim rests on your report. 62 of 158
test_release_pipeline.pytests error withPermissionError: [Errno 13] Permission denied: 'pwsh'on this host — an environment gap (no PowerShell in the Linux test environment), unrelated to this PR; none of them are in the set this PR touches. The PR-guarded runtime paths (--wheel/--verify/--verify-driver-exports, the Linux Docker flow, the macOSlipo/nmblock) still never execute in PR CI, so they remain covered only by the Official build. No Rust or ODBC-surface changes, so parity review is not applicable.
Findings
Blocking
None.
Suggestion
1. scripts/test-python-wheel-installs-linux.sh:4 — the Linux interpreter matrix lost its only cross-check in this delta, reopening the gap the review-added tests were written to close.
At 9139220, test_linux_installs_cover_release_matrix asserted set equality against the canonical list:
assert set(script_python_tags_match[1].split()) == canonical_python_tags # from $pythonTagsf21884a8 necessarily dropped that — #624 removed $pythonTags from verify-python-wheels.ps1 entirely — and replaced it with a floor-only check:
assert min(script_python_minors) == floor_minorThat constrains the bottom of the list and nothing else. Measured, not inferred: narrowing PYTHON_TAGS to (cp310 cp311 cp312) leaves all 20 tests in test_python_wheel_install.py and all 7 targeted test_release_pipeline.py tests green. The wheel still declares Requires-Python >=3.10 with no upper bound and is installable on 3.13/3.14, but the Linux half of the gate would stop exercising them, silently.
The control mutation above shows this is specific to Linux: the same narrowing on the Windows/macOS side fails 5 tests, because test_python_wheel_install_gate_precedes_artifact_publication pins the full pythonVersions list. PYTHON_TAGS has no equivalent.
To be fair to the change: this is a shift-left gap, not a shipped-defect risk — a narrowed matrix tests less, it does not pass a bad wheel. And the ceiling genuinely has no canonical source anymore; 3.14 is now restated independently in stages.yml:247,272, build-python-wheels-template.yml:20, test-python-wheel-installs-template.yml:19, validation-stages.yml:258, containers/PYTHON_WHEELS_README.md:34 and this script, with nothing tying them together.
Cheap to close in the style already in this file: since the Windows/macOS list is already pinned, tie Linux to it rather than to the ps1, so all three platforms move together:
default_versions = next(
parameter["default"]
for parameter in install_template["parameters"]
if parameter["name"] == "pythonVersions"
)
assert set(script_python_tags_match[1].split()) == {
"cp" + version.replace(".", "") for version in default_versions
}That keeps the existing floor assertion meaningful and restores detection of both narrowing and drift.
Nit
2. .pipeline/templates/test-python-wheel-installs-template.yml:64-90 — the macOS block now repeats wheel-invariant verification once per interpreter.
The whole - script: body sits inside ${{ each pythonVersion in parameters.pythonVersions }}, so with the default five interpreters the release gate performs the extract, all three lipo -verify_arch calls and both --verify-driver-exports (nm) passes five times against the identical wheel. Before #624 that was correct — each iteration selected a different per-version wheel. Now there is one cp310-abi3 wheel per platform, and only the pip install + import + SQLAllocHandle round trip actually varies by interpreter; the archive contents do not.
Hoisting the extract/lipo/nm block into a single step ahead of the loop would cut roughly 4/5 of that work off the macOS critical path with no loss of coverage. Note test_macos_wheel_install_gate_verifies_both_architectures asserts template.count("--verify-driver-exports") == 2, which counts occurrences in the template text, so it would still hold after the hoist.
Still open from my 2026-09-21 pass
Not re-filed, and none blocking — listed only so they are not lost behind the abi3 rebase: the expected_driver_path layout literals with no cross-check against Get-ExpectedOdbcMembers/inject-odbc-into-wheels.py; the five-way macosx_15_0_universal2 coupling; REQUIRED_ODBC_SYMBOLS having no stated provenance (39 of the driver's 50 exports); the macOS-14 → macOS-15 bump changing the toolchain for shipped macOS artifacts; and the :latest image tags in the Linux gate.
Both findings above are shift-left suggestions; neither should block. This PR appears ready for human review, but it has not been approved — a maintainer still needs to review and approve it.
…st macOS wheel verification out of interpreter loop - test_linux_installs_cover_release_matrix: cross-check PYTHON_TAGS against the install template's own pythonVersions default (the same source that already gates Windows/macOS), instead of only checking the Requires-Python floor. Restores detection of both narrowing and drift on the Linux side after #624 removed the old \ list this test previously checked against. - test-python-wheel-installs-template.yml (macOS): the wheel's architecture layout and driver exports are invariant across every interpreter under test post-#624 (one cp310-abi3 wheel per platform). Hoist the extract/lipo/nm verification into a single step ahead of the pythonVersions loop instead of repeating it once per interpreter; only the pip install + import + SQLAllocHandle round trip still varies by interpreter. Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
|
Thanks for the delta re-review at
Full packaging suite (286 tests) and YAML parse re-verified green at the new head. |



Description
Adds a release gate to the Official Python Wheels Build that clean-installs and exercises every final wheel after signing, ODBC injection, and Linux repair/retagging, before the platform artifact is published.
This closes a gap left by build, signing, and packaging checks: those checks can succeed while the released wheel is missing the injected driver, contains it under the wrong architecture path, depends on libraries available only in the build image, or was damaged by a final artifact transformation.
The release build produces a single stable-ABI (
cp310-abi3) wheel per platform, forward-compatible with every supported interpreter (Requires-Python >=3.10). The gate covers the full 9-wheel release matrix, each wheel installed and exercised under every supported interpreter (Python 3.10-3.14, except win_arm64 which starts at 3.11):manylinux_2_28,manylinux_2_34, andmusllinux_1_2(6 wheels)For each platform, the test:
cp310-abi3wheel for that platform.python -m pip install --no-index --no-deps.mssql_py_core.mssqlodbclibrary.SQLAllocHandle(SQL_HANDLE_ENV)andSQLFreeHandle.Linux installation tests use the stock PyPA manylinux/musllinux images mirrored at
ghcr.io/microsoft/mssql-rs/import/python-build/.... This avoids both the custom Rust build images, which can mask undeclared runtime dependencies, and a direct dependency onquay.ioegress from the official pipeline.The macOS job uses macOS 15 to match the
macosx_15_0_universal2deployment tag. The hosted Intel runner validates installation and the x64 native slice; native ARM64 execution still requires an Apple Silicon agent.This is an installation, native-load, and basic ODBC ABI smoke gate. It intentionally does not require SQL Server credentials or duplicate the separate database-connected test suite.
Related Issues
AB#48227
Validation
f21884a89dec0329b01edc627fa21c96ec479be5(current head). All 9 final wheels (one per platform,cp310-abi3) completed clean installation, package import, native driver load,SQLAllocHandle, andSQLFreeHandleverification under every supported interpreter; all platform artifacts were published only after their installer gates succeeded; Linux logs confirmed all stock test images were pulled through the Microsoft GHCR mirror.python -m pytest scripts/test_inject_odbc.py scripts/test_verify_python_wheels.py scripts/test_release_pipeline.py scripts/test_validation_pipeline.py scripts/test_repair_glibc_wheels.py scripts/test_bump_released_crate_versions.py scripts/test_python_wheel_install.py -q— 286 passed.bash -n scripts/test-python-wheel-installs-linux.shgit diff --checkcargo bfmtChecklist
cargo bfmtpassescargo bclippynot run (no Rust changes)cargo btestnot run (focused Python packaging and official wheel validation used instead)