akka-aspire-configurat…
Configure Akka.NET with .NET Aspire for local development and production deployments. Covers actor system setup, clustering,…
Cache Playwright browser binaries in CI/CD pipelines (GitHub Actions, Azure DevOps) to avoid 1-2 minute download overhead on every build.
Claude Code
$ npx -y skills add aaronontheweb/dotnet-skills --skill playwright-ci-caching --agent claude-code
Codex
$ npx skills add aaronontheweb/dotnet-skills --skill playwright-ci-caching -a codex -y
Cursor
$ npx skills add aaronontheweb/dotnet-skills --skill playwright-ci-caching -a cursor -y
Gemini CLI
$ npx skills add aaronontheweb/dotnet-skills --skill playwright-ci-caching -a gemini-cli -y
GitHub Copilot
$ npx skills add aaronontheweb/dotnet-skills --skill playwright-ci-caching -a github-copilot -y
OpenCode
$ npx skills add aaronontheweb/dotnet-skills --skill playwright-ci-caching -a opencode -y
Windsurf
$ npx skills add aaronontheweb/dotnet-skills --skill playwright-ci-caching -a windsurf -y
name: playwright-ci-caching description: Cache Playwright browser binaries in CI/CD pipelines (GitHub Actions, Azure DevOps) to avoid 1-2 minute download overhead on every build. user-invocable: false
Use this skill when:
Playwright browsers (~400MB) must be downloaded on every CI run by default. This:
1. **Extract Playwright version** from `Directory.Packages.props` (CPM) to use as cache key 2. **Cache browser binaries** using platform-appropriate paths 3. **Conditional install** - only download on cache miss 4. **Automatic cache bust** - key includes version, so package upgrades invalidate cache
| OS | Path | |----|------| | Linux | `~/.cache/ms-playwright` | | macOS | `~/Library/Caches/ms-playwright` | | Windows | `%USERPROFILE%\AppData\Local\ms-playwright` |
- name: Get Playwright Version
shell: pwsh
run: |
$propsPath = "Directory.Packages.props"
[xml]$props = Get-Content $propsPath
$version = $props.Project.ItemGroup.PackageVersion |
Where-Object { $_.Include -eq "Microsoft.Playwright" } |
Select-Object -ExpandProperty Version
echo "PlaywrightVersion=$version" >> $env:GITHUB_ENV
- name: Cache Playwright Browsers
id: playwright-cache
uses: actions/cache@v4
with:
path: ~/.cache/ms-playwright
key: ${{ runner.os }}-playwright-${{ env.PlaywrightVersion }}
- name: Install Playwright Browsers
if: steps.playwright-cache.outputs.cache-hit != 'true'
shell: pwsh
run: ./build/playwright.ps1 install --with-depsFor workflows that run on multiple operating systems:
- name: Cache Playwright Browsers
id: playwright-cache
uses: actions/cache@v4
with:
path: |
~/.cache/ms-playwright
~/Library/Caches/ms-playwright
~/AppData/Local/ms-playwright
key: ${{ runner.os }}-playwright-${{ env.PlaywrightVersion }}- task: PowerShell@2
displayName: 'Get Playwright Version'
inputs:
targetType: 'inline'
script: |
[xml]$props = Get-Content "Directory.Packages.props"
$version = $props.Project.ItemGroup.PackageVersion |
Where-Object { $_.Include -eq "Microsoft.Playwright" } |
Select-Object -ExpandProperty Version
Write-Host "##vso[task.setvariable variable=PlaywrightVersion]$version"
- task: Cache@2
displayName: 'Cache Playwright Browsers'
inputs:
key: 'playwright | "$(Agent.OS)" | $(PlaywrightVersion)'
path: '$(HOME)/.cache/ms-playwright'
cacheHitVar: 'PlaywrightCacheHit'
- task: PowerShell@2
displayName: 'Install Playwright Browsers'
condition: ne(variables['PlaywrightCacheHit'], 'true')
inputs:
filePath: 'build/playwright.ps1'
arguments: 'install --with-deps'Create a `build/playwright.ps1` script that discovers and runs the Playwright CLI. This abstracts away the Playwright CLI location which varies by project structure.
# build/playwright.ps1
# Discovers Microsoft.Playwright.dll and runs the bundled Playwright CLI
param(
[Parameter(ValueFromRemainingArguments = $true)]
[string[]]$Arguments
)
# Find the Playwright DLL (after dotnet build/restore)
$playwrightDll = Get-ChildItem -Path . -Recurse -Filter "Microsoft.Playwright.dll" -ErrorAction SilentlyContinue |
Select-Object -First 1
if (-not $playwrightDll) {
Write-Error "Microsoft.Playwright.dll not found. Run 'dotnet build' first."
exit 1
}
$playwrightDir = $playwrightDll.DirectoryName
# Find the playwright CLI (path varies by OS and node version)
$playwrightCmd = Get-ChildItem -Path "$playwrightDir/.playwright/node" -Recurse -Filter "playwright.cmd" -ErrorAction SilentlyContinue |
Select-Object -First 1
if (-not $playwrightCmd) {
# Try Unix executable
$playwrightCmd = Get-ChildItem -Path "$playwrightDir/.playwright/node" -Recurse -Filter "playwright" -ErrorAction SilentlyContinue |
Where-Object { $_.Name -eq "playwright" } |
Select-Object -First 1
}
if (-not $playwrightCmd) {
Write-Error "Playwright CLI not found in $playwrightDir/.playwright/node"
exit 1
}
Write-Host "Using Playwright CLI: $($playwrightCmd.FullName)"
& $playwrightCmd.FullName @ArgumentsUsage:
# Install browsers ./build/playwright.ps1 install --with-deps # Install specific browser ./build/playwright.ps1 install chromium # Show installed browsers ./build/playwright.ps1 install --dry-run
This pattern assumes:
1. **Central Package Management (CPM)** with `Directory.Packages.props`:
<Project>
<ItemGroup>
<PackageVersion Include="Microsoft.Playwright" Version="1.40.0" />
</ItemGroup>
</Project>2. **Project has been built** before running `playwright.ps1` (so DLLs exist)
3. **PowerShell available** on CI agents (pre-installed on GitHub Actions and Azure DevOps)
Using the Playwright version in the cache key ensures:
If you hardcode the cache key (e.g., `playwright-browsers-v1`), you'll need to manually bump it every time you upgrade Playwright, or you'll get cryptic version mismatch errors.
1. Verify the version extraction step outputs the correct version 2. Check that the cache path
A comprehensive AI coding plugin with 30 skills and 5 specialized agents for professional .NET development. Battle-tested patterns from production systems covering C#, Akka.NET, Aspire, EF Core, testing, and performance optimization.
Configure Akka.NET with .NET Aspire for local development and production deployments. Covers actor system setup, clustering,…
Critical Akka.NET best practices including EventStream vs DistributedPubSub, supervision strategies, error handling, Props vs…
Patterns for building entity actors with Akka.Hosting - GenericChildPerEntityParent, message extractors, cluster sharding…
Akka.Management for cluster bootstrapping, service discovery (Kubernetes, Azure, Config), health checks, and dynamic cluster…
Write unit and integration tests for Akka.NET actors using modern Akka.Hosting.TestKit patterns. Covers dependency injection,…
Guidelines for making .NET libraries and applications trimming-safe and Native AOT compatible. Covers the trimming/AOT model, the…
You MUST use this before any creative work - creating features, building components, adding functionality, modifying behavior, or…
Ask which skill or flow fits your situation. A router over the skills in this repo.