Skip to content

Instantly share code, notes, and snippets.

@gabriel-vanca
Last active August 6, 2024 00:54
Show Gist options
  • Save gabriel-vanca/4e6a2f17ff946d2d51a3ad7222eb29a9 to your computer and use it in GitHub Desktop.
Save gabriel-vanca/4e6a2f17ff946d2d51a3ad7222eb29a9 to your computer and use it in GitHub Desktop.
Get-ReleaseFromGithub
function Test-Repo {
param (
[Parameter(Mandatory)] [ValidateNotNullOrEmpty()] [String] $Repo
)
$repoName = $NULL
try {
$testUri = "https://api.github.com/repos/$Repo"
$temp = (Invoke-RestMethod -Method GET -Uri $testUri)
$repoName = $temp.name
Write-Host "Repo $repoName is valid" -ForegroundColor DarkGreen
} catch {
throw "Invalid repo"
}
try {
$testUri = "https://api.github.com/repos/$Repo/releases?per_page=100"
$temp = (Invoke-RestMethod -Method GET -Uri $testUri)
$releaseCount = ($temp | Where-Object prerelease -like $False).Count
$prereleaseCount = ($temp | Where-Object prerelease -like $True).Count
Write-Host "Repo $repoName has $releaseCount full releases and $prereleaseCount prereleases within the last 100 releases" -ForegroundColor DarkGreen
if(($releaseCount -eq 0) -and ($prereleaseCount -eq 0)) {
throw "No valid releases"
}
} catch {
throw "No valid releases"
}
return $True
}
function New-TemporaryDirectory {
[Cmdletbinding()]
[Alias('newtempdir')]
param()
do {
# Outer loop checks against race condition
do {
# Inner loop checks against collision
$tempDirPath = Join-Path $env:TEMP ($([System.IO.Path]::GetRandomFileName()) + ".tmp")
} while (Test-Path $tempDirPath)
$tempFile = New-Item -ItemType Directory -Path $tempDirPath -ErrorAction SilentlyContinue
} while (-not $tempFile)
return $tempFile
}
function Get-ReleaseFromGithub {
[CmdletBinding(
DefaultParameterSetName="LatestReleaseFiles"
)]
param (
[Parameter(Mandatory = $True, ParameterSetName = "LatestReleaseFiles", Position = 0)]
[Parameter(Mandatory = $True, ParameterSetName = "LatestPrereleaseFiles", Position = 0)]
[Parameter(Mandatory = $True, ParameterSetName = "TargetedReleaseFiles", Position = 0)]
[Parameter(Mandatory = $True, ParameterSetName = "LatestReleaseExtensions", Position = 0)]
[Parameter(Mandatory = $True, ParameterSetName = "LatestPrereleaseExtensions", Position = 0)]
[Parameter(Mandatory = $True, ParameterSetName = "TargetedReleaseExtensions", Position = 0)]
[ValidateNotNullOrEmpty()]
[string] $Repo,
[Parameter(Mandatory = $False, ParameterSetName = "LatestReleaseFiles", Position = 1)]
[Parameter(Mandatory = $False, ParameterSetName = "LatestPrereleaseFiles", Position = 1)]
[Parameter(Mandatory = $False, ParameterSetName = "TargetedReleaseFiles", Position = 1)]
[string[]] $Files = $NULL,
[Parameter(Mandatory = $False, ParameterSetName = "LatestReleaseExtensions", Position = 1)]
[Parameter(Mandatory = $False, ParameterSetName = "LatestPrereleaseExtensions", Position = 1)]
[Parameter(Mandatory = $False, ParameterSetName = "TargetedReleaseExtensions", Position = 1)]
[string[]] $Extensions = $NULL,
[Parameter(Mandatory = $False, ParameterSetName = "LatestReleaseFiles", Position = 2)]
[Parameter(Mandatory = $False, ParameterSetName = "LatestReleaseExtensions", Position = 2)]
[Switch] $IncludePreleases,
[Parameter(Mandatory = $False, ParameterSetName = "LatestPrereleaseFiles", Position = 2)]
[Parameter(Mandatory = $False, ParameterSetName = "LatestPrereleaseExtensions", Position = 2)]
[Switch] $IncludePreleasesOnly,
[Parameter(Mandatory = $True, ParameterSetName = "TargetedReleaseFiles", Position = 2)]
[Parameter(Mandatory = $True, ParameterSetName = "TargetedReleaseExtensions", Position = 2)]
[ValidateNotNullOrEmpty()]
[string] $Tag,
[Parameter(Mandatory = $False, Position = 3)]
[ValidateScript({ Test-Path $_ })]
[string] $DestinationPath = $NULL
)
BEGIN {
[Net.ServicePointManager]::SecurityProtocol = [Net.SecurityProtocolType]::Tls13
}
PROCESS {
# See API reference https://docs.github.com/en/rest/releases/releases?apiVersion=2022-11-28
switch -Wildcard ($PSCmdlet.ParameterSetName) {
"LatestRelease*" {
if($IncludePreleases) {
# Releases and Prereleases
$releasesUri = "https://api.github.com/repos/$Repo/releases?per_page=1"
} else {
# Releases only
$releasesUri = "https://api.github.com/repos/$Repo/releases/latest"
}
try {
$fullReleaseSet = Invoke-RestMethod -Method GET -Uri $releasesUri
$Tag = $fullReleaseSet.tag_name
}
catch {
Test-Repo $Repo
}
break;
}
"LatestPrerelease*" {
# Prereleases only
$releasesUri = "https://api.github.com/repos/$Repo/releases?per_page=100"
# Using "| Select-Object -First 1" over "[0]" so as not to get a "InvalidOperation: Cannot index into a null array." error when there are no matching releases
# Make sure the Invoke segment is in () ; otherwise you'll get an empty array
try {
$fullReleaseSet = (Invoke-RestMethod -Method GET -Uri $releasesUri) | Where-Object prerelease -like $True | Sort-Object @{Expression = "tag_name"; Descending = $true} | Select-Object -First 1
$Tag = $fullReleaseSet.tag_name
}
catch {
Test-Repo $Repo
}
break;
}
"TargetedRelease*" {
$releasesUri = "https://api.github.com/repos/$Repo/releases/tags/$Tag"
try {
$fullReleaseSet = Invoke-RestMethod -Method GET -Uri $releasesUri
}
catch {
if(Test-Repo $Repo) {
throw "Tag not valid"
}
}
# -ieq is the explicitly case-insensitive version of -eq.
if($fullReleaseSet.tag_name -ieq $Tag) {
Write-Verbose "Targeted release obtained succesfully"
} else {
throw "Targeted release failed"
}
break;
}
}
if($fullReleaseSet -and $Tag) {
Write-Host "Release obtained succesfully"
} else {
throw "Obtaining release failed for unknown reasons"
}
$fullReleaseSet.assets | foreach-object{$_ | Add-Member -MemberType NoteProperty -Name extension -Value ([io.path]::GetExtension($_.name)) }
$fullReleaseSet.assets | foreach-object{$_ | Add-Member -MemberType NoteProperty -Name nameWithoutExtension -Value ([io.path]::GetFileNameWithoutExtension($_.name))}
$releaseAssets = $NULL
switch -Wildcard ($PSCmdlet.ParameterSetName) {
"*Files*" {
$releaseAssets = $fullReleaseSet.assets | Where-Object {($.name -in $Files) -or ($.nameWithoutExtension -in $Files)}
break;
}
"*Extensions*" {
$releaseAssets = $fullReleaseSet.assets | Where-Object {$.extension -in $Extensions}
break;
}
}
if(!$releaseAssets) {
throw "No matching assets"
}
$tempDir = New-TemporaryDirectory
foreach ($currentAsset in $releaseAssets) {
}
$download = "https://github.com/$repo/releases/download/$tag/$file"
$name = $file.Split(".")[0]
$zip = "$name-$tag.zip"
$dir = "$name-$tag"
Write-Host Dowloading latest release
Invoke-WebRequest $download -Out $zip
Write-Host Extracting release files
Expand-Archive $zip -Force
# Cleaning up target dir
Remove-Item $name -Recurse -Force -ErrorAction SilentlyContinue
# Moving from temp dir to target dir
Move-Item $dir\$name -Destination $name -Force
# Removing temp files
Remove-Item $zip -Force
Remove-Item $dir -Recurse -Force
}
END {
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment