Thank you for your interest in contributing to DbDiff! This document provides guidelines and instructions for contributing to the project.
- Code of Conduct
- Getting Started
- Development Workflow
- Coding Standards
- Testing
- Submitting Changes
- Release Process
By participating in this project, you agree to maintain a respectful and inclusive environment for everyone.
- .NET 10.0 SDK or later
- Git
- A code editor (Visual Studio, Visual Studio Code, Rider, etc.)
- SQL Server or PostgreSQL for testing
- Fork the repository on GitHub
- Clone your fork locally:
git clone https://github.com/YOUR-USERNAME/dbdiff.git
cd dbdiff- Add the upstream repository:
git remote add upstream https://github.com/ORIGINAL-OWNER/dbdiff.gitdotnet restore
dotnet builddotnet test- Create a branch for your work:
git checkout -b feature/my-new-feature
# or
git checkout -b fix/bug-description- Make your changes following the coding standards
- Write or update tests for your changes
- Run tests to ensure everything works
- Commit your changes with clear, descriptive messages
- Push to your fork
- Open a Pull Request against the
developbranch
DbDiff follows Hexagonal Architecture (Ports & Adapters) with strict separation of concerns:
-
Domain Layer (
DbDiff.Domain)- Core business entities
- Port interfaces (e.g.,
ISchemaExtractor) - No external dependencies
- Pure C# classes
-
Application Layer (
DbDiff.Application)- Use cases and application services
- DTOs for data transfer
- Formatters and validators
- Depends only on Domain layer
-
Infrastructure Layer (
DbDiff.Infrastructure)- Database-specific implementations
- Adapters implementing domain ports
- External library integrations
- Depends on Domain layer
-
CLI Layer (
DbDiff.Cli)- Entry point and CLI argument parsing
- Dependency injection configuration
- Depends on all other layers
- Namespaces: Omit namespace declarations where possible (use file-scoped or implicit)
// Good
namespace DbDiff.Domain;
public class Table
{
// ...
}- Top-level programs: Use classless top-level programs for entry points
// Good - Program.cs
using DbDiff.Application;
var builder = WebApplication.CreateBuilder(args);
// ...-
SOLID Principles: Follow SOLID principles throughout
-
Async/Await: Use async/await for all I/O operations
-
Dependency Injection: Use constructor injection for dependencies
public class SchemaExportService
{
private readonly ISchemaExtractor _extractor;
private readonly ISchemaFormatter _formatter;
public SchemaExportService(ISchemaExtractor extractor, ISchemaFormatter formatter)
{
_extractor = extractor;
_formatter = formatter;
}
}- Mapping: Always map between layers (no direct exposure of domain entities)
// Good
public SchemaExportResult Export(SchemaExportRequest request)
{
// Map DTO → Domain
var schema = await _extractor.ExtractSchemaAsync(request.ConnectionString);
// Map Domain → DTO
return new SchemaExportResult { Success = true, ... };
}- Never trust user input: Validate and sanitize all inputs
- Use parameterized queries: Always use parameters for SQL queries
- Validate paths: Use
PathValidatorfor all file path operations - No secrets in code: Never commit connection strings, passwords, or API keys
- Use Serilog for structured logging
- Log at appropriate levels:
Verbose- Detailed diagnostic informationDebug- Debugging informationInformation- General informational messagesWarning- Warnings about potential issuesError- Error messages for recoverable errorsFatal- Critical errors that require immediate attention
_logger.LogInformation("Exporting schema from database {DatabaseName}", databaseName);
_logger.LogError(ex, "Failed to extract schema from {ConnectionString}", connectionString);- Write unit tests for all new functionality
- Use XUnit for testing
- Aim for high test coverage
- Test edge cases and error conditions
DbDiff.Application.Tests/
├── Services/
│ └── SchemaExportServiceTests.cs
├── Validation/
│ └── PathValidatorTests.cs
└── Formatters/
└── CustomTextFormatterTests.cs
[Fact]
public void MethodName_Scenario_ExpectedBehavior()
{
// Arrange
var input = "test";
// Act
var result = Method(input);
// Assert
Assert.Equal(expected, result);
}# Run all tests
dotnet test
# Run tests with coverage
dotnet test --collect:"XPlat Code Coverage"
# Run specific test class
dotnet test --filter "FullyQualifiedName~PathValidatorTests"- Update documentation if you've changed functionality
- Update CHANGELOG.md following Keep a Changelog format
- Ensure all tests pass locally
- Create a pull request with a clear title and description
- Link related issues in the PR description
- Respond to review feedback promptly
Before submitting, ensure:
- Code follows the project's coding standards
- All tests pass
- New tests added for new functionality
- Documentation updated
- CHANGELOG.md updated
- No linter warnings or errors
- Hexagonal architecture principles followed
- Proper layer separation maintained
- Security best practices followed
Write clear, descriptive commit messages:
Add PostgreSQL schema extractor
- Implement ISchemaExtractor for PostgreSQL
- Add connection string validation
- Add tests for PostgreSQL extractor
- Update documentation
Fixes #123
feature/description- New featuresfix/description- Bug fixesdocs/description- Documentation updatesrefactor/description- Code refactoringtest/description- Test improvements
Releases are handled by maintainers:
- Update
CHANGELOG.mdwith release version and date - Create a version tag following semver:
git tag v1.0.0 - Push the tag:
git push origin v1.0.0 - GitHub Actions automatically builds and publishes the release
This project follows Semantic Versioning:
- MAJOR: Breaking changes
- MINOR: New features (backward compatible)
- PATCH: Bug fixes (backward compatible)
- Questions: Open a discussion on GitHub
- Bugs: Open an issue with the bug report template
- Features: Open an issue with the feature request template
- Security: See SECURITY.md for reporting security issues
Contributors will be recognized in release notes and the repository's contributor list.
Thank you for contributing to DbDiff! 🎉