Building a GitHub Copilot Skill for Spring Boot Modernization at Scale
- Get link
- X
- Other Apps
Building a GitHub Copilot Skill for Spring Boot Modernization at Scale
What starts as a simple prompt for one application quickly becomes an engineering process problem at scale. This post shares the design principles behind a reusable GitHub Copilot skill that standardized Spring Boot upgrades across dozens of services while reducing manual effort and review overhead.
The Real Challenge of Framework Modernization
Upgrading a single Spring Boot application is usually straightforward.
An experienced engineer can handcraft a prompt, point GitHub Copilot at a repository, review a few changes, and work through the upgrade. The challenge isn't upgrading one application. The challenge is upgrading the next ten, twenty, or forty applications with the same level of quality, consistency, and safety.
That is where a reusable GitHub Copilot Skill becomes valuable.
Rather than relying on engineers to repeatedly write the "perfect upgrade prompt," a skill encodes the entire modernization process once and applies it consistently across every repository. It transforms tribal knowledge, hard-earned lessons, and best practices into a repeatable workflow.
In our case, that approach helped modernize 42 Spring Boot applications in a single week, with upgrade pull requests generated automatically across the portfolio.
The key lesson was simple:
The value of a skill is not that it is smarter than an LLM. The value is that it enforces the same disciplined process every single time.
Why a Skill Instead of a Prompt?
Large language models are exceptionally capable at code transformations, including application upgrades. However, free-form prompting introduces variability.
Different engineers will:
- Ask the problem differently
- Skip important verification steps
- Forget framework-specific breaking changes
- Use inconsistent reporting formats
- Apply different levels of risk mitigation
Over time, this creates operational inconsistency.
A skill addresses this by introducing structure:
Deterministic Detection
The skill uses scripts instead of model reasoning to determine:
- Current Spring Boot version
- Java baseline
- Build system
- Dependency management strategy
- Module layout
No guessing. No assumptions.
Mandatory Planning
The upgrade approach is generated and reviewed before any code modifications occur.
Framework-Specific Knowledge
Known migration issues and breaking changes are maintained centrally and reused across every future upgrade.
Consistent Deliverables
Every modernization produces the same report structure, making pull requests easier to review and audit.
Safety Gates
The skill can prevent unsafe actions, such as skipping major version transitions or proceeding without determining the correct target version.
The Evolution of the Skill
The first iteration was underwhelming.
Like many initial automation attempts, it focused primarily on:
- Detecting the current version
- Running a build
- Reporting project health
That was useful, but it was not modernization.
Real modernization requires more than validating that an application compiles. It requires understanding:
- What the latest supported version actually is
- What breaking changes exist between releases
- Which dependencies can be removed
- Which dependencies must be updated
- Which code patterns need migration
Only after adding those checks did the skill begin creating meaningful business value.
The Seven-Step Upgrade Process
The design eventually converged on a seven-step workflow with two non-negotiable safety gates.
The exact implementation may vary by organization, but the engineering principles remain broadly applicable.
Step 1: Establish the Baseline
Before any decision can be made, the skill must determine the project's current state.
This information should come from a detection script rather than the LLM itself.
For Maven projects, this typically means inspecting:
- Parent POM versions
- Spring Boot BOM versions
- Compiler settings
- Java runtime requirements
For Gradle builds, equivalent metadata can be extracted from build files.
Most importantly, the skill must display the raw detection results before proceeding.
If the version cannot be determined, the process stops.
This eliminates an entire category of upgrade failures caused by incorrect assumptions.
Step 2: Resolve the Latest Stable Version
One of the most common mistakes an AI agent can make is confidently reporting an outdated version as the latest release.
The solution is straightforward:
Never allow the model to answer version questions from memory.
Instead, retrieve version metadata from authoritative sources such as:
- Maven Central
- Internal artifact repositories
- Framework release APIs
- Enterprise package mirrors
Migration guides and release notes remain extremely valuable, but they are supplementary sources, not the authority for version determination.
A modernization workflow should always be able to explain:
- Which version was selected
- Why it was selected
- Where that information came from
Step 3: Create the Migration Plan
Before touching code, the skill generates a complete upgrade strategy.
The plan should include:
Current State Assessment
- Existing framework versions
- Runtime versions
- Project structure
- Dependency overrides
Target State
- Recommended Spring Boot version
- Corresponding Java version requirements
- Dependency alignment strategy
Upgrade Path
Major version jumps should never happen in a single step.
For example:
Each hop is evaluated independently.
Breaking Change Analysis
Examples include:
- Jakarta namespace migration
- Spring Security DSL changes
- Spring Cloud configuration updates
- Actuator endpoint changes
- Jackson compatibility updates
Dependency Audit
The skill should identify:
- Redundant dependency versions
- Obsolete overrides
- Framework-managed dependencies
- Incompatible libraries
Risk Areas
Common risks include:
- Security-sensitive components
- Serialization layers
- Database schema interactions
- Poorly tested services
Reuse Previous Upgrade Work
One of the highest-leverage additions to our process was searching for prior successful upgrades.
If another team already solved:
- A Jakarta migration issue
- A Spring Security migration pattern
- A dependency compatibility problem
Then the skill should reuse those proven changes rather than rediscover them.
At scale, every upgrade should make future upgrades faster.
Step 4: Create a Clean Baseline
Before upgrading anything:
or
should complete successfully.
Without a known-good baseline, it becomes difficult to determine whether failures are caused by modernization work or pre-existing issues.
Low test coverage should also be flagged explicitly so stakeholders understand verification limitations.
Step 5: Upgrade One Hop at a Time
This is the single most important safety mechanism.
For each version hop:
- Update framework version
- Apply required migrations
- Build
- Run tests
- Verify application startup
- Commit the change
Only after a successful verification cycle should the next hop begin.
If a build fails:
- Diagnose
- Fix
- Rebuild
Do not continue stacking changes.
Large unverified jumps dramatically increase troubleshooting complexity.
Step 6: Verify the Entire Application
Reaching the target version is not enough.
The final validation should include:
- Clean builds
- Full test execution
- Application startup verification
- Removal of obsolete package references
- Dependency hygiene checks
- Review of remaining warnings
Anything left unresolved should be documented explicitly.
Step 7: Produce a Modernization Report
A reviewer should be able to understand the upgrade in minutes.
A useful report typically contains:
Upgrade Summary
Upgrade Path
Changes Applied
Validation
Follow-Up Items
This report becomes the foundation for the pull request description and long-term audit history.
Two Non-Negotiable Rules
If there is only one thing to remember from this article, it is these two rules.
Rule #1: Never Trust a Guessed Version
Every version must come from deterministic detection or a live authoritative source.
Never rely solely on model memory.
Rule #2: Never Batch Upgrade Hops
Every major or significant version transition must be independently verified before moving to the next.
These two guardrails eliminate a surprising percentage of upgrade failures.
Lessons Learned from Real Upgrades
A few recurring issues surfaced repeatedly.
Annotation Processor Problems
Some projects compiled under one JDK but failed under another because annotation processors were not configured correctly.
This became a permanent item in our modernization checklist.
Stopping Short of the Latest Patch
Early versions of the skill occasionally stopped on an intermediate version.
The fix was adding a final version-resolution check before declaring success.
Agent Approval Pauses
Even with autonomous execution enabled, agents sometimes paused during higher-risk operations.
This turned out to be a feature rather than a flaw, ensuring human review occurred at important decision points.
Missing Pull Requests
File changes alone are not a finished deliverable.
The skill must explicitly include instructions to:
- Commit
- Push
- Create or update the PR
Otherwise some runs stop prematurely.
Build Time Dominates
Most execution time is spent waiting for build and test validation, not reasoning.
That is expected.
The same would be true of an experienced engineer performing the work manually.
Running Many Upgrades in Parallel
The biggest productivity gain came from using VS Code's new Agents Window.
The process was simple:
- Identify target repositories
- Configure a standard upgrade skill
- Launch one agent session per repository
- Let each workspace run independently
- Review results and PRs periodically
Instead of upgrading repositories sequentially, the work becomes a supervised batch operation.
This dramatically increases throughput while preserving review quality.
Final Thoughts
A Spring Boot modernization skill is not about replacing engineering judgment.
It is about standardizing proven engineering practices.
The most successful skills combine:
- Deterministic version detection
- Live version verification
- Structured planning
- Incremental upgrades
- Strong validation
- Reusable organizational knowledge
More importantly, every upgrade improves the next one.
Your migration checklist grows. Your compatibility database improves. Your automation becomes more reliable.
Eventually, framework modernization shifts from a large project to a repeatable operational process.
And that is where the real value of AI-assisted software modernization begins.
❤️ Support This Blog
If this post helped you, you can support my writing with a small donation. Thank you for reading.
- Get link
- X
- Other Apps
Comments
Post a Comment