Skip to content

Validate packaged compatibility and fix extension shutdown lifecycle - #1994

Draft
Stella Huang (StellaHuang95) wants to merge 4 commits into
microsoft:mainfrom
StellaHuang95:stellahuang95-environments-release-readiness
Draft

Stella Huang (StellaHuang95) wants to merge 4 commits into
microsoft:mainfrom
StellaHuang95:stellahuang95-environments-release-readiness

Conversation

@StellaHuang95

@StellaHuang95 Stella Huang (StellaHuang95) commented Nov 6, 2026 •

Copy link
Copy Markdown
Contributor

Summary

Add bounded packaged compatibility reporting and genuine clean-Windows installed/upgrade acceptance, plus the tightly coupled shutdown defect found during verification. Keep this PR draft; DevDiv final signed-artifact/signature acceptance remains separate.

Verified unsigned head: 003c3b85908e705794f9e73e6a9b6b61ff97845c. Final CI run 42289867126 is successful: all 57 effective jobs passed, including the actual installed candidate/on-off/upgrade job. One unchanged Conda fixture-provisioning timeout required a controlled same-head failed-job-only fresh-host rerun; the original failure and exact disposition are preserved below, not claimed first-attempt green.

What changes and why

  • DevDiv report-only: runPackagedCompatibility stays default false. Consume the original Build VSIX and immutable inputs, reject unexpected PET bundling or wrong identity/version/platform/hash, retain explicit failures/infrastructure evidence. Stable keeps Build -> optional report -> existing manual approval -> Publish; prerelease keeps Build -> optional report -> Publish. Signing/publication defaults and release triggers are unchanged.
  • Read-only draft CI: an explicit data fixture selects this draft. Preparation checks out the exact PR head and reviewed immutable harness in sibling directories, normally packages a no-PET Windows x64 VSIX, and freezes candidate/driver/input/harness hashes and source provenance. A separate clean Windows job consumes the immutable producer artifact ID—even on failed-job-only retries—and runs the real adapter. Runtime restores no dependencies and uses no source checkout; products are installed from the frozen VSIXes, never loaded as development extensions. Both jobs have read-only permissions and no signing/publication credentials.
  • Pinned delivery: decode HTTP identity/gzip transport before checking the unchanged original Marketplace VSIX hash; reject unsupported, truncated/corrupt encoding and bound decoded size. No repacking or PET injection. All source/partner/tooling references are exact; a verification fixture is not a floating or production/runtime fork dependency.
  • Product lifecycle: VS Code calls deactivate() without an argument; the old callback unconditionally read context.subscriptions and threw. Capture activation subscriptions, share one in-flight shutdown promise across concurrent callers, await cleanup and surface failures while the logger remains alive, then dispose logging last. Detach only the owned batch so late registrations remain with the context owner. Explicit opt-out still skips activation; public environment API/routing, setting defaults, PET packaging and dependency/minimum-version contracts are unchanged.

Actual candidate/on-off/upgrade: passed

The installed compatibility job passed on a clean Windows x64 runner. Its four phase reports, eight raw Python result JSONs, modes, disk-persistence controls, saved-selection reads and PET/backend evidence were downloaded and independently verified by both sessions.

Requested mode Released Environments 1.42.0 before upgrade No-PET candidate 1.43.0 after upgrade
Explicit true Both real venvs discovered, selected/switched and run via normal core command; own-Environments PET observed Disk global/workspace nonce and saved second-venv selection verified before reselection, both venvs selected/switched/executed; actual PET supplier changes to Core
Explicit false Both venvs discovered, selected/switched and run; positive legacy-JavaScript backend evidence, no invented native PET Same disk continuity and pre-write saved-selection check pass; explicit/effective false survives; both venvs executed through the legacy route, no runtime PET

Every actual process matched its selected fixture's exact sys.executable, sys.prefix and fresh nonce. Enabled normal-core execution delegated to Environments exactly once per run; off used the legacy route. All eight raw JSON records were checked—not merely discovery counts, a selected string, terminal creation or a nonempty result.

Upgrade hosts are ordinary isolated Code windows with graceful quit, without --extensionTestsPath. The controller's global and workspace Memento tokens survive restart and are read-only verified before product activation/selection. The product's saved second-venv association is then checked before any selection write. Neither association nor explicit-off preference was reseeded to conceal a failure.

Frozen inputs from this successful run

  • Exact source: StellaHuang95/vscode-python-environments head 003c3b85908e705794f9e73e6a9b6b61ff97845c, verified unsigned on GitHub.
  • Normally packaged Windows x64 candidate 1.43.0: SHA-256 0f95f6cab8bd86b088ef203d517ab7ad1e0c1c9a0796de6b72b851437c1d3741; no PET and no compatibility tooling in the VSIX. Preparation and execution used the same bytes, independently rehashed after download.
  • Reviewed persistent-host harness source: StellaHuang95/vscode-python commit 36931aba4f11db19e29f7bdefaeec9acdaff1832; root-lock SHA-256 110cc8382eecd1c79f796cc8833c851b11ea377f0c2c47835ec73735465d4006; actual CI-produced self-contained ZIP 59eedbe23c8150126c17d192021a20e721126510edbde2a84cd5e8b7557e6535.
  • Input ZIP fc62c44ed88f6ae063b6f4ad455b9025c13441e55fb508e00868bec895650f71; driver 216d4c993abdbcda45bfbcba016ea41749ca241b62d87ad342a04a5eb48ae0cc.
  • Released Core Windows x64 2026.10.0: original VSIX ab1c1bf0f5ab273118ca3218e62934a4030203cce2e4b24bb86f0f416de05768.
  • Released Environments Windows x64 1.42.0: original VSIX ce79778a60dfd83892cbd572f5e23f2919e66e6cdaf6880ba2970604a4d7fa98.
  • Actual Code stable 1.110.0, fixture Python 3.12.10, CI tooling Node 22.21.1. Native PET before/after enabled upgrade was observed at the respective installed supplier path with SHA-256 60f09e780cdb97f9fd4e353bf2f9be533463d7183bcb9d978a4f1d459b941120; pet --version reported 0.1.0. Optional build metadata is not fabricated.

The released baseline was not patched or certified error-free: its known missing-context shutdown error and old channel-close errors remain in raw evidence. Candidate after-upgrade hosts no longer emitted that TypeError. Raw PET registry/optional-manager warnings, capability telemetry timeouts and the existing worker-queue shutdown diagnostic are retained, not erased to manufacture clean logs. The explicit-off candidate phase recorded no errors.

Checks, review and failure disposition

  • Local lint and TypeScript checks passed. Full unit suite: 3,532 passing, 9 pre-existing pending, including 10 lifecycle controls for no-argument/pre-activation/repeated/concurrent callbacks, pending cleanup/rejection, real logger lifetime and late-registration ownership.
  • 25 Python adapter/preparation controls passed, including original staged bytes, immutable refs/locks, tracked-clean source provenance, complete harness manifest/tree, artifact failure handling and exact HTTP decoded-size boundaries. Inert Node fixtures are not product acceptance.
  • Both real Marketplace downloads were checked through the corrected transport helper against the original good hashes (Core 9,418,136 bytes; baseline 4,418,069 bytes), with matching identity/version/target. Hashes were not changed to gzip-wire hashes.
  • Independent and parent reviews found/corrected retry artifact naming/extraction, logger lifetime, concurrent shutdown awaiting/rejection and late-registration ownership. Narrow re-reviews found no unresolved issue in those corrections or transport decoding. Required regressions were rerun.
  • Final source CI is successful with 57/57 effective job conclusions. Attempt 1 was 56/57: Windows 3.10 Conda Package Manager's unchanged before-all external fixture conda create ... python=3.12 exceeded 180 seconds and left an incomplete non-Conda directory. Traced the direct external-command provider (_api unused), unchanged fixture/process code and successful pre-lifecycle Windows 3.10 baseline. No changed disposal callback executes before this setup. One exact same-head failed-job-only fresh-host verification passed (job 128151290749, run attempt 2); original failed job 128144844296 and raw logs remain retained. No Conda/deletion code, timeout, Mocha retry or assertion was changed, and the already accepted candidate was not rebuilt.

