feat: support Windows TME VHD builds - #9235
Conversation
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> Copilot-Session: 94930400-cff0-4e18-9ddd-6a285b891087
Windows Unit Test Results 3 files 12 suites 48s ⏱️ 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
There was a problem hiding this comment.
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_modehelper to allow TME release-candidate builds (non-release branch) to run withDRY_RUN=Falsewhen 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 tsvcommonly outputsTrue/False(capitalized). As written, the lowercase comparison (!= "true") can be wrong and may causeaz storage blob copy startto 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 tsvbut compares the result to lowercase"true". If Azure CLI returnsTrue/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 tsvreturnsTrue/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.
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> Copilot-Session: a6f6b936-a7ac-4315-8a30-8e8074517c8d
There was a problem hiding this comment.
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., viatr) 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_INFOwhen it is exactlyTrue, but other parts of the change treat the value case-insensitively (and a variable group may providetrue).
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_INFOwhen it is exactlyTrue, but other parts of the change treat the value case-insensitively (and a variable group may providetrue).
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
ENVIRONMENTandGENERATE_PUBLISHING_INFO, but the inline bash logic intentionally treats them case-insensitively. IfENVIRONMENTis set toTMEorGENERATE_PUBLISHING_INFOistrue, 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_modeand the new ShellSpec coverage treatGENERATE_PUBLISHING_INFOcase-insensitively (e.g.,true), but this condition only matches the capitalized valueTrue. 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')))
|
How do the Linux TME builds work? I'm keen to know that to make sure we're aligning with them. |
|
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.
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. |
|
That analysis makes sense. Can you run the prod and test VHD build pipelines to check for regressions? |
What this changes
.pipelines/.vsts-vhd-builder-release-windows.yamlfor TME rather than adding a separate Windows TME YAMLmainto generate publishing info without deleting the builder SIG imagevhdstagingcontainer and verifies asynchronous page-blob copy into immutable storageReuse model
The TME ADO definition will link the existing
AKS Node SIG 1ES PoolsandDaily VHD Build Variablesgroups 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-shellgit diff --checkRemaining 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