Save-GitHubRelease.ps1


<#PSScriptInfo
 
.VERSION 0.2
 
.GUID 3dd5af75-fbb9-48b0-b464-317ddf712068
 
.AUTHOR Krishna C Vutukuri
 
.COMPANYNAME
 
.COPYRIGHT
 
.TAGS GitHub
 
.LICENSEURI
 
.PROJECTURI
 
.ICONURI
 
.EXTERNALMODULEDEPENDENCIES
 
.REQUIREDSCRIPTS
 
.EXTERNALSCRIPTDEPENDENCIES
 
.RELEASENOTES
 
#>


<#
.Description
Downloads release files from a github repository.
 
.Parameter Owner
This is your user or organization name.
 
.Parameter Repository
This is your repository name.
 
.Parameter DestinationPath
This is a folder where the files will be downloaded to.
 
.Parameter Release
Name of the release. This could be either 'latest' or 'tag name' of the release to download.
Default is latest.
 
.Parameter AccessToken
Token to access releases from a private repo.
#>

param(
    [Parameter(Mandatory = $true)]
    [string] $Owner,

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

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

    [Parameter()]
    [string] $Release = 'latest',

    [Parameter()]
    [string] $AccessToken,

    [Parameter()]
    [switch] $force
)

if (-not ([System.IO.Directory]::Exists($DestinationPath))) {   
    if ($force) {
        $null = New-Item -ItemType Directory -Path $DestinationPath
    }
    else {
        throw "Directory $DestinationPath does not exist."
    }
}

$headers = @{}
if ($AccessToken) {
    $headers.Add("Authorization", "token $AccessToken");
}

# Get the release information. We need assets
$gurl = "https://api.github.com/repos/$owner/$Repository/releases/$Release"
if ($release -ne 'latest') {
    $gurl = "https://api.github.com/repos/$owner/$Repository/releases/tags/$Release"
}

Write-Verbose "Getting release information from $gurl"
$releaseInfo = Invoke-RestMethod -Headers $headers $gurl -UseBasicParsing
if (-not $releaseInfo) {
    throw "Release $release for Repository $Repository not found."
}

# Download all assets from the release
$headers.Add('Accept', 'application/octet-stream')
$releaseInfo.Assets | ForEach-Object {
    $outFile = Join-Path $DestinationPath $_.name
    Write-Verbose "Downlading $($_.url) to $outFile"

    $response = Invoke-WebRequest -Headers $headers -Uri $_.url -UseBasicParsing
    # As per GitHub documentation https://developer.github.com/v3/repos/releases/
    # the client's should handle redirection
    if ($response.StatusCode -eq 302) {
        $redirectUri = $response.Headers["Location"].ToString()
        $response = Invoke-WebRequest -Headers $headers -Uri $redirectUri -UseBasicParsing
    }

    # Now save the content to the file
    $fs = [System.IO.FileStream]::new($outFile, [System.IO.FileMode]::OpenOrCreate)
    try {
        $response.RawContentStream.WriteTo($fs)
    }
    finally {
        $fs.Close()
        $fs.Dispose()
    }
} # Assets