Created
March 7, 2024 17:59
-
-
Save jdhitsolutions/30cd246fd99dd442e4a75ddf0261c2ce to your computer and use it in GitHub Desktop.
My solution for the PowerShell Podcast scripting challenge to write PowerShell code to get GitHub issue statistics.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#requires -version 7.4 | |
<# | |
This function requires the gh.exe command line tool. | |
You many encounter API rate restrictions under heavy use. | |
#> | |
#load the custom formatting file | |
Update-FormatData $PSScriptRoot\ghLabelStatus.format.ps1xml | |
Function Get-ghIssueLabelCount { | |
[cmdletbinding()] | |
[OutputType('ghLabelStatus')] | |
[alias('ghlc')] | |
Param( | |
[Parameter( | |
Position = 0, | |
Mandatory, | |
ValueFromPipeline, | |
HelpMessage = 'Specify the Github owner and repo in the format: owner/repo. You might need to match casing with GitHub.' | |
)] | |
[ValidateNotNullOrEmpty()] | |
[ValidatePattern('\w+/\w+$', ErrorMessage = 'Please use the format OWNER/Repository. e.g. jdhitsolutions/psreleasetools')] | |
[string]$Repository, | |
[Parameter(HelpMessage = 'Specify the first X number of issue labels sorted by count in descending order.')] | |
[ValidateScript({ $_ -gt 0 }, ErrorMessage = 'Enter a value greater than 0.')] | |
[int]$First = 25, | |
[Parameter(HelpMessage = 'Specify the number of issues to analyze')] | |
[ValidateScript({ $_ -gt 0 }, ErrorMessage = 'Enter a value greater than 0.')] | |
[int]$Limit = 1000 | |
) | |
Begin { | |
Write-Verbose "[$((Get-Date).TimeOfDay) BEGIN ] Starting $($MyInvocation.MyCommand)" | |
Write-Verbose "[$((Get-Date).TimeOfDay) BEGIN ] Running under PowerShell version $($PSVersionTable.PSVersion)" | |
Write-Verbose "[$((Get-Date).TimeOfDay) BEGIN ] Using host: $($Host.Name)" | |
$ReportDate = Get-Date | |
} #begin | |
Process { | |
Try { | |
$gh = Get-Command -Name gh.exe -ErrorAction Stop | |
Write-Verbose "[$((Get-Date).TimeOfDay) PROCESS] Using $( gh.exe --version | Select-Object -First 1)" | |
Write-Verbose "[$((Get-Date).TimeOfDay) PROCESS] Processing $Limit issues from $Repository" | |
<# | |
gitHub issue Available JSON fields: | |
assignees | |
author | |
body | |
closed | |
closedAt | |
comments | |
createdAt | |
id | |
labels | |
milestone | |
number | |
projectCards | |
projectItems | |
reactionGroups | |
state | |
title | |
updatedAt | |
url | |
#> | |
$ghData = gh.exe issue list --repo $Repository --limit $Limit --json 'id,title,labels' | ConvertFrom-Json | |
Write-Verbose "[$((Get-Date).TimeOfDay) PROCESS] Found $($ghData.count) items" | |
} #Try | |
Catch { | |
Write-Warning 'This command requires the gh.exe command-line utility.' | |
} #Catch | |
If ($ghData.count -gt 0) { | |
Write-Verbose "[$((Get-Date).TimeOfDay) PROCESS] Getting top $First issue labels" | |
$data = $ghData.labels | | |
Group-Object -Property Name -NoElement | | |
Sort-Object Count, Name -Descending | | |
Select-Object -First $First | |
foreach ($Item in $data) { | |
#create a custom object | |
if ($item.Name -match '\s') { | |
$escName = '%22{0}%22' -f ($item.Name -replace '\s', '+') | |
$uri = "https://github.com/$Repository/issues?q=is%3Aissue+is%3Aopen+label%3A$escName" | |
} | |
else { | |
$uri = "https://github.com/$Repository/issues?q=is%3Aissue+is%3Aopen+label%3A$($Item.Name)" | |
} | |
[PSCustomObject]@{ | |
PStypeName = 'ghLabelStatus' | |
Count = $Item.Count | |
PctTotal = ($item.Count / $ghData.Count) * 100 | |
Label = $Item.Name | |
LabelUri = $uri | |
Repository = $Repository | |
IssueCount = $ghData.Count | |
ReportDate = $ReportDate | |
} | |
} | |
} #if data found | |
else { | |
Write-Warning "No open issues found in $Repository" | |
} | |
} #process | |
End { | |
Write-Verbose "[$((Get-Date).TimeOfDay) END ] Ending $($MyInvocation.MyCommand)" | |
} #end | |
} #close Get-ghIssueLabelCount |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#requires -version 7.4 | |
#a control script to generate a markdown report. | |
#ghLabelReport.ps1 | |
Param( | |
[Parameter( | |
Position = 0, | |
Mandatory, | |
ValueFromPipeline, | |
HelpMessage = 'Specify the Github owner and repo in the format: owner/repo. You might need to match casing with GitHub.' | |
)] | |
[ValidateNotNullOrEmpty()] | |
[ValidatePattern('\w+/\w+$', ErrorMessage = 'Please use the format OWNER/Repository. e.g. jdhitsolutions/psreleasetools')] | |
[string]$Repository, | |
[Parameter(HelpMessage = 'Specify the first X number of issue labels sorted by count in descending order.')] | |
[ValidateScript({ $_ -gt 0 }, ErrorMessage = 'Enter a value greater than 0.')] | |
[int]$First = 25, | |
[Parameter(HelpMessage = 'Specify the number of issues to analyze')] | |
[ValidateScript({ $_ -gt 0 }, ErrorMessage = 'Enter a value greater than 0.')] | |
[int]$Limit = 1000 | |
) | |
#dot source the required function | |
. $PSScriptRoot\Get-ghIssueStats.ps1 | |
$data = Get-ghIssueLabelCount @PSBoundParameters | |
if ($data) { | |
$repoIssues = "https://github.com/$($data[0].Repository)/issues" | |
$md = [System.Collections.Generic.List[string]]::New() | |
$md.Add("# Label Report for [$($data[0].Repository)]($repoIssues)`n") | |
$md.Add("This is the breakdown of labels based on __$($data[0].IssueCount)__ open issues. Total percentages might be more than 100% as issues can have multiple labels.`n") | |
$md.Add("Count| Percent of Total | Label|") | |
$md.Add("|-----|-----|-----|") | |
foreach ($item in $data) { | |
$md.Add("| $($item.count) | $([math]::Round($item.PctTotal,2)) | [$($item.Label)]($($item.LabelUri))|") | |
} | |
$md.Add("`n_$($data[0].ReportDate)_") | |
} | |
#write the markdown to the pipeline | |
$md |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<!-- | |
Format type data generated 12/04/2023 12:58:47 by PROSPERO\Jeff | |
This file was created using the New-PSFormatXML command that is part | |
of the PSScriptTools module. | |
https://github.com/jdhitsolutions/PSScriptTools | |
--> | |
<Configuration> | |
<ViewDefinitions> | |
<View> | |
<!--Created 12/04/2023 12:58:47 by PROSPERO\Jeff--> | |
<Name>default</Name> | |
<ViewSelectedBy> | |
<TypeName>ghLabelStatus</TypeName> | |
</ViewSelectedBy> | |
<GroupBy> | |
<ScriptBlock>"{0} [{1}]" -f $_.Repository,$_.ReportDate</ScriptBlock> | |
<Label>Repository</Label> | |
</GroupBy> | |
<TableControl> | |
<!--Delete the AutoSize node if you want to use the defined widths.--> | |
<AutoSize /> | |
<TableHeaders> | |
<TableColumnHeader> | |
<Label>Count</Label> | |
<Width>8</Width> | |
<Alignment>right</Alignment> | |
</TableColumnHeader> | |
<TableColumnHeader> | |
<Label>PctTotal</Label> | |
<Width>8</Width> | |
<Alignment>right</Alignment> | |
</TableColumnHeader> | |
<TableColumnHeader> | |
<Label>Label</Label> | |
<Width>15</Width> | |
<Alignment>left</Alignment> | |
</TableColumnHeader> | |
</TableHeaders> | |
<TableRowEntries> | |
<TableRowEntry> | |
<TableColumnItems> | |
<TableColumnItem> | |
<PropertyName>Count</PropertyName> | |
</TableColumnItem> | |
<TableColumnItem> | |
<ScriptBlock>"{0:p2}" -f ($_.Count/$_.IssueCount)</ScriptBlock> | |
</TableColumnItem> | |
<TableColumnItem> | |
<PropertyName>Label</PropertyName> | |
</TableColumnItem> | |
</TableColumnItems> | |
</TableRowEntry> | |
</TableRowEntries> | |
</TableControl> | |
</View> | |
<View> | |
<!--Created 12/04/2023 15:18:46 by PROSPERO\Jeff--> | |
<Name>uri</Name> | |
<ViewSelectedBy> | |
<TypeName>ghLabelStatus</TypeName> | |
</ViewSelectedBy> | |
<GroupBy> | |
<ScriptBlock> | |
$link = $PSStyle.FormatHyperlink($_.Repository,"https://github.com/$($_.Repository)/issues") | |
"$($PSStyle.Foreground.Yellow +$PSStyle.Italic)$link$($PSStyle.Reset) [$($_.ReportDate)]" | |
</ScriptBlock> | |
<Label>Repository</Label> | |
</GroupBy> | |
<TableControl> | |
<!--Delete the AutoSize node if you want to use the defined widths.--> | |
<AutoSize /> | |
<TableHeaders> | |
<TableColumnHeader> | |
<Label>Count</Label> | |
<Width>8</Width> | |
<Alignment>right</Alignment> | |
</TableColumnHeader> | |
<TableColumnHeader> | |
<Label>PctTotal</Label> | |
<Width>8</Width> | |
<Alignment>right</Alignment> | |
</TableColumnHeader> | |
<TableColumnHeader> | |
<Label>Label</Label> | |
<Width>14</Width> | |
<Alignment>left</Alignment> | |
</TableColumnHeader> | |
</TableHeaders> | |
<TableRowEntries> | |
<TableRowEntry> | |
<TableColumnItems> | |
<TableColumnItem> | |
<PropertyName>Count</PropertyName> | |
</TableColumnItem> | |
<TableColumnItem> | |
<ScriptBlock>"{0:p2}" -f ($_.Count/$_.IssueCount)</ScriptBlock> | |
</TableColumnItem> | |
<TableColumnItem> | |
<ScriptBlock> | |
$link = $PSStyle.FormatHyperlink($_.Label,$_.LabelUri) | |
"$($PSStyle.Foreground.Yellow +$PSStyle.Italic)$link$($PSStyle.Reset)" | |
</ScriptBlock> | |
</TableColumnItem> | |
</TableColumnItems> | |
</TableRowEntry> | |
</TableRowEntries> | |
</TableControl> | |
</View> | |
</ViewDefinitions> | |
</Configuration> |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
This code is explained at ;https://jdhitsolutions.com/blog/powershell/9343/github-scripting-challenge-solution/'(https://jdhitsolutions.com/blog/powershell/9343/github-scripting-challenge-solution/)