mirror of
https://github.com/gmeligio/flutter-docker-image.git
synced 2026-05-24 12:30:34 +00:00
feat: pin Windows toolchain versions in config/version.json (#456)
- Extends the manifest-first discipline (already used for Flutter/Android) to the Windows toolchain. `config/version.json` now carries `windows.git`, `windows.vsBuildTools.cmakeProject`, `windows.vsBuildTools.windows11Sdk.build`, and `windows.vsBuildTools.vcTools`; `config/schema.cue` validates them via new `#SemverQuad` and `#WindowsToolchain` definitions. --------- Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com> Co-authored-by: verified-commit[bot] <180343340+verified-commit[bot]@users.noreply.github.com>
This commit is contained in:
+1
-1
@@ -19,6 +19,6 @@
|
|||||||
"plexsystems/container-structure-test-action" = "~0.3.0"
|
"plexsystems/container-structure-test-action" = "~0.3.0"
|
||||||
|
|
||||||
[actions.overrides]
|
[actions.overrides]
|
||||||
"actions/download-artifact" = [{ workflow = ".github/workflows/build.yml", job = "test_image", step = 2, version = "^4" }, { workflow = ".github/workflows/build.yml", job = "scan_image", step = 0, version = "^4" }, { workflow = ".github/workflows/update_version.yml", job = "validate_config_version", step = 2, version = "~6.0.0" }, { workflow = ".github/workflows/update_version.yml", job = "update_docs_and_create_pr", step = 2, version = "~6.0.0" }, { workflow = ".github/workflows/update_version.yml", job = "update_docs_and_create_pr", step = 3, version = "~6.0.0" }, { workflow = ".github/workflows/update_version.yml", job = "update_android_version", step = 2, version = "~6.0.0" }]
|
"actions/download-artifact" = [{ workflow = ".github/workflows/build.yml", job = "test_image", step = 2, version = "^4" }, { workflow = ".github/workflows/build.yml", job = "scan_image", step = 0, version = "^4" }, { workflow = ".github/workflows/update_version.yml", job = "validate_config_version", step = 2, version = "~6.0.0" }, { workflow = ".github/workflows/update_version.yml", job = "update_docs_and_create_pr", step = 2, version = "~6.0.0" }, { workflow = ".github/workflows/update_version.yml", job = "update_android_version", step = 2, version = "~6.0.0" }, { workflow = ".github/workflows/update_version.yml", job = "update_windows_version", step = 3, version = "~6.0.0" }, { workflow = ".github/workflows/update_version.yml", job = "update_docs_and_create_pr", step = 6, version = "~6.0.0" }]
|
||||||
"docker/metadata-action" = [ { workflow = ".github/workflows/ci.yml", job = "test_image", step = 5, version = "~5.10.0" }, { workflow = ".github/workflows/release.yml", job = "release_android", step = 2, version = "~5.10.0" }, { workflow = ".github/workflows/windows.yml", job = "test_windows", step = 3, version = "~5.7.0" }, { workflow = ".github/workflows/windows.yml", job = "test_windows", step = 4, version = "~5.7.0" }, { workflow = ".github/workflows/release.yml", job = "release_windows", step = 2, version = "~5.10.0" }, { workflow = ".github/workflows/build.yml", job = "build_image", step = 7, version = "~5.10.0" }]
|
"docker/metadata-action" = [ { workflow = ".github/workflows/ci.yml", job = "test_image", step = 5, version = "~5.10.0" }, { workflow = ".github/workflows/release.yml", job = "release_android", step = 2, version = "~5.10.0" }, { workflow = ".github/workflows/windows.yml", job = "test_windows", step = 3, version = "~5.7.0" }, { workflow = ".github/workflows/windows.yml", job = "test_windows", step = 4, version = "~5.7.0" }, { workflow = ".github/workflows/release.yml", job = "release_windows", step = 2, version = "~5.10.0" }, { workflow = ".github/workflows/build.yml", job = "build_image", step = 7, version = "~5.10.0" }]
|
||||||
"docker/scout-action" = [{ workflow = ".github/workflows/build.yml", job = "scan_image", step = 3, version = "~1.20.4" }, { workflow = ".github/workflows/release.yml", job = "record_image", step = 2, version = "~1.18.2" }, { workflow = ".github/workflows/build.yml", job = "scan_image", step = 5, version = "~1.20.4" }]
|
"docker/scout-action" = [{ workflow = ".github/workflows/build.yml", job = "scan_image", step = 3, version = "~1.20.4" }, { workflow = ".github/workflows/release.yml", job = "record_image", step = 2, version = "~1.18.2" }, { workflow = ".github/workflows/build.yml", job = "scan_image", step = 5, version = "~1.20.4" }]
|
||||||
|
|||||||
@@ -159,6 +159,10 @@ jobs:
|
|||||||
|
|
||||||
$buildArgs = $tagArgs + $labelArgs + @(
|
$buildArgs = $tagArgs + $labelArgs + @(
|
||||||
'--build-arg', "flutter_version=${{ env.FLUTTER_VERSION }}",
|
'--build-arg', "flutter_version=${{ env.FLUTTER_VERSION }}",
|
||||||
|
'--build-arg', "git_version=${{ env.GIT_VERSION }}",
|
||||||
|
'--build-arg', "vs_cmake_version=${{ env.VS_CMAKE_VERSION }}",
|
||||||
|
'--build-arg', "vs_win11sdk_build=${{ env.VS_WIN11SDK_BUILD }}",
|
||||||
|
'--build-arg', "vs_vctools_version=${{ env.VS_VCTOOLS_VERSION }}",
|
||||||
'--target', 'flutter',
|
'--target', 'flutter',
|
||||||
'--file', 'windows.Dockerfile',
|
'--file', 'windows.Dockerfile',
|
||||||
'.'
|
'.'
|
||||||
|
|||||||
@@ -83,6 +83,119 @@ jobs:
|
|||||||
name: flutter_version.json
|
name: flutter_version.json
|
||||||
path: ${{ env.FLUTTER_VERSION_PATH }}
|
path: ${{ env.FLUTTER_VERSION_PATH }}
|
||||||
|
|
||||||
|
update_windows_version:
|
||||||
|
permissions:
|
||||||
|
contents: write
|
||||||
|
needs: update_flutter_version
|
||||||
|
if: ${{ needs.update_flutter_version.outputs.new_version == 'true' }}
|
||||||
|
outputs:
|
||||||
|
version_artifact_id: ${{ steps.upload-version.outputs.artifact-id }}
|
||||||
|
runs-on: ubuntu-24.04
|
||||||
|
steps:
|
||||||
|
- name: Checkout repository
|
||||||
|
uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 # v6.0.1
|
||||||
|
|
||||||
|
- name: Setup CUE
|
||||||
|
uses: jaxxstorm/action-install-gh-release@6096f2a2bbfee498ced520b6922ac2c06e990ed2 # v2.1.0
|
||||||
|
with:
|
||||||
|
repo: cue-lang/cue
|
||||||
|
tag: v0.15.0
|
||||||
|
digest: 06925fc1e5174591cef0b1e42ac32cff4271804742cd20893de1793b6d82d460
|
||||||
|
|
||||||
|
# Parallel pattern with update_android_version: the artifact is downloaded
|
||||||
|
# to keep job structure symmetric, even though windows fields are not
|
||||||
|
# currently tied to a specific Flutter tag.
|
||||||
|
- name: Delete flutter_version.json
|
||||||
|
run: rm ${{ env.FLUTTER_VERSION_PATH }}
|
||||||
|
|
||||||
|
- name: Download artifact with the new Flutter version
|
||||||
|
uses: actions/download-artifact@018cc2cf5baa6db3ef3c5f8a56943fffe632ef53 # v6.0.0
|
||||||
|
with:
|
||||||
|
artifact-ids: ${{ needs.update_flutter_version.outputs.flutter_version_artifact_id }}
|
||||||
|
path: config
|
||||||
|
|
||||||
|
- name: Resolve latest Git for Windows version
|
||||||
|
id: git_version
|
||||||
|
run: |
|
||||||
|
tag=$(curl -fsSL https://api.github.com/repos/git-for-windows/git/releases/latest | jq -r '.tag_name')
|
||||||
|
version=${tag#v}
|
||||||
|
version=${version%.windows.*}
|
||||||
|
echo "git_version=$version" >> "$GITHUB_OUTPUT"
|
||||||
|
echo "Resolved Git for Windows version: $version"
|
||||||
|
|
||||||
|
- name: Fetch VS channel manifest
|
||||||
|
run: curl -fsSL https://aka.ms/vs/17/release/channel -o channel.json
|
||||||
|
|
||||||
|
# The channel manifest only contains product-level entries; per-component
|
||||||
|
# versions live in VisualStudio.vsman, referenced and SHA-256 pinned from
|
||||||
|
# the channel via the Microsoft.VisualStudio.Manifests.VisualStudio item.
|
||||||
|
- name: Resolve VS catalog manifest payload
|
||||||
|
id: vsman_payload
|
||||||
|
run: |
|
||||||
|
url=$(jq -r '.channelItems[] | select(.id=="Microsoft.VisualStudio.Manifests.VisualStudio") | .payloads[0].url' channel.json)
|
||||||
|
sha=$(jq -r '.channelItems[] | select(.id=="Microsoft.VisualStudio.Manifests.VisualStudio") | .payloads[0].sha256' channel.json)
|
||||||
|
echo "url=$url" >> "$GITHUB_OUTPUT"
|
||||||
|
echo "sha=$sha" >> "$GITHUB_OUTPUT"
|
||||||
|
|
||||||
|
- name: Download and verify VS catalog manifest
|
||||||
|
run: |
|
||||||
|
curl -fsSL "${{ steps.vsman_payload.outputs.url }}" -o vsman.json
|
||||||
|
echo "${{ steps.vsman_payload.outputs.sha }} vsman.json" | sha256sum -c -
|
||||||
|
|
||||||
|
- name: Resolve VS BuildTools component versions
|
||||||
|
id: vs_versions
|
||||||
|
run: |
|
||||||
|
cmake=$(jq -r '.packages[] | select(.id=="Microsoft.VisualStudio.Component.VC.CMake.Project") | .version' vsman.json)
|
||||||
|
vctools=$(jq -r '.packages[] | select(.id=="Microsoft.VisualStudio.Workload.VCTools") | .version' vsman.json)
|
||||||
|
echo "cmake=$cmake" >> "$GITHUB_OUTPUT"
|
||||||
|
echo "vctools=$vctools" >> "$GITHUB_OUTPUT"
|
||||||
|
echo "CMake: $cmake; VCTools: $vctools"
|
||||||
|
|
||||||
|
- name: Write windows block into config/version.json
|
||||||
|
env:
|
||||||
|
GIT_VERSION: ${{ steps.git_version.outputs.git_version }}
|
||||||
|
VS_CMAKE_VERSION: ${{ steps.vs_versions.outputs.cmake }}
|
||||||
|
VS_VCTOOLS_VERSION: ${{ steps.vs_versions.outputs.vctools }}
|
||||||
|
run: |
|
||||||
|
# Win11SDK build id is human-pinned (changes infrequently; tied to OS branding).
|
||||||
|
win11sdk_build=$(jq -r '.windows.vsBuildTools.windows11Sdk.build' config/version.json)
|
||||||
|
jq --arg git "$GIT_VERSION" \
|
||||||
|
--arg cmake "$VS_CMAKE_VERSION" \
|
||||||
|
--arg vctools "$VS_VCTOOLS_VERSION" \
|
||||||
|
--argjson sdkbuild "$win11sdk_build" \
|
||||||
|
'.windows = {
|
||||||
|
git: {version: $git},
|
||||||
|
vsBuildTools: {
|
||||||
|
cmakeProject: {version: $cmake},
|
||||||
|
windows11Sdk: {build: $sdkbuild},
|
||||||
|
vcTools: {version: $vctools}
|
||||||
|
}
|
||||||
|
}' config/version.json > config/version.json.tmp
|
||||||
|
mv config/version.json.tmp config/version.json
|
||||||
|
|
||||||
|
- name: Validate version.json with CUE
|
||||||
|
run: cue vet config/schema.cue -d '#Version' config/version.json
|
||||||
|
|
||||||
|
# The artifact's file is renamed so it doesn't collide with the Android
|
||||||
|
# artifact's version.json in update_docs_and_create_pr's merge step.
|
||||||
|
- name: Stage windows-only artifact
|
||||||
|
run: cp config/version.json "${RUNNER_TEMP}/version.json.windows"
|
||||||
|
|
||||||
|
- name: Upload artifact with the updated windows block
|
||||||
|
id: upload-version
|
||||||
|
uses: actions/upload-artifact@330a01c490aca151604b8cf639adc76d48f6c5d4 # v5.0.0
|
||||||
|
with:
|
||||||
|
name: version.json.windows
|
||||||
|
path: ${{ runner.temp }}/version.json.windows
|
||||||
|
|
||||||
|
- name: Upload VS manifest artifacts for forensics
|
||||||
|
uses: actions/upload-artifact@330a01c490aca151604b8cf639adc76d48f6c5d4 # v5.0.0
|
||||||
|
with:
|
||||||
|
name: vs-manifests
|
||||||
|
path: |
|
||||||
|
channel.json
|
||||||
|
vsman.json
|
||||||
|
|
||||||
update_android_version:
|
update_android_version:
|
||||||
permissions:
|
permissions:
|
||||||
# Allow to write contents to push commits
|
# Allow to write contents to push commits
|
||||||
@@ -223,6 +336,7 @@ jobs:
|
|||||||
needs:
|
needs:
|
||||||
- update_flutter_version
|
- update_flutter_version
|
||||||
- update_android_version
|
- update_android_version
|
||||||
|
- update_windows_version
|
||||||
- validate_config_version
|
- validate_config_version
|
||||||
runs-on: ubuntu-24.04
|
runs-on: ubuntu-24.04
|
||||||
env:
|
env:
|
||||||
@@ -243,11 +357,33 @@ jobs:
|
|||||||
- name: Download configuration artifacts
|
- name: Download configuration artifacts
|
||||||
uses: actions/download-artifact@018cc2cf5baa6db3ef3c5f8a56943fffe632ef53 # v6.0.0
|
uses: actions/download-artifact@018cc2cf5baa6db3ef3c5f8a56943fffe632ef53 # v6.0.0
|
||||||
with:
|
with:
|
||||||
artifact-ids: ${{ needs.update_flutter_version.outputs.flutter_version_artifact_id }},${{ needs.update_android_version.outputs.version_artifact_id }}
|
artifact-ids: ${{ needs.update_flutter_version.outputs.flutter_version_artifact_id }},${{ needs.update_android_version.outputs.version_artifact_id }},${{ needs.update_windows_version.outputs.version_artifact_id }}
|
||||||
path: config
|
path: config
|
||||||
# Download to the configured path instead of separated directories by artifact id
|
# Download to the configured path instead of separated directories by artifact id.
|
||||||
|
# Artifacts contain distinct filenames (flutter_version.json, version.json,
|
||||||
|
# version.json.windows) so merge-multiple is safe.
|
||||||
merge-multiple: true
|
merge-multiple: true
|
||||||
|
|
||||||
|
# Merge order: the Android artifact's version.json is the base (it carries
|
||||||
|
# the new flutter and android blocks). The Windows artifact's windows block
|
||||||
|
# overlays the windows field. This keeps each producer authoritative over
|
||||||
|
# its own block.
|
||||||
|
- name: Merge windows block into version.json
|
||||||
|
run: |
|
||||||
|
jq -s '.[0] + {windows: .[1].windows}' config/version.json config/version.json.windows > config/version.json.merged
|
||||||
|
mv config/version.json.merged config/version.json
|
||||||
|
rm config/version.json.windows
|
||||||
|
|
||||||
|
- name: Setup CUE
|
||||||
|
uses: jaxxstorm/action-install-gh-release@6096f2a2bbfee498ced520b6922ac2c06e990ed2 # v2.1.0
|
||||||
|
with:
|
||||||
|
repo: cue-lang/cue
|
||||||
|
tag: v0.15.0
|
||||||
|
digest: 06925fc1e5174591cef0b1e42ac32cff4271804742cd20893de1793b6d82d460
|
||||||
|
|
||||||
|
- name: Validate merged version.json with CUE
|
||||||
|
run: cue vet config/schema.cue -d '#Version' config/version.json
|
||||||
|
|
||||||
- name: Download test artifacts
|
- name: Download test artifacts
|
||||||
uses: actions/download-artifact@018cc2cf5baa6db3ef3c5f8a56943fffe632ef53 # v6.0.0
|
uses: actions/download-artifact@018cc2cf5baa6db3ef3c5f8a56943fffe632ef53 # v6.0.0
|
||||||
with:
|
with:
|
||||||
|
|||||||
@@ -58,7 +58,13 @@ jobs:
|
|||||||
- name: Test image and push to local Docker daemon
|
- name: Test image and push to local Docker daemon
|
||||||
shell: powershell
|
shell: powershell
|
||||||
run: |
|
run: |
|
||||||
docker build . -f windows.Dockerfile --build-arg flutter_version=${{ env.FLUTTER_VERSION }} -t ${{ fromJson(steps.metadata.outputs.json).tags[0] }} --target test
|
docker build . -f windows.Dockerfile `
|
||||||
|
--build-arg flutter_version=${{ env.FLUTTER_VERSION }} `
|
||||||
|
--build-arg git_version=${{ env.GIT_VERSION }} `
|
||||||
|
--build-arg vs_cmake_version=${{ env.VS_CMAKE_VERSION }} `
|
||||||
|
--build-arg vs_win11sdk_build=${{ env.VS_WIN11SDK_BUILD }} `
|
||||||
|
--build-arg vs_vctools_version=${{ env.VS_VCTOOLS_VERSION }} `
|
||||||
|
-t ${{ fromJson(steps.metadata.outputs.json).tags[0] }} --target test
|
||||||
|
|
||||||
docker run --rm ${{ fromJson(steps.metadata.outputs.json).tags[0] }}
|
docker run --rm ${{ fromJson(steps.metadata.outputs.json).tags[0] }}
|
||||||
|
|
||||||
|
|||||||
@@ -13,6 +13,21 @@ import "list"
|
|||||||
version!: =~ "^\\d+.\\d+.\\d+$"
|
version!: =~ "^\\d+.\\d+.\\d+$"
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#SemverQuad: {
|
||||||
|
version!: =~ "^\\d+\\.\\d+\\.\\d+\\.\\d+$"
|
||||||
|
}
|
||||||
|
|
||||||
|
#WindowsToolchain: {
|
||||||
|
git: #SemverPatch
|
||||||
|
vsBuildTools: {
|
||||||
|
cmakeProject: #SemverQuad
|
||||||
|
windows11Sdk: {
|
||||||
|
build!: int
|
||||||
|
}
|
||||||
|
vcTools: #SemverQuad
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
#FlutterVersion: {
|
#FlutterVersion: {
|
||||||
flutter: {
|
flutter: {
|
||||||
channel!: "stable"
|
channel!: "stable"
|
||||||
@@ -36,4 +51,6 @@ import "list"
|
|||||||
}
|
}
|
||||||
|
|
||||||
fastlane!: #SemverPatch
|
fastlane!: #SemverPatch
|
||||||
|
|
||||||
|
windows!: #WindowsToolchain
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -28,5 +28,21 @@
|
|||||||
},
|
},
|
||||||
"fastlane": {
|
"fastlane": {
|
||||||
"version": "2.234.0"
|
"version": "2.234.0"
|
||||||
|
},
|
||||||
|
"windows": {
|
||||||
|
"git": {
|
||||||
|
"version": "2.46.0"
|
||||||
|
},
|
||||||
|
"vsBuildTools": {
|
||||||
|
"cmakeProject": {
|
||||||
|
"version": "17.14.36510.44"
|
||||||
|
},
|
||||||
|
"windows11Sdk": {
|
||||||
|
"build": 22621
|
||||||
|
},
|
||||||
|
"vcTools": {
|
||||||
|
"version": "17.14.36331.10"
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -4,6 +4,10 @@
|
|||||||
|
|
||||||
& $Env:ProgramFiles\Docker\Docker\DockerCli.exe -SwitchDaemon
|
& $Env:ProgramFiles\Docker\Docker\DockerCli.exe -SwitchDaemon
|
||||||
|
|
||||||
|
## Toolchain versions
|
||||||
|
|
||||||
|
Windows toolchain versions (Git for Windows, Visual Studio BuildTools components, Windows 11 SDK build) are pinned in `config/version.json` under the `windows` block and validated by `config/schema.cue`. The `update_version.yml` workflow refreshes these alongside Flutter and Android in the monthly upgrade PR, and the Pester suite asserts the installed image matches the manifest on every CI run.
|
||||||
|
|
||||||
## TODO
|
## TODO
|
||||||
|
|
||||||
1. Install tools
|
1. Install tools
|
||||||
@@ -32,9 +36,7 @@ RUN Invoke-WebRequest -Uri https://aka.ms/vs/17/release/vs_buildtools.exe -OutFi
|
|||||||
1. Read dependencies from [flutter_tools](https://github.com/flutter/flutter/blob/master/packages/flutter_tools/lib/src/windows/visual_studio.dart).
|
1. Read dependencies from [flutter_tools](https://github.com/flutter/flutter/blob/master/packages/flutter_tools/lib/src/windows/visual_studio.dart).
|
||||||
1. Check how it can be run in Github actions.
|
1. Check how it can be run in Github actions.
|
||||||
1. Check how it can be run in Gitlab CI/CD.
|
1. Check how it can be run in Gitlab CI/CD.
|
||||||
1. Test where is installed.
|
|
||||||
1. Test that path to powershell.exe exists.
|
1. Test that path to powershell.exe exists.
|
||||||
1. Test with a snapshot of flutter config to determine if new feature flags should be enabled or disabled.
|
|
||||||
1. Test that Build Tools were installed in C:\Program Files (x86)\Microsoft Visual Studio\2022\BuildTools\msbuild\current\bin
|
1. Test that Build Tools were installed in C:\Program Files (x86)\Microsoft Visual Studio\2022\BuildTools\msbuild\current\bin
|
||||||
1. Check [Windows installation requirements for Flutter](https://docs.flutter.dev/get-started/install/windows/desktop)
|
1. Check [Windows installation requirements for Flutter](https://docs.flutter.dev/get-started/install/windows/desktop)
|
||||||
1. Add docs explaining to use `$VerbosePreference = 'Continue';` in the SHELL to debug unexpected pwsh problems.
|
1. Add docs explaining to use `$VerbosePreference = 'Continue';` in the SHELL to debug unexpected pwsh problems.
|
||||||
|
|||||||
+8
-6
@@ -6,6 +6,10 @@
|
|||||||
|
|
||||||
& $Env:ProgramFiles\\Docker\\Docker\\DockerCli.exe -SwitchDaemon
|
& $Env:ProgramFiles\\Docker\\Docker\\DockerCli.exe -SwitchDaemon
|
||||||
|
|
||||||
|
## Toolchain versions
|
||||||
|
|
||||||
|
Windows toolchain versions (Git for Windows, Visual Studio BuildTools components, Windows 11 SDK build) are pinned in `config/version.json` under the `windows` block and validated by `config/schema.cue`. The `update_version.yml` workflow refreshes these alongside Flutter and Android in the monthly upgrade PR, and the Pester suite asserts the installed image matches the manifest on every CI run.
|
||||||
|
|
||||||
## TODO
|
## TODO
|
||||||
|
|
||||||
1. Install tools
|
1. Install tools
|
||||||
@@ -35,12 +39,10 @@ RUN Invoke-WebRequest -Uri https://aka.ms/vs/17/release/vs_buildtools.exe -OutFi
|
|||||||
1. Read dependencies from [flutter\_tools](https://github.com/flutter/flutter/blob/master/packages/flutter%5Ftools/lib/src/windows/visual%5Fstudio.dart).
|
1. Read dependencies from [flutter\_tools](https://github.com/flutter/flutter/blob/master/packages/flutter%5Ftools/lib/src/windows/visual%5Fstudio.dart).
|
||||||
2. Check how it can be run in Github actions.
|
2. Check how it can be run in Github actions.
|
||||||
3. Check how it can be run in Gitlab CI/CD.
|
3. Check how it can be run in Gitlab CI/CD.
|
||||||
4. Test where is installed.
|
4. Test that path to powershell.exe exists.
|
||||||
5. Test that path to powershell.exe exists.
|
5. Test that Build Tools were installed in C:\\Program Files (x86)\\Microsoft Visual Studio\\2022\\BuildTools\\msbuild\\current\\bin
|
||||||
6. Test with a snapshot of flutter config to determine if new feature flags should be enabled or disabled.
|
6. Check [Windows installation requirements for Flutter](https://docs.flutter.dev/get-started/install/windows/desktop)
|
||||||
7. Test that Build Tools were installed in C:\\Program Files (x86)\\Microsoft Visual Studio\\2022\\BuildTools\\msbuild\\current\\bin
|
7. Add docs explaining to use `$VerbosePreference = 'Continue';` in the SHELL to debug unexpected pwsh problems.
|
||||||
8. Check [Windows installation requirements for Flutter](https://docs.flutter.dev/get-started/install/windows/desktop)
|
|
||||||
9. Add docs explaining to use `$VerbosePreference = 'Continue';` in the SHELL to debug unexpected pwsh problems.
|
|
||||||
|
|
||||||
## Open issue in windows Docker images repo
|
## Open issue in windows Docker images repo
|
||||||
|
|
||||||
|
|||||||
@@ -4,7 +4,7 @@ The repository already has a strong "manifest is source of truth" discipline for
|
|||||||
|
|
||||||
Constraints:
|
Constraints:
|
||||||
|
|
||||||
- Microsoft does not publish a clean, programmatic, monotonic API for VS BuildTools component versions. The closest source is the channel manifest at `https://aka.ms/vs/17/release/channel` (JSON), which is used by Microsoft's own VS installers but has nondeterministic ordering and changes structure occasionally.
|
- Microsoft does not publish a clean, programmatic, monotonic API for VS BuildTools component versions. The closest source is a two-step fetch: the channel manifest at `https://aka.ms/vs/17/release/channel` (JSON, ~90 KB) lists 13 product-level entries all stamped with the overall release version (e.g., `17.14.37314.3`) and references the catalog manifest `VisualStudio.vsman` (JSON, ~17 MB, SHA-256 pinned by the channel) via the `Microsoft.VisualStudio.Manifests.VisualStudio` channel item. `vsman.packages[]` is where per-component versions live (verified 2026-05-21: `VC.CMake.Project` → `17.14.36510.44`, `Windows11SDK.22621` → `17.14.36510.44`, `Workload.VCTools` → `17.14.36331.10`). The channel manifest alone is insufficient.
|
||||||
- The Windows 11 SDK build number (`22621`) is essentially a Microsoft branding choice; it changes infrequently (Win11 22H2, 23H2 etc.) and is not strictly tied to VS BuildTools versions.
|
- The Windows 11 SDK build number (`22621`) is essentially a Microsoft branding choice; it changes infrequently (Win11 22H2, 23H2 etc.) and is not strictly tied to VS BuildTools versions.
|
||||||
- Git for Windows publishes clean GitHub releases at `git-for-windows/git`, but the tag naming is `vM.m.p.windows.N` — the `.windows.N` suffix needs to be stripped before storing as a clean semver.
|
- Git for Windows publishes clean GitHub releases at `git-for-windows/git`, but the tag naming is `vM.m.p.windows.N` — the `.windows.N` suffix needs to be stripped before storing as a clean semver.
|
||||||
- `cue` already vendors well in this repo; adding `#SemverQuad` is a one-line addition.
|
- `cue` already vendors well in this repo; adding `#SemverQuad` is a one-line addition.
|
||||||
@@ -29,9 +29,11 @@ Constraints:
|
|||||||
|
|
||||||
## Decisions
|
## Decisions
|
||||||
|
|
||||||
### Decision: VS BuildTools component versions are pinned in `config/version.json`, refreshed manually from the channel manifest
|
### Decision: VS BuildTools component versions are pinned in `config/version.json`, refreshed from the VS catalog manifest (`vsman`) via a two-step fetch
|
||||||
|
|
||||||
The `update_windows_version` job reads `https://aka.ms/vs/17/release/channel` and writes the resolved component versions into `config/version.json`. However, the channel manifest occasionally drops or renames components, so this is treated as a *suggestion* not a *truth*: the PR is opened with the new values, but the Pester suite then verifies that those values actually install. If they don't, the PR fails and a human pins by hand.
|
The `update_windows_version` job (1) fetches `https://aka.ms/vs/17/release/channel`, (2) extracts the `Microsoft.VisualStudio.Manifests.VisualStudio` payload URL + SHA-256, (3) downloads that `VisualStudio.vsman` (~17 MB), (4) verifies the SHA, (5) `jq`s `.packages[] | select(.id == <component>) | .version` for each tracked component, and writes the resolved versions into `config/version.json`. The catalog occasionally drops or renames components, so this is treated as a *suggestion* not a *truth*: the PR is opened with the new values, but the Pester suite then verifies that those values actually install. If they don't, the PR fails and a human pins by hand.
|
||||||
|
|
||||||
|
The SHA-pinning of `vsman` by the channel is a free integrity property — the job can trust the catalog without committing it. Also note: `Microsoft.VisualStudio.Component.Windows11SDK.22621` carries the build id (`22621`) in the component **id**, not the version field; the `version` is the VS release stamp. This matches the design's decision to model the SDK build as a bare `int` separate from the `#SemverQuad` version fields.
|
||||||
|
|
||||||
Alternatives considered:
|
Alternatives considered:
|
||||||
|
|
||||||
@@ -74,7 +76,9 @@ This means the test compares the leading three parts of `git --version` output t
|
|||||||
- **[Risk] Microsoft yanks a VS component version (it has happened) and the image cannot be rebuilt for a tag that pinned the yanked version.** → Mitigation: the existing tag's image is already pushed and immutable. Future tags use new versions. Old-tag rebuilds (`workflow_dispatch` per `p2`) might fail until the manifest is updated; document this as a known limitation.
|
- **[Risk] Microsoft yanks a VS component version (it has happened) and the image cannot be rebuilt for a tag that pinned the yanked version.** → Mitigation: the existing tag's image is already pushed and immutable. Future tags use new versions. Old-tag rebuilds (`workflow_dispatch` per `p2`) might fail until the manifest is updated; document this as a known limitation.
|
||||||
- **[Risk] Tightening Pester to exact versions makes the test brittle.** → Acceptable: that's the point. Drift detection is a feature.
|
- **[Risk] Tightening Pester to exact versions makes the test brittle.** → Acceptable: that's the point. Drift detection is a feature.
|
||||||
- **[Trade-off] More fields in `version.json` mean more review surface for upgrade PRs.** → Acceptable: the alternative is hidden state in the Dockerfile, which has no review surface at all.
|
- **[Trade-off] More fields in `version.json` mean more review surface for upgrade PRs.** → Acceptable: the alternative is hidden state in the Dockerfile, which has no review surface at all.
|
||||||
- **[Trade-off] `update_windows_version` adds a runtime dependency on `aka.ms/vs/17/release/channel` and `api.github.com/repos/git-for-windows/git`.** → Acceptable: the workflow already depends on `storage.googleapis.com/flutter_infra_release` and `raw.githubusercontent.com/flutter/flutter`. Two more upstreams is incremental.
|
- **[Trade-off] `update_windows_version` adds a runtime dependency on `aka.ms/vs/17/release/channel`, `download.visualstudio.microsoft.com` (for `vsman`), and `api.github.com/repos/git-for-windows/git`.** → Acceptable: the workflow already depends on `storage.googleapis.com/flutter_infra_release` and `raw.githubusercontent.com/flutter/flutter`. Three more upstreams is incremental.
|
||||||
|
- **[Trade-off] `update_windows_version` downloads ~17 MB (`VisualStudio.vsman`) per run.** → Acceptable. `update_version.yml` is scheduled `0 0 * * MON-FRI`, but `update_windows_version` is gated on `update_flutter_version.outputs.new_version == 'true'` (same gating pattern as `update_android_version`), so the fetch only fires when Flutter actually bumped — empirically about once a month. On quiet weekdays the job is skipped and nothing is downloaded. No cross-run caching: the catalog would have to be invalidated against the channel anyway, and at ~once-a-month firing the savings don't justify the cache plumbing.
|
||||||
|
- **[Forensic mitigation] The job uploads the raw `VisualStudio.vsman` (and the channel JSON) as workflow artifacts.** → 90-day retention is enough to diagnose any "why did this PR pick these versions" question without committing the manifest into git. Avoids the noisy-history tradeoff while preserving the forensic record.
|
||||||
|
|
||||||
## Automated Test Strategy
|
## Automated Test Strategy
|
||||||
|
|
||||||
@@ -109,8 +113,12 @@ This means the test compares the leading three parts of `git --version` output t
|
|||||||
6. Wait for the next scheduled `update_version.yml` run; it should produce a PR that includes a `windows` block diff. Review and merge as usual.
|
6. Wait for the next scheduled `update_version.yml` run; it should produce a PR that includes a `windows` block diff. Review and merge as usual.
|
||||||
7. Rollback strategy: if `update_windows_version` produces consistently-bad PRs, mark it `if: false` in a follow-up PR. The schema and Dockerfile changes do not need rolling back; they are stable.
|
7. Rollback strategy: if `update_windows_version` produces consistently-bad PRs, mark it `if: false` in a follow-up PR. The schema and Dockerfile changes do not need rolling back; they are stable.
|
||||||
|
|
||||||
|
## Resolved Questions
|
||||||
|
|
||||||
|
- **`#SemverQuad` placement:** lives alongside `#SemverPatch` in `schema.cue`. `schema.cue` is 39 lines today; all five existing version primitives share the file, and there's no per-OS/per-domain split precedent. Splitting on Windows alone would invite drift (someone adds `#SemverQuint` to one file and forgets the other).
|
||||||
|
- **`vs_BuildTools.exe` URL as build arg:** no. The URL `https://aka.ms/vs/17/release/vs_buildtools.exe` embeds a single version token (`17` = VS 2022). A VS major-version bump (to `/vs/18/…`) is an out-of-band migration — component IDs change, the Pester assertions need rewriting, and `update_version.yml` cannot meaningfully automate it. Adding it as a build arg would be ceremony, not capability. A separate change handles VS 2025 if/when needed.
|
||||||
|
- **Commit `vsman` / channel manifest into the repo:** no. The channel manifest already SHA-256-pins `vsman`, so reproducibility-from-a-snapshot is built into Microsoft's design — committing it duplicates state Microsoft already authenticates. Forensic access is preserved by uploading both JSONs as workflow artifacts (90-day retention), which avoids polluting git history with vsman's frequent unrelated churn.
|
||||||
|
|
||||||
## Open Questions
|
## Open Questions
|
||||||
|
|
||||||
- Should `#SemverQuad` live alongside `#SemverPatch` in `schema.cue` or in a separate `windows.cue`? *Tentative: same file.* `schema.cue` is small and the cohesion is high.
|
- None blocking. The three above are resolved; the original "channel manifest as source" assumption was corrected during research (see Constraints: per-component versions live in `vsman`, not the channel — verified 2026-05-21).
|
||||||
- Should the `windows.Dockerfile`'s `vs_BuildTools.exe` URL be a build arg too? *Tentative: no.* The URL is `https://aka.ms/vs/17/release/vs_buildtools.exe` which Microsoft promises to keep stable per major VS version. If that promise breaks, this is a separate change.
|
|
||||||
- Should the channel manifest be cached in the repo (committed) so the update job is reproducible offline? *Tentative: no.* That would mean tracking churn that doesn't affect us. The runtime dependency is acceptable.
|
|
||||||
|
|||||||
@@ -17,7 +17,7 @@
|
|||||||
- In the Pester suite (added by `p1`), tighten the VS component assertions from `*,version=*` to `*,version=<exact-version>*`, and assert Git's reported `git --version` matches `windows.git.version`.
|
- In the Pester suite (added by `p1`), tighten the VS component assertions from `*,version=*` to `*,version=<exact-version>*`, and assert Git's reported `git --version` matches `windows.git.version`.
|
||||||
- Add a new `update_windows_version` job to `update_version.yml`, parallel to `update_android_version` (both gated by `update_flutter_version`'s `result == 'true'` output). The job:
|
- Add a new `update_windows_version` job to `update_version.yml`, parallel to `update_android_version` (both gated by `update_flutter_version`'s `result == 'true'` output). The job:
|
||||||
- reads upstream Git for Windows latest release from `https://api.github.com/repos/git-for-windows/git/releases/latest`,
|
- reads upstream Git for Windows latest release from `https://api.github.com/repos/git-for-windows/git/releases/latest`,
|
||||||
- reads VS BuildTools component versions from the channel manifest (or pins them; see design),
|
- reads VS BuildTools component versions from the VS catalog manifest `VisualStudio.vsman` (fetched via `aka.ms/vs/17/release/channel` → `Microsoft.VisualStudio.Manifests.VisualStudio` payload, SHA-256-verified; see design for two-step fetch),
|
||||||
- writes the new fields into `config/version.json` and uploads the artifact for the `validate_config_version` and `update_docs_and_create_pr` jobs to consume.
|
- writes the new fields into `config/version.json` and uploads the artifact for the `validate_config_version` and `update_docs_and_create_pr` jobs to consume.
|
||||||
- The Windows-relevant fields fall under the existing `flutter-version-update` PR cadence — same upgrade PR carries both Android and Windows updates.
|
- The Windows-relevant fields fall under the existing `flutter-version-update` PR cadence — same upgrade PR carries both Android and Windows updates.
|
||||||
|
|
||||||
@@ -38,5 +38,5 @@
|
|||||||
- Cross-cutting: this is the largest of the three changes. Touches schema, manifest, dockerfile, two workflows, the version-update node script, and the test suite.
|
- Cross-cutting: this is the largest of the three changes. Touches schema, manifest, dockerfile, two workflows, the version-update node script, and the test suite.
|
||||||
- Depends on: `p1-fix-windows-ci-tests` landed (Pester tests exist to tighten); `p2-release-windows-image` ideally landed (so the build args also flow through release).
|
- Depends on: `p1-fix-windows-ci-tests` landed (Pester tests exist to tighten); `p2-release-windows-image` ideally landed (so the build args also flow through release).
|
||||||
- Does not depend on the Renovate-via-`gx` integration (`actions-version-tracking`) since Windows toolchain versions are tracked in `config/version.json` like Android, not in `gx.toml`. Renovate is unaffected.
|
- Does not depend on the Renovate-via-`gx` integration (`actions-version-tracking`) since Windows toolchain versions are tracked in `config/version.json` like Android, not in `gx.toml`. Renovate is unaffected.
|
||||||
- Risk: VS BuildTools component versioning is provided by Microsoft via the channel manifest; the source of truth and the update API have less stability than Flutter's `releases_linux.json`. Mitigation in design.
|
- Risk: VS BuildTools component versioning is provided by Microsoft via the VS catalog manifest (`vsman`, ~17 MB, referenced and SHA-pinned by the channel manifest); the source of truth and the update API have less stability than Flutter's `releases_linux.json`. Mitigation in design.
|
||||||
- Risk: tightening Pester assertions to exact versions means a Microsoft-side patch bump to a VS component will fail CI even though the image still works. Mitigation: track at the build-id level for Win11SDK (already coarse), at the publisher's `version=` for the others, accept that an upgrade PR is required when Microsoft ships a patch.
|
- Risk: tightening Pester assertions to exact versions means a Microsoft-side patch bump to a VS component will fail CI even though the image still works. Mitigation: track at the build-id level for Win11SDK (already coarse), at the publisher's `version=` for the others, accept that an upgrade PR is required when Microsoft ships a patch.
|
||||||
|
|||||||
@@ -1,52 +1,58 @@
|
|||||||
## 1. Extend the CUE schema
|
## 1. Extend the CUE schema
|
||||||
|
|
||||||
- [ ] 1.1 Add `#SemverQuad: { version!: =~ "^\\d+\\.\\d+\\.\\d+\\.\\d+$" }` to `config/schema.cue` alongside the existing `#SemverPatch`.
|
- [x] 1.1 Add `#SemverQuad: { version!: =~ "^\\d+\\.\\d+\\.\\d+\\.\\d+$" }` to `config/schema.cue` alongside the existing `#SemverPatch`.
|
||||||
- [ ] 1.2 Add a `#WindowsToolchain` definition with sub-fields `git: #SemverPatch`, `vsBuildTools.cmakeProject: #SemverQuad`, `vsBuildTools.windows11Sdk.build!: int`, `vsBuildTools.vcTools: #SemverQuad`.
|
- [x] 1.2 Add a `#WindowsToolchain` definition with sub-fields `git: #SemverPatch`, `vsBuildTools.cmakeProject: #SemverQuad`, `vsBuildTools.windows11Sdk.build!: int`, `vsBuildTools.vcTools: #SemverQuad`.
|
||||||
- [ ] 1.3 Extend `#Version` to require `windows: #WindowsToolchain`.
|
- [x] 1.3 Extend `#Version` to require `windows: #WindowsToolchain`.
|
||||||
- [ ] 1.4 Run `cue vet config/schema.cue -d '#Version' config/version.json` and confirm it fails (because `version.json` doesn't yet have the `windows` block — the next group fixes this).
|
- [x] 1.4 Run `cue vet config/schema.cue -d '#Version' config/version.json` and confirm it fails (because `version.json` doesn't yet have the `windows` block — the next group fixes this).
|
||||||
|
|
||||||
## 2. Backfill `config/version.json`
|
## 2. Backfill `config/version.json`
|
||||||
|
|
||||||
- [ ] 2.1 Read the current values from `windows.Dockerfile`: Git `2.46.0`, Win11SDK build `22621`. Run `vs_BuildTools.exe` introspection (or look at a successful `windows-2025` build's package directory listing in a recent CI run) to find the four-part versions actually installed for `Microsoft.VisualStudio.Component.VC.CMake.Project` and `Microsoft.VisualStudio.Workload.VCTools`.
|
- [x] 2.1 Read the current values from `windows.Dockerfile`: Git `2.46.0`, Win11SDK build `22621`. Source the four-part component versions from `VisualStudio.vsman` (fetched via `aka.ms/vs/17/release/channel` → `Microsoft.VisualStudio.Manifests.VisualStudio` payload URL; see Decision in design.md). As of 2026-05-21: `Microsoft.VisualStudio.Component.VC.CMake.Project` = `17.14.36510.44`, `Microsoft.VisualStudio.Workload.VCTools` = `17.14.36331.10`. Rerun the query close to merge time so backfilled values match what `windows.yml` will actually install.
|
||||||
- [ ] 2.2 Add the `windows` block to `config/version.json` with those four values.
|
- [x] 2.2 Add the `windows` block to `config/version.json` with those four values.
|
||||||
- [ ] 2.3 Run `cue vet config/schema.cue -d '#Version' config/version.json`; it should now exit 0.
|
- [x] 2.3 Run `cue vet config/schema.cue -d '#Version' config/version.json`; it should now exit 0.
|
||||||
|
|
||||||
## 3. Remove version literals from `windows.Dockerfile`
|
## 3. Remove version literals from `windows.Dockerfile`
|
||||||
|
|
||||||
- [ ] 3.1 Replace `ARG git_version=2.46.0` with `ARG git_version` (no default).
|
- [x] 3.1 Replace `ARG git_version=2.46.0` with `ARG git_version` (no default).
|
||||||
- [ ] 3.2 Add `ARG vs_cmake_version`, `ARG vs_win11sdk_build`, `ARG vs_vctools_version` (no defaults) before the `vs_BuildTools.exe` invocation.
|
- [x] 3.2 Add `ARG vs_cmake_version`, `ARG vs_win11sdk_build`, `ARG vs_vctools_version` (no defaults) before the `vs_BuildTools.exe` invocation.
|
||||||
- [ ] 3.3 Replace the literal `--add Microsoft.VisualStudio.Component.Windows11SDK.22621` with `--add Microsoft.VisualStudio.Component.Windows11SDK.${env:vs_win11sdk_build}` (or the correct PowerShell expansion syntax inside the RUN command).
|
- [x] 3.3 Replace the literal `--add Microsoft.VisualStudio.Component.Windows11SDK.22621` with `--add Microsoft.VisualStudio.Component.Windows11SDK.${env:vs_win11sdk_build}` (or the correct PowerShell expansion syntax inside the RUN command).
|
||||||
- [ ] 3.4 The CMake and VCTools `--add` lines do not embed versions in the component id — versions are picked up from the channel and asserted later by Pester. Leave the `--add` lines alone for these.
|
- [x] 3.4 The CMake and VCTools `--add` lines do not embed versions in the component id — versions are picked up from the channel and asserted later by Pester. Leave the `--add` lines alone for these.
|
||||||
|
|
||||||
## 4. Surface the new fields via `setEnvironmentVariables.js`
|
## 4. Surface the new fields via `setEnvironmentVariables.js`
|
||||||
|
|
||||||
- [ ] 4.1 Open `script/setEnvironmentVariables.js`. Add reads for `windows.git.version`, `windows.vsBuildTools.cmakeProject.version`, `windows.vsBuildTools.windows11Sdk.build`, `windows.vsBuildTools.vcTools.version`.
|
- [x] 4.1 Open `script/setEnvironmentVariables.js`. Add reads for `windows.git.version`, `windows.vsBuildTools.cmakeProject.version`, `windows.vsBuildTools.windows11Sdk.build`, `windows.vsBuildTools.vcTools.version`.
|
||||||
- [ ] 4.2 Export each via `core.exportVariable` as `GIT_VERSION`, `VS_CMAKE_VERSION`, `VS_WIN11SDK_BUILD`, `VS_VCTOOLS_VERSION`.
|
- [x] 4.2 Export each via `core.exportVariable` as `GIT_VERSION`, `VS_CMAKE_VERSION`, `VS_WIN11SDK_BUILD`, `VS_VCTOOLS_VERSION`.
|
||||||
- [ ] 4.3 Confirm existing exported variables are unchanged.
|
- [x] 4.3 Confirm existing exported variables are unchanged.
|
||||||
|
|
||||||
## 5. Wire build args into the workflows
|
## 5. Wire build args into the workflows
|
||||||
|
|
||||||
- [ ] 5.1 In `.github/workflows/windows.yml`, update the `docker build` invocation in the `Test image and push to local Docker daemon` step to pass `--build-arg git_version=${{ env.GIT_VERSION }}`, `--build-arg vs_cmake_version=${{ env.VS_CMAKE_VERSION }}`, `--build-arg vs_win11sdk_build=${{ env.VS_WIN11SDK_BUILD }}`, `--build-arg vs_vctools_version=${{ env.VS_VCTOOLS_VERSION }}`.
|
- [x] 5.1 In `.github/workflows/windows.yml`, update the `docker build` invocation in the `Test image and push to local Docker daemon` step to pass `--build-arg git_version=${{ env.GIT_VERSION }}`, `--build-arg vs_cmake_version=${{ env.VS_CMAKE_VERSION }}`, `--build-arg vs_win11sdk_build=${{ env.VS_WIN11SDK_BUILD }}`, `--build-arg vs_vctools_version=${{ env.VS_VCTOOLS_VERSION }}`.
|
||||||
- [ ] 5.2 If `p2-release-windows-image` is already merged, apply the same `--build-arg` changes to the `release_windows` job in `.github/workflows/release.yml`.
|
- [x] 5.2 If `p2-release-windows-image` is already merged, apply the same `--build-arg` changes to the `release_windows` job in `.github/workflows/release.yml`.
|
||||||
|
|
||||||
## 6. Tighten the Pester assertions
|
## 6. Tighten the Pester assertions
|
||||||
|
|
||||||
- [ ] 6.1 In `test/windows/Windows.Tests.ps1`, add a `BeforeAll` block that reads `config\version.json` via `Get-Content -Raw | ConvertFrom-Json` into `$manifest`.
|
- [x] 6.1 In `test/windows/Windows.Tests.ps1`, add a `BeforeAll` block that reads `config\version.json` via `Get-Content -Raw | ConvertFrom-Json` into `$manifest`.
|
||||||
- [ ] 6.2 Add a Git version test that runs `git --version`, parses the leading three-part semver (`X.Y.Z` from `git version X.Y.Z.windows.N`), and asserts equality with `$manifest.windows.git.version`.
|
- [x] 6.2 Add a Git version test that runs `git --version`, parses the leading three-part semver (`X.Y.Z` from `git version X.Y.Z.windows.N`), and asserts equality with `$manifest.windows.git.version`.
|
||||||
- [ ] 6.3 Tighten the existing CMake assertion: change pattern from `,version=*` to `,version=$($manifest.windows.vsBuildTools.cmakeProject.version)*`.
|
- [x] 6.3 Tighten the existing CMake assertion: change pattern from `,version=*` to `,version=$($manifest.windows.vsBuildTools.cmakeProject.version)*`.
|
||||||
- [ ] 6.4 Tighten the existing Win11SDK assertion: change to match `Microsoft.VisualStudio.Component.Windows11SDK.$($manifest.windows.vsBuildTools.windows11Sdk.build),version*`.
|
- [x] 6.4 Tighten the existing Win11SDK assertion: change to match `Microsoft.VisualStudio.Component.Windows11SDK.$($manifest.windows.vsBuildTools.windows11Sdk.build),version*`.
|
||||||
- [ ] 6.5 Tighten the existing VCTools assertion: change pattern from `,version=*` to `,version=$($manifest.windows.vsBuildTools.vcTools.version)*`.
|
- [x] 6.5 Tighten the existing VCTools assertion: change pattern from `,version=*` to `,version=$($manifest.windows.vsBuildTools.vcTools.version)*`.
|
||||||
|
|
||||||
## 7. Add `update_windows_version` to `update_version.yml`
|
## 7. Add `update_windows_version` to `update_version.yml`
|
||||||
|
|
||||||
- [ ] 7.1 Add a job `update_windows_version` after `update_flutter_version`. Set `runs-on: ubuntu-24.04`, `needs: update_flutter_version`, `if: ${{ needs.update_flutter_version.outputs.new_version == 'true' }}`. Note: this job runs in parallel with `update_android_version`.
|
- [x] 7.1 Add a job `update_windows_version` after `update_flutter_version`. Set `runs-on: ubuntu-24.04`, `needs: update_flutter_version`, `if: ${{ needs.update_flutter_version.outputs.new_version == 'true' }}`. Note: this job runs in parallel with `update_android_version`.
|
||||||
- [ ] 7.2 Job step: download the `flutter_version.json` artifact (parallel pattern with `update_android_version`).
|
- [x] 7.2 Job step: download the `flutter_version.json` artifact (parallel pattern with `update_android_version`).
|
||||||
- [ ] 7.3 Job step: `curl -fsSL https://api.github.com/repos/git-for-windows/git/releases/latest | jq -r '.tag_name'`; strip leading `v` and trailing `.windows.N`; export as `GIT_VERSION_NEW`.
|
- [x] 7.3 Job step: `curl -fsSL https://api.github.com/repos/git-for-windows/git/releases/latest | jq -r '.tag_name'`; strip leading `v` and trailing `.windows.N`; export as `GIT_VERSION_NEW`.
|
||||||
- [ ] 7.4 Job step: `curl -fsSL https://aka.ms/vs/17/release/channel | jq …` to extract the `Microsoft.VisualStudio.Component.VC.CMake.Project` and `Microsoft.VisualStudio.Workload.VCTools` component versions. Document the jq path in a comment so future maintainers can update it if the channel manifest restructures.
|
- [x] 7.4 Job steps to resolve VS component versions (two-step fetch — the channel manifest alone does NOT contain per-component versions; they live in `vsman`):
|
||||||
- [ ] 7.5 Job step: write the four resolved values into `config/version.json` using `jq` (preserving existing keys).
|
- [x] 7.4a `curl -fsSL https://aka.ms/vs/17/release/channel -o channel.json`
|
||||||
- [ ] 7.6 Job step: validate with `cue vet config/schema.cue -d '#Version' config/version.json`. Fail the job on non-zero exit.
|
- [x] 7.4b Extract the catalog URL and SHA: ``vsman_url=$(jq -r '.channelItems[] | select(.id=="Microsoft.VisualStudio.Manifests.VisualStudio") | .payloads[0].url' channel.json)`` and ``vsman_sha=$(jq -r '.channelItems[] | select(.id=="Microsoft.VisualStudio.Manifests.VisualStudio") | .payloads[0].sha256' channel.json)``
|
||||||
- [ ] 7.7 Job step: upload `config/version.json` as an artifact named `version.json.windows` (so it doesn't collide with the Android artifact).
|
- [x] 7.4c `curl -fsSL "$vsman_url" -o vsman.json` (~17 MB)
|
||||||
- [ ] 7.8 In `update_docs_and_create_pr`, add a `download` step for the new artifact and a merge step that combines the Android-emitted `version.json` and the Windows-emitted `version.json` into one. Document the merge order: Android artifact wins for `flutter`/`android` keys, Windows artifact wins for `windows` keys.
|
- [x] 7.4d Verify SHA-256: `echo "$vsman_sha vsman.json" | sha256sum -c -`. Fail the job on mismatch.
|
||||||
|
- [x] 7.4e Extract versions: `jq -r '.packages[] | select(.id=="Microsoft.VisualStudio.Component.VC.CMake.Project") | .version' vsman.json` (and analogously for `Microsoft.VisualStudio.Workload.VCTools`). Document the jq paths in comments so future maintainers can update them if the catalog manifest restructures.
|
||||||
|
- [x] 7.4f Upload both `channel.json` and `vsman.json` as workflow artifacts (90-day retention) for forensic record. This is the mitigation that lets us skip committing the manifest into git (see resolved question in design.md).
|
||||||
|
- [x] 7.5 Job step: write the four resolved values into `config/version.json` using `jq` (preserving existing keys).
|
||||||
|
- [x] 7.6 Job step: validate with `cue vet config/schema.cue -d '#Version' config/version.json`. Fail the job on non-zero exit.
|
||||||
|
- [x] 7.7 Job step: upload `config/version.json` as an artifact named `version.json.windows` (so it doesn't collide with the Android artifact).
|
||||||
|
- [x] 7.8 In `update_docs_and_create_pr`, add a `download` step for the new artifact and a merge step that combines the Android-emitted `version.json` and the Windows-emitted `version.json` into one. Document the merge order: Android artifact wins for `flutter`/`android` keys, Windows artifact wins for `windows` keys.
|
||||||
|
|
||||||
## 8. Validate end-to-end
|
## 8. Validate end-to-end
|
||||||
|
|
||||||
@@ -55,8 +61,8 @@
|
|||||||
|
|
||||||
## 9. Documentation
|
## 9. Documentation
|
||||||
|
|
||||||
- [ ] 9.1 Update `docs/src/windows.mdx` (and the auto-generated `docs/windows.md`) to note that the Windows toolchain versions are pinned in `config/version.json` and refreshed by the monthly upgrade PR.
|
- [x] 9.1 Update `docs/src/windows.mdx` (and the auto-generated `docs/windows.md`) to note that the Windows toolchain versions are pinned in `config/version.json` and refreshed by the monthly upgrade PR.
|
||||||
- [ ] 9.2 Remove now-completed TODO items in `docs/windows.md` referring to "test where is installed" and "snapshot of flutter config" — those are covered by the Pester suite now.
|
- [x] 9.2 Remove now-completed TODO items in `docs/windows.md` referring to "test where is installed" and "snapshot of flutter config" — those are covered by the Pester suite now.
|
||||||
|
|
||||||
## 10. Archive
|
## 10. Archive
|
||||||
|
|
||||||
|
|||||||
@@ -34,6 +34,19 @@ module.exports = async ({ core }) => {
|
|||||||
core.exportVariable('ANDROID_PLATFORM_VERSIONS', platforms)
|
core.exportVariable('ANDROID_PLATFORM_VERSIONS', platforms)
|
||||||
core.exportVariable('ANDROID_NDK_VERSION', data.android.ndk.version)
|
core.exportVariable('ANDROID_NDK_VERSION', data.android.ndk.version)
|
||||||
core.exportVariable('CMAKE_VERSION', data.android.cmake.version)
|
core.exportVariable('CMAKE_VERSION', data.android.cmake.version)
|
||||||
|
core.exportVariable('GIT_VERSION', data.windows.git.version)
|
||||||
|
core.exportVariable(
|
||||||
|
'VS_CMAKE_VERSION',
|
||||||
|
data.windows.vsBuildTools.cmakeProject.version
|
||||||
|
)
|
||||||
|
core.exportVariable(
|
||||||
|
'VS_WIN11SDK_BUILD',
|
||||||
|
data.windows.vsBuildTools.windows11Sdk.build
|
||||||
|
)
|
||||||
|
core.exportVariable(
|
||||||
|
'VS_VCTOOLS_VERSION',
|
||||||
|
data.windows.vsBuildTools.vcTools.version
|
||||||
|
)
|
||||||
core.exportVariable(
|
core.exportVariable(
|
||||||
'IMAGE_REPOSITORY_PATH',
|
'IMAGE_REPOSITORY_PATH',
|
||||||
`${GITHUB_REPOSITORY_OWNER}/${IMAGE_REPOSITORY_NAME}`
|
`${GITHUB_REPOSITORY_OWNER}/${IMAGE_REPOSITORY_NAME}`
|
||||||
|
|||||||
@@ -1,7 +1,10 @@
|
|||||||
|
BeforeAll {
|
||||||
|
$script:manifest = Get-Content -Raw "config\version.json" | ConvertFrom-Json
|
||||||
|
}
|
||||||
|
|
||||||
Describe "Flutter version" {
|
Describe "Flutter version" {
|
||||||
It "Should match the version in config/version.json" {
|
It "Should match the version in config/version.json" {
|
||||||
$manifest = Get-Content "config\version.json" | ConvertFrom-Json
|
$expectedVersion = $script:manifest.flutter.version
|
||||||
$expectedVersion = $manifest.flutter.version
|
|
||||||
|
|
||||||
$firstLine = flutter --version 2>&1 | Select-Object -First 1
|
$firstLine = flutter --version 2>&1 | Select-Object -First 1
|
||||||
$firstLine -match 'Flutter (\S+)' | Out-Null
|
$firstLine -match 'Flutter (\S+)' | Out-Null
|
||||||
@@ -54,6 +57,18 @@ Describe "Flutter doctor" {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Describe "Git version" {
|
||||||
|
It "Should match windows.git.version in config/version.json" {
|
||||||
|
$expectedVersion = $script:manifest.windows.git.version
|
||||||
|
|
||||||
|
$firstLine = git --version 2>&1 | Select-Object -First 1
|
||||||
|
$firstLine -match 'git version (\d+\.\d+\.\d+)' | Out-Null
|
||||||
|
$actualVersion = $Matches[1]
|
||||||
|
|
||||||
|
$actualVersion | Should -Be $expectedVersion -Because "git --version reported '$actualVersion' but config/version.json specifies '$expectedVersion'"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
Describe "Windows file structure tests" {
|
Describe "Windows file structure tests" {
|
||||||
It "Should have specific file content in dart telemetry config" {
|
It "Should have specific file content in dart telemetry config" {
|
||||||
"$env:APPDATA\.dart-tool\dart-flutter-telemetry.config" | Should -FileContentMatchExactly "reporting=0"
|
"$env:APPDATA\.dart-tool\dart-flutter-telemetry.config" | Should -FileContentMatchExactly "reporting=0"
|
||||||
@@ -65,18 +80,21 @@ Describe "Windows file structure tests" {
|
|||||||
}
|
}
|
||||||
|
|
||||||
It "CMake version matches" {
|
It "CMake version matches" {
|
||||||
|
$expectedVersion = $script:manifest.windows.vsBuildTools.cmakeProject.version
|
||||||
$directoryName = $visualStudioPackages | Select-String -CaseSensitive Microsoft.VisualStudio.Component.VC.CMake.Project
|
$directoryName = $visualStudioPackages | Select-String -CaseSensitive Microsoft.VisualStudio.Component.VC.CMake.Project
|
||||||
$directoryName | Should -BeLikeExactly "Microsoft.VisualStudio.Component.VC.CMake.Project,version=*"
|
$directoryName | Should -BeLikeExactly "Microsoft.VisualStudio.Component.VC.CMake.Project,version=$expectedVersion*"
|
||||||
}
|
}
|
||||||
|
|
||||||
It "Windows11SDK version matches" {
|
It "Windows11SDK version matches" {
|
||||||
|
$expectedBuild = $script:manifest.windows.vsBuildTools.windows11Sdk.build
|
||||||
$directoryName = $visualStudioPackages | Select-String -CaseSensitive Microsoft.VisualStudio.Component.Windows11SDK
|
$directoryName = $visualStudioPackages | Select-String -CaseSensitive Microsoft.VisualStudio.Component.Windows11SDK
|
||||||
$directoryName | Should -BeLikeExactly "Microsoft.VisualStudio.Component.Windows11SDK.22621,version=*"
|
$directoryName | Should -BeLikeExactly "Microsoft.VisualStudio.Component.Windows11SDK.$expectedBuild,version=*"
|
||||||
}
|
}
|
||||||
|
|
||||||
It "VCTools version matches" {
|
It "VCTools version matches" {
|
||||||
|
$expectedVersion = $script:manifest.windows.vsBuildTools.vcTools.version
|
||||||
$directoryName = $visualStudioPackages | Select-String -CaseSensitive Microsoft.VisualStudio.Workload.VCTools
|
$directoryName = $visualStudioPackages | Select-String -CaseSensitive Microsoft.VisualStudio.Workload.VCTools
|
||||||
$directoryName | Should -BeLikeExactly "Microsoft.VisualStudio.Workload.VCTools,version=*"
|
$directoryName | Should -BeLikeExactly "Microsoft.VisualStudio.Workload.VCTools,version=$expectedVersion*"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
+8
-4
@@ -4,7 +4,7 @@ FROM mcr.microsoft.com/windows/servercore:ltsc2025@sha256:83374b6927f7945bb0933d
|
|||||||
|
|
||||||
SHELL ["powershell", "-Command", "$ErrorActionPreference = 'Stop'; $ProgressPreference = 'SilentlyContinue';"]
|
SHELL ["powershell", "-Command", "$ErrorActionPreference = 'Stop'; $ProgressPreference = 'SilentlyContinue';"]
|
||||||
|
|
||||||
ARG git_version=2.46.0
|
ARG git_version
|
||||||
ARG git_installation_path="C:\Program Files\Git"
|
ARG git_installation_path="C:\Program Files\Git"
|
||||||
|
|
||||||
# TODO: Find a way to pass $env:USERPROFILE instead of hardcoding C:\Users\ContainerUser. It's hardcoded because environment variables in Windows container works by setting for the Machine scope and that will have $env:USERPROFILE as C:\Users\ContainerAdministrator instead.
|
# TODO: Find a way to pass $env:USERPROFILE instead of hardcoding C:\Users\ContainerUser. It's hardcoded because environment variables in Windows container works by setting for the Machine scope and that will have $env:USERPROFILE as C:\Users\ContainerAdministrator instead.
|
||||||
@@ -64,15 +64,19 @@ RUN git clone `
|
|||||||
flutter create build_app;
|
flutter create build_app;
|
||||||
|
|
||||||
|
|
||||||
|
ARG vs_cmake_version
|
||||||
|
ARG vs_win11sdk_build
|
||||||
|
ARG vs_vctools_version
|
||||||
|
|
||||||
# The user ContainerAdministrator must be used because is the one that has permissions to install with vs_BuildTools
|
# The user ContainerAdministrator must be used because is the one that has permissions to install with vs_BuildTools
|
||||||
USER ContainerAdministrator
|
USER ContainerAdministrator
|
||||||
# Download the Build Tools bootstrapper
|
# Download the Build Tools bootstrapper
|
||||||
# See https://learn.microsoft.com/en-us/visualstudio/install/build-tools-container?view=vs-2022
|
# See https://learn.microsoft.com/en-us/visualstudio/install/build-tools-container?view=vs-2022
|
||||||
RUN Invoke-WebRequest -Uri https://aka.ms/vs/17/release/vs_buildtools.exe -OutFile vs_BuildTools.exe; `
|
RUN Invoke-WebRequest -Uri https://aka.ms/vs/17/release/vs_buildtools.exe -OutFile vs_BuildTools.exe; `
|
||||||
Start-Process vs_BuildTools.exe -ArgumentList '--quiet --wait --norestart --nocache `
|
Start-Process vs_BuildTools.exe -ArgumentList \"--quiet --wait --norestart --nocache `
|
||||||
--add Microsoft.VisualStudio.Component.VC.CMake.Project `
|
--add Microsoft.VisualStudio.Component.VC.CMake.Project `
|
||||||
--add Microsoft.VisualStudio.Component.Windows11SDK.22621 `
|
--add Microsoft.VisualStudio.Component.Windows11SDK.${env:vs_win11sdk_build} `
|
||||||
--add Microsoft.VisualStudio.Workload.VCTools' `
|
--add Microsoft.VisualStudio.Workload.VCTools\" `
|
||||||
-Wait; `
|
-Wait; `
|
||||||
Remove-Item vs_BuildTools.exe;
|
Remove-Item vs_BuildTools.exe;
|
||||||
USER ContainerUser
|
USER ContainerUser
|
||||||
|
|||||||
Reference in New Issue
Block a user