Last active
March 7, 2021 12:12
-
-
Save Seekatar/ae32fbe1e82d86d15c7d7342220a52ff to your computer and use it in GitHub Desktop.
Psakefile for building, running dotnet app
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<# | |
psakefile for building and running dotnet app in docker | |
Invoke like this: | |
Invoke-Psake -buildFile '.\psakefile.ps1' -taskList @($Task) -parameters @{ | |
dockerEnvFile = $DockerEnvFile | |
dockerTag = $DockerTag | |
containerName = $ContainerName | |
nugetUrl = $NugetUrl | |
userName = $NexusUser | |
pass = $NexusPass | |
localPort = $LocalPort | |
noCache = [bool]$NoCache | |
plain = [bool] $PlainOutput | |
version = $Version | |
} -Verbose:$VerbosePreference | |
#> | |
[Diagnostics.CodeAnalysis.SuppressMessageAttribute("PSUseDeclaredVarsMoreThanAssignments", "", Justification = "Vars in properties block are actually used")] | |
param() | |
Set-StrictMode -Version latest | |
TaskSetup { | |
Write-Host "##[section]Starting: Build task '$TaskName'" | |
} | |
TaskTearDown { | |
Write-Host "##[section]Finishing: Build task '$TaskName'" | |
} | |
properties { | |
$dockerPlain = $true | |
if (Test-Path variable:plain) { | |
$dockerPlain = $plain | |
} | |
$baseDir = $PSScriptRoot | |
$sourceDir = (Join-Path $baseDir "src") | |
$aspNetPort = 8080 | |
$ASPNETCORE_URLS="http://+:$aspNetPort" | |
$NUGET_SOURCE="https://api.nuget.org/v3/index.json" | |
$dockerTag = $dockerTag.ToLowerInvariant() | |
$dockerfile = "Dockerfile" | |
$helmDryRun = $false | |
$helmWait = $true | |
} | |
task default -depends BuildMessage, DockerBuild, DockerInteractive | |
task ci -depends DockerBuild | |
task UpdateRunPs1 { | |
"Does nothing, but run.ps1 ValidateSet should be updated" | |
} | |
task DumpVars { | |
"`n`n==== Variables ====" | |
Get-ChildItem variable: | Select-Object name, value | |
"`n`n==== Environment ====" | |
Get-ChildItem env: | Where-Object name -NotLike *passw* | Select-Object name, value | |
} | |
task DotnetBuild { | |
exec -workingDirectory $sourceDir { | |
dotnet build | |
} | |
} | |
task TestClient { | |
exec -workingDirectory $sourceDir/TestClient { | |
dotnet run | |
} | |
} | |
task DotnetTest { | |
exec -workingDirectory $sourceDir { | |
dotnet test | |
} | |
} | |
task OpenSln { | |
exec -workingDirectory $sourceDir { | |
Start-Process (Get-Item *.sln) | |
} | |
} | |
task BuildMessage { | |
if ($version) { | |
exec -workingDirectory $sourceDir { | |
$folder = @(Get-Item CCC.CAS.*Messages) | |
if ($folder -and $folder.Count -eq 1) { | |
$packageFolder = Join-Path $PWD packages | |
if (!(Test-Path $packageFolder)) { | |
$null = New-Item -ItemType Directory $packageFolder | |
} | |
if (!(dotnet nuget list source | Select-String $packageFolder -SimpleMatch)) { | |
dotnet nuget add source $packageFolder --name $folder.Name | |
} else { | |
"Found local nuget for $packageFolder" | |
} | |
exec -workingDirectory $folder[0] { | |
dotnet build --configuration Release -p:Version=$version -p:AssemblyVersion=$version | |
} | |
exec -workingDirectory $folder[0] { | |
dotnet pack --configuration Release --output $packageFolder -p:Version=$version -p:AssemblyVersion=$version --include-source --no-build | |
} | |
} else { | |
"No message folder to build -- or more that one message folder found. Ok for API" | |
} | |
} | |
} else { | |
Write-Error "Must supply version when using pack." | |
} | |
} | |
function Get-NugetSource | |
{ | |
Set-StrictMode -Version Latest | |
$ErrorActionPreference = 'Stop' | |
$sources = @() | |
$inSource = $false | |
$source = $null | |
dotnet nuget list source | ForEach-Object { | |
if ($_ -match "\s+\d+\.\s+([\w-\.]+) \[(.*)\]") { | |
$inSource = $true | |
$source = @{ | |
name = $Matches[1] | |
enabled = $Matches[2] -eq 'Enabled' | |
testedAndExists = $false | |
path = '' | |
} | |
} elseif ($inSource) { | |
$inSource = $false | |
$source.path = $_.Trim() | |
$sources += [PSCustomObject]$source | |
$source = $null | |
} else { | |
$inSource = $false | |
} | |
} | |
$sources | |
} | |
task DockerBuild { | |
if ($userName -and $pass -and $nugetUrl) { | |
$parms = @() | |
if ($noCache) { | |
$parms += "--no-cache" | |
} | |
if ($dockerPlain) { | |
$parms += "--progress" | |
$parms += "plain" | |
} | |
"Dockerfile is $Dockerfile" | |
exec -workingDirectory $sourceDir { | |
if (!(Test-Path 'packages/C*.nupkg')) { | |
# we don't have packages folder, but is there one? | |
if ((Get-Item *.sln).Name -match "(.*)(Api|Service)\.sln") { | |
Write-Verbose "Found SLN for $($Matches | out-string)" | |
$source = Get-NugetSource | Where-Object { $_.name -eq "$($Matches[1])Messages" -and $_.enabled } | |
if ($source) { | |
Write-Verbose "Copying from $($source.path) to .\packages\" | |
xcopy $source.path .\packages\ | |
} else { | |
throw "Couldn't find NuGet source for $($Matches[1])Messages. Build with the Service project" | |
} | |
} else { | |
throw "No sln found in $sourceDir" | |
} | |
} | |
docker build --rm --tag $dockerTag ` | |
--build-arg userName="$userName" ` | |
--build-arg pass=$pass ` | |
--build-arg nugetUrl=$nugetUrl ` | |
--file $dockerfile ` | |
@parms ` | |
. | |
$image = ($dockerTag -split ':')[0] | |
if ($LASTEXITCODE -eq 0) | |
{ | |
docker images $dockerTag -q | ForEach-Object { docker tag $_ "${image}:latest" } | |
"Created image with tag: $dockerTag and ${image}:latest" | |
} | |
} | |
} else { | |
Write-Error "Must supply username, pass, and nugetUrl to build Docker image" | |
} | |
} | |
function GetSharedAppsettings | |
{ | |
[CmdletBinding()] | |
param() | |
Set-StrictMode -Version Latest | |
$folder = Split-Path $PWD -Parent | |
while ($folder -and !(Test-Path (Join-Path $folder shared_appsettings.json))) { | |
$folder = Split-Path $folder -Parent | |
} | |
if ($folder -and (Test-Path (Join-Path $folder shared_appsettings.json))) { | |
Write-Verbose "Found $folder/shared_appsettings.json" | |
return Join-Path $folder shared_appsettings.json | |
} else { | |
Write-Warning ">>> Couldn't find shared_appsettings.json above $PWD" | |
Write-Warning ">>> Active MQ etc. won't work." | |
Write-Warning ">>> See README.md" | |
throw "Couldn't find shared_appsettings.json above $PWD. See README.md" | |
} | |
} | |
task helmInstall { | |
$parms = @() | |
if ($helmWait) { | |
$parms += "--wait" # default wait is 5m0s | |
} | |
if ($helmDryRun) { | |
$parms += "--dry-run" | |
} | |
$sets = @( | |
'--set', 'cas-service.image.tag=latest', | |
'--set', 'cas-service.image.repository=""', | |
'--set', 'cas-service.image.pullPolicy=Never', | |
'--set', 'cas-service.deployFlow=false' | |
) | |
exec { helm dependency build } -workingdir $PSScriptRoot/build/helm | |
exec { helm upgrade --install --values (GetSharedAppsettings) $containerName @sets . @parms} -workingdir $PSScriptRoot/build/helm | |
} | |
task helmUniInstall { | |
exec { helm uninstall $containerName } | |
} | |
function CreateEnvList { | |
$dockerEnvList = New-TemporaryFile | |
$envList = @{} | |
if (Test-Path .\env.list) { | |
Get-Content .\env.list | ForEach-Object { | |
$equals = $_.IndexOf('=') | |
if ($equals -gt 0 ) { | |
$envList[$_.SubString(0,$equals)] = $_.SubString($equals+1) | |
} | |
} | |
} | |
$sharedSettings = GetSharedAppsettings | |
if ($sharedSettings) { | |
$config = Get-Content $sharedSettings -Raw | ConvertFrom-Json | |
$config | Get-Member -MemberType NoteProperty | | |
ForEach-Object { | |
$value = $config."$($_.Name)" -replace 'localhost','host.docker.internal' | |
$envList[$_.Name -replace ':','__']=$value | |
} | |
} | |
$launchSettings = @(Get-ChildItem .\launchsettings.json -r | Where-Object FullName -notlike '*Test*') | |
if ($launchSettings.Count -gt 1) { | |
Write-Warning "Merging more than one non-test launchsettings.json into env.list" | |
} elseif ($launchSettings) { | |
foreach ($ls in $launchSettings) { | |
$settings = Get-Content $launchSettings[0] | ConvertFrom-Json | |
try { | |
$config = $settings.profiles.Kestrel.environmentVariables | |
} catch { | |
throw "Error trying to process profiles.Kestrel.environmentVariables in $($launchSettings[0])" | |
} | |
$config | Get-Member -MemberType NoteProperty | | |
ForEach-Object { | |
$value = $config."$($_.Name)" -replace 'localhost','host.docker.internal' | |
$envList[$_.Name -replace ':','__']=$value | |
} | |
} | |
} | |
$envList.Keys | ForEach-Object { "$_=$($envList[$_])" } | Out-File $dockerEnvList -Encoding ascii | |
$dockerEnvList | |
} | |
task DockerRun { | |
$latest = $dockerTag -replace ":.*",":latest" | |
"Attempting to run image: $latest named $containerName. Container id follows." | |
">>>>" | |
">>>>" | |
">>>> URL will be http://localhost:$localPort/swagger" | |
">>>>" | |
">>>>" | |
$envList = CreateEnvList | |
exec -workingDirectory $sourceDir { | |
docker run --rm ` | |
--publish "${localPort}:$aspNetPort" ` | |
--env "ASPNETCORE_URLS=$ASPNETCORE_URLS" ` | |
--env-file $envList ` | |
--detach ` | |
--name $containerName ` | |
--network services ` | |
$latest | |
"If the container isn't running, use .\run.ps1 DockerInteractive to get output" | |
"URL is http://localhost:$localPort/swagger" | |
} | |
Remove-Item $envList | |
} | |
task DockerInteractive { | |
$latest = $dockerTag -replace ":.*",":latest" | |
"Attempting to run image: $latest named $containerName. Container id follows." | |
">>>>" | |
">>>>" | |
">>>> URL will be http://localhost:$localPort/swagger" | |
">>>>" | |
">>>>" | |
$envList = CreateEnvList | |
exec -workingDirectory $sourceDir { | |
docker run --rm ` | |
--publish "${localPort}:$aspNetPort" ` | |
--env "ASPNETCORE_URLS=$ASPNETCORE_URLS" ` | |
--env-file $envList ` | |
--interactive ` | |
--tty ` | |
--name $containerName ` | |
--network services ` | |
$latest | |
} | |
Remove-Item $envList | |
} | |
task DockerStop { | |
docker stop $containerName | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment