Skip to content

Commit 4b82a0a

Browse files
committed
fix: devpack test
1 parent f644eff commit 4b82a0a

1 file changed

Lines changed: 101 additions & 12 deletions

File tree

.github/workflows/verify-devpack-scripts.yml

Lines changed: 101 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@ on:
1818
- release
1919
- aka
2020
- brew
21+
- winget
2122
telemetry:
2223
description: "Send installer telemetry during this validation run"
2324
required: true
@@ -93,7 +94,7 @@ jobs:
9394
throw 'Azure CLI is still available after removal'
9495
}
9596
96-
- name: Install VS Code and Copilot CLI
97+
- name: Install VS Code, Copilot CLI, and Claude shim
9798
if: matrix.scenario == 'with-code'
9899
shell: pwsh
99100
run: |
@@ -112,6 +113,11 @@ jobs:
112113
if (-not $copilotPackage) { throw 'GitHub Copilot CLI package directory not found' }
113114
Add-Content -Path $env:GITHUB_PATH -Value $copilotPackage.FullName
114115
116+
$claudeBin = Join-Path $env:RUNNER_TEMP 'claude-bin'
117+
New-Item -ItemType Directory -Force -Path $claudeBin | Out-Null
118+
Set-Content -Path (Join-Path $claudeBin 'claude.cmd') -Value "@echo off`r`nexit /b 0`r`n" -NoNewline
119+
Add-Content -Path $env:GITHUB_PATH -Value $claudeBin
120+
115121
- name: Confirm Copilot CLI is absent
116122
if: matrix.scenario != 'with-code'
117123
shell: pwsh
@@ -121,6 +127,7 @@ jobs:
121127
}
122128
123129
- name: Download and verify signed bootstrap
130+
if: env.INSTALL_SOURCE != 'winget'
124131
shell: pwsh
125132
run: |
126133
$ErrorActionPreference = 'Stop'
@@ -165,7 +172,7 @@ jobs:
165172
"SIGNER_THUMBPRINT=$($signature.SignerCertificate.Thumbprint)" | Out-File -FilePath $env:GITHUB_ENV -Encoding utf8 -Append
166173
"SIGNER_WAS_TRUSTED=$wasTrusted" | Out-File -FilePath $env:GITHUB_ENV -Encoding utf8 -Append
167174
168-
- name: Install through PowerShell bootstrap
175+
- name: Install DevPack
169176
shell: pwsh
170177
run: |
171178
$ErrorActionPreference = 'Stop'
@@ -177,16 +184,48 @@ jobs:
177184
if ($env:INSTALL_SOURCE -eq 'aka') {
178185
& powershell.exe -ExecutionPolicy AllSigned -Command `
179186
"Invoke-RestMethod 'https://aka.ms/foundry-devpack-install.ps1' | Invoke-Expression"
187+
} elseif ($env:INSTALL_SOURCE -eq 'winget') {
188+
$installerLog = Join-Path $env:RUNNER_TEMP 'foundry-devpack.log'
189+
$expectedVersion = $env:RELEASE_TAG -replace '^devpack-installer-', ''
190+
winget install --exact --id Microsoft.FoundryDevPack `
191+
--version $expectedVersion --source winget --force --silent `
192+
--disable-interactivity --accept-package-agreements --accept-source-agreements `
193+
--log $installerLog
180194
} else {
195+
$installerLog = Join-Path $env:RUNNER_TEMP 'foundry-devpack.log'
181196
& powershell.exe -NoProfile -NonInteractive -ExecutionPolicy AllSigned `
182-
-File $env:DEVPACK_SCRIPT --verbose
197+
-File $env:DEVPACK_SCRIPT --verbose --log $installerLog
198+
}
199+
if ($LASTEXITCODE -ne 0) { throw "DevPack install exited $LASTEXITCODE" }
200+
if ($env:INSTALL_SOURCE -in @('release', 'winget')) {
201+
if (-not (Test-Path $installerLog)) { throw 'installer log was not created' }
202+
$logText = Get-Content $installerLog -Raw
203+
if ($logText -notmatch 'Finished \(failed=0, cancelled=False\)') {
204+
throw 'installer log does not contain the successful run result'
205+
}
183206
}
184-
if ($LASTEXITCODE -ne 0) { throw "PowerShell bootstrap exited $LASTEXITCODE" }
185207
$leaked = @(Get-ChildItem $temp -Directory -Filter 'foundry-devpack-*' -ErrorAction SilentlyContinue)
186208
if ($leaked.Count) {
187209
throw "bootstrap left temporary directories: $($leaked.FullName -join ', ')"
188210
}
189211
212+
- name: Verify winget repair
213+
if: env.INSTALL_SOURCE == 'winget'
214+
shell: pwsh
215+
run: |
216+
$ErrorActionPreference = 'Stop'
217+
$repairLog = Join-Path $env:RUNNER_TEMP 'foundry-devpack-repair.log'
218+
$expectedVersion = $env:RELEASE_TAG -replace '^devpack-installer-', ''
219+
winget repair --exact --id Microsoft.FoundryDevPack `
220+
--version $expectedVersion --source winget --force --silent `
221+
--disable-interactivity --accept-package-agreements --accept-source-agreements `
222+
--log $repairLog
223+
if ($LASTEXITCODE -ne 0) { throw "winget repair exited $LASTEXITCODE" }
224+
if (-not (Test-Path $repairLog)) { throw 'repair log was not created' }
225+
if ((Get-Content $repairLog -Raw) -notmatch 'Finished \(failed=0, cancelled=False\)') {
226+
throw 'repair log does not contain the successful run result'
227+
}
228+
190229
- name: Verify installed components
191230
shell: pwsh
192231
run: |
@@ -223,6 +262,18 @@ jobs:
223262
throw 'Foundry Copilot plugin not installed'
224263
}
225264
265+
$canonicalSkill = Join-Path $env:USERPROFILE '.agents\skills\microsoft-foundry'
266+
$claudeSkill = Join-Path $env:USERPROFILE '.claude\skills\microsoft-foundry'
267+
$item = Get-Item -LiteralPath $claudeSkill -Force
268+
if (-not $item.LinkType) { throw 'Claude Code skill is not a link' }
269+
$resolved = $item.ResolveLinkTarget($true)
270+
if (-not $resolved -or -not $resolved.FullName.Equals($canonicalSkill, [StringComparison]::OrdinalIgnoreCase)) {
271+
throw "Claude Code skill link does not target $canonicalSkill"
272+
}
273+
if (Test-Path (Join-Path $claudeSkill '.foundry-devpack-copy')) {
274+
throw 'Claude Code skill unexpectedly used the copy fallback'
275+
}
276+
226277
- name: Verify ARP and uninstall
227278
shell: pwsh
228279
run: |
@@ -232,14 +283,30 @@ jobs:
232283
$entry = Get-ItemProperty $key
233284
if (-not (Test-Path $entry.InstallLocation -PathType Container)) { throw 'ARP install location not found' }
234285
if (-not (Test-Path $entry.DisplayIcon -PathType Leaf)) { throw 'persisted installer not found' }
286+
$binarySignature = Get-AuthenticodeSignature $entry.DisplayIcon
287+
if ($binarySignature.Status -ne 'Valid') {
288+
throw "invalid installer signature: $($binarySignature.Status) $($binarySignature.StatusMessage)"
289+
}
290+
if ($binarySignature.SignerCertificate.Subject -notlike 'CN=Microsoft Corporation,*') {
291+
throw "unexpected installer signer: $($binarySignature.SignerCertificate.Subject)"
292+
}
293+
$expectedVersion = $env:RELEASE_TAG -replace '^devpack-installer-', ''
294+
if ($entry.DisplayVersion -ne $expectedVersion) {
295+
throw "ARP version $($entry.DisplayVersion), expected $expectedVersion"
296+
}
235297
Write-Host "ARP: $($entry.DisplayName) $($entry.DisplayVersion)"
236298
237-
& $entry.DisplayIcon uninstall
299+
if ($env:INSTALL_SOURCE -eq 'winget') {
300+
winget uninstall --exact --id Microsoft.FoundryDevPack --source winget `
301+
--silent --disable-interactivity --accept-source-agreements
302+
} else {
303+
& $entry.DisplayIcon uninstall
304+
}
238305
if ($LASTEXITCODE -ne 0) { throw "uninstall exited $LASTEXITCODE" }
239306
if (Test-Path $key) { throw 'ARP entry still present after uninstall' }
240307
241308
- name: Remove trusted publisher and bootstrap
242-
if: always()
309+
if: always() && env.INSTALL_SOURCE != 'winget'
243310
shell: pwsh
244311
run: |
245312
if ($env:SIGNER_THUMBPRINT -and $env:SIGNER_WAS_TRUSTED -eq 'False') {
@@ -259,7 +326,7 @@ jobs:
259326
Remove-Item $env:DEVPACK_SCRIPT -Force -ErrorAction SilentlyContinue
260327
261328
linux:
262-
if: ${{ (startsWith(github.event.release.tag_name, 'devpack-installer-') || startsWith(inputs.release_tag, 'devpack-installer-')) && (github.event_name == 'release' || inputs.install_source != 'brew') }}
329+
if: ${{ (startsWith(github.event.release.tag_name, 'devpack-installer-') || startsWith(inputs.release_tag, 'devpack-installer-')) && (github.event_name == 'release' || (inputs.install_source != 'brew' && inputs.install_source != 'winget')) }}
263330
name: linux ${{ matrix.platform.arch }} ${{ matrix.scenario }} (${{ inputs.install_source || 'release' }}, telemetry=${{ inputs.telemetry || false }})
264331
runs-on: ${{ matrix.platform.os }}
265332
timeout-minutes: 30
@@ -293,7 +360,7 @@ jobs:
293360
exit 1
294361
fi
295362
296-
- name: Install VS Code and Copilot CLI
363+
- name: Install VS Code, Copilot CLI, and Claude shim
297364
if: matrix.scenario == 'with-code'
298365
shell: bash
299366
run: |
@@ -306,6 +373,10 @@ jobs:
306373
sudo apt-get install -y code
307374
curl -fsSL https://gh.io/copilot-install | bash
308375
echo "$HOME/.local/bin" >> "$GITHUB_PATH"
376+
mkdir -p "$RUNNER_TEMP/claude-bin"
377+
printf '#!/bin/sh\nexit 0\n' > "$RUNNER_TEMP/claude-bin/claude"
378+
chmod +x "$RUNNER_TEMP/claude-bin/claude"
379+
echo "$RUNNER_TEMP/claude-bin" >> "$GITHUB_PATH"
309380
310381
- name: Confirm Copilot CLI is absent
311382
if: matrix.scenario != 'with-code'
@@ -342,7 +413,11 @@ jobs:
342413
if [ "$INSTALL_SOURCE" = "aka" ]; then
343414
curl -fsSL https://aka.ms/foundry-devpack-install.sh | bash
344415
else
345-
bash "$DEVPACK_SCRIPT" --verbose
416+
bash "$DEVPACK_SCRIPT" --verbose --log "$RUNNER_TEMP/foundry-devpack.log"
417+
fi
418+
if [ "$INSTALL_SOURCE" = "release" ]; then
419+
test -f "$RUNNER_TEMP/foundry-devpack.log"
420+
grep -F 'Finished (failed=0, cancelled=False)' "$RUNNER_TEMP/foundry-devpack.log"
346421
fi
347422
if find "$temp" -mindepth 1 -maxdepth 1 -type d -name 'foundry-devpack-*' -print -quit | grep -q .; then
348423
echo "error: bootstrap left temporary directories under $temp" >&2
@@ -371,14 +446,17 @@ jobs:
371446
code --list-extensions | grep -qi 'ms-windows-ai-studio.windows-ai-studio'
372447
copilot plugin list --no-color | tee "$RUNNER_TEMP/copilot-plugins.txt"
373448
grep -qi 'microsoft-foundry' "$RUNNER_TEMP/copilot-plugins.txt"
449+
test -L "$HOME/.claude/skills/microsoft-foundry"
450+
test "$(readlink "$HOME/.claude/skills/microsoft-foundry")" = "$HOME/.agents/skills/microsoft-foundry"
451+
test ! -e "$HOME/.claude/skills/microsoft-foundry/.foundry-devpack-copy"
374452
375453
- name: Remove bootstrap
376454
if: always()
377455
shell: bash
378456
run: rm -f "$DEVPACK_SCRIPT"
379457

380458
macos:
381-
if: ${{ startsWith(github.event.release.tag_name, 'devpack-installer-') || startsWith(inputs.release_tag, 'devpack-installer-') }}
459+
if: ${{ (startsWith(github.event.release.tag_name, 'devpack-installer-') || startsWith(inputs.release_tag, 'devpack-installer-')) && (github.event_name == 'release' || inputs.install_source != 'winget') }}
382460
name: macos ${{ matrix.platform.arch }} ${{ matrix.scenario }} (${{ inputs.install_source || 'release' }}, telemetry=${{ inputs.telemetry || false }})
383461
runs-on: ${{ matrix.platform.os }}
384462
timeout-minutes: 30
@@ -416,7 +494,7 @@ jobs:
416494
exit 1
417495
fi
418496
419-
- name: Install VS Code and Copilot CLI
497+
- name: Install VS Code, Copilot CLI, and Claude shim
420498
if: matrix.scenario == 'with-code'
421499
shell: bash
422500
run: |
@@ -425,6 +503,10 @@ jobs:
425503
brew install --cask copilot-cli
426504
sudo mkdir -p /usr/local/bin
427505
sudo ln -sf '/Applications/Visual Studio Code.app/Contents/Resources/app/bin/code' /usr/local/bin/code
506+
mkdir -p "$RUNNER_TEMP/claude-bin"
507+
printf '#!/bin/sh\nexit 0\n' > "$RUNNER_TEMP/claude-bin/claude"
508+
chmod +x "$RUNNER_TEMP/claude-bin/claude"
509+
echo "$RUNNER_TEMP/claude-bin" >> "$GITHUB_PATH"
428510
429511
- name: Confirm Copilot CLI is absent
430512
if: matrix.scenario != 'with-code'
@@ -470,13 +552,17 @@ jobs:
470552
foundry-devpack --version | grep -F "$expected_version"
471553
;;
472554
release)
473-
bash "$DEVPACK_SCRIPT" --verbose
555+
bash "$DEVPACK_SCRIPT" --verbose --log "$RUNNER_TEMP/foundry-devpack.log"
474556
;;
475557
*)
476558
echo "error: unsupported install source: $INSTALL_SOURCE" >&2
477559
exit 1
478560
;;
479561
esac
562+
if [ "$INSTALL_SOURCE" = "release" ]; then
563+
test -f "$RUNNER_TEMP/foundry-devpack.log"
564+
grep -F 'Finished (failed=0, cancelled=False)' "$RUNNER_TEMP/foundry-devpack.log"
565+
fi
480566
if find "$temp" -mindepth 1 -maxdepth 1 -type d -name 'foundry-devpack-*' -print -quit | grep -q .; then
481567
echo "error: bootstrap left temporary directories under $temp" >&2
482568
find "$temp" -mindepth 1 -maxdepth 1 -type d -name 'foundry-devpack-*' -print >&2
@@ -504,6 +590,9 @@ jobs:
504590
code --list-extensions | grep -qi 'ms-windows-ai-studio.windows-ai-studio'
505591
copilot plugin list --no-color | tee "$RUNNER_TEMP/copilot-plugins.txt"
506592
grep -qi 'microsoft-foundry' "$RUNNER_TEMP/copilot-plugins.txt"
593+
test -L "$HOME/.claude/skills/microsoft-foundry"
594+
test "$(readlink "$HOME/.claude/skills/microsoft-foundry")" = "$HOME/.agents/skills/microsoft-foundry"
595+
test ! -e "$HOME/.claude/skills/microsoft-foundry/.foundry-devpack-copy"
507596
508597
- name: Uninstall Homebrew cask
509598
if: env.INSTALL_SOURCE == 'brew'

0 commit comments

Comments
 (0)