Skip to content

Instantly share code, notes, and snippets.

@Seekatar
Last active March 7, 2021 12:12
Show Gist options
  • Save Seekatar/ae32fbe1e82d86d15c7d7342220a52ff to your computer and use it in GitHub Desktop.
Save Seekatar/ae32fbe1e82d86d15c7d7342220a52ff to your computer and use it in GitHub Desktop.
Psakefile for building, running dotnet app
<#
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