Public/Common/Initialize-AutomationWorkspace.ps1
|
function Initialize-AutomationWorkspace { <# .SYNOPSIS Initialises a customer workspace: config, folders, logging and secrets awareness. .DESCRIPTION Loads workspace.json from the workspace root (a customer repo scaffolded by bootstrap.ps1) and deep-merges the gitignored workspace.local.json over it when present. Resolves the data, output and exports folders to absolute paths against the root, creates the output and log folders, stores the result in module scope (see Get-AutomationWorkspace) and starts logging under <outputFolder>\log. Warns - without throwing - when secrets\secrets.json is missing so read-only flows still work. The banner and all log output contain paths only, never secrets. .PARAMETER Path Workspace root: the folder containing workspace.json. Defaults to the current directory. .PARAMETER NoLogging Skip starting the file logger (useful for tests and quick sessions). .EXAMPLE Initialize-AutomationWorkspace -Path $PSScriptRoot #> [CmdletBinding()] param( [string]$Path = (Get-Location).Path, [switch]$NoLogging ) $Path = (Resolve-Path -LiteralPath $Path).Path $configFile = Join-Path $Path 'workspace.json' if (-not (Test-Path -LiteralPath $configFile)) { throw "No workspace.json found in '$Path'. Is this a customer workspace? Bootstrap one with: irm https://raw.githubusercontent.com/nkdAgility/azure-devops-automation-tools/main/bootstrap.ps1 | iex" } $config = @{} foreach ($property in (Get-Content -LiteralPath $configFile -Raw | ConvertFrom-Json).PSObject.Properties) { $config[$property.Name] = $property.Value } $localFile = Join-Path $Path 'workspace.local.json' if (Test-Path -LiteralPath $localFile) { foreach ($property in (Get-Content -LiteralPath $localFile -Raw | ConvertFrom-Json).PSObject.Properties) { $config[$property.Name] = $property.Value } } $resolveFolder = { param([string]$value, [string]$default) if (-not $value) { $value = $default } if ([System.IO.Path]::IsPathRooted($value)) { $value } else { Join-Path $Path $value } } $script:Workspace = @{ Root = $Path DataFolder = & $resolveFolder $config['dataFolder'] 'data' OutputFolder = & $resolveFolder $config['outputFolder'] 'output' ExportsFolder = & $resolveFolder $config['exportsFolder'] 'exports' SecretsPath = Join-Path $Path 'secrets\secrets.json' QueryString = if ($config['queryString']) { $config['queryString'] } else { 'api-version=7.0' } QueryStringPreview = if ($config['queryStringPreview']) { $config['queryStringPreview'] } else { 'api-version=7.1-preview.3' } } New-Item -Path $script:Workspace.OutputFolder -ItemType Directory -Force | Out-Null if (-not $NoLogging) { Initialize-AutomationLogging -LogFolder (Join-Path $script:Workspace.OutputFolder 'log') } Write-FixSection "Workspace: $Path" Write-FixStep "Data: $($script:Workspace.DataFolder)" Write-FixStep "Output: $($script:Workspace.OutputFolder)" Write-FixStep "Exports: $($script:Workspace.ExportsFolder)" if (-not (Test-Path -LiteralPath $script:Workspace.SecretsPath)) { Write-Warning "No secrets file at $($script:Workspace.SecretsPath). Copy secrets\secrets.example.json to secrets\secrets.json and fill in the PATs." } elseif (-not (Get-AutomationSecrets -SecretsPath $script:Workspace.SecretsPath | Where-Object AccessToken)) { Write-Warning "Secrets file $($script:Workspace.SecretsPath) has no usable tokens (all empty or placeholders)." } return Get-AutomationWorkspace } |