Behind the PowerShell Pipeline logo

Behind the PowerShell Pipeline

Subscribe
Archives
October 18, 2024

Creating a GitHub Repository Tool - Part 4

I've come a long way with the project and the end is in sight. Hopefully, we can wrap up building my GitHub repository tool today. At this point, I have a PowerShell class-based tool with several functions for working with the GitHub repository data. I have a rich object.

PS C:\> $in[10]

Name              : PSReleaseTools
Description       : 🚢 A set of commands for working with PowerShell 7.x releases.
LastUpdate        : 8/29/2024 9:07:55 AM
Visibility        : Public
DefaultBranch     : master
LatestReleaseName : PSReleaseTools_v1.12.0
LatestReleaseDate : 6/4/2022 10:08:49 AM
LastPush          : 8/4/2024 4:57:03 PM
StargazerCount    : 112
WatcherCount      : 11
URL               : https://github.com/jdhitsolutions/PSReleaseTools
DiskUsage         : 3175
ID                : MDEwOlJlcG9zaXRvcnk3ODA1NTc4NA==
InfoDate          : 10/10/2024 3:21:25 PM
UpdateAge         : 43.05:12:53.9554832
isReleased        : True
ReleaseAge        : 860.04:11:59.9556128
IsEmpty           : False

Since last time, I've extended this object even further.

More Type Extensions

One thing I had to do was revised the type extension that defined the ReleaseAge property. If the repository didn't have a release, the previous code was throwing an error. I revised the definition to check for a null value using the PowerShell 7 ternary operator.

Update-TypeData -TypeName GitHubRepoInfo -MemberType ScriptProperty -MemberName ReleaseAge -Value {
 ($Null -eq $this.LatestReleaseName) ? $null :  (Get-Date) - $this.LatestReleaseDate
} -force

I also realized that I could make the object even easier to use. I might want to run a command like this:

$in | where {$_.Visibility -eq 'public' -AND $_.IsReleased} | Sort-Object ReleaseAge | Select-Object ReleaseAge,name,LatestReleaseName,description -first 5

I can simplify this by adding custom boolean properties indicating if the repository is public or private.

Update-TypeData -TypeName GitHubRepoInfo -MemberType ScriptProperty -MemberName IsPublic -Value { $this.Visibility -eq 'Public' } -Force
Update-TypeData -TypeName GitHubRepoInfo -MemberType ScriptProperty -MemberName IsPrivate -Value { $this.Visibility -eq 'Private' } -Force

With this, I can reduce the amount of typing.

$in | where {$_.IsPublic -AND $_.IsReleased} | Sort-Object ReleaseAge | Select-Object ReleaseAge,name,LatestReleaseName,description -first 5

When creating tools, and especially custom objects, find ways to reduce the friction in using them. Another good example is the use of alias properties. I have a few properties that are good candidates. Here's an example:

$in | where IsPublic | Sort StargazerCount -Descending | Select-Object Name,StarGazerCount,WatcherCount -first 5

Yes, I know I could use wildcards. But an alias feels a little cleaner.

Update-TypeData -TypeName GitHubRepoInfo -MemberType AliasProperty -MemberName Stars -Value StargazerCount -Force
Update-TypeData -TypeName GitHubRepoInfo -MemberType AliasProperty -MemberName Watchers -Value WatcherCount -Force

Compare the difference.

$in | where IsPublic | Sort Stars -Descending | Select-Object Name,Stars,Watchers -first 5

Even better, the output uses the aliases.

Using custom property aliases
figure 1

Property Sets

At this point, here's what the object looks like.

Defined GitHubRepoInfo properties
figure 2

Thinking again about ease of use, are there situations where the user might want to specify a subset of properties on a regular basis? I'm thinking the following is a core set of properties that I want to use repeatedly.

$in | Select LastUpdate,Name,Visibility,URL,Description -first 5 | Format-Table -Wrap

But I'm lazy. I don't want to have to remember to type these properties every time. Instead, I can create a property set.

If I don't plan on using custom formatting, I can define a default property set.

Update-TypeData -Typename GitHubRepoInfo -DefaultDisplayPropertySet LastUpdate,Name,Visibility,URL,Description -Force

This gives me a type of default formatting.

PS C:\> $in[0]

LastUpdate  : 10/10/2024 1:52:05 PM
Name        : PSGalleryReport
Visibility  : Public
URL         : https://github.com/jdhitsolutions/PSGalleryReport
Description : A set of reports in PDF and Markdown format about recently published and popular modules in the PowerShell Gallery. The reports are generated by a
              GitHub Action. This is NOT a PowerShell module.

But I plan on defining custom formatting, and there are other groups of properties I think I want to bundle together to save typing.

$in | Select Name,LatestReleaseName,LatestReleaseDate,ReleaseAge,Url
$in | Select Name,Stars,Watchers,Url,Description

To define these as property sets, I need to use an XML file. This can't be done with Update-TypeData. But let me make this easy for you. Install the PSTypeExtensionTools module from the PowerShell Gallery. I wrote a command called New-PSPropertySet that will create the XML file for you.

New-PSPropertySet -Typename GitHubRepoInfo -Name ReleaseInfo -Properties Name,LatestReleaseName,LatestReleaseDate,ReleaseAge,Url -FilePath .\GitHubRepoInfo.types.ps1xml
Want to read the full issue?
GitHub Bluesky LinkedIn About Jeff
Powered by Buttondown, the easiest way to start and grow your newsletter.