Skip to content

sagasthy/copilot-scaffold-java

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

3 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

GitHub Copilot Java Enterprise Scaffold

A ready-to-use Copilot configuration for Java teams — covering legacy codebases (JSP/Struts, Java 7-style) and modern Spring Boot (Java 17+). Copy .github/ into your repo and Copilot becomes aware of your team's quality standards, architectural rules, and migration strategy.


Installation

cp -r .github/ /path/to/your-java-repo/.github/

Commit the .github/ directory. Copilot will pick up the files automatically in VS Code.

For agents, ensure your team has GitHub Copilot Chat enabled in VS Code (extension: GitHub.copilot-chat).


What's Included

Path Purpose
.github/copilot-instructions.md Repo-wide quality standard — always active
.github/skills/java-error-handling/ Sealed errors, Optional, no exception swallowing
.github/skills/java-streams/ Stream pipelines over imperative loops
.github/skills/java-testing/ JUnit 5 + Mockito + AssertJ patterns
.github/skills/java-domain-modeling/ Records, sealed interfaces, value objects
.github/skills/spring-architecture/ Layering, DI, transactions, DTOs
.github/skills/legacy-modernization/ Strangler fig, anti-corruption, safe migration
.github/agents/spring-expert.agent.md Architecture guidance for Spring Boot
.github/agents/legacy-modernizer.agent.md Safe JSP/Struts → Spring Boot migration
.github/agents/test-writer.agent.md JUnit 5, Mockito, Testcontainers
.github/skills/java-observability/ SLF4J + MDC, structured logging, Micrometer, Actuator
.github/skills/java-data-access/ JPA N+1, fetch strategies, pagination, projections
.github/skills/api-design/ REST conventions, error envelope, versioning, OpenAPI
.github/hooks/pre-command.sh + pre-command.json Block dangerous shell and SQL operations
.github/hooks/post-edit.sh + post-edit.json Code smell suggestions after Java edits
.githooks/pre-commit Block commits with vulnerable Maven/Gradle dependencies
.githooks/commit-msg Enforce Conventional Commits format
.githooks/pre-push Run tests before any push
scripts/setup-hooks.sh Install .githooks/ into .git/hooks/
.gitlab-ci.yml Build, test, and dependency scan on push/MR
.gitlab/merge_request_templates/Default.md MR checklist: what/why/testing/architecture

Two Layers of Knowledge

Always-on: .github/copilot-instructions.md

Injected into every Copilot suggestion, regardless of what file is open or what task is underway. Keep this file to non-negotiable rules: the quality standard, forbidden patterns, and layering laws. The shorter it is, the more it actually influences behaviour.

On-demand: .github/skills/

Skills are loaded by Copilot when they're relevant to the current task — not on every file open. Each skill has a SKILL.md with a description field that tells Copilot when to use it. The description is the routing key: it should say both what the skill covers and the conditions under which it applies.

.github/skills/
└── java-error-handling/
    └── SKILL.md          ← frontmatter: name + description (routing key)
                           ← body: the actual patterns and examples

This matters: a skill about stream pipelines costs zero context when you're writing a domain model. With always-on instruction files, you pay for everything all the time.

Write the description carefully. "Use when writing or reviewing error handling, exception types, or null safety in Java code" loads the skill at the right moment. "Java patterns" loads it for everything.

Show, don't describe. Every principle should have a before/after code block. Copilot reasons in code. Abstract principles without examples are ignored.


Agents

Agents are purpose-built assistants you invoke with @agent-name in Copilot Chat.

@spring-expert

Use when designing or reviewing Spring Boot code: service layer, JPA, REST controllers, transaction boundaries, DI wiring. Ask it to review a class for architectural violations or to generate new code that follows your team's conventions.

@spring-expert review this service class for layering violations
@spring-expert generate a REST endpoint for creating an order

@legacy-modernizer

Use when touching legacy JSP/Struts code or planning a migration. It will assess risk, identify seams, and propose incremental steps rather than rewrites.

@legacy-modernizer how do I extract this Struts Action into a Spring service?
@legacy-modernizer what's the safest way to add a new endpoint alongside this legacy flow?

@test-writer

Use when you need tests for existing code, or want to validate test quality. It writes behavior-focused tests, not implementation tests — your tests survive refactors.

@test-writer write unit tests for OrderService.createOrder
@test-writer add an integration test for the /orders POST endpoint using Testcontainers

Hook System

Each hook consists of two files: a .sh script that contains the logic, and a .json config that registers it with Copilot.

pre-command.sh / pre-command.json

Runs before Copilot executes a terminal command. Blocks destructive operations:

  • Force push without --force-with-lease
  • rm -rf on root paths
  • DROP TABLE / DROP DATABASE / DROP SCHEMA
  • DELETE FROM without a WHERE clause
  • TRUNCATE TABLE
  • chmod 777

Adapt the patterns in pre-command.sh to match your team's guardrails.

commit-msg (git hook)

Enforces Conventional Commits format on every commit message.

<type>(<optional scope>): <description>

Allowed types: feat, fix, docs, style, refactor, perf, test, build, ci, chore, revert. Append ! for breaking changes. The hook prints examples and the full type list when the format is wrong.

To bypass: SKIP_COMMIT_MSG=1 git commit ...


pre-push (git hook)

Runs the full test suite (mvn test / ./gradlew test) before any push. Detects Maven or Gradle automatically. Blocks the push if tests fail and prints the bypass command.

To bypass: SKIP_TESTS=1 git push ...


pre-commit (git hook)

Scans pom.xml (Maven) or build.gradle / build.gradle.kts (Gradle) for known CVEs using the OWASP Dependency-Check plugin before every commit that stages a build file. Blocks the commit if any dependency has a CVSS score ≥ 7 (configurable).

Setup — run once after cloning:

./scripts/setup-hooks.sh

Behaviour:

  • Only triggers when pom.xml, build.gradle, or build.gradle.kts is staged — other commits are unaffected
  • Writes a full HTML report to target/dependency-check-report/ (Maven) or build/dependency-check-report/ (Gradle)
  • On first run, downloads the NVD database (~few minutes); subsequent runs are fast
  • If both build files are staged (polyglot repo), both are scanned

Gradle setup — the OWASP plugin must be applied in your build file before the hook can scan it. The hook will print setup instructions if it's missing:

// build.gradle
plugins {
    id "org.owasp.dependencycheck" version "10.0.4"
}
dependencyCheck {
    failBuildOnCVSS = 7
    outputDirectory = "build/dependency-check-report"
    suppressionFile = "dependency-check-suppressions.xml"  // optional
}
// build.gradle.kts
plugins {
    id("org.owasp.dependencycheck") version "10.0.4"
}
dependencyCheck {
    failBuildOnCVSS = 7.0f
    outputDirectory = "build/dependency-check-report"
    suppressionFile = "dependency-check-suppressions.xml"  // optional
}

Configuration:

Variable Default Purpose
CVSS_THRESHOLD 7 Minimum score to fail (010)
SKIP_DEP_CHECK 0 Set to 1 to bypass for a single commit
# Raise threshold to critical only
CVSS_THRESHOLD=9 git commit -m "..."

# Emergency bypass
SKIP_DEP_CHECK=1 git commit -m "..."

Suppressing false positives — if a CVE does not apply to your usage, add a suppression file:

# Create dependency-check-suppressions.xml in the repo root
# See: https://jeremylong.github.io/DependencyCheck/general/suppression.html

post-edit.sh / post-edit.json

Runs after Copilot edits a .java file. Surfaces common code smells:

  • for loops over collections → suggest stream pipelines
  • catch (Exception / catch (Throwable → catch specific types
  • Optional.get() without guard → unsafe access risk
  • new RuntimeException( / new Exception( → define a typed domain exception
  • @Autowired on a field → constructor injection
  • return null → consider returning Optional<T>
  • System.out.println → use SLF4J logger

These are suggestions, not blocks. The developer sees the message and decides.


CI Pipeline

.gitlab-ci.yml runs on every push and merge request. It auto-detects Maven or Gradle using rules: exists: and runs only the relevant jobs.

Job Stage What it does
build-maven / build-gradle build Compile + run full test suite
dep-check-maven / dep-check-gradle security OWASP Dependency-Check scan (non-blocking by default)

Making the dependency scan blocking: remove allow_failure: true from the relevant dep-check job in .gitlab-ci.yml. The local pre-commit hook enforces it before a commit lands; the CI job closes the gap for contributors who bypassed the hook.

Failed test reports and CVE scan reports are uploaded as job artifacts (retained 7 and 30 days respectively).


MR Template

.gitlab/merge_request_templates/Default.md auto-populates the description when an MR is opened in GitLab. It includes:

  • What changed — 2-4 bullets describing the change
  • Why — motivation and ticket link
  • Testing done — checklist: unit tests, integration tests, manual verification
  • Architecture checklist — controller/service separation, constructor injection, transaction placement, ControllerAdvice, no entity leakage

Runbooks

Debug Runbook (4-Session Protocol)

When a bug is hard to pin down, open four Copilot Chat sessions in parallel — one per hypothesis — rather than exploring sequentially. Each session gets a single focused question. Compare conclusions before acting.

Example for a NullPointerException in order processing:

Session Hypothesis
1 order.getCustomer() is null — trace where customer is set
2 @Transactional boundary issue — lazy-loaded relation accessed outside session
3 Race condition — two threads modify the same entity
4 Missing null guard in a recent commit — git log --oneline -20 -- OrderService.java

All four run at the same time. You converge on the answer faster than one long conversation that goes down wrong paths.


Code Review Runbook

Before asking Copilot to fix code in a review:

  1. Name the problem first. Ask @spring-expert what's wrong with this code? before asking it to fix anything. You need to understand the issue, not just apply the patch.
  2. Verify the fix composes. If the suggested fix adds a null check, ask why the value is null. Compensatory fixes (patching the symptom) accumulate into unmaintainable code.
  3. Check the boundary. Every service method should be reviewable for: what comes in (input type), what goes out (return type or exception), and what it depends on (injected services). If any of these are unclear, that's the review feedback.

Extending the Scaffold

Adding a skill:

  1. Create .github/skills/<topic>/SKILL.md
  2. Set name to match the directory name
  3. Write a description that says what it covers and when to use it — this is how Copilot decides to load it
  4. Add before/after examples — minimum two per principle
  5. Add a row to the table above

Adding an agent:

  1. Create .github/agents/<name>.agent.md
  2. Keep the system prompt under 500 words — specificity beats length
  3. Document usage in the Agents section above

Adding a git hook:

  1. Drop an executable script into .githooks/ with the standard git hook name (e.g. pre-push, commit-msg)
  2. Re-run ./scripts/setup-hooks.sh to install it
  3. Document it in the Hook System section above

Raising the quality bar: Edit .github/copilot-instructions.md. This file applies to every suggestion in the repo. Be deliberate — every line costs context budget on every interaction.


References

About

Copilot scaffold for Java enterprise teams: custom skills, agents, and guardrail hooks for Spring Boot and legacy modernization.

Resources

Stars

Watchers

Forks

Releases

No releases published

Packages

 
 
 

Contributors

Languages