250 lines
11 KiB
YAML
250 lines
11 KiB
YAML
- name: Install Chocolatey
|
|
ansible.builtin.raw: |
|
|
Set-ExecutionPolicy Bypass -Scope Process -Force
|
|
[System.Net.ServicePointManager]::SecurityProtocol = [System.Net.ServicePointManager]::SecurityProtocol -bor 3072
|
|
if (-not (Get-Command choco -ErrorAction SilentlyContinue)) {
|
|
Invoke-Expression ((New-Object System.Net.WebClient).DownloadString('https://community.chocolatey.org/install.ps1'))
|
|
}
|
|
changed_when: true
|
|
|
|
- name: Install Windows toolchain packages
|
|
ansible.windows.win_shell: |
|
|
$ErrorActionPreference = "Stop"
|
|
$packages = @()
|
|
$packages += 'git'
|
|
if ({{ toolchains.vscode | bool | ternary('$true', '$false') }}) { $packages += 'vscode' }
|
|
if ({{ toolchains.android_studio | bool | ternary('$true', '$false') }}) { $packages += 'androidstudio' }
|
|
if ({{ toolchains.codex | bool | ternary('$true', '$false') }}) {
|
|
$packages += 'vcredist140'
|
|
$packages += 'nodejs-lts'
|
|
}
|
|
if ({{ toolchains.flutter | bool | ternary('$true', '$false') }}) {
|
|
$packages += @({{ cloud_dev_desktop_windows_visualstudio_packages | map('to_json') | join(', ') }})
|
|
}
|
|
if (({{ toolchains.dart | bool | ternary('$true', '$false') }}) -and (-not {{ toolchains.flutter | bool | ternary('$true', '$false') }})) {
|
|
$packages += 'dart-sdk'
|
|
}
|
|
foreach ($pkg in ($packages | Select-Object -Unique)) {
|
|
choco install $pkg -y --no-progress
|
|
}
|
|
changed_when: true
|
|
|
|
- name: Install Codex CLI globally on Windows
|
|
ansible.windows.win_shell: |
|
|
$ErrorActionPreference = "Stop"
|
|
$machinePath = [Environment]::GetEnvironmentVariable('Path', 'Machine')
|
|
$userPath = [Environment]::GetEnvironmentVariable('Path', 'User')
|
|
$npmUserBin = if ($env:APPDATA) { Join-Path $env:APPDATA 'npm' } else { '' }
|
|
$extraPaths = @(
|
|
$npmUserBin,
|
|
'C:\Program Files\nodejs',
|
|
'C:\ProgramData\chocolatey\bin'
|
|
) | Where-Object { $_ }
|
|
$env:Path = (($machinePath, $userPath, ($extraPaths -join ';')) -join ';')
|
|
npm install -g @openai/codex
|
|
changed_when: true
|
|
when: toolchains.codex | bool
|
|
|
|
- name: Enable Windows virtualization features required for Android emulators
|
|
ansible.windows.win_optional_feature:
|
|
name: "{{ cloud_dev_desktop_windows_android_optional_features }}"
|
|
state: present
|
|
include_parent: true
|
|
register: windows_android_virtualization_features
|
|
when: toolchains.android_studio | bool
|
|
|
|
- name: Reboot Windows after enabling Android virtualization features
|
|
ansible.windows.win_reboot:
|
|
reboot_timeout: 3600
|
|
connect_timeout: 30
|
|
post_reboot_delay: 60
|
|
when:
|
|
- toolchains.android_studio | bool
|
|
- windows_android_virtualization_features.reboot_required | default(false)
|
|
|
|
- name: Install Android SDK command-line tools on Windows
|
|
ansible.windows.win_shell: |
|
|
$ErrorActionPreference = "Stop"
|
|
$androidSdkRoot = Join-Path $env:LOCALAPPDATA 'Android\Sdk'
|
|
$cmdlineToolsRoot = Join-Path $androidSdkRoot 'cmdline-tools'
|
|
$cmdlineToolsLatest = Join-Path $cmdlineToolsRoot 'latest'
|
|
$cmdlineToolsBin = Join-Path $cmdlineToolsLatest 'bin'
|
|
$javaHome = 'C:\Program Files\Android\Android Studio\jbr'
|
|
New-Item -ItemType Directory -Force -Path $androidSdkRoot, $cmdlineToolsRoot | Out-Null
|
|
if (-not (Test-Path (Join-Path $cmdlineToolsBin 'sdkmanager.bat'))) {
|
|
$zipPath = Join-Path $env:TEMP 'android-commandlinetools.zip'
|
|
$extractDir = Join-Path $env:TEMP 'android-commandlinetools'
|
|
if (Test-Path $extractDir) {
|
|
Remove-Item -Recurse -Force $extractDir
|
|
}
|
|
Invoke-WebRequest -UseBasicParsing -Uri '{{ cloud_dev_desktop_windows_android_cmdline_tools_url }}' -OutFile $zipPath
|
|
Expand-Archive -LiteralPath $zipPath -DestinationPath $extractDir -Force
|
|
if (Test-Path $cmdlineToolsLatest) {
|
|
Remove-Item -Recurse -Force $cmdlineToolsLatest
|
|
}
|
|
Move-Item -Path (Join-Path $extractDir 'cmdline-tools') -Destination $cmdlineToolsLatest
|
|
}
|
|
if (Test-Path $javaHome) {
|
|
[Environment]::SetEnvironmentVariable('JAVA_HOME', $javaHome, 'User')
|
|
$env:JAVA_HOME = $javaHome
|
|
}
|
|
[Environment]::SetEnvironmentVariable('ANDROID_HOME', $androidSdkRoot, 'User')
|
|
[Environment]::SetEnvironmentVariable('ANDROID_SDK_ROOT', $androidSdkRoot, 'User')
|
|
$userPath = [Environment]::GetEnvironmentVariable('Path', 'User')
|
|
$androidPathEntries = @(
|
|
$androidSdkRoot,
|
|
(Join-Path $androidSdkRoot 'platform-tools'),
|
|
(Join-Path $androidSdkRoot 'emulator'),
|
|
$cmdlineToolsBin
|
|
)
|
|
if ($env:JAVA_HOME) {
|
|
$androidPathEntries += (Join-Path $env:JAVA_HOME 'bin')
|
|
}
|
|
$userPathParts = @($userPath -split ';') | Where-Object { $_ }
|
|
foreach ($entry in $androidPathEntries) {
|
|
if (-not ($userPathParts -contains $entry)) {
|
|
$userPathParts += $entry
|
|
}
|
|
}
|
|
$newUserPath = ($userPathParts | Select-Object -Unique) -join ';'
|
|
[Environment]::SetEnvironmentVariable('Path', $newUserPath, 'User')
|
|
$env:ANDROID_HOME = $androidSdkRoot
|
|
$env:ANDROID_SDK_ROOT = $androidSdkRoot
|
|
$env:Path = ([Environment]::GetEnvironmentVariable('Path', 'Machine') + ';' + $newUserPath + ';C:\ProgramData\chocolatey\bin')
|
|
$sdkmanager = Join-Path $cmdlineToolsBin 'sdkmanager.bat'
|
|
$sdkPackages = @(
|
|
'platform-tools',
|
|
'platforms;android-{{ cloud_dev_desktop_windows_android_sdk_api_level }}',
|
|
'build-tools;{{ cloud_dev_desktop_windows_android_build_tools_version }}',
|
|
'emulator',
|
|
'{{ cloud_dev_desktop_windows_android_system_image }}'
|
|
)
|
|
1..32 | ForEach-Object { 'y' } | & $sdkmanager --sdk_root="$androidSdkRoot" --licenses | Out-Null
|
|
if ($LASTEXITCODE -ne 0) {
|
|
throw "Android SDK license acceptance failed with exit code $LASTEXITCODE"
|
|
}
|
|
& $sdkmanager --sdk_root="$androidSdkRoot" @sdkPackages
|
|
if ($LASTEXITCODE -ne 0) {
|
|
throw "Android SDK package installation failed with exit code $LASTEXITCODE"
|
|
}
|
|
$avdmanager = Join-Path $cmdlineToolsBin 'avdmanager.bat'
|
|
$avdName = '{{ cloud_dev_desktop_windows_android_avd_name }}'
|
|
$avdPath = Join-Path $env:USERPROFILE ".android\avd\$avdName.avd"
|
|
if (-not (Test-Path $avdPath)) {
|
|
'no' | & $avdmanager create avd --force -n $avdName -k '{{ cloud_dev_desktop_windows_android_system_image }}' | Out-Null
|
|
if ($LASTEXITCODE -ne 0) {
|
|
throw "Android AVD creation failed with exit code $LASTEXITCODE"
|
|
}
|
|
}
|
|
changed_when: true
|
|
when: toolchains.android_studio | bool
|
|
|
|
- name: Probe installed Flutter SDK on Windows
|
|
ansible.windows.win_shell: |
|
|
$ErrorActionPreference = "Stop"
|
|
$flutterBat = Join-Path '{{ cloud_dev_desktop_windows_flutter_install_root }}' 'bin\flutter.bat'
|
|
if (Test-Path $flutterBat) {
|
|
& $flutterBat --version
|
|
}
|
|
register: windows_flutter_version_probe
|
|
changed_when: false
|
|
failed_when: false
|
|
when: toolchains.flutter | bool
|
|
|
|
- name: Install Flutter SDK on Windows
|
|
ansible.windows.win_shell: |
|
|
$ErrorActionPreference = "Stop"
|
|
$flutterRoot = '{{ cloud_dev_desktop_windows_flutter_install_root }}'
|
|
$installRoot = Split-Path -Parent $flutterRoot
|
|
$zipPath = Join-Path $env:TEMP 'flutter-windows-sdk.zip'
|
|
New-Item -ItemType Directory -Force -Path $installRoot | Out-Null
|
|
if (Test-Path $flutterRoot) {
|
|
Remove-Item -Recurse -Force $flutterRoot
|
|
}
|
|
Invoke-WebRequest -UseBasicParsing -Uri '{{ cloud_dev_desktop_windows_flutter_sdk_url }}' -OutFile $zipPath
|
|
Expand-Archive -LiteralPath $zipPath -DestinationPath $installRoot -Force
|
|
if (-not (Test-Path (Join-Path $flutterRoot 'bin\flutter.bat'))) {
|
|
throw "Flutter SDK install failed: missing $(Join-Path $flutterRoot 'bin\flutter.bat')"
|
|
}
|
|
changed_when: true
|
|
when:
|
|
- toolchains.flutter | bool
|
|
- windows_flutter_version_probe.rc != 0 or ("Flutter " ~ cloud_dev_desktop_windows_flutter_version ~ " ") not in windows_flutter_version_probe.stdout
|
|
|
|
- name: Configure Flutter on Windows
|
|
ansible.windows.win_shell: |
|
|
$ErrorActionPreference = "Stop"
|
|
$machinePath = [Environment]::GetEnvironmentVariable('Path', 'Machine')
|
|
$userPath = [Environment]::GetEnvironmentVariable('Path', 'User')
|
|
$npmUserBin = if ($env:APPDATA) { Join-Path $env:APPDATA 'npm' } else { '' }
|
|
$extraPaths = @(
|
|
$npmUserBin,
|
|
'C:\Program Files\nodejs',
|
|
'{{ cloud_dev_desktop_windows_flutter_install_root }}\bin',
|
|
'C:\Program Files\Microsoft VS Code\bin',
|
|
'C:\ProgramData\chocolatey\bin'
|
|
) | Where-Object { $_ }
|
|
$env:Path = (($machinePath, $userPath, ($extraPaths -join ';')) -join ';')
|
|
if ({{ toolchains.android_studio | bool | ternary('$true', '$false') }}) {
|
|
flutter config --android-sdk (Join-Path $env:LOCALAPPDATA 'Android\Sdk')
|
|
}
|
|
flutter config --enable-windows-desktop
|
|
flutter doctor
|
|
changed_when: true
|
|
when: toolchains.flutter | bool
|
|
|
|
- name: Verify Windows desktop toolchain versions
|
|
ansible.builtin.raw: |
|
|
$ErrorActionPreference = "Stop"
|
|
$machinePath = [Environment]::GetEnvironmentVariable('Path', 'Machine')
|
|
$userPath = [Environment]::GetEnvironmentVariable('Path', 'User')
|
|
$npmUserBin = if ($env:APPDATA) { Join-Path $env:APPDATA 'npm' } else { '' }
|
|
$extraPaths = @(
|
|
$npmUserBin,
|
|
'C:\Program Files\nodejs',
|
|
'{{ cloud_dev_desktop_windows_flutter_install_root }}\bin',
|
|
'C:\Program Files\Microsoft VS Code\bin',
|
|
'C:\ProgramData\chocolatey\bin'
|
|
) | Where-Object { $_ }
|
|
$env:Path = (($machinePath, $userPath, ($extraPaths -join ';')) -join ';')
|
|
$nodeMajor = [int]((node --version).Trim().TrimStart('v').Split('.')[0])
|
|
if ($nodeMajor -lt 22) {
|
|
throw "Node.js 22+ is required, found $(node --version)"
|
|
}
|
|
if ({{ toolchains.codex | bool | ternary('$true', '$false') }}) {
|
|
$codexCmd = Join-Path $env:APPDATA 'npm\codex.cmd'
|
|
if (-not (Test-Path $codexCmd)) {
|
|
throw "Missing Codex CLI launcher at $codexCmd"
|
|
}
|
|
$codexCmdLine = '"' + $codexCmd + '" --version'
|
|
cmd.exe /d /c $codexCmdLine | Out-Null
|
|
if ($LASTEXITCODE -ne 0) {
|
|
throw "Codex CLI version probe failed with exit code $LASTEXITCODE"
|
|
}
|
|
}
|
|
if ({{ toolchains.vscode | bool | ternary('$true', '$false') }}) {
|
|
Get-Command code | Out-Null
|
|
}
|
|
if ({{ toolchains.android_studio | bool | ternary('$true', '$false') }}) {
|
|
if (-not (Test-Path 'C:\Program Files\Android\Android Studio\bin\studio64.exe')) {
|
|
throw 'Missing Android Studio executable at C:\Program Files\Android\Android Studio\bin\studio64.exe'
|
|
}
|
|
}
|
|
if ({{ toolchains.flutter | bool | ternary('$true', '$false') }}) {
|
|
flutter --version | Out-Null
|
|
}
|
|
changed_when: false
|
|
|
|
- name: Create Windows desktop metadata directory
|
|
ansible.builtin.raw: |
|
|
$ErrorActionPreference = "Stop"
|
|
New-Item -ItemType Directory -Force -Path 'C:\cloud-dev-desktop' | Out-Null
|
|
@"
|
|
PROFILE_NAME={{ profile_name }}
|
|
PROVIDER={{ provider }}
|
|
OWNER={{ owner }}
|
|
PURPOSE={{ purpose }}
|
|
EXPIRES_AT={{ vars.get('cloud_vm_expires_at', '') }}
|
|
"@ | Set-Content -Encoding ASCII 'C:\cloud-dev-desktop\profile.env'
|
|
changed_when: true
|