Skip to content

feat: support Windows TME VHD builds - #9235

Merged
janenotjung-hue merged 3 commits into
mainfrom
janejung/windows-tme-vhd-build
Aug 20, 2026
Merged

feat: support Windows TME VHD builds#9235
janenotjung-hue merged 3 commits into
mainfrom
janejung/windows-tme-vhd-build

Conversation

@janenotjung-hue

@janenotjung-hue janenotjung-hue commented Aug 18, 2026

Copy link
Copy Markdown
Contributor

What this changes

  • reuses the existing .pipelines/.vsts-vhd-builder-release-windows.yaml for TME rather than adding a separate Windows TME YAML
  • allows TME release-candidate builds from main to generate publishing info without deleting the builder SIG image
  • converts Windows SIG images through the existing TME vhdstaging container and verifies asynchronous page-blob copy into immutable storage
  • preserves existing AME production and MSFT test behavior
  • adds ShellSpec coverage for release, normal test, and TME release-candidate build modes

Reuse model

The TME ADO definition will link the existing AKS Node SIG 1ES Pools and Daily VHD Build Variables groups and point at the same Windows YAML used by definitions 188674 and 210712. AgentBaker E2E remains outside the VHD build and will use the existing TME E2E pipeline, matching the Linux daily flow.

A separate TME ADO definition is still required because its service connection, subscription, permissions, schedule, and audit boundary are statically tenant-specific. No separate build implementation or tenant variable group is required.

Validation

  • make validate-shell
  • targeted ShellSpec: 6 examples, 0 failures
  • YAML parsing for all modified pipeline files
  • ADO preview compilation from this branch against the existing Windows definition
  • git diff --check

Remaining integration gate

Create the TME definition against the shared YAML and run one SKU first to validate Windows policy/WinRM access through the TME service connection before enabling the full matrix.

Work item: https://msazure.visualstudio.com/CloudNativeCompute/_workitems/edit/39310306

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

Copilot-Session: 94930400-cff0-4e18-9ddd-6a285b891087
@github-actions

github-actions Bot commented Aug 18, 2026

Copy link
Copy Markdown
Contributor

Windows Unit Test Results

  3 files   12 suites   48s ⏱️
389 tests 389 ✅ 0 💤 0 ❌
392 runs  392 ✅ 0 💤 0 ❌

Results for commit 9b3e95b.

♻️ This comment has been updated with latest results.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

Copilot-Session: 94930400-cff0-4e18-9ddd-6a285b891087

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Pull request overview

This PR extends the Windows VHD build/release pipeline to support TME “release-candidate” builds by reusing the existing Windows release YAML, enabling publishing-info generation from main without triggering production SIG deletion behavior, and adding a TME-specific staging → immutable copy flow for Windows VHD blobs. It also adds ShellSpec coverage for the new build-mode logic.

Changes:

  • Add a configure_windows_build_mode helper to allow TME release-candidate builds (non-release branch) to run with DRY_RUN=False when publishing info is enabled.
  • Update the Windows builder release template to pass ENVIRONMENT/GENERATE_PUBLISHING_INFO, allow publishing-info generation outside production releases, and add a staging-container + async copy verification step for TME.
  • Add ShellSpec coverage for normal, release, and TME release-candidate modes; minor YAML cleanup in Windows templates.

Reviewed changes

Copilot reviewed 6 out of 6 changed files in this pull request and generated 1 comment.

Show a summary per file
File Description
spec/vhdbuilder/packer/windows_build_vhd_spec.sh Adds ShellSpec tests for the new Windows build-mode logic (incl. TME RC mode).
.pipelines/templates/.builder-release-template-windows.yaml Enables TME publishing-info path and adds staging → immutable blob copy/verification for Windows.
.pipelines/templates/.build-and-test-windows-vhds-template.yaml Removes a stray YAML line artifact.
.pipelines/templates/.build-and-test-windows-vhd-template.yaml Removes stray YAML line artifacts.
.pipelines/scripts/windows_build_vhd.sh Refactors branch/build-mode gating into configure_windows_build_mode with TME RC support.
.pipelines/.vsts-vhd-builder-release-windows.yaml Notes that TME will reuse the same Windows build YAML.
Suppressed comments (3)

.pipelines/templates/.builder-release-template-windows.yaml:313

  • az storage blob exists --query exists --output tsv commonly outputs True/False (capitalized). As written, the lowercase comparison (!= "true") can be wrong and may cause az storage blob copy start to run even when the destination blob already exists (potentially failing or overwriting unexpectedly). Normalize the output before comparing.
          --auth-mode login \
          --query exists \
          --output tsv)

        if [ "${destination_exists}" != "true" ]; then

