diff --git a/.claude/settings.local.json b/.claude/settings.local.json index 4cd927b3..4ca5dfd2 100644 --- a/.claude/settings.local.json +++ b/.claude/settings.local.json @@ -1,7 +1,6 @@ { - "model": "opus", + "model": "sonnet", "cleanupPeriodDays": 30, - "dangerously-skip-permissions": true, "permissions": { "defaultMode": "bypassPermissions", "allow": ["*"], diff --git a/.devcontainer/devcontainer.json b/.devcontainer/devcontainer.json index e6da3300..5b528f28 100644 --- a/.devcontainer/devcontainer.json +++ b/.devcontainer/devcontainer.json @@ -52,7 +52,9 @@ } }, "terminal.integrated.shell.linux": "pwsh", - "terminal.integrated.defaultProfile.linux": "pwsh" + "terminal.integrated.defaultProfile.linux": "pwsh", + "powershell.developer.editorServicesLogLevel": "Error", + "powershell.integratedConsole.suppressStartupBanner": true }, "extensions": [ "ms-vscode.powershell", diff --git a/.devcontainer/scripts/profile.ps1 b/.devcontainer/scripts/profile.ps1 index e69de29b..bbf4ee49 100644 --- a/.devcontainer/scripts/profile.ps1 +++ b/.devcontainer/scripts/profile.ps1 @@ -0,0 +1 @@ +$env:POWERSHELL_UPDATECHECK = 'Off' diff --git a/.github/workflows/build-release.yml b/.github/workflows/build-release.yml index e422526b..482c94c2 100644 --- a/.github/workflows/build-release.yml +++ b/.github/workflows/build-release.yml @@ -21,8 +21,32 @@ on: required: false jobs: + linux-build: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v4 + + - name: Setup .NET + uses: actions/setup-dotnet@v4 + with: + dotnet-version: | + 8.0.x + 6.0.x + + - name: Build core/lib + shell: pwsh + run: | + ./build/build.ps1 -CoreOnly + + - name: Upload Linux artifacts + uses: actions/upload-artifact@v4 + with: + name: core-lib-linux + path: artifacts/dbatools.library/core/lib/ + build-windows: runs-on: windows-latest + needs: linux-build steps: - name: Checkout code @@ -45,7 +69,23 @@ jobs: shell: pwsh run: | # Run the build script - .\build\build.ps1 + .\build\build.ps1 -BuildZip + + - name: Download Linux artifacts + uses: actions/download-artifact@v4 + with: + name: core-lib-linux + path: artifacts/core-lib-linux/ + + - name: Extract core-lib-linux artifact and copy to core/lib + shell: pwsh + run: Copy-Item -Path "artifacts/core-lib-linux/*" -Destination "artifacts/dbatools.library/core/lib" -Recurse -Force + + - name: Ensure sqlpackage is executable + shell: pwsh + run: | + chmod +x ./artifacts/dbatools.library/core/lib/dac/linux/sqlpackage + chmod +x ./artifacts/dbatools.library/core/lib/dac/mac/sqlpackage - name: Verify critical files and directories shell: pwsh @@ -56,14 +96,13 @@ jobs: $criticalPaths = @( "desktop\lib", "desktop\lib\runtimes\win-x64\native", + "core\lib\dac\windows", "desktop\third-party", "core\lib", "core\lib\runtimes\win-x64\native", - "core\lib\dac\windows", "core\lib\dac\linux", "core\lib\dac\mac", - "core\third-party", - "private" + "core\third-party" ) $missingPaths = @() @@ -110,7 +149,7 @@ jobs: path: artifacts/dbatools.library.zip test-sqlpackage: - name: Test SqlPackage on ${{ matrix.os }} + name: Test sqlpackage on ${{ matrix.os }} runs-on: ${{ matrix.os }} needs: build-windows strategy: @@ -144,7 +183,7 @@ jobs: exit 1 } - - name: Test SqlPackage + - name: Test sqlpackage shell: pwsh run: | # Import the built module @@ -158,71 +197,68 @@ jobs: Write-Host "Module loaded successfully with version: $($module.Version)" Write-Host "Module path: $($module.ModuleBase)" - # Determine SqlPackage path based on OS + # Determine sqlpackage path based on OS $modulePath = $module.ModuleBase - if ($IsWindows -or $PSVersionTable.PSVersion.Major -eq 5) { - Write-Host "Testing Windows SqlPackage..." - $dacPath = Join-Path $modulePath "core/lib/dac/windows" - $sqlPackageName = "SqlPackage.exe" - } elseif ($IsLinux) { - Write-Host "Testing Linux SqlPackage..." - $dacPath = Join-Path $modulePath "core/lib/dac/linux" - $sqlPackageName = "SqlPackage" - } elseif ($IsMacOS) { - Write-Host "Testing macOS SqlPackage..." - $dacPath = Join-Path $modulePath "core/lib/dac/mac" - $sqlPackageName = "SqlPackage" - } else { - Write-Error "Unknown operating system" - exit 1 - } + $sqlPackageName = @( + (Join-Path $modulePath "desktop/lib/dac/SqlPackage.exe"), + (Join-Path $modulePath "core/lib/dac/windows/sqlpackage.exe"), + (Join-Path $modulePath "core/lib/dac/linux/sqlpackage"), + (Join-Path $modulePath "core/lib/dac/mac/sqlpackage") + ) - # Check if SqlPackage directory exists - if (-not (Test-Path $dacPath)) { - Write-Error "SqlPackage directory not found: $dacPath" - Write-Host "Available directories in core/lib:" - Get-ChildItem (Join-Path $modulePath "core/lib") -Directory | ForEach-Object { Write-Host " - $($_.Name)" } - exit 1 + foreach ($sqlPackage in $sqlPackageName) { + if (Test-Path $sqlPackage) { + Write-Host "Found sqlpackage at: $sqlPackage" + } else { + Write-Warning "sqlpackage not found: $sqlPackage" + Write-Host "Available directories in module" + Get-ChildItem $modulePath -Recurse | Where-Object Name -match sqlpack | Select-Object Fullname + } } - # Check if SqlPackage executable exists - $sqlPackagePath = Join-Path $dacPath $sqlPackageName - if (-not (Test-Path $sqlPackagePath)) { - Write-Error "SqlPackage executable not found: $sqlPackagePath" - Write-Host "Files in $dacPath :" - Get-ChildItem $dacPath | ForEach-Object { Write-Host " - $($_.Name)" } - exit 1 + $sqlPackagePath = if ($IsMacOS) { + Join-Path $modulePath "core/lib/dac/mac/sqlpackage" + } elseif ($IsLinux) { + Join-Path $modulePath "core/lib/dac/linux/sqlpackage" + } else { + # if core then core + if ($PSVersionTable.PSEdition -eq 'Core') { + Join-Path $modulePath "core/lib/dac/windows/sqlpackage.exe" + } else { + # if desktop then desktop + Join-Path $modulePath "desktop/lib/dac/SqlPackage.exe" + } } - Write-Host "SqlPackage found at: $sqlPackagePath" + Write-Host "Using sqlpackage at: $sqlPackagePath" - # Make SqlPackage executable on non-Windows platforms + # Make sqlpackage executable on non-Windows platforms if ($IsLinux -or $IsMacOS) { chmod +x $sqlPackagePath } - # Test SqlPackage execution + # Test sqlpackage execution try { - Write-Host "Testing SqlPackage execution..." + Write-Host "Testing sqlpackage execution..." $versionOutput = & $sqlPackagePath /Version 2>&1 - Write-Host "SqlPackage version: $versionOutput" + Write-Host "sqlpackage version: $versionOutput" # Basic functionality test - show help - Write-Host "`nTesting SqlPackage help command..." + Write-Host "`nTesting sqlpackage help command..." $helpOutput = & $sqlPackagePath /? 2>&1 | Select-Object -First 10 $helpOutput | ForEach-Object { Write-Host $_ } Write-Host "... (output truncated)" # Verify expected output from help $helpString = $helpOutput -join "`n" - if ($helpString -match "Specifies a name value pair" -or $helpString -match "SqlPackage" -or $helpString -match "Command") { - Write-Host "`nSqlPackage test completed successfully!" + if ($helpString -match "Specifies a name value pair" -or $helpString -match "sqlpackage" -or $helpString -match "Command") { + Write-Host "`nsqlpackage test completed successfully!" } else { - Write-Error "SqlPackage help output does not contain expected content" + Write-Error "sqlpackage help output does not contain expected content" exit 1 } } catch { - Write-Error "Failed to execute SqlPackage: $_" + Write-Error "Failed to execute sqlpackage: $_" exit 1 } @@ -252,7 +288,7 @@ jobs: } # Download dbatools from GitHub - $branch = "${{ github.event.inputs.dbatools_branch || 'newver' }}" + $branch = "${{ github.event.inputs.dbatools_branch || 'newestver' }}" Write-Host "Downloading dbatools from GitHub (branch: $branch)..." $zipUrl = "https://github.com/dataplat/dbatools/archive/refs/heads/$branch.zip" @@ -309,17 +345,20 @@ jobs: Write-Host "Importing dbatools..." Import-Module dbatools -Force - Write-Host "Testing Get-DbaManagementObject..." + Write-Host "Testing Connect-DbaInstance..." try { - $result = Get-DbaManagementObject - Write-Host "Test passed: Get-DbaManagementObject ran without fail" + $result = Connect-DbaInstance -SqlInstance localhost } catch { - Write-Error "Test failed with exception: $_" - exit 1 + if ($PSItem.Exception.Message -notmatch "not accessible") { + Write-Error "Test failed with exception: $_" + exit 1 + } else { + Write-Host "Test failed successfully (lol) with inaccessible instance message: $($PSItem.Exception.Message)" -ForegroundColor Green + } } create-preview-release: - needs: [build-windows, test-sqlpackage] + needs: [linux-build, build-windows, test-sqlpackage] runs-on: windows-latest # Create release if manually triggered OR if version contains "preview" if: github.event_name == 'workflow_dispatch' || github.event_name == 'push' diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 93593d50..6f728773 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -5,14 +5,42 @@ defaults: run: shell: pwsh jobs: - # Linux tests are disabled - build-core.ps1 script not found - # Keeping Windows build test only for now + linux-build: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v4 + + - name: Setup .NET + uses: actions/setup-dotnet@v4 + with: + dotnet-version: | + 8.0.x + 6.0.x + + - name: Build core/lib + shell: pwsh + run: | + ./build/build.ps1 -CoreOnly + + - name: Upload Linux artifacts + uses: actions/upload-artifact@v4 + with: + name: core-lib-linux + path: artifacts/dbatools.library/core/lib/ + windows-tests: runs-on: windows-latest + needs: linux-build steps: - uses: actions/checkout@v4 + - name: Download Linux artifacts + uses: actions/download-artifact@v4 + with: + name: core-lib-linux + path: artifacts/dbatools.library/core/lib/ + - name: Setup .NET uses: actions/setup-dotnet@v4 with: @@ -31,6 +59,13 @@ jobs: run: | ./build/build.ps1 + - name: Copy Linux core/lib files + shell: pwsh + run: | + Copy-Item -Path artifacts/core-lib-linux/* -Destination artifacts/dbatools.library/core/lib/ -Recurse -Force + # delete windows sqlpackage on core cuz its the same as desktop + Remove-Item -Path artifacts/dbatools.library/core/lib/dac/windows -Recurse -Force -ErrorAction Ignore + - name: Verify critical files and directories shell: pwsh run: | @@ -39,15 +74,14 @@ jobs: $artifactsDir = "./artifacts/dbatools.library" $criticalPaths = @( "desktop\lib", + "desktop\lib\dac", "desktop\lib\runtimes\win-x64\native", "desktop\third-party", "core\lib", "core\lib\runtimes\win-x64\native", - "core\lib\dac\windows", "core\lib\dac\linux", "core\lib\dac\mac", - "core\third-party", - "private" + "core\third-party" ) $missingPaths = @() diff --git a/.gitignore b/.gitignore index 331a2b42..deedfe37 100644 --- a/.gitignore +++ b/.gitignore @@ -40,3 +40,4 @@ lib/ .devcontainer/.env dbatools.library.zip /artifacts +.roo/mcp.json diff --git a/.roo/mcp.json b/.roo/mcp.json deleted file mode 100644 index 1f1b22aa..00000000 --- a/.roo/mcp.json +++ /dev/null @@ -1,11 +0,0 @@ -{ - "mcpServers": { - "brave-search": { - "command": "npx", - "args": [ - "-y", - "@modelcontextprotocol/server-brave-search" - ] - } - } -} \ No newline at end of file diff --git a/CLAUDE.md b/CLAUDE.md index e8e119d3..ca602285 100644 --- a/CLAUDE.md +++ b/CLAUDE.md @@ -91,7 +91,7 @@ Get-DbatoolsLoadedAssembly 1. **Clean**: Removes previous build artifacts 2. **Compile**: Builds C# projects for both target frameworks 3. **Package Dependencies**: Downloads and extracts: - - SQL Server DacFramework (SqlPackage) + - SQL Server DacFramework (sqlpackage) - Third-party NuGet packages (Bogus, LumenWorks CSV) - XESmartTarget for Extended Events 4. **Platform Distribution**: Copies assemblies to appropriate platform directories @@ -159,17 +159,20 @@ This file provides guidance to Claude Code (claude.ai/code) when working with co ## Development Commands ### Testing + +> **Note:** The following test commands reference Appveyor and Windows PowerShell scripts. For modern Linux/macOS/PowerShell Core setups or non-Appveyor CI, substitute with appropriate Pester/Invoke-Pester commands, and paths using forward slashes as needed. + ```powershell -# Run all tests +# Run all tests (legacy, Windows/Appveyor) .\tests\appveyor.pester.ps1 -# Run tests with code coverage +# Run tests with code coverage (Windows/Appveyor) .\tests\appveyor.pester.ps1 -IncludeCoverage -# Run specific test file +# Run specific test file (cross-platform) Invoke-Pester ./tests/Get-DbaDatabase.Tests.ps1 -# Finalize test results +# Finalize test results (Windows/Appveyor) .\tests\appveyor.pester.ps1 -Finalize ``` diff --git a/build/build.ps1 b/build/build.ps1 index 92b6a435..7f424286 100644 --- a/build/build.ps1 +++ b/build/build.ps1 @@ -1,9 +1,10 @@ param( - [switch]$NoZip + [switch]$BuildZip, + [switch]$CoreOnly ) $PSDefaultParameterValues["*:Force"] = $true $PSDefaultParameterValues["*:Confirm"] = $false - +$ProgressPreference = "SilentlyContinue" # Import MSI waiting functions . "$PSScriptRoot\Wait-MsiInstall.ps1" @@ -15,8 +16,6 @@ if (-not $scriptroot) { $root = Split-Path -Path $scriptroot Push-Location $root -Write-Warning $root - # Update module version to today's date $today = Get-Date -Format "yyyy.M.d" $psd1Path = Join-Path $root "dbatools.library.psd1" @@ -80,61 +79,79 @@ Write-Host "Copying .NET 8 output with preserved structure..." $null = New-Item -ItemType Directory -Path (Join-Path $libPath "core/lib") -Force Copy-Item -Path "$tempCorePublish\*" -Destination (Join-Path $libPath "core/lib") -Recurse -Force -# Handle legacy lib/release output directory if it exists (for backward compatibility) -$legacyReleaseDir = Join-Path $root "lib\release" -if (Test-Path $legacyReleaseDir) { - Write-Host "Found legacy lib/release directory, copying to artifacts/release" -ForegroundColor Yellow - $artifactsReleaseDir = Join-Path $artifactsDir "release" - $null = New-Item -ItemType Directory -Path $artifactsReleaseDir -Force - Copy-Item -Path "$legacyReleaseDir\*" -Destination $artifactsReleaseDir -Recurse -Force +# Verify and organize runtime dependencies +Write-Host "Verifying .NET 8 runtime dependencies..." +$coreRuntimesPath = Join-Path $libPath "core\lib\runtimes" +$desktopRuntimesPath = Join-Path $libPath "desktop\lib\runtimes" - # Inform about the change - Write-Host "NOTE: The lib directory in the root is deprecated. Please use artifacts/release instead." -ForegroundColor Yellow -} +# Ensure desktop runtimes directory exists +New-Item -ItemType Directory -Path $desktopRuntimesPath -Force | Out-Null -# Verify core runtime dependencies -Write-Host "Verifying .NET 8 runtime dependencies..." -$sniPath = Join-Path $libPath "core\lib\runtimes\win-x64\native\Microsoft.Data.SqlClient.SNI.dll" -if (Test-Path $sniPath) { - $sniBase = Join-Path $libPath "core\lib\runtimes" - $targetBase = Join-Path $libPath "desktop\lib\runtimes" +if (Test-Path $coreRuntimesPath) { + Write-Host "Core runtimes folder found. Processing native dependencies..." -ForegroundColor Green $architectures = @("win-x86", "win-x64", "win-arm", "win-arm64") foreach ($arch in $architectures) { - $sniPath = Join-Path $sniBase "$arch\native\Microsoft.Data.SqlClient.SNI.dll" - if (Test-Path $sniPath) { - Write-Host "Found SNI DLL at: $sniPath" -ForegroundColor Green - $dllInfo = Get-Item $sniPath - Write-Host "DLL Size: $($dllInfo.Length) bytes" - - $destFolder = Join-Path $targetBase "$arch\native" - New-Item -ItemType Directory -Path $destFolder -Force | Out-Null - Copy-Item $sniPath -Destination $destFolder -Force - - Write-Host "Copied to: $destFolder" -ForegroundColor Cyan + $coreArchPath = Join-Path $coreRuntimesPath "$arch\native" + $desktopArchPath = Join-Path $desktopRuntimesPath "$arch\native" + + if (Test-Path $coreArchPath) { + Write-Host "Processing architecture: $arch" -ForegroundColor Cyan + + # Ensure desktop architecture directory exists + New-Item -ItemType Directory -Path $desktopArchPath -Force | Out-Null + + # Copy all native files from core to desktop for Windows PowerShell compatibility + Get-ChildItem -Path $coreArchPath -File | ForEach-Object { + $sourcePath = $_.FullName + $destPath = Join-Path $desktopArchPath $_.Name + + Copy-Item $sourcePath -Destination $destPath -Force + Write-Host " Copied: $($_.Name)" -ForegroundColor Green + } + + # Verify SNI DLL specifically + $sniPath = Join-Path $coreArchPath "Microsoft.Data.SqlClient.SNI.dll" + if (Test-Path $sniPath) { + $dllInfo = Get-Item $sniPath + Write-Host " SNI DLL verified - Size: $($dllInfo.Length) bytes" -ForegroundColor Green + } else { + Write-Warning " SNI DLL not found for $arch" + } } else { - Write-Warning "Missing: $sniPath" + Write-Warning "Architecture path not found: $coreArchPath" } } - } else { - Write-Host "ERROR: SNI DLL not found at expected location: $sniPath" -ForegroundColor Red - # Check if runtimes folder exists at all - if (Test-Path (Join-Path $libPath "core\lib\runtimes")) { - Write-Host "Runtimes folder exists. Contents:" - Get-ChildItem -Path (Join-Path $libPath "core\lib\runtimes") -Recurse | Select-Object FullName - } else { - Write-Host "ERROR: Runtimes folder not found in output!" -ForegroundColor Red + Write-Host "ERROR: Core runtimes folder not found at: $coreRuntimesPath" -ForegroundColor Red + + # Check what's actually in the core lib directory + $coreLibPath = Join-Path $libPath "core\lib" + if (Test-Path $coreLibPath) { + Write-Host "Core lib directory contents:" -ForegroundColor Yellow + Get-ChildItem -Path $coreLibPath -Recurse | Where-Object { $_.Name -like "*SNI*" } | Select-Object FullName } } +Copy-Item (Join-Path $libPath "core\lib\runtimes\unix\lib\net8.0\Microsoft.Data.SqlClient.dll") -Destination (Join-Path $libPath "core/lib/") -Force + +if ($CoreOnly) { + Write-Host "CoreOnly specified - returning after core build" + return +} # Run tests specifically for dbatools.Tests # dotnet test dbatools.Tests/dbatools.Tests.csproj --framework net472 --verbosity normal --no-restore --nologo | Out-String -OutVariable test Pop-Location -Remove-Item -Path (Join-Path $libPath "desktop/net472") -Recurse -ErrorAction SilentlyContinue -Remove-Item -Path (Join-Path $libPath "core/net8.0") -Recurse -ErrorAction SilentlyContinue +$targetDesktop = (Join-Path $libPath "desktop/net472") +if (Test-Path $targetDesktop) { + Remove-Item -Path $targetDesktop -Recurse -ErrorAction SilentlyContinue +} +$targetCore = (Join-Path $libPath "core/net8.0") +if (Test-Path $targetCore) { + Remove-Item -Path $targetCore -Recurse -ErrorAction SilentlyContinue +} $tempdir = Join-Path ([System.IO.Path]::GetTempPath()) "dbatools-build" @@ -147,10 +164,11 @@ $null = New-Item -ItemType Directory (Join-Path $tempPath "mac") -Force -ErrorAc $null = New-Item -ItemType Directory (Join-Path $libPath "desktop/third-party/XESmartTarget") -Force $null = New-Item -ItemType Directory (Join-Path $libPath "desktop/third-party/bogus") -Force $null = New-Item -ItemType Directory (Join-Path $libPath "desktop/third-party/LumenWorks") -Force +$null = New-Item -ItemType Directory (Join-Path $libPath "desktop/lib/dac") -Force +$null = New-Item -ItemType Directory (Join-Path $libPath "core/lib/dac/windows") -Force $null = New-Item -ItemType Directory (Join-Path $libPath "core/third-party/XESmartTarget") -Force $null = New-Item -ItemType Directory (Join-Path $libPath "core/third-party/bogus") -Force $null = New-Item -ItemType Directory (Join-Path $libPath "core/third-party/LumenWorks") -Force -$null = New-Item -ItemType Directory (Join-Path $libPath "core/lib/dac/windows") -Force $null = New-Item -ItemType Directory (Join-Path $libPath "core/lib/dac/mac") -Force $null = New-Item -ItemType Directory (Join-Path $libPath "core/lib/dac/linux") -Force $null = New-Item -ItemType Directory (Join-Path $libPath "core/lib/runtimes") -Force @@ -159,36 +177,9 @@ $null = New-Item -ItemType Directory (Join-Path $tempdir "nuget") -Force Register-PackageSource -provider NuGet -name nugetRepository -Location https://www.nuget.org/api/v2 -Trusted -ErrorAction Ignore -$ProgressPreference = "SilentlyContinue" - -# Install Microsoft.Identity.Client NuGet package -$parms = @{ - Provider = "Nuget" - Destination = "$tempdir\nuget" - Source = "nugetRepository" - Scope = "CurrentUser" - Force = $true - SkipDependencies = $true -} - -$parms.Name = "Microsoft.Identity.Client" -$parms.RequiredVersion = "4.61.3.0" -$null = Install-Package @parms - -$parms.Name = "Microsoft.Data.SqlClient" -$parms.RequiredVersion = "5.1.6" -Install-Package @parms - - -# Copy DLLs to appropriate lib directories -Copy-Item "$tempdir\nuget\Microsoft.Identity.Client.4.61.3\lib\net462\Microsoft.Identity.Client.dll" -Destination (Join-Path $libPath "desktop/lib/") -Force - -Copy-Item "$tempdir\nuget\Microsoft.Data.SqlClient.5.1.6\runtimes\unix\lib\net6.0\Microsoft.Data.SqlClient.dll" -Destination (Join-Path $libPath "core/lib/") -Force - -#Copy-Item "$tempdir\nuget\Microsoft.Identity.Client.4.61.3.0\lib\net461\Microsoft.Identity.Client.dll" -Destination (Join-Path $libPath "core/lib/") -Force - # Download all required packages Invoke-WebRequest -Uri https://aka.ms/dacfx-msi -OutFile (Join-Path $tempPath "DacFramework.msi") +Invoke-WebRequest -Uri https://aka.ms/sqlpackage-windows -OutFile (Join-Path $tempPath "sqlpackage-windows.zip") Invoke-WebRequest -Uri https://www.nuget.org/api/v2/package/Bogus -OutFile (Join-Path $tempPath "bogus.zip") Invoke-WebRequest -Uri https://www.nuget.org/api/v2/package/LumenWorksCsvReader -OutFile (Join-Path $tempPath "LumenWorksCsvReader.zip") Invoke-WebRequest -Uri https://github.com/spaghettidba/XESmartTarget/releases/download/v1.5.7/XESmartTarget_x64.msi -OutFile (Join-Path $tempPath "XESmartTarget_x64.msi") @@ -202,6 +193,7 @@ $ProgressPreference = "Continue" 7z x (Join-Path $tempPath "LumenWorksCsvReader.zip") "-o$(Join-Path $tempPath "LumenWorksCsvReader")" -y 7z x (Join-Path $tempPath "bogus.zip") "-o$(Join-Path $tempPath "bogus")" -y 7z x (Join-Path $tempPath "XESmartTarget-linux.zip") "-o$(Join-Path $tempPath "xe-linux")" -y +7z x (Join-Path $tempPath "sqlpackage-windows.zip") "-o$(Join-Path $tempPath "windows")" -y 7z x (Join-Path $tempPath "sqlpackage-linux.zip") "-o$(Join-Path $tempPath "linux")" -y 7z x (Join-Path $tempPath "sqlpackage-macos.zip") "-o$(Join-Path $tempPath "mac")" -y @@ -287,40 +279,58 @@ if (-not $bogusCoreCopied) { Copy-Item (Join-Path $tempPath "LumenWorksCsvReader/lib/net461/LumenWorks.Framework.IO.dll") -Destination (Join-Path $libPath "desktop/third-party/LumenWorks/LumenWorks.Framework.IO.dll") -Force Copy-Item (Join-Path $tempPath "LumenWorksCsvReader/lib/netstandard2.0/LumenWorks.Framework.IO.dll") -Destination (Join-Path $libPath "core/third-party/LumenWorks/LumenWorks.Framework.IO.dll") -Force -# Copy ALL SqlPackage files for each platform -Write-Host "Copying SqlPackage files for all platforms..." -ForegroundColor Green +# Copy ALL sqlpackage files for each platform +Write-Host "Copying sqlpackage files for all platforms..." -ForegroundColor Green -# Windows - Copy ALL files from DAC bin directory +# Windows - Copy ALL files from DAC bin directory to desktop/lib/dac (dacfx-msi) $dacPath = Join-Path (Join-Path $tempPath "dacfull") "Microsoft SQL Server\170\DAC\bin" if (Test-Path $dacPath) { - Write-Host "Copying ALL SqlPackage files for Windows..." -ForegroundColor Green - Copy-Item (Join-Path $dacPath "*") -Destination (Join-Path $libPath "core/lib/dac/windows/") -Recurse -Force + Write-Host "Copying dacfx-msi files to desktop/lib/dac..." -ForegroundColor Green + Copy-Item (Join-Path $dacPath "*") -Destination (Join-Path $libPath "desktop/lib/dac/") -Recurse -Force } else { Write-Warning "Windows DAC path not found: $dacPath" } +# Windows Core - Copy ALL files from sqlpackage Windows download to core/lib/dac/windows +if (Test-Path (Join-Path $tempPath "windows")) { + Write-Host "Copying sqlpackage Windows files to core/lib/dac/windows..." -ForegroundColor Green + Copy-Item (Join-Path $tempPath "windows/*") -Destination (Join-Path $libPath "core/lib/dac/windows/") -Recurse -Force +} else { + Write-Warning "Windows sqlpackage path not found: $(Join-Path $tempPath "windows")" +} + # Linux - Copy ALL files from temp/linux if (Test-Path (Join-Path $tempPath "linux")) { - Write-Host "Copying ALL SqlPackage files for Linux..." -ForegroundColor Green + Write-Host "Copying ALL sqlpackage files for Linux..." -ForegroundColor Green Copy-Item (Join-Path $tempPath "linux/*") -Destination (Join-Path $libPath "core/lib/dac/linux/") -Recurse -Force - - # Fix SqlPackage naming for Linux - rename lowercase to uppercase if it exists - $linuxSqlPackageLowerCase = Join-Path $libPath "core/lib/dac/linux/sqlpackage" - $linuxSqlPackageUpperCase = Join-Path $libPath "core/lib/dac/linux/SqlPackage" - if (Test-Path $linuxSqlPackageLowerCase) { - Write-Host "Renaming lowercase 'sqlpackage' to 'SqlPackage' for Linux compatibility" - Move-Item $linuxSqlPackageLowerCase $linuxSqlPackageUpperCase -Force + # Ensure SqlPackage is renamed to sqlpackage (Linux is case-sensitive) + $linSqlPackage = Join-Path $libPath "core/lib/dac/linux/SqlPackage" + $finalname = Join-Path $libPath "core/lib/dac/linux/sqlpackage" + $tempname = Join-Path $libPath "core/lib/dac/linux/sqlpackage-temp" + + if (Test-Path $linSqlPackage) { + Rename-Item $linSqlPackage $tempname + Rename-Item $tempname $finalname } } else { - Write-Warning "Linux SqlPackage path not found: $(Join-Path $tempPath "linux")" + Write-Warning "Linux sqlpackage path not found: $(Join-Path $tempPath "linux")" } # macOS - Copy ALL files from temp/mac if (Test-Path (Join-Path $tempPath "mac")) { - Write-Host "Copying ALL SqlPackage files for macOS..." -ForegroundColor Green + Write-Host "Copying ALL sqlpackage files for macOS..." -ForegroundColor Green Copy-Item (Join-Path $tempPath "mac/*") -Destination (Join-Path $libPath "core/lib/dac/mac/") -Recurse -Force + # Ensure SqlPackage is renamed to sqlpackage (macOS case-sensitive too) + $linSqlPackage = Join-Path $libPath "core/lib/dac/mac/SqlPackage" + $finalname = Join-Path $libPath "core/lib/dac/mac/sqlpackage" + $tempname = Join-Path $libPath "core/lib/dac/mac/sqlpackage-temp" + + if (Test-Path $linSqlPackage) { + Rename-Item $linSqlPackage $tempname + Rename-Item $tempname $finalname + } } else { - Write-Warning "macOS SqlPackage path not found: $(Join-Path $tempPath "mac")" + Write-Warning "macOS sqlpackage path not found: $(Join-Path $tempPath "mac")" } # Core files are already in place from dotnet publish @@ -341,15 +351,6 @@ Write-Host "Cleaning up temporary files..." # We don't remove the artifacts directory since it's our centralized build output Get-ChildItem -Path (Join-Path $libPath "*") -Recurse -Include "*.pdf","*.xml" | Remove-Item -Force -# Create private directory for assembly loading scripts -$null = New-Item -ItemType Directory -Path "./private" -Force -ErrorAction SilentlyContinue - -# Copy assembly loading scripts to private directory -if (Test-Path (Join-Path $root "private")) { - Copy-Item -Path (Join-Path $root "private\*") -Destination "./private/" -Force -ErrorAction SilentlyContinue - Write-Host "Copied assembly loading scripts to private directory" -} - # Create directory structure for different versions of System.Runtime.CompilerServices.Unsafe.dll $null = New-Item -ItemType Directory -Path (Join-Path $libPath "desktop/v4") -Force $null = New-Item -ItemType Directory -Path (Join-Path $libPath "desktop/lib/v6") -Force @@ -375,12 +376,6 @@ Copy-Item -Path (Join-Path $root "dbatools.library.psm1") -Destination $dbatools Copy-Item -Path (Join-Path $root "LICENSE") -Destination $dbatoolsLibraryDir -Force -ErrorAction SilentlyContinue Write-Host "Copied module files to artifacts/dbatools.library" -ForegroundColor Green -# Copy private folder with assembly loading scripts -if (Test-Path (Join-Path $root "private")) { - Copy-Item -Path (Join-Path $root "private") -Destination $dbatoolsLibraryDir -Recurse -Force - Write-Host "Included private folder in artifacts/dbatools.library" -ForegroundColor Green -} - # Copy third-party-licenses $licensePath = Join-Path $dbatoolsLibraryDir "third-party-licenses" $null = New-Item -ItemType Directory -Path $licensePath -Force @@ -396,7 +391,9 @@ if (Test-Path (Join-Path $root "var/third-party-licenses")) { # Create zip file for testing (release format) Write-Host "Creating dbatools.library.zip for testing..." $zipPath = Join-Path $artifactsDir "dbatools.library.zip" -Remove-Item -Path $zipPath -Force -ErrorAction SilentlyContinue +if (Test-Path $zipPath) { + Remove-Item -Path $zipPath -Force -ErrorAction SilentlyContinue +} # Copy third-party-licenses if (Test-Path (Join-Path $root "var\third-party-licenses")) { @@ -409,7 +406,7 @@ Write-Host "All build artifacts are centralized in: $artifactsDir" -ForegroundCo # Create the zip file directly from the artifacts/dbatools.library directory Push-Location $artifactsDir -if (-not $NoZip) { +if ($BuildZip) { Compress-Archive -Path "dbatools.library" -DestinationPath $zipPath -CompressionLevel Optimal -Force } Pop-Location diff --git a/dbatools.library.psd1 b/dbatools.library.psd1 index 21c37844..36c2a16c 100644 --- a/dbatools.library.psd1 +++ b/dbatools.library.psd1 @@ -7,7 +7,7 @@ # @{ # Version number of this module. - ModuleVersion = '2025.7.13' + ModuleVersion = '2025.7.19' # ID used to uniquely identify this module GUID = '00b61a37-6c36-40d8-8865-ac0180288c84' diff --git a/dbatools.library.psm1 b/dbatools.library.psm1 index 343dd585..90fdfbd8 100644 --- a/dbatools.library.psm1 +++ b/dbatools.library.psm1 @@ -1,76 +1,192 @@ function Get-DbatoolsLibraryPath { [CmdletBinding()] param() - Write-Debug "PSScriptRoot: $PSScriptRoot" - Write-Debug "Module Base: $($MyInvocation.MyCommand.Module.ModuleBase)" - - # Use ModuleBase as it's more reliable when importing via absolute path - $MyInvocation.MyCommand.Module.ModuleBase + if ($PSVersionTable.PSEdition -eq "Core") { + Join-Path -Path $PSScriptRoot -ChildPath core + } else { + Join-Path -Path $PSScriptRoot -ChildPath desktop + } } $script:libraryroot = Get-DbatoolsLibraryPath -# Ensure private directory exists -$privateDir = Join-Path $PSScriptRoot "private" -if (-not (Test-Path $privateDir)) { - $null = New-Item -ItemType Directory -Path $privateDir -Force -} +if ($PSVersionTable.PSEdition -ne "Core") { + $dir = [System.IO.Path]::Combine($script:libraryroot, "lib") + $dir = ("$dir\").Replace('\', '\\') -# Define component load order (important for dependencies) -$components = @( - 'assembly-lists.ps1', # Must be first as others depend on its variables - 'assembly-redirector.ps1', # Assembly redirection for version conflicts - 'assembly-compilerservices-resolver.ps1', # Specific resolver for System.Runtime.CompilerServices.Unsafe - 'assembly-resolution.ps1', # Depends on assembly lists - 'assembly-loader.ps1', # Depends on both above - 'assembly-troubleshoot.ps1' # Troubleshooting tools -) - -# Load component scripts -foreach ($component in $components) { - $componentPath = Join-Path $PSScriptRoot "private\$component" - if (Test-Path $componentPath) { - . $componentPath - } else { - throw "Required component not found: $componentPath" + if (-not ("Redirector" -as [type])) { + $source = @" + using System; + using System.Linq; + using System.Reflection; + using System.Text.RegularExpressions; + + public class Redirector + { + public Redirector() + { + this.EventHandler = new ResolveEventHandler(AssemblyResolve); + } + + public readonly ResolveEventHandler EventHandler; + + protected Assembly AssemblyResolve(object sender, ResolveEventArgs e) + { + string[] dlls = { + "System.Memory", + "System.Runtime.CompilerServices.Unsafe", + "Microsoft.Bcl.AsyncInterfaces", + "System.Text.Json", + "System.Resources.Extensions", + "Microsoft.SqlServer.ConnectionInfo", + "Microsoft.SqlServer.Smo", + "Microsoft.Identity.Client", + "System.Diagnostics.DiagnosticSource", + "Microsoft.IdentityModel.Abstractions", + "Microsoft.Data.SqlClient", + "Microsoft.SqlServer.Types", + "System.Configuration.ConfigurationManager", + "Microsoft.SqlServer.Management.Sdk.Sfc", + "Microsoft.SqlServer.Management.IntegrationServices", + "Microsoft.SqlServer.Replication", + "Microsoft.SqlServer.Rmo", + "System.Private.CoreLib", + "Azure.Core", + "Azure.Identity" + }; + + var name = new AssemblyName(e.Name); + var assemblyName = name.Name.ToString(); + foreach (string dll in dlls) + { + if (assemblyName == dll) + { + string filelocation = "$dir" + dll + ".dll"; + //Console.WriteLine(filelocation); + return Assembly.LoadFrom(filelocation); + } + } + + foreach (var assembly in AppDomain.CurrentDomain.GetAssemblies()) + { + // maybe this needs to change? + var info = assembly.GetName(); + if (info.FullName == e.Name) { + return assembly; + } + } + return null; + } + } +"@ + + $null = Add-Type -TypeDefinition $source + } + + try { + $redirector = New-Object Redirector + [System.AppDomain]::CurrentDomain.add_AssemblyResolve($redirector.EventHandler) + } catch { + # unsure } } -# Initialize assembly handling +# REMOVED win-sqlclient logic - SqlClient is now directly in lib +$sqlclient = [System.IO.Path]::Combine($script:libraryroot, "lib", "Microsoft.Data.SqlClient.dll") + try { - Initialize-DbatoolsAssemblyLoader - Write-Debug "Assembly loader initialized successfully" + Import-Module $sqlclient } catch { - throw "Failed to initialize assembly loader: $_" + throw "Couldn't import $sqlclient | $PSItem" } -# Register cleanup for module removal -$MyInvocation.MyCommand.ScriptBlock.Module.OnRemove = { - if ($PSVersionTable.PSEdition -ne "Core") { - try { - # Remove both event handlers - [System.AppDomain]::CurrentDomain.remove_AssemblyResolve($script:onAssemblyResolveEventHandler) +if ($PSVersionTable.PSEdition -ne "Core") { + [System.AppDomain]::CurrentDomain.remove_AssemblyResolve($onAssemblyResolveEventHandler) +} - # Get the redirector instance and remove its handler - $redirector = New-Object Redirector - [System.AppDomain]::CurrentDomain.remove_AssemblyResolve($redirector.EventHandler) +if ($PSVersionTable.PSEdition -eq "Core") { + $names = @( + 'Microsoft.SqlServer.Server', + 'Azure.Core', + 'Azure.Identity', + 'Microsoft.IdentityModel.Abstractions', + 'Microsoft.SqlServer.Dac', + 'Microsoft.SqlServer.Smo', + 'Microsoft.SqlServer.SmoExtended', + 'Microsoft.SqlServer.SqlWmiManagement', + 'Microsoft.SqlServer.WmiEnum', + 'Microsoft.SqlServer.Management.RegisteredServers', + 'Microsoft.SqlServer.Management.Collector', + 'Microsoft.SqlServer.Management.XEvent', + 'Microsoft.SqlServer.Management.XEventDbScoped', + 'Microsoft.SqlServer.XEvent.XELite' + ) +} else { + $names = @( + 'Azure.Core', + 'Azure.Identity', + 'Microsoft.IdentityModel.Abstractions', + 'Microsoft.Data.SqlClient', + 'Microsoft.SqlServer.Dac', + 'Microsoft.SqlServer.Smo', + 'Microsoft.SqlServer.SmoExtended', + 'Microsoft.SqlServer.SqlWmiManagement', + 'Microsoft.SqlServer.WmiEnum', + 'Microsoft.SqlServer.Management.RegisteredServers', + 'Microsoft.SqlServer.Management.IntegrationServices', + 'Microsoft.SqlServer.Management.Collector', + 'Microsoft.SqlServer.Management.XEvent', + 'Microsoft.SqlServer.Management.XEventDbScoped', + 'Microsoft.SqlServer.XEvent.XELite' + ) +} - Write-Debug "Successfully removed assembly resolve handlers" - } - catch { - Write-Warning "Error removing assembly resolve handlers: $_" - } - } +if ($Env:SMODefaultModuleName) { + # then it's DSC, load other required assemblies + $names += "Microsoft.AnalysisServices.Core" + $names += "Microsoft.AnalysisServices" + $names += "Microsoft.AnalysisServices.Tabular" + $names += "Microsoft.AnalysisServices.Tabular.Json" +} + +# XEvent stuff kills CI/CD +if ($PSVersionTable.OS -match "ARM64") { + $names = $names | Where-Object { $PSItem -notmatch "XE" } +} +#endregion Names + +# this takes 10ms +$assemblies = [System.AppDomain]::CurrentDomain.GetAssemblies() + +try { + $null = Import-Module ([IO.Path]::Combine($script:libraryroot, "third-party", "bogus", "Bogus.dll")) +} catch { + Write-Error "Could not import $assemblyPath : $($_ | Out-String)" +} + +try { + $null = Import-Module ([IO.Path]::Combine($script:libraryroot, "third-party", "LumenWorks", "LumenWorks.Framework.IO.dll")) +} catch { + Write-Error "Could not import LumenWorks.Framework.IO.dll : $($_ | Out-String)" } -# Export module functions -Export-ModuleMember -Function @( - 'Get-DbatoolsLibraryPath', - 'Get-DbatoolsPlatformInfo', - 'Get-DbatoolsLoadedAssembly', - 'Test-DbatoolsAssemblyLoading', - 'Reset-DbatoolsAssemblyLoader', - 'Test-DbatoolsAssemblyEnvironment', - 'Reset-DbatoolsAssemblyCache', - 'Get-PlatformDetails' -) \ No newline at end of file +foreach ($name in $names) { + # REMOVED win-sqlclient handling and mac-specific logic since files are in standard lib folder + + $x64only = 'Microsoft.SqlServer.Replication', 'Microsoft.SqlServer.XEvent.Linq', 'Microsoft.SqlServer.BatchParser', 'Microsoft.SqlServer.Rmo', 'Microsoft.SqlServer.BatchParserClient' + + if ($name -in $x64only -and $env:PROCESSOR_ARCHITECTURE -eq "x86") { + Write-Verbose -Message "Skipping $name. x86 not supported for this library." + continue + } + + $assemblyPath = [IO.Path]::Combine($script:libraryroot, "lib", "$name.dll") + $assemblyfullname = $assemblies.FullName | Out-String + if (-not ($assemblyfullname.Contains("$name,"))) { + $null = try { + $null = Import-Module $assemblyPath + } catch { + Write-Error "Could not import $assemblyPath : $($_ | Out-String)" + } + } +} \ No newline at end of file diff --git a/project/dbatools/dbatools.csproj b/project/dbatools/dbatools.csproj index 02e7f1cd..5e4b6dae 100644 --- a/project/dbatools/dbatools.csproj +++ b/project/dbatools/dbatools.csproj @@ -14,38 +14,71 @@ true true - - latest - ..\..\artifacts\lib\$(Configuration)\ - ..\..\artifacts\lib\$(Configuration)\dbatools.xml - full DEBUG;TRACE + ..\..\artifacts\lib\$(Configuration)\ + 7.3 pdbonly true TRACE + ..\..\artifacts\lib\$(Configuration)\ + ..\..\artifacts\lib\$(Configuration)\dbatools.xml + 7.3 + + + + ..\..\artifacts\lib\ + TRACE;NORUNSPACENAME + ..\..\artifacts\lib\dbatools.xml + true + pdbonly + MinimumRecommendedRules.ruleset + 5 + + + + ..\..\artifacts\lib\ + TRACE;NORUNSPACENAME + ..\..\artifacts\lib\dbatools.xml + true + pdbonly + MinimumRecommendedRules.ruleset + 7.3 + + + - - + + + + + + + C:\Windows\Microsoft.NET\assembly\GAC_MSIL\System.Management.Automation\v4.0_3.0.0.0__31bf3856ad364e35\System.Management.Automation.dll False False + + + + + \ No newline at end of file diff --git a/var/misc/both/Microsoft.SqlServer.ReplEnum.dll b/var/misc/both/Microsoft.SqlServer.ReplEnum.dll new file mode 100644 index 00000000..ff1205ed Binary files /dev/null and b/var/misc/both/Microsoft.SqlServer.ReplEnum.dll differ diff --git a/var/misc/both/Microsoft.SqlServer.Replication.dll b/var/misc/both/Microsoft.SqlServer.Replication.dll index c9003132..95f12f04 100644 Binary files a/var/misc/both/Microsoft.SqlServer.Replication.dll and b/var/misc/both/Microsoft.SqlServer.Replication.dll differ diff --git a/var/misc/both/Microsoft.SqlServer.Rmo.dll b/var/misc/both/Microsoft.SqlServer.Rmo.dll index c90ced12..77355aa1 100644 Binary files a/var/misc/both/Microsoft.SqlServer.Rmo.dll and b/var/misc/both/Microsoft.SqlServer.Rmo.dll differ diff --git a/var/misc/both/instapi170.dll b/var/misc/both/instapi170.dll new file mode 100644 index 00000000..6316a905 Binary files /dev/null and b/var/misc/both/instapi170.dll differ