Netscoot.Core/Public/Update-Netscoot.ps1

function Update-Netscoot {
    <#
    .SYNOPSIS
        Update an installed netscoot to the latest GitHub release, in place. The one-command
        update for non-clone installs.
 
    .DESCRIPTION
        Checks GitHub for a newer release (via Test-NetscootUpdate) and, if the installed version
        is behind, runs the release's install.ps1 to overwrite the modules on your module path. No
        git, no clone. Does nothing when already current unless -Force. Honors -WhatIf/-Confirm.
 
        After it runs, reload the module in the current session with `Import-Module Netscoot -Force`.
        Needs network access to GitHub. For Gallery installs, use `Update-Module Netscoot` (with
        `-AllowPrerelease` for betas) instead. This command updates installer/clone installs in place
        from the GitHub release, and replaces a Gallery install's folder with an installer copy.
 
        When the update policy is Disabled (see Set-NetscootUpdatePolicy), this refuses to update.
        -Force overrides a policy you set for yourself, never one an administrator set.
 
    .PARAMETER Force
        Reinstall the latest release even if already current, and override a Disabled update policy
        that you set for yourself.
 
    .PARAMETER Repository
        The GitHub repository to install from, in `owner/name` form. Defaults to the project
        repository.
 
    .PARAMETER Channel
        Which releases to consider: Stable or Beta (prerelease releases too). Defaults to the resolved
        channel (Get-NetscootUpdateChannel). Set Beta to track prerelease builds.
 
    .OUTPUTS
        Netscoot.Update - the record from Test-NetscootUpdate, so the decision is inspectable. Nothing
        when the update policy blocks the update or the check fails.
 
    .EXAMPLE
        # Update to the latest release if the installed copy is behind
        Update-Netscoot
        # Report what it would do without downloading or installing
        Update-Netscoot -WhatIf
        # Reinstall the latest even if already up to date
        Update-Netscoot -Force
 
    .LINK
        Test-NetscootUpdate
 
    .LINK
        Get-NetscootUpdatePolicy
 
    .LINK
        Set-NetscootUpdatePolicy
    #>

    [CmdletBinding(SupportsShouldProcess, ConfirmImpact = 'Medium')]
    [OutputType('Netscoot.Update')]
    param(
        [switch]$Force,
        [ValidatePattern('^[^/]+/[^/]+$')]
        [string]$Repository = 'kappasims/netscoot',
        [ValidateSet('Stable', 'Beta')]
        [string]$Channel = (Get-NetscootUpdateChannel).Channel
    )

    # Policy kill-switch, checked before the network call so a disabled fleet makes no request.
    # -Force overrides a Disabled the user set for themselves, never an administrator's.
    $policy = Get-NetscootUpdatePolicy
    if ($policy.State -eq 'Disabled') {
        if ($policy.Source -eq 'Machine') {
            Write-Warning 'Updates are disabled by an administrator (machine-scope policy); -Force cannot override. Update through your managed pipeline, or contact your administrator.'
            return
        }
        if (-not $Force) {
            Write-Warning 'Updates are disabled by the update policy. Use -Force to override, or run Set-NetscootUpdatePolicy -State Manual.'
            return
        }
    }

    $check = Test-NetscootUpdate -Repository $Repository -Channel $Channel
    if (-not $check) { return }   # connection error already surfaced by Test-NetscootUpdate

    if (-not $check.UpdateAvailable -and -not $Force) {
        Write-Host "netscoot is already up to date (installed $($check.Installed))." -ForegroundColor Green
        return $check
    }

    if ($PSCmdlet.ShouldProcess('Netscoot', "update to $($check.Tag) from GitHub")) {
        $tmp = Join-Path ([System.IO.Path]::GetTempPath()) ("netscoot_update_" + [guid]::NewGuid().ToString('N').Substring(0, 8) + '.ps1')
        try {
            # -OutFile writes the installer without a content-write cmdlet (keeps the first-party
            # drift monitor happy); Unblock-File clears the mark-of-the-web so it can run.
            Invoke-WebRequest -Uri "https://raw.githubusercontent.com/$Repository/$($check.Tag)/install.ps1" `
                -OutFile $tmp -Headers @{ 'User-Agent' = 'Netscoot' } -ErrorAction Stop
            if (Get-Command Unblock-File -ErrorAction SilentlyContinue) { Unblock-File -LiteralPath $tmp }
            & $tmp
            Write-Host 'Reload it in this session: Import-Module Netscoot -Force' -ForegroundColor Cyan
        } finally {
            Remove-Item -LiteralPath $tmp -Force -ErrorAction SilentlyContinue
        }
    }
    return $check
}