.pipelines/templates/.builder-release-template-windows.yaml:360

  • This uses az storage blob exists --query exists --output tsv but compares the result to lowercase "true". If Azure CLI returns True/False, the staging-blob cleanup path will be skipped and the subsequent existence check can also be bypassed, leaving the staging VHD behind. Normalize the exists output before the comparison.
          --auth-mode login \
          --query exists \
          --output tsv)
        if [ "${source_exists}" = "true" ]; then
          az storage blob delete \

.pipelines/templates/.builder-release-template-windows.yaml:376

  • Same exists-check issue here: if az storage blob exists --output tsv returns True/False, the lowercase comparison can incorrectly skip the post-delete validation, so the pipeline may not fail even when the staging VHD still exists. Normalize the output before comparing.
          --auth-mode login \
          --query exists \
          --output tsv)
        if [ "${source_exists}" = "true" ]; then
          echo "##vso[task.logissue type=error]Staging VHD ${VHD_STAGING_CONTAINER_NAME}/${vhd_name} still exists after cleanup"

💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.

Comment thread .pipelines/templates/.builder-release-template-windows.yaml Outdated
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

Copilot-Session: a6f6b936-a7ac-4315-8a30-8e8074517c8d
Copilot AI review requested due to automatic review settings August 18, 2026 23:32

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Pull request overview

Copilot reviewed 6 out of 6 changed files in this pull request and generated 1 comment.

Suppressed comments (5)

.pipelines/scripts/windows_build_vhd.sh:70

  • This uses Bash-only case-conversion (${var,,}), but ShellCheck’s POSIX pass ("--shell=sh") will flag this in scripts not listed in BASH_ONLY_LIST. Use a POSIX-compatible lowercase normalization (e.g., via tr) for the comparison.
  if [ "${environment,,}" = "tme" ] && [ "${generate_publishing_info,,}" = "true" ]; then

.pipelines/templates/.builder-release-template-windows.yaml:447

  • Same issue as above: this condition only matches GENERATE_PUBLISHING_INFO when it is exactly True, but other parts of the change treat the value case-insensitively (and a variable group may provide true).
    condition: and(succeeded(), ne(variables.skipping_vhd_build, 'true'), eq(variables.DRY_RUN, 'False'), or(eq(variables.SIG_FOR_PRODUCTION, 'True'), eq(variables.GENERATE_PUBLISHING_INFO, 'True')))

.pipelines/templates/.builder-release-template-windows.yaml:468

  • Same issue as above: this condition only matches GENERATE_PUBLISHING_INFO when it is exactly True, but other parts of the change treat the value case-insensitively (and a variable group may provide true).
    condition: and(succeeded(), ne(variables.skipping_vhd_build, 'true'), eq(variables.DRY_RUN, 'False'), or(eq(variables.SIG_FOR_PRODUCTION, 'True'), eq(variables.GENERATE_PUBLISHING_INFO, 'True')))

.pipelines/templates/.builder-release-template-windows.yaml:380

  • This condition is case-sensitive for both ENVIRONMENT and GENERATE_PUBLISHING_INFO, but the inline bash logic intentionally treats them case-insensitively. If ENVIRONMENT is set to TME or GENERATE_PUBLISHING_INFO is true, this copy/cleanup step won’t run, leaving the VHD in the staging container.
    condition: and(succeeded(), ne(variables.skipping_vhd_build, 'true'), eq(variables.DRY_RUN, 'False'), eq(variables.ENVIRONMENT, 'tme'), eq(variables.GENERATE_PUBLISHING_INFO, 'True'))

.pipelines/templates/.builder-release-template-windows.yaml:277

  • configure_windows_build_mode and the new ShellSpec coverage treat GENERATE_PUBLISHING_INFO case-insensitively (e.g., true), but this condition only matches the capitalized value True. If the variable group uses lowercase (common for booleans), this conversion step will be skipped unexpectedly.

This issue also appears in the following locations of the same file:

  • line 447
  • line 468
    condition: and(succeeded(), ne(variables.skipping_vhd_build, 'true'), eq(variables.DRY_RUN, 'False'), or(eq(variables.SIG_FOR_PRODUCTION, 'True'), eq(variables.GENERATE_PUBLISHING_INFO, 'True')))

Comment thread .pipelines/scripts/windows_build_vhd.sh
@timmy-wright

Copy link
Copy Markdown
Contributor

How do the Linux TME builds work? I'm keen to know that to make sure we're aligning with them.

@janenotjung-hue

janenotjung-hue commented Aug 19, 2026

Copy link
Copy Markdown
Contributor Author

Tim Wright (@timmy-wright) Here is the Linux TME flow step by step, with the Windows equivalent and whether it already existed, was changed by this PR, or is covered by a follow-up under parent story 38893317 — Windows daily builds in TME pipeline with Linux daily builds.

Linux TME step Windows equivalent Windows status
Reuses .vsts-vhd-builder-release.yaml. Reuses .vsts-vhd-builder-release-windows.yaml. Exists already
Uses a separate TME ADO definition for identity, subscription, storage, permissions, and schedule. Create a Windows TME ADO definition pointing at the shared Windows YAML. Needs follow-up — 39310306
Sets ENVIRONMENT=tme, DRY_RUN=False, and GENERATE_PUBLISHING_INFO=True. Configure the same variables on the Windows TME definition. Needs follow-up — 39310306
Passes the TME settings into the shared Linux build. Passes ENVIRONMENT and GENERATE_PUBLISHING_INFO into windows_build_vhd.sh. Added in this PR
Allows a non-dry TME build from main. Stops Windows from forcing this specific TME build back to dry-run mode. Added in this PR
Builds a SIG image using the shared Linux builder. Builds a SIG image using the shared Windows builder. Exists already
Tests and scans the built Linux image. Runs the Windows VHD cache test. Exists already
Keeps the SIG available for testing. Sets SIG_FOR_PRODUCTION=False so cleanup keeps the Windows SIG. Added in this PR
Optionally runs Linux prefetch optimization. No Windows equivalent is required. Linux only
Uses CLASSIC_BLOB_STAGING before writing to immutable storage. Sends the converted Windows VHD to the same staging container. Added in this PR
Creates the staging container if needed. Performs the same container check and creation. Added in this PR
Converts SIG → managed disk → VHD using convert-sig-to-classic-storage-account-blob. Uses the same conversion script. Exists already
Runs conversion when publishing information is requested. Allows conversion for TME through GENERATE_PUBLISHING_INFO=True. Changed in this PR
Copies the staging VHD into the immutable container. Performs the same server-side blob copy. Added in this PR
The newer Linux prefetch path checks for an existing destination. Checks whether the destination Windows VHD already exists. Added in this PR
The newer Linux prefetch path waits for copy completion. Waits for success and fails on copy failure, abort, or timeout. Added in this PR
Deletes the staging VHD after promotion. Deletes it after copy success and verifies it is gone. Added in this PR
Cleans temporary build resources while retaining the current SIG. Uses the existing Windows cleanup script, with SIG_FOR_PRODUCTION=False to retain the SIG. Cleanup exists already; TME behavior added in this PR
Generates vhd-publishing-info.json using the final VHD URL. Uses the same publishing-info generator. Exists already
Generates publishing information for TME builds. Extends the existing production-only task to run when GENERATE_PUBLISHING_INFO=True. Changed in this PR
Publishes the publishing-info artifact. Extends the existing artifact task to include TME builds. Changed in this PR
Uses AgentBaker E2E in the daily TME flow. Run the retained Windows SIG through the existing AgentBaker E2E pipeline. Pipeline exists; Windows handoff tracked by 39310308
Publishes tested images to the MSFT E2E galleries and runs aks-rp E2E. Add Windows build-ID handling, gallery publishing, an ephemeral aks-rp branch, and Windows RP E2E. Needs follow-up — 39310307
Coordinates the scheduled Linux daily build, testing, reporting, and cleanup. Add the full scheduled Windows daily orchestrator using the shared Linux orchestration. Needs follow-up — 39310308
Runs against established TME permissions and infrastructure. Run one Windows SKU to validate the service connection, policy/WinRM access, immutable storage promotion, and E2E discovery. Needs follow-up — 39310306

The main point is that Windows is reusing its existing shared implementation, just as Linux does. This PR adds the TME-specific mode and publishing path that the shared Windows implementation did not previously support; it does not add a separate Windows TME build implementation.

@janenotjung-hue
janenotjung-hue enabled auto-merge (squash) August 19, 2026 04:28
@timmy-wright

Copy link
Copy Markdown
Contributor

That analysis makes sense. Can you run the prod and test VHD build pipelines to check for regressions?

@janenotjung-hue
janenotjung-hue merged commit dbc5cb2 into main Aug 20, 2026
55 checks passed
@janenotjung-hue
janenotjung-hue deleted the janejung/windows-tme-vhd-build branch August 20, 2026 01:01
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants