Thank you for your interest in contributing to Guinevere! We welcome contributions from the community and are pleased to have you join us.
- Code of Conduct
- Getting Started
- Development Setup
- How to Contribute
- Coding Standards
- Testing
- Documentation
- Pull Request Process
- Release Process
This project adheres to a code of conduct that we expect all contributors to follow. Please be respectful and constructive in all interactions.
- Be respectful: Treat everyone with respect and kindness
- Be inclusive: Welcome newcomers and help them learn
- Be constructive: Provide helpful feedback and suggestions
- Be patient: Remember that everyone has different experience levels
- Be professional: Keep discussions focused on the project
Before you begin, ensure you have the following installed:
- .NET 9.0 SDK or later
- Git for version control
- Visual Studio 2022 or JetBrains Rider (recommended IDEs)
- GitVersion for semantic versioning
- Fork the repository on GitHub
- Clone your fork locally:
git clone https://github.com/YOUR-USERNAME/guinevere.git cd guinevere - Add the upstream repository:
git remote add upstream https://github.com/brmassa/guinevere.git
-
Restore packages:
dotnet restore
-
Build the solution:
./build.sh Compile
-
Run tests:
./build.sh Test
Guinevere/
├── Guinevere/ # Core library
├── Integrations/ # Graphics API integrations
│ ├── Guinevere.OpenGL.OpenTK/
│ ├── Guinevere.OpenGL.Raylib/
│ ├── Guinevere.OpenGL.SilkNET/
│ └── Guinevere.Vulkan.SilkNET/
├── Samples/ # Example applications
├── Guinevere.Tests/ # Unit tests
├── .nuke/ # Build automation
└── .github/ # GitHub workflows
We welcome several types of contributions:
- Bug fixes: Fix issues in existing code
- New features: Add new functionality to the core library or integrations
- Documentation: Improve or add documentation
- Examples: Create new sample applications
- Tests: Add or improve test coverage
- Performance improvements: Optimize existing code
- Check existing issues: Look for related issues or feature requests
- Create an issue: If none exists, create one to discuss your proposal
- Get feedback: Wait for maintainer feedback before starting work
- Assign yourself: Once approved, assign the issue to yourself
-
Create a feature branch:
git checkout -b feature/your-feature-name
-
Make your changes:
- Write clean, readable code
- Follow the coding standards
- Add tests for new functionality
- Update documentation as needed
-
Test your changes:
./build.sh Test ./build.sh BuildSamples
-
Commit your changes:
git add . git commit -m "feat: add new feature description"
-
Push to your fork:
git push origin feature/your-feature-name
-
Create a Pull Request: Open a PR against the
mainbranch
-
Naming: Follow standard C# naming conventions
- PascalCase for classes, methods, properties
- camelCase for fields, parameters, local variables
- Use descriptive names
-
Documentation: Add XML documentation for public APIs
/// <summary> /// Renders a button with the specified text. /// </summary> /// <param name="text">The button text to display</param> /// <returns>True if the button was clicked</returns> public bool Button(string text)
-
Null handling: Use nullable reference types appropriately
-
Async/await: Use async patterns for I/O operations
-
Resource disposal: Properly dispose of resources using
usingstatements
- Formatting: Use consistent indentation (4 spaces)
- Line length: Keep lines under 120 characters when reasonable
- Braces: Use opening braces on the same line for control structures
- Spacing: Add spaces around operators and after commas
namespace Guinevere.Core
{
/// <summary>
/// Represents a GUI context for rendering immediate mode interfaces.
/// </summary>
public class GuiContext : IDisposable
{
private readonly IRenderer renderer;
private bool disposed;
/// <summary>
/// Initializes a new instance of the GuiContext class.
/// </summary>
/// <param name="renderer">The renderer to use for drawing</param>
public GuiContext(IRenderer renderer)
{
this.renderer = renderer ?? throw new ArgumentNullException(nameof(renderer));
}
/// <summary>
/// Renders a button with the specified text.
/// </summary>
/// <param name="text">The button text to display</param>
/// <returns>True if the button was clicked</returns>
public bool Button(string text)
{
if (string.IsNullOrEmpty(text))
throw new ArgumentException("Button text cannot be null or empty", nameof(text));
return renderer.DrawButton(text);
}
/// <summary>
/// Disposes of the GUI context and releases resources.
/// </summary>
public void Dispose()
{
Dispose(true);
GC.SuppressFinalize(this);
}
protected virtual void Dispose(bool disposing)
{
if (!disposed && disposing)
{
renderer?.Dispose();
disposed = true;
}
}
}
}- Unit tests: Write unit tests for all new functionality
- Integration tests: Add integration tests for new integrations
- Coverage: Maintain test coverage above 80%
- Test naming: Use descriptive test method names
[TestClass]
public class GuiContextTests
{
[TestMethod]
public void Button_WithValidText_ReturnsExpectedResult()
{
// Arrange
var mockRenderer = new Mock<IRenderer>();
mockRenderer.Setup(r => r.DrawButton("Test")).Returns(true);
var context = new GuiContext(mockRenderer.Object);
// Act
var result = context.Button("Test");
// Assert
Assert.IsTrue(result);
mockRenderer.Verify(r => r.DrawButton("Test"), Times.Once);
}
[TestMethod]
[ExpectedException(typeof(ArgumentException))]
public void Button_WithNullText_ThrowsArgumentException()
{
// Arrange
var context = new GuiContext(Mock.Of<IRenderer>());
// Act & Assert
context.Button(null);
}
}# Run all tests
./build.sh Test
# Run tests with coverage report
./build.sh TestReport
# Run specific test project
dotnet test Guinevere.Tests/- API documentation: Add XML comments to all public APIs
- README updates: Update README.md for new features
- Sample code: Provide working examples for new features
- Architecture docs: Document significant architectural changes
- Clear and concise: Write in clear, simple language
- Examples: Include code examples where helpful
- Up-to-date: Keep documentation current with code changes
- Accessible: Write for developers of all experience levels
Before submitting a pull request, ensure:
- Code follows the coding standards
- All tests pass
- New functionality has tests
- Documentation is updated
- No merge conflicts with main branch
- Commit messages follow conventional format
Use conventional commit format for commit messages:
<type>(<scope>): <description>
[optional body]
[optional footer]
Types:
feat: New featurefix: Bug fixdocs: Documentation changesstyle: Code style changesrefactor: Code refactoringtest: Adding or updating testschore: Maintenance tasks
Examples:
feat(core): add button click animation support
fix(opengl): resolve texture binding issue
docs(readme): update installation instructions
- Automated checks: Ensure all CI checks pass
- Code review: Wait for maintainer review
- Address feedback: Make requested changes
- Final approval: Maintainer approves and merges
We use Semantic Versioning:
- MAJOR: Breaking changes
- MINOR: New features (backward compatible)
- PATCH: Bug fixes (backward compatible)
- Automatic releases: Every Thursday if there are new commits
- Manual releases: For urgent fixes or major features
- Pre-releases: For testing significant changes
Each release includes:
- NuGet packages for all libraries
- Sample application packages (Windows/Linux)
- Release notes with changelog
- Source code archives
- GitHub Issues: For bug reports and feature requests
- GitHub Discussions: For questions and general discussion
- Pull Requests: For code review and collaboration
If you have questions about contributing:
- Check existing issues and discussions
- Create a new issue with the "question" label
- Provide context and specific details
Contributors will be recognized in:
- Project README.md
- Release notes
- Project documentation
Thank you for contributing to Guinevere! 🎨⚡