I've been continuing to work with the GitHub API in PowerShell. Today I have a function you can use to create a new GitHub repository. Of course you will need to have a GitHub account and another piece of critical information, but after that it is quite easy to create new repositories. This makes it easier for you to automate provisioning new projects, which is something else I'm working on. But for now, let's create some repos!
ManageEngine ADManager Plus - Download Free Trial
Exclusive offer on ADManager Plus for US and UK regions. Claim now!
The first bit of information you are going to need is a GitHub personal access token. If you don't have one saved you'll need to create one. Go to your GitHub profile settings and click on the "Personal access tokens" link. You may see a list of existing tokens but you wont' be able to see the actual value. But you can easily create a new token to use with your PowerShell scripts.
Click the "Generate New Token" link and confirm your password. Enter a description and then select the scopes. Because you might use this with other PowerShell scripts I'd choose all repo, gist, and user scopes. Click "Generate token" and copy the 40 digit string and save it someplace secure. This is the Git token you will need to authenticate. In my PowerShell profile I have it stored in a variable, $gitToken. You should protect this token.
Now you're ready to start working with your GitHub account.
Here's the PowerShell function I've been working on.
Function New-GitHubRepository { [cmdletbinding(SupportsShouldProcess)] Param( [Parameter(Position = 0, Mandatory, HelpMessage = "Enter the new repository name")] [ValidateNotNullorEmpty()] [string]$Name, [string]$Description, [switch]$Private, [switch]$NoWiki, [switch]$NoIssues, [switch]$NoDownloads, [switch]$AutoInitialize, #license templates found at https://github.com/github/choosealicense.com/tree/gh-pages/_licenses [ValidateSet("MIT","apache-2.0","gpl-3.0","ms-pl","unlicense")] [string]$LicenseTemplate, [Alias("token")] [ValidateNotNullorEmpty()] [string]$UserToken = $gitToken, #write full native response to the pipeline [switch]$Raw ) Write-Verbose "[BEGIN ] Starting: $($MyInvocation.Mycommand)" #display PSBoundparameters formatted nicely for Verbose output [string]$pb = ($PSBoundParameters | Format-Table -AutoSize | Out-String).TrimEnd() Write-Verbose "[BEGIN ] PSBoundparameters: `n$($pb.split("`n").Foreach({"$("`t"*2)$_"}) | Out-String) `n" #create the header $head = @{ Authorization = 'Basic ' + $UserToken } #create a hashtable from properties $hash = @{ name = $Name description = $Description private = $Private -as [boolean] has_wiki = (-Not $NoWiki) has_issues = (-Not $NoIssues) has_downloads = (-Not $NoDownloads) auto_init = $AutoInitialize -as [boolean] } if ($LicenseTemplate) { $hash.add("license_template",$LicenseTemplate) } $body = $hash | ConvertTo-Json Write-Verbose "[PROCESS] Sending json" Write-Verbose $body #define parameter hashtable for Invoke-RestMethod $paramHash = @{ Uri = "https://api.github.com/user/repos" Method = "Post" body = $body ContentType = "application/json" Headers = $head UseBasicParsing = $True DisableKeepAlive = $True } #should process if ($PSCmdlet.ShouldProcess("$name [$description]")) { $r = Invoke-RestMethod @paramHash if ($r.id -AND $Raw) { Write-Verbose "[PROCESS] Raw result" $r } elseif ($r.id) { write-Verbose "[PROCESS] Formatted results" $r | Select-Object @{Name = "Name";Expression = {$_.name}}, @{Name = "Description";Expression = {$_.description}}, @{Name = "Private";Expression = {$_.private}}, @{Name = "Issues";Expression = {$_.has_issues}}, @{Name = "Wiki";Expression = {$_.has_wiki}}, @{Name = "URL";Expression = {$_.html_url}}, @{Name = "Clone";Expression = {$_.clone_url}} } else { Write-Warning "Something went wrong with this process" } if ($r.clone_url) { $msg = @" To push an existing local repository to Github run these commands: -> git remote add origin $($r.clone_url)" -> git push -u origin master "@ Write-Host $msg -ForegroundColor Green } } Write-Verbose "[END ] Ending: $($MyInvocation.Mycommand)" }
Let me point out a few things.
The only truly required parameters are the Name and GitHub token. I've set the default value of the latter to the variable from my profile which is why the parameter is not marked as Mandatory. You can also specify a repository Description.
When you create a new repository, by default it is public. But if you have a paid account, you can opt to make it Private. All repos also get a wiki, issues and the option to have downloads but you can create a repo without any of these things with the corresponding parameters.
I tend to create repos after I've started a project locally so I handle things like a license and README.md on my own. When you create a new repo with my function you can choose to include a license (I've added a validation set for the more common choices I think you'd make), as well as a parameter to Autoinitialize. This will create a default README.md file.
The magic in all of this is creating a body of directives formatted as json.
#create a hashtable from properties $hash = @{ name = $Name description = $Description private = $Private -as [boolean] has_wiki = (-Not $NoWiki) has_issues = (-Not $NoIssues) has_downloads = (-Not $NoDownloads) auto_init = $AutoInitialize -as [boolean] } if ($LicenseTemplate) { $hash.add("license_template",$LicenseTemplate) } $body = $hash | ConvertTo-Json
This body becomes part of the parameters I'll splat to Invoke-Restmethod.
$paramHash = @{ Uri = "https://api.github.com/user/repos" Method = "Post" body = $body ContentType = "application/json" Headers = $head UseBasicParsing = $True DisableKeepAlive = $True }
The header is constructed from your user token.
$head = @{ Authorization = 'Basic ' + $UserToken }
The result from GitHub is a json document but Invoke-RestMethod turns it automatically into an object. Be default I build a custom output object from this data.
$r | Select-Object @{Name = "Name";Expression = {$_.name}}, @{Name = "Description";Expression = {$_.description}}, @{Name = "Private";Expression = {$_.private}}, @{Name = "Issues";Expression = {$_.has_issues}}, @{Name = "Wiki";Expression = {$_.has_wiki}}, @{Name = "URL";Expression = {$_.html_url}}, @{Name = "Clone";Expression = {$_.clone_url}}
Or you can use -Raw to see everything.
The last bit of the function is something you get in GitHub when you create an empty repository and that is a tip on how to configure a local repository.
if ($r.clone_url) { $msg = @" To push an existing local repository to Github run these commands: -> git remote add origin $($r.clone_url)" -> git push -u origin master "@ Write-Host $msg -ForegroundColor Green }
I can never seem to remember the syntax so this is a nice touch for me.
My function makes use of Write-Verbose and supports -Whatif.
Now for real and I'll drop -Verbose.
Done! You can see the git commands at the end in green. Here's the repo on GitHub.
It has nothing in it yet, and I'll delete it shortly but it works.
This function will eventually, hopefully, become part of a larger toolkit. But feel free to use it now and let me know how it works for you.
Enjoy and have a great weekend.