Private/Save-GitHubRepoArchive.ps1
|
function Save-GitHubRepoArchive { <# .SYNOPSIS Downloads and extracts a GitHub repository zip archive. .DESCRIPTION Downloads the zip archive of a public GitHub repository and extracts it to a temporary directory. Returns the path to the extracted repo contents (inside the single top-level prefix directory that GitHub creates). The caller is responsible for cleaning up the returned directory when done (Remove-Item -Recurse -Force on the parent temp directory). .PARAMETER Owner The GitHub repository owner (user or organization). .PARAMETER Repo The GitHub repository name. .PARAMETER Ref Branch, tag, or commit SHA. Defaults to 'master'. .OUTPUTS [PSCustomObject] with: - ExtractedPath: Path to the extracted repo contents - TempDirectory: Path to the temp directory (caller must clean up) .EXAMPLE $archive = Save-GitHubRepoArchive -Owner prowler-cloud -Repo prowler try { Get-ChildItem $archive.ExtractedPath } finally { Remove-Item $archive.TempDirectory -Recurse -Force } #> [CmdletBinding()] [OutputType([PSCustomObject])] param( [Parameter(Mandatory)] [ValidateNotNullOrEmpty()] [string]$Owner, [Parameter(Mandatory)] [ValidateNotNullOrEmpty()] [string]$Repo, [Parameter()] [ValidateNotNullOrEmpty()] [string]$Ref = 'master' ) $ErrorActionPreference = 'Stop' $tempDir = Join-Path ([System.IO.Path]::GetTempPath()) "github-archive-$([guid]::NewGuid().ToString('N').Substring(0,8))" New-Item -ItemType Directory -Path $tempDir -Force | Out-Null $zipPath = Join-Path $tempDir "$Repo-$Ref.zip" $extractDir = Join-Path $tempDir 'extracted' $uri = "https://github.com/$Owner/$Repo/archive/$Ref.zip" Write-Verbose "Downloading archive from $uri..." try { Invoke-WebRequest -Uri $uri -OutFile $zipPath -ErrorAction Stop Write-Verbose "Downloaded archive to $zipPath ($('{0:N1} MB' -f ((Get-Item $zipPath).Length / 1MB)))" Write-Verbose "Extracting archive..." Expand-Archive -Path $zipPath -DestinationPath $extractDir -Force -ErrorAction Stop # GitHub archives contain a single top-level directory like "prowler-master/" $topLevelDirs = @(Get-ChildItem -Path $extractDir -Directory) if ($topLevelDirs.Count -ne 1) { throw "Expected exactly 1 top-level directory in archive, found $($topLevelDirs.Count)" } $extractedPath = $topLevelDirs[0].FullName Write-Verbose "Extracted to $extractedPath" [PSCustomObject]@{ ExtractedPath = $extractedPath TempDirectory = $tempDir } } catch { # Clean up temp directory on failure if (Test-Path $tempDir) { Remove-Item $tempDir -Recurse -Force -ErrorAction SilentlyContinue } throw } finally { # Always clean up the zip file (extracted directory stays) if (Test-Path $zipPath) { Remove-Item $zipPath -Force -ErrorAction SilentlyContinue } } } |