Public/GitLab.ps1
|
# PSSnips — GitLab Snippets integration. function Get-GitLabSnipList { <# .SYNOPSIS Lists GitLab snippets for the authenticated user. .DESCRIPTION Calls the GitLab Snippets API (GET /api/v4/snippets) and displays a formatted table of snippets showing ID, Title, Visibility, and FileName. .PARAMETER Filter Optional substring to match against title and file_name. .PARAMETER Count Optional. Maximum number of snippets to retrieve. Default: 30. .EXAMPLE Get-GitLabSnipList .EXAMPLE Get-GitLabSnipList -Filter 'deploy' -Count 50 .INPUTS None. .OUTPUTS System.Management.Automation.PSCustomObject[] .NOTES Requires GitLabToken config or $env:GITLAB_TOKEN. #> [CmdletBinding()] [OutputType([PSCustomObject[]])] param( [string]$Filter = '', [uint32]$Count = 30 ) script:InitEnv $p = script:Get-RemoteProvider -Name 'GitLab' if (-not $p.IsConfigured()) { script:Out-Err 'GitLab credentials not configured. Run Set-SnipConfig -GitLabToken <token>.'; return } try { $snips = @($p.ListRemote($Filter)) } catch { Write-Error "GitLab API error: $_" -ErrorAction Continue; return } if ([int]$Count -lt $snips.Count) { $snips = $snips[0..([int]$Count - 1)] } if (-not $snips -or $snips.Count -eq 0) { script:Out-Info "No GitLab snippets found."; return } Write-Host "" Write-Host (" {0,-10} {1,-40} {2,-10} {3}" -f 'ID','TITLE','VISIBILITY','FILENAME') -ForegroundColor DarkCyan Write-Host " $('─' * 80)" -ForegroundColor DarkGray foreach ($s in $snips) { $fn = if ($s.file_name) { $s.file_name } else { '' } Write-Host (" {0,-10} {1,-40} {2,-10} {3}" -f $s.id, $s.title, $s.visibility, $fn) -ForegroundColor Gray } Write-Host "" return $snips } function Get-GitLabSnip { <# .SYNOPSIS Fetches and displays a specific GitLab snippet by ID. .DESCRIPTION Calls GET /api/v4/snippets/<id> and GET /api/v4/snippets/<id>/raw, returning the snippet object with RawContent added. .PARAMETER SnipId Mandatory. The GitLab snippet ID. .EXAMPLE Get-GitLabSnip 12345 .INPUTS None. .OUTPUTS System.Management.Automation.PSCustomObject .NOTES Requires GitLabToken config or $env:GITLAB_TOKEN. #> [CmdletBinding()] [OutputType([PSCustomObject])] param( [Parameter(Mandatory, Position=0, HelpMessage='GitLab snippet ID')] [ValidateNotNullOrEmpty()] [string]$SnipId ) script:InitEnv $p = script:Get-RemoteProvider -Name 'GitLab' try { $snip = $p.GetRemoteById($SnipId) } catch { Write-Error "GitLab API error: $_" -ErrorAction Continue; return } $raw = $snip.RawContent $snip | Add-Member -NotePropertyName RawContent -NotePropertyValue $raw -Force Write-Host "" Write-Host (" Snippet: {0} (ID: {1})" -f $snip.title, $SnipId) -ForegroundColor Cyan if ($snip.description) { Write-Host " $($snip.description)" -ForegroundColor Gray } Write-Host " $($snip.web_url)" -ForegroundColor DarkCyan Write-Host "" Write-Host $raw Write-Host "" return $snip } function Import-GitLabSnip { <# .SYNOPSIS Downloads a GitLab snippet and saves it as a local snippet. .DESCRIPTION Fetches the raw content from /api/v4/snippets/<id>/raw and metadata from /api/v4/snippets/<id>, then saves to local snippets dir and registers in the index with gitlabId and gitlabUrl fields. .PARAMETER SnipId Mandatory. The GitLab snippet ID to import. .PARAMETER Name Optional. Override the local snippet name. .PARAMETER Force Optional switch. Overwrites existing snippet with the same name. .EXAMPLE Import-GitLabSnip 12345 .EXAMPLE Import-GitLabSnip 12345 -Name my-local-name -Force .INPUTS None. .OUTPUTS None. .NOTES Requires GitLabToken config or $env:GITLAB_TOKEN. The gitlabId and gitlabUrl are stored in the index for future sync. #> [CmdletBinding()] param( [Parameter(Mandatory, Position=0, HelpMessage='GitLab snippet ID to import')] [ValidateNotNullOrEmpty()] [string]$SnipId, [string]$Name = '', [switch]$Force ) script:InitEnv $cfg = script:LoadCfg $p = script:Get-RemoteProvider -Name 'GitLab' try { $meta = $p.GetRemoteById($SnipId) $raw = $meta.RawContent } catch { Write-Error "GitLab API error: $_" -ErrorAction Continue; return } $fn = if ($meta.file_name) { $meta.file_name } else { 'snippet.txt' } $ext = [System.IO.Path]::GetExtension($fn).TrimStart('.') if (-not $ext) { $ext = 'txt' } $snipName = if ($Name) { $Name } else { [System.IO.Path]::GetFileNameWithoutExtension($fn) } $idx = script:LoadIdx # Deduplicate name if ($idx.snippets.ContainsKey($snipName) -and -not $Force) { $base = $snipName; $n = 1 while ($idx.snippets.ContainsKey($snipName)) { $snipName = "$base-$n"; $n++ } } Set-Content (Join-Path $cfg.SnippetsDir "$snipName.$ext") -Value $raw -Encoding UTF8 $glMeta = [SnippetMetadata]::new() $glMeta.Name = $snipName $glMeta.Description = if ($meta.description) { $meta.description } else { if ($meta.title) { $meta.title } else { '' } } $glMeta.Language = $ext $glMeta.ContentHash = script:GetContentHash -Content $raw Add-Member -InputObject $glMeta -NotePropertyName 'GitLabId' -NotePropertyValue $SnipId -Force Add-Member -InputObject $glMeta -NotePropertyName 'GitLabUrl' -NotePropertyValue (if ($meta.web_url) { $meta.web_url } else { '' }) -Force $idx.snippets[$snipName] = $glMeta script:SaveIdx -Idx $idx script:Out-OK "Imported GitLab snippet '$snipName' ($ext)." script:Write-AuditLog -Operation 'Import' -SnippetName $snipName } function Export-GitLabSnip { <# .SYNOPSIS Exports a local snippet to GitLab as a new or updated snippet. .DESCRIPTION Creates (POST /api/v4/snippets) or updates (PUT /api/v4/snippets/<id>) a GitLab snippet. After success, saves gitlabId and gitlabUrl to the index. .PARAMETER Name Mandatory. The local snippet name to export. .PARAMETER Description Optional. Description for the GitLab snippet. .PARAMETER Visibility Optional. 'public', 'internal', or 'private'. Default: 'private'. .EXAMPLE Export-GitLabSnip my-snippet .EXAMPLE Export-GitLabSnip my-snippet -Description 'Deploy script' -Visibility internal .INPUTS None. .OUTPUTS None. .NOTES Requires GitLabToken config or $env:GITLAB_TOKEN. If snippet already has a gitlabId, the existing GitLab snippet is updated. #> [CmdletBinding()] param( [Parameter(Mandatory, Position=0, HelpMessage='Local snippet name to export')] [ValidateNotNullOrEmpty()] [string]$Name, [string]$Description = '', [ValidateSet('public','internal','private')] [string]$Visibility = 'private' ) script:InitEnv $idx = script:LoadIdx if (-not $idx.snippets.ContainsKey($Name)) { Write-Error "Snippet '$Name' not found." -ErrorAction Continue; return } $meta = $idx.snippets[$Name] $path = script:FindFile -Name $Name if (-not $path -or -not (Test-Path $path)) { Write-Error "Snippet file for '$Name' not found." -ErrorAction Continue; return } $content = Get-Content $path -Raw -Encoding UTF8 $fn = "$Name.$($meta.Language)" $desc = if ($Description) { $Description } elseif ($meta.Description) { $meta.Description } else { $Name } $p = script:Get-RemoteProvider -Name 'GitLab' if (-not $p.IsConfigured()) { Write-Error "GitLab credentials not configured. Run Set-SnipConfig -GitLabToken <token>." -ErrorAction Continue; return } $glId = if ($null -ne $meta.PSObject.Properties['GitLabId'] -and $meta.GitLabId) { $meta.GitLabId } else { $null } try { if ($glId) { $p.UpdateRemote($glId, $fn, $content) $glUrl = if ($null -ne $meta.PSObject.Properties['GitLabUrl']) { $meta.GitLabUrl } else { '' } } else { $result = $p.CreateRemote($desc, $content, $meta.Language, ($Visibility -eq 'private')) $idx.snippets[$Name].GitLabId = $result.Id $idx.snippets[$Name].GitLabUrl = $result.Url script:SaveIdx -Idx $idx $glUrl = $result.Url } script:Out-OK "GitLab snippet $(if ($glId) {'updated'} else {'created'}): $glUrl" script:Write-AuditLog -Operation 'Export' -SnippetName $Name script:Invoke-SnipEvent -EventName 'SnipPublished' -Data @{ Name = $Name Provider = 'gitlab' Url = $glUrl } } catch { Write-Error "Failed to export to GitLab: $_" -ErrorAction Continue } } |