Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
12 changes: 12 additions & 0 deletions .github/dependabot.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
version: 2
updates:
- package-ecosystem: "nuget"
directory: "/"
schedule:
interval: "weekly"
day: "wednesday"
open-pull-requests-limit: 25
groups:
dotnet:
patterns:
- "*"
19 changes: 19 additions & 0 deletions .github/workflows/build.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
name: Build
on:
workflow_dispatch:
push:
branches:
- main
- beta
- release/*
tags:
- v*
permissions: write-all
jobs:
build:
uses: LayeredCraft/devops-templates/.github/workflows/package-build.yaml@v5.0
with:
dotnet-version: |
8.0.x
9.0.x
secrets: inherit
18 changes: 18 additions & 0 deletions .github/workflows/pr-build.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
name: PR Build

on:
pull_request:
branches:
- main
permissions: write-all
jobs:
build:
uses: LayeredCraft/devops-templates/.github/workflows/pr-build.yaml@v5.0
with:
solution: LayeredCraft.Cdk.Constructs.sln
hasTests: true
dotnetVersion: |
8.0.x
9.0.x
runCdk: false
secrets: inherit
2 changes: 2 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -416,3 +416,5 @@ FodyWeavers.xsd
*.msix
*.msm
*.msp

.idea
105 changes: 105 additions & 0 deletions CLAUDE.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,105 @@
# CLAUDE.md

This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository.

## Project Overview

This is a .NET library that provides reusable AWS CDK constructs for serverless applications. The library is designed specifically for LayeredCraft projects and focuses on Lambda functions with integrated OpenTelemetry support, IAM management, and environment configuration.

## Commands

### Build and Test
```bash
# Build the solution
dotnet build

# Run all tests
dotnet test

# Run tests for a specific project
dotnet test test/LayeredCraft.Cdk.Constructs.Tests/

# Run a specific test
dotnet test --filter "Construct_ShouldCreateLambdaFunction"
```

### Package Management
```bash
# Restore packages
dotnet restore

# Add a package reference
dotnet add src/LayeredCraft.Cdk.Constructs/ package PackageName

# Add a test package reference
dotnet add test/LayeredCraft.Cdk.Constructs.Tests/ package PackageName
```

## Architecture

### Core Components

**LambdaFunctionConstruct** (`src/LayeredCraft.Cdk.Constructs/Constructs/LambdaFunctionConstruct.cs`)
- Main CDK construct that creates Lambda functions with comprehensive configuration
- Automatically creates IAM roles and policies with CloudWatch Logs permissions
- Supports OpenTelemetry layer integration via AWS managed layer
- Creates function versions and aliases for deployment management
- Handles Lambda permissions for multiple targets (function, version, alias)

**Configuration Models** (`src/LayeredCraft.Cdk.Constructs/Models/`)
- `LambdaFunctionConstructProps`: Main configuration interface and record for Lambda construct
- `LambdaPermission`: Record for defining Lambda invocation permissions

### Key Design Patterns

1. **Construct Pattern**: Uses AWS CDK construct pattern for reusable infrastructure components
2. **Interface + Record Pattern**: Props classes use both interface and record for flexibility and immutability
3. **Multi-Target Permissions**: Automatically applies permissions to function, version, and alias
4. **OpenTelemetry Integration**: Built-in support for AWS OTEL collector layer
5. **Versioning Strategy**: Creates new versions on every deployment with "live" alias

### Target Frameworks
- .NET 8.0 and .NET 9.0
- Uses AWS CDK v2 (Amazon.CDK.Lib 2.203.1)

## Testing Framework

### Test Structure
- Uses xUnit v3 with AutoFixture for data generation
- AwesomeAssertions for fluent assertions
- NSubstitute for mocking (though not heavily used in current tests)
- AWS CDK Template assertions for infrastructure testing

### Test Architecture
**Custom Attributes**:
- `LambdaFunctionConstructAutoDataAttribute`: AutoFixture attribute with customizable parameters
- `BaseFixtureFactory`: Factory for creating configured AutoFixture instances

**Test Customizations**:
- `LambdaFunctionConstructCustomization`: Configures realistic test data for Lambda constructs
- Supports parameterized test scenarios (OTEL layer on/off, permissions included/excluded)

### Test Data Strategy
- Uses AutoFixture with custom configurations for realistic AWS resource names
- Test assets include `test-lambda.zip` for Lambda deployment packages
- Tests verify both resource creation and property configuration

## Development Practices

### Code Style
- C# 12+ features enabled (records, required properties, collection expressions)
- Nullable reference types enabled
- Implicit usings enabled
- Uses `required` properties for mandatory configuration

### NuGet Package Configuration
- Configured for NuGet.org publishing with MIT license
- Includes source linking via Microsoft.SourceLink.GitHub
- Symbol packages (snupkg) enabled for debugging support
- Package metadata includes proper tagging for discoverability

### AWS CDK Patterns
- Uses `PROVIDED_AL2023` runtime for Lambda functions (supports custom runtimes)
- Hardcoded OpenTelemetry layer ARN for us-east-1 region
- Default memory: 1024MB, timeout: 6 seconds, log retention: 2 weeks
- Uses `RemovalPolicy.RETAIN` for Lambda versions to prevent deletion
29 changes: 29 additions & 0 deletions Directory.Build.props
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
<Project>
<PropertyGroup>
<VersionPrefix>0.1.0-beta</VersionPrefix>
<!-- SPDX license identifier for MIT -->
<PackageLicenseExpression>MIT</PackageLicenseExpression>
Comment thread
ncipollina marked this conversation as resolved.

<!-- Other useful metadata -->
<RepositoryUrl>https://github.com/LayeredCraft/cdk-constructs</RepositoryUrl>
<RepositoryType>git</RepositoryType>
<Authors>Nick Cipollina</Authors>
<PackageProjectUrl>https://github.com/LayeredCraft/cdk-constructs</PackageProjectUrl>

<!-- NuGet.org specific -->
<PackageRequireLicenseAcceptance>false</PackageRequireLicenseAcceptance>
<IsPackable>true</IsPackable>
<IncludeSymbols>true</IncludeSymbols>
<SymbolPackageFormat>snupkg</SymbolPackageFormat>
<PublishRepositoryUrl>true</PublishRepositoryUrl>
<EmbedUntrackedSources>true</EmbedUntrackedSources>
</PropertyGroup>

<ItemGroup>
<PackageReference Include="Microsoft.SourceLink.GitHub" Version="8.0.0">
<PrivateAssets>all</PrivateAssets>
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
</PackageReference>
</ItemGroup>

</Project>
52 changes: 52 additions & 0 deletions LayeredCraft.Cdk.Constructs.sln
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@

Microsoft Visual Studio Solution File, Format Version 12.00
# Visual Studio Version 17
VisualStudioVersion = 17.0.31903.59
MinimumVisualStudioVersion = 10.0.40219.1
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "src", "src", "{5C4245CB-F794-42A5-8226-AF6AA00D0E5E}"
EndProject
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "test", "test", "{F802A3E0-E887-4EAA-87FA-AB090DCCB788}"
EndProject
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Solution Items", "Solution Items", "{34177AB8-B46F-4340-8D3A-478B24804E73}"
ProjectSection(SolutionItems) = preProject
CLAUDE.md = CLAUDE.md
Directory.Build.props = Directory.Build.props
README.md = README.md
LICENSE = LICENSE
EndProjectSection
EndProject
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "git", "git", "{32F31203-71F9-4824-A5E0-D326AF212DD4}"
ProjectSection(SolutionItems) = preProject
.gitignore = .gitignore
.github\dependabot.yml = .github\dependabot.yml
.github\workflows\build.yaml = .github\workflows\build.yaml
.github\workflows\pr-build.yaml = .github\workflows\pr-build.yaml
EndProjectSection
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "LayeredCraft.Cdk.Constructs", "src\LayeredCraft.Cdk.Constructs\LayeredCraft.Cdk.Constructs.csproj", "{63FCBE95-6714-49D5-A9CD-0BE725BAE259}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "LayeredCraft.Cdk.Constructs.Tests", "test\LayeredCraft.Cdk.Constructs.Tests\LayeredCraft.Cdk.Constructs.Tests.csproj", "{7F2D2EA4-D201-4B0E-AE44-6D03B1B7AEBC}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU
Release|Any CPU = Release|Any CPU
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
EndGlobalSection
GlobalSection(NestedProjects) = preSolution
{63FCBE95-6714-49D5-A9CD-0BE725BAE259} = {5C4245CB-F794-42A5-8226-AF6AA00D0E5E}
{7F2D2EA4-D201-4B0E-AE44-6D03B1B7AEBC} = {F802A3E0-E887-4EAA-87FA-AB090DCCB788}
EndGlobalSection
GlobalSection(ProjectConfigurationPlatforms) = postSolution
{63FCBE95-6714-49D5-A9CD-0BE725BAE259}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{63FCBE95-6714-49D5-A9CD-0BE725BAE259}.Debug|Any CPU.Build.0 = Debug|Any CPU
{63FCBE95-6714-49D5-A9CD-0BE725BAE259}.Release|Any CPU.ActiveCfg = Release|Any CPU
{63FCBE95-6714-49D5-A9CD-0BE725BAE259}.Release|Any CPU.Build.0 = Release|Any CPU
{7F2D2EA4-D201-4B0E-AE44-6D03B1B7AEBC}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{7F2D2EA4-D201-4B0E-AE44-6D03B1B7AEBC}.Debug|Any CPU.Build.0 = Debug|Any CPU
{7F2D2EA4-D201-4B0E-AE44-6D03B1B7AEBC}.Release|Any CPU.ActiveCfg = Release|Any CPU
{7F2D2EA4-D201-4B0E-AE44-6D03B1B7AEBC}.Release|Any CPU.Build.0 = Release|Any CPU
EndGlobalSection
EndGlobal
Loading