Earlier failed attempts retained, not relabeled

The local R1 attempt was blocked by the developer machine's existing updater mutex; no updater/process/profile, OS setting, product file or elevation credential was modified or bypassed. Its infrastructure/not-run evidence remains retained separately.

Previous clean run 42285124088 genuinely failed both post-upgrade selection assertions while both baseline modes ran correctly. Exact shipped Code 1.110 source proved that --extensionTestsPath forces in-memory Mementos even with identical profile/workspace IDs. The fix was the shared normal persistent-host/controller control described above—not a product association patch, cached-selection copy, assertion relaxation or baseline mutation. The old failed run remains failed. Its separate Windows 3.15 removal timeout was also retained; that unchanged removal test passed on the final head.

Acceptance limits

This is genuine unsigned CI-built Windows x64 candidate/released-core/on-off/upgrade coverage, not final signed DevDiv publication acceptance, an all-version/all-manager matrix or certification of the old baseline's shutdown health.

Current shared DevDiv templates sign later in Publish, export detached-signature artifact extension and have no isolated post-Sign/pre-Publish compatibility hook. Reports retain finalSignedArtifactValidated: false. Final acceptance still needs the approved non-privileged shared hook, exact signed-byte reconciliation, detached-signature verification and actual host/upgrade scenarios; never rebuild/restamp to conceal differences. The DevDiv preview was denied for missing EditBuild; no alternate identity/endpoint retry or hosted-success claim was made. Clean GitHub CI is not a substitute for that template/signing/permission acceptance.

Do not merge or publish extensions as part of this work. Keep both coordinated PRs draft.

Validate original DevDiv Build VSIX identity and pinned compatibility inputs in a nonprivileged report-only job. Preserve production defaults, manual approval and publication behavior, and document the unverified shared harness and final-signed-artifact acceptance boundary.

Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
@StellaHuang95 Stella Huang (StellaHuang95) added the debt Code quality issues label Nov 6, 2026
Add explicitly scoped read-only draft preparation and clean Windows installed-VSIX acceptance using a reviewed immutable harness, exact partner pins, artifact IDs and recorded provenance. Fix the reproduced zero-argument shutdown callback with shared asynchronous cleanup, logger lifetime and late-subscription ownership controls; keep activation defaults, API routing and production release behavior unchanged.

Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
Handle Marketplace HTTP gzip transport explicitly, reject unsupported or damaged encodings, and bound decoded bytes before checking the unchanged canonical VSIX hashes. Cover identity, gzip, CRC/truncation and exact decoded-size boundaries; real fixed-version downloads match their original reviewed package identities.

Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
@StellaHuang95 Stella Huang (StellaHuang95) changed the title Add opt-in pre-sign packaged compatibility reporting for Environments Validate packaged compatibility and fix extension shutdown lifecycle Nov 6, 2026
Pin the reviewed shared runtime that avoids VS Code test-mode in-memory storage for upgrades, closes normal isolated windows gracefully, and checks an independent controller-owned disk-Memento nonce before the strict product association assertion. Preserve the prior failed evidence, original baseline and candidate behavior; document cleanup semantics without changing routing or defaults.

Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
Stella Huang (StellaHuang95) added a commit to microsoft/vscode-python that referenced this pull request Nov 13, 2026
## Summary

Add Windows x64 and Linux x64 compatibility checks for the **actual
packaged Python extension**, paired with a fixed released Python
Environments extension. The goal is to catch packaging and
cross-extension integration issues before release by verifying
discovery, interpreter switching, and real Python execution with
Environments explicitly enabled and disabled.

Existing source, native, and packaged smoke tests remain in place. This
closes a specific coverage gap: the current Run Python File packaged
smoke test explicitly disables Environments, and its execution case
skips Windows. It does not imply that all integration coverage was
missing or that the released packages are incompatible.

## Before and after

