PluginBench
Skill
Review
Audit score 70

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
Prerequisites
  • Maven or Gradle build tool configured
  • Java project with Spring Boot setup
  • Optional: Testcontainers for integration tests
  • Optional: git-secrets configured for enhanced scanning
Claude Code
Cursor
Windsurf
Cline

How to use springboot-verification

  1. 1.Run Phase 1 (Build): Execute mvn clean verify -DskipTests or gradlew clean assemble -x test and fix any build errors
  2. 2.Run Phase 2 (Static Analysis): Execute spotbugs, PMD, and checkstyle checks via Maven or Gradle
  3. 3.Run Phase 3 (Tests + Coverage): Run full test suite and generate JaCoCo coverage report, verify 80%+ coverage threshold
  4. 4.Run Phase 4 (Security Scan): Check for dependency CVEs with OWASP Dependency-Check and scan for hardcoded secrets
  5. 5.Run Phase 5 (Lint/Format): Apply code formatting with Spotless if configured
  6. 6.Run Phase 6 (Diff Review): Review git diff --stat and git diff against the provided checklist
  7. 7.Generate verification report documenting pass/fail status for each phase and overall readiness

Use cases

Good for
  • 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
Who it's for
  • Spring Boot developers
  • Backend engineers managing microservices
  • DevOps/SRE teams preparing releases
  • Teams with strict code quality and security requirements

springboot-verification FAQ

When should I run this verification loop?

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.

What if the build fails in Phase 1?

Stop immediately and fix the build errors. Do not proceed to subsequent phases until the build passes cleanly.

How do I ensure test coverage meets requirements?

Run mvn jacoco:report or gradlew jacocoTestReport and verify the coverage percentage (lines and branches) meets your threshold, typically 80%+.

What types of tests are included?

Unit tests with mocked dependencies (Mockito), integration tests against real databases (Testcontainers), and API layer tests (MockMvc).

How do I scan for secrets in my codebase?

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.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.