Skip to content

feat: AddOrUpdate sets ApiVersion/Kind if not set#157

Merged
IvanJosipovic merged 1 commit into
alphafrom
dev1
May 12, 2026
Merged

feat: AddOrUpdate sets ApiVersion/Kind if not set#157
IvanJosipovic merged 1 commit into
alphafrom
dev1

Conversation

@IvanJosipovic
Copy link
Copy Markdown
Owner

@IvanJosipovic IvanJosipovic commented May 12, 2026

chore: update and enhance documentation; chore: refactor resource handling methods

Summary by CodeRabbit

  • New Features

    • Added GetKubeResource<T>() method to deserialize Kubernetes objects from resources.
  • Bug Fixes

    • Renamed extension methods GetObservedComposedResourcesGetObservedResources and GetDesiredComposedResourcesGetDesiredResources for API clarity.
  • Documentation

    • Updated Crossplane support requirement from v1.17 to v2.
    • Enhanced XML documentation across SDK extensions and source generator.
  • Tests

    • Removed legacy test suite and example test project.

chore: update and enhance documentation; chore: refactor resource handling methods
@coderabbitai
Copy link
Copy Markdown

coderabbitai Bot commented May 12, 2026

📝 Walkthrough

Walkthrough

The PR refactors the C# SDK's resource handling API, renaming request extension methods from "Composed" to simpler names, adding a Kubernetes resource deserialization method, updating dependent code, and removing the example test project. Supporting documentation, configuration, and formatting adjustments accompany these changes.

Changes

Resource Handling & Deserialization Enhancements

Layer / File(s) Summary
Request extension API redesign
src/Function.SDK.CSharp/Extensions/RequestExtensions.cs
GetObservedComposedResources and GetDesiredComposedResources are renamed to GetObservedResources and GetDesiredResources. Protobuf imports are updated and XML documentation is expanded for all resource-retrieval helpers.
Resource deserialization capability
src/Function.SDK.CSharp/Extensions/ResourceExtensions.cs
New generic extension method GetKubeResource<T> deserializes a Resource's protobuf field into a Kubernetes object. GetCondition documentation is refined with parameter and return-type details.
Dependent code updates
src/Function.SDK.CSharp/Extensions/ResponseExtensions.cs, src/Function.SDK.CSharp/Extensions/StateExtensions.cs
ResponseExtensions.UpdateDesiredReadyStatus switches from GetObservedComposedResources() to GetObservedResources(). StateExtensions.AddOrUpdate adds initialization logic to set ApiVersion and Kind when missing before resource merge. Both methods gain or expand XML documentation.
Documentation, formatting, and configuration
README.md, src/Function.SDK.CSharp.SourceGenerator/SourceGenerator.cs, src/Function.SDK.CSharp/Models/V1ConversionReview.cs, src/Function.SDK.CSharp/Properties/launchSettings.json, tests/Function.SDK.CSharp.Tests/V1alpha1XStorageBucket.cs
README updates Crossplane requirement to v2+. SourceGenerator class and Initialize method documentation is added. V1ConversionReview.cs is reformatted (whitespace/indentation). Launch settings ports are updated. Unnecessary using directives are trimmed from V1alpha1XStorageBucket.cs.

Example Test Project Removal

Layer / File(s) Summary
Deletion of example test infrastructure
tests/Function.SDK.CSharp.Example.Tests/ConversionWebhookTests.cs, tests/Function.SDK.CSharp.Example.Tests/TestExtensions.cs, tests/Function.SDK.CSharp.Example.Tests/UnitTest1.cs, tests/Function.SDK.CSharp.Example.Tests/Function.SDK.CSharp.Example.Tests.csproj, tests/Function.SDK.CSharp.Example.Tests/xunit.runner.json
The entire example test project directory and its test classes, helper extensions, unit tests (TestMerge, TestReadyFalse, TestReadyTrue, TestReadyIgnore), and project configuration are removed.

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~20 minutes

Poem

🐰 Hops of change, renamed with care,
Resources now simpler to share,
Deserialization, a Kube delight,
Tests retired, the SDK's redesign shines bright!

🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title accurately describes the main feature being introduced: AddOrUpdate now sets ApiVersion/Kind when not already set, which aligns with the primary change documented in StateExtensions.cs.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.

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

✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch dev1

Tip

💬 Introducing Slack Agent: The best way for teams to turn conversations into code.

Slack Agent is built on CodeRabbit's deep understanding of your code, so your team can collaborate across the entire SDLC without losing context.

  • Generate code and open pull requests
  • Plan features and break down work
  • Investigate incidents and troubleshoot customer tickets together
  • Automate recurring tasks and respond to alerts with triggers
  • Summarize progress and report instantly

Built for teams:

  • Shared memory across your entire org—no repeating context
  • Per-thread sandboxes to safely plan and execute work
  • Governance built-in—scoped access, auditability, and budget controls

One agent for your entire SDLC. Right inside Slack.

👉 Get started


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.

@codecov
Copy link
Copy Markdown

codecov Bot commented May 12, 2026

Codecov Report

❌ Patch coverage is 25.00000% with 9 lines in your changes missing coverage. Please review.
✅ Project coverage is 25.78%. Comparing base (aeb2d6c) to head (4f9eec2).

Files with missing lines Patch % Lines
...c/Function.SDK.CSharp/Models/V1ConversionReview.cs 0.00% 7 Missing ⚠️
.../Function.SDK.CSharp/Extensions/StateExtensions.cs 0.00% 1 Missing and 1 partial ⚠️
Additional details and impacted files
@@            Coverage Diff             @@
##            alpha     #157      +/-   ##
==========================================
- Coverage   26.06%   25.78%   -0.28%     
==========================================
  Files           7        7              
  Lines         188      190       +2     
  Branches       39       40       +1     
==========================================
  Hits           49       49              
- Misses        137      138       +1     
- Partials        2        3       +1     

☔ View full report in Codecov by Sentry.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.

Copy link
Copy Markdown

@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.

Actionable comments posted: 2

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (1)
src/Function.SDK.CSharp/Extensions/ResponseExtensions.cs (1)

70-70: ⚠️ Potential issue | 🟡 Minor | ⚡ Quick win

Fix the locale-dependent string formatting.

The pipeline is reporting CA1305: string.Format behavior could vary based on the current user's locale settings. Specify an explicit IFormatProvider to ensure consistent behavior.

🌐 Proposed fix to specify culture
-            Message = string.Format(message, args)
+            Message = string.Format(System.Globalization.CultureInfo.InvariantCulture, message, args)
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@src/Function.SDK.CSharp/Extensions/ResponseExtensions.cs` at line 70, The
string.Format call in ResponseExtensions (the assignment setting Message) is
locale-dependent; update it to use an explicit IFormatProvider (e.g.,
CultureInfo.InvariantCulture) by calling the overload that accepts an
IFormatProvider (string.Format(CultureInfo.InvariantCulture, ...)) and add the
necessary using for System.Globalization; locate the assignment in
ResponseExtensions (the Message = string.Format(...) line) and replace it with
the culture-specific overload to satisfy CA1305.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@src/Function.SDK.CSharp/Extensions/ResourceExtensions.cs`:
- Around line 19-24: Add defensive checks and error handling to
GetKubeResource<T>: validate the extension receiver (Resource resource) and
resource.Resource_ for null and throw ArgumentNullException with clear parameter
names if null; wrap the JsonFormatter.Default.Format(...) and
KubernetesJson.Deserialize<T>(...) calls in a try-catch, catching Exception, and
rethrow a descriptive InvalidOperationException (or similar) that includes the
target type name (typeof(T)) and the original exception as innerException so
deserialization errors (malformed JSON or type mismatches) are surfaced with
context rather than causing obscure failures; do not swallow the exception and
ensure messages reference Resource.Resource_ and the failing operation
(format/deserialize).

In `@src/Function.SDK.CSharp/Models/V1ConversionReview.cs`:
- Line 20: The non-nullable property `Request` on `V1ConversionReview` triggers
CS8618 because it has no initializer; update the declaration of `public
V1ConversionReviewRequest Request { get; set; }` to ensure it is always
initialized—preferably add the `required` modifier (e.g., make it `required
V1ConversionReviewRequest Request`) so callers/deserializers must supply it;
alternatively, if it can be absent make the type nullable
(`V1ConversionReviewRequest? Request`) or provide a default using the
null-forgiving operator—choose the `required` approach for strictness.

