Skip to content

Install-DbaCommunitySoftware - add unified community tooling installer (do Install-DbaCommunitySoftware) - #10565

Merged
potatoqualitee merged 6 commits into
developmentfrom
install-dbacommunitysoftware
Aug 13, 2026
Merged

Install-DbaCommunitySoftware - add unified community tooling installer (do Install-DbaCommunitySoftware)#10565
potatoqualitee merged 6 commits into
developmentfrom
install-dbacommunitysoftware

Conversation

@potatoqualitee

Copy link
Copy Markdown
Member

What this does

Adds Install-DbaCommunitySoftware, the install-side counterpart to Save-DbaCommunitySoftware. That command already unifies the download step behind one -Software parameter; this does the same for installing, so you don't need to remember six separate command names.

Install-DbaCommunitySoftware -SqlInstance sql2017 -Software All
Install-DbaCommunitySoftware -SqlInstance sql2017 -Software FirstResponderKit, WhoIsActive -Database DBAtools
Software Installer
MaintenanceSolution Install-DbaMaintenanceSolution
FirstResponderKit Install-DbaFirstResponderKit
DarlingData Install-DbaDarlingData
SQLWATCH Install-DbaSqlWatch
WhoIsActive Install-DbaWhoIsActive
DbaMultiTool Install-DbaMultiTool

The -Software names match Save-DbaCommunitySoftware so the download and install steps read the same way.

Design notes

  • Output is pass-through and unshaped. The installers don't agree on a shape — MaintenanceSolution returns Results with no Database/Name/Status, SQLWATCH returns DashboardPath and no Name, and WhoIsActive carries a Version. All three variants are documented in .OUTPUTS rather than normalized away.
  • Forwarding is derived, not hardcoded. Each target's real parameter list decides what gets passed, so -Branch reaches only the three tools that have one and a warning names any selection it was dropped from.
  • -Database and -Branch forward only when explicitly bound, so each installer keeps its own default otherwise — notably SqlWatch, which defaults to the SQLWATCH database and would be silently relocated by an unconditional -Database master.
  • ShouldProcess is declared but not called at this level, so -WhatIf/-Confirm flow down and prompt once instead of twice.
  • AzSqlTips is excluded on purposeSave-DbaCommunitySoftware downloads it, but Invoke-DbaDbAzSqlTip consumes it as a query rather than installing procedures.

Two behaviors deliberately differ from calling an installer yourself, both documented in the help:

  1. WhoIsActive is given master when -Database is omitted. Called directly with no database it opens an interactive Show-DbaDbList picker, which would stall an unattended run.
  2. A failure against one tool warns and continues rather than ending the batch.

Testing

18 tests, run against SQL Server 2022. 18 passed, 0 failed, 0 skipped.

Integration coverage spans multi-tool dispatch, single-tool pass-through, continuation past an unreachable instance (a real unreachable host ordered ahead of a live one — no mocks), -Branch warning, and -WhatIf asserting the side effect did not happen.

Two edge cases are covered because they were live bugs during development:

  • -Database "" reached Install-DbaWhoIsActive's own if (-not $Database) test and opened the interactive picker. Now rejected at binding.
  • Select-Object -Unique compares case-sensitively on both 5.1 and 7, while ValidateSet accepts any casing — so -Software WhoIsActive, whoisactive installed twice and falsely tripped the single-tool -LocalFile guard. Deduplication is now case-insensitive and order-preserving.

The WhoIsActive-defaults-to-master test never touches a master.dbo.sp_WhoisActive it did not create; it installs only when the procedure is absent and reports itself skipped otherwise, since an encrypted procedure has no recoverable definition and permissions do not survive a drop.

Verified under both PowerShell 5.1 and 7. Invoke-DbatoolsFormatter and PSScriptAnalyzer are clean.

🤖 Generated with Claude Code

claude added 6 commits August 13, 2026 12:28
Adds the install-side counterpart to Save-DbaCommunitySoftware, which already
unifies the download step behind one -Software parameter. One command now
installs the Maintenance Solution, First Responder Kit, DarlingData, SqlWatch,
sp_WhoIsActive and the DBA MultiTool, instead of six command names to remember.

Each tool is dispatched to its own installer and the objects that installer
emits are passed straight back, unshaped. Forwarding is worked out from the
target's actual parameter list rather than a hardcoded map, so -Branch reaches
only the three tools that have it and a warning names any selection it was
dropped for. -Database and -Branch are forwarded only when explicitly bound,
which leaves each installer on its own default otherwise.

Two behaviors differ from calling an installer directly, both documented in
the help: WhoIsActive is given master when Database is omitted, since it
otherwise opens an interactive picker that would stall an unattended run, and
a failure against one tool warns and continues rather than ending the batch.

ShouldProcess is declared but deliberately not called at this level, so
-WhatIf and -Confirm flow down to the installers and prompt once rather than
twice.

AzSqlTips is excluded on purpose. Save-DbaCommunitySoftware downloads it, but
Invoke-DbaDbAzSqlTip consumes it as a query rather than installing procedures.

(do Install-DbaCommunitySoftware)

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Install-DbaSqlWatch is available everywhere, so saying SQLWATCH cannot be
selected on Linux or macOS was wrong. public/ is dot-sourced wholesale and
dbatools.psd1 exports the command unconditionally; the $script:windowsonly
list it appears in is only read inside a PSVersion.Major -lt 5 branch, which
never runs on 5.1 or 7. The missing-installer message covers a broken import,
which is the case that can actually reach it.

(do Install-DbaCommunitySoftware)

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Install-DbaSqlWatch supports Windows PowerShell only, but its edition check
sits in process while the download it needs runs in begin, so calling it from
Core fetches the payload over the network and only then refuses. Selecting All
from PowerShell Core paid for that on every run.

SQLWATCH is now dropped before dispatch with a warning naming it, and the rest
of the batch continues. Selecting it on its own stops with a clear message
instead of silently doing nothing.

Covered on Core with a real call, not a mock: SQLWATCH plus WhoIsActive warns
and returns exactly the WhoIsActive row.

(do Install-DbaCommunitySoftware)

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
…nces

Every installer downloads its payload in begin and loops instances in process,
so dispatching per instance fetched the same archive once per target - and with
Force, redownloaded it every time. Collect instances in process and dispatch
from end instead.

Also drop SQLWATCH on PowerShell Core before the LocalFile count check, so
losing it can leave a single tool holding the file rather than failing a
selection that is no longer ambiguous, and reject a whitespace-only Database
up front rather than quietly redirecting it to master.

(do Install-DbaCommunitySoftware)
Absence of the downstream Core refusal message also fits a download that failed
before it could warn, so check the SQLWATCH cache directory instead. Force makes
Install-DbaSqlWatch refresh that directory unconditionally in begin, and
Save-DbaCommunitySoftware deletes and recreates it, so an unchanged write time
can only mean the installer was never entered. Verified the sentinel can trip.

Also cover the whitespace Database guard, which ValidateNotNullOrEmpty lets
through and the existing empty-string test never reached.

(do Install-DbaCommunitySoftware)
…filter

Dropping SQLWATCH on PowerShell Core left the guard counting survivors, so
-Software SQLWATCH,WhoIsActive -LocalFile sqlwatch.zip saw one tool, passed, and
handed the SqlWatch archive to Install-DbaWhoIsActive. Count what the caller
asked for instead: an archive belongs to one named tool however many of them
can run on this edition.

Verified against the pre-fix code, where the call reached Install-DbaWhoIsActive
and failed on its own LocalFile ValidateScript rather than on the guard.

(do Install-DbaCommunitySoftware)
@potatoqualitee

Copy link
Copy Markdown
Member Author

Mayyybe in 3.0, I'll make all the sub commands internal 🤔

@potatoqualitee
potatoqualitee merged commit 7b2ad85 into development Aug 13, 2026
21 checks passed
@potatoqualitee
potatoqualitee deleted the install-dbacommunitysoftware branch August 13, 2026 13:17
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants