Skip to content

Fix style for terminating error in commands#2312

Merged
johlju merged 25 commits intodsccommunity:mainfrom
johlju:fix/issue-#2200
Oct 22, 2025
Merged

Fix style for terminating error in commands#2312
johlju merged 25 commits intodsccommunity:mainfrom
johlju:fix/issue-#2200

Conversation

@johlju
Copy link
Member

@johlju johlju commented Oct 20, 2025

Pull Request (PR) description

  • Remove-SqlDscAgentAlert
    • Now uses $PSCmdlet.ThrowTerminatingError() instead of exception helper
      functions for proper terminating error handling (issue #2193).
  • Set-SqlDscAgentAlert
    • Now uses $PSCmdlet.ThrowTerminatingError() instead of exception helper
      functions for proper terminating error handling (issue #2196).
  • Remove-SqlDscDatabase
    • Now uses $PSCmdlet.ThrowTerminatingError() instead of exception helper
      functions for proper terminating error handling (issue #2195).
  • Remove-SqlDscRole
    • Now uses $PSCmdlet.ThrowTerminatingError() instead of exception helper
      functions for proper terminating error handling (issue #2199).
  • New-SqlDscDatabase
    • Now uses $PSCmdlet.ThrowTerminatingError() instead of exception helper
      functions for proper terminating error handling (issue #2200).
  • Set-SqlDscDatabase
    • Now uses $PSCmdlet.ThrowTerminatingError() instead of exception helper
      functions for proper terminating error handling (issue #2198).

This Pull Request (PR) fixes the following issues

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).
  • Resource documentation updated in the resource's README.md.
  • Resource parameter descriptions updated in schema.mof.
  • Comment-based help updated, including parameter descriptions.
  • Localization strings updated.
  • Examples updated.
  • Unit tests updated. See DSC Community Testing Guidelines.
  • Integration tests updated (where possible). See DSC Community Testing Guidelines.
  • Code changes adheres to DSC Community Style Guidelines.

This change is Reviewable

@johlju johlju requested a review from a team as a code owner October 20, 2025 18:10
@coderabbitai
Copy link

coderabbitai bot commented Oct 20, 2025

Walkthrough

Refactors terminating-error handling across multiple public cmdlets to use $PSCmdlet.ThrowTerminatingError() with constructed ErrorRecords and error IDs; adds scoped ErrorActionPreference/ConfirmPreference adjustments, ShouldProcess message updates and localization key changes; updates tests and a test SMO enum.

Changes

Cohort / File(s) Summary
Alert cmdlets
source/Public/Remove-SqlDscAgentAlert.ps1, source/Public/Set-SqlDscAgentAlert.ps1
Replace exception-helper throws with $PSCmdlet.ThrowTerminatingError() and structured ErrorRecords (e.g., RSAA0005, SSAA0002, SSAA0008); add scoped $ErrorActionPreference='Stop', try/catch/finally, and improved verbose messaging.
Database cmdlets
source/Public/New-SqlDscDatabase.ps1, source/Public/Remove-SqlDscDatabase.ps1, source/Public/Set-SqlDscDatabase.ps1
Replace New-ArgumentException/New-InvalidOperationException/object-not-found helpers with $PSCmdlet.ThrowTerminatingError() using ErrorRecords (IDs: NSD0003/NSD0004, RSDD0001RSDD0005, SSDD0001SSDD0004); add begin blocks for ConfirmPreference, preserve/restore $ErrorActionPreference, try/catch flows, and explicit DropConnections handling.
Role cmdlets
source/Public/Remove-SqlDscRole.ps1, source/Public/Get-SqlDscRole.ps1, source/Public/New-SqlDscRole.ps1
Convert thrown helpers to $PSCmdlet.ThrowTerminatingError() with ErrorRecords (RSDR0001RSDR0003); add begin blocks to suppress confirmation when -Force used, remove -Force OR from ShouldProcess guards, update ShouldProcess message keys, and early-return on missing role.
Localization / Strings
source/en-US/SqlServerDsc.strings.psd1
Rename/add localization keys and append diagnostic codes (e.g., Role_NotFoundGet_SqlDscRole_NotFound, add Remove_SqlDscRole_NotFound, add Remove_SqlDscDatabase_NotFound); update ShouldProcess description/confirmation keys.
Unit tests (error assertions updated)
tests/Unit/Public/New-SqlDscDatabase.Tests.ps1, tests/Unit/Public/Remove-SqlDscAgentAlert.Tests.ps1, tests/Unit/Public/Set-SqlDscDatabase.Tests.ps1, tests/Unit/Public/Get-SqlDscRole.Tests.ps1, tests/Unit/Public/Remove-SqlDscDatabase.Tests.ps1
Update tests to capture error objects (-PassThru) and assert on Exception.Message/type, FullyQualifiedErrorId/-ErrorId, CategoryInfo and TargetName; add contexts for database modification failure and tighten ErrorId expectations.
Integration tests
tests/Integration/Commands/Get-SqlDscRole.Integration.Tests.ps1
Relax exact error-message assertion to a generic Should -Throw to accommodate appended diagnostic codes.
Test stubs / exported types
tests/Unit/Stubs/SMO.cs
Add public enum DatabaseUserAccess : int { Multiple = 0, Single = 1, Restricted = 2 } to test stubs.
Changelog
CHANGELOG.md
Document terminating-error handling changes across public commands and reference issues #2193, #2195, #2196, #2198, #2199, #2200.

Sequence Diagram(s)

sequenceDiagram
  autonumber
  participant Caller
  participant Cmdlet as "Public Cmdlet"
  participant Validator as "Validation / SMO"
  participant Host as "PowerShell Host"

  Caller->>Cmdlet: Invoke (params, -Force/-Confirm)
  Cmdlet->>Cmdlet: adjust ConfirmPreference / scope $ErrorActionPreference
  Cmdlet->>Validator: validate inputs / perform SMO operation
  alt validation/operation fails
    Validator-->>Cmdlet: exception
    Cmdlet->>Host: $PSCmdlet.ThrowTerminatingError(ErrorRecord)
    Note right of Host #f7fbff: Terminating error surfaced\n(ErrorRecord: ID, Category, Target)
    Host->>Caller: terminating error (ErrorRecord)
  else success
    Validator-->>Cmdlet: result
    Cmdlet-->>Caller: return result
  end
Loading

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~45 minutes

Possibly related PRs

Pre-merge checks

❌ Failed checks (1 warning)
Check name Status Explanation Resolution
Out of Scope Changes Check ⚠️ Warning The PR includes changes to Get-SqlDscRole and New-SqlDscRole that are not covered by any of the six linked issues (#2193, #2195, #2196, #2198, #2199, #2200). Get-SqlDscRole was modified to use Get_SqlDscRole_NotFound localization key with error code GSDR0001, and New-SqlDscRole was modified to add a begin block for ConfirmPreference handling and change ShouldProcess flow. While these changes appear to follow the same error-handling modernization pattern, they extend the PR scope beyond the explicitly stated objectives which list only six specific commands. Additionally, changes to localization strings and test stubs go beyond direct support for the six target commands. Consider whether changes to Get-SqlDscRole and New-SqlDscRole are necessary for this PR or should be separated into a follow-up PR. If these changes are necessary for consistency and maintainability, they should be explicitly mentioned in the PR description and linked to related issues. Otherwise, revert them to keep the PR focused on the six specified commands and issues.
✅ Passed checks (4 passed)
Check name Status Explanation
Title Check ✅ Passed The title "Fix style for terminating error in commands" accurately and concisely captures the primary change in the PR. It clearly indicates that the changeset addresses how terminating errors are handled across multiple commands, which is exactly what the PR accomplishes by replacing exception helper functions with $PSCmdlet.ThrowTerminatingError(). The title is specific enough to convey the main objective to reviewers scanning the history.
Linked Issues Check ✅ Passed The code changes successfully address all requirements from the six linked issues (#2193, #2195, #2196, #2198, #2199, #2200). Each targeted command has been updated to replace exception helper functions with $PSCmdlet.ThrowTerminatingError() and appropriate ErrorRecord objects: Remove-SqlDscAgentAlert wraps the drop operation with try/catch/finally using InvalidOperationException; Set-SqlDscAgentAlert constructs ErrorRecord with ItemNotFoundException and InvalidOperationException; Remove-SqlDscDatabase uses ItemNotFoundException and InvalidOperationException with specific error codes; Remove-SqlDscRole uses ObjectNotFound and InvalidOperation categories; New-SqlDscDatabase replaces New-ArgumentException with ThrowTerminatingError for validation; Set-SqlDscDatabase constructs ErrorRecord for multiple failure scenarios. Unit tests have been updated to validate the new error handling behavior.
Description Check ✅ Passed The PR description is directly related to the changeset and provides specific information about what was changed. It clearly lists all six affected commands (Remove-SqlDscAgentAlert, Set-SqlDscAgentAlert, Remove-SqlDscDatabase, Remove-SqlDscRole, New-SqlDscDatabase, Set-SqlDscDatabase), explains the change for each (replacing exception helpers with $PSCmdlet.ThrowTerminatingError), and references the corresponding issue numbers. The description also indicates which tasks in the checklist were completed.
Docstring Coverage ✅ Passed No functions found in the changes. Docstring coverage check skipped.

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.

Copy link

@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: 5

🧹 Nitpick comments (5)
source/Public/New-SqlDscDatabase.ps1 (1)

151-158: Good switch to structured terminating errors; add a guard for future SQL versions.

If $ServerObject.VersionMajor isn’t in $supportedCompatibilityLevels, the lookup returns $null and any value will be treated as invalid. Add a fallback to the highest known set (or skip validation) to avoid false negatives on future releases.

Example minimal change:

-            if ($CompatibilityLevel -notin $supportedCompatibilityLevels.$($ServerObject.VersionMajor))
+            $allowed = $supportedCompatibilityLevels[$ServerObject.VersionMajor]
+            if (-not $allowed) { $allowed = $supportedCompatibilityLevels[[int]($supportedCompatibilityLevels.Keys | Measure-Object -Maximum).Maximum] }
+            if ($CompatibilityLevel -notin $allowed)
source/Public/Remove-SqlDscRole.ps1 (2)

97-104: Use ObjectNotFound category for missing role.

The error fits ObjectNotFound better than InvalidOperation. Consider:

-                        [System.InvalidOperationException]::new($errorMessage),
-                        'RSDR0001',
-                        [System.Management.Automation.ErrorCategory]::InvalidOperation,
+                        [System.Management.Automation.ItemNotFoundException]::new($errorMessage),
+                        'RSDR0001',
+                        [System.Management.Automation.ErrorCategory]::ObjectNotFound,

119-125: Built-in role guard: terminating error usage looks good.

InvalidOperation with localized message and target object is appropriate here. LGTM. As a consistency tweak, consider adopting the Force confirmation pattern ($ConfirmPreference = 'None') instead of bypassing ShouldProcess when -Force is used.

source/Public/Remove-SqlDscDatabase.ps1 (2)

170-201: Use SMO enum for UserAccess; keep the robust restore of ErrorActionPreference.

Assigning 'Single' relies on implicit conversion; prefer the enum to avoid brittleness across SMO versions.

-                    $DatabaseObject.UserAccess = 'Single'
+                    $DatabaseObject.UserAccess = [Microsoft.SqlServer.Management.Smo.DatabaseUserAccess]::Single

205-214: Removal flow and verbose telemetry are fine; structure looks good.

Try/restore pattern with a dedicated ErrorId is solid. Consider adopting the Force confirmation pattern (if ($Force.IsPresent -and -not $Confirm) { $ConfirmPreference = 'None' }) for consistency with other commands.

📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 0f3d639 and fbc4055.

📒 Files selected for processing (10)
  • CHANGELOG.md (1 hunks)
  • source/Public/New-SqlDscDatabase.ps1 (2 hunks)
  • source/Public/Remove-SqlDscAgentAlert.ps1 (2 hunks)
  • source/Public/Remove-SqlDscDatabase.ps1 (5 hunks)
  • source/Public/Remove-SqlDscRole.ps1 (3 hunks)
  • source/Public/Set-SqlDscAgentAlert.ps1 (2 hunks)
  • source/Public/Set-SqlDscDatabase.ps1 (4 hunks)
  • tests/Unit/Public/New-SqlDscDatabase.Tests.ps1 (1 hunks)
  • tests/Unit/Public/Remove-SqlDscAgentAlert.Tests.ps1 (1 hunks)
  • tests/Unit/Public/Set-SqlDscDatabase.Tests.ps1 (4 hunks)
🧰 Additional context used
📓 Path-based instructions (13)
**/*.[Tt]ests.ps1

📄 CodeRabbit inference engine (.github/instructions/dsc-community-style-guidelines-pester.instructions.md)

**/*.[Tt]ests.ps1: All public commands, private functions, and classes must have unit tests
All public commands and class-based resources must have integration tests
Use Pester v5 syntax only
Test code only inside Describe blocks
Assertions only in It blocks
Never test verbose messages, debug messages, or parameter binding behavior
Pass all mandatory parameters to avoid prompts
Inside It blocks, assign unused return objects to $null (unless part of a pipeline)
Call the tested entity from within the It blocks
Keep results and assertions in the same It block
Avoid try/catch/finally for cleanup; use AfterAll or AfterEach
Avoid unnecessary remove/recreate cycles
One Describe block per file matching the tested entity name
Context descriptions start with 'When'
It descriptions start with 'Should' and must not contain 'when'
Mock variables must be prefixed with 'mock'
Public commands: never use InModuleScope (except for retrieving localized strings)
Private functions and class resources: always use InModuleScope
Each class method gets a separate Context block
Each scenario gets a separate Context block
Use nested Context blocks for complex scenarios
Perform mocking in BeforeAll (use BeforeEach only when required)
Place setup/teardown (BeforeAll/BeforeEach/AfterAll/AfterEach) close to usage
Use PascalCase for Pester keywords: Describe, Context, It, Should, BeforeAll, BeforeEach, AfterAll, AfterEach
Use -BeTrue/-BeFalse; never use -Be $true/-Be $false
Never use Assert-MockCalled; use Should -Invoke instead
Do not use Should -Not -Throw; invoke commands directly
Never add an empty -MockWith block
Omit -MockWith when returning $null
Set $PSDefaultParameterValues for Mock:ModuleName, Should:ModuleName, and InModuleScope:ModuleName
Omit the -ModuleName parameter on Pester commands
Never use Mock inside an InModuleScope block
Define variables for -ForEach in a separate BeforeDiscovery near usage
Use -ForEach only on Context and It blocks
Keep variable scope close to the usage c...

Files:

  • tests/Unit/Public/Remove-SqlDscAgentAlert.Tests.ps1
  • tests/Unit/Public/New-SqlDscDatabase.Tests.ps1
  • tests/Unit/Public/Set-SqlDscDatabase.Tests.ps1

⚙️ CodeRabbit configuration file

**/*.[Tt]ests.ps1: # Tests Guidelines

Core Requirements

  • All public commands, private functions and classes must have unit tests
  • All public commands and class-based resources must have integration tests
  • Use Pester v5 syntax only
  • Test code only inside Describe blocks
  • Assertions only in It blocks
  • Never test verbose messages, debug messages or parameter binding behavior
  • Pass all mandatory parameters to avoid prompts

Requirements

  • Inside It blocks, assign unused return objects to $null (unless part of pipeline)
  • Tested entity must be called from within the It blocks
  • Keep results and assertions in same It block
  • Avoid try-catch-finally for cleanup, use AfterAll or AfterEach
  • Avoid unnecessary remove/recreate cycles

Naming

  • One Describe block per file matching the tested entity name
  • Context descriptions start with 'When'
  • It descriptions start with 'Should', must not contain 'when'
  • Mock variables prefix: 'mock'

Structure & Scope

  • Public commands: Never use InModuleScope (unless retrieving localized strings)
  • Private functions/class resources: Always use InModuleScope
  • Each class method = separate Context block
  • Each scenario = separate Context block
  • Use nested Context blocks for complex scenarios
  • Mocking in BeforeAll (BeforeEach only when required)
  • Setup/teardown in BeforeAll,BeforeEach/AfterAll,AfterEach close to usage

Syntax Rules

  • PascalCase: Describe, Context, It, Should, BeforeAll, BeforeEach, AfterAll, AfterEach
  • Use -BeTrue/-BeFalse never -Be $true/-Be $false
  • Never use Assert-MockCalled, use Should -Invoke instead
  • No Should -Not -Throw - invoke commands directly
  • Never add an empty -MockWith block
  • Omit -MockWith when returning $null
  • Set $PSDefaultParameterValues for Mock:ModuleName, Should:ModuleName, InModuleScope:ModuleName
  • Omit -ModuleName parameter on Pester commands
  • Never use Mock inside `InModuleSc...

Files:

  • tests/Unit/Public/Remove-SqlDscAgentAlert.Tests.ps1
  • tests/Unit/Public/New-SqlDscDatabase.Tests.ps1
  • tests/Unit/Public/Set-SqlDscDatabase.Tests.ps1
tests/Unit/Public/*.Tests.ps1

📄 CodeRabbit inference engine (.github/instructions/dsc-community-style-guidelines-pester.instructions.md)

Public command unit tests must reside in tests/Unit/Public/{Name}.Tests.ps1

Place unit tests for public commands in tests/Unit/Public/{Name}.Tests.ps1

Files:

  • tests/Unit/Public/Remove-SqlDscAgentAlert.Tests.ps1
  • tests/Unit/Public/New-SqlDscDatabase.Tests.ps1
  • tests/Unit/Public/Set-SqlDscDatabase.Tests.ps1
**/*.{ps1,psm1}

📄 CodeRabbit inference engine (.github/instructions/dsc-community-style-guidelines-powershell.instructions.md)

**/*.{ps1,psm1}: Use descriptive names (3+ characters, no abbreviations)
Function names use PascalCase Verb-Noun with approved verbs
Parameter names use PascalCase
Variable names use camelCase
Keywords are lower-case
Class names use PascalCase
Include scope prefixes for script/global/environment variables: $script:, $global:, $env:
Use one space around operators (e.g., $a = 1 + 2)
Use one space between type and variable (e.g., [String] $name)
Use one space between keyword and parenthesis (e.g., if ($condition))
Place newline before opening brace (except variable assignments)
One newline after opening brace
Two newlines after closing brace (one if followed by another brace or continuation)
Use single quotes unless variable expansion is needed
Arrays on one line use @('one','two'); multi-line arrays have one element per line with proper indentation
Do not use unary comma in return statements to force an array
Single-line comments: '# Comment' capitalized on its own line
Multi-line comments use <# #> with brackets on their own lines and indented text
No commented-out code
Add comment-based help to all functions and scripts
Comment-based help must include SYNOPSIS, DESCRIPTION (40+ chars), PARAMETER, and EXAMPLE sections before function/class
Comment-based help indentation: keywords at 4 spaces, text at 8 spaces
Include examples for all parameter sets and combinations
INPUTS: list each pipeline-accepted type with one-line description; repeat .INPUTS per type
OUTPUTS: list each return type with one-line description; repeat .OUTPUTS per type; must match [OutputType()] and actual returns
.NOTES only if critical (constraints, side effects, security, version compatibility, breaking behavior), ≤2 short sentences
Avoid aliases; use full command names
Avoid Write-Host; prefer Write-Verbose/Write-Information/etc.
Avoid Write-Output; use return instead
Do not use ConvertTo-SecureString -AsPlainText in production code
Do not redefine reserved parameters (Verbose, Debug, etc.)
In...

Files:

  • tests/Unit/Public/Remove-SqlDscAgentAlert.Tests.ps1
  • source/Public/Remove-SqlDscDatabase.ps1
  • source/Public/Set-SqlDscDatabase.ps1
  • tests/Unit/Public/New-SqlDscDatabase.Tests.ps1
  • source/Public/Set-SqlDscAgentAlert.ps1
  • source/Public/Remove-SqlDscRole.ps1
  • tests/Unit/Public/Set-SqlDscDatabase.Tests.ps1
  • source/Public/New-SqlDscDatabase.ps1
  • source/Public/Remove-SqlDscAgentAlert.ps1
**/*.{ps1,psm1,psd1}

📄 CodeRabbit inference engine (.github/instructions/dsc-community-style-guidelines-powershell.instructions.md)

**/*.{ps1,psm1,psd1}: Indent with 4 spaces; do not use tabs
No spaces on empty lines
Try to limit lines to 120 characters
Empty hashtable is @{}
Hashtable: each property on its own line with proper indentation
Hashtable property names use PascalCase
End files with exactly one blank line
Use line endings as defined by .gitattributes policy
Allow at most two consecutive newlines
No trailing whitespace on any line
Use UTF-8 encoding without BOM for all files

Files:

  • tests/Unit/Public/Remove-SqlDscAgentAlert.Tests.ps1
  • source/Public/Remove-SqlDscDatabase.ps1
  • source/Public/Set-SqlDscDatabase.ps1
  • tests/Unit/Public/New-SqlDscDatabase.Tests.ps1
  • source/Public/Set-SqlDscAgentAlert.ps1
  • source/Public/Remove-SqlDscRole.ps1
  • tests/Unit/Public/Set-SqlDscDatabase.Tests.ps1
  • source/Public/New-SqlDscDatabase.ps1
  • source/Public/Remove-SqlDscAgentAlert.ps1
tests/[Uu]nit/**/*.[Tt]ests.ps1

📄 CodeRabbit inference engine (.github/instructions/dsc-community-style-guidelines-unit-tests.instructions.md)

tests/[Uu]nit/**/*.[Tt]ests.ps1: In unit tests, access localized strings using InModuleScope -ScriptBlock { $script:localizedData.Key }
When mocking files in tests, use the $TestDrive variable for file system operations
All public commands must include parameter set validation tests
Include the exact Pester setup block before Describe: SuppressMessage attribute with param (); BeforeDiscovery to ensure DscResource.Test is available (fallback to build.ps1 -Tasks 'noop') and Import-Module; BeforeAll to set $script:moduleName, import the module, and set PSDefaultParameterValues for InModuleScope/Mock/Should; AfterAll to remove those defaults and unload the tested module
Use the provided Parameter Set Validation test template to assert command ParameterSetName and full parameter list string; for multiple parameter sets, supply multiple hashtables via -ForEach
Use the Parameter Properties template to assert a parameter is mandatory via $parameterInfo = (Get-Command -Name 'CommandName').Parameters['ParameterName']; $parameterInfo.Attributes.Mandatory | Should -BeTrue

Files:

  • tests/Unit/Public/Remove-SqlDscAgentAlert.Tests.ps1
  • tests/Unit/Public/New-SqlDscDatabase.Tests.ps1
  • tests/Unit/Public/Set-SqlDscDatabase.Tests.ps1

⚙️ CodeRabbit configuration file

tests/[Uu]nit/**/*.[Tt]ests.ps1: # Unit Tests Guidelines

  • Test with localized strings: Use InModuleScope -ScriptBlock { $script:localizedData.Key }
  • Mock files: Use $TestDrive variable (path to the test drive)
  • All public commands require parameter set validation tests
  • After modifying classes, always run tests in new session (for changes to take effect)

Test Setup Requirements

Use this exact setup block before Describe:

[System.Diagnostics.CodeAnalysis.SuppressMessageAttribute('PSUseDeclaredVarsMoreThanAssignments', '', Justification = 'Suppressing this rule because Script Analyzer does not understand Pester syntax.')]
param ()

BeforeDiscovery {
    try
    {
        if (-not (Get-Module -Name 'DscResource.Test'))
        {
            # Assumes dependencies have been resolved, so if this module is not available, run 'noop' task.
            if (-not (Get-Module -Name 'DscResource.Test' -ListAvailable))
            {
                # Redirect all streams to $null, except the error stream (stream 2)
                & "$PSScriptRoot/../../../build.ps1" -Tasks 'noop' 3>&1 4>&1 5>&1 6>&1 > $null
            }

            # If the dependencies have not been resolved, this will throw an error.
            Import-Module -Name 'DscResource.Test' -Force -ErrorAction 'Stop'
        }
    }
    catch [System.IO.FileNotFoundException]
    {
        throw 'DscResource.Test module dependency not found. Please run ".\build.ps1 -ResolveDependency -Tasks noop" first.'
    }
}

BeforeAll {
    $script:moduleName = '{MyModuleName}'

    Import-Module -Name $script:moduleName -Force -ErrorAction 'Stop'

    $PSDefaultParameterValues['InModuleScope:ModuleName'] = $script:moduleName
    $PSDefaultParameterValues['Mock:ModuleName'] = $script:moduleName
    $PSDefaultParameterValues['Should:ModuleName'] = $script:moduleName
}

AfterAll {
    $PSDefaultParameterValues.Remove('InModuleScope:ModuleName')
    $PSDefaultParameterValues.Remove('Mock:ModuleNam...

Files:

  • tests/Unit/Public/Remove-SqlDscAgentAlert.Tests.ps1
  • tests/Unit/Public/New-SqlDscDatabase.Tests.ps1
  • tests/Unit/Public/Set-SqlDscDatabase.Tests.ps1
**/*.ps1

📄 CodeRabbit inference engine (.github/instructions/dsc-community-style-guidelines.instructions.md)

Follow PowerShell style and test guideline instructions strictly

Files:

  • tests/Unit/Public/Remove-SqlDscAgentAlert.Tests.ps1
  • source/Public/Remove-SqlDscDatabase.ps1
  • source/Public/Set-SqlDscDatabase.ps1
  • tests/Unit/Public/New-SqlDscDatabase.Tests.ps1
  • source/Public/Set-SqlDscAgentAlert.ps1
  • source/Public/Remove-SqlDscRole.ps1
  • tests/Unit/Public/Set-SqlDscDatabase.Tests.ps1
  • source/Public/New-SqlDscDatabase.ps1
  • source/Public/Remove-SqlDscAgentAlert.ps1
tests/Unit/{Classes,Public,Private}/*.Tests.ps1

📄 CodeRabbit inference engine (.github/instructions/dsc-community-style-guidelines.instructions.md)

Add unit tests for all commands, functions, and resources

Files:

  • tests/Unit/Public/Remove-SqlDscAgentAlert.Tests.ps1
  • tests/Unit/Public/New-SqlDscDatabase.Tests.ps1
  • tests/Unit/Public/Set-SqlDscDatabase.Tests.ps1
**

⚙️ CodeRabbit configuration file

**: # DSC Community Guidelines

Terminology

  • Command: Public command
  • Function: Private function
  • Resource: DSC class-based resource

Build & Test Workflow Requirements

  • Run PowerShell script files from repository root
  • Setup build and test environment (once per pwsh session): ./build.ps1 -Tasks noop
  • Build project before running tests: ./build.ps1 -Tasks build
  • Always run tests in new pwsh session: Invoke-Pester -Path @({test paths}) -Output Detailed

File Organization

  • Public commands: source/Public/{CommandName}.ps1
  • Private functions: source/Private/{FunctionName}.ps1
  • Unit tests: tests/Unit/{Classes|Public|Private}/{Name}.Tests.ps1
  • Integration tests: tests/Integration/Commands/{CommandName}.Integration.Tests.ps1

Requirements

  • Follow instructions over existing code patterns
  • Follow PowerShell style and test guideline instructions strictly
  • Always update CHANGELOG.md Unreleased section
  • Localize all strings using string keys; remove any orphaned string keys
  • Check DscResource.Common before creating private functions
  • Separate reusable logic into private functions
  • DSC resources should always be created as class-based resources
  • Add unit tests for all commands/functions/resources
  • Add integration tests for all public commands and resources

Files:

  • tests/Unit/Public/Remove-SqlDscAgentAlert.Tests.ps1
  • source/Public/Remove-SqlDscDatabase.ps1
  • source/Public/Set-SqlDscDatabase.ps1
  • tests/Unit/Public/New-SqlDscDatabase.Tests.ps1
  • source/Public/Set-SqlDscAgentAlert.ps1
  • source/Public/Remove-SqlDscRole.ps1
  • tests/Unit/Public/Set-SqlDscDatabase.Tests.ps1
  • source/Public/New-SqlDscDatabase.ps1
  • source/Public/Remove-SqlDscAgentAlert.ps1
  • CHANGELOG.md
{**/*.ps1,**/*.psm1,**/*.psd1}

⚙️ CodeRabbit configuration file

{**/*.ps1,**/*.psm1,**/*.psd1}: # PowerShell Guidelines

Naming

  • Use descriptive names (3+ characters, no abbreviations)
  • Functions: PascalCase with Verb-Noun format using approved verbs
  • Parameters: PascalCase
  • Variables: camelCase
  • Keywords: lower-case
  • Classes: PascalCase
  • Include scope for script/global/environment variables: $script:, $global:, $env:

File naming

  • Class files: ###.ClassName.ps1 format (e.g. 001.SqlReason.ps1, 004.StartupParameters.ps1)

Formatting

Indentation & Spacing

  • Use 4 spaces (no tabs)
  • One space around operators: $a = 1 + 2
  • One space between type and variable: [String] $name
  • One space between keyword and parenthesis: if ($condition)
  • No spaces on empty lines
  • Try to limit lines to 120 characters

Braces

  • Newline before opening brace (except variable assignments)
  • One newline after opening brace
  • Two newlines after closing brace (one if followed by another brace or continuation)

Quotes

  • Use single quotes unless variable expansion is needed: 'text' vs "text $variable"

Arrays

  • Single line: @('one', 'two', 'three')
  • Multi-line: each element on separate line with proper indentation
  • Do not use the unary comma operator (,) in return statements to force
    an array

Hashtables

  • Empty: @{}
  • Each property on separate line with proper indentation
  • Properties: Use PascalCase

Comments

  • Single line: # Comment (capitalized, on own line)
  • Multi-line: <# Comment #> format (opening and closing brackets on own line), and indent text
  • No commented-out code

Comment-based help

  • Always add comment-based help to all functions and scripts
  • Comment-based help: SYNOPSIS, DESCRIPTION (40+ chars), PARAMETER, EXAMPLE sections before function/class
  • Comment-based help indentation: keywords 4 spaces, text 8 spaces
  • Include examples for all parameter sets and combinations
  • INPUTS: List each pipeline‑accepted type (one per line) with a 1‑line description...

Files:

  • tests/Unit/Public/Remove-SqlDscAgentAlert.Tests.ps1
  • source/Public/Remove-SqlDscDatabase.ps1
  • source/Public/Set-SqlDscDatabase.ps1
  • tests/Unit/Public/New-SqlDscDatabase.Tests.ps1
  • source/Public/Set-SqlDscAgentAlert.ps1
  • source/Public/Remove-SqlDscRole.ps1
  • tests/Unit/Public/Set-SqlDscDatabase.Tests.ps1
  • source/Public/New-SqlDscDatabase.ps1
  • source/Public/Remove-SqlDscAgentAlert.ps1
source/**/*.ps1

📄 CodeRabbit inference engine (.github/instructions/dsc-community-style-guidelines-localization.instructions.md)

source/**/*.ps1: Localize all Write-Debug, Write-Verbose, Write-Error, Write-Warning, and $PSCmdlet.ThrowTerminatingError() messages
Use localized string keys instead of hardcoded strings in script output/messages
Assume and use $script:localizedData for accessing localized strings
When emitting messages, reference $script:localizedData.KeyName and format with the -f operator (e.g., Write-Verbose -Message ($script:localizedData.KeyName -f $value1))

Files:

  • source/Public/Remove-SqlDscDatabase.ps1
  • source/Public/Set-SqlDscDatabase.ps1
  • source/Public/Set-SqlDscAgentAlert.ps1
  • source/Public/Remove-SqlDscRole.ps1
  • source/Public/New-SqlDscDatabase.ps1
  • source/Public/Remove-SqlDscAgentAlert.ps1

⚙️ CodeRabbit configuration file

source/**/*.ps1: # Localization Guidelines

Requirements

  • Localize all Write-Debug, Write-Verbose, Write-Error, Write-Warning and $PSCmdlet.ThrowTerminatingError() messages
  • Use localized string keys, not hardcoded strings
  • Assume $script:localizedData is available

String Files

  • Commands/functions: source/en-US/{MyModuleName}.strings.psd1
  • Class resources: source/en-US/{ResourceClassName}.strings.psd1

Key Naming Patterns

  • Format: Verb_FunctionName_Action (underscore separators), e.g. Get_Database_ConnectingToDatabase

String Format

ConvertFrom-StringData @'
    KeyName = Message with {0} placeholder. (PREFIX0001)
'@

String IDs

  • Format: (PREFIX####)
  • PREFIX: First letter of each word in class or function name (SqlSetup → SS, Get-SqlDscDatabase → GSDD)
  • Number: Sequential from 0001

Usage

Write-Verbose -Message ($script:localizedData.KeyName -f $value1)

Files:

  • source/Public/Remove-SqlDscDatabase.ps1
  • source/Public/Set-SqlDscDatabase.ps1
  • source/Public/Set-SqlDscAgentAlert.ps1
  • source/Public/Remove-SqlDscRole.ps1
  • source/Public/New-SqlDscDatabase.ps1
  • source/Public/Remove-SqlDscAgentAlert.ps1
source/Public/*.ps1

📄 CodeRabbit inference engine (.github/instructions/dsc-community-style-guidelines.instructions.md)

Place public commands in source/Public/{CommandName}.ps1

Files:

  • source/Public/Remove-SqlDscDatabase.ps1
  • source/Public/Set-SqlDscDatabase.ps1
  • source/Public/Set-SqlDscAgentAlert.ps1
  • source/Public/Remove-SqlDscRole.ps1
  • source/Public/New-SqlDscDatabase.ps1
  • source/Public/Remove-SqlDscAgentAlert.ps1
**/*.md

📄 CodeRabbit inference engine (.github/instructions/dsc-community-style-guidelines-markdown.instructions.md)

**/*.md: Wrap lines at word boundaries when over 80 characters (except tables/code blocks)
Use 2 spaces for indentation in Markdown documents
Use '1.' for all items in ordered lists (1/1/1 numbering style)
Disable MD013 for tables/code blocks exceeding 80 characters via an inline comment
Require empty lines before and after code blocks and headings (except before line 1)
Escape backslashes in file paths only, not inside code blocks
All fenced code blocks must specify a language identifier
Format parameter names as bold
Format values/literals as inline code
Format resource/module/product names as italic
Format commands, file names, and paths as inline code

Files:

  • CHANGELOG.md

⚙️ CodeRabbit configuration file

**/*.md: # Markdown Style Guidelines

  • Wrap lines at word boundaries when over 80 characters (except tables/code blocks)
  • Use 2 spaces for indentation
  • Use '1.' for all items in ordered lists (1/1/1 numbering style)
  • Disable MD013 rule by adding a comment for tables/code blocks exceeding 80 characters
  • Empty lines required before/after code blocks and headings (except before line 1)
  • Escape backslashes in file paths only (not in code blocks)
  • Code blocks must specify language identifiers

Text Formatting

  • Parameters: bold
  • Values/literals: inline code
  • Resource/module/product names: italic
  • Commands/files/paths: inline code

Files:

  • CHANGELOG.md
CHANGELOG.md

📄 CodeRabbit inference engine (.github/instructions/dsc-community-style-guidelines-changelog.instructions.md)

CHANGELOG.md: Always update the Unreleased section in CHANGELOG.md
Use Keep a Changelog format
Describe notable changes briefly, with no more than 2 items per change type
Reference issues using the format issue #<issue_number>
No empty lines between list items in the same section
Skip adding an entry if the same change already exists in the Unreleased section
No duplicate sections or items in the Unreleased section

Always update the Unreleased section of CHANGELOG.md

Files:

  • CHANGELOG.md

⚙️ CodeRabbit configuration file

CHANGELOG.md: # Changelog Guidelines

  • Always update the Unreleased section in CHANGELOG.md
  • Use Keep a Changelog format
  • Describe notable changes briefly, ≤2 items per change type
  • Reference issues using format issue #<issue_number>
  • No empty lines between list items in same section
  • Skip adding entry if same change already exists in Unreleased section
  • No duplicate sections or items in Unreleased section

Files:

  • CHANGELOG.md
🧠 Learnings (4)
📓 Common learnings
Learnt from: CR
PR: dsccommunity/SqlServerDsc#0
File: .github/instructions/dsc-community-style-guidelines-powershell.instructions.md:0-0
Timestamp: 2025-09-16T16:34:27.319Z
Learning: Applies to **/*.{ps1,psm1} : For terminating errors use $PSCmdlet.ThrowTerminatingError() (not in classes); include relevant error category and in catch include exception with localized message
Learnt from: CR
PR: dsccommunity/SqlServerDsc#0
File: .github/instructions/dsc-community-style-guidelines-mof-resources.instructions.md:0-0
Timestamp: 2025-09-12T13:20:57.155Z
Learning: Applies to source/DSCResources/**/*.psm1 : Do not use throw for terminating errors; instead use New-*Exception helper commands (e.g., New-InvalidDataException, New-ArgumentException, New-InvalidOperationException, New-ObjectNotFoundException, New-InvalidResultException, New-NotImplementedException)
📚 Learning: 2025-09-12T13:20:57.155Z
Learnt from: CR
PR: dsccommunity/SqlServerDsc#0
File: .github/instructions/dsc-community-style-guidelines-mof-resources.instructions.md:0-0
Timestamp: 2025-09-12T13:20:57.155Z
Learning: Applies to source/DSCResources/**/*.psm1 : Do not use throw for terminating errors; instead use New-*Exception helper commands (e.g., New-InvalidDataException, New-ArgumentException, New-InvalidOperationException, New-ObjectNotFoundException, New-InvalidResultException, New-NotImplementedException)

Applied to files:

  • source/Public/Remove-SqlDscRole.ps1
  • source/Public/New-SqlDscDatabase.ps1
📚 Learning: 2025-08-18T13:50:53.789Z
Learnt from: johlju
PR: dsccommunity/SqlServerDsc#2132
File: tests/Unit/Public/New-SqlDscLogin.Tests.ps1:0-0
Timestamp: 2025-08-18T13:50:53.789Z
Learning: In SqlServerDsc unit tests, SMO stub objects can be used to verify method calls like Create() on Login objects by adding mock verifications with Should -Invoke, providing more robust testing than just checking for no exceptions.

Applied to files:

  • tests/Unit/Public/Set-SqlDscDatabase.Tests.ps1
📚 Learning: 2025-09-12T13:20:14.850Z
Learnt from: CR
PR: dsccommunity/SqlServerDsc#0
File: .github/instructions/dsc-community-style-guidelines-class-resource.instructions.md:0-0
Timestamp: 2025-09-12T13:20:14.850Z
Learning: Applies to source/[cC]lasses/**/*.ps1 : For terminating errors, use New-*Exception cmdlets: New-InvalidDataException, New-ArgumentException, New-InvalidOperationException, New-ObjectNotFoundException, New-InvalidResultException, New-NotImplementedException

Applied to files:

  • source/Public/New-SqlDscDatabase.ps1
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (2)
  • GitHub Check: dsccommunity.SqlServerDsc (Build Package Module)
  • GitHub Check: PSScriptAnalyzer
🔇 Additional comments (17)
source/Public/Set-SqlDscAgentAlert.ps1 (2)

145-152: Terminating error shape and category are spot on.

Item-not-found path correctly uses ObjectNotFound with a specific error ID and localized message. LGTM.


221-228: Catch block preserves inner exception and uses a specific ErrorId — good.

Structured ErrorRecord with InvalidOperation and target object looks correct.

source/Public/Remove-SqlDscRole.ps1 (1)

146-153: Failure on Drop(): preserves inner exception and uses a specific ErrorId.

Structured error is correct and helpful. LGTM.

CHANGELOG.md (1)

198-215: Changelog entry formatting and scope look correct.

Items are under “Changed”, reference issues properly, and are concise. LGTM.

source/Public/Remove-SqlDscDatabase.ps1 (5)

115-122: System database protection: correct terminating error usage.

InvalidOperation with specific ID and localized message is appropriate. LGTM.


132-139: Missing database path: good use of ObjectNotFound and specific ErrorId.

Error shape and categorization look right. LGTM.


153-160: System database guard (object parameter set) looks correct.

Consistent with the server-object path. LGTM.


219-226: Failure path preserves inner exception and targets the DB object — good.

Terminating error construction is correct and actionable. LGTM.


228-231: State restoration is correct.

$ErrorActionPreference is restored even on error — good hygiene. LGTM.

tests/Unit/Public/Remove-SqlDscAgentAlert.Tests.ps1 (1)

214-221: Test correctly validates terminating error properties.

The test properly captures the error via -PassThru and validates all essential error properties (exception type, message pattern, and FullyQualifiedErrorId). This aligns with the PR objective to use $PSCmdlet.ThrowTerminatingError() for terminating errors.

tests/Unit/Public/New-SqlDscDatabase.Tests.ps1 (2)

136-143: Comprehensive validation of CompatibilityLevel error.

The test properly validates all ErrorRecord properties including the category (InvalidArgument) and target name (Version80), which correctly identifies the invalid parameter value.


146-153: Comprehensive validation of Collation error.

The test properly validates all ErrorRecord properties with the correct error ID (NSD0004) and target name (InvalidCollation).

source/Public/Remove-SqlDscAgentAlert.ps1 (2)

120-148: ErrorActionPreference management follows best practices.

The code properly saves the original $ErrorActionPreference, sets it to 'Stop' before the operation, and restores it in the finally block. This ensures proper cleanup regardless of success or failure.


136-143: Missing exception in ThrowTerminatingError call.

The ErrorRecord::new() constructor is missing the original exception from the catch block. The pattern should include $_.Exception to preserve the exception chain.

Apply this diff to include the original exception:

                 $PSCmdlet.ThrowTerminatingError(
                     [System.Management.Automation.ErrorRecord]::new(
-                        [System.InvalidOperationException]::new($errorMessage, $_.Exception),
+                        ([System.InvalidOperationException]::new($errorMessage, $_.Exception)),
                         'RSAA0005', # cspell: disable-line
                         [System.Management.Automation.ErrorCategory]::InvalidOperation,
                         $alertObjectToRemove
                     )
                 )

Note: The first parameter expects an Exception object. Wrapping in parentheses ensures the InvalidOperationException constructor result is properly passed.

⛔ Skipped due to learnings
Learnt from: CR
PR: dsccommunity/SqlServerDsc#0
File: .github/instructions/dsc-community-style-guidelines-mof-resources.instructions.md:0-0
Timestamp: 2025-09-12T13:20:57.155Z
Learning: Applies to source/DSCResources/**/*.psm1 : Do not use throw for terminating errors; instead use New-*Exception helper commands (e.g., New-InvalidDataException, New-ArgumentException, New-InvalidOperationException, New-ObjectNotFoundException, New-InvalidResultException, New-NotImplementedException)
tests/Unit/Public/Set-SqlDscDatabase.Tests.ps1 (2)

111-111: Error ID validation correctly added to existing tests.

The -ErrorId parameter additions align with the corresponding error codes in the production code (SSDD0001, SSDD0002, SSDD0003), ensuring proper validation of terminating error behavior.

Also applies to: 169-169, 223-223


282-307: New test context provides comprehensive failure coverage.

The test properly validates the terminating error behavior when Alter() fails, including the error message pattern and error ID (SSDD0004). The mock setup correctly simulates an Alter() failure.

source/Public/Set-SqlDscDatabase.ps1 (1)

129-137: Rewrite ErrorRecord calls to use typed exception objects for consistency with codebase patterns.

While PowerShell's ErrorRecord constructor accepts strings and automatically converts them to exception objects, the codebase standard is to use typed exception objects. Update the four ErrorRecord calls in Set-SqlDscDatabase.ps1 to match the pattern used throughout similar commands.

Lines 131-135: Use [System.Management.Automation.ItemNotFoundException]::new($errorMessage) (ObjectNotFound category)

Lines 167-171 and 185-189: Use [System.ArgumentException]::new($errorMessage) (InvalidArgument category)

Lines 250-254: Use [System.InvalidOperationException]::new($errorMessage) (InvalidOperation category)

⛔ Skipped due to learnings
Learnt from: johlju
PR: dsccommunity/SqlServerDsc#2132
File: source/Public/New-SqlDscLogin.ps1:218-225
Timestamp: 2025-08-17T18:25:52.891Z
Learning: PowerShell's System.Management.Automation.ErrorRecord constructor accepts a string as the first parameter and automatically converts it to an exception object internally. No need to manually wrap strings in System.Exception when creating ErrorRecord objects in PowerShell.
Learnt from: CR
PR: dsccommunity/SqlServerDsc#0
File: .github/instructions/dsc-community-style-guidelines-mof-resources.instructions.md:0-0
Timestamp: 2025-09-12T13:20:57.155Z
Learning: Applies to source/DSCResources/**/*.psm1 : Do not use throw for terminating errors; instead use New-*Exception helper commands (e.g., New-InvalidDataException, New-ArgumentException, New-InvalidOperationException, New-ObjectNotFoundException, New-InvalidResultException, New-NotImplementedException)
Learnt from: CR
PR: dsccommunity/SqlServerDsc#0
File: .github/instructions/dsc-community-style-guidelines-class-resource.instructions.md:0-0
Timestamp: 2025-09-12T13:20:14.850Z
Learning: Applies to source/[cC]lasses/**/*.ps1 : For terminating errors, use New-*Exception cmdlets: New-InvalidDataException, New-ArgumentException, New-InvalidOperationException, New-ObjectNotFoundException, New-InvalidResultException, New-NotImplementedException

Copy link

@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: 0

Caution

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

⚠️ Outside diff range comments (1)
source/Public/Remove-SqlDscRole.ps1 (1)

96-153: Add missing string ID suffixes to localized error messages.

The localized strings in source/en-US/SqlServerDsc.strings.psd1 are missing required string ID suffixes. Per coding guidelines, localized strings must follow the format: KeyName = Message (PREFIX####).

Update the following lines:

  • Line 317: Add (RSDR0001) suffix to Role_NotFound
  • Line 335: Add (RSDR0002) suffix to Role_CannotRemoveBuiltIn
  • Line 334: Add (RSDR0003) suffix to Role_RemoveFailed

Example:

Role_NotFound = Server role '{0}' was not found. (RSDR0001)
Role_CannotRemoveBuiltIn = Cannot remove built-in server role '{0}'. (RSDR0002)
Role_RemoveFailed = Failed to remove server role '{0}' from instance '{1}'. (RSDR0003)
🧹 Nitpick comments (1)
source/Public/Set-SqlDscDatabase.ps1 (1)

248-256: Preserve the original exception in catch block.

In catch blocks, preserve the exception chain by passing the original exception as an inner exception. This maintains valuable diagnostic information for troubleshooting.

Apply this diff to preserve the original exception:

                 $PSCmdlet.ThrowTerminatingError(
                     [System.Management.Automation.ErrorRecord]::new(
-                        [System.InvalidOperationException]::new($errorMessage),
+                        [System.InvalidOperationException]::new($errorMessage, $_.Exception),
                         'SSDD0004', # SQL Server Database - Set failed
                         [System.Management.Automation.ErrorCategory]::InvalidOperation,
                         $DatabaseObject
                     )
                 )
📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between fbc4055 and fa615da.

📒 Files selected for processing (2)
  • source/Public/Remove-SqlDscRole.ps1 (3 hunks)
  • source/Public/Set-SqlDscDatabase.ps1 (4 hunks)
🧰 Additional context used
📓 Path-based instructions (7)
source/**/*.ps1

📄 CodeRabbit inference engine (.github/instructions/dsc-community-style-guidelines-localization.instructions.md)

source/**/*.ps1: Localize all Write-Debug, Write-Verbose, Write-Error, Write-Warning, and $PSCmdlet.ThrowTerminatingError() messages
Use localized string keys instead of hardcoded strings in script output/messages
Assume and use $script:localizedData for accessing localized strings
When emitting messages, reference $script:localizedData.KeyName and format with the -f operator (e.g., Write-Verbose -Message ($script:localizedData.KeyName -f $value1))

Files:

  • source/Public/Set-SqlDscDatabase.ps1
  • source/Public/Remove-SqlDscRole.ps1

⚙️ CodeRabbit configuration file

source/**/*.ps1: # Localization Guidelines

Requirements

  • Localize all Write-Debug, Write-Verbose, Write-Error, Write-Warning and $PSCmdlet.ThrowTerminatingError() messages
  • Use localized string keys, not hardcoded strings
  • Assume $script:localizedData is available

String Files

  • Commands/functions: source/en-US/{MyModuleName}.strings.psd1
  • Class resources: source/en-US/{ResourceClassName}.strings.psd1

Key Naming Patterns

  • Format: Verb_FunctionName_Action (underscore separators), e.g. Get_Database_ConnectingToDatabase

String Format

ConvertFrom-StringData @'
    KeyName = Message with {0} placeholder. (PREFIX0001)
'@

String IDs

  • Format: (PREFIX####)
  • PREFIX: First letter of each word in class or function name (SqlSetup → SS, Get-SqlDscDatabase → GSDD)
  • Number: Sequential from 0001

Usage

Write-Verbose -Message ($script:localizedData.KeyName -f $value1)

Files:

  • source/Public/Set-SqlDscDatabase.ps1
  • source/Public/Remove-SqlDscRole.ps1
**/*.{ps1,psm1}

📄 CodeRabbit inference engine (.github/instructions/dsc-community-style-guidelines-powershell.instructions.md)

**/*.{ps1,psm1}: Use descriptive names (3+ characters, no abbreviations)
Function names use PascalCase Verb-Noun with approved verbs
Parameter names use PascalCase
Variable names use camelCase
Keywords are lower-case
Class names use PascalCase
Include scope prefixes for script/global/environment variables: $script:, $global:, $env:
Use one space around operators (e.g., $a = 1 + 2)
Use one space between type and variable (e.g., [String] $name)
Use one space between keyword and parenthesis (e.g., if ($condition))
Place newline before opening brace (except variable assignments)
One newline after opening brace
Two newlines after closing brace (one if followed by another brace or continuation)
Use single quotes unless variable expansion is needed
Arrays on one line use @('one','two'); multi-line arrays have one element per line with proper indentation
Do not use unary comma in return statements to force an array
Single-line comments: '# Comment' capitalized on its own line
Multi-line comments use <# #> with brackets on their own lines and indented text
No commented-out code
Add comment-based help to all functions and scripts
Comment-based help must include SYNOPSIS, DESCRIPTION (40+ chars), PARAMETER, and EXAMPLE sections before function/class
Comment-based help indentation: keywords at 4 spaces, text at 8 spaces
Include examples for all parameter sets and combinations
INPUTS: list each pipeline-accepted type with one-line description; repeat .INPUTS per type
OUTPUTS: list each return type with one-line description; repeat .OUTPUTS per type; must match [OutputType()] and actual returns
.NOTES only if critical (constraints, side effects, security, version compatibility, breaking behavior), ≤2 short sentences
Avoid aliases; use full command names
Avoid Write-Host; prefer Write-Verbose/Write-Information/etc.
Avoid Write-Output; use return instead
Do not use ConvertTo-SecureString -AsPlainText in production code
Do not redefine reserved parameters (Verbose, Debug, etc.)
In...

Files:

  • source/Public/Set-SqlDscDatabase.ps1
  • source/Public/Remove-SqlDscRole.ps1
**/*.{ps1,psm1,psd1}

📄 CodeRabbit inference engine (.github/instructions/dsc-community-style-guidelines-powershell.instructions.md)

**/*.{ps1,psm1,psd1}: Indent with 4 spaces; do not use tabs
No spaces on empty lines
Try to limit lines to 120 characters
Empty hashtable is @{}
Hashtable: each property on its own line with proper indentation
Hashtable property names use PascalCase
End files with exactly one blank line
Use line endings as defined by .gitattributes policy
Allow at most two consecutive newlines
No trailing whitespace on any line
Use UTF-8 encoding without BOM for all files

Files:

  • source/Public/Set-SqlDscDatabase.ps1
  • source/Public/Remove-SqlDscRole.ps1
source/Public/*.ps1

📄 CodeRabbit inference engine (.github/instructions/dsc-community-style-guidelines.instructions.md)

Place public commands in source/Public/{CommandName}.ps1

Files:

  • source/Public/Set-SqlDscDatabase.ps1
  • source/Public/Remove-SqlDscRole.ps1
**/*.ps1

📄 CodeRabbit inference engine (.github/instructions/dsc-community-style-guidelines.instructions.md)

Follow PowerShell style and test guideline instructions strictly

Files:

  • source/Public/Set-SqlDscDatabase.ps1
  • source/Public/Remove-SqlDscRole.ps1
**

⚙️ CodeRabbit configuration file

**: # DSC Community Guidelines

Terminology

  • Command: Public command
  • Function: Private function
  • Resource: DSC class-based resource

Build & Test Workflow Requirements

  • Run PowerShell script files from repository root
  • Setup build and test environment (once per pwsh session): ./build.ps1 -Tasks noop
  • Build project before running tests: ./build.ps1 -Tasks build
  • Always run tests in new pwsh session: Invoke-Pester -Path @({test paths}) -Output Detailed

File Organization

  • Public commands: source/Public/{CommandName}.ps1
  • Private functions: source/Private/{FunctionName}.ps1
  • Unit tests: tests/Unit/{Classes|Public|Private}/{Name}.Tests.ps1
  • Integration tests: tests/Integration/Commands/{CommandName}.Integration.Tests.ps1

Requirements

  • Follow instructions over existing code patterns
  • Follow PowerShell style and test guideline instructions strictly
  • Always update CHANGELOG.md Unreleased section
  • Localize all strings using string keys; remove any orphaned string keys
  • Check DscResource.Common before creating private functions
  • Separate reusable logic into private functions
  • DSC resources should always be created as class-based resources
  • Add unit tests for all commands/functions/resources
  • Add integration tests for all public commands and resources

Files:

  • source/Public/Set-SqlDscDatabase.ps1
  • source/Public/Remove-SqlDscRole.ps1
{**/*.ps1,**/*.psm1,**/*.psd1}

⚙️ CodeRabbit configuration file

{**/*.ps1,**/*.psm1,**/*.psd1}: # PowerShell Guidelines

Naming

  • Use descriptive names (3+ characters, no abbreviations)
  • Functions: PascalCase with Verb-Noun format using approved verbs
  • Parameters: PascalCase
  • Variables: camelCase
  • Keywords: lower-case
  • Classes: PascalCase
  • Include scope for script/global/environment variables: $script:, $global:, $env:

File naming

  • Class files: ###.ClassName.ps1 format (e.g. 001.SqlReason.ps1, 004.StartupParameters.ps1)

Formatting

Indentation & Spacing

  • Use 4 spaces (no tabs)
  • One space around operators: $a = 1 + 2
  • One space between type and variable: [String] $name
  • One space between keyword and parenthesis: if ($condition)
  • No spaces on empty lines
  • Try to limit lines to 120 characters

Braces

  • Newline before opening brace (except variable assignments)
  • One newline after opening brace
  • Two newlines after closing brace (one if followed by another brace or continuation)

Quotes

  • Use single quotes unless variable expansion is needed: 'text' vs "text $variable"

Arrays

  • Single line: @('one', 'two', 'three')
  • Multi-line: each element on separate line with proper indentation
  • Do not use the unary comma operator (,) in return statements to force
    an array

Hashtables

  • Empty: @{}
  • Each property on separate line with proper indentation
  • Properties: Use PascalCase

Comments

  • Single line: # Comment (capitalized, on own line)
  • Multi-line: <# Comment #> format (opening and closing brackets on own line), and indent text
  • No commented-out code

Comment-based help

  • Always add comment-based help to all functions and scripts
  • Comment-based help: SYNOPSIS, DESCRIPTION (40+ chars), PARAMETER, EXAMPLE sections before function/class
  • Comment-based help indentation: keywords 4 spaces, text 8 spaces
  • Include examples for all parameter sets and combinations
  • INPUTS: List each pipeline‑accepted type (one per line) with a 1‑line description...

Files:

  • source/Public/Set-SqlDscDatabase.ps1
  • source/Public/Remove-SqlDscRole.ps1
🧠 Learnings (3)
📓 Common learnings
Learnt from: CR
PR: dsccommunity/SqlServerDsc#0
File: .github/instructions/dsc-community-style-guidelines-powershell.instructions.md:0-0
Timestamp: 2025-09-16T16:34:27.319Z
Learning: Applies to **/*.{ps1,psm1} : For terminating errors use $PSCmdlet.ThrowTerminatingError() (not in classes); include relevant error category and in catch include exception with localized message
Learnt from: CR
PR: dsccommunity/SqlServerDsc#0
File: .github/instructions/dsc-community-style-guidelines-powershell.instructions.md:0-0
Timestamp: 2025-09-16T16:34:27.319Z
Learning: Applies to **/*.{ps1,psm1} : Use Write-Error for non-terminating errors with -Message (localized), -Category, -ErrorId (unique, matches localized ID), -TargetObject; in catch include -Exception; always return after Write-Error
Learnt from: CR
PR: dsccommunity/SqlServerDsc#0
File: .github/instructions/dsc-community-style-guidelines-mof-resources.instructions.md:0-0
Timestamp: 2025-09-12T13:20:57.155Z
Learning: Applies to source/DSCResources/**/*.psm1 : Do not use throw for terminating errors; instead use New-*Exception helper commands (e.g., New-InvalidDataException, New-ArgumentException, New-InvalidOperationException, New-ObjectNotFoundException, New-InvalidResultException, New-NotImplementedException)
Learnt from: CR
PR: dsccommunity/SqlServerDsc#0
File: .github/instructions/dsc-community-style-guidelines-class-resource.instructions.md:0-0
Timestamp: 2025-09-12T13:20:14.850Z
Learning: Applies to source/[cC]lasses/**/*.ps1 : Do not use throw for terminating errors in classes
Learnt from: CR
PR: dsccommunity/SqlServerDsc#0
File: .github/instructions/dsc-community-style-guidelines-class-resource.instructions.md:0-0
Timestamp: 2025-09-12T13:20:14.850Z
Learning: Applies to source/[cC]lasses/**/*.ps1 : For terminating errors, use New-*Exception cmdlets: New-InvalidDataException, New-ArgumentException, New-InvalidOperationException, New-ObjectNotFoundException, New-InvalidResultException, New-NotImplementedException
📚 Learning: 2025-09-12T13:20:57.155Z
Learnt from: CR
PR: dsccommunity/SqlServerDsc#0
File: .github/instructions/dsc-community-style-guidelines-mof-resources.instructions.md:0-0
Timestamp: 2025-09-12T13:20:57.155Z
Learning: Applies to source/DSCResources/**/*.psm1 : Do not use throw for terminating errors; instead use New-*Exception helper commands (e.g., New-InvalidDataException, New-ArgumentException, New-InvalidOperationException, New-ObjectNotFoundException, New-InvalidResultException, New-NotImplementedException)

Applied to files:

  • source/Public/Set-SqlDscDatabase.ps1
  • source/Public/Remove-SqlDscRole.ps1
📚 Learning: 2025-08-17T18:25:52.891Z
Learnt from: johlju
PR: dsccommunity/SqlServerDsc#2132
File: source/Public/New-SqlDscLogin.ps1:218-225
Timestamp: 2025-08-17T18:25:52.891Z
Learning: PowerShell's System.Management.Automation.ErrorRecord constructor accepts a string as the first parameter and automatically converts it to an exception object internally. No need to manually wrap strings in System.Exception when creating ErrorRecord objects in PowerShell.

Applied to files:

  • source/Public/Set-SqlDscDatabase.ps1
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (3)
  • GitHub Check: dsccommunity.SqlServerDsc (Build Package Module)
  • GitHub Check: PSScriptAnalyzer
  • GitHub Check: PSScriptAnalyzer
🔇 Additional comments (7)
source/Public/Set-SqlDscDatabase.ps1 (4)

129-137: Proper terminating error implementation for database not found.

The ErrorRecord construction is correct and follows DSC Community guidelines. The use of InvalidOperationException with the localized error message, error ID SSDD0001, and appropriate category/target is properly implemented.

Note: Past review comments suggesting this was incorrect have been superseded by the learning that PowerShell's ErrorRecord constructor properly handles exception objects.


165-173: Proper terminating error implementation for invalid compatibility level.

The ErrorRecord construction correctly uses ArgumentException for an invalid parameter value, with appropriate error ID SSDD0002 and category InvalidArgument. The target object properly identifies the problematic compatibility level value.


184-191: Proper terminating error implementation for invalid collation.

The ErrorRecord construction follows the correct pattern with ArgumentException, error ID SSDD0003, and appropriate category/target for an invalid collation parameter.


128-128: Let me verify the complete localization string definitions to ensure they include error IDs:

Based on my verification of the codebase, all four localized string keys referenced in source/Public/Set-SqlDscDatabase.ps1 exist in source/en-US/SqlServerDsc.strings.psd1:

  • Database_NotFound (line 353)
  • Database_InvalidCompatibilityLevel (line 361)
  • Database_InvalidCollation (line 362)
  • Database_SetFailed (line 372)

The localization keys are properly defined and accessible via the $script:localizedData variable.

source/Public/Remove-SqlDscRole.ps1 (3)

96-104: LGTM! Proper ObjectNotFound error handling.

The implementation correctly uses $PSCmdlet.ThrowTerminatingError() with:

  • ItemNotFoundException for role not found scenario
  • ObjectNotFound error category
  • Unique error ID RSDR0001 following the naming pattern
  • Appropriate target object ($Name)
  • Localized error message

117-125: LGTM! Proper InvalidOperation error handling.

The implementation correctly uses $PSCmdlet.ThrowTerminatingError() with:

  • InvalidOperationException for built-in role removal attempt
  • InvalidOperation error category
  • Unique error ID RSDR0002
  • Appropriate target object ($RoleObject)
  • Localized error message

145-153: LGTM! Proper error handling with exception chaining.

The implementation correctly uses $PSCmdlet.ThrowTerminatingError() in the catch block with:

  • InvalidOperationException for operation failure
  • Inner exception ($_.Exception) properly preserved for error context
  • InvalidOperation error category
  • Unique error ID RSDR0003
  • Appropriate target object ($RoleObject)
  • Localized error message

@johlju johlju changed the title Fix/issue #2200 Fix style for terminating error in commands Oct 20, 2025
Copy link

@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: 1

📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between fa615da and 8d65470.

📒 Files selected for processing (2)
  • source/Public/Set-SqlDscDatabase.ps1 (4 hunks)
  • source/en-US/SqlServerDsc.strings.psd1 (2 hunks)
🧰 Additional context used
📓 Path-based instructions (9)
source/en-US/*.strings.psd1

📄 CodeRabbit inference engine (.github/instructions/dsc-community-style-guidelines-localization.instructions.md)

source/en-US/*.strings.psd1: Store command/function localization in source/en-US/{MyModuleName}.strings.psd1
Store class localization in source/en-US/{ResourceClassName}.strings.psd1
Name localization keys as Verb_FunctionName_Action using underscores (e.g., Get_Database_ConnectingToDatabase)
Define strings using ConvertFrom-StringData with entries like KeyName = Message with {0} placeholder. (PREFIX0001)
Include string IDs in the form (PREFIX####), where PREFIX is initials from the class/function name and numbers are sequential from 0001

Files:

  • source/en-US/SqlServerDsc.strings.psd1
**/*.{ps1,psm1,psd1}

📄 CodeRabbit inference engine (.github/instructions/dsc-community-style-guidelines-powershell.instructions.md)

**/*.{ps1,psm1,psd1}: Indent with 4 spaces; do not use tabs
No spaces on empty lines
Try to limit lines to 120 characters
Empty hashtable is @{}
Hashtable: each property on its own line with proper indentation
Hashtable property names use PascalCase
End files with exactly one blank line
Use line endings as defined by .gitattributes policy
Allow at most two consecutive newlines
No trailing whitespace on any line
Use UTF-8 encoding without BOM for all files

Files:

  • source/en-US/SqlServerDsc.strings.psd1
  • source/Public/Set-SqlDscDatabase.ps1
**/*.psd1

📄 CodeRabbit inference engine (.github/instructions/dsc-community-style-guidelines-powershell.instructions.md)

In module manifests, do not use NestedModules for shared commands without specifying RootModule

Files:

  • source/en-US/SqlServerDsc.strings.psd1
**

⚙️ CodeRabbit configuration file

**: # DSC Community Guidelines

Terminology

  • Command: Public command
  • Function: Private function
  • Resource: DSC class-based resource

Build & Test Workflow Requirements

  • Run PowerShell script files from repository root
  • Setup build and test environment (once per pwsh session): ./build.ps1 -Tasks noop
  • Build project before running tests: ./build.ps1 -Tasks build
  • Always run tests in new pwsh session: Invoke-Pester -Path @({test paths}) -Output Detailed

File Organization

  • Public commands: source/Public/{CommandName}.ps1
  • Private functions: source/Private/{FunctionName}.ps1
  • Unit tests: tests/Unit/{Classes|Public|Private}/{Name}.Tests.ps1
  • Integration tests: tests/Integration/Commands/{CommandName}.Integration.Tests.ps1

Requirements

  • Follow instructions over existing code patterns
  • Follow PowerShell style and test guideline instructions strictly
  • Always update CHANGELOG.md Unreleased section
  • Localize all strings using string keys; remove any orphaned string keys
  • Check DscResource.Common before creating private functions
  • Separate reusable logic into private functions
  • DSC resources should always be created as class-based resources
  • Add unit tests for all commands/functions/resources
  • Add integration tests for all public commands and resources

Files:

  • source/en-US/SqlServerDsc.strings.psd1
  • source/Public/Set-SqlDscDatabase.ps1
{**/*.ps1,**/*.psm1,**/*.psd1}

⚙️ CodeRabbit configuration file

{**/*.ps1,**/*.psm1,**/*.psd1}: # PowerShell Guidelines

Naming

  • Use descriptive names (3+ characters, no abbreviations)
  • Functions: PascalCase with Verb-Noun format using approved verbs
  • Parameters: PascalCase
  • Variables: camelCase
  • Keywords: lower-case
  • Classes: PascalCase
  • Include scope for script/global/environment variables: $script:, $global:, $env:

File naming

  • Class files: ###.ClassName.ps1 format (e.g. 001.SqlReason.ps1, 004.StartupParameters.ps1)

Formatting

Indentation & Spacing

  • Use 4 spaces (no tabs)
  • One space around operators: $a = 1 + 2
  • One space between type and variable: [String] $name
  • One space between keyword and parenthesis: if ($condition)
  • No spaces on empty lines
  • Try to limit lines to 120 characters

Braces

  • Newline before opening brace (except variable assignments)
  • One newline after opening brace
  • Two newlines after closing brace (one if followed by another brace or continuation)

Quotes

  • Use single quotes unless variable expansion is needed: 'text' vs "text $variable"

Arrays

  • Single line: @('one', 'two', 'three')
  • Multi-line: each element on separate line with proper indentation
  • Do not use the unary comma operator (,) in return statements to force
    an array

Hashtables

  • Empty: @{}
  • Each property on separate line with proper indentation
  • Properties: Use PascalCase

Comments

  • Single line: # Comment (capitalized, on own line)
  • Multi-line: <# Comment #> format (opening and closing brackets on own line), and indent text
  • No commented-out code

Comment-based help

  • Always add comment-based help to all functions and scripts
  • Comment-based help: SYNOPSIS, DESCRIPTION (40+ chars), PARAMETER, EXAMPLE sections before function/class
  • Comment-based help indentation: keywords 4 spaces, text 8 spaces
  • Include examples for all parameter sets and combinations
  • INPUTS: List each pipeline‑accepted type (one per line) with a 1‑line description...

Files:

  • source/en-US/SqlServerDsc.strings.psd1
  • source/Public/Set-SqlDscDatabase.ps1
source/**/*.ps1

📄 CodeRabbit inference engine (.github/instructions/dsc-community-style-guidelines-localization.instructions.md)

source/**/*.ps1: Localize all Write-Debug, Write-Verbose, Write-Error, Write-Warning, and $PSCmdlet.ThrowTerminatingError() messages
Use localized string keys instead of hardcoded strings in script output/messages
Assume and use $script:localizedData for accessing localized strings
When emitting messages, reference $script:localizedData.KeyName and format with the -f operator (e.g., Write-Verbose -Message ($script:localizedData.KeyName -f $value1))

Files:

  • source/Public/Set-SqlDscDatabase.ps1

⚙️ CodeRabbit configuration file

source/**/*.ps1: # Localization Guidelines

Requirements

  • Localize all Write-Debug, Write-Verbose, Write-Error, Write-Warning and $PSCmdlet.ThrowTerminatingError() messages
  • Use localized string keys, not hardcoded strings
  • Assume $script:localizedData is available

String Files

  • Commands/functions: source/en-US/{MyModuleName}.strings.psd1
  • Class resources: source/en-US/{ResourceClassName}.strings.psd1

Key Naming Patterns

  • Format: Verb_FunctionName_Action (underscore separators), e.g. Get_Database_ConnectingToDatabase

String Format

ConvertFrom-StringData @'
    KeyName = Message with {0} placeholder. (PREFIX0001)
'@

String IDs

  • Format: (PREFIX####)
  • PREFIX: First letter of each word in class or function name (SqlSetup → SS, Get-SqlDscDatabase → GSDD)
  • Number: Sequential from 0001

Usage

Write-Verbose -Message ($script:localizedData.KeyName -f $value1)

Files:

  • source/Public/Set-SqlDscDatabase.ps1
**/*.{ps1,psm1}

📄 CodeRabbit inference engine (.github/instructions/dsc-community-style-guidelines-powershell.instructions.md)

**/*.{ps1,psm1}: Use descriptive names (3+ characters, no abbreviations)
Function names use PascalCase Verb-Noun with approved verbs
Parameter names use PascalCase
Variable names use camelCase
Keywords are lower-case
Class names use PascalCase
Include scope prefixes for script/global/environment variables: $script:, $global:, $env:
Use one space around operators (e.g., $a = 1 + 2)
Use one space between type and variable (e.g., [String] $name)
Use one space between keyword and parenthesis (e.g., if ($condition))
Place newline before opening brace (except variable assignments)
One newline after opening brace
Two newlines after closing brace (one if followed by another brace or continuation)
Use single quotes unless variable expansion is needed
Arrays on one line use @('one','two'); multi-line arrays have one element per line with proper indentation
Do not use unary comma in return statements to force an array
Single-line comments: '# Comment' capitalized on its own line
Multi-line comments use <# #> with brackets on their own lines and indented text
No commented-out code
Add comment-based help to all functions and scripts
Comment-based help must include SYNOPSIS, DESCRIPTION (40+ chars), PARAMETER, and EXAMPLE sections before function/class
Comment-based help indentation: keywords at 4 spaces, text at 8 spaces
Include examples for all parameter sets and combinations
INPUTS: list each pipeline-accepted type with one-line description; repeat .INPUTS per type
OUTPUTS: list each return type with one-line description; repeat .OUTPUTS per type; must match [OutputType()] and actual returns
.NOTES only if critical (constraints, side effects, security, version compatibility, breaking behavior), ≤2 short sentences
Avoid aliases; use full command names
Avoid Write-Host; prefer Write-Verbose/Write-Information/etc.
Avoid Write-Output; use return instead
Do not use ConvertTo-SecureString -AsPlainText in production code
Do not redefine reserved parameters (Verbose, Debug, etc.)
In...

Files:

  • source/Public/Set-SqlDscDatabase.ps1
source/Public/*.ps1

📄 CodeRabbit inference engine (.github/instructions/dsc-community-style-guidelines.instructions.md)

Place public commands in source/Public/{CommandName}.ps1

Files:

  • source/Public/Set-SqlDscDatabase.ps1
**/*.ps1

📄 CodeRabbit inference engine (.github/instructions/dsc-community-style-guidelines.instructions.md)

Follow PowerShell style and test guideline instructions strictly

Files:

  • source/Public/Set-SqlDscDatabase.ps1
🧠 Learnings (3)
📓 Common learnings
Learnt from: CR
PR: dsccommunity/SqlServerDsc#0
File: .github/instructions/dsc-community-style-guidelines-powershell.instructions.md:0-0
Timestamp: 2025-09-16T16:34:27.319Z
Learning: Applies to **/*.{ps1,psm1} : For terminating errors use $PSCmdlet.ThrowTerminatingError() (not in classes); include relevant error category and in catch include exception with localized message
Learnt from: CR
PR: dsccommunity/SqlServerDsc#0
File: .github/instructions/dsc-community-style-guidelines-powershell.instructions.md:0-0
Timestamp: 2025-09-16T16:34:27.319Z
Learning: Applies to **/*.{ps1,psm1} : Use Write-Error for non-terminating errors with -Message (localized), -Category, -ErrorId (unique, matches localized ID), -TargetObject; in catch include -Exception; always return after Write-Error
Learnt from: CR
PR: dsccommunity/SqlServerDsc#0
File: .github/instructions/dsc-community-style-guidelines-powershell.instructions.md:0-0
Timestamp: 2025-09-16T16:34:27.319Z
Learning: Applies to **/*.{ps1,psm1} : Set $ErrorActionPreference='Stop' immediately before commands using -ErrorAction 'Stop' and restore after; do not use try-catch-finally for this
Learnt from: johlju
PR: dsccommunity/SqlServerDsc#2189
File: source/Public/Set-SqlDscDatabaseDefault.ps1:124-130
Timestamp: 2025-09-06T19:12:11.414Z
Learning: In PowerShell functions, when calling commands with -ErrorAction 'Stop', if the command fails it throws a terminating error that stops execution of the calling function entirely, so $ErrorActionPreference restoration only needs to happen after successful completion, not in a finally block.
Learnt from: CR
PR: dsccommunity/SqlServerDsc#0
File: .github/instructions/dsc-community-style-guidelines-mof-resources.instructions.md:0-0
Timestamp: 2025-09-12T13:20:57.155Z
Learning: Applies to source/DSCResources/**/*.psm1 : Do not use throw for terminating errors; instead use New-*Exception helper commands (e.g., New-InvalidDataException, New-ArgumentException, New-InvalidOperationException, New-ObjectNotFoundException, New-InvalidResultException, New-NotImplementedException)
Learnt from: CR
PR: dsccommunity/SqlServerDsc#0
File: .github/instructions/dsc-community-style-guidelines-integration-tests.instructions.md:0-0
Timestamp: 2025-10-12T11:23:30.123Z
Learning: Applies to tests/[iI]ntegration/**/*.[iI]ntegration.[tT]ests.ps1 : Use -ErrorAction 'Stop' on commands so failures surface immediately
Learnt from: CR
PR: dsccommunity/SqlServerDsc#0
File: .github/instructions/dsc-community-style-guidelines-class-resource.instructions.md:0-0
Timestamp: 2025-09-12T13:20:14.850Z
Learning: Applies to source/[cC]lasses/**/*.ps1 : Do not use throw for terminating errors in classes
📚 Learning: 2025-09-12T13:20:57.155Z
Learnt from: CR
PR: dsccommunity/SqlServerDsc#0
File: .github/instructions/dsc-community-style-guidelines-mof-resources.instructions.md:0-0
Timestamp: 2025-09-12T13:20:57.155Z
Learning: Applies to source/DSCResources/**/*.psm1 : Do not use throw for terminating errors; instead use New-*Exception helper commands (e.g., New-InvalidDataException, New-ArgumentException, New-InvalidOperationException, New-ObjectNotFoundException, New-InvalidResultException, New-NotImplementedException)

Applied to files:

  • source/Public/Set-SqlDscDatabase.ps1
📚 Learning: 2025-08-17T18:25:52.891Z
Learnt from: johlju
PR: dsccommunity/SqlServerDsc#2132
File: source/Public/New-SqlDscLogin.ps1:218-225
Timestamp: 2025-08-17T18:25:52.891Z
Learning: PowerShell's System.Management.Automation.ErrorRecord constructor accepts a string as the first parameter and automatically converts it to an exception object internally. No need to manually wrap strings in System.Exception when creating ErrorRecord objects in PowerShell.

Applied to files:

  • source/Public/Set-SqlDscDatabase.ps1
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (3)
  • GitHub Check: dsccommunity.SqlServerDsc (Build Package Module)
  • GitHub Check: PSScriptAnalyzer
  • GitHub Check: PSScriptAnalyzer
🔇 Additional comments (5)
source/Public/Set-SqlDscDatabase.ps1 (4)

129-137: LGTM! ErrorRecord construction is correct.

The ErrorRecord is now properly constructed with an InvalidOperationException wrapping the localized error message, addressing the previous review feedback. The error ID, category, and target object are all appropriate for this "database not found" scenario.


165-173: LGTM! ErrorRecord construction is correct.

The ErrorRecord properly uses ArgumentException for this validation scenario, with appropriate error category (InvalidArgument) and target object. This addresses the previous review feedback.


183-191: LGTM! ErrorRecord construction is correct.

The ErrorRecord correctly uses ArgumentException with appropriate error category and target object for this collation validation failure, addressing the previous review feedback.


247-256: LGTM! ErrorRecord construction correctly preserves exception chain.

The ErrorRecord properly includes the original exception ($_.Exception) as the inner exception, which preserves the full exception chain for debugging. This correctly addresses the previous review feedback and follows best practices for error handling in catch blocks.

source/en-US/SqlServerDsc.strings.psd1 (1)

334-335: LGTM!

The error codes are correctly formatted and use the appropriate RSDR prefix for Remove-SqlDscRole operations. The additions align with the PR's objective to provide proper ErrorRecord details for terminating errors.

Copy link

@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: 0

Caution

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

⚠️ Outside diff range comments (1)
source/Public/Get-SqlDscRole.ps1 (1)

76-88: Return immediately after Write-Error to avoid further processing

Per guidelines, always return after Write-Error. Add an explicit return of a typed empty array right after Write-Error.

As per coding guidelines

-                Write-Error @writeErrorParameters
+                Write-Error @writeErrorParameters
+                return [Microsoft.SqlServer.Management.Smo.ServerRole[]] @()
🧹 Nitpick comments (1)
source/Public/Remove-SqlDscRole.ps1 (1)

128-133: Align with standard ShouldProcess + Force/Confirm pattern

Follow the documented pattern to keep behavior consistent and still bypass prompts with -Force.

As per coding guidelines

-        if ($Force.IsPresent -or $PSCmdlet.ShouldProcess($verboseDescriptionMessage, $verboseWarningMessage, $captionMessage))
+        # If Force is used without explicit -Confirm, suppress confirmation prompts.
+        if ($Force.IsPresent -and -not $Confirm)
+        {
+            $ConfirmPreference = 'None'
+        }
+
+        # Use standard variable names for ShouldProcess messages.
+        $descriptionMessage = $verboseDescriptionMessage
+        $confirmationMessage = $verboseWarningMessage
+
+        if ($PSCmdlet.ShouldProcess($descriptionMessage, $confirmationMessage, $captionMessage))
📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 8d65470 and 0756914.

📒 Files selected for processing (4)
  • source/Public/Get-SqlDscRole.ps1 (1 hunks)
  • source/Public/Remove-SqlDscRole.ps1 (3 hunks)
  • source/en-US/SqlServerDsc.strings.psd1 (2 hunks)
  • tests/Unit/Public/Get-SqlDscRole.Tests.ps1 (1 hunks)
🚧 Files skipped from review as they are similar to previous changes (1)
  • source/en-US/SqlServerDsc.strings.psd1
🧰 Additional context used
📓 Path-based instructions (11)
**/*.[Tt]ests.ps1

📄 CodeRabbit inference engine (.github/instructions/dsc-community-style-guidelines-pester.instructions.md)

**/*.[Tt]ests.ps1: All public commands, private functions, and classes must have unit tests
All public commands and class-based resources must have integration tests
Use Pester v5 syntax only
Test code only inside Describe blocks
Assertions only in It blocks
Never test verbose messages, debug messages, or parameter binding behavior
Pass all mandatory parameters to avoid prompts
Inside It blocks, assign unused return objects to $null (unless part of a pipeline)
Call the tested entity from within the It blocks
Keep results and assertions in the same It block
Avoid try/catch/finally for cleanup; use AfterAll or AfterEach
Avoid unnecessary remove/recreate cycles
One Describe block per file matching the tested entity name
Context descriptions start with 'When'
It descriptions start with 'Should' and must not contain 'when'
Mock variables must be prefixed with 'mock'
Public commands: never use InModuleScope (except for retrieving localized strings)
Private functions and class resources: always use InModuleScope
Each class method gets a separate Context block
Each scenario gets a separate Context block
Use nested Context blocks for complex scenarios
Perform mocking in BeforeAll (use BeforeEach only when required)
Place setup/teardown (BeforeAll/BeforeEach/AfterAll/AfterEach) close to usage
Use PascalCase for Pester keywords: Describe, Context, It, Should, BeforeAll, BeforeEach, AfterAll, AfterEach
Use -BeTrue/-BeFalse; never use -Be $true/-Be $false
Never use Assert-MockCalled; use Should -Invoke instead
Do not use Should -Not -Throw; invoke commands directly
Never add an empty -MockWith block
Omit -MockWith when returning $null
Set $PSDefaultParameterValues for Mock:ModuleName, Should:ModuleName, and InModuleScope:ModuleName
Omit the -ModuleName parameter on Pester commands
Never use Mock inside an InModuleScope block
Define variables for -ForEach in a separate BeforeDiscovery near usage
Use -ForEach only on Context and It blocks
Keep variable scope close to the usage c...

Files:

  • tests/Unit/Public/Get-SqlDscRole.Tests.ps1

⚙️ CodeRabbit configuration file

**/*.[Tt]ests.ps1: # Tests Guidelines

Core Requirements

  • All public commands, private functions and classes must have unit tests
  • All public commands and class-based resources must have integration tests
  • Use Pester v5 syntax only
  • Test code only inside Describe blocks
  • Assertions only in It blocks
  • Never test verbose messages, debug messages or parameter binding behavior
  • Pass all mandatory parameters to avoid prompts

Requirements

  • Inside It blocks, assign unused return objects to $null (unless part of pipeline)
  • Tested entity must be called from within the It blocks
  • Keep results and assertions in same It block
  • Avoid try-catch-finally for cleanup, use AfterAll or AfterEach
  • Avoid unnecessary remove/recreate cycles

Naming

  • One Describe block per file matching the tested entity name
  • Context descriptions start with 'When'
  • It descriptions start with 'Should', must not contain 'when'
  • Mock variables prefix: 'mock'

Structure & Scope

  • Public commands: Never use InModuleScope (unless retrieving localized strings)
  • Private functions/class resources: Always use InModuleScope
  • Each class method = separate Context block
  • Each scenario = separate Context block
  • Use nested Context blocks for complex scenarios
  • Mocking in BeforeAll (BeforeEach only when required)
  • Setup/teardown in BeforeAll,BeforeEach/AfterAll,AfterEach close to usage

Syntax Rules

  • PascalCase: Describe, Context, It, Should, BeforeAll, BeforeEach, AfterAll, AfterEach
  • Use -BeTrue/-BeFalse never -Be $true/-Be $false
  • Never use Assert-MockCalled, use Should -Invoke instead
  • No Should -Not -Throw - invoke commands directly
  • Never add an empty -MockWith block
  • Omit -MockWith when returning $null
  • Set $PSDefaultParameterValues for Mock:ModuleName, Should:ModuleName, InModuleScope:ModuleName
  • Omit -ModuleName parameter on Pester commands
  • Never use Mock inside `InModuleSc...

Files:

  • tests/Unit/Public/Get-SqlDscRole.Tests.ps1
tests/Unit/Public/*.Tests.ps1

📄 CodeRabbit inference engine (.github/instructions/dsc-community-style-guidelines-pester.instructions.md)

Public command unit tests must reside in tests/Unit/Public/{Name}.Tests.ps1

Place unit tests for public commands in tests/Unit/Public/{Name}.Tests.ps1

Files:

  • tests/Unit/Public/Get-SqlDscRole.Tests.ps1
**/*.{ps1,psm1}

📄 CodeRabbit inference engine (.github/instructions/dsc-community-style-guidelines-powershell.instructions.md)

**/*.{ps1,psm1}: Use descriptive names (3+ characters, no abbreviations)
Function names use PascalCase Verb-Noun with approved verbs
Parameter names use PascalCase
Variable names use camelCase
Keywords are lower-case
Class names use PascalCase
Include scope prefixes for script/global/environment variables: $script:, $global:, $env:
Use one space around operators (e.g., $a = 1 + 2)
Use one space between type and variable (e.g., [String] $name)
Use one space between keyword and parenthesis (e.g., if ($condition))
Place newline before opening brace (except variable assignments)
One newline after opening brace
Two newlines after closing brace (one if followed by another brace or continuation)
Use single quotes unless variable expansion is needed
Arrays on one line use @('one','two'); multi-line arrays have one element per line with proper indentation
Do not use unary comma in return statements to force an array
Single-line comments: '# Comment' capitalized on its own line
Multi-line comments use <# #> with brackets on their own lines and indented text
No commented-out code
Add comment-based help to all functions and scripts
Comment-based help must include SYNOPSIS, DESCRIPTION (40+ chars), PARAMETER, and EXAMPLE sections before function/class
Comment-based help indentation: keywords at 4 spaces, text at 8 spaces
Include examples for all parameter sets and combinations
INPUTS: list each pipeline-accepted type with one-line description; repeat .INPUTS per type
OUTPUTS: list each return type with one-line description; repeat .OUTPUTS per type; must match [OutputType()] and actual returns
.NOTES only if critical (constraints, side effects, security, version compatibility, breaking behavior), ≤2 short sentences
Avoid aliases; use full command names
Avoid Write-Host; prefer Write-Verbose/Write-Information/etc.
Avoid Write-Output; use return instead
Do not use ConvertTo-SecureString -AsPlainText in production code
Do not redefine reserved parameters (Verbose, Debug, etc.)
In...

Files:

  • tests/Unit/Public/Get-SqlDscRole.Tests.ps1
  • source/Public/Remove-SqlDscRole.ps1
  • source/Public/Get-SqlDscRole.ps1
**/*.{ps1,psm1,psd1}

📄 CodeRabbit inference engine (.github/instructions/dsc-community-style-guidelines-powershell.instructions.md)

**/*.{ps1,psm1,psd1}: Indent with 4 spaces; do not use tabs
No spaces on empty lines
Try to limit lines to 120 characters
Empty hashtable is @{}
Hashtable: each property on its own line with proper indentation
Hashtable property names use PascalCase
End files with exactly one blank line
Use line endings as defined by .gitattributes policy
Allow at most two consecutive newlines
No trailing whitespace on any line
Use UTF-8 encoding without BOM for all files

Files:

  • tests/Unit/Public/Get-SqlDscRole.Tests.ps1
  • source/Public/Remove-SqlDscRole.ps1
  • source/Public/Get-SqlDscRole.ps1
tests/[Uu]nit/**/*.[Tt]ests.ps1

📄 CodeRabbit inference engine (.github/instructions/dsc-community-style-guidelines-unit-tests.instructions.md)

tests/[Uu]nit/**/*.[Tt]ests.ps1: In unit tests, access localized strings using InModuleScope -ScriptBlock { $script:localizedData.Key }
When mocking files in tests, use the $TestDrive variable for file system operations
All public commands must include parameter set validation tests
Include the exact Pester setup block before Describe: SuppressMessage attribute with param (); BeforeDiscovery to ensure DscResource.Test is available (fallback to build.ps1 -Tasks 'noop') and Import-Module; BeforeAll to set $script:moduleName, import the module, and set PSDefaultParameterValues for InModuleScope/Mock/Should; AfterAll to remove those defaults and unload the tested module
Use the provided Parameter Set Validation test template to assert command ParameterSetName and full parameter list string; for multiple parameter sets, supply multiple hashtables via -ForEach
Use the Parameter Properties template to assert a parameter is mandatory via $parameterInfo = (Get-Command -Name 'CommandName').Parameters['ParameterName']; $parameterInfo.Attributes.Mandatory | Should -BeTrue

Files:

  • tests/Unit/Public/Get-SqlDscRole.Tests.ps1

⚙️ CodeRabbit configuration file

tests/[Uu]nit/**/*.[Tt]ests.ps1: # Unit Tests Guidelines

  • Test with localized strings: Use InModuleScope -ScriptBlock { $script:localizedData.Key }
  • Mock files: Use $TestDrive variable (path to the test drive)
  • All public commands require parameter set validation tests
  • After modifying classes, always run tests in new session (for changes to take effect)

Test Setup Requirements

Use this exact setup block before Describe:

[System.Diagnostics.CodeAnalysis.SuppressMessageAttribute('PSUseDeclaredVarsMoreThanAssignments', '', Justification = 'Suppressing this rule because Script Analyzer does not understand Pester syntax.')]
param ()

BeforeDiscovery {
    try
    {
        if (-not (Get-Module -Name 'DscResource.Test'))
        {
            # Assumes dependencies have been resolved, so if this module is not available, run 'noop' task.
            if (-not (Get-Module -Name 'DscResource.Test' -ListAvailable))
            {
                # Redirect all streams to $null, except the error stream (stream 2)
                & "$PSScriptRoot/../../../build.ps1" -Tasks 'noop' 3>&1 4>&1 5>&1 6>&1 > $null
            }

            # If the dependencies have not been resolved, this will throw an error.
            Import-Module -Name 'DscResource.Test' -Force -ErrorAction 'Stop'
        }
    }
    catch [System.IO.FileNotFoundException]
    {
        throw 'DscResource.Test module dependency not found. Please run ".\build.ps1 -ResolveDependency -Tasks noop" first.'
    }
}

BeforeAll {
    $script:moduleName = '{MyModuleName}'

    Import-Module -Name $script:moduleName -Force -ErrorAction 'Stop'

    $PSDefaultParameterValues['InModuleScope:ModuleName'] = $script:moduleName
    $PSDefaultParameterValues['Mock:ModuleName'] = $script:moduleName
    $PSDefaultParameterValues['Should:ModuleName'] = $script:moduleName
}

AfterAll {
    $PSDefaultParameterValues.Remove('InModuleScope:ModuleName')
    $PSDefaultParameterValues.Remove('Mock:ModuleNam...

Files:

  • tests/Unit/Public/Get-SqlDscRole.Tests.ps1
**/*.ps1

📄 CodeRabbit inference engine (.github/instructions/dsc-community-style-guidelines.instructions.md)

Follow PowerShell style and test guideline instructions strictly

Files:

  • tests/Unit/Public/Get-SqlDscRole.Tests.ps1
  • source/Public/Remove-SqlDscRole.ps1
  • source/Public/Get-SqlDscRole.ps1
tests/Unit/{Classes,Public,Private}/*.Tests.ps1

📄 CodeRabbit inference engine (.github/instructions/dsc-community-style-guidelines.instructions.md)

Add unit tests for all commands, functions, and resources

Files:

  • tests/Unit/Public/Get-SqlDscRole.Tests.ps1
**

⚙️ CodeRabbit configuration file

**: # DSC Community Guidelines

Terminology

  • Command: Public command
  • Function: Private function
  • Resource: DSC class-based resource

Build & Test Workflow Requirements

  • Run PowerShell script files from repository root
  • Setup build and test environment (once per pwsh session): ./build.ps1 -Tasks noop
  • Build project before running tests: ./build.ps1 -Tasks build
  • Always run tests in new pwsh session: Invoke-Pester -Path @({test paths}) -Output Detailed

File Organization

  • Public commands: source/Public/{CommandName}.ps1
  • Private functions: source/Private/{FunctionName}.ps1
  • Unit tests: tests/Unit/{Classes|Public|Private}/{Name}.Tests.ps1
  • Integration tests: tests/Integration/Commands/{CommandName}.Integration.Tests.ps1

Requirements

  • Follow instructions over existing code patterns
  • Follow PowerShell style and test guideline instructions strictly
  • Always update CHANGELOG.md Unreleased section
  • Localize all strings using string keys; remove any orphaned string keys
  • Check DscResource.Common before creating private functions
  • Separate reusable logic into private functions
  • DSC resources should always be created as class-based resources
  • Add unit tests for all commands/functions/resources
  • Add integration tests for all public commands and resources

Files:

  • tests/Unit/Public/Get-SqlDscRole.Tests.ps1
  • source/Public/Remove-SqlDscRole.ps1
  • source/Public/Get-SqlDscRole.ps1
{**/*.ps1,**/*.psm1,**/*.psd1}

⚙️ CodeRabbit configuration file

{**/*.ps1,**/*.psm1,**/*.psd1}: # PowerShell Guidelines

Naming

  • Use descriptive names (3+ characters, no abbreviations)
  • Functions: PascalCase with Verb-Noun format using approved verbs
  • Parameters: PascalCase
  • Variables: camelCase
  • Keywords: lower-case
  • Classes: PascalCase
  • Include scope for script/global/environment variables: $script:, $global:, $env:

File naming

  • Class files: ###.ClassName.ps1 format (e.g. 001.SqlReason.ps1, 004.StartupParameters.ps1)

Formatting

Indentation & Spacing

  • Use 4 spaces (no tabs)
  • One space around operators: $a = 1 + 2
  • One space between type and variable: [String] $name
  • One space between keyword and parenthesis: if ($condition)
  • No spaces on empty lines
  • Try to limit lines to 120 characters

Braces

  • Newline before opening brace (except variable assignments)
  • One newline after opening brace
  • Two newlines after closing brace (one if followed by another brace or continuation)

Quotes

  • Use single quotes unless variable expansion is needed: 'text' vs "text $variable"

Arrays

  • Single line: @('one', 'two', 'three')
  • Multi-line: each element on separate line with proper indentation
  • Do not use the unary comma operator (,) in return statements to force
    an array

Hashtables

  • Empty: @{}
  • Each property on separate line with proper indentation
  • Properties: Use PascalCase

Comments

  • Single line: # Comment (capitalized, on own line)
  • Multi-line: <# Comment #> format (opening and closing brackets on own line), and indent text
  • No commented-out code

Comment-based help

  • Always add comment-based help to all functions and scripts
  • Comment-based help: SYNOPSIS, DESCRIPTION (40+ chars), PARAMETER, EXAMPLE sections before function/class
  • Comment-based help indentation: keywords 4 spaces, text 8 spaces
  • Include examples for all parameter sets and combinations
  • INPUTS: List each pipeline‑accepted type (one per line) with a 1‑line description...

Files:

  • tests/Unit/Public/Get-SqlDscRole.Tests.ps1
  • source/Public/Remove-SqlDscRole.ps1
  • source/Public/Get-SqlDscRole.ps1
source/**/*.ps1

📄 CodeRabbit inference engine (.github/instructions/dsc-community-style-guidelines-localization.instructions.md)

source/**/*.ps1: Localize all Write-Debug, Write-Verbose, Write-Error, Write-Warning, and $PSCmdlet.ThrowTerminatingError() messages
Use localized string keys instead of hardcoded strings in script output/messages
Assume and use $script:localizedData for accessing localized strings
When emitting messages, reference $script:localizedData.KeyName and format with the -f operator (e.g., Write-Verbose -Message ($script:localizedData.KeyName -f $value1))

Files:

  • source/Public/Remove-SqlDscRole.ps1
  • source/Public/Get-SqlDscRole.ps1

⚙️ CodeRabbit configuration file

source/**/*.ps1: # Localization Guidelines

Requirements

  • Localize all Write-Debug, Write-Verbose, Write-Error, Write-Warning and $PSCmdlet.ThrowTerminatingError() messages
  • Use localized string keys, not hardcoded strings
  • Assume $script:localizedData is available

String Files

  • Commands/functions: source/en-US/{MyModuleName}.strings.psd1
  • Class resources: source/en-US/{ResourceClassName}.strings.psd1

Key Naming Patterns

  • Format: Verb_FunctionName_Action (underscore separators), e.g. Get_Database_ConnectingToDatabase

String Format

ConvertFrom-StringData @'
    KeyName = Message with {0} placeholder. (PREFIX0001)
'@

String IDs

  • Format: (PREFIX####)
  • PREFIX: First letter of each word in class or function name (SqlSetup → SS, Get-SqlDscDatabase → GSDD)
  • Number: Sequential from 0001

Usage

Write-Verbose -Message ($script:localizedData.KeyName -f $value1)

Files:

  • source/Public/Remove-SqlDscRole.ps1
  • source/Public/Get-SqlDscRole.ps1
source/Public/*.ps1

📄 CodeRabbit inference engine (.github/instructions/dsc-community-style-guidelines.instructions.md)

Place public commands in source/Public/{CommandName}.ps1

Files:

  • source/Public/Remove-SqlDscRole.ps1
  • source/Public/Get-SqlDscRole.ps1
🧠 Learnings (6)
📓 Common learnings
Learnt from: CR
PR: dsccommunity/SqlServerDsc#0
File: .github/instructions/dsc-community-style-guidelines-powershell.instructions.md:0-0
Timestamp: 2025-09-16T16:34:27.319Z
Learning: Applies to **/*.{ps1,psm1} : For terminating errors use $PSCmdlet.ThrowTerminatingError() (not in classes); include relevant error category and in catch include exception with localized message
Learnt from: CR
PR: dsccommunity/SqlServerDsc#0
File: .github/instructions/dsc-community-style-guidelines-powershell.instructions.md:0-0
Timestamp: 2025-09-16T16:34:27.319Z
Learning: Applies to **/*.{ps1,psm1} : Use Write-Error for non-terminating errors with -Message (localized), -Category, -ErrorId (unique, matches localized ID), -TargetObject; in catch include -Exception; always return after Write-Error
Learnt from: johlju
PR: dsccommunity/SqlServerDsc#2189
File: source/Public/Set-SqlDscDatabaseDefault.ps1:124-130
Timestamp: 2025-09-06T19:12:11.414Z
Learning: In PowerShell functions, when calling commands with -ErrorAction 'Stop', if the command fails it throws a terminating error that stops execution of the calling function entirely, so $ErrorActionPreference restoration only needs to happen after successful completion, not in a finally block.
Learnt from: CR
PR: dsccommunity/SqlServerDsc#0
File: .github/instructions/dsc-community-style-guidelines-mof-resources.instructions.md:0-0
Timestamp: 2025-09-12T13:20:57.155Z
Learning: Applies to source/DSCResources/**/*.psm1 : Do not use throw for terminating errors; instead use New-*Exception helper commands (e.g., New-InvalidDataException, New-ArgumentException, New-InvalidOperationException, New-ObjectNotFoundException, New-InvalidResultException, New-NotImplementedException)
Learnt from: CR
PR: dsccommunity/SqlServerDsc#0
File: .github/instructions/dsc-community-style-guidelines-powershell.instructions.md:0-0
Timestamp: 2025-09-16T16:34:27.319Z
Learning: Applies to **/*.{ps1,psm1} : Set $ErrorActionPreference='Stop' immediately before commands using -ErrorAction 'Stop' and restore after; do not use try-catch-finally for this
📚 Learning: 2025-09-12T13:20:57.155Z
Learnt from: CR
PR: dsccommunity/SqlServerDsc#0
File: .github/instructions/dsc-community-style-guidelines-mof-resources.instructions.md:0-0
Timestamp: 2025-09-12T13:20:57.155Z
Learning: Applies to source/DSCResources/**/*.psm1 : Do not use throw for terminating errors; instead use New-*Exception helper commands (e.g., New-InvalidDataException, New-ArgumentException, New-InvalidOperationException, New-ObjectNotFoundException, New-InvalidResultException, New-NotImplementedException)

Applied to files:

  • source/Public/Remove-SqlDscRole.ps1
📚 Learning: 2025-08-17T10:48:15.384Z
Learnt from: johlju
PR: dsccommunity/SqlServerDsc#2136
File: source/suffix.ps1:24-24
Timestamp: 2025-08-17T10:48:15.384Z
Learning: In source/suffix.ps1, the Write-Verbose message in the catch block for Import-SqlDscPreferredModule does not need localization because the exception message from Import-SqlDscPreferredModule is already localized by that command, making it an edge case exception to the localization guidelines.

Applied to files:

  • source/Public/Get-SqlDscRole.ps1
📚 Learning: 2025-08-29T17:22:23.268Z
Learnt from: CR
PR: dsccommunity/SqlServerDsc#0
File: .github/instructions/dsc-community-style-guidelines-localization.instructions.md:0-0
Timestamp: 2025-08-29T17:22:23.268Z
Learning: Applies to source/**/*.ps1 : Use localized string keys instead of hardcoded strings in script output/messages

Applied to files:

  • source/Public/Get-SqlDscRole.ps1
📚 Learning: 2025-09-12T13:20:57.155Z
Learnt from: CR
PR: dsccommunity/SqlServerDsc#0
File: .github/instructions/dsc-community-style-guidelines-mof-resources.instructions.md:0-0
Timestamp: 2025-09-12T13:20:57.155Z
Learning: Applies to source/DSCResources/**/*.psm1 : Use localized strings for all messages (e.g., Write-Verbose, Write-Error)

Applied to files:

  • source/Public/Get-SqlDscRole.ps1
📚 Learning: 2025-10-04T21:33:23.022Z
Learnt from: dan-hughes
PR: dsccommunity/UpdateServicesDsc#85
File: source/en-US/UpdateServicesDsc.strings.psd1:1-2
Timestamp: 2025-10-04T21:33:23.022Z
Learning: In UpdateServicesDsc (and similar DSC modules), the module-level localization file (source/en-US/<ModuleName>.strings.psd1) can be empty when DSC resources have their own localization files in source/DSCResources/<ResourceName>/en-US/DSC_<ResourceName>.strings.psd1. Automated tests verify localization completeness for resources. Don't flag empty module-level localization files as issues when resources have separate localization.

Applied to files:

  • source/Public/Get-SqlDscRole.ps1
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (3)
  • GitHub Check: dsccommunity.SqlServerDsc (Build Package Module)
  • GitHub Check: PSScriptAnalyzer
  • GitHub Check: PSScriptAnalyzer
🔇 Additional comments (4)
tests/Unit/Public/Get-SqlDscRole.Tests.ps1 (1)

127-131: LGTM: message assertion updated to include code (GSDR0001)

Change aligns with localized key and ErrorId updates.

source/Public/Remove-SqlDscRole.ps1 (3)

95-105: Good swap to ThrowTerminatingError for not-found

Correct category, ErrorId, and localized message. Targeting $Name is appropriate for this parameter set.


118-126: Built-in role guard now properly terminates

Correct use of InvalidOperation category and localized message.


146-153: Removal failure now surfaces original exception with localized context

Good: wraps inner exception, uses InvalidOperation, and terminates via ErrorRecord.

@codecov
Copy link

codecov bot commented Oct 20, 2025

Codecov Report

❌ Patch coverage is 93.87755% with 3 lines in your changes missing coverage. Please review.
✅ Project coverage is 94%. Comparing base (0f3d639) to head (8e28bf0).
⚠️ Report is 31 commits behind head on main.

Files with missing lines Patch % Lines
source/Public/Remove-SqlDscDatabase.ps1 82% 3 Missing ⚠️
Additional details and impacted files

Impacted file tree graph

@@         Coverage Diff          @@
##           main   #2312   +/-   ##
====================================
  Coverage    94%     94%           
====================================
  Files       150     150           
  Lines      9248    9246    -2     
====================================
  Hits       8760    8760           
+ Misses      488     486    -2     
Flag Coverage Δ
unit 94% <93%> (+<1%) ⬆️
Files with missing lines Coverage Δ
source/Public/Get-SqlDscRole.ps1 100% <100%> (ø)
source/Public/New-SqlDscDatabase.ps1 93% <100%> (ø)
source/Public/New-SqlDscRole.ps1 100% <100%> (ø)
source/Public/Remove-SqlDscAgentAlert.ps1 100% <100%> (ø)
source/Public/Remove-SqlDscRole.ps1 100% <100%> (ø)
source/Public/Set-SqlDscAgentAlert.ps1 95% <100%> (ø)
source/Public/Set-SqlDscDatabase.ps1 98% <100%> (+3%) ⬆️
source/Public/Remove-SqlDscDatabase.ps1 80% <82%> (-5%) ⬇️
🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.

@johlju
Copy link
Member Author

johlju commented Oct 21, 2025

@coderabbitai review

@coderabbitai
Copy link

coderabbitai bot commented Oct 21, 2025

✅ Actions performed

Review triggered.

Note: CodeRabbit is an incremental review system and does not re-review already reviewed commits. This command is applicable only when automatic reviews are paused.

Copy link

@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: 0

Caution

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

⚠️ Outside diff range comments (2)
source/Public/New-SqlDscRole.ps1 (1)

96-104: Update ErrorId prefix from NSR to NSDR for New-SqlDscRole function alignment with coding guidelines.

The review is correct. Per the established naming convention (first letter of each word), New-SqlDscRole requires the NSDR prefix (N-S-D-R), not NSR. This matches the pattern used throughout the codebase: Remove-SqlDscRole uses RSDR, Set-SqlDscDatabase uses SSDD, etc. Both error IDs at lines 99 and 136 need updating.

source/Public/Remove-SqlDscDatabase.ps1 (1)

213-239: Drop() failure leaves DB in SINGLE_USER when -DropConnections; add best-effort revert and remove EAP toggling

If Drop() throws after setting SINGLE_USER, the database can be left locked in single-user mode. Add a best-effort revert to MULTI_USER before throwing. Also remove EAP toggling here as well.

-            try
-            {
-                $originalErrorActionPreference = $ErrorActionPreference
-
-                $ErrorActionPreference = 'Stop'
-
-                $DatabaseObject.Drop()
-
-                Write-Verbose -Message ($script:localizedData.Database_Removed -f $Name)
-            }
-            catch
-            {
-                $errorMessage = $script:localizedData.Database_RemoveFailed -f $Name, $DatabaseObject.Parent.InstanceName
-
-                $PSCmdlet.ThrowTerminatingError(
-                    [System.Management.Automation.ErrorRecord]::new(
-                        [System.InvalidOperationException]::new($errorMessage, $_.Exception),
-                        'RSDD0005', # cspell: disable-line
-                        [System.Management.Automation.ErrorCategory]::InvalidOperation,
-                        $DatabaseObject
-                    )
-                )
-            }
-            finally
-            {
-                $ErrorActionPreference = $originalErrorActionPreference
-            }
+            try
+            {
+                $DatabaseObject.Drop()
+
+                Write-Verbose -Message ($script:localizedData.Database_Removed -f $Name)
+            }
+            catch
+            {
+                if ($DropConnections.IsPresent)
+                {
+                    try
+                    {
+                        $DatabaseObject.UserAccess = [Microsoft.SqlServer.Management.Smo.DatabaseUserAccess]::Multiple
+                        $DatabaseObject.Alter([Microsoft.SqlServer.Management.Smo.TerminationClause]::RollbackTransactionsImmediately)
+                    }
+                    catch
+                    {
+                        Write-Debug -Message ($script:localizedData.Database_RevertMultiUserFailed -f $Name)
+                    }
+                }
+
+                $errorMessage = $script:localizedData.Database_RemoveFailed -f $Name, $DatabaseObject.Parent.InstanceName
+
+                $PSCmdlet.ThrowTerminatingError(
+                    [System.Management.Automation.ErrorRecord]::new(
+                        [System.InvalidOperationException]::new($errorMessage, $_.Exception),
+                        'RSDD0005', # cspell: disable-line
+                        [System.Management.Automation.ErrorCategory]::InvalidOperation,
+                        $DatabaseObject
+                    )
+                )
+            }

Add the new localized string key Database_RevertMultiUserFailed. As per coding guidelines.

🧹 Nitpick comments (7)
source/Public/New-SqlDscRole.ps1 (2)

110-110: Align ShouldProcess usage with style: variable names and no Verbose in block.

  • Rename variables to $descriptionMessage/$confirmationMessage/$captionMessage.
  • Avoid Write-Verbose inside the ShouldProcess block; rely on the ShouldProcess messages or emit status via Write-Information if needed. [As per coding guidelines]

114-115: Prefer ::new() over New-Object for .NET types.

Use the static ctor for SMO types. [As per coding guidelines]

-                $serverRole = New-Object -TypeName Microsoft.SqlServer.Management.Smo.ServerRole -ArgumentList $ServerObject, $Name
+                $serverRole = [Microsoft.SqlServer.Management.Smo.ServerRole]::new($ServerObject, $Name)
source/Public/Remove-SqlDscRole.ps1 (1)

140-140: ShouldProcess style nits: standard var names; avoid Verbose inside.

  • Rename to $descriptionMessage/$confirmationMessage/$captionMessage.
  • Keep the block focused on the state change; drop/move Write-Verbose from inside it. [As per coding guidelines]
source/Public/Remove-SqlDscDatabase.ps1 (4)

121-130: Unify ErrorId for the same condition ("cannot remove system database")

Two different ErrorIds are used for the same error condition (RSDD0001 vs RSDD0003). Prefer a single ErrorId to simplify localization, testing, and troubleshooting.

Apply this diff to reuse RSDD0001 in both branches:

-                        'RSDD0003', # cspell: disable-line
+                        'RSDD0001', # cspell: disable-line

Update unit tests/localized docs accordingly. As per coding guidelines.

Also applies to: 161-168


176-176: Align variable names with the ShouldProcess pattern

Use the canonical variable names $descriptionMessage/$confirmationMessage/$captionMessage for clarity and to match our pattern.

-        $verboseDescriptionMessage = $script:localizedData.Database_Remove_ShouldProcessVerboseDescription -f $Name, $DatabaseObject.Parent.InstanceName
-        $verboseWarningMessage = $script:localizedData.Database_Remove_ShouldProcessVerboseWarning -f $Name
+        $descriptionMessage = $script:localizedData.Database_Remove_ShouldProcessVerboseDescription -f $Name, $DatabaseObject.Parent.InstanceName
+        $confirmationMessage = $script:localizedData.Database_Remove_ShouldProcessVerboseWarning -f $Name
@@
-        if ($PSCmdlet.ShouldProcess($verboseDescriptionMessage, $verboseWarningMessage, $captionMessage))
+        if ($PSCmdlet.ShouldProcess($descriptionMessage, $confirmationMessage, $captionMessage))

As per coding guidelines.


178-209: Remove ErrorActionPreference toggling around SMO methods

$ErrorActionPreference only affects PowerShell cmdlets with -ErrorAction, not .NET/SMO methods. The try/finally used solely to save/restore EAP is unnecessary noise.

Apply this diff:

-                try
-                {
-                    $originalErrorActionPreference = $ErrorActionPreference
-
-                    $ErrorActionPreference = 'Stop'
-
-                    $DatabaseObject.UserAccess = 'Single'
-                    $DatabaseObject.Alter([Microsoft.SqlServer.Management.Smo.TerminationClause]::RollbackTransactionsImmediately)
-                }
+                try
+                {
+                    $DatabaseObject.UserAccess = [Microsoft.SqlServer.Management.Smo.DatabaseUserAccess]::Single
+                    $DatabaseObject.Alter([Microsoft.SqlServer.Management.Smo.TerminationClause]::RollbackTransactionsImmediately)
+                }
                 catch
                 {
                     $errorMessage = $script:localizedData.Database_DropConnectionsFailed -f $Name
@@
-                finally
-                {
-                    $ErrorActionPreference = $originalErrorActionPreference
-                }

As per retrieved learnings and coding guidelines.


181-181: Avoid Write-Verbose inside the ShouldProcess block

Guideline: inside $PSCmdlet.ShouldProcess { ... } avoid Write-Verbose. Either remove these or emit pre-/post-action messages outside the block.
As per coding guidelines.

Also applies to: 211-211, 221-221

📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 0756914 and 107fcd6.

📒 Files selected for processing (5)
  • source/Public/Get-SqlDscRole.ps1 (2 hunks)
  • source/Public/New-SqlDscRole.ps1 (2 hunks)
  • source/Public/Remove-SqlDscDatabase.ps1 (5 hunks)
  • source/Public/Remove-SqlDscRole.ps1 (4 hunks)
  • source/Public/Set-SqlDscDatabase.ps1 (5 hunks)
🧰 Additional context used
📓 Path-based instructions (3)
**

⚙️ CodeRabbit configuration file

**: # DSC Community Guidelines

Terminology

  • Command: Public command
  • Function: Private function
  • Resource: DSC class-based resource

Build & Test Workflow Requirements

  • Run PowerShell script files from repository root
  • Setup build and test environment (once per pwsh session): ./build.ps1 -Tasks noop
  • Build project before running tests: ./build.ps1 -Tasks build
  • Always run tests in new pwsh session: Invoke-Pester -Path @({test paths}) -Output Detailed

File Organization

  • Public commands: source/Public/{CommandName}.ps1
  • Private functions: source/Private/{FunctionName}.ps1
  • Unit tests: tests/Unit/{Classes|Public|Private}/{Name}.Tests.ps1
  • Integration tests: tests/Integration/Commands/{CommandName}.Integration.Tests.ps1

Requirements

  • Follow instructions over existing code patterns
  • Follow PowerShell style and test guideline instructions strictly
  • Always update CHANGELOG.md Unreleased section
  • Localize all strings using string keys; remove any orphaned string keys
  • Check DscResource.Common before creating private functions
  • Separate reusable logic into private functions
  • DSC resources should always be created as class-based resources
  • Add unit tests for all commands/functions/resources
  • Add integration tests for all public commands and resources

Files:

  • source/Public/Set-SqlDscDatabase.ps1
  • source/Public/Get-SqlDscRole.ps1
  • source/Public/Remove-SqlDscDatabase.ps1
  • source/Public/New-SqlDscRole.ps1
  • source/Public/Remove-SqlDscRole.ps1
{**/*.ps1,**/*.psm1,**/*.psd1}

⚙️ CodeRabbit configuration file

{**/*.ps1,**/*.psm1,**/*.psd1}: # PowerShell Guidelines

Naming

  • Use descriptive names (3+ characters, no abbreviations)
  • Functions: PascalCase with Verb-Noun format using approved verbs
  • Parameters: PascalCase
  • Variables: camelCase
  • Keywords: lower-case
  • Classes: PascalCase
  • Include scope for script/global/environment variables: $script:, $global:, $env:

File naming

  • Class files: ###.ClassName.ps1 format (e.g. 001.SqlReason.ps1, 004.StartupParameters.ps1)

Formatting

Indentation & Spacing

  • Use 4 spaces (no tabs)
  • One space around operators: $a = 1 + 2
  • One space between type and variable: [String] $name
  • One space between keyword and parenthesis: if ($condition)
  • No spaces on empty lines
  • Try to limit lines to 120 characters

Braces

  • Newline before opening brace (except variable assignments)
  • One newline after opening brace
  • Two newlines after closing brace (one if followed by another brace or continuation)

Quotes

  • Use single quotes unless variable expansion is needed: 'text' vs "text $variable"

Arrays

  • Single line: @('one', 'two', 'three')
  • Multi-line: each element on separate line with proper indentation
  • Do not use the unary comma operator (,) in return statements to force
    an array

Hashtables

  • Empty: @{}
  • Each property on separate line with proper indentation
  • Properties: Use PascalCase

Comments

  • Single line: # Comment (capitalized, on own line)
  • Multi-line: <# Comment #> format (opening and closing brackets on own line), and indent text
  • No commented-out code

Comment-based help

  • Always add comment-based help to all functions and scripts
  • Comment-based help: SYNOPSIS, DESCRIPTION (40+ chars), PARAMETER, EXAMPLE sections before function/class
  • Comment-based help indentation: keywords 4 spaces, text 8 spaces
  • Include examples for all parameter sets and combinations
  • INPUTS: List each pipeline‑accepted type (one per line) with a 1‑line description...

Files:

  • source/Public/Set-SqlDscDatabase.ps1
  • source/Public/Get-SqlDscRole.ps1
  • source/Public/Remove-SqlDscDatabase.ps1
  • source/Public/New-SqlDscRole.ps1
  • source/Public/Remove-SqlDscRole.ps1
source/**/*.ps1

⚙️ CodeRabbit configuration file

source/**/*.ps1: # Localization Guidelines

Requirements

  • Localize all Write-Debug, Write-Verbose, Write-Error, Write-Warning and $PSCmdlet.ThrowTerminatingError() messages
  • Use localized string keys, not hardcoded strings
  • Assume $script:localizedData is available

String Files

  • Commands/functions: source/en-US/{MyModuleName}.strings.psd1
  • Class resources: source/en-US/{ResourceClassName}.strings.psd1

Key Naming Patterns

  • Format: Verb_FunctionName_Action (underscore separators), e.g. Get_Database_ConnectingToDatabase

String Format

ConvertFrom-StringData @'
    KeyName = Message with {0} placeholder. (PREFIX0001)
'@

String IDs

  • Format: (PREFIX####)
  • PREFIX: First letter of each word in class or function name (SqlSetup → SS, Get-SqlDscDatabase → GSDD)
  • Number: Sequential from 0001

Usage

Write-Verbose -Message ($script:localizedData.KeyName -f $value1)

Files:

  • source/Public/Set-SqlDscDatabase.ps1
  • source/Public/Get-SqlDscRole.ps1
  • source/Public/Remove-SqlDscDatabase.ps1
  • source/Public/New-SqlDscRole.ps1
  • source/Public/Remove-SqlDscRole.ps1
🧠 Learnings (8)
📓 Common learnings
Learnt from: CR
PR: dsccommunity/SqlServerDsc#0
File: .github/instructions/dsc-community-style-guidelines-powershell.instructions.md:0-0
Timestamp: 2025-09-16T16:34:27.319Z
Learning: Applies to **/*.{ps1,psm1} : For terminating errors use $PSCmdlet.ThrowTerminatingError() (not in classes); include relevant error category and in catch include exception with localized message
Learnt from: CR
PR: dsccommunity/SqlServerDsc#0
File: .github/instructions/dsc-community-style-guidelines-powershell.instructions.md:0-0
Timestamp: 2025-09-16T16:34:27.319Z
Learning: Applies to **/*.{ps1,psm1} : Use Write-Error for non-terminating errors with -Message (localized), -Category, -ErrorId (unique, matches localized ID), -TargetObject; in catch include -Exception; always return after Write-Error
Learnt from: johlju
PR: dsccommunity/SqlServerDsc#2189
File: source/Public/Set-SqlDscDatabaseDefault.ps1:124-130
Timestamp: 2025-09-06T19:12:11.414Z
Learning: In PowerShell functions, when calling commands with -ErrorAction 'Stop', if the command fails it throws a terminating error that stops execution of the calling function entirely, so $ErrorActionPreference restoration only needs to happen after successful completion, not in a finally block.
Learnt from: CR
PR: dsccommunity/SqlServerDsc#0
File: .github/instructions/dsc-community-style-guidelines-powershell.instructions.md:0-0
Timestamp: 2025-09-16T16:34:27.319Z
Learning: Applies to **/*.{ps1,psm1} : Set $ErrorActionPreference='Stop' immediately before commands using -ErrorAction 'Stop' and restore after; do not use try-catch-finally for this
Learnt from: CR
PR: dsccommunity/SqlServerDsc#0
File: .github/instructions/dsc-community-style-guidelines-mof-resources.instructions.md:0-0
Timestamp: 2025-09-12T13:20:57.155Z
Learning: Applies to source/DSCResources/**/*.psm1 : Do not use throw for terminating errors; instead use New-*Exception helper commands (e.g., New-InvalidDataException, New-ArgumentException, New-InvalidOperationException, New-ObjectNotFoundException, New-InvalidResultException, New-NotImplementedException)
📚 Learning: 2025-08-17T18:25:52.891Z
Learnt from: johlju
PR: dsccommunity/SqlServerDsc#2132
File: source/Public/New-SqlDscLogin.ps1:218-225
Timestamp: 2025-08-17T18:25:52.891Z
Learning: PowerShell's System.Management.Automation.ErrorRecord constructor accepts a string as the first parameter and automatically converts it to an exception object internally. No need to manually wrap strings in System.Exception when creating ErrorRecord objects in PowerShell.

Applied to files:

  • source/Public/Set-SqlDscDatabase.ps1
📚 Learning: 2025-09-12T13:20:57.155Z
Learnt from: CR
PR: dsccommunity/SqlServerDsc#0
File: .github/instructions/dsc-community-style-guidelines-mof-resources.instructions.md:0-0
Timestamp: 2025-09-12T13:20:57.155Z
Learning: Applies to source/DSCResources/**/*.psm1 : Do not use throw for terminating errors; instead use New-*Exception helper commands (e.g., New-InvalidDataException, New-ArgumentException, New-InvalidOperationException, New-ObjectNotFoundException, New-InvalidResultException, New-NotImplementedException)

Applied to files:

  • source/Public/Set-SqlDscDatabase.ps1
📚 Learning: 2025-09-16T16:34:27.319Z
Learnt from: CR
PR: dsccommunity/SqlServerDsc#0
File: .github/instructions/dsc-community-style-guidelines-powershell.instructions.md:0-0
Timestamp: 2025-09-16T16:34:27.319Z
Learning: Applies to **/*.{ps1,psm1} : Implement Force parameter pattern: if ($Force.IsPresent -and -not $Confirm) { $ConfirmPreference = 'None' }

Applied to files:

  • source/Public/Set-SqlDscDatabase.ps1
  • source/Public/New-SqlDscRole.ps1
  • source/Public/Remove-SqlDscRole.ps1
📚 Learning: 2025-08-18T10:44:38.990Z
Learnt from: johlju
PR: dsccommunity/SqlServerDsc#2132
File: source/Public/New-SqlDscLogin.ps1:254-257
Timestamp: 2025-08-18T10:44:38.990Z
Learning: When implementing Force and Confirm parameter interaction in PowerShell functions with SupportsShouldProcess, use the pattern `if ($Force.IsPresent -and -not $Confirm)` to suppress confirmations. This ensures that explicit `-Confirm:$true` is respected even when `-Force` is present, preserving user intent when they explicitly request confirmation alongside Force.

Applied to files:

  • source/Public/Set-SqlDscDatabase.ps1
  • source/Public/New-SqlDscRole.ps1
📚 Learning: 2025-08-17T10:03:59.993Z
Learnt from: johlju
PR: dsccommunity/SqlServerDsc#2136
File: source/Public/Remove-SqlDscLogin.ps1:83-86
Timestamp: 2025-08-17T10:03:59.993Z
Learning: In PowerShell functions with SupportsShouldProcess, the $Confirm automatic variable defaults to $false when no -Confirm parameter is passed, and only becomes $true when -Confirm or -Confirm:$true is explicitly passed. The logic `if ($Force.IsPresent -and -not $Confirm)` correctly handles both cases where no -Confirm is passed and where -Confirm:$false is explicitly passed.

Applied to files:

  • source/Public/Set-SqlDscDatabase.ps1
📚 Learning: 2025-08-17T10:48:15.384Z
Learnt from: johlju
PR: dsccommunity/SqlServerDsc#2136
File: source/suffix.ps1:24-24
Timestamp: 2025-08-17T10:48:15.384Z
Learning: In source/suffix.ps1, the Write-Verbose message in the catch block for Import-SqlDscPreferredModule does not need localization because the exception message from Import-SqlDscPreferredModule is already localized by that command, making it an edge case exception to the localization guidelines.

Applied to files:

  • source/Public/Get-SqlDscRole.ps1
📚 Learning: 2025-09-16T16:34:27.319Z
Learnt from: CR
PR: dsccommunity/SqlServerDsc#0
File: .github/instructions/dsc-community-style-guidelines-powershell.instructions.md:0-0
Timestamp: 2025-09-16T16:34:27.319Z
Learning: Applies to **/*.{ps1,psm1} : Follow the ShouldProcess message variables pattern ($descriptionMessage, $confirmationMessage, $captionMessage)

Applied to files:

  • source/Public/New-SqlDscRole.ps1
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (33)
  • GitHub Check: dsccommunity.SqlServerDsc (Integration Test Resources - Reporting Services Integration SQL2022_WIN2025)
  • GitHub Check: dsccommunity.SqlServerDsc (Integration Test Resources - Reporting Services Integration SQL2022_WIN2022)
  • GitHub Check: dsccommunity.SqlServerDsc (Integration Test Resources - Reporting Services Integration SQL2019_WIN2025)
  • GitHub Check: dsccommunity.SqlServerDsc (Integration Test Resources - Reporting Services (dbatools) Integration SQL2022_WIN2022)
  • GitHub Check: dsccommunity.SqlServerDsc (Integration Test Resources - Reporting Services Integration SQL2019_WIN2022)
  • GitHub Check: dsccommunity.SqlServerDsc (Integration Test Resources - Reporting Services (dbatools) Integration SQL2019_WIN2022)
  • GitHub Check: dsccommunity.SqlServerDsc (Integration Test Resources - Reporting Services Integration SQL2017_WIN2022)
  • GitHub Check: dsccommunity.SqlServerDsc (Integration Test Resources - Reporting Services (dbatools) Integration SQL2017_WIN2022)
  • GitHub Check: dsccommunity.SqlServerDsc (Integration Test Resources - SQL Server (dbatools) Integration SQL2022_WIN2022)
  • GitHub Check: dsccommunity.SqlServerDsc (Integration Test Resources - SQL Server (dbatools) Integration SQL2019_WIN2022)
  • GitHub Check: dsccommunity.SqlServerDsc (Integration Test Resources - SQL Server (dbatools) Integration SQL2017_WIN2022)
  • GitHub Check: dsccommunity.SqlServerDsc (Integration Test Commands - SQL Server Commands SQL2022_WIN2025)
  • GitHub Check: dsccommunity.SqlServerDsc (Integration Test Resources - SQL Server Integration SQL2022_WIN2025)
  • GitHub Check: dsccommunity.SqlServerDsc (Integration Test Commands - SQL Server Commands SQL2022_WIN2022)
  • GitHub Check: dsccommunity.SqlServerDsc (Integration Test Resources - SQL Server Integration SQL2022_WIN2022)
  • GitHub Check: dsccommunity.SqlServerDsc (Integration Test Commands - SQL Server Commands SQL2019_WIN2025)
  • GitHub Check: dsccommunity.SqlServerDsc (Integration Test Resources - SQL Server Integration SQL2019_WIN2025)
  • GitHub Check: dsccommunity.SqlServerDsc (Integration Test Commands - SQL Server Commands SQL2019_WIN2022)
  • GitHub Check: dsccommunity.SqlServerDsc (Integration Test Resources - SQL Server Integration SQL2019_WIN2022)
  • GitHub Check: dsccommunity.SqlServerDsc (Integration Test Commands - SQL Server Commands SQL2017_WIN2022)
  • GitHub Check: dsccommunity.SqlServerDsc (Integration Test Resources - SQL Server Integration SQL2017_WIN2022)
  • GitHub Check: dsccommunity.SqlServerDsc (Integration Test Commands - SQL Server (Prepared Image) Commands - Prepared Image SQL2022_WIN2025)
  • GitHub Check: dsccommunity.SqlServerDsc (Integration Test Commands - SQL Server (Prepared Image) Commands - Prepared Image SQL2022_WIN2022)
  • GitHub Check: dsccommunity.SqlServerDsc (Integration Test Commands - SQL Server (Prepared Image) Commands - Prepared Image SQL2019_WIN2025)
  • GitHub Check: dsccommunity.SqlServerDsc (Integration Test Commands - SQL Server (Prepared Image) Commands - Prepared Image SQL2019_WIN2022)
  • GitHub Check: dsccommunity.SqlServerDsc (Integration Test Resources - Power BI Report Server Integration PowerBI_WIN2025)
  • GitHub Check: dsccommunity.SqlServerDsc (Integration Test Commands - SQL Server (Prepared Image) Commands - Prepared Image SQL2017_WIN2022)
  • GitHub Check: dsccommunity.SqlServerDsc (Integration Test Resources - Power BI Report Server Integration PowerBI_WIN2022)
  • GitHub Check: dsccommunity.SqlServerDsc (Quality Test and Unit Test Publish Code Coverage)
  • GitHub Check: dsccommunity.SqlServerDsc (Quality Test and Unit Test HQRM)
  • GitHub Check: dsccommunity.SqlServerDsc (Quality Test and Unit Test Determine DSC Resource Test Requirements)
  • GitHub Check: dsccommunity.SqlServerDsc (Quality Test and Unit Test Unit)
  • GitHub Check: dsccommunity.SqlServerDsc (Build Package Module)
🔇 Additional comments (13)
source/Public/Get-SqlDscRole.ps1 (1)

76-89: LGTM! Proper implementation of non-terminating error pattern.

The changes correctly implement the coding guidelines:

  • Localization key renamed to follow Verb_FunctionName_Action pattern
  • Write-Error includes all required parameters (Message, Category, ErrorId, TargetObject)
  • return statement properly added after Write-Error to prevent further processing
  • ErrorId GSDR0001 follows the correct PREFIX pattern (Get-SqlDscRole → GSDR)

The use of a non-terminating error is appropriate for a Get command, allowing pipeline operations to continue when a role is not found.

Based on coding guidelines.

source/Public/Set-SqlDscDatabase.ps1 (5)

111-117: LGTM! Force parameter pattern correctly implemented.

The begin block properly implements the Force parameter pattern, suppressing confirmations when -Force is used while respecting explicit -Confirm:$true.

Based on coding guidelines.


138-145: LGTM! Terminating error correctly constructed.

The ErrorRecord construction is correct:

  • Appropriate exception type (InvalidOperationException) for database not found
  • Correct error category (InvalidOperation)
  • Proper error ID (SSDD0001)
  • Target object correctly set to $Name

174-181: LGTM! Input validation error correctly handled.

The ErrorRecord construction is appropriate:

  • ArgumentException correctly used for invalid parameter value
  • Error category (InvalidArgument) matches the validation failure
  • Target object properly set to $CompatibilityLevel
  • Sequential error ID (SSDD0002)

192-199: LGTM! Collation validation error correctly implemented.

The ErrorRecord follows the same correct pattern:

  • ArgumentException for invalid parameter validation
  • Appropriate error category (InvalidArgument)
  • Target object set to $Collation
  • Sequential error ID (SSDD0003)

257-264: LGTM! Exception chain correctly preserved in catch block.

The ErrorRecord construction properly:

  • Uses InvalidOperationException for the operation failure
  • Preserves the original exception via $_.Exception as the inner exception (line 259)
  • Sets appropriate error category (InvalidOperation)
  • Targets $DatabaseObject
  • Uses sequential error ID (SSDD0004)

This correctly maintains the full exception chain for debugging.

Based on coding guidelines.

source/Public/New-SqlDscRole.ps1 (1)

73-79: Force/Confirm pattern looks correct.

Respects explicit -Confirm and suppresses prompts only when -Force and not -Confirm. Scope-local ConfirmPreference change. [Based on learnings]

source/Public/Remove-SqlDscRole.ps1 (4)

78-84: Force/Confirm handling LGTM.

Pattern matches guidance; -Force doesn’t override explicit -Confirm. [Based on learnings]


126-133: Built-in role protection LGTM.

InvalidOperation with target RoleObject and RSDR0002 is appropriate.


154-161: Failure path terminating error LGTM.

Wraps original exception, InvalidOperation category, targets RoleObject, ErrorId RSDR0003.


103-112: All verification requirements confirmed; code is correct.

The localized key Remove_SqlDscRole_NotFound and error ID RSDR0001 both exist in the strings file (line 334 of source/en-US/SqlServerDsc.strings.psd1). The code snippet at lines 103-112 correctly uses both resources, pairs ItemNotFoundException with ObjectNotFound category appropriately, and targets the Name parameter. No duplicate error IDs exist in the codebase. All naming conventions are followed.

source/Public/Remove-SqlDscDatabase.ps1 (2)

97-104: Force/Confirm pattern looks good

Setting ConfirmPreference to 'None' when -Force and not -Confirm is aligned with the Force pattern.
If other commands in this PR follow the same pattern, keep it consistent across all. As per coding guidelines.


140-147: Good NotFound handling

ItemNotFoundException with ObjectNotFound category and a localized message via ThrowTerminatingError is correct.

Copy link

@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: 1

🧹 Nitpick comments (7)
tests/Unit/Stubs/SMO.cs (1)

166-171: LGTM! Clean stub addition for database user access modes.

The enum follows SMO conventions and provides the necessary stub for testing database user access functionality. The values correctly represent SQL Server's database user access modes (MULTI_USER, SINGLE_USER, RESTRICTED_USER).

Consider adding a "Used by:" documentation comment for consistency with other enums in this file:

+    // TypeName: Microsoft.SqlServer.Management.Smo.DatabaseUserAccess
+    // Used by:
+    //  New-SqlDscDatabase.Tests.ps1
+    //  Set-SqlDscDatabase.Tests.ps1
     public enum DatabaseUserAccess : int
source/Public/Remove-SqlDscRole.ps1 (2)

78-84: Force pattern: looks correct; optional hardening for -Confirm detection

Pattern aligns with our guidance. Optionally, avoid depending on $Confirm being auto-bound by checking $PSBoundParameters instead.

-        if ($Force.IsPresent -and -not $Confirm)
+        if ($Force.IsPresent -and -not $PSBoundParameters.ContainsKey('Confirm'))
         {
             $ConfirmPreference = 'None'
         }

As per coding guidelines.


101-112: NotFound path uses proper terminating error; minor style nit for null-check

Construction of ErrorRecord (ItemNotFound, RSDR0001, target $Name) is spot on. Prefer explicit null comparison per style guide.

-            if (-not $RoleObject)
+            if ($null -eq $RoleObject)
             {
                 $errorMessage = $script:localizedData.Remove_SqlDscRole_NotFound -f $Name

                 $PSCmdlet.ThrowTerminatingError(
                     [System.Management.Automation.ErrorRecord]::new(
                         [System.Management.Automation.ItemNotFoundException]::new($errorMessage),
                         'RSDR0001', # cspell: disable-line
                         [System.Management.Automation.ErrorCategory]::ObjectNotFound,
                         $Name
                     )
                 )
             }

As per coding guidelines.

tests/Unit/Public/Remove-SqlDscDatabase.Tests.ps1 (2)

82-85: Also assert ErrorId for the not-found case

The implementation throws RSDD0002 for missing DBs; assert it to fully verify semantics.

-            { Remove-SqlDscDatabase -ServerObject $mockServerObject -Name 'NonExistentDatabase' -Force } |
-                Should -Throw -ExpectedMessage '*not found*'
+            { Remove-SqlDscDatabase -ServerObject $mockServerObject -Name 'NonExistentDatabase' -Force } |
+                Should -Throw -ExpectedMessage '*not found*' -ErrorId 'RSDD0002,Remove-SqlDscDatabase'

52-221: Prefer localized strings in assertions

Fetch messages using InModuleScope { $script:localizedData.Key } instead of hardcoded substrings to avoid locale brittleness.

Example:

$expected = InModuleScope -ScriptBlock { $script:localizedData.Database_CannotRemoveSystem } -ModuleName $script:dscModuleName
{ Remove-SqlDscDatabase -ServerObject $mockServerObject -Name 'master' -Force } |
    Should -Throw -ExpectedMessage ("*{0}*" -f $expected)

As per coding guidelines.

source/Public/Remove-SqlDscDatabase.ps1 (2)

152-156: Align ShouldProcess string keys with pattern

Use ...ShouldProcessDescription and ...ShouldProcessConfirmation keys (no “Verbose”/“Warning” suffixes) to match the documented pattern.

-$descriptionMessage = $script:localizedData.Database_Remove_ShouldProcessVerboseDescription -f $Name, $DatabaseObject.Parent.InstanceName
-$confirmationMessage = $script:localizedData.Database_Remove_ShouldProcessVerboseWarning -f $Name
+$descriptionMessage = $script:localizedData.Database_Remove_ShouldProcessDescription -f $Name, $DatabaseObject.Parent.InstanceName
+$confirmationMessage = $script:localizedData.Database_Remove_ShouldProcessConfirmation -f $Name

As per coding guidelines.


158-181: Avoid Write-Verbose inside ShouldProcess

Replace with Write-Information for user-facing status, or move messaging outside the block.

-                Write-Verbose -Message ($script:localizedData.Database_DroppingConnections -f $Name)
+                Write-Information -MessageData ($script:localizedData.Database_DroppingConnections -f $Name)

As per coding guidelines.

📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 107fcd6 and 6c7f034.

📒 Files selected for processing (7)
  • source/Public/New-SqlDscRole.ps1 (3 hunks)
  • source/Public/Remove-SqlDscDatabase.ps1 (2 hunks)
  • source/Public/Remove-SqlDscRole.ps1 (3 hunks)
  • source/en-US/SqlServerDsc.strings.psd1 (2 hunks)
  • tests/Integration/Commands/Get-SqlDscRole.Integration.Tests.ps1 (1 hunks)
  • tests/Unit/Public/Remove-SqlDscDatabase.Tests.ps1 (2 hunks)
  • tests/Unit/Stubs/SMO.cs (1 hunks)
🚧 Files skipped from review as they are similar to previous changes (1)
  • source/en-US/SqlServerDsc.strings.psd1
🧰 Additional context used
📓 Path-based instructions (13)
**/*.[Tt]ests.ps1

📄 CodeRabbit inference engine (.github/instructions/dsc-community-style-guidelines-pester.instructions.md)

**/*.[Tt]ests.ps1: All public commands, private functions, and classes must have unit tests
All public commands and class-based resources must have integration tests
Use Pester v5 syntax only
Test code only inside Describe blocks
Assertions only in It blocks
Never test verbose messages, debug messages, or parameter binding behavior
Pass all mandatory parameters to avoid prompts
Inside It blocks, assign unused return objects to $null (unless part of a pipeline)
Call the tested entity from within the It blocks
Keep results and assertions in the same It block
Avoid try/catch/finally for cleanup; use AfterAll or AfterEach
Avoid unnecessary remove/recreate cycles
One Describe block per file matching the tested entity name
Context descriptions start with 'When'
It descriptions start with 'Should' and must not contain 'when'
Mock variables must be prefixed with 'mock'
Public commands: never use InModuleScope (except for retrieving localized strings)
Private functions and class resources: always use InModuleScope
Each class method gets a separate Context block
Each scenario gets a separate Context block
Use nested Context blocks for complex scenarios
Perform mocking in BeforeAll (use BeforeEach only when required)
Place setup/teardown (BeforeAll/BeforeEach/AfterAll/AfterEach) close to usage
Use PascalCase for Pester keywords: Describe, Context, It, Should, BeforeAll, BeforeEach, AfterAll, AfterEach
Use -BeTrue/-BeFalse; never use -Be $true/-Be $false
Never use Assert-MockCalled; use Should -Invoke instead
Do not use Should -Not -Throw; invoke commands directly
Never add an empty -MockWith block
Omit -MockWith when returning $null
Set $PSDefaultParameterValues for Mock:ModuleName, Should:ModuleName, and InModuleScope:ModuleName
Omit the -ModuleName parameter on Pester commands
Never use Mock inside an InModuleScope block
Define variables for -ForEach in a separate BeforeDiscovery near usage
Use -ForEach only on Context and It blocks
Keep variable scope close to the usage c...

Files:

  • tests/Unit/Public/Remove-SqlDscDatabase.Tests.ps1
  • tests/Integration/Commands/Get-SqlDscRole.Integration.Tests.ps1

⚙️ CodeRabbit configuration file

**/*.[Tt]ests.ps1: # Tests Guidelines

Core Requirements

  • All public commands, private functions and classes must have unit tests
  • All public commands and class-based resources must have integration tests
  • Use Pester v5 syntax only
  • Test code only inside Describe blocks
  • Assertions only in It blocks
  • Never test verbose messages, debug messages or parameter binding behavior
  • Pass all mandatory parameters to avoid prompts

Requirements

  • Inside It blocks, assign unused return objects to $null (unless part of pipeline)
  • Tested entity must be called from within the It blocks
  • Keep results and assertions in same It block
  • Avoid try-catch-finally for cleanup, use AfterAll or AfterEach
  • Avoid unnecessary remove/recreate cycles

Naming

  • One Describe block per file matching the tested entity name
  • Context descriptions start with 'When'
  • It descriptions start with 'Should', must not contain 'when'
  • Mock variables prefix: 'mock'

Structure & Scope

  • Public commands: Never use InModuleScope (unless retrieving localized strings)
  • Private functions/class resources: Always use InModuleScope
  • Each class method = separate Context block
  • Each scenario = separate Context block
  • Use nested Context blocks for complex scenarios
  • Mocking in BeforeAll (BeforeEach only when required)
  • Setup/teardown in BeforeAll,BeforeEach/AfterAll,AfterEach close to usage

Syntax Rules

  • PascalCase: Describe, Context, It, Should, BeforeAll, BeforeEach, AfterAll, AfterEach
  • Use -BeTrue/-BeFalse never -Be $true/-Be $false
  • Never use Assert-MockCalled, use Should -Invoke instead
  • No Should -Not -Throw - invoke commands directly
  • Never add an empty -MockWith block
  • Omit -MockWith when returning $null
  • Set $PSDefaultParameterValues for Mock:ModuleName, Should:ModuleName, InModuleScope:ModuleName
  • Omit -ModuleName parameter on Pester commands
  • Never use Mock inside `InModuleSc...

Files:

  • tests/Unit/Public/Remove-SqlDscDatabase.Tests.ps1
  • tests/Integration/Commands/Get-SqlDscRole.Integration.Tests.ps1
tests/Unit/Public/*.Tests.ps1

📄 CodeRabbit inference engine (.github/instructions/dsc-community-style-guidelines-pester.instructions.md)

Public command unit tests must reside in tests/Unit/Public/{Name}.Tests.ps1

Place unit tests for public commands in tests/Unit/Public/{Name}.Tests.ps1

Files:

  • tests/Unit/Public/Remove-SqlDscDatabase.Tests.ps1
**/*.{ps1,psm1}

📄 CodeRabbit inference engine (.github/instructions/dsc-community-style-guidelines-powershell.instructions.md)

**/*.{ps1,psm1}: Use descriptive names (3+ characters, no abbreviations)
Function names use PascalCase Verb-Noun with approved verbs
Parameter names use PascalCase
Variable names use camelCase
Keywords are lower-case
Class names use PascalCase
Include scope prefixes for script/global/environment variables: $script:, $global:, $env:
Use one space around operators (e.g., $a = 1 + 2)
Use one space between type and variable (e.g., [String] $name)
Use one space between keyword and parenthesis (e.g., if ($condition))
Place newline before opening brace (except variable assignments)
One newline after opening brace
Two newlines after closing brace (one if followed by another brace or continuation)
Use single quotes unless variable expansion is needed
Arrays on one line use @('one','two'); multi-line arrays have one element per line with proper indentation
Do not use unary comma in return statements to force an array
Single-line comments: '# Comment' capitalized on its own line
Multi-line comments use <# #> with brackets on their own lines and indented text
No commented-out code
Add comment-based help to all functions and scripts
Comment-based help must include SYNOPSIS, DESCRIPTION (40+ chars), PARAMETER, and EXAMPLE sections before function/class
Comment-based help indentation: keywords at 4 spaces, text at 8 spaces
Include examples for all parameter sets and combinations
INPUTS: list each pipeline-accepted type with one-line description; repeat .INPUTS per type
OUTPUTS: list each return type with one-line description; repeat .OUTPUTS per type; must match [OutputType()] and actual returns
.NOTES only if critical (constraints, side effects, security, version compatibility, breaking behavior), ≤2 short sentences
Avoid aliases; use full command names
Avoid Write-Host; prefer Write-Verbose/Write-Information/etc.
Avoid Write-Output; use return instead
Do not use ConvertTo-SecureString -AsPlainText in production code
Do not redefine reserved parameters (Verbose, Debug, etc.)
In...

Files:

  • tests/Unit/Public/Remove-SqlDscDatabase.Tests.ps1
  • tests/Integration/Commands/Get-SqlDscRole.Integration.Tests.ps1
  • source/Public/New-SqlDscRole.ps1
  • source/Public/Remove-SqlDscDatabase.ps1
  • source/Public/Remove-SqlDscRole.ps1
**/*.{ps1,psm1,psd1}

📄 CodeRabbit inference engine (.github/instructions/dsc-community-style-guidelines-powershell.instructions.md)

**/*.{ps1,psm1,psd1}: Indent with 4 spaces; do not use tabs
No spaces on empty lines
Try to limit lines to 120 characters
Empty hashtable is @{}
Hashtable: each property on its own line with proper indentation
Hashtable property names use PascalCase
End files with exactly one blank line
Use line endings as defined by .gitattributes policy
Allow at most two consecutive newlines
No trailing whitespace on any line
Use UTF-8 encoding without BOM for all files

Files:

  • tests/Unit/Public/Remove-SqlDscDatabase.Tests.ps1
  • tests/Integration/Commands/Get-SqlDscRole.Integration.Tests.ps1
  • source/Public/New-SqlDscRole.ps1
  • source/Public/Remove-SqlDscDatabase.ps1
  • source/Public/Remove-SqlDscRole.ps1
tests/[Uu]nit/**/*.[Tt]ests.ps1

📄 CodeRabbit inference engine (.github/instructions/dsc-community-style-guidelines-unit-tests.instructions.md)

tests/[Uu]nit/**/*.[Tt]ests.ps1: In unit tests, access localized strings using InModuleScope -ScriptBlock { $script:localizedData.Key }
When mocking files in tests, use the $TestDrive variable for file system operations
All public commands must include parameter set validation tests
Include the exact Pester setup block before Describe: SuppressMessage attribute with param (); BeforeDiscovery to ensure DscResource.Test is available (fallback to build.ps1 -Tasks 'noop') and Import-Module; BeforeAll to set $script:moduleName, import the module, and set PSDefaultParameterValues for InModuleScope/Mock/Should; AfterAll to remove those defaults and unload the tested module
Use the provided Parameter Set Validation test template to assert command ParameterSetName and full parameter list string; for multiple parameter sets, supply multiple hashtables via -ForEach
Use the Parameter Properties template to assert a parameter is mandatory via $parameterInfo = (Get-Command -Name 'CommandName').Parameters['ParameterName']; $parameterInfo.Attributes.Mandatory | Should -BeTrue

Files:

  • tests/Unit/Public/Remove-SqlDscDatabase.Tests.ps1

⚙️ CodeRabbit configuration file

tests/[Uu]nit/**/*.[Tt]ests.ps1: # Unit Tests Guidelines

  • Test with localized strings: Use InModuleScope -ScriptBlock { $script:localizedData.Key }
  • Mock files: Use $TestDrive variable (path to the test drive)
  • All public commands require parameter set validation tests
  • After modifying classes, always run tests in new session (for changes to take effect)

Test Setup Requirements

Use this exact setup block before Describe:

[System.Diagnostics.CodeAnalysis.SuppressMessageAttribute('PSUseDeclaredVarsMoreThanAssignments', '', Justification = 'Suppressing this rule because Script Analyzer does not understand Pester syntax.')]
param ()

BeforeDiscovery {
    try
    {
        if (-not (Get-Module -Name 'DscResource.Test'))
        {
            # Assumes dependencies have been resolved, so if this module is not available, run 'noop' task.
            if (-not (Get-Module -Name 'DscResource.Test' -ListAvailable))
            {
                # Redirect all streams to $null, except the error stream (stream 2)
                & "$PSScriptRoot/../../../build.ps1" -Tasks 'noop' 3>&1 4>&1 5>&1 6>&1 > $null
            }

            # If the dependencies have not been resolved, this will throw an error.
            Import-Module -Name 'DscResource.Test' -Force -ErrorAction 'Stop'
        }
    }
    catch [System.IO.FileNotFoundException]
    {
        throw 'DscResource.Test module dependency not found. Please run ".\build.ps1 -ResolveDependency -Tasks noop" first.'
    }
}

BeforeAll {
    $script:moduleName = '{MyModuleName}'

    Import-Module -Name $script:moduleName -Force -ErrorAction 'Stop'

    $PSDefaultParameterValues['InModuleScope:ModuleName'] = $script:moduleName
    $PSDefaultParameterValues['Mock:ModuleName'] = $script:moduleName
    $PSDefaultParameterValues['Should:ModuleName'] = $script:moduleName
}

AfterAll {
    $PSDefaultParameterValues.Remove('InModuleScope:ModuleName')
    $PSDefaultParameterValues.Remove('Mock:ModuleNam...

Files:

  • tests/Unit/Public/Remove-SqlDscDatabase.Tests.ps1
**/*.ps1

📄 CodeRabbit inference engine (.github/instructions/dsc-community-style-guidelines.instructions.md)

Follow PowerShell style and test guideline instructions strictly

Files:

  • tests/Unit/Public/Remove-SqlDscDatabase.Tests.ps1
  • tests/Integration/Commands/Get-SqlDscRole.Integration.Tests.ps1
  • source/Public/New-SqlDscRole.ps1
  • source/Public/Remove-SqlDscDatabase.ps1
  • source/Public/Remove-SqlDscRole.ps1
tests/Unit/{Classes,Public,Private}/*.Tests.ps1

📄 CodeRabbit inference engine (.github/instructions/dsc-community-style-guidelines.instructions.md)

Add unit tests for all commands, functions, and resources

Files:

  • tests/Unit/Public/Remove-SqlDscDatabase.Tests.ps1
**

⚙️ CodeRabbit configuration file

**: # DSC Community Guidelines

Terminology

  • Command: Public command
  • Function: Private function
  • Resource: DSC class-based resource

Build & Test Workflow Requirements

  • Run PowerShell script files from repository root
  • Setup build and test environment (once per pwsh session): ./build.ps1 -Tasks noop
  • Build project before running tests: ./build.ps1 -Tasks build
  • Always run tests in new pwsh session: Invoke-Pester -Path @({test paths}) -Output Detailed

File Organization

  • Public commands: source/Public/{CommandName}.ps1
  • Private functions: source/Private/{FunctionName}.ps1
  • Unit tests: tests/Unit/{Classes|Public|Private}/{Name}.Tests.ps1
  • Integration tests: tests/Integration/Commands/{CommandName}.Integration.Tests.ps1

Requirements

  • Follow instructions over existing code patterns
  • Follow PowerShell style and test guideline instructions strictly
  • Always update CHANGELOG.md Unreleased section
  • Localize all strings using string keys; remove any orphaned string keys
  • Check DscResource.Common before creating private functions
  • Separate reusable logic into private functions
  • DSC resources should always be created as class-based resources
  • Add unit tests for all commands/functions/resources
  • Add integration tests for all public commands and resources

Files:

  • tests/Unit/Public/Remove-SqlDscDatabase.Tests.ps1
  • tests/Unit/Stubs/SMO.cs
  • tests/Integration/Commands/Get-SqlDscRole.Integration.Tests.ps1
  • source/Public/New-SqlDscRole.ps1
  • source/Public/Remove-SqlDscDatabase.ps1
  • source/Public/Remove-SqlDscRole.ps1
{**/*.ps1,**/*.psm1,**/*.psd1}

⚙️ CodeRabbit configuration file

{**/*.ps1,**/*.psm1,**/*.psd1}: # PowerShell Guidelines

Naming

  • Use descriptive names (3+ characters, no abbreviations)
  • Functions: PascalCase with Verb-Noun format using approved verbs
  • Parameters: PascalCase
  • Variables: camelCase
  • Keywords: lower-case
  • Classes: PascalCase
  • Include scope for script/global/environment variables: $script:, $global:, $env:

File naming

  • Class files: ###.ClassName.ps1 format (e.g. 001.SqlReason.ps1, 004.StartupParameters.ps1)

Formatting

Indentation & Spacing

  • Use 4 spaces (no tabs)
  • One space around operators: $a = 1 + 2
  • One space between type and variable: [String] $name
  • One space between keyword and parenthesis: if ($condition)
  • No spaces on empty lines
  • Try to limit lines to 120 characters

Braces

  • Newline before opening brace (except variable assignments)
  • One newline after opening brace
  • Two newlines after closing brace (one if followed by another brace or continuation)

Quotes

  • Use single quotes unless variable expansion is needed: 'text' vs "text $variable"

Arrays

  • Single line: @('one', 'two', 'three')
  • Multi-line: each element on separate line with proper indentation
  • Do not use the unary comma operator (,) in return statements to force
    an array

Hashtables

  • Empty: @{}
  • Each property on separate line with proper indentation
  • Properties: Use PascalCase

Comments

  • Single line: # Comment (capitalized, on own line)
  • Multi-line: <# Comment #> format (opening and closing brackets on own line), and indent text
  • No commented-out code

Comment-based help

  • Always add comment-based help to all functions and scripts
  • Comment-based help: SYNOPSIS, DESCRIPTION (40+ chars), PARAMETER, EXAMPLE sections before function/class
  • Comment-based help indentation: keywords 4 spaces, text 8 spaces
  • Include examples for all parameter sets and combinations
  • INPUTS: List each pipeline‑accepted type (one per line) with a 1‑line description...

Files:

  • tests/Unit/Public/Remove-SqlDscDatabase.Tests.ps1
  • tests/Integration/Commands/Get-SqlDscRole.Integration.Tests.ps1
  • source/Public/New-SqlDscRole.ps1
  • source/Public/Remove-SqlDscDatabase.ps1
  • source/Public/Remove-SqlDscRole.ps1
tests/Integration/Commands/*.Integration.Tests.ps1

📄 CodeRabbit inference engine (.github/instructions/dsc-community-style-guidelines.instructions.md)

tests/Integration/Commands/*.Integration.Tests.ps1: Place integration tests for public commands in tests/Integration/Commands/{CommandName}.Integration.Tests.ps1
Add integration tests for all public commands (and resources)

Place command integration tests at tests/Integration/Commands/{CommandName}.Integration.Tests.ps1

Files:

  • tests/Integration/Commands/Get-SqlDscRole.Integration.Tests.ps1
tests/[iI]ntegration/**/*.[iI]ntegration.[tT]ests.ps1

📄 CodeRabbit inference engine (.github/instructions/dsc-community-style-guidelines-integration-tests.instructions.md)

tests/[iI]ntegration/**/*.[iI]ntegration.[tT]ests.ps1: Do not use mocking in integration tests; run against a real environment
Cover all scenarios and code paths in integration tests
Use Get-ComputerName to determine computer names in CI
Avoid using -ExpectedMessage with Should -Throw assertions
Call commands with -Force where applicable to avoid prompting
Use -ErrorAction 'Stop' on commands so failures surface immediately
Include the required Pester setup block (SuppressMessage param, BeforeDiscovery loading DscResource.Test, and BeforeAll importing the module)

Files:

  • tests/Integration/Commands/Get-SqlDscRole.Integration.Tests.ps1

⚙️ CodeRabbit configuration file

tests/[iI]ntegration/**/*.[iI]ntegration.[tT]ests.ps1: # Integration Tests Guidelines

Requirements

  • Location Commands: tests/Integration/Commands/{CommandName}.Integration.Tests.ps1
  • Location Resources: tests/Integration/Resources/{ResourceName}.Integration.Tests.ps1
  • No mocking - real environment only
  • Cover all scenarios and code paths
  • Use Get-ComputerName for computer names in CI
  • Avoid ExpectedMessage for Should -Throw assertions
  • Only run integration tests in CI unless explicitly instructed.
  • Call commands with -Force parameter where applicable (avoids prompting).
  • Use -ErrorAction 'Stop' on commands so failures surface immediately

Required Setup Block

[System.Diagnostics.CodeAnalysis.SuppressMessageAttribute('PSUseDeclaredVarsMoreThanAssignments', '', Justification = 'Suppressing this rule because Script Analyzer does not understand Pester syntax.')]
param ()

BeforeDiscovery {
    try
    {
        if (-not (Get-Module -Name 'DscResource.Test'))
        {
            # Assumes dependencies have been resolved, so if this module is not available, run 'noop' task.
            if (-not (Get-Module -Name 'DscResource.Test' -ListAvailable))
            {
                # Redirect all streams to $null, except the error stream (stream 2)
                & "$PSScriptRoot/../../../build.ps1" -Tasks 'noop' 3>&1 4>&1 5>&1 6>&1 > $null
            }

            # If the dependencies have not been resolved, this will throw an error.
            Import-Module -Name 'DscResource.Test' -Force -ErrorAction 'Stop'
        }
    }
    catch [System.IO.FileNotFoundException]
    {
        throw 'DscResource.Test module dependency not found. Please run ".\build.ps1 -ResolveDependency -Tasks noop" first.'
    }
}

BeforeAll {
    $script:moduleName = '{MyModuleName}'

    Import-Module -Name $script:moduleName -Force -ErrorAction 'Stop'
}

Files:

  • tests/Integration/Commands/Get-SqlDscRole.Integration.Tests.ps1
source/**/*.ps1

📄 CodeRabbit inference engine (.github/instructions/dsc-community-style-guidelines-localization.instructions.md)

source/**/*.ps1: Localize all Write-Debug, Write-Verbose, Write-Error, Write-Warning, and $PSCmdlet.ThrowTerminatingError() messages
Use localized string keys instead of hardcoded strings in script output/messages
Assume and use $script:localizedData for accessing localized strings
When emitting messages, reference $script:localizedData.KeyName and format with the -f operator (e.g., Write-Verbose -Message ($script:localizedData.KeyName -f $value1))

Files:

  • source/Public/New-SqlDscRole.ps1
  • source/Public/Remove-SqlDscDatabase.ps1
  • source/Public/Remove-SqlDscRole.ps1

⚙️ CodeRabbit configuration file

source/**/*.ps1: # Localization Guidelines

Requirements

  • Localize all Write-Debug, Write-Verbose, Write-Error, Write-Warning and $PSCmdlet.ThrowTerminatingError() messages
  • Use localized string keys, not hardcoded strings
  • Assume $script:localizedData is available

String Files

  • Commands/functions: source/en-US/{MyModuleName}.strings.psd1
  • Class resources: source/en-US/{ResourceClassName}.strings.psd1

Key Naming Patterns

  • Format: Verb_FunctionName_Action (underscore separators), e.g. Get_Database_ConnectingToDatabase

String Format

ConvertFrom-StringData @'
    KeyName = Message with {0} placeholder. (PREFIX0001)
'@

String IDs

  • Format: (PREFIX####)
  • PREFIX: First letter of each word in class or function name (SqlSetup → SS, Get-SqlDscDatabase → GSDD)
  • Number: Sequential from 0001

Usage

Write-Verbose -Message ($script:localizedData.KeyName -f $value1)

Files:

  • source/Public/New-SqlDscRole.ps1
  • source/Public/Remove-SqlDscDatabase.ps1
  • source/Public/Remove-SqlDscRole.ps1
source/Public/*.ps1

📄 CodeRabbit inference engine (.github/instructions/dsc-community-style-guidelines.instructions.md)

Place public commands in source/Public/{CommandName}.ps1

Files:

  • source/Public/New-SqlDscRole.ps1
  • source/Public/Remove-SqlDscDatabase.ps1
  • source/Public/Remove-SqlDscRole.ps1
🧠 Learnings (5)
📓 Common learnings
Learnt from: CR
PR: dsccommunity/SqlServerDsc#0
File: .github/instructions/dsc-community-style-guidelines-powershell.instructions.md:0-0
Timestamp: 2025-09-16T16:34:27.319Z
Learning: Applies to **/*.{ps1,psm1} : For terminating errors use $PSCmdlet.ThrowTerminatingError() (not in classes); include relevant error category and in catch include exception with localized message
Learnt from: CR
PR: dsccommunity/SqlServerDsc#0
File: .github/instructions/dsc-community-style-guidelines-powershell.instructions.md:0-0
Timestamp: 2025-09-16T16:34:27.319Z
Learning: Applies to **/*.{ps1,psm1} : Use Write-Error for non-terminating errors with -Message (localized), -Category, -ErrorId (unique, matches localized ID), -TargetObject; in catch include -Exception; always return after Write-Error
Learnt from: CR
PR: dsccommunity/SqlServerDsc#0
File: .github/instructions/dsc-community-style-guidelines-mof-resources.instructions.md:0-0
Timestamp: 2025-09-12T13:20:57.155Z
Learning: Applies to source/DSCResources/**/*.psm1 : Do not use throw for terminating errors; instead use New-*Exception helper commands (e.g., New-InvalidDataException, New-ArgumentException, New-InvalidOperationException, New-ObjectNotFoundException, New-InvalidResultException, New-NotImplementedException)
📚 Learning: 2025-09-23T10:20:59.832Z
Learnt from: CR
PR: dsccommunity/SqlServerDsc#0
File: .github/instructions/SqlServerDsc-guidelines.instructions.md:0-0
Timestamp: 2025-09-23T10:20:59.832Z
Learning: Applies to tests/Stubs/SMO.cs : Unit tests that cover classes/commands using SMO types must have those SMO types stubbed in tests/Stubs/SMO.cs

Applied to files:

  • tests/Unit/Stubs/SMO.cs
📚 Learning: 2025-10-12T11:23:30.123Z
Learnt from: CR
PR: dsccommunity/SqlServerDsc#0
File: .github/instructions/dsc-community-style-guidelines-integration-tests.instructions.md:0-0
Timestamp: 2025-10-12T11:23:30.123Z
Learning: Applies to tests/[iI]ntegration/**/*.[iI]ntegration.[tT]ests.ps1 : Avoid using -ExpectedMessage with Should -Throw assertions

Applied to files:

  • tests/Integration/Commands/Get-SqlDscRole.Integration.Tests.ps1
📚 Learning: 2025-09-16T16:34:27.319Z
Learnt from: CR
PR: dsccommunity/SqlServerDsc#0
File: .github/instructions/dsc-community-style-guidelines-powershell.instructions.md:0-0
Timestamp: 2025-09-16T16:34:27.319Z
Learning: Applies to **/*.{ps1,psm1} : Implement Force parameter pattern: if ($Force.IsPresent -and -not $Confirm) { $ConfirmPreference = 'None' }

Applied to files:

  • source/Public/New-SqlDscRole.ps1
  • source/Public/Remove-SqlDscRole.ps1
📚 Learning: 2025-08-18T10:44:38.990Z
Learnt from: johlju
PR: dsccommunity/SqlServerDsc#2132
File: source/Public/New-SqlDscLogin.ps1:254-257
Timestamp: 2025-08-18T10:44:38.990Z
Learning: When implementing Force and Confirm parameter interaction in PowerShell functions with SupportsShouldProcess, use the pattern `if ($Force.IsPresent -and -not $Confirm)` to suppress confirmations. This ensures that explicit `-Confirm:$true` is respected even when `-Force` is present, preserving user intent when they explicitly request confirmation alongside Force.

Applied to files:

  • source/Public/New-SqlDscRole.ps1
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (2)
  • GitHub Check: dsccommunity.SqlServerDsc (Build Package Module)
  • GitHub Check: PSScriptAnalyzer
🔇 Additional comments (16)
source/Public/New-SqlDscRole.ps1 (4)

73-79: LGTM! Force parameter pattern correctly implemented.

The begin block properly implements the Force parameter interaction pattern, ensuring confirmations are suppressed when -Force is present unless the user explicitly specifies -Confirm:$true.

Based on learnings


99-99: LGTM! Error code follows naming convention.

The error code NSDR0001 correctly follows the PREFIX#### format where NSDR is derived from New-SqlDscRole.

As per coding guidelines


106-110: LGTM! ShouldProcess pattern correctly implemented.

The ShouldProcess implementation follows the required pattern with properly named message variables (descriptionMessage, confirmationMessage, captionMessage) and correct localization usage.

As per coding guidelines


132-132: LGTM! Error code maintains consistency.

The error code NSDR0002 maintains consistency with the naming convention and sequential numbering used throughout the file.

As per coding guidelines

tests/Integration/Commands/Get-SqlDscRole.Integration.Tests.ps1 (3)

1-30: LGTM! Required setup block is correct.

The integration test setup follows the required pattern exactly, including the SuppressMessageAttribute, proper BeforeDiscovery block for loading DscResource.Test, and BeforeAll block for importing the module under test.


32-50: LGTM! Test initialization is properly structured.

The test setup correctly establishes a connection to a real SQL Server instance with proper credentials and includes appropriate cleanup in AfterAll to disconnect the server object.


52-126: LGTM! Comprehensive test coverage with proper structure.

The test cases provide excellent coverage of various scenarios:

  • Getting all roles vs. specific roles
  • System roles vs. user-created roles
  • Error handling (both throwing and silently continuing)
  • Refresh parameter behavior
  • Pipeline input

The tests follow Pester v5 syntax correctly with proper naming conventions and no mocking (appropriate for integration tests).

source/Public/Remove-SqlDscRole.ps1 (3)

126-133: Built-in role guard: correct category/ID/target

Good use of InvalidOperation, ID RSDR0002, and targeting the role object. No issues.


136-141: ShouldProcess message pattern is correct and localized

Variables and call signature follow the required pattern. Ensure the caption string has no trailing period and the keys exist in the strings file.

As per coding guidelines.


150-157: Failure path preserves original exception; correct terminating error

Wrapping original exception, using InvalidOperation, and ID RSDR0003 is appropriate. Consider adding/confirming unit tests that assert:

  • $_.CategoryInfo.Category and FullyQualifiedErrorId
  • Exception message localization and inner exception type
  • Behavior of -WhatIf and -Force with/without -Confirm

Based on learnings.

tests/Unit/Public/Remove-SqlDscDatabase.Tests.ps1 (2)

88-90: Good: asserting FullyQualifiedErrorId for system DB path

Adding -ErrorId 'RSDD0001,Remove-SqlDscDatabase' ensures the terminating error is validated precisely.


124-126: Good: ErrorId asserted for DatabaseObject system DB path

Mirrors the command’s RSDD0001 behavior via ThrowTerminatingError.

source/Public/Remove-SqlDscDatabase.ps1 (4)

97-104: Force pattern correctly disables confirmation

Begin-block handles -Force with ConfirmPreference = 'None' when -not $Confirm. Matches module guidance. As per coding guidelines.


118-129: Correct terminating error for not-found database

Uses localized message, ItemNotFoundException, ObjectNotFound category, and ErrorId RSDD0002. TargetObject is the name, which is acceptable. Based on learnings.


137-150: Correct system-database guard as terminating error

Appropriate InvalidOperation, RSDD0001, and localized message.


183-199: Good failure wrapping for drop operation

Localized message, inner exception preservation, InvalidOperation category, and RSDD0005 ErrorId are spot on.

Copy link

@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: 1

🧹 Nitpick comments (5)
tests/Unit/Public/Remove-SqlDscDatabase.Tests.ps1 (3)

83-85: Good use of localized strings and ErrorId assertions.

Fetching the message via InModuleScope and asserting ErrorId aligns with the updated terminating-error semantics. As a stability tweak, you can drop -ExpectedMessage and assert only -ErrorId to reduce brittleness from message text changes.

Also applies to: 88-88


92-95: Same here—test is aligned; consider simplifying assertion.

Pattern is correct. Optionally remove -ExpectedMessage and rely on -ErrorId only for resilience.

Also applies to: 97-97


132-135: Consistent with new behavior; consider adding negative-path coverage.

This assertion is fine. Consider adding unit tests for:

  • Drop-connections failure → RSDD0004
  • Drop failure → RSDD0005

I can scaffold tests if helpful.

Also applies to: 137-137

source/Public/Remove-SqlDscDatabase.ps1 (2)

159-166: Avoid Write-Verbose inside ShouldProcess; prefer Information or move outside.

Guideline says to avoid Write-Verbose inside the ShouldProcess block. Suggest emitting a user-facing status via Write-Information instead.

-                Write-Verbose -Message ($script:localizedData.Database_DroppingConnections -f $Name)
+                Write-Information -MessageData ($script:localizedData.Database_DroppingConnections -f $Name)

Also applies to: 161-161


183-199: Robust failure handling; optional improvement to restore access mode on failure.

Catch converts to a terminating InvalidOperation with inner exception and RSDD0005—good. Optional: best‑effort revert UserAccess back to Multiple if Drop() fails after switching to Single (only when -DropConnections) to avoid leaving the DB in single‑user state.

📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 6c7f034 and 8e28bf0.

📒 Files selected for processing (5)
  • source/Public/Remove-SqlDscDatabase.ps1 (2 hunks)
  • source/en-US/SqlServerDsc.strings.psd1 (2 hunks)
  • tests/Integration/Commands/Get-SqlDscRole.Integration.Tests.ps1 (1 hunks)
  • tests/Unit/Public/Remove-SqlDscDatabase.Tests.ps1 (2 hunks)
  • tests/Unit/Stubs/SMO.cs (1 hunks)
🚧 Files skipped from review as they are similar to previous changes (1)
  • tests/Integration/Commands/Get-SqlDscRole.Integration.Tests.ps1
🧰 Additional context used
📓 Path-based instructions (13)
source/en-US/*.strings.psd1

📄 CodeRabbit inference engine (.github/instructions/dsc-community-style-guidelines-localization.instructions.md)

source/en-US/*.strings.psd1: Store command/function localization in source/en-US/{MyModuleName}.strings.psd1
Store class localization in source/en-US/{ResourceClassName}.strings.psd1
Name localization keys as Verb_FunctionName_Action using underscores (e.g., Get_Database_ConnectingToDatabase)
Define strings using ConvertFrom-StringData with entries like KeyName = Message with {0} placeholder. (PREFIX0001)
Include string IDs in the form (PREFIX####), where PREFIX is initials from the class/function name and numbers are sequential from 0001

Files:

  • source/en-US/SqlServerDsc.strings.psd1
**/*.{ps1,psm1,psd1}

📄 CodeRabbit inference engine (.github/instructions/dsc-community-style-guidelines-powershell.instructions.md)

**/*.{ps1,psm1,psd1}: Indent with 4 spaces; do not use tabs
No spaces on empty lines
Try to limit lines to 120 characters
Empty hashtable is @{}
Hashtable: each property on its own line with proper indentation
Hashtable property names use PascalCase
End files with exactly one blank line
Use line endings as defined by .gitattributes policy
Allow at most two consecutive newlines
No trailing whitespace on any line
Use UTF-8 encoding without BOM for all files

Files:

  • source/en-US/SqlServerDsc.strings.psd1
  • tests/Unit/Public/Remove-SqlDscDatabase.Tests.ps1
  • source/Public/Remove-SqlDscDatabase.ps1
**/*.psd1

📄 CodeRabbit inference engine (.github/instructions/dsc-community-style-guidelines-powershell.instructions.md)

In module manifests, do not use NestedModules for shared commands without specifying RootModule

Files:

  • source/en-US/SqlServerDsc.strings.psd1
**

⚙️ CodeRabbit configuration file

**: # DSC Community Guidelines

Terminology

  • Command: Public command
  • Function: Private function
  • Resource: DSC class-based resource

Build & Test Workflow Requirements

  • Run PowerShell script files from repository root
  • Setup build and test environment (once per pwsh session): ./build.ps1 -Tasks noop
  • Build project before running tests: ./build.ps1 -Tasks build
  • Always run tests in new pwsh session: Invoke-Pester -Path @({test paths}) -Output Detailed

File Organization

  • Public commands: source/Public/{CommandName}.ps1
  • Private functions: source/Private/{FunctionName}.ps1
  • Unit tests: tests/Unit/{Classes|Public|Private}/{Name}.Tests.ps1
  • Integration tests: tests/Integration/Commands/{CommandName}.Integration.Tests.ps1

Requirements

  • Follow instructions over existing code patterns
  • Follow PowerShell style and test guideline instructions strictly
  • Always update CHANGELOG.md Unreleased section
  • Localize all strings using string keys; remove any orphaned string keys
  • Check DscResource.Common before creating private functions
  • Separate reusable logic into private functions
  • DSC resources should always be created as class-based resources
  • Add unit tests for all commands/functions/resources
  • Add integration tests for all public commands and resources

Files:

  • source/en-US/SqlServerDsc.strings.psd1
  • tests/Unit/Public/Remove-SqlDscDatabase.Tests.ps1
  • source/Public/Remove-SqlDscDatabase.ps1
  • tests/Unit/Stubs/SMO.cs
{**/*.ps1,**/*.psm1,**/*.psd1}

⚙️ CodeRabbit configuration file

{**/*.ps1,**/*.psm1,**/*.psd1}: # PowerShell Guidelines

Naming

  • Use descriptive names (3+ characters, no abbreviations)
  • Functions: PascalCase with Verb-Noun format using approved verbs
  • Parameters: PascalCase
  • Variables: camelCase
  • Keywords: lower-case
  • Classes: PascalCase
  • Include scope for script/global/environment variables: $script:, $global:, $env:

File naming

  • Class files: ###.ClassName.ps1 format (e.g. 001.SqlReason.ps1, 004.StartupParameters.ps1)

Formatting

Indentation & Spacing

  • Use 4 spaces (no tabs)
  • One space around operators: $a = 1 + 2
  • One space between type and variable: [String] $name
  • One space between keyword and parenthesis: if ($condition)
  • No spaces on empty lines
  • Try to limit lines to 120 characters

Braces

  • Newline before opening brace (except variable assignments)
  • One newline after opening brace
  • Two newlines after closing brace (one if followed by another brace or continuation)

Quotes

  • Use single quotes unless variable expansion is needed: 'text' vs "text $variable"

Arrays

  • Single line: @('one', 'two', 'three')
  • Multi-line: each element on separate line with proper indentation
  • Do not use the unary comma operator (,) in return statements to force
    an array

Hashtables

  • Empty: @{}
  • Each property on separate line with proper indentation
  • Properties: Use PascalCase

Comments

  • Single line: # Comment (capitalized, on own line)
  • Multi-line: <# Comment #> format (opening and closing brackets on own line), and indent text
  • No commented-out code

Comment-based help

  • Always add comment-based help to all functions and scripts
  • Comment-based help: SYNOPSIS, DESCRIPTION (40+ chars), PARAMETER, EXAMPLE sections before function/class
  • Comment-based help indentation: keywords 4 spaces, text 8 spaces
  • Include examples for all parameter sets and combinations
  • INPUTS: List each pipeline‑accepted type (one per line) with a 1‑line description...

Files:

  • source/en-US/SqlServerDsc.strings.psd1
  • tests/Unit/Public/Remove-SqlDscDatabase.Tests.ps1
  • source/Public/Remove-SqlDscDatabase.ps1
**/*.[Tt]ests.ps1

📄 CodeRabbit inference engine (.github/instructions/dsc-community-style-guidelines-pester.instructions.md)

**/*.[Tt]ests.ps1: All public commands, private functions, and classes must have unit tests
All public commands and class-based resources must have integration tests
Use Pester v5 syntax only
Test code only inside Describe blocks
Assertions only in It blocks
Never test verbose messages, debug messages, or parameter binding behavior
Pass all mandatory parameters to avoid prompts
Inside It blocks, assign unused return objects to $null (unless part of a pipeline)
Call the tested entity from within the It blocks
Keep results and assertions in the same It block
Avoid try/catch/finally for cleanup; use AfterAll or AfterEach
Avoid unnecessary remove/recreate cycles
One Describe block per file matching the tested entity name
Context descriptions start with 'When'
It descriptions start with 'Should' and must not contain 'when'
Mock variables must be prefixed with 'mock'
Public commands: never use InModuleScope (except for retrieving localized strings)
Private functions and class resources: always use InModuleScope
Each class method gets a separate Context block
Each scenario gets a separate Context block
Use nested Context blocks for complex scenarios
Perform mocking in BeforeAll (use BeforeEach only when required)
Place setup/teardown (BeforeAll/BeforeEach/AfterAll/AfterEach) close to usage
Use PascalCase for Pester keywords: Describe, Context, It, Should, BeforeAll, BeforeEach, AfterAll, AfterEach
Use -BeTrue/-BeFalse; never use -Be $true/-Be $false
Never use Assert-MockCalled; use Should -Invoke instead
Do not use Should -Not -Throw; invoke commands directly
Never add an empty -MockWith block
Omit -MockWith when returning $null
Set $PSDefaultParameterValues for Mock:ModuleName, Should:ModuleName, and InModuleScope:ModuleName
Omit the -ModuleName parameter on Pester commands
Never use Mock inside an InModuleScope block
Define variables for -ForEach in a separate BeforeDiscovery near usage
Use -ForEach only on Context and It blocks
Keep variable scope close to the usage c...

Files:

  • tests/Unit/Public/Remove-SqlDscDatabase.Tests.ps1

⚙️ CodeRabbit configuration file

**/*.[Tt]ests.ps1: # Tests Guidelines

Core Requirements

  • All public commands, private functions and classes must have unit tests
  • All public commands and class-based resources must have integration tests
  • Use Pester v5 syntax only
  • Test code only inside Describe blocks
  • Assertions only in It blocks
  • Never test verbose messages, debug messages or parameter binding behavior
  • Pass all mandatory parameters to avoid prompts

Requirements

  • Inside It blocks, assign unused return objects to $null (unless part of pipeline)
  • Tested entity must be called from within the It blocks
  • Keep results and assertions in same It block
  • Avoid try-catch-finally for cleanup, use AfterAll or AfterEach
  • Avoid unnecessary remove/recreate cycles

Naming

  • One Describe block per file matching the tested entity name
  • Context descriptions start with 'When'
  • It descriptions start with 'Should', must not contain 'when'
  • Mock variables prefix: 'mock'

Structure & Scope

  • Public commands: Never use InModuleScope (unless retrieving localized strings)
  • Private functions/class resources: Always use InModuleScope
  • Each class method = separate Context block
  • Each scenario = separate Context block
  • Use nested Context blocks for complex scenarios
  • Mocking in BeforeAll (BeforeEach only when required)
  • Setup/teardown in BeforeAll,BeforeEach/AfterAll,AfterEach close to usage

Syntax Rules

  • PascalCase: Describe, Context, It, Should, BeforeAll, BeforeEach, AfterAll, AfterEach
  • Use -BeTrue/-BeFalse never -Be $true/-Be $false
  • Never use Assert-MockCalled, use Should -Invoke instead
  • No Should -Not -Throw - invoke commands directly
  • Never add an empty -MockWith block
  • Omit -MockWith when returning $null
  • Set $PSDefaultParameterValues for Mock:ModuleName, Should:ModuleName, InModuleScope:ModuleName
  • Omit -ModuleName parameter on Pester commands
  • Never use Mock inside `InModuleSc...

Files:

  • tests/Unit/Public/Remove-SqlDscDatabase.Tests.ps1
tests/Unit/Public/*.Tests.ps1

📄 CodeRabbit inference engine (.github/instructions/dsc-community-style-guidelines-pester.instructions.md)

Public command unit tests must reside in tests/Unit/Public/{Name}.Tests.ps1

Place unit tests for public commands in tests/Unit/Public/{Name}.Tests.ps1

Files:

  • tests/Unit/Public/Remove-SqlDscDatabase.Tests.ps1
**/*.{ps1,psm1}

📄 CodeRabbit inference engine (.github/instructions/dsc-community-style-guidelines-powershell.instructions.md)

**/*.{ps1,psm1}: Use descriptive names (3+ characters, no abbreviations)
Function names use PascalCase Verb-Noun with approved verbs
Parameter names use PascalCase
Variable names use camelCase
Keywords are lower-case
Class names use PascalCase
Include scope prefixes for script/global/environment variables: $script:, $global:, $env:
Use one space around operators (e.g., $a = 1 + 2)
Use one space between type and variable (e.g., [String] $name)
Use one space between keyword and parenthesis (e.g., if ($condition))
Place newline before opening brace (except variable assignments)
One newline after opening brace
Two newlines after closing brace (one if followed by another brace or continuation)
Use single quotes unless variable expansion is needed
Arrays on one line use @('one','two'); multi-line arrays have one element per line with proper indentation
Do not use unary comma in return statements to force an array
Single-line comments: '# Comment' capitalized on its own line
Multi-line comments use <# #> with brackets on their own lines and indented text
No commented-out code
Add comment-based help to all functions and scripts
Comment-based help must include SYNOPSIS, DESCRIPTION (40+ chars), PARAMETER, and EXAMPLE sections before function/class
Comment-based help indentation: keywords at 4 spaces, text at 8 spaces
Include examples for all parameter sets and combinations
INPUTS: list each pipeline-accepted type with one-line description; repeat .INPUTS per type
OUTPUTS: list each return type with one-line description; repeat .OUTPUTS per type; must match [OutputType()] and actual returns
.NOTES only if critical (constraints, side effects, security, version compatibility, breaking behavior), ≤2 short sentences
Avoid aliases; use full command names
Avoid Write-Host; prefer Write-Verbose/Write-Information/etc.
Avoid Write-Output; use return instead
Do not use ConvertTo-SecureString -AsPlainText in production code
Do not redefine reserved parameters (Verbose, Debug, etc.)
In...

Files:

  • tests/Unit/Public/Remove-SqlDscDatabase.Tests.ps1
  • source/Public/Remove-SqlDscDatabase.ps1
tests/[Uu]nit/**/*.[Tt]ests.ps1

📄 CodeRabbit inference engine (.github/instructions/dsc-community-style-guidelines-unit-tests.instructions.md)

tests/[Uu]nit/**/*.[Tt]ests.ps1: In unit tests, access localized strings using InModuleScope -ScriptBlock { $script:localizedData.Key }
When mocking files in tests, use the $TestDrive variable for file system operations
All public commands must include parameter set validation tests
Include the exact Pester setup block before Describe: SuppressMessage attribute with param (); BeforeDiscovery to ensure DscResource.Test is available (fallback to build.ps1 -Tasks 'noop') and Import-Module; BeforeAll to set $script:moduleName, import the module, and set PSDefaultParameterValues for InModuleScope/Mock/Should; AfterAll to remove those defaults and unload the tested module
Use the provided Parameter Set Validation test template to assert command ParameterSetName and full parameter list string; for multiple parameter sets, supply multiple hashtables via -ForEach
Use the Parameter Properties template to assert a parameter is mandatory via $parameterInfo = (Get-Command -Name 'CommandName').Parameters['ParameterName']; $parameterInfo.Attributes.Mandatory | Should -BeTrue

Files:

  • tests/Unit/Public/Remove-SqlDscDatabase.Tests.ps1

⚙️ CodeRabbit configuration file

tests/[Uu]nit/**/*.[Tt]ests.ps1: # Unit Tests Guidelines

  • Test with localized strings: Use InModuleScope -ScriptBlock { $script:localizedData.Key }
  • Mock files: Use $TestDrive variable (path to the test drive)
  • All public commands require parameter set validation tests
  • After modifying classes, always run tests in new session (for changes to take effect)

Test Setup Requirements

Use this exact setup block before Describe:

[System.Diagnostics.CodeAnalysis.SuppressMessageAttribute('PSUseDeclaredVarsMoreThanAssignments', '', Justification = 'Suppressing this rule because Script Analyzer does not understand Pester syntax.')]
param ()

BeforeDiscovery {
    try
    {
        if (-not (Get-Module -Name 'DscResource.Test'))
        {
            # Assumes dependencies have been resolved, so if this module is not available, run 'noop' task.
            if (-not (Get-Module -Name 'DscResource.Test' -ListAvailable))
            {
                # Redirect all streams to $null, except the error stream (stream 2)
                & "$PSScriptRoot/../../../build.ps1" -Tasks 'noop' 3>&1 4>&1 5>&1 6>&1 > $null
            }

            # If the dependencies have not been resolved, this will throw an error.
            Import-Module -Name 'DscResource.Test' -Force -ErrorAction 'Stop'
        }
    }
    catch [System.IO.FileNotFoundException]
    {
        throw 'DscResource.Test module dependency not found. Please run ".\build.ps1 -ResolveDependency -Tasks noop" first.'
    }
}

BeforeAll {
    $script:moduleName = '{MyModuleName}'

    Import-Module -Name $script:moduleName -Force -ErrorAction 'Stop'

    $PSDefaultParameterValues['InModuleScope:ModuleName'] = $script:moduleName
    $PSDefaultParameterValues['Mock:ModuleName'] = $script:moduleName
    $PSDefaultParameterValues['Should:ModuleName'] = $script:moduleName
}

AfterAll {
    $PSDefaultParameterValues.Remove('InModuleScope:ModuleName')
    $PSDefaultParameterValues.Remove('Mock:ModuleNam...

Files:

  • tests/Unit/Public/Remove-SqlDscDatabase.Tests.ps1
**/*.ps1

📄 CodeRabbit inference engine (.github/instructions/dsc-community-style-guidelines.instructions.md)

Follow PowerShell style and test guideline instructions strictly

Files:

  • tests/Unit/Public/Remove-SqlDscDatabase.Tests.ps1
  • source/Public/Remove-SqlDscDatabase.ps1
tests/Unit/{Classes,Public,Private}/*.Tests.ps1

📄 CodeRabbit inference engine (.github/instructions/dsc-community-style-guidelines.instructions.md)

Add unit tests for all commands, functions, and resources

Files:

  • tests/Unit/Public/Remove-SqlDscDatabase.Tests.ps1
source/**/*.ps1

📄 CodeRabbit inference engine (.github/instructions/dsc-community-style-guidelines-localization.instructions.md)

source/**/*.ps1: Localize all Write-Debug, Write-Verbose, Write-Error, Write-Warning, and $PSCmdlet.ThrowTerminatingError() messages
Use localized string keys instead of hardcoded strings in script output/messages
Assume and use $script:localizedData for accessing localized strings
When emitting messages, reference $script:localizedData.KeyName and format with the -f operator (e.g., Write-Verbose -Message ($script:localizedData.KeyName -f $value1))

Files:

  • source/Public/Remove-SqlDscDatabase.ps1

⚙️ CodeRabbit configuration file

source/**/*.ps1: # Localization Guidelines

Requirements

  • Localize all Write-Debug, Write-Verbose, Write-Error, Write-Warning and $PSCmdlet.ThrowTerminatingError() messages
  • Use localized string keys, not hardcoded strings
  • Assume $script:localizedData is available

String Files

  • Commands/functions: source/en-US/{MyModuleName}.strings.psd1
  • Class resources: source/en-US/{ResourceClassName}.strings.psd1

Key Naming Patterns

  • Format: Verb_FunctionName_Action (underscore separators), e.g. Get_Database_ConnectingToDatabase

String Format

ConvertFrom-StringData @'
    KeyName = Message with {0} placeholder. (PREFIX0001)
'@

String IDs

  • Format: (PREFIX####)
  • PREFIX: First letter of each word in class or function name (SqlSetup → SS, Get-SqlDscDatabase → GSDD)
  • Number: Sequential from 0001

Usage

Write-Verbose -Message ($script:localizedData.KeyName -f $value1)

Files:

  • source/Public/Remove-SqlDscDatabase.ps1
source/Public/*.ps1

📄 CodeRabbit inference engine (.github/instructions/dsc-community-style-guidelines.instructions.md)

Place public commands in source/Public/{CommandName}.ps1

Files:

  • source/Public/Remove-SqlDscDatabase.ps1
🧠 Learnings (3)
📓 Common learnings
Learnt from: CR
PR: dsccommunity/SqlServerDsc#0
File: .github/instructions/dsc-community-style-guidelines-powershell.instructions.md:0-0
Timestamp: 2025-09-16T16:34:27.319Z
Learning: Applies to **/*.{ps1,psm1} : For terminating errors use $PSCmdlet.ThrowTerminatingError() (not in classes); include relevant error category and in catch include exception with localized message
Learnt from: CR
PR: dsccommunity/SqlServerDsc#0
File: .github/instructions/dsc-community-style-guidelines-powershell.instructions.md:0-0
Timestamp: 2025-09-16T16:34:27.319Z
Learning: Applies to **/*.{ps1,psm1} : Use Write-Error for non-terminating errors with -Message (localized), -Category, -ErrorId (unique, matches localized ID), -TargetObject; in catch include -Exception; always return after Write-Error
Learnt from: CR
PR: dsccommunity/SqlServerDsc#0
File: .github/instructions/dsc-community-style-guidelines-mof-resources.instructions.md:0-0
Timestamp: 2025-09-12T13:20:57.155Z
Learning: Applies to source/DSCResources/**/*.psm1 : Do not use throw for terminating errors; instead use New-*Exception helper commands (e.g., New-InvalidDataException, New-ArgumentException, New-InvalidOperationException, New-ObjectNotFoundException, New-InvalidResultException, New-NotImplementedException)
📚 Learning: 2025-10-12T11:23:30.123Z
Learnt from: CR
PR: dsccommunity/SqlServerDsc#0
File: .github/instructions/dsc-community-style-guidelines-integration-tests.instructions.md:0-0
Timestamp: 2025-10-12T11:23:30.123Z
Learning: Applies to tests/[iI]ntegration/**/*.[iI]ntegration.[tT]ests.ps1 : Avoid using -ExpectedMessage with Should -Throw assertions

Applied to files:

  • tests/Unit/Public/Remove-SqlDscDatabase.Tests.ps1
📚 Learning: 2025-09-23T10:20:59.832Z
Learnt from: CR
PR: dsccommunity/SqlServerDsc#0
File: .github/instructions/SqlServerDsc-guidelines.instructions.md:0-0
Timestamp: 2025-09-23T10:20:59.832Z
Learning: Applies to tests/Stubs/SMO.cs : Unit tests that cover classes/commands using SMO types must have those SMO types stubbed in tests/Stubs/SMO.cs

Applied to files:

  • tests/Unit/Stubs/SMO.cs
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (3)
  • GitHub Check: dsccommunity.SqlServerDsc (Build Package Module)
  • GitHub Check: PSScriptAnalyzer
  • GitHub Check: PSScriptAnalyzer
🔇 Additional comments (10)
tests/Unit/Stubs/SMO.cs (1)

166-176: LGTM! Proper stub enum addition.

The DatabaseUserAccess enum is correctly defined with appropriate values that match SQL Server's database user access modes (Multiple, Single, Restricted). The stub follows the established pattern in the file and will properly support testing for the affected cmdlets.

source/Public/Remove-SqlDscDatabase.ps1 (6)

97-104: Force pattern implemented correctly.

Setting ConfirmPreference to 'None' when -Force and not -Confirm matches the guideline.


120-129: Terminating not‑found error is correct and localized.

Using ItemNotFoundException, ObjectNotFound category, target = Name, and RSDD0002 looks right.


137-150: System-database guard is correct.

Appropriate InvalidOperation with RSDD0001; good early exit.


152-157: ShouldProcess messages follow the required pattern.

description/confirmation/caption variables and call ordering match the style guideline.


163-181: Drop-connections failure path looks good.

Throws terminating InvalidOperation with inner exception and RSDD0004; target object is DatabaseObject—good.


152-156: FQID shape verified—all error paths correctly use RSDD000x pattern.

All four ThrowTerminatingError calls in the file use ErrorIds that follow the required pattern:

  • Line 125: RSDD0002
  • Line 145: RSDD0001
  • Line 175: RSDD0004
  • Line 194: RSDD0005

When thrown from Remove-SqlDscDatabase, PowerShell automatically constructs the FullyQualifiedErrorId as RSDD000x,Remove-SqlDscDatabase, matching the test assertion shape.

source/en-US/SqlServerDsc.strings.psd1 (3)

317-317: Prefix fix for Get-SqlDscRole not‑found looks good.

GSDR0001 under the Get‑SqlDscRole section resolves the earlier prefix mismatch.


323-325: ShouldProcess text normalization is consistent.

Description/Confirmation keys for role creation match new pattern.


330-335: Remove‑SqlDscRole messages are correctly aligned with RSDR prefix.

Verification confirms all localization keys are properly defined in source/en-US/SqlServerDsc.strings.psd1 (lines 330–334) and consistently referenced in the public commands:

  • RSDR0001: Remove_SqlDscRole_NotFound (used in Remove-SqlDscRole.ps1)
  • RSDR0002: Role_CannotRemoveBuiltIn (used in Remove-SqlDscRole.ps1)
  • RSDR0003: Role_RemoveFailed (used in Remove-SqlDscRole.ps1)
  • ShouldProcess keys correctly defined without trailing periods
  • GSDR0001: Get_SqlDscRole_NotFound (used in Get-SqlDscRole.ps1)

All naming conventions followed; no orphaned keys or mismatches detected.

Copy link
Member Author

@johlju johlju left a comment

Choose a reason for hiding this comment

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

:lgtm:

@johlju reviewed 7 of 10 files at r1, 5 of 10 files at r3, 5 of 5 files at r4, all commit messages.
Reviewable status: :shipit: complete! all files reviewed, all discussions resolved (waiting on @johlju)

@johlju johlju merged commit 5454f55 into dsccommunity:main Oct 22, 2025
49 checks passed
@johlju johlju deleted the fix/issue-#2200 branch October 22, 2025 15:05
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment