Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
@@ -0,0 +1,115 @@
id: runner-environment-519
title: 'Azure Artifacts Credential Provider Removed from Ubuntu Runners — NuGet Private Feed Auth Fails'
category: runner-environment
severity: error
tags:
- azure-artifacts
- nuget
- credential-provider
- ubuntu
- dotnet
- private-feed
- regression
- june-2026
patterns:
- regex: 'Path to the Azure Artifacts Credential Provider is null or empty'
flags: 'i'
- regex: 'CredentialProvider\.Microsoft.*not found|artifacts-credprovider.*missing'
flags: 'i'
- regex: 'Unable to obtain credentials for feed.*Azure Artifacts'
flags: 'i'
- regex: 'Response status code does not indicate success.*401.*nuget|nuget.*401.*azure\.artifacts'
flags: 'i'
error_messages:
- "Value cannot be null. (Parameter 'Path to the Azure Artifacts Credential Provider is null or empty. See https://github.com/NuGet/Home/wiki/NuGet-cross-plat-authentication-plugin#plugin-installation-and-discovery to set up the Credential Provider.')"
- "Unable to obtain credentials for feed 'https://pkgs.dev.azure.com/...'"
- "CredentialProvider.Microsoft.exe: plugin not found"
root_cause: |
As of runner image build `20260611.554` (deployed June 17, 2026), the Azure Artifacts
Credential Provider (`Microsoft.Net.Http.Headers.CredentialProvider.Microsoft.exe`) was
silently removed from the pre-installed tool set on all GitHub-hosted Ubuntu runner images.
Previously it was bundled at `~/.nuget/plugins/netcore/CredentialProvider.Microsoft/`.

Affected runner labels (as of June 17, 2026):
- `ubuntu-22.04`, `ubuntu-22.04-arm`
- `ubuntu-24.04`, `ubuntu-24.04-arm`
- `ubuntu-26.04`, `ubuntu-26.04-arm`
- `ubuntu-latest`, `ubuntu-slim`

macOS and Windows runners may be affected as well (see actions/runner-images#14270).

Any workflow that uses `dotnet restore`, `nuget restore`, or `msbuild /restore` against a
private Azure Artifacts NuGet feed relies on this provider for MSAL-based authentication.
The restore fails with HTTP 401 when the provider is absent, even if `NUGET_CREDENTIALPROVIDERS_PATH`
is set or `nugetAuthenticate@1` task is configured — that task only configures credentials, it
does not install the provider binary.
fix: |
Add an explicit install step for the Azure Artifacts Credential Provider **before** any NuGet
restore or build step:

```bash
sh -c "$(curl -fsSL https://aka.ms/install-artifacts-credprovider.sh)"
```

This installs the provider to `~/.nuget/plugins/netcore/CredentialProvider.Microsoft/`.
Subsequent `dotnet restore`, `nuget restore`, and `msbuild /restore` commands will find and
use it automatically.

For workflows using `NuGetAuthenticate@1` or similar Azure DevOps task wrappers, the install
step must still be added — those tasks configure credentials but don't install the binary.
fix_code:
- language: yaml
label: 'Install Azure Artifacts Credential Provider before dotnet restore'
code: |
jobs:
build:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v6

- name: Install Azure Artifacts Credential Provider
run: sh -c "$(curl -fsSL https://aka.ms/install-artifacts-credprovider.sh)"

- name: Restore NuGet packages
run: dotnet restore
env:
NUGET_CREDENTIALPROVIDERS_PATH: "${{ runner.temp }}/plugins/netcore"
VSS_NUGET_EXTERNAL_FEED_ENDPOINTS: |
{
"endpointCredentials": [{
"endpoint": "https://pkgs.dev.azure.com/YOUR_ORG/_packaging/YOUR_FEED/nuget/v3/index.json",
"username": "any",
"password": "${{ secrets.AZURE_DEVOPS_PAT }}"
}]
}

- name: Build
run: dotnet build --no-restore
- language: yaml
label: 'Reusable composite step — install credential provider once'
code: |
# .github/actions/install-azartifacts-cred/action.yml
name: Install Azure Artifacts Credential Provider
description: Installs CredentialProvider.Microsoft on the runner
runs:
using: composite
steps:
- name: Install credential provider
shell: bash
run: sh -c "$(curl -fsSL https://aka.ms/install-artifacts-credprovider.sh)"
prevention:
- "Do not assume the Azure Artifacts Credential Provider is pre-installed on Ubuntu runners after June 17, 2026"
- "Add the `install-artifacts-credprovider.sh` install step as the first step in any job that restores NuGet packages from private Azure Artifacts feeds"
- "For Windows runners, use the equivalent PowerShell script: `iex \"& { $(irm https://aka.ms/install-artifacts-credprovider.ps1) }\"`"
- "Pin the install script URL from `aka.ms` (Microsoft short link) rather than hardcoding the GitHub release URL — Microsoft keeps the alias stable"
docs:
- url: 'https://github.com/actions/runner-images/issues/14270'
label: 'runner-images#14270: Azure Artifacts Credential Provider missing on Ubuntu Runner'
- url: 'https://github.com/microsoft/artifacts-credprovider'
label: 'microsoft/artifacts-credprovider — official provider repo'
- url: 'https://aka.ms/install-artifacts-credprovider.sh'
label: 'Official install script (Linux/macOS)'
- url: 'https://github.com/NuGet/Home/wiki/NuGet-cross-plat-authentication-plugin#plugin-installation-and-discovery'
label: 'NuGet cross-platform authentication plugin discovery guide'
- url: 'https://learn.microsoft.com/en-us/azure/devops/artifacts/nuget/nuget-exe?view=azure-devops'
label: 'Azure Artifacts: NuGet restore authentication guide'
Original file line number Diff line number Diff line change
@@ -0,0 +1,131 @@
id: runner-environment-520
title: 'Windows 11 ARM64 `wsl.exe --update` Prompt on Logon Steals Focus — GUI Automation Breaks'
category: runner-environment
severity: error
tags:
- windows-11-arm
- arm64
- wsl
- gui
- focus
- regression
- browser-automation
- playwright
- selenium
- june-2026
patterns:
- regex: 'wsl\.exe.*--update.*--confirm.*--prompt-before-exit'
flags: 'i'
- regex: 'windows.terminal.*stole.*focus|focus.*stolen.*wsl|wsl.*update.*window.*focus'
flags: 'i'
- regex: 'Timeout.*waiting for.*browser.*focus|element.*not.*focused.*arm64'
flags: 'i'
error_messages:
- "Error: Timeout 30000ms exceeded. waiting for element to be focused."
- "browserType.launch: Target page, context or browser has been closed"
- "wsl.exe --update --confirm --prompt-before-exit"
root_cause: |
Runner image builds shipping from late June 2026 for `windows-11-arm` introduced a Windows
startup logon trigger that runs `wsl.exe --update --confirm --prompt-before-exit`. This spawns
a visible Windows Terminal window that:
1. Takes foreground focus away from the test runner process.
2. Waits up to 60 seconds for a user interaction that never arrives in CI.
3. Remains topmost, preventing GUI automation frameworks from interacting with the window under test.

Effects on common frameworks:
- **Playwright** (headed mode): `page.click()` misses because the WSL window has focus.
`browserType.launch()` may fail with "target has been closed" if the runner's session
times out waiting for the WSL prompt to dismiss.
- **Selenium / WebDriver**: `driver.findElement().click()` acts on wrong window; element
interaction assertions fail.
- **WinForms / WPF UI tests**: `Form.ActiveForm` may return the WSL terminal window's handle,
and `SendKeys` targets the wrong window.
- **Screenshot-based tests**: screenshots capture the WSL terminal overlay instead of the app.

This is distinct from the known `windows-11-arm` non-interactive session limitation
(runner-environment-113 / ku-113). That issue is about Form.ActiveForm always being null;
this issue is about a pop-up window actively stealing focus from a running test session.

Tracked at actions/runner-images#14264 — open, under investigation by the runner team.
fix: |
**Workaround 1 — Suppress WSL at session start (recommended while issue is open):**
Add a step before any GUI/browser automation to kill the WSL update window and disable
the startup trigger:

```powershell
# Kill any WSL update window that appeared on logon
Get-Process -Name "WindowsTerminal" -ErrorAction SilentlyContinue | Stop-Process -Force
# Disable WSL update prompt for this session
Set-ItemProperty -Path "HKCU:\Software\Microsoft\Windows\CurrentVersion\Run" `
-Name "WslUpdatePrompt" -Value "" -ErrorAction SilentlyContinue
```

**Workaround 2 — Avoid `windows-11-arm` for GUI automation until fixed:**
Route headed browser and GUI automation tests to `windows-latest` (x64 Windows Server 2025),
which does not exhibit this WSL update prompt regression.

**Workaround 3 — Use headless mode:**
Switch Playwright / Selenium to headless mode to avoid the focus-stealing issue entirely.
Headless browsers are not affected by the WSL window.

Monitor actions/runner-images#14264 for an official image patch.
fix_code:
- language: yaml
label: 'Suppress WSL update window before GUI tests on windows-11-arm'
code: |
jobs:
gui-tests:
runs-on: windows-11-arm
steps:
- uses: actions/checkout@v6

- name: Suppress WSL update prompt (regression workaround — runner-images#14264)
shell: pwsh
run: |
# Kill any Windows Terminal window spawned by the WSL update logon trigger
Get-Process -Name "WindowsTerminal" -ErrorAction SilentlyContinue | Stop-Process -Force
Start-Sleep -Seconds 2 # allow window teardown to complete

- name: Run Playwright tests
run: npx playwright test
- language: yaml
label: 'Route GUI tests to windows-latest; arm-specific tests to windows-11-arm'
code: |
jobs:
tests:
strategy:
matrix:
include:
- os: windows-latest
suite: gui # headed browser / WinForms tests
- os: windows-11-arm
suite: native # ARM64 native code tests — no GUI
runs-on: ${{ matrix.os }}
steps:
- uses: actions/checkout@v6

- name: Run tests
run: dotnet test --filter Category=${{ matrix.suite }}
- language: yaml
label: 'Force headless mode on windows-11-arm to avoid focus issues'
code: |
- name: Run Playwright tests (headless on ARM64)
run: |
if [ "${{ runner.arch }}" = "ARM64" ]; then
npx playwright test --project=chromium-headless-shell
else
npx playwright test
fi
shell: bash
prevention:
- "Avoid headed browser automation on `windows-11-arm` until actions/runner-images#14264 is resolved"
- "Add a 'kill WindowsTerminal' pre-step when running GUI tests on windows-11-arm"
- "Prefer headless mode for cross-platform browser tests to avoid session focus dependencies"
- "Subscribe to actions/runner-images#14264 for the official image fix"
docs:
- url: 'https://github.com/actions/runner-images/issues/14264'
label: 'runner-images#14264: Windows 11 ARM64 image shows WSL update required prompt'
- url: 'https://github.com/actions/runner-images/issues/14049'
label: 'runner-images#14049: windows-11-arm non-interactive session (related context)'
- url: 'https://docs.github.com/en/actions/using-github-hosted-runners/using-github-hosted-runners/about-github-hosted-runners'
label: 'GitHub Docs: About GitHub-hosted runners'
Loading