Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
39 commits
Select commit Hold shift + click to select a range
458ee31
Add Test-SqlDscIsAgentAlert function to validate SQL Agent Alerts
johlju Sep 8, 2025
194945a
Update OUTPUTS section in guidelines for clarity and add alias usage …
johlju Sep 8, 2025
6766bf8
Clarify instructions for running scripts in PowerShell by specifying …
johlju Sep 8, 2025
9da75ea
Clarify changelog guidelines by specifying to skip adding entries for…
johlju Sep 8, 2025
d7fe31e
Refactor alert existence check in New-SqlDscAgentAlert function to us…
johlju Sep 8, 2025
2efd2cf
Update changelog to reflect renaming of Test-SqlDscAgentAlert to Test…
johlju Sep 8, 2025
e6c1778
Remove unnecessary empty SuppressMessage attributes from test files
johlju Sep 9, 2025
7c74739
Enhance error handling guidelines by specifying required parameters f…
johlju Sep 9, 2025
5c2cfaf
Remove unnecessary SuppressMessage attribute from unit test guidelines
johlju Sep 9, 2025
0c132b3
Update SqlServerDsc guidelines to clarify requirements and improve st…
johlju Sep 9, 2025
26f3f4b
Add Viscalyx.Common module for development and testing
johlju Sep 9, 2025
051a08d
Add Test-SqlDscAgentAlertProperty function and associated tests for v…
johlju Sep 9, 2025
bdb4d30
Refactor Test-SqlDscIsAgentAlert to simplify parameter handling and r…
johlju Sep 9, 2025
09dac6d
Update references in SMO.cs to use Test-SqlDscIsAgentAlert for consis…
johlju Sep 9, 2025
69ec72d
Add Test-SqlDscAgentAlertProperty command and update Test-SqlDscIsAge…
johlju Sep 9, 2025
bd6da11
Add Test-SqlDscAgentAlertProperty integration test to pipeline
johlju Sep 9, 2025
3aa0891
Return $false instead of just returning when the SQL Agent Alert is n…
johlju Sep 9, 2025
207d5bb
Add -ErrorAction 'Stop' to Test-SqlDscAgentAlertProperty calls and ha…
johlju Sep 9, 2025
d19ffa5
Add -ErrorAction 'Stop' to Test-SqlDscAgentAlertProperty calls to ens…
johlju Sep 9, 2025
e32bc7d
Add -ErrorAction 'Stop' to Get-SqlDscAgentAlert calls in Test-SqlDscA…
johlju Sep 9, 2025
463b05f
Add -ErrorAction 'Stop' to Test-SqlDscIsAgentAlert calls for improved…
johlju Sep 9, 2025
2fc75de
Add environment variable setup and cleanup in BeforeAll and AfterAll …
johlju Sep 9, 2025
995818b
Add Test-SqlDscAgentAlertProperty to integration tests run order
johlju Sep 9, 2025
dad271f
Add environment variable setup and cleanup in BeforeAll and AfterAll …
johlju Sep 9, 2025
38132cd
Update build environment instructions for clarity
johlju Sep 9, 2025
98cba99
Update Test-SqlDscIsAgentAlert message for clarity by removing redund…
johlju Sep 9, 2025
e80d0b1
Remove unnecessary comment from Test-SqlDscIsAgentAlert function
johlju Sep 9, 2025
6bc9f58
Fix path formatting in build instructions for consistency across guid…
johlju Sep 9, 2025
c91efae
Update error ID for Test-SqlDscAgentAlertProperty to maintain consist…
johlju Sep 9, 2025
a411af0
Update INPUTS and OUTPUTS sections for clarity and consistency in com…
johlju Sep 9, 2025
4274176
Merge branch 'main' into f/2202-test-sqldscisagentalert
johlju Sep 13, 2025
91d4e6f
Update test assertions to use 'Test-SqlDscIsAgentAlert' instead of 'G…
johlju Sep 13, 2025
ce2fd39
Clarify SqlServerDsc-specific guidelines in copilot instructions
johlju Sep 13, 2025
b54b0f1
Add guideline for passing original exception in catch blocks
johlju Sep 13, 2025
231c23a
Refine Build & Test Workflow section in community guidelines for clar…
johlju Sep 13, 2025
74b9634
Refine Build & Test Workflow requirements for clarity and consistency
johlju Sep 13, 2025
7cf071c
Fix typo in Build & Test Workflow requirements for consistency
johlju Sep 13, 2025
dd3d326
Remove unnecessary ValidateNotNullOrEmpty attribute from Name paramet…
johlju Sep 13, 2025
e9d788c
Update tests for non-existent alerts to expect exceptions instead of …
johlju Sep 13, 2025
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion .github/copilot-instructions.md
Original file line number Diff line number Diff line change
@@ -1,2 +1,2 @@
# Requirements
- SqlServerDsc-specific guidelines override general project guidelines
- SqlServerDsc-specific guidelines and requirements override general project guidelines and requirements
12 changes: 10 additions & 2 deletions .github/instructions/SqlServerDsc-guidelines.instructions.md
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,15 @@ description: SqlServerDsc-specific guidelines for AI development.
applyTo: "**"
---

# SqlServerDsc Guidelines
# SqlServerDsc Requirements

## 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`
- Run tests without coverage (wildcards allowed): `Invoke-PesterJob -Path '{tests filepath}' -SkipCodeCoverage`
- Run QA tests: `Invoke-PesterJob -Path 'tests/QA' -SkipCodeCoverage`
- Never run integration tests locally

## Naming
- Public commands: `{Verb}-SqlDsc{Noun}` format
Expand All @@ -25,7 +33,7 @@ applyTo: "**"
- Reporting Services: instance `SSRS`
- Power BI Report Server: instance `PBIRS`

## Test Requirements
## Tests Requirements
- Unit tests: Add `$env:SqlServerDscCI = $true` in `BeforeAll`, remove in `AfterAll`
- Integration tests:
- If requiring SQL Server DB, start the Windows service in `BeforeAll`, stop it in `AfterAll`.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,4 +10,5 @@ applyTo: "CHANGELOG.md"
- Describe notable changes briefly, ≤2 items per change type
- Reference issues using format [issue #<issue_number>](https://github.com/<owner>/<repo>/issues/<issue_number>)
- No empty lines between list items in same section
- Do not add item if there are already an existing item for the same change
- Skip adding entry if same change already exists in Unreleased section
- No duplicate sections or items in Unreleased section
Original file line number Diff line number Diff line change
Expand Up @@ -64,8 +64,8 @@ applyTo: "**/*.ps?(m|d)1"
- 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.
- OUTPUTS: List each return type (one per line) with a 1‑line description. Must match both [OutputType()] and actual returns.
- INPUTS: List each pipeline‑accepted type (one per line) with a 1‑line description. Repeat keyword for each input type.
- OUTPUTS: List each return type (one per line) with a 1‑line description. Repeat keyword for each output type. Must match both `[OutputType()]` and actual returns.
- .NOTES: Include only if it conveys critical info (constraints, side effects, security, version compatibility, breaking behavior). Keep to ≤2 short sentences.

## Functions
Expand All @@ -83,6 +83,7 @@ applyTo: "**/*.ps?(m|d)1"
- Inside `$PSCmdlet.ShouldProcess`-block, avoid using `Write-Verbose`
- Never use backtick as line continuation in production code.
- Set `$ErrorActionPreference = 'Stop'` before commands using `-ErrorAction 'Stop'`; restore previous value directly after invocation (do not use try-catch-finally)
- Use `[Alias()]` attribute for function aliases, never `Set-Alias` or `New-Alias`

## Output streams

Expand All @@ -92,7 +93,10 @@ applyTo: "**/*.ps?(m|d)1"
- Use `Write-Information` for: User-facing status updates; Important operational messages; Non-error state changes
- Use `Write-Warning` for: Non-fatal issues requiring attention; Deprecated functionality usage; Configuration problems that don't block execution
- Use `$PSCmdlet.ThrowTerminatingError()` for terminating errors (except for classes), use relevant error category, in try-catch include exception with localized message
- Use `Write-Error` for non-terminating errors, use relevant error category; always use `return` after `Write-Error` to avoid further processing
- Use `Write-Error` for non-terminating errors
- Always include `-Message` (localized string), `-Category` (relevant error category), `-ErrorId` (unique ID matching localized string ID), `-TargetObject` (object causing error)
- In catch blocks, pass original exception using `-Exception`
- Always use `return` after `Write-Error` to avoid further processing

## ShouldProcess Required Pattern

Expand Down Expand Up @@ -134,14 +138,25 @@ if ($Force.IsPresent -and -not $Confirm)
Parameter description

.INPUTS
TypeName
TypeName1

Description
Description1

.INPUTS
TypeName2

Description2

.OUTPUTS
TypeName
TypeName1

Description1

.OUTPUTS
TypeName2

Description2

Description
#>
function Get-Something
{
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,10 +10,11 @@ applyTo: "**"
- **Function**: Private function
- **Resource**: DSC class-based resource

## Build & Test Workflow
- Run in PowerShell, from repository root
- Build before running tests: `.\build.ps1 -Tasks build`
- Always run tests in new PowerShell session: `Invoke-Pester -Path @({test paths}) -Output Detailed`
## 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`
Expand Down
19 changes: 18 additions & 1 deletion CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -92,7 +92,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
`Remove-SqlDscRole`, and `Remove-SqlDscLogin` commands for retrieving and managing
SQL Server logins and roles with support for refresh, pipeline input, and ShouldProcess.
- Added `Get-SqlDscAgentAlert`, `New-SqlDscAgentAlert`,
`Set-SqlDscAgentAlert`, `Remove-SqlDscAgentAlert`, and `Test-SqlDscAgentAlert`
`Set-SqlDscAgentAlert`, `Remove-SqlDscAgentAlert`, and `Test-SqlDscIsAgentAlert`
to manage SQL Agent alerts on a Database Engine instance.
- Added new public commands for SQL Agent Operator management:
- `Get-SqlDscAgentOperator` - Get SQL Agent Operators from a SQL Server
Expand All @@ -115,6 +115,12 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
patterns
- Database objects can also be used as pipeline input for Set and Remove operations
- Commands include comprehensive validation, localization, and ShouldProcess support
- `Test-SqlDscAgentAlertProperty`
- New command to test specific properties of SQL Agent alerts.
- Supports testing severity and message ID properties.
- Requires at least one property parameter to be specified.
- Supports pipeline input of
`[Microsoft.SqlServer.Management.Smo.Agent.Alert]` objects.
- Added private function `Get-CommandParameter` to filter command parameters
by excluding specified parameter names and common parameters, providing a
reusable way to determine settable properties on objects.
Expand Down Expand Up @@ -197,6 +203,17 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
- `source/Examples/Resources/SqlSetup/5-InstallNamedInstanceInFailoverClusterSecondNode.ps1`
- Removed redundant `$SqlAdministratorCredential` parameter from example
configuration.
- `New-SqlDscAgentAlert`
- Updated the command to use `Test-SqlDscIsAgentAlert` instead of directly
calling `Get-AgentAlertObject` when checking if an alert already exists
(issue [#2202](https://github.com/dsccommunity/SqlServerDsc/issues/2202)).
- `Test-SqlDscIsAgentAlert`
- Removed optional `Severity` and `MessageId` parameters - use
`Test-SqlDscAgentAlertProperty` instead for property testing.
- Now only tests for alert existence.
- Added support for pipeline input of
`[Microsoft.SqlServer.Management.Smo.Agent.Alert]` objects.
- Updated examples and documentation to reflect the simplified functionality.

## [17.1.0] - 2025-05-22

Expand Down
3 changes: 3 additions & 0 deletions RequiredModules.psd1
Original file line number Diff line number Diff line change
Expand Up @@ -66,4 +66,7 @@
}
}
PlatyPS = 'latest'

# For development
'Viscalyx.Common' = 'latest' # Invoke-PesterJob to run tests
}
3 changes: 2 additions & 1 deletion azure-pipelines.yml
Original file line number Diff line number Diff line change
Expand Up @@ -316,7 +316,8 @@ stages:
'tests/Integration/Commands/Get-SqlDscAgentAlert.Integration.Tests.ps1'
'tests/Integration/Commands/New-SqlDscAgentAlert.Integration.Tests.ps1'
'tests/Integration/Commands/Set-SqlDscAgentAlert.Integration.Tests.ps1'
'tests/Integration/Commands/Test-SqlDscAgentAlert.Integration.Tests.ps1'
'tests/Integration/Commands/Test-SqlDscAgentAlertProperty.Integration.Tests.ps1'
'tests/Integration/Commands/Test-SqlDscIsAgentAlert.Integration.Tests.ps1'
'tests/Integration/Commands/Get-SqlDscAgentOperator.Integration.Tests.ps1'
'tests/Integration/Commands/New-SqlDscAgentOperator.Integration.Tests.ps1'
'tests/Integration/Commands/Set-SqlDscAgentOperator.Integration.Tests.ps1'
Expand Down
4 changes: 2 additions & 2 deletions source/Public/New-SqlDscAgentAlert.ps1
Original file line number Diff line number Diff line change
Expand Up @@ -105,9 +105,9 @@ function New-SqlDscAgentAlert
Assert-BoundParameter -BoundParameterList $PSBoundParameters -MutuallyExclusiveList1 @('Severity') -MutuallyExclusiveList2 @('MessageId')

# Check if alert already exists
$existingAlert = Get-AgentAlertObject -ServerObject $ServerObject -Name $Name
$alertExists = Test-SqlDscIsAgentAlert -ServerObject $ServerObject -Name $Name

if ($existingAlert)
if ($alertExists)
{
$errorMessage = $script:localizedData.New_SqlDscAgentAlert_AlertAlreadyExists -f $Name

Expand Down
Original file line number Diff line number Diff line change
@@ -1,17 +1,21 @@
<#
.SYNOPSIS
Tests if a SQL Agent Alert exists and has the desired properties.
Tests if a SQL Agent Alert has the specified properties.

.DESCRIPTION
This command tests if a SQL Agent Alert exists on a SQL Server Database Engine
instance and optionally validates its properties.
This command tests if a SQL Agent Alert on a SQL Server Database Engine
instance has the specified properties. At least one property parameter
must be specified.

.PARAMETER ServerObject
Specifies current server connection object.

.PARAMETER Name
Specifies the name of the SQL Agent Alert to test.

.PARAMETER AlertObject
Specifies the SQL Agent Alert object to test.

.PARAMETER Severity
Specifies the expected severity level for the SQL Agent Alert. Valid range is 0 to 25.
If specified, the command will return $true only if the alert exists and has this severity.
Expand All @@ -25,43 +29,52 @@

SQL Server Database Engine instance object.

.INPUTS
Microsoft.SqlServer.Management.Smo.Agent.Alert

SQL Agent Alert object.

.OUTPUTS
[System.Boolean]

.EXAMPLE
$serverObject = Connect-SqlDscDatabaseEngine -InstanceName 'MyInstance'
Test-SqlDscAgentAlert -ServerObject $serverObject -Name 'MyAlert'
Test-SqlDscAgentAlertProperty -ServerObject $serverObject -Name 'MyAlert' -Severity 16

Tests if the SQL Agent Alert named 'MyAlert' exists.
Tests if the SQL Agent Alert named 'MyAlert' exists and has severity level 16.

.EXAMPLE
$serverObject = Connect-SqlDscDatabaseEngine -InstanceName 'MyInstance'
$serverObject | Test-SqlDscAgentAlert -Name 'MyAlert' -Severity 16
$serverObject | Test-SqlDscAgentAlertProperty -Name 'MyAlert' -MessageId 50001

Tests if the SQL Agent Alert named 'MyAlert' exists and has severity level 16.
Tests if the SQL Agent Alert named 'MyAlert' exists and has message ID 50001.

.EXAMPLE
$serverObject = Connect-SqlDscDatabaseEngine -InstanceName 'MyInstance'
$serverObject | Test-SqlDscAgentAlert -Name 'MyAlert' -MessageId 50001
$alertObject = $serverObject | Get-SqlDscAgentAlert -Name 'MyAlert'
$alertObject | Test-SqlDscAgentAlertProperty -Severity 16

Tests if the SQL Agent Alert named 'MyAlert' exists and has message ID 50001.
Tests if the SQL Agent Alert has severity level 16 using alert object pipeline input.
#>
function Test-SqlDscAgentAlert
function Test-SqlDscAgentAlertProperty
{
[System.Diagnostics.CodeAnalysis.SuppressMessageAttribute('UseSyntacticallyCorrectExamples', '', Justification = 'Because the rule does not yet support parsing the code when a parameter type is not available. The ScriptAnalyzer rule UseSyntacticallyCorrectExamples will always error in the editor due to https://github.com/indented-automation/Indented.ScriptAnalyzerRules/issues/8.')]
[CmdletBinding()]
[CmdletBinding(DefaultParameterSetName = 'ByServerAndName')]
[OutputType([System.Boolean])]
param
(
[Parameter(Mandatory = $true, ValueFromPipeline = $true)]
[Parameter(ParameterSetName = 'ByServerAndName', Mandatory = $true, ValueFromPipeline = $true)]
[Microsoft.SqlServer.Management.Smo.Server]
$ServerObject,

[Parameter(Mandatory = $true)]
[ValidateNotNullOrEmpty()]
[Parameter(ParameterSetName = 'ByServerAndName', Mandatory = $true)]
[System.String]
$Name,

[Parameter(ParameterSetName = 'ByAlertObject', Mandatory = $true, ValueFromPipeline = $true)]
[Microsoft.SqlServer.Management.Smo.Agent.Alert]
$AlertObject,

[Parameter()]
[ValidateRange(0, 25)]
[System.Int32]
Expand All @@ -73,65 +86,51 @@ function Test-SqlDscAgentAlert
$MessageId
)

# cSpell: ignore TSAA
# cSpell: ignore TSAAP
process
{
# Ensure at least one property parameter is specified
Assert-BoundParameter -BoundParameterList $PSBoundParameters -AtLeastOneList @('Severity', 'MessageId')

# Validate that both Severity and MessageId are not specified
Assert-BoundParameter -BoundParameterList $PSBoundParameters -MutuallyExclusiveList1 @('Severity') -MutuallyExclusiveList2 @('MessageId')

Write-Verbose -Message ($script:localizedData.Test_SqlDscAgentAlert_TestingAlert -f $Name)

$alertObject = Get-AgentAlertObject -ServerObject $ServerObject -Name $Name

if ($null -eq $alertObject)
if ($PSCmdlet.ParameterSetName -eq 'ByAlertObject')
{
Write-Verbose -Message ($script:localizedData.Test_SqlDscAgentAlert_AlertNotFound -f $Name)

return $false
$alertObject = $AlertObject
}
else
{
$alertObject = Get-AgentAlertObject -ServerObject $ServerObject -Name $Name

Write-Verbose -Message ($script:localizedData.Test_SqlDscAgentAlert_AlertFound -f $Name)
if ($null -eq $alertObject)
{
$errorMessage = $script:localizedData.Test_SqlDscAgentAlertProperty_AlertNotFound -f $Name

# If no specific properties are specified, just return true (alert exists)
if (-not $PSBoundParameters.ContainsKey('Severity') -and -not $PSBoundParameters.ContainsKey('MessageId'))
{
Write-Verbose -Message ($script:localizedData.Test_SqlDscAgentAlert_NoPropertyTest)
Write-Error -Message $errorMessage -Category 'ObjectNotFound' -ErrorId 'TSDAAP0001' -TargetObject $Name

return $true
return $false
}
}

# Test severity if specified
if ($PSBoundParameters.ContainsKey('Severity'))
{
if ($alertObject.Severity -ne $Severity)
{
Write-Verbose -Message ($script:localizedData.Test_SqlDscAgentAlert_SeverityMismatch -f $alertObject.Severity, $Severity)

return $false
}
else
{
Write-Verbose -Message ($script:localizedData.Test_SqlDscAgentAlert_SeverityMatch -f $Severity)
}
}

# Test message ID if specified
if ($PSBoundParameters.ContainsKey('MessageId'))
{
if ($alertObject.MessageId -ne $MessageId)
{
Write-Verbose -Message ($script:localizedData.Test_SqlDscAgentAlert_MessageIdMismatch -f $alertObject.MessageId, $MessageId)

return $false
}
else
{
Write-Verbose -Message ($script:localizedData.Test_SqlDscAgentAlert_MessageIdMatch -f $MessageId)
}
}

Write-Verbose -Message ($script:localizedData.Test_SqlDscAgentAlert_AllTestsPassed -f $Name)

return $true
}
}
Loading
Loading