home / skills / affaan-m / everything-claude-code / springboot-verification
This skill streamlines Spring Boot verification by automating build, static analysis, tests with coverage, security scans, and diff reviews before release.
npx playbooks add skill affaan-m/everything-claude-code --skill springboot-verificationReview the files below or copy the command above to add this skill to your agents.
---
name: springboot-verification
description: "Verification loop for Spring Boot projects: build, static analysis, tests with coverage, security scans, and diff review before release or PR."
---
# Spring Boot Verification Loop
Run before PRs, after major changes, and pre-deploy.
## When to Activate
- Before opening a pull request for a Spring Boot service
- After major refactoring or dependency upgrades
- Pre-deployment verification for staging or production
- Running full build → lint → test → security scan pipeline
- Validating test coverage meets thresholds
## Phase 1: Build
```bash
mvn -T 4 clean verify -DskipTests
# or
./gradlew clean assemble -x test
```
If build fails, stop and fix.
## Phase 2: Static Analysis
Maven (common plugins):
```bash
mvn -T 4 spotbugs:check pmd:check checkstyle:check
```
Gradle (if configured):
```bash
./gradlew checkstyleMain pmdMain spotbugsMain
```
## Phase 3: Tests + Coverage
```bash
mvn -T 4 test
mvn jacoco:report # verify 80%+ coverage
# or
./gradlew test jacocoTestReport
```
Report:
- Total tests, passed/failed
- Coverage % (lines/branches)
### Unit Tests
Test service logic in isolation with mocked dependencies:
```java
@ExtendWith(MockitoExtension.class)
class UserServiceTest {
@Mock private UserRepository userRepository;
@InjectMocks private UserService userService;
@Test
void createUser_validInput_returnsUser() {
var dto = new CreateUserDto("Alice", "[email protected]");
var expected = new User(1L, "Alice", "[email protected]");
when(userRepository.save(any(User.class))).thenReturn(expected);
var result = userService.create(dto);
assertThat(result.name()).isEqualTo("Alice");
verify(userRepository).save(any(User.class));
}
@Test
void createUser_duplicateEmail_throwsException() {
var dto = new CreateUserDto("Alice", "[email protected]");
when(userRepository.existsByEmail(dto.email())).thenReturn(true);
assertThatThrownBy(() -> userService.create(dto))
.isInstanceOf(DuplicateEmailException.class);
}
}
```
### Integration Tests with Testcontainers
Test against a real database instead of H2:
```java
@SpringBootTest
@Testcontainers
class UserRepositoryIntegrationTest {
@Container
static PostgreSQLContainer<?> postgres = new PostgreSQLContainer<>("postgres:16-alpine")
.withDatabaseName("testdb");
@DynamicPropertySource
static void configureProperties(DynamicPropertyRegistry registry) {
registry.add("spring.datasource.url", postgres::getJdbcUrl);
registry.add("spring.datasource.username", postgres::getUsername);
registry.add("spring.datasource.password", postgres::getPassword);
}
@Autowired private UserRepository userRepository;
@Test
void findByEmail_existingUser_returnsUser() {
userRepository.save(new User("Alice", "[email protected]"));
var found = userRepository.findByEmail("[email protected]");
assertThat(found).isPresent();
assertThat(found.get().getName()).isEqualTo("Alice");
}
}
```
### API Tests with MockMvc
Test controller layer with full Spring context:
```java
@WebMvcTest(UserController.class)
class UserControllerTest {
@Autowired private MockMvc mockMvc;
@MockBean private UserService userService;
@Test
void createUser_validInput_returns201() throws Exception {
var user = new UserDto(1L, "Alice", "[email protected]");
when(userService.create(any())).thenReturn(user);
mockMvc.perform(post("/api/users")
.contentType(MediaType.APPLICATION_JSON)
.content("""
{"name": "Alice", "email": "[email protected]"}
"""))
.andExpect(status().isCreated())
.andExpect(jsonPath("$.name").value("Alice"));
}
@Test
void createUser_invalidEmail_returns400() throws Exception {
mockMvc.perform(post("/api/users")
.contentType(MediaType.APPLICATION_JSON)
.content("""
{"name": "Alice", "email": "not-an-email"}
"""))
.andExpect(status().isBadRequest());
}
}
```
## Phase 4: Security Scan
```bash
# Dependency CVEs
mvn org.owasp:dependency-check-maven:check
# or
./gradlew dependencyCheckAnalyze
# Secrets in source
grep -rn "password\s*=\s*\"" src/ --include="*.java" --include="*.yml" --include="*.properties"
grep -rn "sk-\|api_key\|secret" src/ --include="*.java" --include="*.yml"
# Secrets (git history)
git secrets --scan # if configured
```
### Common Security Findings
```
# Check for System.out.println (use logger instead)
grep -rn "System\.out\.print" src/main/ --include="*.java"
# Check for raw exception messages in responses
grep -rn "e\.getMessage()" src/main/ --include="*.java"
# Check for wildcard CORS
grep -rn "allowedOrigins.*\*" src/main/ --include="*.java"
```
## Phase 5: Lint/Format (optional gate)
```bash
mvn spotless:apply # if using Spotless plugin
./gradlew spotlessApply
```
## Phase 6: Diff Review
```bash
git diff --stat
git diff
```
Checklist:
- No debugging logs left (`System.out`, `log.debug` without guards)
- Meaningful errors and HTTP statuses
- Transactions and validation present where needed
- Config changes documented
## Output Template
```
VERIFICATION REPORT
===================
Build: [PASS/FAIL]
Static: [PASS/FAIL] (spotbugs/pmd/checkstyle)
Tests: [PASS/FAIL] (X/Y passed, Z% coverage)
Security: [PASS/FAIL] (CVE findings: N)
Diff: [X files changed]
Overall: [READY / NOT READY]
Issues to Fix:
1. ...
2. ...
```
## Continuous Mode
- Re-run phases on significant changes or every 30–60 minutes in long sessions
- Keep a short loop: `mvn -T 4 test` + spotbugs for quick feedback
**Remember**: Fast feedback beats late surprises. Keep the gate strict—treat warnings as defects in production systems.
This skill runs a verification loop for Spring Boot services that combines build, static analysis, tests with coverage, security scans, and a diff review before a PR or release. It produces a concise verification report showing pass/fail status for each phase and items to fix so teams can gate changes reliably. The workflow supports Maven and Gradle projects and includes quick continuous-mode checks for fast feedback.
The skill executes a phased pipeline: build (skip tests optional), static analysis (SpotBugs/PMD/Checkstyle), unit/integration/API tests with JaCoCo coverage, dependency and secret scans, optional formatter/linter gates, and a final git diff review. Each phase returns structured results (pass/fail, test counts, coverage %, CVE findings, changed files) and the skill emits a VERIFICATION REPORT template with an overall READY/NOT READY decision. It can run full checks on demand or short loops (tests + spotbugs) for continuous feedback.
Does this work with both Maven and Gradle?
Yes. The skill runs equivalent commands for Maven and Gradle, including build, static analysis, tests, JaCoCo reports, and dependency checks.
How is test coverage enforced?
The verification includes a JaCoCo report and compares coverage against a configured threshold (commonly 80%); failures are reported in the VERIFICATION REPORT.