| Area | Existing behavior | Added coverage |
|---|---|---|
| Packaged execution | The Run Python File smoke case exercises the
legacy route and skips execution on Windows. | Separate Windows/Linux
checks discover two real venvs, select and switch between them, and
execute through Core's normal command in both modes. |
| Candidate identity | CI builds platform-specific VSIX artifacts. | The
new jobs consume the original artifact from that same run and retain its
version, hash, and producer/source identity; they do not rebuild or
substitute a released Core. |
| Runtime evidence | Package contents or terminal creation alone cannot
prove which interpreter or discovery backend ran. | Check the actual
Python executable, environment prefix, and fresh execution token, plus
the observed PET supplier or supported legacy discovery backend. |

## Current flows with this change

| Flow | What runs |
|---|---|
| GitHub PR/CI | Existing `build-vsix` jobs -> new Windows/Linux
candidate compatibility jobs -> retained reports and raw logs. Each
candidate is paired with the pinned released Environments package.
Existing build and test jobs are unchanged. |
| Harness maintenance | When relevant tooling changes, a separate
workflow runs guard tests, packages the reusable harness, and exercises
a pinned released Core/Environments pair on Windows/Linux. This is a
control for the harness, not a substitute for candidate testing. |
| Azure release reporting | A new, separately queued report pipeline
consumes an exact existing Build artifact and pinned partner inputs from
the same Azure project. It is opt-in and pre-sign, with no signing or
publishing steps. It is not inserted into the existing production
release graph. |

The fixed controls currently use Environments 1.42.0 and VS Code
1.110.0; the harness-control pair also uses Core 2026.10.0. Missing or
mismatched candidate inputs fail explicitly rather than falling back to
that released pair.

## What the checks verify

- Core and Environments load from the inspected VSIX contents, not
product source checkouts. Only the small independent controller is a
development extension.
- Each mode has its own process, workspace, profile, and extension
directory. Explicit settings are written before activation and checked
afterward, including the supported `false` opt-out.
- Both fixture venvs must be discovered before selection. Core's normal
`python.execInTerminal` command must produce fresh output matching the
selected `sys.executable` and `sys.prefix`; opening a terminal is not a
pass.
- Enabled execution must delegate through the real Environments API.
When PET runs, its actual startup path and hash must match the expected
installed supplier. Disabled mode may legitimately use legacy JavaScript
discovery, which requires positive backend evidence rather than an
invented PET identity.
- Reports distinguish assertion failures, infrastructure failures, and
cases that did not run. Original package hashes are rechecked; isolated
profiles, credential filtering, bounded archive extraction, and
owned-process cleanup keep the test independent of a developer
installation.

The reusable harness also supports the bundled-PET to Core-PET fallback
upgrade used by [the companion Environments PR
#1994](microsoft/vscode-python-environments#1994).
Upgrade phases use normal isolated windows with disk-backed storage,
verify independent storage continuity, and read the saved interpreter
selection **before any reselection**. Product state is not copied or
reseeded. This upgrade is not an additional default Core candidate job.

## Scope and release impact

There are **no production runtime, integration-default, opt-out,
dependency, PET-bundling, or existing build/sign/publish changes** in
this PR. The harness is excluded from the shipped VSIX. No
branch-protection or publication gate is enabled.

GitHub candidate checks can fail CI; the separate Azure consumer is
deliberately report-only. CI-built package results are not final
signed-publication certification. Actual Azure artifact
permissions/hosted acceptance, a post-Sign hook, and reconciliation with
the exact signed/published bytes remain rollout work.

Coverage is bounded to the pinned pairs and local venv workflow. The
current bundled-Environments pair can use Environments' PET when enabled
and JavaScript discovery when disabled, so it does not guarantee
execution of the candidate Core's own PET in every run.

Runner inputs, reports, and release handoff details are documented in
[`build/releaseCompatibility/README.md`](https://github.com/StellaHuang95/vscode-python/blob/stellahuang95-core-release-readiness/build/releaseCompatibility/README.md).

---------

Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

debt Code quality issues

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant