Thank you for your interest in contributing to Lambda.GraphQL! This guide will help you get started with development, testing, and submitting contributions.
- Code of Conduct
- Getting Started
- Development Setup
- Project Structure
- Development Workflow
- Testing Guidelines
- Code Style
- Submitting Changes
- Release Process
This project follows a simple code of conduct:
- Be respectful - Treat all contributors with respect
- Be constructive - Provide helpful feedback and suggestions
- Be collaborative - Work together to improve the project
- Be patient - Remember that everyone is learning
- .NET 6.0 SDK or later - Download
- Git - Download
- IDE (recommended):
- Visual Studio 2022+ with .NET workload
- JetBrains Rider 2022.3+
- Visual Studio Code with C# extension
# Fork the repository on GitHub, then clone your fork
git clone https://github.com/YOUR-USERNAME/lambda-graphql.git
cd lambda-graphql
# Add upstream remote
git remote add upstream https://github.com/dguisinger/lambda-graphql.git# Restore dependencies
dotnet restore
# Build solution
dotnet build
# Run tests
dotnet test
# Verify example project builds and generates schema
cd Lambda.GraphQL.Examples
dotnet build
ls -la schema.graphql resolvers.json
cd ..Expected Output:
- All projects build successfully
- 84+ tests pass
schema.graphqlandresolvers.jsongenerated in Examples project
- Open
Lambda.GraphQL.sln - Set build configuration to Debug
- Enable "Show All Files" in Solution Explorer
- View generated files in
obj/directories
- Open
Lambda.GraphQL.sln - Enable "Show All Files" in Solution view
- Settings → Build, Execution, Deployment → Toolset and Build
- Use MSBuild version: .NET SDK
- Open project folder
- Install recommended extensions:
- C# (Microsoft)
- C# Dev Kit (Microsoft)
- Use integrated terminal for build commands
Lambda.GraphQL/
├── Lambda.GraphQL/ # Main package
│ ├── Attributes/ # GraphQL attribute definitions
│ │ ├── GraphQLTypeAttribute.cs
│ │ ├── GraphQLFieldAttribute.cs
│ │ ├── GraphQLOperationAttributes.cs
│ │ └── ...
│ └── build/ # MSBuild integration files
│ ├── Lambda.GraphQL.props
│ └── Lambda.GraphQL.targets
│
├── Lambda.GraphQL.SourceGenerator/ # Roslyn source generator
│ ├── GraphQLSchemaGenerator.cs # Main generator entry point
│ ├── SdlGenerator.cs # SDL generation logic
│ ├── TypeMapper.cs # C# to GraphQL type mapping
│ ├── AwsScalarMapper.cs # AWS scalar type mapping
│ ├── ReturnTypeExtractor.cs # Method return type analysis
│ ├── ResolverManifestGenerator.cs # Resolver JSON generation
│ ├── DiagnosticDescriptors.cs # Compiler diagnostics
│ └── Models/ # Data models
│ ├── TypeInfo.cs
│ ├── FieldInfo.cs
│ ├── ResolverInfo.cs
│ └── ...
│
├── Lambda.GraphQL.Build/ # MSBuild task
│ └── ExtractGraphQLSchemaTask.cs # Schema extraction task
│
├── Lambda.GraphQL.Tests/ # Unit tests
│ ├── TypeMapperTests.cs
│ ├── SdlGeneratorTests.cs
│ ├── ResolverManifestTests.cs
│ └── ...
│
├── Lambda.GraphQL.Examples/ # Example project
│ ├── Product.cs
│ ├── ProductFunctions.cs
│ └── AdvancedTypes.cs
│
└── docs/ # Documentation
├── README.md
├── getting-started.md
├── architecture.md
└── ...
| Package | Purpose | Key Files |
|---|---|---|
Lambda.GraphQL |
Attributes and build integration | Attributes/.cs, build/.targets |
Lambda.GraphQL.SourceGenerator |
Compile-time schema generation | GraphQLSchemaGenerator.cs, SdlGenerator.cs |
Lambda.GraphQL.Build |
Post-build schema extraction | ExtractGraphQLSchemaTask.cs |
Lambda.GraphQL.Tests |
Unit and integration tests | *Tests.cs |
Lambda.GraphQL.Examples |
Example usage and validation | *.cs |
- Create a feature branch:
git checkout -b feature/your-feature-name-
Make your changes following the code style guidelines
-
Build and test:
# IMPORTANT: Shutdown build server after source generator changes
dotnet build-server shutdown
# Build
dotnet build
# Run tests
dotnet test
# Test with example project
cd Lambda.GraphQL.Examples
dotnet build
cat schema.graphql
cd ..- Commit your changes:
git add .
git commit -m "feat: add support for X"Follow Conventional Commits:
<type>(<scope>): <description>
[optional body]
[optional footer]
Types:
feat: New featurefix: Bug fixdocs: Documentation changestest: Test additions or changesrefactor: Code refactoringperf: Performance improvementschore: Build process or tooling changes
Examples:
feat(generator): add support for union types
fix(mapper): handle nullable reference types correctly
docs(readme): update installation instructions
test(sdl): add tests for interface generation
# Run all tests
dotnet test
# Run specific test class
dotnet test --filter "FullyQualifiedName~TypeMapperTests"
# Run with detailed output
dotnet test -v detailed
# Run with coverage (requires coverlet)
dotnet test /p:CollectCoverage=trueusing Xunit;
using FluentAssertions;
public class YourFeatureTests
{
[Fact]
public void MethodName_Scenario_ExpectedBehavior()
{
// Arrange
var input = "test";
// Act
var result = YourMethod(input);
// Assert
result.Should().Be("expected");
}
}- Type Mapping Tests - Verify C# to GraphQL type conversion
- SDL Generation Tests - Verify correct GraphQL schema syntax
- Resolver Tests - Verify resolver manifest generation
- Attribute Tests - Verify attribute parsing
- Diagnostic Tests - Verify error reporting
// Use helper methods for complex test data
private static TypeInfo CreateTypeInfo(string name, GraphQLTypeKind kind)
{
return new TypeInfo
{
Name = name,
Kind = kind,
Fields = new List<FieldInfo>()
};
}
[Fact]
public void GenerateType_WithFields_GeneratesCorrectSdl()
{
// Arrange
var typeInfo = CreateTypeInfo("Product", GraphQLTypeKind.Object);
typeInfo.Fields.Add(new FieldInfo { Name = "id", Type = "ID!" });
// Act & Assert
// ...
}- Minimum: 80% code coverage
- Target: 90% code coverage
- Critical paths: 100% coverage (type mapping, SDL generation)
Follow Microsoft C# Coding Conventions:
// ✅ Good
public class TypeMapper
{
private readonly Dictionary<string, string> _typeMap;
public string MapType(string csharpType)
{
if (string.IsNullOrEmpty(csharpType))
{
throw new ArgumentException("Type cannot be null or empty", nameof(csharpType));
}
return _typeMap.TryGetValue(csharpType, out var graphqlType)
? graphqlType
: "String";
}
}
// ❌ Bad
public class typemapper
{
private Dictionary<string, string> typeMap;
public string mapType(string t)
{
if (t == null || t == "") throw new Exception("bad type");
return typeMap.ContainsKey(t) ? typeMap[t] : "String";
}
}- Classes: PascalCase (
TypeMapper,SdlGenerator) - Methods: PascalCase (
MapType,GenerateSchema) - Properties: PascalCase (
Name,Description) - Fields: _camelCase with underscore (
_typeMap, _context`) - Parameters: camelCase (
csharpType,context) - Constants: PascalCase (
DefaultTimeout)
// 1. Using statements (sorted)
using System;
using System.Collections.Generic;
using System.Linq;
using Microsoft.CodeAnalysis;
// 2. Namespace
namespace Lambda.GraphQL.SourceGenerator;
// 3. Class documentation
/// <summary>
/// Maps C# types to GraphQL types.
/// </summary>
public class TypeMapper
{
// 4. Constants
private const string DefaultType = "String";
// 5. Fields
private readonly Dictionary<string, string> _typeMap;
// 6. Constructor
public TypeMapper()
{
_typeMap = new Dictionary<string, string>();
}
// 7. Public methods
public string MapType(string csharpType)
{
// Implementation
}
// 8. Private methods
private bool IsNullable(string type)
{
// Implementation
}
}/// <summary>
/// Maps a C# type to its corresponding GraphQL type.
/// </summary>
/// <param name="csharpType">The C# type name (e.g., "string", "int", "List<Product>").</param>
/// <returns>The GraphQL type (e.g., "String!", "Int!", "[Product]!").</returns>
/// <exception cref="ArgumentException">Thrown when csharpType is null or empty.</exception>
public string MapType(string csharpType)
{
// Implementation
}- Update your branch:
git fetch upstream
git rebase upstream/main- Push to your fork:
git push origin feature/your-feature-name-
Create Pull Request on GitHub:
- Use descriptive title following commit message format
- Fill out PR template completely
- Link related issues
- Add screenshots/examples if applicable
-
Address review feedback:
# Make changes
git add .
git commit -m "fix: address review feedback"
git push origin feature/your-feature-name- Code builds successfully
- All tests pass
- New tests added for new functionality
- Documentation updated
- CHANGELOG.md updated (for significant changes)
- No breaking changes (or clearly documented)
- Commit messages follow convention
- Code follows style guidelines
- Automated Checks: CI/CD runs tests and linting
- Code Review: Maintainer reviews code quality and design
- Feedback: Address any requested changes
- Approval: Maintainer approves PR
- Merge: Maintainer merges to main branch
CRITICAL: After making changes to Lambda.GraphQL.SourceGenerator, you MUST run:
dotnet build-server shutdownThe Roslyn compiler server caches loaded analyzers/generators, so changes won't take effect until the server is restarted.
# Find generated files
find Lambda.GraphQL.Examples/obj -name "*GraphQLSchemaGenerator*.cs"
# View generated file
cat Lambda.GraphQL.Examples/obj/Debug/net6.0/generated/Lambda.GraphQL.SourceGenerator/Lambda.GraphQL.SourceGenerator.GraphQLSchemaGenerator/GraphQLSchema.g.cs<!-- Add to .csproj for debugging -->
<PropertyGroup>
<EmitCompilerGeneratedFiles>true</EmitCompilerGeneratedFiles>
<CompilerGeneratedFilesOutputPath>$(BaseIntermediateOutputPath)Generated</CompilerGeneratedFilesOutputPath>
</PropertyGroup>- Set
Lambda.GraphQL.SourceGeneratoras startup project - Right-click project → Properties → Debug
- Launch profile: Roslyn Component
- Set breakpoints in generator code
- F5 to debug
Follow Semantic Versioning:
- Major (1.0.0): Breaking changes
- Minor (0.1.0): New features, backward compatible
- Patch (0.0.1): Bug fixes, backward compatible
- Update version in
Directory.Build.props - Update CHANGELOG.md
- Create release branch:
release/v1.0.0 - Run full test suite
- Build NuGet packages:
dotnet pack -c Release - Test packages locally
- Create GitHub release with tag
- Publish to NuGet.org
- GitHub Discussions: Ask questions and discuss ideas
- GitHub Issues: Report bugs or request features
- Email: Contact maintainers directly for sensitive issues
Thank you for contributing to Lambda.GraphQL! 🎉