How I Use a Custom AI Skill to Upgrade a Large ABP Solution
TL;DR: I created a project-specific AI skill that treats an ABP upgrade as a complete engineering workflow—not merely a package update. It inventories the current solution, creates recovery points, applies the upgrade, resolves known breaking changes, validates the result, and records new lessons for the next upgrade.
Introduction
Upgrading a small application can be as simple as changing a few package versions and rebuilding. Upgrading a mature ABP solution is different.
My solution contains custom ABP service replacements, Entity Framework Core migrations, NuGet and npm dependencies, authentication, Redis, background processing, multiple user interfaces, and production-specific integrations. A framework upgrade can affect any of those areas. More importantly, a successful compilation does not prove that authentication, billing, localization, caching, or database behavior still works.
I wanted my coding agent to understand that wider context every time I asked it to perform an upgrade. Repeating a large prompt from memory was unreliable, so I captured the workflow in a custom skill. You can call yours anything; the reusable example included with this article is named upgrade-abp-solution.
The skill gives the agent:
- A repeatable upgrade process
- Project-specific validation requirements
- PowerShell helpers for inventory, backup, and verification
- References for migration and namespace changes
- A durable log of problems encountered in previous upgrades
- An explicit rollback path
This article explains how the skill is structured, how I use it, and why the most valuable part is not the automation—it is the memory the workflow builds over time.
Why abp update Is Only One Step
The ABP CLI does a useful job of updating ABP-related dependencies:
abp update --version 10.5.0
However, an update command cannot answer solution-specific questions such as:
- Do custom classes still match constructors in ABP base classes?
- Has an implemented ABP interface gained a new member?
- Does the new ABP version require an EF Core migration?
- Are directly pinned packages now downgrading transitive dependencies?
- Is the LeptonX version line different from the main ABP version?
- Did a cached value become incompatible with the new application?
- Do login, two-factor authentication, password reset, and token flows still behave correctly?
- Can the solution be restored if a generated migration is unsafe?
My skill therefore treats abp update as an implementation detail inside a larger process:
Inspect → Protect → Research → Update → Compile → Migrate → Validate → Learn
That change in perspective matters. The goal is not to make package files say the new version. The goal is to move the entire solution to the new version with evidence that it remains safe to ship.
The Anatomy of the Skill
The skill is deliberately small enough to inspect and maintain:
upgrade-abp-solution/
├── SKILL.md
├── agents/
│ └── openai.yaml
├── references/
│ ├── encountered-issues.md
│ └── migration-checklist.md
└── scripts/
├── Get-AbpInventory.ps1
├── New-PreUpgradeSnapshot.ps1
└── Test-AbpUpgrade.ps1
Each part has a distinct responsibility.
You can browse or copy the complete sample upgrade-abp-solution skill included with this article. It is generic and has no dependencies on my solution.
SKILL.md: The Operating Procedure
SKILL.md is the entry point. Its description tells the agent when the skill applies, while its body describes the ordered workflow.
At a high level, the instructions require the agent to:
- Review problems from earlier upgrades.
- Back up the database and create a Git recovery point.
- Identify the current and target versions.
- Read the applicable migration guidance.
- Update the ABP CLI and solution dependencies.
- Update the .NET SDK and target frameworks when required.
- Restore and compile before touching the database.
- Generate and manually review EF Core migrations.
- Run automated and application-level validation.
- Add newly discovered issues to the knowledge log.
The ordering is intentional. For example, generating a migration before resolving all compilation errors produces noise rather than useful evidence. Likewise, an upgrade should not begin until the recovery path is known.
references/migration-checklist.md: The Stable Checklist
The migration checklist contains the things I want checked on every upgrade:
- Git and database recovery points
- ABP and .NET version alignment
- Official migration guidance
- NuGet restore and full-solution compilation
- EF Core migration review
- Unit and integration tests
- Authentication and CRUD smoke tests
- Redis and deployment configuration
It also groups recurring problems by area: Entity Framework Core, authorization, localization, caching, background jobs, and ABP system tables.
This file represents stable knowledge. It changes occasionally as the architecture evolves, but it is not rewritten for every upgrade.
Migration References: Fast Triage for Compile Errors
Framework upgrades frequently move types, add async APIs, or change module contracts. The migration checklist and encountered-issues log provide focused places to capture those changes and search patterns.
When the build reports a missing type, the skill directs the agent to:
- Search the current ABP source for the type.
- Read the migration guide for the target version.
- Determine whether the type moved, its package was split, or its API was replaced.
- Apply bulk edits only after confirming the correct replacement.
That sequence avoids a common failure mode: guessing a namespace that compiles but represents the wrong abstraction.
references/encountered-issues.md: The Compounding Asset
The issue log is the part I value most. After every upgrade, the agent records:
- Source and target versions
- The exact error or symptom
- The solution that worked
- Relevant files
- Time spent
- Runtime concerns to retest
- Advice for the next upgrade
This converts one-off debugging into reusable operational knowledge.
For example, the log now knows that:
- Visual Studio can lock project files while
abp updateis running. - A failing ABP CLI discovery step may justify a controlled manual package bump.
- Custom implementations of ABP base classes and interfaces deserve early attention.
- Direct dependency pins can become downgrade errors after transitive requirements move.
- LeptonX can follow a different version line from the main ABP packages.
- A green build does not resolve a test process that hangs after the test runner starts.
The next upgrade begins with those lessons already in context.
The Three Helper Scripts
The scripts turn repetitive checks into consistent evidence. They do not replace engineering judgment; they make it easier to apply that judgment to the right information.
1. Inventory the Current State
Get-AbpInventory.ps1 scans the solution and reports:
- Resolved
Volo.Abp,Volo.CmsKit,Volo.Docs, andVolo.Bloggingpackages - The installed ABP CLI version
- The active .NET SDK
- Target frameworks found across project files
I can run it from the solution root:
.\scripts\Get-AbpInventory.ps1 -SolutionDir "D:\Projects\MySolution"
This provides a baseline before any file changes occur. It can also reveal version drift that was already present before the upgrade.
2. Create a Recovery Point
New-PreUpgradeSnapshot.ps1 records the state needed to understand or reverse the code-side upgrade:
.\scripts\New-PreUpgradeSnapshot.ps1 `
-SolutionDir "D:\Projects\MySolution" `
-OutputDir "D:\Backups\abp-upgrades"
The script:
- Warns about uncommitted changes
- Saves the current package list
- Copies central build and SDK configuration
- Records the current commit
- Creates a timestamped Git restore branch
- Writes restore instructions alongside the backup
It intentionally reminds me that the database backup is a separate operation. A Git branch can restore code; it cannot restore a database after a destructive migration.
3. Validate the Result
Test-AbpUpgrade.ps1 provides a repeatable first validation pass:
.\scripts\Test-AbpUpgrade.ps1 `
-SolutionDir "D:\Projects\MySolution" `
-Detailed
It checks:
- Whether the solution builds without restoring again
- Whether obsolete API warnings appeared
- Whether unit tests pass
- Whether ABP package versions are consistent
- Whether expected configuration files are present
- Whether EF Core migrations exist
- Whether known breaking-change patterns remain
- Whether deployment files may still reference an older .NET version
Warnings are deliberately distinct from failures. A warning means the script cannot prove something automatically; it does not mean the concern can be ignored.
For example, finding a migrations directory is not the same as proving the model is current. I still run an explicit drift check:
dotnet ef migrations has-pending-model-changes `
--project src\MySolution.EntityFrameworkCore `
--startup-project src\MySolution.DbMigrator
My End-to-End Upgrade Workflow
Here is how the skill guides an actual upgrade.
Phase 1: Preflight
First, the agent reads the issue log and applicable migration guidance. It inventories the current package graph, SDK, target frameworks, frontend packages, and explicit dependency pins.
It also identifies solution-specific risk areas before editing anything:
- ABP base classes that have been subclassed
- ABP interfaces implemented by custom infrastructure
- Replaced application services
- Custom
DbContextinterfaces - Authentication and OpenIddict customization
- Custom event bus implementations
- Packages pinned to work around earlier vulnerabilities or incompatibilities
This produces a risk map for the upgrade rather than waiting for the compiler to discover everything.
Phase 2: Protection
The working tree must be understood and a restore point must exist. I back up the database separately, then run the pre-upgrade script.
The key question is simple:
If the package update or migration goes wrong, can I return both the code and the data to a known state?
If the answer is uncertain, the upgrade does not proceed.
Phase 3: Dependency Update
The preferred path is the ABP updater:
dotnet tool update -g Volo.Abp.Cli
abp update --version X.Y.Z
The skill still expects the result to be inspected. An updater may change the primary ABP packages while leaving:
- npm packages on another version
- lock files stale
- direct NuGet pins incompatible
- container or CI SDK versions unchanged
If the CLI cannot complete, the issue log contains a bounded fallback: update the relevant packages manually, refresh lock files, and let restore surface inconsistencies. The fallback is controlled and reviewable, not a blind search-and-replace across every version string.
Phase 4: Restore and Compile
The next gate is:
dotnet restore
dotnet build --no-restore
Restore failures and compile failures are treated as different classes of problem.
Restore commonly exposes:
- A package version that does not exist
- A direct package pin below a new transitive lower bound
- Mixed ABP versions
- An unreachable or slow package source
Compilation commonly exposes:
- New constructor dependencies in ABP base classes
- New interface members
- Changed override signatures
- Moved namespaces
- New
DbSetrequirements - Changes to custom infrastructure contracts
Separating these stages keeps the diagnosis precise.
Phase 5: Database Migration
Only after the solution compiles does the workflow check for model changes:
dotnet ef migrations add Upgraded_To_Abp_X_Y `
--project src\MySolution.EntityFrameworkCore `
--startup-project src\MySolution.DbMigrator
The generated migration is reviewed like production code. I specifically look for:
- Dropped columns or tables
- Destructive type or length changes
- Unexpected modifications to ABP system tables
- Changes that conflict with custom mappings
- Provider-specific changes that do not apply to my database
An empty migration is removed. A dangerous migration is corrected or the upgrade is paused; it is never accepted simply because it was generated by a tool.
Phase 6: Validation
The automated validation script is only the first layer. The skill also calls for focused runtime checks:
- Application startup
- Login and logout
- Two-factor authentication and password reset
- Basic create, read, update, and delete operations
- Tenant switching, when applicable
- English and French localization
- Audit logging
- Redis serialization and cache behavior
- Background workers
- Critical business integrations
The exact list should reflect the solution. In my case, billing and external healthcare integrations deserve explicit checks because they are more important than a generic home-page smoke test.
Phase 7: Record What Was Learned
Finally, the agent adds new findings to encountered-issues.md.
This is not optional housekeeping. It closes the loop:
Previous upgrades inform this upgrade
↓
A new issue is solved
↓
The solution is added to the skill
↓
Future upgrades start smarter
Without this step, the skill is a static checklist. With it, the skill becomes a project-specific engineering memory.
Examples of Lessons That Paid Off
The upgrade log has already changed how later upgrades are performed.
Close Development Tools Before Updating
One upgrade produced confusing IOException failures because Visual Studio held project files open. The package changes mostly succeeded, leaving the solution in a partially updated state.
That experience became a preflight instruction: close Visual Studio before running the updater. A later upgrade avoided the problem entirely.
Do Not Spend Unlimited Time Fighting the Preferred Tool
During another upgrade, package discovery repeatedly timed out. The skill now recommends a time-bounded decision: try the CLI first, but move to a controlled manual bump when the failure is clearly environmental and repeatable.
This retains a preferred path without turning it into dogma.
Check Custom ABP Extension Points Early
Custom base-class overrides and interface implementations are frequent compile-break candidates because they mirror ABP contracts closely.
Past upgrades have required:
- Passing new dependencies to base constructors
- Implementing newly added interface methods
- Updating a custom event bus for string-based event contracts
- Adding a newly required identity
DbSet
The skill now inspects those seams early rather than treating each error as an unrelated surprise.
Verify Behavior Even When There Are No Compile Breaks
One upgrade compiled cleanly and required no EF migration, but it introduced an identity token behavior change worth retesting. The build could not prove whether the application's login, two-factor, password-reset, and account-linking experiences still met expectations.
That lesson reinforces the central principle of the skill: compatibility includes behavior, not only APIs.
What the Skill Does Not Automate
I intentionally keep several decisions human-reviewed:
- Approving destructive database migrations
- Choosing when a failed updater should be replaced with a manual update
- Deciding whether package-version differences are legitimate
- Evaluating business-critical runtime workflows
- Clearing production caches or authentication data
- Deploying the upgraded solution
Commands such as flushing Redis or truncating OpenIddict tables can have serious operational consequences. They may be useful recovery options, but they should never run automatically merely because an upgrade occurred.
The skill makes these risks visible and supplies context. It does not remove ownership of the decision.
Design Principles for Your Own Upgrade Skill
If you want to build a similar skill for your ABP solution, I recommend the following principles.
Start with Your Architecture
Generic migration guidance is useful, but the skill becomes valuable when it knows your extension points, infrastructure, deployment model, and critical user journeys.
Separate Procedure, References, and Executable Checks
Keep the main skill concise. Put stable checklists and historical details in reference files, and put deterministic operations in scripts. This makes each layer easier to review.
Prefer Evidence-Producing Automation
A good helper script should answer a question:
- What versions are installed?
- Can I recover the previous state?
- Does the solution compile?
- Are package versions inconsistent?
- Is the EF Core model current?
Avoid automation whose only output is “done.”
Make Rollback Part of the Happy Path
Rollback planning should happen before the update, not after an error. Record the Git commit, create a restore branch, save dependency state, and back up the database.
Treat Warnings as Unproven Conditions
Not every check can be binary. A warning should clearly identify what still needs review and why automation could not settle it.
Update the Skill After Every Upgrade
The knowledge log is what gives the skill compounding returns. Record exact errors and proven solutions while they are fresh.
Summary
My custom ABP upgrade skill turns a risky, memory-driven maintenance task into a repeatable workflow:
- ✅ It inventories the full technology stack before changes begin.
- ✅ It creates code recovery points and requires a separate database backup.
- ✅ It combines official migration guidance with project-specific knowledge.
- ✅ It distinguishes dependency, compilation, schema, and runtime validation.
- ✅ It remembers real failures so future upgrades avoid the same traps.
- ✅ It keeps destructive and business-critical decisions under deliberate review.
The skill does not make framework upgrades effortless, and that is not the goal. It makes them explainable, recoverable, and progressively more predictable.
For a large ABP solution, that is a much more useful kind of automation.
References
- ABP Framework migration guides
- ABP Framework release notes
- ABP Framework source code
- EF Core migrations overview
- EF Core breaking changes
About the Author
Kori Francis
ABP Framework developer with experience building and operating large .NET solutions, cloud deployments, and project-specific AI engineering workflows.
Connect with me:
- 🐦 Twitter: @kfrancis
- 💼 LinkedIn: Kori Francis
Have you built a project-specific workflow for framework upgrades? I would be interested to hear which checks and lessons have saved your team the most time.
Tags: #ABPFramework #DotNet #AI #Automation #EntityFrameworkCore #PowerShell
Comments
No one has commented yet, be the first to comment!