springboot-verification
affaan-m/everything-claude-code
Automated verification loop for Spring Boot projects: build, static analysis, tests with coverage, security scans, and diff review.
What is springboot-verification?
Runs a multi-phase verification pipeline for Spring Boot services before PRs and deployments. Executes build, static analysis (spotbugs, PMD, checkstyle), unit/integration/API tests with coverage reporting, dependency and secrets scanning, and diff review to catch issues early.
- Build verification with Maven or Gradle
- Static analysis with spotbugs, PMD, and checkstyle
- Unit tests with mocked dependencies using Mockito
- Integration tests against real databases via Testcontainers
- API layer testing with MockMvc
- Dependency CVE scanning with OWASP Dependency-Check
How to install springboot-verification
npx skills add https://github.com/affaan-m/everything-claude-code --skill springboot-verification- Maven or Gradle build tool configured
- Java project with Spring Boot setup
- Optional: Testcontainers for integration tests
- Optional: git-secrets configured for enhanced scanning
How to use springboot-verification
- 1.Run Phase 1 (Build): Execute mvn clean verify -DskipTests or gradlew clean assemble -x test and fix any build errors
- 2.Run Phase 2 (Static Analysis): Execute spotbugs, PMD, and checkstyle checks via Maven or Gradle
- 3.Run Phase 3 (Tests + Coverage): Run full test suite and generate JaCoCo coverage report, verify 80%+ coverage threshold
- 4.Run Phase 4 (Security Scan): Check for dependency CVEs with OWASP Dependency-Check and scan for hardcoded secrets
- 5.Run Phase 5 (Lint/Format): Apply code formatting with Spotless if configured
- 6.Run Phase 6 (Diff Review): Review git diff --stat and git diff against the provided checklist
- 7.Generate verification report documenting pass/fail status for each phase and overall readiness
Use cases
- Pre-pull request verification for Spring Boot services
- Post-refactoring validation to ensure no regressions
- Pre-deployment checks for staging or production environments
- Dependency upgrade verification to catch breaking changes
- Continuous verification during long development sessions
- Spring Boot developers
- Backend engineers managing microservices
- DevOps/SRE teams preparing releases
- Teams with strict code quality and security requirements
springboot-verification FAQ
Run before opening pull requests, after major refactoring or dependency upgrades, and pre-deployment to staging or production. In long sessions, re-run every 30–60 minutes on significant changes.
Stop immediately and fix the build errors. Do not proceed to subsequent phases until the build passes cleanly.
Run mvn jacoco:report or gradlew jacocoTestReport and verify the coverage percentage (lines and branches) meets your threshold, typically 80%+.
Unit tests with mocked dependencies (Mockito), integration tests against real databases (Testcontainers), and API layer tests (MockMvc).
Use grep patterns to find hardcoded passwords, API keys, and secrets in source files, or configure git-secrets to scan git history automatically.
Full instructions (SKILL.md)
Source of truth, from affaan-m/everything-claude-code.
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." metadata: origin: ECC
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
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):
mvn -T 4 spotbugs:check pmd:check checkstyle:check
Gradle (if configured):
./gradlew checkstyleMain pmdMain spotbugsMain
Phase 3: Tests + Coverage
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:
@ExtendWith(MockitoExtension.class)
class UserServiceTest {
@Mock private UserRepository userRepository;
@InjectMocks private UserService userService;
@Test
void createUser_validInput_returnsUser() {
var dto = new CreateUserDto("Alice", "alice@example.com");
var expected = new User(1L, "Alice", "alice@example.com");
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", "existing@example.com");
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:
@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", "alice@example.com"));
var found = userRepository.findByEmail("alice@example.com");
assertThat(found).isPresent();
assertThat(found.get().getName()).isEqualTo("Alice");
}
}
API Tests with MockMvc
Test controller layer with full Spring context:
@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", "alice@example.com");
when(userService.create(any())).thenReturn(user);
mockMvc.perform(post("/api/users")
.contentType(MediaType.APPLICATION_JSON)
.content("""
{"name": "Alice", "email": "alice@example.com"}
"""))
.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
# 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)
mvn spotless:apply # if using Spotless plugin
./gradlew spotlessApply
Phase 6: Diff Review
git diff --stat
git diff
Checklist:
- No debugging logs left (
System.out,log.debugwithout 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.
Related skills
More from affaan-m/everything-claude-code and the wider catalog.
security-review
Security checklist and patterns for authentication, input validation, secrets, and sensitive features.
golang-patterns
Idiomatic Go patterns, best practices, and conventions for building robust, efficient, and maintainable applications.
coding-standards
Baseline coding conventions for naming, readability, immutability, and quality across projects.
frontend-patterns
React and Next.js patterns for components, state management, performance, and modern frontend practices.
backend-patterns
REST/GraphQL API design, database optimization, and server-side patterns for Node.js, Express, and Next.js.
golang-testing
Go testing patterns: table-driven tests, subtests, benchmarks, fuzzing, and TDD methodology.