Conserving dependencies present is simple to agree on and arduous to do constantly. In .NET options that use Aspire, the problem shouldn’t be solely updating NuGet packages, but additionally holding the Aspire SDK model in AppHost tasks aligned with the most recent steady launch.
Dependabot is nice for broad dependency automation, however with Aspire it has two sensible limitations: it creates many small pull requests, and it doesn’t replace the Aspire SDK (Aspire.AppHost.Sdk) within the venture Sdk attribute.
To shut that hole, I added a devoted GitHub Actions workflow that runs aspire replace on a schedule and creates a single pull request when SDK and/or Aspire packages change.
Why aspire replace helps
aspire replace is purpose-built for Aspire repositories:
- Updates
Aspire.AppHost.Sdkwithin the ventureSdkattribute - Updates
Aspire.*package deal references to the most recent steady model - Applies updates constantly throughout the answer
This provides a cleaner and extra Aspire-aware replace course of than many particular person Dependabot PRs.
The workflow
The workflow runs each three days at 6:00 AM UTC and may also be began manually from the Actions tab.
title: Aspire SDK Replace
# Triggers:
# - Mechanically runs each three days at 6 AM UTC beginning on the first of every month
# - Might be manually triggered from the Actions tab utilizing workflow_dispatch
on:
schedule:
- cron: '0 6 */3 * *' # 6 AM UTC each three days
workflow_dispatch:
permissions:
contents: write
pull-requests: write
env:
DOTNET_VERSION: '10.0.x'
jobs:
aspire-update:
runs-on: ubuntu-latest
timeout-minutes: 30
steps:
- title: Checkout repository
makes use of: actions/checkout@v6
- title: Setup .NET
makes use of: actions/setup-dotnet@v5
with:
dotnet-version: ${{ env.DOTNET_VERSION }}
- title: Set up Aspire CLI
run: dotnet instrument set up --global aspire.cli
- title: Run aspire replace
# aspire replace scans for AppHost tasks, updates the Aspire.AppHost.Sdk
# model within the .csproj Undertaking Sdk attribute, and updates all Aspire.*
# NuGet package deal references to the most recent steady launch.
# --yes auto-confirms all prompts; --non-interactive disables spinners/interactivity.
# Each flags are required for dependable CI/CD execution.
working-directory: src
run: |
echo "🔄 Working aspire replace..."
aspire replace --non-interactive --yes
echo "✅ aspire replace accomplished."
- title: Test for modifications
id: modifications
run: |
CHANGES=$(git standing --porcelain)
if [ -n "$CHANGES" ]; then
echo "has_changes=true" >> $GITHUB_OUTPUT
echo "📝 Adjustments detected in Aspire SDK/package deal information:"
git diff --stat
else
echo "has_changes=false" >> $GITHUB_OUTPUT
echo "✅ No modifications detected — Aspire SDK and packages are already updated"
fi
- title: Cache NuGet packages
if: steps.modifications.outputs.has_changes == 'true'
makes use of: actions/cache@v5
with:
path: ~/.nuget/packages
key: ${{ runner.os }}-nuget-${{ hashFiles('**/*.csproj') }}
restore-keys: |
${{ runner.os }}-nuget-
- title: Restore dependencies
if: steps.modifications.outputs.has_changes == 'true'
run: dotnet restore src/CNInnovationWeb.slnx
- title: Construct answer
if: steps.modifications.outputs.has_changes == 'true'
run: dotnet construct src/CNInnovationWeb.slnx --no-restore --configuration Launch
- title: Run unit checks
if: steps.modifications.outputs.has_changes == 'true'
run: |
cd src/CNInnovationWeb.Checks
dotnet check --project CNInnovationWeb.Checks.csproj --no-build --configuration Launch --verbosity regular
- title: Create pull request
if: steps.modifications.outputs.has_changes == 'true'
makes use of: peter-evans/create-pull-request@5f6978faf089d4d20b00c7766989d076bb2fc7f1 # v8.1.1
with:
commit-message: "chore: replace Aspire SDK and packages"
title: "chore: automated Aspire SDK and package deal replace"
physique: |
## Automated Aspire SDK and Package deal Replace
This pull request was robotically created by the [Aspire SDK Update](${{ github.server_url }}/${{ github.repository }}/actions/runs/${{ github.run_id }}) workflow.
### What modified?
The [Aspire](https://aspire.dev/docs/) SDK model (in `Aspire.AppHost.Sdk`) and/or a number of `Aspire.*` NuGet package deal references have been up to date to their newest steady releases.
### Verification
- ✅ Answer builds efficiently
- ✅ Unit checks cross
### Subsequent steps
1. Overview the up to date SDK and package deal variations within the modified `.csproj` information.
2. Seek the advice of the [Aspire release notes](https://github.com/dotnet/aspire/releases) for any breaking modifications or migration steps.
3. Run the appliance regionally and confirm Aspire orchestration nonetheless works as anticipated.
4. Merge this PR if every thing appears to be like good.
---
*This PR was created robotically. See [docs/ci.md](docs/ci.md) for extra info.*
department: automated/aspire-update
delete-branch: true
labels: |
dependencies
automated
GitHub Actions used on this workflow
This workflow combines just a few commonplace actions with one key automation motion:
actions/checkout@v6actions/setup-dotnet@v5actions/cache@v5peter-evans/create-pull-request@v8(pinned to a commit SHA within the workflow)
checkout checks out the repository so the job can examine and modify information. setup-dotnet ensures the correct .NET SDK is offered to run the Aspire CLI and construct/check instructions. cache optimizes the workflow by caching NuGet packages based mostly on the hash of all .csproj information, which implies the cache is robotically invalidated when package deal references change. create-pull-request handles the whole Git stream of making a department, committing modifications, pushing to the repository, and opening/updating a PR with the required title, physique, and labels.
Why create-pull-request is necessary right here
With out this motion, the workflow might replace information within the runner, however these modifications can be misplaced when the job ends. create-pull-request handles the complete Git stream robotically:
- Creates (or reuses) a department (
automated/aspire-update) - Commits the modified information together with your message
- Pushes the department to the repository
- Opens or updates a PR together with your title/physique/labels
- Optionally deletes the department after merge (
delete-branch: true)
On this workflow, it solely runs when precise file modifications are detected (if: steps.modifications.outputs.has_changes == 'true'). That stops empty or noisy PRs.
Inputs used for create-pull-request
commit-message: Git commit message for the automated replace committitle: Pull request titlephysique: Detailed PR description with verification and subsequent stepsdepartment: Fastened department title for replace PRsdelete-branch: Cleans up department after PR mergelabels: Provides metadata (dependencies,automated) for filtering and triage
This makes the replace stream predictable and reviewer-friendly: Aspire updates are grouped, validated, and introduced in a single constant PR.
What this improves over Dependabot for Aspire
Dependabot remains to be helpful, however for Aspire particularly this workflow provides higher upkeep:
- Handles Aspire SDK updates (Dependabot doesn’t)
- Teams Aspire SDK/package deal modifications into one reviewable PR
- Verifies modifications with restore, construct, and unit checks earlier than proposing updates
- Runs on schedule and on demand
Lead to observe
The workflow creates a PR solely when updates are wanted. Right here is an instance:

I can approve and merge this PR with confidence as a result of the workflow already verified that the answer builds and checks cross with the brand new Aspire variations. The PR description additionally guides me by way of reviewing the modifications and checking launch notes for any necessary updates. With the approval, the following workflow is triggered to publish the brand new model of the web site with the up to date Aspire SDK and packages to the check setting.

This retains Aspire infrastructure present with much less guide work and fewer noisy dependency PRs.
Abstract
In case your app makes use of Aspire, including an aspire replace workflow is a sensible complement to Dependabot. Dependabot continues dealing with broad dependency updates, whereas the Aspire workflow closes the SDK hole and retains AppHost and Aspire packages aligned.
Hyperlinks
Your flip
Do you utilize Dependabot as we speak? Are you already constructing apps with Aspire? And did this workflow method allow you to enhance your replace course of?
I’d love to listen to the way you deal with dependency and SDK updates in your tasks.
The weblog picture was created with AI. The workflow (created with the assistance of GitHub Copilot) is predicated on the implementation for the CN innovation web site, which is constructed with Aspire.

