tasks/common.tasks.ps1

$PackagesDir ??= "_packages"
$CoverageDir ??= "_codeCoverage"
$CoverageDir = [IO.Path]::IsPathRooted($CoverageDir) ? $CoverageDir : (Join-Path $here $CoverageDir)


$SkipBuildModuleVersionCheck = $false
$SkipPrAutoflowVersionCheck = $false
$SkipPrAutoflowEnrollmentCheck = $false

# Synopsis: Allows build properties to be overriden by environment variables
task ApplyEnvironmentVariableOverrides {

    # dot-source the function to load into the same scope as
    # the InvokeBuild process, otherwise as a module function it
    # won't havea ccess to any of the variables it needs to update
    . $PSScriptRoot/../functions/_Set-VariableFromEnvVar.ps1
    
    $buildEnvVars = Get-ChildItem env:BUILDVAR_*
    foreach ($buildEnvVar in $buildEnvVars) {
        # strip the 'BUILDVAR_' prefix to leave the variable name to be overridden
        $varName = $buildEnvVar.Name -replace "^BUILDVAR_",""

        $res = Set-VariableFromEnvVar -VariableName $varName -EnvironmentVariableName $buildEnvVar.Name

        if ($res) {
            Write-Build Yellow "Overriding '$varName' from environment variable [Value=$((Get-Item variable:/$varName).Value)] [Type=$((Get-Item variable:/$varName).Value.GetType().Name)]"
        }
    }
}

task CheckLatestVersion -If { !$SkipBuildModuleVersionCheck } {
    $currentVersion = (get-module Endjin.RecommendedPractices.Build).Version
    [version]$latestVersion = (Find-Module Endjin.RecommendedPractices.Build -Repository PSGallery).Version
    if ($currentVersion -lt $latestVersion) {
        $msg = @"
A newer Endjin.RecommendedPractices.Build version is available: $latestVersion
An overnight CodeOps process should automatically update this, alternatively, you can manually update by changing the default value of the '`$BuildModuleVersion' parameter in this build script to be '$latestVersion'
"@

        Write-Warning $msg
    }
    else {
        Write-Build Green "Build tooling is up-to-date"
    }
}

task CheckPrAutoflowVersion -If { !$SkipPrAutoflowVersionCheck -and $script:repoIsEnrolledWithPrAutoflow } EnsureGitHubCli,{

    $sourceRepo = "endjin/endjin-codeops"
    $sourceRepoPath = "repo-level-processes/pr-autoflow/workflow-templates"
    $workflowsToCheck = @(
        "auto_release.yml"
        "dependabot_approve_and_label.yml"
    )

    $allWorkflowsUpToDate = $true
    foreach ($workflow in $workflowsToCheck) {
        $resp = $null
        exec { & gh api "repos/$sourceRepo/contents/$sourceRepoPath/$workflow" } |
            ConvertFrom-Json -Depth 100 |
            Tee-Object -Variable resp
        $latestWorkflow = [System.Text.Encoding]::UTF8.GetString([System.Convert]::FromBase64String(($resp).content))
        if ($IsWindows) {
            # Convert the linux line-endings so we can compare it to our local file
            $latestWorkflow = $latestWorkflow -replace "`n","`r`n"
        }
        $currentWorkflow = Get-Content -Raw $here/.github/workflows/$workflow
        if (Compare-Object $latestWorkflow $currentWorkflow -CaseSensitive) {
            $allWorkflowsUpToDate = $false
            Write-Warning "Out-dated workflow: $workflow"
        }
    }

    if ($allWorkflowsUpToDate) {
        Write-Build Green "All 'pr-autoflow' workflows are up-to-date"
    }
    else {
        Write-Warning "Out-of-date workflows can be updated (for all repos) by triggering this workflow: https://github.com/endjin/endjin-codeops/actions/workflows/deploy_pr_autoflow.yml"
    }
}

task CheckPrAutoflowEnrollment -If { !$SkipPrAutoflowEnrollmentCheck } EnsureGitHubCli,{

    # Ensure the YAML parsing module is installed
    if (!(Get-Module -ListAvailable powershell-yaml)) {
        Write-Host "Installing required module: powershell-yaml"
        Install-Module powershell-yaml -Scope CurrentUser -Force -Repository PSGallery -RequiredVersion 0.4.7
    }

    # Workaround for powershell-yaml bug whereby it overwrites the '$here' variable in the calling scope
    $here_backup = $here
    Import-Module powershell-yaml
    $script:here = $here_backup

    # TODO: This needs to be abstracted as OSS users will need to be able to specify their own repo
    $sourceRepo = "endjin/endjin-codeops"
    $sourceRepoPath = "repo-level-processes/config/live"
    $repoDetails = $null
    exec { gh repo view --json owner,name } |
        ConvertFrom-Json |
        Tee-Object -Variable repoDetails
    $orgName = $repoDetails.owner.login
    $repoName = $repoDetails.name

    $resp = $null
    exec { & gh api "repos/$sourceRepo/contents/$sourceRepoPath/$orgName.yml" } |
        ConvertFrom-Json -Depth 100 |
        Tee-Object -Variable resp
    $config = [System.Text.Encoding]::UTF8.GetString([System.Convert]::FromBase64String(($resp).content))
    $enrollment = $config | ConvertFrom-Yaml | ? { $repoName -in $_.repos.name -and $_.repos.ContainsKey("prAutoflowSettings") }
    $script:repoIsEnrolledWithPrAutoflow = $enrollment -ne $null
    if (!$repoIsEnrolledWithPrAutoflow) {
        Write-Warning "Repository not enrolled with 'pr-autoflow' - refer to https://github.com/endjin/endjin-codeops/blob/main/README.md#enrollment for how to enroll this repository."
    }
    else {
        Write-Build Green "Repository is enrolled with 'pr-autoflow'"
    }
}

task EnsureGitHubCli {
    if (!(Get-Command gh -ErrorAction SilentlyContinue)) {
        throw "The GitHub CLI is required - please install as per: https://github.com/cli/cli#installation"
    }

    # Test whether GitHub CLI is logged-in
    & gh repo view endjin/Endjin.RecommendedPractices.Build | Out-Null
    if ($LASTEXITCODE -eq 4) {
        throw "You must be logged-in to GitHub CLI to run this build. Please run 'gh auth login' to login and then re-run the build."
    }
}

task EnsurePackagesDir {
    # Ensure we resolve a relative path for $PackagesDir now, rather than letting it be resolved by downstream tooling
    # For example, 'dotnet pack' will resolve it relative to a given project which is not what we want.
    $script:PackagesDir = [IO.Path]::IsPathRooted($PackagesDir) ? $PackagesDir : (Join-Path $here $PackagesDir)

    if (!(Test-Path $PackagesDir)) {
        New-Item -Path $PackagesDir -ItemType Directory | Out-Null
    }
}

task RunChecks -If { !$IsRunningOnBuildServer } CheckLatestVersion,CheckPrAutoflowEnrollment,CheckPrAutoflowVersion