My Workflow for using Git with GitHub, OneDrive, PowerShell & Exchange – optimising efficiency across devices. Pt 2

Ryan YatesConsultant

Just a person in their 30's doing things in Tech & trying to break the stigma's around talking about Mental Health

So this is the Second of a series of blog posts about how my workflow with Git, GitHub, PowerShell & Exchange currently works.

In this series we will cover a number of different applications and a number of custom PowerShell Functions that will really help you to optimise efficiency across devices when these processes are put in place.

As we left off the last part I had opened up the thoughts to the next stages of the process – the actual automation of the workloads and in this post I will go into detail about the integration between GitHub & Exchange to create New Inbox Folders and Inbox Rules for any newly followed Repo’s

So I’ve just followed a bunch of new GitHub Repo’s and now I want to have the Inbox rules & Folders set up for me – Manually this is not that much of a task – but why manually do this when there is a way to Automate it

121815_1235_MyWorkflowf1

 

 

 

 

 

 

So to do this we need to Query the GitHub API, and we will be utilising Invoke-WebRequest for this, to see all the Watched Repo’s which is accessible for any user via the following URL – just replace kilasuit (my GitHub alias) with the username that you want to query - https://api.github.com/users/kilasuit/subscriptions

Now this is a paginated and non-authenticated URL which means that it returns only 30 results at a time and these 30 results will only be public repos, so if your following more than 30 repos then you will need to rerun the query with a small addition to get the correct outputs, however if your following private repos then you will need to wait for a following post on how to accomplish this.

To do this we will check the request to see if there is an included Link Header – if there is then we know that the user is watching over 30 public repos and we also from this header we will get the number of pages (batches of 30) that we will need to iterate through to get all the users watched public Repo’s

Below we have a small snippet of the overall function to do the iteration of the pages (this could be tidied up – but for now it works)

$repos =@()

$web = Invoke-WebRequest -Uri “https://api.github.com/users/$githubuser/subscriptions"

$page1 = Invoke-RestMethod -Uri “https://api.github.com/users/$githubuser/subscriptions"

$page1 | ForEach-Object { $repos += $_.name }

if ($web.Headers.Keys.Contains(‘Link’))

{

    $LastLink = $web.Headers.Link.Split(’,’)[1].replace(’<’,’’).replace(’>’,’’).replace(’ ‘,’’).replace(‘rel=“last”’,’’).replace(’;’,’’)

    [int]$last = $($lastlink[($lastlink.ToCharArray().count -1)]).tostring()

    $pages = 2..$last

    foreach ($page in $pages)

        {

        Invoke-RestMethod -Uri “https://api.github.com/users/$githubuser/subscriptions?page=$page" | ForEach-Object { $repos += $_.name }

        }

}

So as you can see above we have queried the GitHub API and we have stored a result in a local variable. This then allows us to pull manipulate the data stored in the corresponding Object to add all the watched Repos (from this initial 30 responses) into an array and as you can see from the above we are piping the Web Object to the ConvertFrom-JSON command and then piping that to the ForEach-Object Command.

After this we then query the Web Object it to see if there is a Link Header. If we find that there is a Link Header, then we will generate the needed array of pages and add this to another local array called pages. We then loop through the array of pages to get all the repos and do exactly the same as above to add them into the repos array.

At this point we then have the name of all of the watched repos in the repos variable and we are making use of the name property for the rest of the function.

However, there are a lot more properties that have been collected as part of the Invoke-WebRequest call as can be seen below for the PowerShellEditorServices Repo.

Please note I’ve excluded a fair amount of properties in the below (using the *_url string) because there are some almost useless properties there unless you are going to do further queries.

121815_1232_MyWorkflowf2

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

As we can see there are some interesting and useful details given here including open_issues, forks, watchers, pushed_at (when the last local commit was pushed to the GitHub Repo), updated_at (when the last commit was made – not when it was pushed), name & full_name.

So from the data that we can get programmatically for repo’s we can really do quite a lot with it – especially with all the different url options that there are included as well as shown below – notice that the majority of them are the relevant API URL – this makes building out some wrapping functions that call Invoke-WebRequest for those API endpoints very much easier – so Kudos to GitHub for making things easier for Developers to do this sort of thing.

121815_1232_MyWorkflowf3

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

As it is there is certainly a lot of flexibility that comes with using GitHub and PowerShell for some automation of smaller tasks like this.

The below is the “Meat” of this function where we connect to Exchange Online using a wrapper function Connect-EXOSession (See my PoshFunctions repo for where this lives) where all we need to pass is a PSCredential.

Once we have connected to the PSSession to Exchange Online we then are gathering all the current folders that live in the GitHub Stuff Folder in my Inbox into another array variable. This means that we can then compare whether there is already a folder there or not and if the folder doesn’t exist then we will create one and then we will then create a new Inbox Rule for it to automatically move any emails that come from GitHub to the correct folder for the Repo.

 

We then write a small amount of text to the screen to tell which folders and rules have been set up – useful if like me you are following almost 50 repos already and this is likely to increase over time as well.

Connect-EXOSession -EXOCredential $EXOCredential

$folders = Get-MailboxFolder $MailboxFolderParent -GetChildren | Select-Object -ExpandProperty Name

foreach ($repo in $repos) {

    if($folders -notcontains $repo)

        { New-MailboxFolder -Parent $MailboxFolderParent -Name $repo | Out-Null

          New-InboxRule -SubjectContainsWords “[$repo]” -MoveToFolder $MailboxFolderParent\$repo -Name $repo -Force | Out-Null

          Write-Output “Folder & rule for $repo have been created”

          }

    }

Then as you can see we then are removing the PSSession, EXOSession, as to clean up the PowerShell session as the EXOSession will stay in memory unless Remove-PSSession is run.

Remove-PSSession -Name EXOSession

The full version of this function can be found in my PoshFunctions Repo on GitHub located at https://github.com/kilasuit/PoshFunctions

Stay tuned for part 3 where I will go into the details as to how and where to structure your GitHub Repo’s to allow you to then automatically check the status of all of the repo’s in 1 function. This will be a less intensive post but is still useful to read for the efficiency that can be gained from using this method and it will then help you understand the more detail specific aspects of the rest of my workflow.