---

Outside diff comments:
In `@src/Function.SDK.CSharp/Extensions/ResponseExtensions.cs`:
- Line 70: The string.Format call in ResponseExtensions (the assignment setting
Message) is locale-dependent; update it to use an explicit IFormatProvider
(e.g., CultureInfo.InvariantCulture) by calling the overload that accepts an
IFormatProvider (string.Format(CultureInfo.InvariantCulture, ...)) and add the
necessary using for System.Globalization; locate the assignment in
ResponseExtensions (the Message = string.Format(...) line) and replace it with
the culture-specific overload to satisfy CA1305.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro Plus

Run ID: 266cb6c9-be25-4a6d-be70-ef51eec09324

📥 Commits

Reviewing files that changed from the base of the PR and between aeb2d6c and 4f9eec2.

📒 Files selected for processing (14)
  • README.md
  • src/Function.SDK.CSharp.SourceGenerator/SourceGenerator.cs
  • src/Function.SDK.CSharp/Extensions/RequestExtensions.cs
  • src/Function.SDK.CSharp/Extensions/ResourceExtensions.cs
  • src/Function.SDK.CSharp/Extensions/ResponseExtensions.cs
  • src/Function.SDK.CSharp/Extensions/StateExtensions.cs
  • src/Function.SDK.CSharp/Models/V1ConversionReview.cs
  • src/Function.SDK.CSharp/Properties/launchSettings.json
  • tests/Function.SDK.CSharp.Example.Tests/ConversionWebhookTests.cs
  • tests/Function.SDK.CSharp.Example.Tests/Function.SDK.CSharp.Example.Tests.csproj
  • tests/Function.SDK.CSharp.Example.Tests/TestExtensions.cs
  • tests/Function.SDK.CSharp.Example.Tests/UnitTest1.cs
  • tests/Function.SDK.CSharp.Example.Tests/xunit.runner.json
  • tests/Function.SDK.CSharp.Tests/V1alpha1XStorageBucket.cs
💤 Files with no reviewable changes (5)
  • tests/Function.SDK.CSharp.Example.Tests/xunit.runner.json
  • tests/Function.SDK.CSharp.Example.Tests/Function.SDK.CSharp.Example.Tests.csproj
  • tests/Function.SDK.CSharp.Example.Tests/TestExtensions.cs
  • tests/Function.SDK.CSharp.Example.Tests/ConversionWebhookTests.cs
  • tests/Function.SDK.CSharp.Example.Tests/UnitTest1.cs

Comment on lines +19 to +24
public static T GetKubeResource<T>(this Resource resource)
{
var json = JsonFormatter.Default.Format(resource.Resource_);

return KubernetesJson.Deserialize<T>(json);
}
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟠 Major | ⚡ Quick win

Add null checks and error handling.

The method lacks defensive checks:

  • No null guard on resource parameter
  • No null check on resource.Resource_
  • No try-catch for deserialization failures (type mismatch, malformed JSON)

These omissions can cause unhandled exceptions at runtime.

🛡️ Proposed fix with null checks and error handling
 public static T GetKubeResource<T>(this Resource resource)
 {
+    if (resource == null)
+        throw new ArgumentNullException(nameof(resource));
+    
+    if (resource.Resource_ == null)
+        throw new InvalidOperationException("Resource.Resource_ is null");
+    
+    try
+    {
         var json = JsonFormatter.Default.Format(resource.Resource_);
-
         return KubernetesJson.Deserialize<T>(json);
+    }
+    catch (Exception ex)
+    {
+        throw new InvalidOperationException($"Failed to deserialize resource to type {typeof(T).Name}", ex);
+    }
 }
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@src/Function.SDK.CSharp/Extensions/ResourceExtensions.cs` around lines 19 -
24, Add defensive checks and error handling to GetKubeResource<T>: validate the
extension receiver (Resource resource) and resource.Resource_ for null and throw
ArgumentNullException with clear parameter names if null; wrap the
JsonFormatter.Default.Format(...) and KubernetesJson.Deserialize<T>(...) calls
in a try-catch, catching Exception, and rethrow a descriptive
InvalidOperationException (or similar) that includes the target type name
(typeof(T)) and the original exception as innerException so deserialization
errors (malformed JSON or type mismatches) are surfaced with context rather than
causing obscure failures; do not swallow the exception and ensure messages
reference Resource.Resource_ and the failing operation (format/deserialize).

public string Kind { get; set; } = KubeKind;
[JsonPropertyName("request")]
public V1ConversionReviewRequest Request { get; set; }
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟡 Minor | ⚡ Quick win

Address the non-nullable property initialization warning.

The Request property is declared as non-nullable but has no default value, required modifier, or initializer. While this likely works in practice since JSON deserialization populates it, it violates C#'s nullability contracts and triggers CS8618. Consider one of these approaches:

Proposed fixes

Option 1 (recommended): Use the required modifier to enforce initialization

 [JsonPropertyName("request")]
-public V1ConversionReviewRequest Request { get; set; }
+public required V1ConversionReviewRequest Request { get; set; }

Option 2: Make the property nullable if it's optional

 [JsonPropertyName("request")]
-public V1ConversionReviewRequest Request { get; set; }
+public V1ConversionReviewRequest? Request { get; set; }

Option 3: Add a default value with null-forgiving operator

 [JsonPropertyName("request")]
-public V1ConversionReviewRequest Request { get; set; }
+public V1ConversionReviewRequest Request { get; set; } = default!;
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
public V1ConversionReviewRequest Request { get; set; }
[JsonPropertyName("request")]
public required V1ConversionReviewRequest Request { get; set; }
🧰 Tools
🪛 GitHub Actions: PR Build & Test / 0_build-test _ Build & Test.txt

[warning] 20-20: CS1591: Missing XML comment for publicly visible type or member 'V1ConversionReview.Request'.


[warning] 20-20: CS8618: Non-nullable property 'Request' must contain a non-null value when exiting constructor. Consider adding the 'required' modifier or declaring the property as nullable.

🪛 GitHub Actions: PR Build & Test / build-test _ Build & Test

[warning] 20-20: warning CS8618: Non-nullable property 'Request' must contain a non-null value when exiting constructor. Consider adding the 'required' modifier or declaring the property as nullable. (net9.0)


[warning] 20-20: warning CS1591: Missing XML comment for publicly visible type or member 'V1ConversionReview.Request' (net9.0)


[warning] 20-20: warning CS8618: Non-nullable property 'Request' must contain a non-null value when exiting constructor. Consider adding the 'required' modifier or declaring the property as nullable. (net10.0)


[warning] 20-20: warning CS1591: Missing XML comment for publicly visible type or member 'V1ConversionReview.Request' (net10.0)

🪛 GitHub Check: build-test / Build & Test

[warning] 20-20:
Non-nullable property 'Request' must contain a non-null value when exiting constructor. Consider adding the 'required' modifier or declaring the property as nullable.


[warning] 20-20:
Missing XML comment for publicly visible type or member 'V1ConversionReview.Request'


[warning] 20-20:
Non-nullable property 'Request' must contain a non-null value when exiting constructor. Consider adding the 'required' modifier or declaring the property as nullable.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@src/Function.SDK.CSharp/Models/V1ConversionReview.cs` at line 20, The
non-nullable property `Request` on `V1ConversionReview` triggers CS8618 because
it has no initializer; update the declaration of `public
V1ConversionReviewRequest Request { get; set; }` to ensure it is always
initialized—preferably add the `required` modifier (e.g., make it `required
V1ConversionReviewRequest Request`) so callers/deserializers must supply it;
alternatively, if it can be absent make the type nullable
(`V1ConversionReviewRequest? Request`) or provide a default using the
null-forgiving operator—choose the `required` approach for strictness.

@IvanJosipovic IvanJosipovic merged commit e840e3f into alpha May 12, 2026
4 of 6 checks passed
@IvanJosipovic IvanJosipovic deleted the dev1 branch May 12, 2026 05:06
@github-actions
Copy link
Copy Markdown

🎉 This PR is included in version 1.0.0-alpha.60 🎉

The release is available on GitHub release

Your semantic-release bot 📦🚀

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant