diff --git a/.github/workflows/create-release.yml b/.github/workflows/create-release.yml index 456e9e8f..63432c70 100644 --- a/.github/workflows/create-release.yml +++ b/.github/workflows/create-release.yml @@ -78,15 +78,15 @@ jobs: } $changeLogContent = @" - :package: All MSLab scripts are in **mslab_${{ needs.new-version.outputs.new_tag }}.zip** file. + :package: MSLab scripts are in **[mslab_${{ needs.new-version.outputs.new_tag }}.zip](${{ github.server_url }}/${{ github.repository }}/releases/download/${{ needs.new-version.outputs.new_tag }}/mslab_${{ needs.new-version.outputs.new_tag }}.zip)** file. :information_source: Remaining `.ps1` files in this release would be downloaded on-demand by MSLab scripts during deployment, only if needed. + "@ if($changelog -ne "") { $changeLogContent += @" - - :basket: Changes in this version: + ## Changes in this version $changelog "@ } @@ -96,8 +96,8 @@ jobs: uses: softprops/action-gh-release@v1 with: tag_name: ${{ needs.new-version.outputs.new_tag }} # ${{ github.ref }} - name: Release ${{ needs.new-version.outputs.new_tag }} # ${{ github.ref }} - generate_release_notes: true + name: MSLab ${{ needs.new-version.outputs.new_tag }} # ${{ github.ref }} + generate_release_notes: false body_path: changelog.md files: | mslab_${{ needs.new-version.outputs.new_tag }}.zip diff --git a/Tools/CreateParentDisk.ps1 b/Tools/CreateParentDisk.ps1 index 95ccda3d..4c75eccb 100644 --- a/Tools/CreateParentDisk.ps1 +++ b/Tools/CreateParentDisk.ps1 @@ -39,6 +39,8 @@ If (-not $isAdmin) { #endregion + $mslabVersion = "dev" + #region download convert-windowsimage if needed and load it $convertWindowsImagePath = "$PSScriptRoot\Convert-WindowsImage.ps1" if (-not (Test-Path -Path $convertWindowsImagePath)) { diff --git a/build.ps1 b/build.ps1 index 602298d6..73be65f8 100644 --- a/build.ps1 +++ b/build.ps1 @@ -5,36 +5,53 @@ param( [string]$Version, [Parameter(Mandatory = $false, ParameterSetName = 'BuildAndSign')] [bool]$SignScripts = $false, - [Parameter(Mandatory = $true, ParameterSetName = 'BuildAndSign')] - [string]$SignScriptUri, - [Parameter(Mandatory = $true, ParameterSetName = 'BuildAndSign')] - [string]$ClientId + [Parameter(Mandatory = $true, ParameterSetName = 'BuildAndSign', HelpMessage = "Azure Blob URI to code signing script")] + [string]$SignScriptUri = "", + [Parameter(Mandatory = $true, ParameterSetName = 'BuildAndSign', HelpMessage = "Client ID of Code Signing App Registration")] + [string]$ClientId = "" ) +#region Configuration $toolsDir = ".\Tools\" -$baseDir = ".\Scripts\" +$scriptsDir = ".\Scripts\" $outputBaseDir = ".\Output\" -$outputDir = "$($outputBaseDir)\Compiled" -$signedOutputDir = "$($outputBaseDir)\Signed" -$toolsOutputDir = "$($outputBaseDir)\Tools" -$outputFile = "Release.zip" - -[array]$ignoredFiles = "0_Shared.ps1" -[array]$ignoredFilesToSign = @() #"LabConfig.ps1" +$scriptsOutputDir = Join-Path $outputBaseDir "ScriptsCompiled" +$signedScriptsOutputDir = Join-Path $outputBaseDir "Scripts" +$toolsOutputDir = Join-Path $outputBaseDir "ToolsCompiled" +$signedToolsOutputDir = Join-Path $outputBaseDir "Tools" +$scriptsOutputFile = "Release.zip" + +# Files that would be skipped by Build function (no replacements) +[array]$scriptsBuildIgnoredFiles = "0_Shared.ps1" +[array]$toolsBuildIgnoredFiles = @() + +# Files that won't be signed after build function +[array]$scriptsIgnoredFilesToSign = @() #"LabConfig.ps1" [array]$toolsIgnoredFilesToSign = @("1_SQL_Install.ps1", "2_ADK_Install.ps1", "3_SCVMM_Install.ps1") +#endregion -#region Build (and optionally sign) Scripts -if(Test-Path -Path $outputDir) { - Remove-Item -Path $outputDir -Recurse -Force +#region Init +if($SignScripts) { + # Download signing script with Managed Identity + $response = Invoke-RestMethod -Uri "http://169.254.169.254/metadata/identity/oauth2/token?api-version=2018-02-01&resource=https%3A%2F%2Fstorage.azure.com%2F" -Headers @{ "Metadata" = "true" } + Invoke-WebRequest -Headers @{ "x-ms-version" = "2017-11-09"; "Authorization" = "Bearer $($response.access_token)" } -Uri $SignScriptUri -OutFile .\sign.ps1 + + . .\sign.ps1 } -$releaseDirectory = New-Item -ItemType "Directory" -Path ".\" -Name $outputDir -$files = Get-ChildItem -Path $baseDir -foreach($file in $files) { - if($file.Name -in $ignoredFiles) { - continue - } - $content = Get-Content -Path $file.FullName +if(Test-Path -Path $outputBaseDir) { + Remove-Item -Path $outputBaseDir -Recurse -Force +} +#endregion + +#region Functions +function Build-File { + param ( + [string]$InputFilePath, + [string]$OutputFilePath + ) + + $content = Get-Content -Path $InputFilePath $output = $content | ForEach-Object { $line = $_ @@ -49,7 +66,7 @@ foreach($file in $files) { if($includeFile.StartsWith(".\")) { $includeFile = $includeFile.Substring(2) } - $includeFile = Join-Path -Path $baseDir -ChildPath $includeFile + $includeFile = Join-Path -Path $scriptsDir -ChildPath $includeFile if(-not (Test-Path -Path $includeFile)) { throw "Unable to include requested script ($includeFile)" } @@ -63,52 +80,70 @@ foreach($file in $files) { $line } - $outFile = Join-Path -Path $releaseDirectory -ChildPath $file.Name - Set-Content -Path $outFile -Value $output + + Set-Content -Path $OutputFilePath -Value $output } +#endregion -$outputFullPath = $releaseDirectory.FullName +#region Build (and optionally sign) Scripts +if(Test-Path -Path $scriptsOutputDir) { + Remove-Item -Path $scriptsOutputDir -Recurse -Force +} -if($SignScripts) { - # Download signing script with Managed Identity - $token = Invoke-RestMethod -Uri "http://169.254.169.254/metadata/identity/oauth2/token?api-version=2018-02-01&resource=https%3A%2F%2Fstorage.azure.com%2F" -Headers @{ "Metadata" = "true" } - Invoke-WebRequest -Headers @{ "x-ms-version" = "2017-11-09"; "Authorization" = "Bearer $($token.access_token)" } -Uri $SignScriptUri -OutFile .\sign.ps1 - - . .\sign.ps1 +if(Test-Path -Path $signedScriptsOutputDir) { + Remove-Item -Path $signedScriptsOutputDir -Recurse -Force } -if(Test-Path -Path $signedOutputDir) { - Remove-Item -Path $signedOutputDir -Recurse -Force +$scriptsReleaseDirectory = New-Item -ItemType "Directory" -Path ".\" -Name $scriptsOutputDir +$scriptsFiles = Get-ChildItem -Path $scriptsDir +foreach($file in $scriptsFiles) { + if($file.Name -in $scriptsBuildIgnoredFiles) { + continue + } + + $outFile = Join-Path -Path $scriptsReleaseDirectory -ChildPath $file.Name + Build-File -InputFilePath $file.FullName -OutputFilePath $outFile } -$signedReleaseDirectory = New-Item -ItemType "Directory" -Path ".\" -Name $signedOutputDir -$files = Get-ChildItem -Path $releaseDirectory -File | Where-Object Name -NotIn $ignoredFilesToSign +$scriptsSignedDirectory = New-Item -ItemType "Directory" -Path ".\" -Name $signedScriptsOutputDir +$scriptFiles = Get-ChildItem -Path $scriptsReleaseDirectory -File | Where-Object Name -NotIn $scriptsIgnoredFilesToSign if($SignScripts) { # sign scripts - Invoke-CodeSign -Files $files -OutputPath $signedReleaseDirectory -ClientId $ClientId + Invoke-CodeSign -Files $scriptFiles -OutputPath $scriptsSignedDirectory -ClientId $ClientId } else { # if not signing, just copy files over as is - $files | Select-Object -ExpandProperty FullName | Copy-Item -Destination $signedReleaseDirectory + $scriptFiles | Select-Object -ExpandProperty FullName | Copy-Item -Destination $scriptsSignedDirectory } -$signedFiles = Get-ChildItem -Path $signedReleaseDirectory.FullName -if($files.Length -ne $signedFiles.Length) { - throw "Signing files failed (source count: $($files.Length), signedCount: $($signedFiles.Length))" +$signedScriptFiles = Get-ChildItem -Path $scriptsSignedDirectory.FullName +if($scriptFiles.Length -ne $signedScriptFiles.Length) { + throw "Signing files failed (source count: $($scriptFiles.Length), signedCount: $($signedScriptFiles.Length))" } #endregion #region Build (and optionally sign) Tools -if(Test-Path -Path $ToolsOutputDir) { - Remove-Item -Path $ToolsOutputDir -Recurse -Force +if(Test-Path -Path $toolsOutputDir) { + Remove-Item -Path $toolsOutputDir -Recurse -Force +} + +if(Test-Path -Path $signedToolsOutputDir) { + Remove-Item -Path $signedToolsOutputDir -Recurse -Force } -# and copy scripts that are ignored from signing -Get-ChildItem -Path $releaseDirectory -File | Where-Object Name -In $ignoredFilesToSign | Copy-Item -Destination $signedReleaseDirectory.FullName -$outputFullPath = $signedReleaseDirectory.FullName +$toolsReleaseDirectory = New-Item -ItemType "Directory" -Path ".\" -Name $toolsOutputDir +$toolsFiles = Get-ChildItem -Path $toolsDir +foreach($file in $toolsFiles) { + if($file.Name -in $toolsBuildIgnoredFiles) { + continue + } + + $outFile = Join-Path -Path $toolsReleaseDirectory -ChildPath $file.Name + Build-File -InputFilePath $file.FullName -OutputFilePath $outFile +} -$toolsSignedDirectory = New-Item -ItemType "Directory" -Path ".\" -Name $toolsOutputDir -$toolsFiles = Get-ChildItem -Path $toolsDir -File | Where-Object Name -NotIn $toolsIgnoredFilesToSign +$toolsSignedDirectory = New-Item -ItemType "Directory" -Path ".\" -Name $signedToolsOutputDir +$toolsFiles = Get-ChildItem -Path $toolsReleaseDirectory -File | Where-Object Name -NotIn $toolsIgnoredFilesToSign if($SignScripts) { # Sign scripts in Tools folder @@ -124,4 +159,7 @@ if($toolsFiles.Length -ne $signedToolsFiles.Length) { } #endregion -Compress-Archive -Path "$($outputFullPath)\*" -DestinationPath $outputFile -CompressionLevel Optimal -Force +#region Create Scripts release ZIP +$scriptsOutputFullPath = $scriptsSignedDirectory.FullName +Compress-Archive -Path "$($scriptsOutputFullPath)\*" -DestinationPath $scriptsOutputFile -CompressionLevel Optimal -Force +#endregion \ No newline at end of file