Automatic Code Review with GitHub Copilot
Code review is one of the pillars of software quality, but it is also one of the most expensive processes in terms of time and resources. In many teams, Pull Requests remain waiting for review for hours or even days, slowing down the entire development cycle. GitHub Copilot Code Review addresses this problem by providing AI-powered reviews that complete the analysis in less than 30 seconds.
In this article we will explore how to configure automatic review, how the analysis process works, how to customize review rules to meet the team's standards, and how to integrate the AI review with human review to maximize code quality.
Series Overview
| # | Article | Focus |
|---|---|---|
| 1 | Foundation and Mindset | Setup and mindset |
| 2 | Ideation and Requirements | From idea to MVP |
| 3 | Backend Architecture | API and database |
| 4 | Frontend Structure | UI and components |
| 5 | Prompt Engineering | Prompts and MCP Agents |
| 6 | Testing and Quality | Unit, integration, E2E |
| 7 | Documentation | README, API docs, ADR |
| 8 | Deploy and DevOps | Docker, CI/CD |
| 9 | Evolution | Scalability and maintenance |
| 10 | Coding Agent | Autonomous development |
| 11 | You are here → Code Review | AI-powered review |
| 12 | Copilot Edits and Agent Mode | Multi-file editing |
| 13 | GitHub Spark | AI-native micro-apps |
| 14 | Copilot Spaces and Memory | Shared context |
| 15 | AI Models | Multi-model and selection |
| 16 | Customization | Custom instructions |
| 17 | Enterprise and Business | Organizational adoption |
| 18 | Extensions and Marketplace | Copilot Extensions |
| 19 | Security | Security and compliance |
Why Automatic Code Review
Manual code review presents several challenges that impact team productivity and software quality. Understanding these problems helps appreciate the value of automatic review.
Problems with Traditional Code Review
| Problem | Impact | Frequency |
|---|---|---|
| Wait time | PRs blocked for hours/days, context switching for the reviewer | Very frequent |
| Inconsistency | Different reviewers have different standards, subjective feedback | Frequent |
| Review fatigue | After the third PR, attention drops and changes are approved without checking | Frequent |
| Partial coverage | The reviewer focuses on logic and overlooks security, performance, edge cases | Very frequent |
| Bottleneck | Few senior reviewers become a bottleneck for the entire team | Frequent in small teams |
| Knowledge gaps | The reviewer is not familiar with that part of the codebase | Occasional |
Copilot's automatic review does not replace human review, but complements it. The AI handles mechanical checks (style, patterns, common bugs, security), freeing the human reviewer to focus on aspects that require judgment: architecture, design, readability, and correctness of business logic.
Task Division: AI vs Human
| Aspect | Copilot Code Review | Human Review |
|---|---|---|
| Style and formatting | Excellent | Not necessary |
| Known bug patterns | Excellent | Complementary |
| Security vulnerabilities | Good | Essential for complex cases |
| Performance issues | Good for known patterns | Essential for optimizations |
| Logical correctness | Limited | Essential |
| Architectural decisions | Not applicable | Essential |
| Naming and readability | Good | Complementary |
| Test coverage | Good | Complementary |
| Speed | < 30 seconds | 15-60 minutes |
| Consistency | Always the same | Variable |
| Availability | 24/7 | Working hours |
Configuring Automatic Review
Configuring automatic review is done at the repository or organization level. There are different activation strategies, from reviewing all PRs to selective review based on branches or paths.
Automatic Review for All PRs
The simplest configuration activates Copilot review on every Pull Request opened in the repository. This mode is ideal for teams that want an automatic first level of control on all code.
# In the repository Settings page:
# 1. Go to Settings > Code review > Copilot
# 2. Select "Automatic" under "Copilot code review"
# 3. Choose the trigger:
# - "All pull requests" - automatic review on every PR
# - "When requested" - only when manually requested
# To enable via GitHub API:
# PATCH /repos/{{ '{' }}owner}/{{ '{' }}repo}
# {{ '{' }}
# "copilot_code_review": {{ '{' }}
# "automatic": true,
# "trigger": "all_pull_requests"
# }
# }
# At the organization level (for all repositories):
# Organization Settings > Copilot > Policies > Code Review
# Enable: "Automatic code review for all repositories"
Selective Review: Branches and Paths
In large projects, you may want to activate automatic review only for certain situations: PRs targeting the main branch, changes to critical paths, or contributions from specific teams.
# .github/workflows/copilot-review.yml
name: Request Copilot Code Review
on:
pull_request:
types: [opened, synchronize]
branches:
- main
- release/*
paths:
- 'src/**'
- 'lib/**'
- '!src/**/*.test.ts'
- '!src/**/*.spec.ts'
- '!docs/**'
jobs:
request-review:
runs-on: ubuntu-latest
steps:
- name: Request Copilot Review
uses: actions/github-script@v7
with:
script: |
// Request review only if the PR has more than 10 modified lines
const {{ '{' }} data: files } = await github.rest.pulls.listFiles({{ '{' }}
owner: context.repo.owner,
repo: context.repo.repo,
pull_number: context.payload.pull_request.number
});
const totalChanges = files.reduce((sum, f) =>
sum + f.additions + f.deletions, 0);
if (totalChanges > 10) {{ '{' }}
await github.rest.pulls.requestReviewers({{ '{' }}
owner: context.repo.owner,
repo: context.repo.repo,
pull_number: context.payload.pull_request.number,
reviewers: ['copilot'] // Request review from Copilot
});
console.log(`Requested Copilot review for PR #${{ '{' }}context.payload.pull_request.number}`);
} else {{ '{' }}
console.log(`Skipped: only ${{ '{' }}totalChanges} lines changed`);
}
Support for Draft PRs
Copilot can also analyze Draft Pull Requests, allowing you to receive early feedback before the PR is ready for human review. This accelerates the feedback cycle and reduces the number of iterations needed.
Strategies for Draft PRs
| Strategy | When to Use It | Advantage |
|---|---|---|
| Early review | PR in early development stage | Identify structural problems before completing the work |
| Iterative review | Complex PR with many changes | Receive feedback on each push, correct incrementally |
| Pre-review | Before requesting human review | Resolve mechanical issues before human review |
How the Review Works
When Copilot analyzes a Pull Request, it performs a series of in-depth checks on the modified code. The process is designed to be fast (less than 30 seconds) while covering a broad spectrum of potential issues.
Analysis Process
- Context gathering: Copilot reads the PR diff, context files (
copilot-instructions.md), and the project structure - Category analysis: Each change is analyzed across different problem categories (bugs, security, performance, style)
- Comment generation: For each issue found, Copilot generates an inline comment with a problem description and suggested fix
- Code suggestion: When possible, a replacement code block is provided with the "Implement suggestion" button
- Summary: A general comment summarizes the main findings and the risk level
Review Categories
Copilot analyzes the code through different lenses, each focused on a specific aspect of software quality.
Code Review Analysis Categories
| Category | What It Verifies | Issue Examples | Severity |
|---|---|---|---|
| Bugs and Correctness | Logic errors, null reference, off-by-one, race condition | Array index out of bounds, missing null handling | Critical |
| Security | Common vulnerabilities: injection, XSS, CSRF, auth bypass | Concatenated SQL, unsanitized input, secrets in code | Critical |
| Performance | N+1 queries, inefficient loops, memory leaks, missing indexes | SELECT * in loop, non-memoized array, unremoved event listener | High |
| Best Practices | Violated patterns, anti-patterns, non-idiomatic code | Callback hell, God class, Single Responsibility violation | Medium |
| Code Quality | Naming, complexity, duplication, readability | Variables with generic names, functions too long, duplicate code | Medium |
| Documentation | Missing comments, outdated docs, incomplete JSDoc | Public function without JSDoc, outdated README | Low |
| Testing | Missing coverage, fragile tests, excessive mocking | New function without test, test that verifies implementation | Medium |
The "Implement Suggestion" Button
One of the most powerful features of Copilot's review is the "Implement suggestion" button. When Copilot identifies a problem and proposes a fix, the button allows you to apply the change with a single click, automatically creating a commit on the PR.
Suggestion Workflow
- Copilot identifies a problem in the code
- Generates an inline comment with the problem description
- Proposes a replacement code block
- The PR author can click "Implement suggestion"
- GitHub automatically creates a commit with the fix
- The PR is updated with the change
- If continuous review is enabled, Copilot re-evaluates the code
Continuous Review
When you enable continuous review, Copilot automatically analyzes every new push to the PR. This means that every time the author adds commits to respond to review comments or to continue development, Copilot re-evaluates the changes and provides new feedback.
Advantages of Continuous Review
- Immediate feedback on every push
- Verifies that fixes actually resolve the problems
- Detects new problems introduced during corrections
- Reduces the human review time required
- Keeps the PR always "review-ready"
Configuration
- Activation: Settings > Copilot > Continuous Review
- Trigger: every push (default) or only significant pushes
- Throttling: max 1 review every 5 minutes per PR
- Scope: only files modified since the last review
- Notifications: summary comment for each cycle
Custom Review Instructions
One of the most important features is the ability to customize review rules to align them with the specific standards of the team and the organization. Custom review instructions allow you to define what Copilot should look for and how it should evaluate the code.
Configuring the Instructions
Custom instructions are defined in a configuration file in the repository. Copilot reads them before each review and uses them as a guide for the analysis.
# Copilot Code Review Instructions
## Team Code Standards
### TypeScript
- Use `strict: true` in tsconfig.json
- Never use `any`: prefer `unknown` with type guard
- Prefer `interface` over `type` for objects
- Use `readonly` for properties that must not change
- Always enumerate cases in switch on union type
- Use optional chaining (`?.`) instead of manual null checks
- Prefer `const` over `let`, never `var`
### Naming Conventions
- Classes and interfaces: PascalCase (e.g. `UserService`, `IUserRepository`)
- Variables and functions: camelCase (e.g. `getUserById`, `isActive`)
- Constants: UPPER_SNAKE_CASE (e.g. `MAX_RETRY_COUNT`)
- Files: kebab-case (e.g. `user-service.ts`)
- Tests: [name].test.ts or [name].spec.ts
- Booleans: prefix is/has/should (e.g. `isActive`, `hasPermission`)
### Error Handling
- Use custom error classes (AppError, NotFoundError, etc.)
- Do not catch errors without re-throwing or logging them
- Include context in the error: `throw new NotFoundError('User', userId)`
- Do not use try/catch for flow control
- All API endpoints must have an error handler
### Security (HIGH PRIORITY)
- Never concatenate user input in SQL queries
- Validate ALL inputs with class-validator
- Sanitize HTML output to prevent XSS
- Verify authorization for every protected endpoint
- Do not expose stack traces or internal details in API responses
- Rate limiting on public endpoints
- Secrets only via environment variables
### Performance
- Avoid N+1 queries: use include/eager loading
- Mandatory pagination for lists: max 100 items
- Caching for frequently accessed data
- Async/await for I/O operations
- Avoid blocking synchronous operations
### Tests
- Every new public function must have at least one test
- Tests must be independent (no execution order)
- Mock only external dependencies (database, API, file system)
- Descriptive names: "should [action] when [condition]"
- At least one test for the error case
### Angular (Frontend)
- Use standalone components
- Signals for state management
- OnPush change detection for all components
- Lazy loading for non-critical routes
- No `subscribe()` in templates: use async pipe or toSignal
Language-Specific Rules
Instructions can be specified per language, allowing you to have different standards for backend and frontend, or for different languages in the same project.
# Language-specific rules
## Python (ML Backend)
- Type hints mandatory for all parameters and return
- Google style docstring for every public function
- Use `dataclasses` or `pydantic` for data objects
- Black formatting (line length 88)
- Imports sorted with isort
## SQL (Migrations)
- Never DROP TABLE without a documented backup plan
- ALTER TABLE must be reversible
- Index for every foreign key
- Column names in snake_case
- SQL comment for each migration explaining the "why"
## YAML/Config
- Comments for every non-obvious section
- Secrets referenced via variables, never hardcoded values
- Schema validation for configuration files
Architectural Patterns to Verify
# Architectural Patterns
## Layered Architecture
The project follows a layered architecture:
- Controller → Service → Repository
- Controllers MUST NOT access repositories directly
- Repositories MUST NOT contain business logic
- Each layer communicates only with the layer immediately below
## Dependency Injection
- All dependencies injected via constructor
- Interfaces for dependencies (IUserService, IUserRepository)
- No manual singleton pattern: use the DI container
## Event-Driven Communication
- Cross-service communication via events
- Events must be immutable
- Each event has a unique type and a typed payload
- Event handlers must be idempotent
## VERIFY:
- If a controller calls a repository directly: ERROR
- If a service instantiates a dependency directly: WARNING
- If a SQL query appears outside a repository: ERROR
- If business logic appears in a controller: WARNING
Practical Review Examples
To better understand how Copilot analyzes code, let us look at some concrete examples of problems that automatic review identifies and the suggestions it proposes.
Example 1: SQL Injection Vulnerability
// File: src/repositories/user.repository.ts
// Line added in the PR:
async findByName(name: string): Promise<User[]> {{ '{' }}
const query = `SELECT * FROM users WHERE name LIKE '%${{ '{' }}name}%'`;
return this.db.raw(query);
}
Copilot Comment
Severity: Critical - SQL Injection Vulnerability
The name parameter is interpolated directly into the SQL query
without sanitization. An attacker could inject arbitrary SQL code.
Suggestion: Use parameterized queries to prevent SQL injection.
async findByName(name: string): Promise<User[]> {{ '{' }}
return this.db.query(
'SELECT * FROM users WHERE name LIKE $1',
[`%${{ '{' }}name}%`]
);
}
Example 2: Performance - N+1 Query
// File: src/services/order.service.ts
async getOrdersWithDetails(userId: string): Promise<OrderDetail[]> {{ '{' }}
const orders = await this.orderRepo.findByUserId(userId);
const result = [];
for (const order of orders) {{ '{' }}
const items = await this.itemRepo.findByOrderId(order.id);
const customer = await this.customerRepo.findById(order.customerId);
result.push({{ '{' }} ...order, items, customer });
}
return result;
}
Copilot Comment
Severity: High - N+1 Query Pattern
This code executes 2N+1 database queries (1 for orders + N for items + N for customers). With 100 orders, that means 201 database queries. This will significantly degrade performance as data grows.
Suggestion: Use eager loading or batch queries to reduce to 3 total queries.
async getOrdersWithDetails(userId: string): Promise<OrderDetail[]> {{ '{' }}
const orders = await this.orderRepo.findByUserId(userId);
if (orders.length === 0) return [];
const orderIds = orders.map(o => o.id);
const customerIds = [...new Set(orders.map(o => o.customerId))];
// Batch query: 3 total queries instead of 2N+1
const [allItems, allCustomers] = await Promise.all([
this.itemRepo.findByOrderIds(orderIds),
this.customerRepo.findByIds(customerIds)
]);
const itemsByOrder = new Map();
for (const item of allItems) {{ '{' }}
if (!itemsByOrder.has(item.orderId)) {{ '{' }}
itemsByOrder.set(item.orderId, []);
}
itemsByOrder.get(item.orderId).push(item);
}
const customersById = new Map(
allCustomers.map(c => [c.id, c])
);
return orders.map(order => ({{ '{' }}
...order,
items: itemsByOrder.get(order.id) || [],
customer: customersById.get(order.customerId)
}));
}
Example 3: Best Practice - Error Handling
// File: src/controllers/payment.controller.ts
async processPayment(req: Request, res: Response) {{ '{' }}
try {{ '{' }}
const result = await this.paymentService.charge(
req.body.amount,
req.body.cardToken
);
res.json(result);
} catch (e) {{ '{' }}
console.log(e);
res.status(500).json({{ '{' }} error: 'Something went wrong' });
}
}
Copilot Comment
Severity: Medium - Multiple Issues
- Unvalidated input:
req.body.amountandreq.body.cardTokenare not validated. Malformed input could cause errors in the payment service. - Error swallowing:
console.logis not structured logging. In production this message could be lost. - Generic error: All errors return 500, even when the error is invalid input (400) or a declined payment (402).
- Internal details exposed: The original error is logged but the response message is too generic to be useful to the client.
async processPayment(req: Request, res: Response) {{ '{' }}
// Input validation
const {{ '{' }} amount, cardToken } = req.body;
if (!amount || typeof amount !== 'number' || amount <= 0) {{ '{' }}
return res.status(400).json({{ '{' }}
error: 'Invalid amount',
detail: 'Amount must be a positive number'
});
}
if (!cardToken || typeof cardToken !== 'string') {{ '{' }}
return res.status(400).json({{ '{' }}
error: 'Invalid card token',
detail: 'Card token is required'
});
}
try {{ '{' }}
const result = await this.paymentService.charge(amount, cardToken);
res.json(result);
} catch (error) {{ '{' }}
logger.error('Payment processing failed', {{ '{' }}
amount,
error: error.message,
stack: error.stack,
requestId: req.id
});
if (error instanceof PaymentDeclinedError) {{ '{' }}
return res.status(402).json({{ '{' }}
error: 'Payment declined',
detail: error.declineReason
});
}
if (error instanceof ValidationError) {{ '{' }}
return res.status(400).json({{ '{' }}
error: 'Validation error',
detail: error.message
});
}
res.status(500).json({{ '{' }}
error: 'Internal server error',
requestId: req.id // For debugging without exposing details
});
}
}
Available Plans
Copilot's automatic code review is not available on all plans. Here is an overview of the features available for each plan.
Availability by Plan
| Feature | Individual | Business | Enterprise |
|---|---|---|---|
| On-demand review | Not available | Available | Available |
| Automatic review | Not available | Available | Available |
| Continuous review | Not available | Available | Available |
| Custom review instructions | Not available | Available | Available |
| Organization policies | Not applicable | Basic | Advanced |
| Audit log | Not available | Basic | Complete |
| Review metrics | Not available | Basic | Advanced with dashboard |
| Codebase fine-tuning | Not available | Not available | Available |
Integration with the Existing PR Workflow
Copilot's review integrates naturally into the team's existing PR workflow. Here is how to configure a review process that combines AI and human effectively.
Recommended Workflow
Integrated Review Process
- PR Opened: The developer opens the PR with description and context
- AI Review (30 sec): Copilot automatically analyzes and leaves comments
- Quick Fixes: The author applies mechanical suggestions with "Implement suggestion"
- Updated AI Review: Copilot re-evaluates after fixes (if continuous review is enabled)
- Human Review: The human reviewer focuses on architecture, logic, and design
- Iteration: Any changes requested by the human reviewer
- Approval and Merge: PR approved by at least one human reviewer
# Recommended Branch Protection Rules to integrate Copilot
# Settings > Branches > Branch protection rules > main
# Mandatory rules:
# 1. Require pull request reviews: 1 reviewer minimum
# 2. Require review from Code Owners: enabled
# 3. Dismiss stale reviews: enabled (when new pushes invalidate reviews)
# 4. Require status checks: enabled
# - Required checks:
# - ci/build (CI pipeline)
# - ci/test (test suite)
# - security/codeql (static analysis)
# 5. Require Copilot code review: enabled (optional)
#
# Note: Copilot review can be required as a mandatory check,
# but it is recommended NOT to make it blocking
# to avoid false positives that slow down merging.
#
# Recommended strategy:
# - Copilot review: mandatory but not blocking
# - Human reviewer: mandatory and blocking
# - CI/CD checks: mandatory and blocking
Combining AI and Human Review
Responsibilities in the Review Process
| Who | What to Verify | When |
|---|---|---|
| Copilot (Automatic) | Common bugs, vulnerabilities, style, anti-patterns, performance patterns | Immediately when the PR is opened |
| CI/CD Pipeline | Build, tests, linting, coverage, security scan | In parallel with the AI review |
| Code Owner | Architecture, design, domain correctness, impact on other modules | After AI review and CI are green |
| Tech Lead | Architectural decisions, trade-offs, alignment with roadmap | Only for PRs with architectural impact |
| Security Team | Complex vulnerabilities, compliance, data handling | Only for PRs that touch auth, payment, PII |
Metrics and Reporting
Measuring the impact of automatic review is essential to justify the investment and optimize the process. GitHub provides dedicated metrics to evaluate the effectiveness of Copilot's review.
Key Metrics
| Metric | What It Measures | Ideal Target | How to Improve It |
|---|---|---|---|
| Average time to first review | From PR opening to first comment | < 5 minutes | Enable automatic review |
| Accepted suggestions | % of Copilot suggestions applied | 40-60% | Improve custom instructions |
| Review cycles | Number of iterations before merge | < 3 | Mechanical fixes before human review |
| Time to merge | From PR opening to merge | < 24 hours | Reduce wait with AI review + clear process |
| Post-review bugs in production | Bugs found after merge | < 2% | Analyze escaped bugs and update instructions |
| False positives | Suggestions ignored because they were incorrect | < 20% | Refine custom instructions and context |
Review Dashboard
For Enterprise teams, GitHub offers a dedicated dashboard that aggregates review metrics across the entire team and organization. This dashboard allows you to identify trends, areas for improvement, and the overall impact of AI on code quality.
Team Metrics
- Average review time per repository
- Suggestion distribution by category
- Top issues found by AI review
- Weekly trend of review cycles
- Before/after Copilot comparison
Individual Metrics
- Suggestions accepted per developer
- Recurring issues per developer
- Response time to comments
- Reduction in iterations over time
- Suggested areas for improvement
Best Practices to Maximize Quality
To get the most out of automatic review, it is important to follow some best practices that improve the quality of feedback and reduce false positives.
Operational Best Practices
| Practice | Why | How |
|---|---|---|
| Keep instructions up to date | Outdated instructions generate false positives | Quarterly review of the copilot-review-instructions.md file |
| Small and focused PRs | Copilot analyzes small, coherent diffs better | Max 400 lines per PR, one concept per PR |
| Detailed PR description | Context improves analysis quality | PR template with "what" and "why" sections |
| Apply mechanical fixes right away | Frees the human reviewer for important issues | Use "Implement suggestion" before requesting human review |
| Feedback loop | Copilot improves with more precise instructions | When a suggestion is wrong, update the instructions |
| Do not ignore warnings | Today's warnings are tomorrow's bugs | Fix or document why the warning is a false positive |
Mistakes to Avoid
- Making AI review blocking without refined instructions
- Systematically ignoring suggestions
- Not customizing instructions for the project
- Relying solely on AI review without human review
- Huge PRs that confuse the analysis
- Not providing context in the PR description
Winning Strategies
- AI for the first pass, human for the second
- Specific instructions for each area of the codebase
- PR templates that guide both the author and the AI
- Retrospectives on ignored suggestions
- Clear escalation for security issues
- Weekly metrics to track improvement
Summary and Next Steps
Automatic code review with Copilot transforms a traditionally slow and inconsistent process into a fast, comprehensive, and always-available first level of analysis. It does not replace human review, but makes it more efficient by allowing reviewers to focus on aspects that require human judgment.
Key Takeaways
- Speed: Review in less than 30 seconds, immediate feedback on every push.
- Consistency: Same standards applied to all PRs, 24/7, without review fatigue.
- Customization: Custom instructions align the review to team standards.
- Integration: Fits naturally into the existing PR workflow, complementing human review.
- Measurability: Concrete metrics to evaluate and improve the review process.
Series Progress
| # | Article | Status |
|---|---|---|
| 1 | Foundation and Mindset | Completed |
| 2 | Ideation and Requirements | Completed |
| 3 | Backend Architecture | Completed |
| 4 | Frontend Structure | Completed |
| 5 | Prompt Engineering | Completed |
| 6 | Testing and Quality | Completed |
| 7 | Documentation | Completed |
| 8 | Deploy and DevOps | Completed |
| 9 | Evolution | Completed |
| 10 | Coding Agent | Completed |
| 11 | Code Review | Completed |
| 12 | Copilot Edits and Agent Mode | Next |
| 13 | GitHub Spark | Coming soon |
| 14 | Copilot Spaces and Memory | Coming soon |
| 15 | AI Models | Coming soon |
| 16 | Customization | Coming soon |
| 17 | Enterprise and Business | Coming soon |
| 18 | Extensions and Marketplace | Coming soon |
| 19 | Security | Coming soon |
In the next article we will explore Copilot Edits and Agent Mode, discovering how to use multi-file editing, the agent mode with auto-healing, Plan Mode for complex tasks, and Next Edit Suggestions for fluid and productive editing.
Commenti
Caricamento commenti...
Sign in to comment