Repository navigation
vm-repair: remove unused opencensus dependency, and declare applicationinsights - #10249
Conversation
…sights opencensus was declared in setup.py but never imported anywhere in the extension. Because extensions install with `pip --target`, that dead declaration vendored ~20 packages into the extension folder, including cryptography, which stopped publishing 32-bit Windows wheels in 49.0.0. On a 32-bit CLI pip found no compatible wheel, fell back to the sdist, and failed with `Pip failed with status code 2` (ICM 854928087). applicationinsights is imported by telemetry.py on the hot path of every command but was never declared; it resolved only because the Azure CLI happens to ship it, and no Azure CLI package requires it. requests stays undeclared on purpose: azure-cli-core guarantees it via msal/msrest, and vendoring it could shadow the CLI's own copy on sys.path. Adds a static regression test asserting both directions of the invariant: no undeclared third-party import, and no declared-but-unused dependency.
|
Hi Edwin Bernal Microsoft (@EdwinBernal1), |
|
Azure Pipelines: There may be pipelines that require an authorized user to comment /azp run to run. |
There was a problem hiding this comment.
Pull request overview
Updates vm-repair dependency metadata to prevent 32-bit Windows installation failures and ensure telemetry dependencies are declared.
Changes:
- Replaces unused
opencensuswithapplicationinsights. - Bumps version to 2.2.6 and adds release notes.
- Adds dependency declaration regression tests.
Reviewed changes
Copilot reviewed 3 out of 3 changed files in this pull request and generated 1 comment.
| File | Summary |
|---|---|
src/vm-repair/setup.py |
Updates dependencies and version. |
src/vm-repair/HISTORY.rst |
Documents the 2.2.6 fix. |
src/vm-repair/azext_vm_repair/tests/latest/test_dependency_declarations.py |
Adds import/dependency checks; currently uses sys.stdlib_module_names, which is unavailable on supported Python 3.9. |
💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.
|
/azp run |
|
Azure Pipelines: Successfully started running 2 pipeline(s). |
sys.stdlib_module_names was added in 3.10, but setup.py still advertises Python 3.9. On a 3.9 run _third_party_imports() raised AttributeError before reaching either assertion, so the regression test failed rather than testing. Falls back to deriving the stdlib set from sys.builtin_module_names plus the stdlib, lib-dynload and DLLs directories when the attribute is absent, so the test keeps its coverage on 3.9 instead of being skipped there. Verified by forcing the fallback path on 3.13: both branches classify the extension's imports identically (only applicationinsights is third-party), and no stdlib module the extension imports is missed by the fallback.
|
/azp run |
|
Azure Pipelines: Successfully started running 2 pipeline(s). |
|
[Release] Update index.json for extension [ vm-repair-2.2.6 ] : https://dev.azure.com/msazure/One/_build/results?buildId=178212921&view=results |
🤖 PR Validation — ️✔️ All clear
Related command
az vm repair(all commands) — extension install/upgrade path.Fixes the install failure reported in ICM 854928087:
az extension add --name vm-repairfails withPip failed with status code 2on 32-bit Windows installations of the Azure CLI.Summary
src/vm-repair/setup.pyhad its dependency declarations inverted:opencensuswas declared but never imported. It appears in no import statement anywhere inazext_vm_repair. Because extensions are installed withpip install --target <extension dir>— fully isolated from the CLI's own site-packages — that dead declaration vendored roughly 20 packages into the extension folder:plus
protobuf,cffi,proto-plus,googleapis-common-protos,requests,urllib3,certifi,idna,charset-normalizer,pyasn1,pyasn1-modules,pycparser,six,opencensus-context.cryptographystopped publishing 32-bit Windows wheels at version 49.0.0 (48.0.1 was the last withwin32wheels):On 32-bit Windows pip finds no compatible wheel, falls back to the sdist, and the source build requires a Rust toolchain — producing the reported
Pip failed with status code 2.applicationinsightswas imported but never declared.azext_vm_repair/telemetry.pydoesfrom applicationinsights import TelemetryClient, andcommand_helper_class.pyimports telemetry at module scope, so it is on the hot path of every command. It resolved only because the Azure CLI happens to shipapplicationinsights0.11.9 —pip show applicationinsightsreportsRequired-by:as empty, meaning no Azure CLI package requires it. A future CLI that dropped it would break everyaz vm repaircommand at import time.Changes
src/vm-repair/setup.py— dropopencensus, declareapplicationinsights, bumpVERSION2.2.5 → 2.2.6.src/vm-repair/HISTORY.rst— 2.2.6 changelog entry in user-facing language.src/vm-repair/azext_vm_repair/tests/latest/test_dependency_declarations.py— new static AST regression test.applicationinsights0.11.10 is a zero-dependencypy2.py3-none-anywheel, so this removes ~20 vendored packages and adds one small universal one.requestsis deliberately left undeclared. It is imported by shipped code, but it is guaranteed by the CLI dependency graph (Required-by: msal, msrest, PyGithub, requests-oauthlib). Vendoring it into the extension folder would risk shadowing the CLI's ownrequestsonsys.path. The reasoning is recorded in a code comment so it is not "corrected" later.Regression test
The new test asserts both directions of the invariant, so this class of defect cannot silently return:
applicationinsightsopencensusVerified it actually bites: forcing the declared set back to
{'opencensus'}fails both assertions (['applicationinsights'] != []and['opencensus'] != []).Testing
All gates run locally in a proper
azdevenvironment (azdev 0.2.13, Python 3.13.15 x64):azdev style vm-repair→ PASSED (pylint PASSED, flake8 PASSED)azdev linter vm-repair→ PASSED (no violations; custom pylint rules also clean)azdev test vm-repair→ 96 passed, 35 skipped in 12.55s (skips are the live-Azure scenarios)python scripts/ci/test_index.py -q→ 9 tests, OK (2 skipped)win32Python 3.14.7 → old dependency fails, new dependency succeeds (details below)The two new regression tests are collected and pass as part of the azdev run:
32-bit reproduction (confirmed)
Reproduced on a real 32-bit Python 3.14.7 (
sysconfig.get_platform() == 'win32',struct.calcsize('P')*8 == 32), using the same install shape the CLI uses —pip install --target, no wheel-only restriction:Before (old dependency) — fails:
pip selects a
cryptographyrelease with nowin32wheel, falls back to the sdist, and attempts a Rust/OpenSSL source build fori686-pc-windows-msvc.After (new dependency) — succeeds:
Vendored contents afterwards are just
applicationinsights/and its.dist-info— nocryptography,cffi,google-*,protobuf, oropencensus. Zero native code.Note
Two honest caveats on this repro. It used a standalone 32-bit CPython rather than a 32-bit Azure CLI, because no 32-bit CLI was installable here; the failing component is pip's resolver, which is what was exercised. And pip returned exit code
1here versus the2in the incident report — the failure mode is identical (cryptographysource build), and the numeric code varies by pip version.Also worth recording: resolving the same tree with
pip download --only-binary=:all: --platform win32succeeds, because that flag forces pip to backtrack tocryptography 48.0.1(the last release withwin32wheels). That flag is not used byaz extension add, so it masks the bug — a wheel-only check is not a valid test for this issue.Positive control also captured: an isolated 64-bit install of 2.2.5 (fresh
AZURE_CONFIG_DIR) succeeded and its debug log shows the fullopencensustree — includingcryptography— being vendored.Version & changelog
setup.pyVERSION:2.2.5→2.2.6HISTORY.rstentry added: yesCross-repo impact (repair-script-library)
None. No
--run-id,map.json, or script changes.Security review
Reduces supply-chain surface by removing ~20 unnecessary vendored packages. No untrusted-input → shell paths touched; no credential handling or logging changed.
Backward compatibility
No command, parameter, default, or behavior changes. Patch-level and backward compatible.
Note on the original triage
The ICM was initially attributed to
pkgutil.get_loader()under Python 3.14, with a recommendation to publish 2.2.5.vm-repair2.2.5 was in fact already published on 2026-08-20 (before the ICM was filed), andpkgutilis runtime code that cannot cause pip to exit 2 during install. The reporter's own 64-bit run installed 2.2.5 from the same index at the same time the 32-bit run failed — the differentiator was architecture, not the index. This change addresses the actual install-time cause.General Guidelines
azdev style <YOUR_EXT>locally? — passed, as didazdev linter vm-repairandazdev test vm-repairpython scripts/ci/test_index.py -qlocally? — passesAbout Extension Publish
src/index.jsonis intentionally not modified in this PR.