functions/powershell/module/Publish-MyModule.ps1

function Publish-MyModule {
    [CmdletBinding()]
    param (
        [Parameter(Mandatory = $false)]
        [string]$Path = (Resolve-Path -Path '.').Path,

        [Parameter(Mandatory = $true, ParameterSetName = 'NuGetApiKeySecretName')]
        [string]$NuGetApiKeySecretName,

        [Parameter(Mandatory = $true, ParameterSetName = 'NuGetApiKey')]
        [string]$NuGetApiKey,

        [Parameter(Mandatory = $true)]
        [string]$NewReleaseNote,

        [string]$Psm1HeaderBlock,
        [string]$Psm1VariablesBlock,

        [switch]$SkipDocsUpdate,
        # [switch]$SkipBuild,
        [switch]$SkipManifestUpdate,
        [switch]$SkipVersionAndReleaseNote
    )

    $CurrentErrorActionPreference = $ErrorActionPreference
    $ErrorActionPreference = 'Stop'

    $Path = (Resolve-Path -Path $Path).Path
    $moduleName = Split-Path -Path $Path -Leaf
    $psd1Path = Join-Path -Path $Path -ChildPath "$($moduleName).psd1"
    $functionsPath = Join-Path -Path $Path -ChildPath functions
    $docsPath = Join-Path -Path $Path -ChildPath docs

    if (-not (Test-Path -Path $psd1Path)) {
        Write-Error ".psd1 file not found at $($psd1Path)"
        return $false
    }
    if (-not (Test-Path -Path $functionsPath)) {
        Write-Error "functions directory not found at path: $($functionsPath)"
        return $false
    }
    if (-not (Test-Path -Path $docsPath)) {
        Write-Verbose "docs directory not found at path $($docsPath). Creating ..."
        New-Item -Path $docsPath -ItemType Directory -Force | Out-Null
    }

    # Cleanup if loaded
    Get-Module -Name $moduleName | Remove-Module

    # Dot-source functions
    Get-ChildItem -Path $functionsPath -Recurse -Filter *.ps1 -File | Where-Object { Select-String -Path $_.FullName -Pattern 'function\s+\w+' -Quiet } | ForEach-Object { . $_.FullName }

    Convert-ToUtf8Bom -Path $Path

    Update-Psm1FromSource -ModuleRoot $Path -UpdateManifest:(-not $SkipManifestUpdate) -Psm1HeaderBlock $Psm1HeaderBlock -Psm1VariablesBlock $Psm1VariablesBlock

    if (-not $SkipVersionAndReleaseNote) {
        Update-ModuleVersion -Path $Path -AutoIncrementRevision -ReleaseNote $NewReleaseNote
    }

    # PSScriptAnalyzer test
    if (-not (Get-Module -Name PSScriptAnalyzer)) {
        Import-Module -Name PSScriptAnalyzer
    }
    if ((Get-Command -Name Invoke-ScriptAnalyzer -ErrorAction SilentlyContinue)) {
        $analyzerResult = Invoke-ScriptAnalyzer -Path $Path
        if ($analyzerResult) {
            $analyzerResult

            $confirmation = Read-Host "ScriptAnalyzer-Ergebnis okay und fortfahren? (y/n)"
            if ($confirmation -ne 'y') {
                throw 'Veröffentlichungsprozess abgebrochen.'
            }
        }
    } else {
        Write-Warning "Command Invoke-ScriptAnalyzer not found!"
    }

    # Core manifest test
    Test-ModuleManifest $psd1Path

    # Update docs
    if (-not $SkipDocsUpdate) {
        Export-FunctionDocs -SourcePath $Path -OutputPath $docsPath
    }

    # TODO implement a build-required detection
    # if (-not $SkipBuild) {
    # dotnet build --configuration:Release
    # }

    if (-not $SkipVersionAndReleaseNote) {
        if (-not ([string]::IsNullOrWhiteSpace($NuGetApiKey))) {
            $apiKey = $NuGetApiKey
        } elseif (-not ([string]::IsNullOrWhiteSpace($NuGetApiKeySecretName))) {
            $apiKey = Get-Secret -Name $NuGetApiKeySecretName -AsPlainText
        } else {
            Write-Error "You must provide either -NuGetApiKey or -NuGetApiKeySecretName!"
            return $false
        }
        
        $newModule = Invoke-PublishModule -Path $Path -ExcludeListFile (Join-Path -Path $Path -ChildPath exclude-files.json) -NuGetApiKey $apiKey

        if ($null -ne $newModule) {
            Write-Verbose "Wait 10 seconds for PSGallery before installing the published module ..."
            Start-Sleep -Seconds 10

            Write-Verbose "Install $($moduleName) from PSGallery."
            Install-Module -Name $moduleName -Repository PSGallery -Force
            Import-Module -Name $moduleName -Force

            return $newModule
        }
    } else {
        Write-Warning "-SkipVersionAndReleaseNote was used, skipped publish process as the module version number stays the same!"
    }

    $ErrorActionPreference = $CurrentErrorActionPreference
}