Skip to content

fix(sdk-dotnet): provide default AWS region in SecretProviderFactory#147

Merged
macalbert merged 30 commits intomainfrom
fix/dotnet-sdk-ci-aws-region
Apr 9, 2026
Merged

fix(sdk-dotnet): provide default AWS region in SecretProviderFactory#147
macalbert merged 30 commits intomainfrom
fix/dotnet-sdk-ci-aws-region

Conversation

@macalbert
Copy link
Copy Markdown
Owner

@macalbert macalbert commented Apr 8, 2026

Summary

Introduces the .NET SDK for Envilder with AWS SSM and Azure Key Vault support, along with CI pipeline fixes for AWS region resolution. The SDK follows the same map-file contract as the TypeScript core and supports hierarchical config binding, runtime provider overrides, and end-to-end testing via TestContainers.

Changes

.NET SDK (src/sdks/dotnet/)

  • Add .NET SDK with ISecretProvider port, EnvilderClient, and MapFileParser
  • Implement AwsSsmSecretProvider and AzureKeyVaultSecretProvider adapters
  • Add SecretProviderFactory with dynamic AWS region resolution from profile config and env vars
  • Support hierarchical config binding via map file ($config section)
  • Add argument validation and improved null checks across core and infrastructure layers
  • Use enum (SecretProviderType) for provider type selection
  • Simplify ParsedMapFile and improve secret resolution logic

Documentation

  • Add .NET SDK documentation and installation instructions
  • Update README and CHANGELOG for .NET SDK introduction
  • Update dotnet README with runtime overrides example
  • Add XML docs and end-to-end consumer tests

CI / Workflows

  • Add .NET SDK test workflow with caching and status reporting
  • Configure AWS credentials and LOCALSTACK_AUTH_TOKEN in CI
  • Update actions/cache, actions/upload-artifact, and actions/checkout versions
  • Fix test status handling in workflow
  • Include tests/ directory in NuGet publish workflow
  • Enable manual trigger for NuGet publish workflow

Tests

  • Add end-to-end acceptance tests using TestContainers (LocalStack, Lowkey Vault)
  • Update test collection to ContainersCollection
  • Add missing using for LocalStackHealthCheck
  • Fallback to AWS provider in CI pipelines for integration tests

Testing

  • dotnet build src/sdks/dotnet/Envilder.sln
  • dotnet test tests/sdks/dotnet/
  • pnpm test passes (TypeScript core unaffected)
  • pnpm lint passes

Related

Builds on the .NET SDK branch (macalbert/sdk-dotnet).

macalbert added 13 commits April 7, 2026 03:39
Implement the Envilder .NET SDK targeting netstandard2.0 with hexagonal
architecture (Domain/Application/Infrastructure). Includes map-file
parsing, secret resolution, IConfiguration and IServiceCollection
integration, plus unit and acceptance tests using LocalStack and
Lowkey Vault via Testcontainers.
Implement the Envilder .NET SDK targeting netstandard2.0 with hexagonal
architecture (Domain/Application/Infrastructure). Includes map-file
parsing, secret resolution, IConfiguration and IServiceCollection
integration, plus unit and acceptance tests using LocalStack and
Lowkey Vault via Testcontainers.
Replaces string provider selection with SecretProviderType enum for
strong typing and clarity. Refactors SecretProviderFactory and parsing
logic accordingly. Updates tests to use the enum and improves LocalStack
test reliability with health checks and embedded secrets.
Add comprehensive XML documentation for all public APIs to improve
discoverability and maintainability. Introduce end-to-end tests using
LocalStack and Lowkey Vault to verify integration with AWS SSM and Azure
Key Vault, including configuration and error handling scenarios. Update
test dependencies to Microsoft.Extensions.* v10 for .NET 8 support.
Allow MapFileConfig and ParsedMapFile properties to be set after
construction. Remove IsExternalInit.cs as it is no longer needed.
Enable slash-delimited keys in map file for hierarchical config
binding (e.g., Database/ConnectionString). Refactor ParsedMapFile
to use immutable properties. Add validation and error handling to
AddEnvilder. Remove unused Region option. Update and add tests for
section binding and error cases.
Add explicit null and argument validation to constructors and
methods for improved robustness and fail-fast behavior. Update
tests to cover new error cases. Update package versions and
improve resource handling and code clarity.
Ensure integration tests run in CI by falling back to AWS when the
configured secret provider (e.g., Azure Key Vault) is unavailable.
Add workflow_dispatch trigger for manual execution
@coderabbitai
Copy link
Copy Markdown
Contributor

coderabbitai Bot commented Apr 8, 2026

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

Run ID: 989aefe9-2c2b-426b-9998-a96d4ebc3807

📥 Commits

Reviewing files that changed from the base of the PR and between bf38ab4 and c1ed4d4.

⛔ Files ignored due to path filters (2)
  • .github/dependabot.yml is excluded by none and included by none
  • .github/workflows/tests-dotnet-sdk.yml is excluded by none and included by none
📒 Files selected for processing (2)
  • src/sdks/dotnet/Infrastructure/SecretProviderFactory.cs
  • src/sdks/dotnet/README.md
✅ Files skipped from review due to trivial changes (1)
  • src/sdks/dotnet/Infrastructure/SecretProviderFactory.cs
🚧 Files skipped from review as they are similar to previous changes (1)
  • src/sdks/dotnet/README.md

Walkthrough

SecretProviderFactory now resolves and supplies an explicit AWS region (with a USEast1 fallback) when constructing SSM clients. Tests/fixtures expanded exception handling and added a test for factory behavior with no AWS region env vars. Documentation and README entries for the .NET SDK were added.

Changes

Cohort / File(s) Summary
Secret provider / AWS region
src/sdks/dotnet/Infrastructure/SecretProviderFactory.cs
Added ResolveRegion, ResolveProfileRegion, and FallbackRegion (RegionEndpoint.USEast1). SSM client construction now receives an explicit RegionEndpoint in both profile and default credential paths.
Tests — factory behavior
tests/sdks/dotnet/Infrastructure/SecretProviderFactoryTests.cs
Added Should_SelectAwsProvider_When_NoAwsRegionConfigured test that clears AWS region/profile env vars, sets temp AWS config/credentials paths and user dirs, calls SecretProviderFactory.Create(new MapFileConfig()), asserts no throw and returns an AwsSsmSecretProvider; restores env and cleans temp dir. Added collection attribute and fixture using.
Tests — fixtures / error handling & namespaces
tests/sdks/dotnet/Fixtures/LocalStackFixture.cs, tests/sdks/dotnet/Fixtures/LocalStackHealthCheck.cs
Broadened ResolveClient exception handling to treat InvalidOperationException or AmazonServiceException as fallback triggers and return an AWS-backed provider; updated namespace in LocalStackHealthCheck.
Docs / README / changelog
docs/CHANGELOG.md, docs/architecture/README.md, docs/requirements-installation.md, src/sdks/dotnet/README.md
Added 0.10.0 changelog and .NET SDK docs: architecture, installation, README examples (SecretProviderFactory usage, EnvilderOptions runtime overrides), and config-normalization notes.

Estimated code review effort

🎯 2 (Simple) | ⏱️ ~10 minutes

Possibly related PRs

🚥 Pre-merge checks | ✅ 2 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 28.57% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (2 passed)
Check name Status Explanation
Title check ✅ Passed The title accurately summarizes the main change: providing a default AWS region in SecretProviderFactory to fix CI failures.
Description check ✅ Passed The description is comprehensive, covering root cause, changes made, and verification. It follows the template structure with clear sections for problem statement, changes, and checklist completion.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch fix/dotnet-sdk-ci-aws-region

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

devin-ai-integration[bot]

This comment was marked as resolved.

gemini-code-assist[bot]

This comment was marked as resolved.

The AWS SDK for .NET requires a RegionEndpoint or ServiceURL when creating
an SSM client. Without one, AmazonClientException is thrown. This works
locally when ~/.aws/config exists but fails in CI where no AWS config is
present.

- Add RegionEndpoint.USEast1 as default in CreateAwsSecretProvider
- Broaden LocalStackFixture.ResolveClient catch to handle any exception
- Exclude EndToEnd tests from publish-nuget workflow (need Docker + creds)
- Add tests-dotnet-sdk.yml CI workflow for PR validation
- Add regression test Should_SelectAwsProvider_When_NoAwsRegionConfigured
@macalbert macalbert force-pushed the fix/dotnet-sdk-ci-aws-region branch from a2376d0 to 1a88c54 Compare April 9, 2026 06:23
devin-ai-integration[bot]

This comment was marked as resolved.

@macalbert macalbert changed the base branch from macalbert/sdk-dotnet to main April 9, 2026 07:31
Copy link
Copy Markdown
Contributor

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🧹 Nitpick comments (3)
src/sdks/dotnet/Infrastructure/SecretProviderFactory.cs (1)

19-19: Hardcoded default region may cause issues for users with secrets in other regions.

While this fix resolves the CI issue, hardcoding USEast1 means users with AWS SSM parameters in other regions (e.g., eu-west-1, ap-southeast-1) will silently connect to the wrong region and fail to retrieve their secrets.

Consider making the region configurable via MapFileConfig and/or EnvilderOptions, falling back to USEast1 only when no region is specified anywhere:

♻️ Proposed approach to make region configurable
 public static class SecretProviderFactory
 {
-    private static readonly Amazon.RegionEndpoint DefaultRegion = Amazon.RegionEndpoint.USEast1;
+    private static readonly Amazon.RegionEndpoint FallbackRegion = Amazon.RegionEndpoint.USEast1;

Then in CreateAwsSecretProvider:

+        var regionName = options?.Region ?? config.Region;
+        var region = string.IsNullOrWhiteSpace(regionName)
+            ? FallbackRegion
+            : Amazon.RegionEndpoint.GetBySystemName(regionName);
+
         if (!string.IsNullOrWhiteSpace(profile))
         {
             // ...
-                return new(new AmazonSimpleSystemsManagementClient(credentials, DefaultRegion));
+                return new(new AmazonSimpleSystemsManagementClient(credentials, region));
         }
 
         return new(new AmazonSimpleSystemsManagementClient(new AmazonSimpleSystemsManagementConfig
         {
-            RegionEndpoint = DefaultRegion,
+            RegionEndpoint = region,
         }));
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@src/sdks/dotnet/Infrastructure/SecretProviderFactory.cs` at line 19, The
DefaultRegion constant in SecretProviderFactory is hardcoded to USEast1 which
can cause wrong-region lookups; update SecretProviderFactory to accept a
configurable region (use MapFileConfig and/or EnvilderOptions as the source) and
have CreateAwsSecretProvider use that configured region, falling back to
Amazon.RegionEndpoint.USEast1 only if no region is provided; reference the
DefaultRegion symbol to remove/replace it, and wire the region through the
factory constructor or method parameters so callers can specify region via
MapFileConfig/EnvilderOptions.
tests/sdks/dotnet/Fixtures/LocalStackFixture.cs (1)

94-97: Consider catching specific exception types instead of bare Exception.

Catching all exceptions is overly broad and may mask unexpected errors (e.g., OutOfMemoryException, ArgumentNullException from a bug). The PR description mentions AWS SDK throws AmazonClientException, so consider catching that alongside InvalidOperationException:

♻️ Proposed fix to catch specific exceptions
+using Amazon.Runtime;
+
 // ...
 
     private static EnvilderClient ResolveClient(ParsedMapFile mapFile)
     {
         try
         {
             return new(SecretProviderFactory.Create(mapFile.Config));
         }
-        catch (Exception)
+        catch (Exception ex) when (ex is InvalidOperationException or AmazonServiceException)
         {
             return new(SecretProviderFactory.Create(new() { Provider = SecretProviderType.Aws }));
         }
     }

This uses an exception filter to catch only the expected failure types while letting truly unexpected exceptions propagate for investigation.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@tests/sdks/dotnet/Fixtures/LocalStackFixture.cs` around lines 94 - 97,
Replace the broad catch(Exception) in LocalStackFixture.cs with a specific
exception filter that only handles the expected AWS/client errors; catch
AmazonClientException and InvalidOperationException (e.g., use "catch (Exception
ex) when (ex is AmazonClientException || ex is InvalidOperationException)") and
then return the fallback SecretProviderFactory.Create(new() { Provider =
SecretProviderType.Aws }); ensure the AmazonClientException type is available
via the appropriate AWS SDK namespace import.
tests/sdks/dotnet/Infrastructure/SecretProviderFactoryTests.cs (1)

102-145: Good regression test, but environment manipulation may cause test flakiness with parallel execution.

This test correctly validates the fix for missing AWS region configuration. However, modifying process-wide environment variables can cause flaky behavior if xUnit runs tests in parallel (which it does by default for different test classes).

Consider adding [Collection("Sequential")] or disabling parallelization for this test class to prevent interference:

♻️ Suggested improvements
  1. Prevent parallel execution issues:
[Collection("EnvironmentTests")]
public class SecretProviderFactoryTests
  1. Enhance assertion to verify the returned type:
             // Assert
-            act.Should().NotThrow();
+            var provider = act.Should().NotThrow().Subject;
+            provider.Should().BeOfType<AwsSsmSecretProvider>();

The Subject property from AwesomeAssertions (FluentAssertions fork) allows chaining assertions on the actual result, providing stronger verification that the factory returns the expected provider type.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@tests/sdks/dotnet/Infrastructure/SecretProviderFactoryTests.cs` around lines
102 - 145, The test Should_SelectAwsProvider_When_NoAwsRegionConfigured
manipulates process-wide environment variables and can flake when xUnit runs
tests in parallel; to fix it, mark the test class SecretProviderFactoryTests
with a collection attribute that forces sequential execution (e.g., add a
[Collection("EnvironmentTests")] or equivalent to the class) or disable
parallelization for this test class, and strengthen the assertion by asserting
the actual returned provider type from SecretProviderFactory.Create(config) (use
FluentAssertions/Subject chaining to verify the concrete provider type) so the
test both avoids parallel-env interference and validates the returned type.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Nitpick comments:
In `@src/sdks/dotnet/Infrastructure/SecretProviderFactory.cs`:
- Line 19: The DefaultRegion constant in SecretProviderFactory is hardcoded to
USEast1 which can cause wrong-region lookups; update SecretProviderFactory to
accept a configurable region (use MapFileConfig and/or EnvilderOptions as the
source) and have CreateAwsSecretProvider use that configured region, falling
back to Amazon.RegionEndpoint.USEast1 only if no region is provided; reference
the DefaultRegion symbol to remove/replace it, and wire the region through the
factory constructor or method parameters so callers can specify region via
MapFileConfig/EnvilderOptions.

In `@tests/sdks/dotnet/Fixtures/LocalStackFixture.cs`:
- Around line 94-97: Replace the broad catch(Exception) in LocalStackFixture.cs
with a specific exception filter that only handles the expected AWS/client
errors; catch AmazonClientException and InvalidOperationException (e.g., use
"catch (Exception ex) when (ex is AmazonClientException || ex is
InvalidOperationException)") and then return the fallback
SecretProviderFactory.Create(new() { Provider = SecretProviderType.Aws });
ensure the AmazonClientException type is available via the appropriate AWS SDK
namespace import.

In `@tests/sdks/dotnet/Infrastructure/SecretProviderFactoryTests.cs`:
- Around line 102-145: The test
Should_SelectAwsProvider_When_NoAwsRegionConfigured manipulates process-wide
environment variables and can flake when xUnit runs tests in parallel; to fix
it, mark the test class SecretProviderFactoryTests with a collection attribute
that forces sequential execution (e.g., add a [Collection("EnvironmentTests")]
or equivalent to the class) or disable parallelization for this test class, and
strengthen the assertion by asserting the actual returned provider type from
SecretProviderFactory.Create(config) (use FluentAssertions/Subject chaining to
verify the concrete provider type) so the test both avoids parallel-env
interference and validates the returned type.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

Run ID: 27471fc5-92a6-4ff4-a3fe-67a1bcf8c1cc

📥 Commits

Reviewing files that changed from the base of the PR and between bdf4055 and 292b61e.

⛔ Files ignored due to path filters (2)
  • .github/workflows/publish-nuget.yml is excluded by none and included by none
  • .github/workflows/tests-dotnet-sdk.yml is excluded by none and included by none
📒 Files selected for processing (3)
  • src/sdks/dotnet/Infrastructure/SecretProviderFactory.cs
  • tests/sdks/dotnet/Fixtures/LocalStackFixture.cs
  • tests/sdks/dotnet/Infrastructure/SecretProviderFactoryTests.cs

devin-ai-integration[bot]

This comment was marked as resolved.

devin-ai-integration[bot]

This comment was marked as resolved.

- Added .NET SDK installation instructions and usage examples to README
- Updated CHANGELOG with .NET SDK details and CI workflow
- Enhanced documentation for SDK architecture and prerequisites
coderabbitai[bot]

This comment was marked as resolved.

devin-ai-integration[bot]

This comment was marked as resolved.

@macalbert macalbert merged commit e6e16d0 into main Apr 9, 2026
10 of 11 checks passed
@macalbert macalbert self-assigned this Apr 9, 2026
@macalbert macalbert deleted the fix/dotnet-sdk-ci-aws-region branch April 9, 2026 13:32
@macalbert macalbert added bug Something isn't working enhancement New feature or request github-actions labels Apr 9, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

bug Something isn't working enhancement New feature or request github-actions

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant