| name | code-review |
|---|---|
| description | Automated PR review checklist covering security, performance, architecture, and code quality. Use when reviewing pull requests, examining code changes, or performing code quality assessments. |
Use the Quick checklist template for a short paste into a PR description. Everything from Review process through Approval criteria is the full deep checklist.
## Security Review
- [ ] No hardcoded secrets or tokens
- [ ] Input validation present
- [ ] Error handling secure (no sensitive data in logs)
## Correctness Review
- [ ] Logic correctly implemented
- [ ] Edge cases handled
- [ ] Error scenarios covered
- [ ] Async/await chains correct
## Architecture Review
- [ ] Proper code organization
- [ ] Design patterns followed
- [ ] Good modularity
- [ ] No circular dependencies
## Performance Review
- [ ] Efficient implementation
- [ ] No unnecessary API calls
- [ ] Memory leaks avoided
- [ ] Concurrency handled correctly
## Testing Review
- [ ] Adequate test coverage (80%+)
- [ ] Quality tests (not just passing)
- [ ] TDD compliance
- [ ] Both success and failure paths tested
## Code Conventions
- [ ] TypeScript strict mode
- [ ] Consistent naming conventions
- [ ] No unused imports or variables
- [ ] Documentation adequate
## Monorepo Checks
- [ ] Cross-package imports use published names
- [ ] Workspace dependencies declared correctly
- [ ] OCLIF manifest updated if commands changed
- [ ] No breaking changes to exported APIs-
🔴 Critical (must fix before merge):
- Security vulnerabilities
- Logic errors causing incorrect behavior
- Breaking API changes
- Hardcoded secrets or credentials
- Data loss scenarios
-
🟡 Important (should fix):
- Performance regressions
- Code maintainability issues
- Missing error handling
- Test coverage gaps
- Best practice violations
-
🟢 Suggestion (consider improving):
- Code readability improvements
- Minor optimizations
- Documentation enhancements
- Style inconsistencies
- No hardcoded API keys, tokens, or passwords
- No secrets in environment variables exposed in logs
- No secrets in test data or fixtures
- Sensitive data not logged or exposed in error messages
- Config files don't contain real credentials
// ✅ GOOD - Validate all user input
if (!region || typeof region !== 'string') {
throw new CLIError('Region must be a non-empty string');
}
if (!['us', 'eu', 'au'].includes(region)) {
throw new CLIError('Invalid region specified');
}
// ❌ BAD - No validation
const result = await client.setRegion(region);- No sensitive data in error messages
- Stack traces don't leak system information
- Error messages are user-friendly
- All errors properly caught and handled
- No raw error objects exposed to users
- OAuth/token handling is secure
- No storing plaintext passwords
- Session tokens validated
- Auth state properly managed
- Rate limiting respected
- Business logic correctly implemented
- Algorithm is correct for the problem
- State transitions valid
- Data types used correctly
- Comparisons use correct operators (=== not ==)
- API failures handled (404, 429, 500, etc.)
- Network timeouts managed
- Empty/null responses handled
- Invalid input rejected
- Partial failures handled gracefully
// ✅ GOOD - Proper async handling
async run(): Promise<void> {
try {
const result = await this.fetchData();
await this.processData(result);
} catch (error) {
handleAndLogError(error, this.contextDetails);
}
}
// ❌ BAD - Missing await
async run(): Promise<void> {
const result = this.fetchData(); // Missing await!
await this.processData(result);
}- No race conditions
- State mutations atomic
- Data validation before mutations
- Rollback strategy for failures
- Concurrent operations safe
- Classes/functions have single responsibility
- No circular dependencies
- Proper module structure
- Clear separation of concerns
- Commands delegate to services/utils
// ✅ GOOD - Service layer separation
export default class MyCommand extends BaseCommand {
async run(): Promise<void> {
const service = new MyService(this.contextDetails);
const result = await service.execute();
}
}
// ❌ BAD - Logic in command
export default class MyCommand extends BaseCommand {
async run(): Promise<void> {
const data = await client.fetch();
for (const item of data) {
// Complex business logic here
}
}
}- Services are reusable
- Utils are generic and testable
- Dependencies injected
- No tight coupling
- Easy to test in isolation
- TypeScript strict mode enabled
- No
anytypes without justification - Interfaces defined for contracts
- Generic types used appropriately
- Type narrowing correct
- Rate limiting respected (10 req/sec for Contentstack)
- No unnecessary API calls in loops
- Pagination implemented for large datasets
- Caching used where appropriate
- Batch operations considered
- No memory leaks in event listeners
- Large arrays streamed not loaded fully
- Cleanup in try/finally blocks
- File handles properly closed
- Resources released after use
// ✅ GOOD - Controlled concurrency
const results = await Promise.all(
items.map(item => processItem(item))
);
// ❌ BAD - Unbounded concurrency
for (const item of items) {
promises.push(processItem(item)); // No limit!
}- Algorithms are efficient for scale
- String concatenation uses proper methods
- Unnecessary computations avoided
- Data structures appropriate
- No repeated lookups without caching
- 80%+ line coverage achieved
- 80%+ branch coverage
- Critical paths fully tested
- Error paths tested
- Edge cases included
// ✅ GOOD - Quality test
it('should throw error when region is empty', () => {
expect(() => validateRegion(''))
.to.throw('Region is required');
});
// ❌ BAD - Weak test
it('should validate region', () => {
validateRegion('us'); // No assertion!
});- Descriptive test names
- Arrange-Act-Assert pattern
- One assertion per test (focus)
- Mocks properly isolated
- No test interdependencies
- Tests written before implementation
- All tests pass
- Code coverage requirements met
- Tests are maintainable
- Both success and failure paths covered
-
strict: truein tsconfig - No
anytypes (useunknownif needed) - Proper null/undefined handling
- Type annotations on public APIs
- Generics used appropriately
- Classes: PascalCase (
MyClass) - Functions: camelCase (
myFunction) - Constants: UPPER_SNAKE_CASE (
MY_CONST) - Booleans start with verb (
isActive,hasData) - Descriptive names (not
x,temp,data)
- No unused imports
- No unused variables
- Proper indentation (consistent spacing)
- Line length reasonable (<100 chars)
- Imports organized (group by type)
- Complex logic documented
- Public APIs have JSDoc comments
- Non-obvious decisions explained
- Examples provided where helpful
- README updated if needed
// ✅ GOOD - Use published package names
import { configHandler } from '@contentstack/cli-utilities';
import { BaseCommand } from '@contentstack/cli-command';
// ❌ BAD - Relative paths across packages
import { configHandler } from '../../../contentstack-utilities/src';- Dependencies declared in correct
package.json - Versions consistent across packages
- No circular dependencies between packages
- Shared deps in root if used by multiple packages
- No installing globally when local version exists
- Command file paths correct in
package.json - OCLIF manifest regenerated (
pnpm build && pnpm oclif manifest) - New commands registered in plugin list if needed
- Topic separators consistent (
:) - Command names follow pattern
- TypeScript compiles without errors
- Build output in
lib/directory - No build artifacts committed
- ESLint passes without warnings
- Tests pass in CI environment
- Delivery-token wording correct (not CMA-centric); GraphQL paths require delivery token
- Integration coverage for new flags when behavior is user-facing
- See package code-review skill
- Config with default passwords
- API keys in client-side code
- SQL injection (N/A here, but parameterization pattern)
- XSS in CLI output (escape HTML if needed)
- API calls in loops
- Synchronous file I/O on large files
- Memory not released properly
- Rate limiting ignored
- Off-by-one errors in loops
- Wrong comparison operators
- Async/await chains broken
- Null/undefined not handled
- Tests pass locally but fail in CI
- Mocks not properly restored
- Race conditions in tests
- Hardcoded timeouts
APPROVE when:
- ✅ All 🔴 Critical items addressed
- ✅ Most 🟡 Important items addressed (document exceptions)
- ✅ Code follows team conventions
- ✅ Tests pass and coverage sufficient
- ✅ Monorepo integrity maintained
REQUEST CHANGES when:
- ❌ Any 🔴 Critical issues present
- ❌ Multiple 🟡 Important issues unaddressed
- ❌ Test coverage below 80%
- ❌ Architecture concerns not resolved
- ❌ Breaking changes not documented
COMMENT for:
- 💬 🟢 Suggestions (non-blocking)
- 💬 Questions about implementation
- 💬 Appreciation for good patterns
- Module organization: Proper separation of concerns
- Lint compliance: ESLint checks for code style
- TypeScript compiler: Successful compilation to
lib/directories - Test execution: All tests pass successfully
- Build verification: Build scripts complete without errors
- Command usability: Clear help text and realistic examples
- Error handling: Appropriate error messages and recovery options
- Test quality: Comprehensive test coverage for critical paths
- Monorepo consistency: Consistent patterns across all packages
- Flag design: Intuitive flag names and combinations
- Inconsistent TypeScript settings: Mixed strict mode without reason
- Real API calls in tests: Unmocked external dependencies
- Missing error handling: Commands that fail silently
- Poor test organization: Tests without clear Arrange-Act-Assert
- Build artifacts committed:
lib/directories in version control - Unclear error messages: Non-actionable error descriptions
- Inconsistent flag naming: Similar flags with different names
- Missing command examples: Examples not showing actual usage
- Command properly extends
@contentstack/cli-commandCommand - Flags defined with proper types from
@contentstack/cli-utilities - Error handling uses
handleAndLogErrorutility - User feedback uses
cliuxutilities - Tests use Mocha + Chai pattern with mocked dependencies
- Package.json has correct scripts (build, compile, test, lint)
- TypeScript compiles with no errors
- Tests pass:
pnpm test - No
.onlyor.skipin test files - Build succeeds:
pnpm run build - OCLIF manifest generated successfully
- All review items addressed
- No build artifacts in commit
- Tests added for new functionality
- Documentation updated if needed
- No console.log() statements (use log.debug instead)
- Error messages are user-friendly