DSC PullServer automation with GitLab
Prerequisites
- Install a Pullserver
- Install GitLab runner on the PullServer with the shell executor and tags "shell", "powershell5", "windows" and "pullserver".
- Register the Gitlab runner/pullServer with your DSC configuration project in GitLab.
- Add a .gitignore file to ignore the build output and compiled mof
- Add .gitlab-ci.yml file to your project with the following contents
stages: - dependencies - test - run manage_dependencies: stage: dependencies tags: - shell # <-- executor, must change config.toml shell from "pwsh" to "powershell" - powershell5 # <-- powershell version` - windows # <-- run only on windows - pullserver # <-- run only on pullserver script: | # Configure Environment $ErrorActionPreference = 'Stop' Set-Location -Path $env:CI_PROJECT_DIR # Initialize variables [string[]]$detectedmodules = @() [string[]]$stagedmodules = @() [string[]]$ignoremodules = "PSDesiredStateConfiguration" [string]$modulespath = 'C:\Program Files\WindowsPowerShell\DscService\Modules' write-warning -Message "This script does not upgrade existing modules. Please test your scripts with modules already installed on the pull server." write-output "Setting PSModulePath..." $env:PSModulePath = 'C:\Program Files\WindowsPowerShell\Modules;C:\Program Files (x86)\WindowsPowerShell\Modules;C:\WINDOWS\system32\WindowsPowerShell\v1.0\Modules' Write-Output "Detecting required modules..." Get-Content -Path "$($env:CI_PROJECT_DIR)\$($env:CI_PROJECT_TITLE).ps1" | Where-Object {$_ -match '(import-dscresource\s+)'} | ForEach-Object { $detectedmodules += $_.ToString().Trim().Split(" ") | Select-Object -Last 1 } $detectedmodules = $detectedmodules | Where-Object{$_ -notcontains $ignoremodules} Write-Output "Getting currently staged modules..." Get-ChildItem -Path $modulespath -Filter *.zip | ForEach-Object { $stagedmodules += $_.Name.ToString().Trim().Split("_")[0] } Write-Output "Checking for modules in the runners's powershell library..." foreach($detectedmodule In $detectedmodules){ write-output "Checking for $detectedmodule..." $checkmod = Get-DscResource -Module $detectedmodule -WarningAction SilentlyContinue If($checkmod){ write-output "$detectedmodule already installed." }else{ Write-Output "Installing $detectedmodule..." Install-Module -Name $detectedmodule } } Write-Output "Identifying modules missing from the pullserver repository..." $missingmodules = $detectedmodules | Where {$stagedmodules -NotContains $_} foreach($missingmodule In $missingmodules){ Write-Output "Downloading $missingmodule..." Save-Module -Name $missingmodule -Path . Write-Output "Unhiding files to enable compression..." Get-ChildItem -path ".\$missingmodule\$version\*" -force -Recurse | where{$_.Attributes -match "hidden"} | foreach{$_.Attributes=""} Write-Output "Compressing module..." $version = (Get-ChildItem -Path ".\$missingmodule").Name $archive = '.\' + $missingmodule + '_' + $version + '.zip' Compress-Archive -Path ".\$missingmodule\$version\*" -DestinationPath $archive Write-Output "Creating checksum..." New-DscChecksum -Path $archive -OutPath . write-output "Copying modules to module share..." Copy-Item -Path $archive -Destination $modulespath write-output "Copying checksum to module share..." Copy-Item -Path "$archive.checksum" -Destination $modulespath } only: - pushes test_dsc: stage: test tags: - shell - powershell5 - windows - pullserver script: | BeforeAll { . "$($env:CI_PROJECT_DIR)\$($env:CI_PROJECT_TITLE).ps1" } Describe 'Pester-Test' { It 'Passes Script Analyzer' { Invoke-ScriptAnalyzer -Path "$($env:CI_PROJECT_DIR)\$($env:CI_PROJECT_TITLE).ps1" -Severity Error | Should -BeNullOrEmpty } It 'Generated MOF' { "$($env:CI_PROJECT_DIR)\$($env:CI_PROJECT_TITLE)\localhost.mof" | Should -Exist } } AfterAll { If(Test-Path -Path "$($env:CI_PROJECT_DIR)\$($env:CI_PROJECT_TITLE)\localhost.mof"){Remove-Item -Path "$($env:CI_PROJECT_DIR)\$($env:CI_PROJECT_TITLE)\localhost.mof"} } only: - pushes run_dsc: stage: run tags: - shell - powershell5 - windows - pullserver script: | # Configure Environment $ErrorActionPreference = 'Stop' Set-Location -Path $env:CI_PROJECT_DIR # Initialize variables [string]$configpath = 'C:\Program Files\WindowsPowerShell\DscService\Configuration' write-output "Setting PSModulePath..." $env:PSModulePath = 'C:\Program Files\WindowsPowerShell\Modules;C:\Program Files (x86)\WindowsPowerShell\Modules;C:\WINDOWS\system32\WindowsPowerShell\v1.0\Modules' Write-Output "Writing MOF..." Try{ & "$($env:CI_PROJECT_DIR)\$($env:CI_PROJECT_TITLE).ps1" -Verbose }Catch{ Throw $_.Exception.Message } Write-Output "Creating Checksum..." New-DscChecksum -Path "$($env:CI_PROJECT_DIR)\$($env:CI_PROJECT_TITLE)\localhost.mof" Write-Output "Renaming MOF file..." Rename-Item -Path "$($env:CI_PROJECT_DIR)\$($env:CI_PROJECT_TITLE)\localhost.mof" -NewName "$($env:CI_PROJECT_TITLE).mof" Write-Output "Renaming checksum file..." Rename-Item -Path "$($env:CI_PROJECT_DIR)\$($env:CI_PROJECT_TITLE)\localhost.mof.checksum" -NewName "$($env:CI_PROJECT_TITLE).mof.checksum" Write-Output "Copying MOF to $configpath..." Copy-Item -Path "$($env:CI_PROJECT_DIR)\$($env:CI_PROJECT_TITLE)\$($env:CI_PROJECT_TITLE).mof" -Destination $configpath Write-Output "Copying checksum to $configpath..." Copy-Item -Path "$($env:CI_PROJECT_DIR)\$($env:CI_PROJECT_TITLE)\$($env:CI_PROJECT_TITLE).mof.checksum" -Destination $configpath only: - master
Document Actions