Skip to content

[ResourceBase]: Add Microsoft DSC support - #54

Draft
Gijsreyn wants to merge 2 commits into
dsccommunity:mainfrom
Gijsreyn:prototype-microsoft-dsc-base
Draft

[ResourceBase]: Add Microsoft DSC support #54
Gijsreyn wants to merge 2 commits into
dsccommunity:mainfrom
Gijsreyn:prototype-microsoft-dsc-base

Conversation

@Gijsreyn

@Gijsreyn Gijsreyn commented Aug 2, 2026

Copy link
Copy Markdown

Pull Request (PR) description

Adds DSC v3 (Microsoft DSC) support to ResourceBase. New hidden helper
methods (GetTestResult(), GetSetResult(), DeleteInstance(),
ExportInstances(), GetInstanceJsonSchema()) let a derived class
participate in Microsoft DSC semantics by declaring one-liner static methods.

These are added as per the resource contract RFC while remaining compatible with PSDSC v1/v2.

This Pull Request (PR) fixes the following issues

n/a

Task list

  • Added an entry to the change log under the Unreleased section of the
    file CHANGELOG.md. Entry should say what was changed and how that
    affects users (if applicable), and reference the issue being resolved
    (if applicable).
  • Documentation added/updated in README.md.
  • Comment-based help added/updated for all new/changed functions.
  • Localization strings added/updated in all localization files as appropriate.
  • Examples appropriately added/updated.
  • Unit tests added/updated. See DSC Community Testing Guidelines.
  • Integration tests added/updated (where possible). See
    DSC Community Testing Guidelines.
  • New/changed code adheres to DSC Community Style Guidelines.

This change is Reviewable

@coderabbitai

coderabbitai Bot commented Aug 2, 2026

Copy link
Copy Markdown

Review Change Stack

Walkthrough

ResourceBase now supports typed test and set results, what-if prediction, deletion, export, existence tracking, and runtime JSON schema generation. Unit and integration tests cover these operations through a new in-memory DSC resource fixture.

Changes

ResourceBase DSC support

Layer / File(s) Summary
Runtime JSON schema generation
source/Private/ConvertTo-JsonSchemaTypeDefinition.ps1, source/Private/ConvertTo-DscResourceJsonSchema.ps1, tests/Unit/Private/*JsonSchema*
New helpers convert .NET types and reflected DSC properties into draft 2020-12 JSON Schema documents. Tests cover inherited properties, validation metadata, required fields, arrays, nullable types, enums, and read-only properties.
ResourceBase lifecycle helpers
source/Classes/010.ResourceBase.ps1, source/Private/New-DscResultTuple.ps1, source/en-US/*.psd1, tests/Unit/Classes/ResourceBase.Tests.ps1, tests/Unit/Private/New-DscResultTuple.Tests.ps1, CHANGELOG.md
ResourceBase now evaluates _exist and provides typed test, set, predicted-state, delete, export, and instance-schema helpers. Tests cover what-if behavior, deletion fallbacks, export overrides, tuple construction, and schema forwarding.
DSC fixture and integration validation
tests/Integration/Fixtures/DscResourceBaseTestResource/*, tests/Integration/ResourceBase.Integration.Tests.ps1
A class-based DSC fixture uses an in-memory store and exposes DSC v3 operations. Integration tests cover static and instance methods, adapter operations, filtered exports, updates, deletion, and schema retrieval.

Estimated code review effort: 4 (Complex) | ~60 minutes

Sequence Diagram(s)

sequenceDiagram
  participant DSCAdapter
  participant DscBaseTestResource
  participant ResourceBase
  participant InMemoryStore

  DSCAdapter->>DscBaseTestResource: Invoke DSC operation
  DscBaseTestResource->>ResourceBase: Call lifecycle helper
  ResourceBase->>InMemoryStore: Read or update state
  ResourceBase-->>DscBaseTestResource: Return typed result
  DscBaseTestResource-->>DSCAdapter: Return operation response
Loading
🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Title check ✅ Passed The title clearly and concisely identifies the main change: adding Microsoft DSC support to ResourceBase.
Description check ✅ Passed The description directly explains the DSC v3 support, helper methods, compatibility goals, documentation, localization, and tests.
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.

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.

@Gijsreyn
Gijsreyn marked this pull request as draft August 2, 2026 23:23
@Gijsreyn

Gijsreyn commented Aug 2, 2026

Copy link
Copy Markdown
Author

@gaelcolas - after trying out v0.119.1 of Sampler locally, the build succeeded. Looks like there have been some breaking changes from v0.120.0 onwards?

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Actionable comments posted: 4

🧹 Nitpick comments (10)
tests/Unit/Private/New-DscResultTuple.Tests.ps1 (1)

105-112: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick win

Assert against the localized string.

The test hardcodes the English error text. Build the expected message from $script:localizedData so a change of the string does not silently break the intent of the test.

♻️ Proposed change
     Context 'When the number of types does not match the number of values' {
         It 'Should throw the correct error' {
             InModuleScope -ScriptBlock {
-                { New-DscResultTuple -Type @([System.String]) -Value @('MyValue', 'MySecondValue') } |
-                    Should -Throw -ExpectedMessage '*does not match the number of values*'
+                Set-StrictMode -Version 1.0
+
+                $mockExpectedMessage = $script:localizedData.NewDscResultTuple_CountMismatch -f 1, 2
+
+                { New-DscResultTuple -Type @([System.String]) -Value @('MyValue', 'MySecondValue') } |
+                    Should -Throw -ExpectedMessage ('*{0}*' -f $mockExpectedMessage)
             }
         }
     }

As per path instructions: "Test with localized strings: Use InModuleScope -ScriptBlock { $script:localizedData.Key }".

🤖 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 `@tests/Unit/Private/New-DscResultTuple.Tests.ps1` around lines 105 - 112,
Update the “When the number of types does not match the number of values” test
for New-DscResultTuple to obtain the expected message from $script:localizedData
inside InModuleScope, then assert the thrown error against that localized value
instead of hardcoding English text.

Source: Path instructions

tests/Integration/ResourceBase.Integration.Tests.ps1 (2)

199-200: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick win

Use one Describe block per file.

The file now contains two Describe blocks. Move the dsc.exe tests into a Context block inside Describe 'ResourceBase' and keep the tag and the skip condition on that Context.

♻️ Proposed structure change
-Describe 'ResourceBase with dsc.exe' -Tag 'RequiresDsc' -Skip:$script:skipDscExe {
-    Context 'When invoking operations through the DSC PowerShell adapter' {
+    Context 'When invoking operations through the DSC PowerShell adapter' -Tag 'RequiresDsc' -Skip:$script:skipDscExe {

As per path instructions: "One Describe block per file matching the tested entity name".

🤖 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 `@tests/Integration/ResourceBase.Integration.Tests.ps1` around lines 199 - 200,
Consolidate the dsc.exe test suite into the existing Describe 'ResourceBase'
block instead of declaring a second Describe. Wrap these tests in a Context that
retains the RequiresDsc tag and skip:$script:skipDscExe condition, while
preserving the existing test behavior.

Source: Path instructions


96-166: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick win

Note the order dependency between the contexts.

The Export(), Set(), and Delete() contexts share one in-memory store. The Export() test expects two instances, and the Delete() test removes Instance1. A change of test order, or execution of a single Context, then fails. Reset the fixture state in a BeforeEach or BeforeAll block per Context to make each context independent.

🤖 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 `@tests/Integration/ResourceBase.Integration.Tests.ps1` around lines 96 - 166,
Reset the shared in-memory fixture before each relevant context so the tests
under Export(), Set(), and Delete() start from the expected initial state
independently. Add the setup to the appropriate BeforeEach or BeforeAll blocks,
using the existing fixture initialization mechanism, while preserving each
context’s current assertions and behavior.
source/Private/ConvertTo-JsonSchemaTypeDefinition.ps1 (1)

1-22: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick win

Missing .INPUTS section in the comment-based help of the new private functions. All three new functions declare .OUTPUTS but omit .INPUTS. None of them accept pipeline input, so each help block must declare None..

  • source/Private/ConvertTo-JsonSchemaTypeDefinition.ps1#L1-L22: add an .INPUTS section with None. before .OUTPUTS.
  • source/Private/ConvertTo-DscResourceJsonSchema.ps1#L1-L22: add an .INPUTS section with None. before .OUTPUTS.
  • source/Private/New-DscResultTuple.ps1#L1-L39: add an .INPUTS section with None. before .OUTPUTS.

As per path instructions: "INPUTS: List each pipeline‑accepted type as inline code with a 1‑line description. ... If there are no inputs, specify None.."

🤖 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 `@source/Private/ConvertTo-JsonSchemaTypeDefinition.ps1` around lines 1 - 22,
Update the comment-based help for ConvertTo-JsonSchemaTypeDefinition in
source/Private/ConvertTo-JsonSchemaTypeDefinition.ps1#L1-L22,
ConvertTo-DscResourceJsonSchema in
source/Private/ConvertTo-DscResourceJsonSchema.ps1#L1-L22, and
New-DscResultTuple in source/Private/New-DscResultTuple.ps1#L1-L39 by adding an
.INPUTS section containing None. immediately before each .OUTPUTS section.

Source: Path instructions

source/Private/New-DscResultTuple.ps1 (1)

57-60: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick win

Use $PSCmdlet.ThrowTerminatingError() instead of throw.

The guidelines require terminating errors from functions to use $PSCmdlet.ThrowTerminatingError() with New-ErrorRecord and New-Exception. Also check the localized key name against the pattern Verb_FunctionName_Action; NewDscResultTuple_CountMismatch misses the separator after the verb.

♻️ Proposed error handling change
     if ($Type.Count -ne $Value.Count)
     {
-        throw ($script:localizedData.NewDscResultTuple_CountMismatch -f $Type.Count, $Value.Count)
+        $errorMessage = $script:localizedData.New_DscResultTuple_CountMismatch -f $Type.Count, $Value.Count
+
+        $PSCmdlet.ThrowTerminatingError(
+            (New-ErrorRecord -Message $errorMessage -ErrorId 'NDRT0001' -ErrorCategory 'InvalidArgument' -TargetObject $Type)
+        )
     }

If you rename the key, update source/en-US/DscResource.Base.strings.psd1 and the assertion in tests/Unit/Private/New-DscResultTuple.Tests.ps1.

As per path instructions: "Use $PSCmdlet.ThrowTerminatingError() for terminating errors (except for classes), use relevant error category, in try-catch include exception with localized message" and "Format: Verb_FunctionName_Action (underscore separators)".

🤖 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 `@source/Private/New-DscResultTuple.ps1` around lines 57 - 60, Replace the
direct throw in New-DscResultTuple with $PSCmdlet.ThrowTerminatingError(),
constructing the error through New-Exception and New-ErrorRecord with the
appropriate error category. Rename the localized key to follow the
Verb_FunctionName_Action pattern, then update its definition in
DscResource.Base.strings.psd1 and the corresponding assertion in
New-DscResultTuple.Tests.ps1.

Source: Path instructions

tests/Unit/Private/ConvertTo-DscResourceJsonSchema.Tests.ps1 (1)

120-234: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick win

Group the It blocks in Context blocks.

All It blocks sit directly under Describe. Add Context blocks per scenario, for example a Context 'When converting a class-based DSC resource type' block that wraps the schema document tests, and separate Context blocks for the property conversion scenarios.

As per path instructions: "Each scenario = separate Context block" and "Context descriptions start with 'When'".

🤖 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 `@tests/Unit/Private/ConvertTo-DscResourceJsonSchema.Tests.ps1` around lines
120 - 234, Group the direct child tests in the ConvertTo-DscResourceJsonSchema
Describe block into separate Context blocks, with each scenario in its own
Context and every Context description starting with “When”. Use a class-based
resource Context for the schema document keyword tests and separate “When”
Contexts for each property conversion, inheritance, exclusion, and description
scenario; keep the existing It assertions unchanged.

Source: Path instructions

tests/Unit/Private/ConvertTo-JsonSchemaTypeDefinition.Tests.ps1 (1)

60-64: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick win

Missing Set-StrictMode -Version 1.0 in the new InModuleScope unit tests. All three new unit test files call the private function inside InModuleScope without strict mode. Add the statement immediately before each invocation.

  • tests/Unit/Private/ConvertTo-JsonSchemaTypeDefinition.Tests.ps1#L60-L64: add Set-StrictMode -Version 1.0 before each ConvertTo-JsonSchemaTypeDefinition call in every InModuleScope block.
  • tests/Unit/Private/ConvertTo-DscResourceJsonSchema.Tests.ps1#L121-L125: add Set-StrictMode -Version 1.0 before each ConvertTo-DscResourceJsonSchema call in every InModuleScope block.
  • tests/Unit/Private/New-DscResultTuple.Tests.ps1#L48-L59: add Set-StrictMode -Version 1.0 before each New-DscResultTuple call in every InModuleScope block.

As per path instructions: "In InModuleScope tests, add Set-StrictMode -Version 1.0 immediately before invoking the tested function".

🤖 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 `@tests/Unit/Private/ConvertTo-JsonSchemaTypeDefinition.Tests.ps1` around lines
60 - 64, All new InModuleScope unit tests must enable strict mode immediately
before invoking the tested private function. In
tests/Unit/Private/ConvertTo-JsonSchemaTypeDefinition.Tests.ps1 lines 60-64, add
Set-StrictMode -Version 1.0 before every ConvertTo-JsonSchemaTypeDefinition
call; apply the same change before every ConvertTo-DscResourceJsonSchema call in
tests/Unit/Private/ConvertTo-DscResourceJsonSchema.Tests.ps1 lines 121-125 and
every New-DscResultTuple call in tests/Unit/Private/New-DscResultTuple.Tests.ps1
lines 48-59.

Source: Path instructions

source/Classes/010.ResourceBase.ps1 (1)

356-359: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick win

New ResourceBase methods use throw for terminating errors. The class guidelines require New-*Exception commands for terminating errors in classes. Both new methods raise errors with throw.

  • source/Classes/010.ResourceBase.ps1#L356-L359: replace throw in DeleteInstance() with New-InvalidOperationException (or New-NotImplementedException) using the localized DeleteInstanceNotSupported message.
  • source/Classes/010.ResourceBase.ps1#L375-L378: replace throw in ExportInstances() with New-NotImplementedException using the localized ExportInstancesMethodNotImplemented message.

As per coding guidelines: "Do not use throw for terminating errors, use New-*Exception commands (never for functions)".

🤖 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 `@source/Classes/010.ResourceBase.ps1` around lines 356 - 359, Replace the
terminating throw in ResourceBase.DeleteInstance() at
source/Classes/010.ResourceBase.ps1:356-359 with New-InvalidOperationException
or New-NotImplementedException, preserving the localized
DeleteInstanceNotSupported message. Also replace the terminating throw in
ResourceBase.ExportInstances() at source/Classes/010.ResourceBase.ps1:375-378
with New-NotImplementedException using the localized
ExportInstancesMethodNotImplemented message.

Source: Path instructions

tests/Unit/Classes/ResourceBase.Tests.ps1 (2)

1786-1811: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick win

Wrap the It blocks in a Context block.

The It blocks sit directly in the Describe block. The tests guidelines require a separate Context block per scenario, and the description must start with 'When'. The GetInstanceJsonSchema() Describe at Lines 2116-2149 has the same structure.

As per coding guidelines: "Each scenario = separate Context block" and "Context descriptions start with 'When'".

🤖 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 `@tests/Unit/Classes/ResourceBase.Tests.ps1` around lines 1786 - 1811, Wrap the
three `It` blocks testing `GetPredictedState` in a dedicated `Context` whose
description starts with “When”, keeping each assertion-focused test within that
context. Apply the same structure to the `GetInstanceJsonSchema()` `Describe`
block, using a separate “When” context for its scenario tests.

Source: Path instructions


1969-1973: 📐 Maintainability & Code Quality | 🔵 Trivial | 💤 Low value

Assert against the localized strings.

Both assertions use hardcoded message fragments. Read the message through $script:localizedData so a message change does not silently break the intent of the test.

As per coding guidelines: "Test with localized strings: Use InModuleScope -ScriptBlock { $script:localizedData.Key }".

Also applies to: 1992-1994

🤖 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 `@tests/Unit/Classes/ResourceBase.Tests.ps1` around lines 1969 - 1973, Update
the error assertions in the tests around DeleteInstance and the additional
assertion near the referenced range to use the expected message fragments from
$script:localizedData inside InModuleScope, rather than hardcoded localized
text. Preserve the existing wildcard matching and exception behavior while
referencing the appropriate localization keys.

Source: Path instructions

🤖 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 `@source/en-US/ResourceBase.strings.psd1`:
- Line 18: Update the DeleteInstanceNotSupported resource string to state that
delete is unsupported when the resource lacks both the _exist and Ensure
properties, while preserving the existing DeleteInstance() override guidance and
error code.

In `@source/Private/New-DscResultTuple.ps1`:
- Around line 62-64: Add an arity validation guard before constructing
$closedTupleType in New-DscResultTuple, rejecting $Type.Count values above 8
with the existing localized count-mismatch/validation error. Preserve the
current generic tuple creation flow for supported arities from 1 through 8.

In `@tests/Integration/ResourceBase.Integration.Tests.ps1`:
- Around line 29-35: Update the PSModulePath setup near $script:fixturePath to
also prepend the built module’s output\RequiredModules directory before
importing DscResourceBaseTestResource. Preserve the existing Fixtures path and
ordering, and ensure both paths are included in $env:PSModulePath for child
processes such as dsc.exe.

In `@tests/Unit/Classes/ResourceBase.Tests.ps1`:
- Around line 2116-2122: Update the test for
$mockResourceBaseType::InstanceJsonSchema() to invoke ConvertFrom-Json directly
with -ErrorAction 'Stop', removing the surrounding Should -Not -Throw assertion
while retaining validation of the returned JSON.

---

Nitpick comments:
In `@source/Classes/010.ResourceBase.ps1`:
- Around line 356-359: Replace the terminating throw in
ResourceBase.DeleteInstance() at source/Classes/010.ResourceBase.ps1:356-359
with New-InvalidOperationException or New-NotImplementedException, preserving
the localized DeleteInstanceNotSupported message. Also replace the terminating
throw in ResourceBase.ExportInstances() at
source/Classes/010.ResourceBase.ps1:375-378 with New-NotImplementedException
using the localized ExportInstancesMethodNotImplemented message.

In `@source/Private/ConvertTo-JsonSchemaTypeDefinition.ps1`:
- Around line 1-22: Update the comment-based help for
ConvertTo-JsonSchemaTypeDefinition in
source/Private/ConvertTo-JsonSchemaTypeDefinition.ps1#L1-L22,
ConvertTo-DscResourceJsonSchema in
source/Private/ConvertTo-DscResourceJsonSchema.ps1#L1-L22, and
New-DscResultTuple in source/Private/New-DscResultTuple.ps1#L1-L39 by adding an
.INPUTS section containing None. immediately before each .OUTPUTS section.

In `@source/Private/New-DscResultTuple.ps1`:
- Around line 57-60: Replace the direct throw in New-DscResultTuple with
$PSCmdlet.ThrowTerminatingError(), constructing the error through New-Exception
and New-ErrorRecord with the appropriate error category. Rename the localized
key to follow the Verb_FunctionName_Action pattern, then update its definition
in DscResource.Base.strings.psd1 and the corresponding assertion in
New-DscResultTuple.Tests.ps1.

In `@tests/Integration/ResourceBase.Integration.Tests.ps1`:
- Around line 199-200: Consolidate the dsc.exe test suite into the existing
Describe 'ResourceBase' block instead of declaring a second Describe. Wrap these
tests in a Context that retains the RequiresDsc tag and skip:$script:skipDscExe
condition, while preserving the existing test behavior.
- Around line 96-166: Reset the shared in-memory fixture before each relevant
context so the tests under Export(), Set(), and Delete() start from the expected
initial state independently. Add the setup to the appropriate BeforeEach or
BeforeAll blocks, using the existing fixture initialization mechanism, while
preserving each context’s current assertions and behavior.

In `@tests/Unit/Classes/ResourceBase.Tests.ps1`:
- Around line 1786-1811: Wrap the three `It` blocks testing `GetPredictedState`
in a dedicated `Context` whose description starts with “When”, keeping each
assertion-focused test within that context. Apply the same structure to the
`GetInstanceJsonSchema()` `Describe` block, using a separate “When” context for
its scenario tests.
- Around line 1969-1973: Update the error assertions in the tests around
DeleteInstance and the additional assertion near the referenced range to use the
expected message fragments from $script:localizedData inside InModuleScope,
rather than hardcoded localized text. Preserve the existing wildcard matching
and exception behavior while referencing the appropriate localization keys.

In `@tests/Unit/Private/ConvertTo-DscResourceJsonSchema.Tests.ps1`:
- Around line 120-234: Group the direct child tests in the
ConvertTo-DscResourceJsonSchema Describe block into separate Context blocks,
with each scenario in its own Context and every Context description starting
with “When”. Use a class-based resource Context for the schema document keyword
tests and separate “When” Contexts for each property conversion, inheritance,
exclusion, and description scenario; keep the existing It assertions unchanged.

In `@tests/Unit/Private/ConvertTo-JsonSchemaTypeDefinition.Tests.ps1`:
- Around line 60-64: All new InModuleScope unit tests must enable strict mode
immediately before invoking the tested private function. In
tests/Unit/Private/ConvertTo-JsonSchemaTypeDefinition.Tests.ps1 lines 60-64, add
Set-StrictMode -Version 1.0 before every ConvertTo-JsonSchemaTypeDefinition
call; apply the same change before every ConvertTo-DscResourceJsonSchema call in
tests/Unit/Private/ConvertTo-DscResourceJsonSchema.Tests.ps1 lines 121-125 and
every New-DscResultTuple call in tests/Unit/Private/New-DscResultTuple.Tests.ps1
lines 48-59.

In `@tests/Unit/Private/New-DscResultTuple.Tests.ps1`:
- Around line 105-112: Update the “When the number of types does not match the
number of values” test for New-DscResultTuple to obtain the expected message
from $script:localizedData inside InModuleScope, then assert the thrown error
against that localized value instead of hardcoding English text.
🪄 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: Organization UI

Review profile: CHILL

Plan: Pro Plus

Run ID: 3f2f5c96-0497-4c8c-9d56-3931cf453935

📥 Commits

Reviewing files that changed from the base of the PR and between 0680303 and 56ced3b.

📒 Files selected for processing (15)
  • CHANGELOG.md
  • source/Classes/010.ResourceBase.ps1
  • source/Private/ConvertTo-DscResourceJsonSchema.ps1
  • source/Private/ConvertTo-JsonSchemaTypeDefinition.ps1
  • source/Private/New-DscResultTuple.ps1
  • source/en-US/DscResource.Base.strings.psd1
  • source/en-US/ResourceBase.strings.psd1
  • tests/Integration/Fixtures/DscResourceBaseTestResource/DscResourceBaseTestResource.psd1
  • tests/Integration/Fixtures/DscResourceBaseTestResource/DscResourceBaseTestResource.psm1
  • tests/Integration/Fixtures/DscResourceBaseTestResource/en-US/DscBaseTestResource.strings.psd1
  • tests/Integration/ResourceBase.Integration.Tests.ps1
  • tests/Unit/Classes/ResourceBase.Tests.ps1
  • tests/Unit/Private/ConvertTo-DscResourceJsonSchema.Tests.ps1
  • tests/Unit/Private/ConvertTo-JsonSchemaTypeDefinition.Tests.ps1
  • tests/Unit/Private/New-DscResultTuple.Tests.ps1

Comment thread source/en-US/ResourceBase.strings.psd1
Comment on lines +62 to +64
$openTupleType = [System.Type] ('System.Tuple`{0}' -f $Type.Count)

$closedTupleType = $openTupleType.MakeGenericType($Type)

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

🩺 Stability & Availability | 🟡 Minor | ⚡ Quick win

🧩 Analysis chain

🌐 Web query:

Does casting the string "System.Tuple2" to [System.Type] in PowerShell resolve the open generic type, and what arities does System.Tuple define?`

💡 Result:

Casting a string like "System.Tuple2" to [System.Type] in PowerShell does not resolve it into a fully constructed (closed) generic type, but rather provides a reference to the open generic type definition [1]. In PowerShell, an open generic type requires the use of the.MakeGenericType method to bind specific type arguments and create a usable, closed type [2][1]. Alternatively, you can use the syntax [System.Tuple[type1, type2]] to directly specify the closed type, provided the syntax is supported by your version of PowerShell [2][3][4]. Regarding arities, the System.Tuple class defines support for tuples ranging from 1 to 8 elements (octuples) [5]. Specifically, the.NET Framework provides the following generic classes: - System.Tuple<T1> (1-tuple) - System.Tuple<T1, T2> (2-tuple) - System.Tuple<T1, T2, T3> (3-tuple) - System.Tuple<T1, T2, T3, T4> (4-tuple) - System.Tuple<T1, T2, T3, T4, T5> (5-tuple) - System.Tuple<T1, T2, T3, T4, T5, T6> (6-tuple) - System.Tuple<T1, T2, T3, T4, T5, T6, T7> (7-tuple) - System.Tuple<T1, T2, T3, T4, T5, T6, T7, TRest> (8 or more elements) [5][6] To create tuples with nine or more components, you use the 8-arity version (System.Tuple8) and nest additional System.Tuple objects within the Rest property [5][6].

Citations:


🏁 Script executed:

#!/bin/bash
set -euo pipefail

printf 'Files matching New-DscResultTuple:\n'
fd -a 'New-DscResultTuple\.ps1$' . || true

file="$(fd 'New-DscResultTuple\.ps1$' . | head -n 1)"
if [ -n "${file:-}" ]; then
  printf '\nOutline:\n'
  ast-grep outline "$file" || true
  printf '\nRelevant content:\n'
  cat -n "$file"
fi

printf '\nSearch for New-DscResultTuple usages:\n'
rg -n "New-DscResultTuple|DscResultTuple|Get-DscResultTuple|Set-DscResultTuple|Test-DscResultTuple" . -g '*.ps1' -g '*.psm1' || true

Repository: dsccommunity/DscResource.Base

Length of output: 5312


🏁 Script executed:

#!/bin/bash
set -euo pipefail

printf 'PowerShell/System.Tuple arity probe:\n'
which pwsh || true
if command -v pwsh >/dev/null 2>&1; then
  pwsh -NoProfile -Command '
    try {
      $openTupleType = [System.Type] ("System.Tuple`{0}" -f 9)
      $closedTupleType = $openTupleType.MakeGenericType([string], [int], [bool], [object], [object], [object], [object], [object], [object])
      "closed9=$closedTupleType"
    } catch {
      "closed9_error=$($_.Exception.GetType().FullName): $($_.TargetObject.ToString() -join `"")"
    }

    try {
      $openTupleType = [System.Type] ("System.Tuple`{0}" -f 8)
      $closedTupleType = $openTupleType.MakeGenericType([string], [int], [bool], [object], [object], [object], [object], [object])
      "closed8=$closedTupleType"
    } catch {
      "closed8_error=$($_.Exception.GetType().FullName): $($_.TargetObject.ToString() -join `"")"
    }

    try {
      $openTupleType = [System.Type] ("System.Tuple`{0}" -f 1)
      $closedTupleType = $openTupleType.MakeGenericType([string])
      "closed1=$closedTupleType"
    } catch {
      "closed1_error=$($_.Exception.GetType().FullName): $($_.TargetObject.ToString() -join `"`")"
    }
  '
else
  printf 'pwsh not available in environment.\n'
fi

printf '\nLocalized string key exists check:\n'
rg -n "NewDscResultTuple_|New-DscResultTuple" source/en-US source/ -g '*.strings.psd1' -g '*.ps1' || true

Repository: dsccommunity/DscResource.Base

Length of output: 978


🏁 Script executed:

#!/bin/bash
set -u

printf 'PowerShell/System.Tuple arity and error-name probe:\n'
which pwsh || true
if command -v pwsh >/dev/null 2>&1; then
  pwsh -NoProfile -Command '
    function TryTuple($arity) {
      $name = ("System.Tuple`{0}" -f $arity)
      Write-Verbose ("Name={0}" -f $name)
      $openTupleType = [System.Type] $name
      $types = 1..$arity | ForEach-Object { [string] }
      $closedTupleType = $openTupleType.MakeGenericType($types)
      return $closedTupleType.FullName
    }

    foreach ($arity in @(1,2,8,9)) {
      try {
        $result = TryTuple $arity -ErrorAction Stop
        Write-Host "$arity=OK $result"
      } catch {
        $ex = $_.Exception
        $tr = $_.TargetObject
        $trStr = if ($tr -gt 0 -and $tr -lt 256) { $tr.ToString("X63") } else { "" }
        Write-Host "$arity=ERROR $($ex.GetType().FullName) $ex.Message TargetId=$trStr"
      }
    }
  ' -ErrorAction Stop
else
  printf 'pwsh not available in environment.\n'
fi

printf '\nLocalized string key exists check:\n'
rg -n "NewDscResultTuple_|New-DscResultTuple" source/en-US source/tests -g '*.strings.psd1' -g '*.ps1' || true

printf '\nCall sites with arity literals:\n'
ruby -e 'STDIN.read.scan(/\[New-DscResultTuple -Type\s+@?\(?\s*\[([^,\]]+)\s*(?:,[^,\]]+)+\s*([^\)]+)\s*]/m) { |types,l| puts "TYPES=#{types.count + 1}" }' <<'PS' > /tmp/dsc_call_extraction.txt 2>/tmp/dsc_call_extraction.err || true
cat /tmp/dsc_call_extraction.txt 2>/dev/null || true
cat /tmp/dsc_call_extraction.err >/dev/null 2>&1 || true
rg -n "New-DscResultTuple\s+-Type" source tests -g '*.ps1' -g '*.psm1' || true

Repository: dsccommunity/DscResource.Base

Length of output: 6279


🏁 Script executed:

#!/usr/bin/env bash
set -u

printf 'PowerShell/System.Tuple arity probe (robust):\n'
command -v pwsh >/dev/null 2>&1 && {
  pwsh -NoProfile -Command '
    function TryTuple($arity) {
      $name = ("System.Tuple`{0}" -f $arity)
      try {
        $openTupleType = $null
        $openTupleType = [System.Type] $name
        $types = 1..$arity | ForEach-Object { [string] }
        $closedTupleType = $openTupleType.MakeGenericType($types)
        return ("OK:{0}" -f $closedTupleType.FullName)
      } catch {
        $msg = $_.Exception.Message.Insert(0, "{0}:" -f $arity)
        return "FAIL:$msg"
      }
    }
    1, 2, 8, 9 | ForEach-Object { TryTuple $_ }
  '
} || printf 'pwsh not available\n'

printf '\nFile and localized key context:\n'
for f in $(fd 'New-DscResultTuple\.ps1$|DscResource\.Base\.strings\.psd1$' .); do
  printf '\n--- %s ---\n' "$f"
  wc -l "$f"
  rg -n "New-DscResultTuple|Tuples are invariant|Arity|tuple" "$f" || true
done
rg -n "New-DscResultTuple\s+-Type" . -g '*.ps1' -g '*.psm1' || true

Repository: dsccommunity/DscResource.Base

Length of output: 3620


Add a tuple arity limit guard.

System.Tuple supports 1 to 8 elements. If $Type has more than 8 types, MakeGenericType() returns null and CreateInstance() then throws an unclear error. Emit the localized count-mismatch/validation error for this case instead of throwing the .NET reflection error.

🤖 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 `@source/Private/New-DscResultTuple.ps1` around lines 62 - 64, Add an arity
validation guard before constructing $closedTupleType in New-DscResultTuple,
rejecting $Type.Count values above 8 with the existing localized
count-mismatch/validation error. Preserve the current generic tuple creation
flow for supported arities from 1 through 8.

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

@Gijsreyn would this be an issue?

Comment thread tests/Integration/ResourceBase.Integration.Tests.ps1
Comment thread tests/Unit/Classes/ResourceBase.Tests.ps1
@johlju johlju added the needs review The pull request needs a code review. label Aug 3, 2026

@johlju johlju left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

this doesn't look like it would break existing functionality. Just a small comment.

Comment on lines +62 to +64
$openTupleType = [System.Type] ('System.Tuple`{0}' -f $Type.Count)

$closedTupleType = $openTupleType.MakeGenericType($Type)

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

@Gijsreyn would this be an issue?

@johlju

johlju commented Aug 3, 2026

Copy link
Copy Markdown
Member

Not sure why the build breaks, something change in new Sampler release maybe?

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

Labels

needs review The pull request needs a code review.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants