Merging multiple accounts on UserEcho

UserEcho is a service employed by the likes of OzCode and SublimeText for collecting and managing customer issues and suggestions; often regarding software features and bugs. It enables users and developers to discuss bugs and ideas, and respond to frequently asked questions.

OzCode UserEcho landing page
OzCode UserEcho landing page

Recently, I signed into the OzCode UserEcho site using my Google credentials. UserEcho supports the OpenID identity system, providing a wide range of ways to authenticate. Upon logging in, I was immediately confused; where was the issue I had raised a week or two earlier? I was certain it should be there but it was not. After a little thought, I realised I may have logged in with the wrong credentials, inadvertently creating a new account. I logged out and then, using my GitHub account to authenticate instead of Google, tried logging back in. Voila! My issue appeared.

For some, this would probably be the end of it, but it bugged me that I now had two accounts. You may think this is no big deal and you are right, but it was bothering me1.

Settings dropdown on UserEcho
Settings dropdown on UserEcho

Using the dropdown captioned with my name at the top-right of the UserEcho site, I chose User Profile. At the bottom of the subsequent page, I found a table of OpenID logins that the account used but no way to edit it. How could I merge my accounts or add new OpenID identities?

OpenID table on UserEcho user profile screen
OpenID table on UserEcho user profile screen

After searching around the UserEcho site a bit and trying a few Google searches2, I was almost ready to contact UserEcho for some help (or just give up), but then I had an idea. If UserEcho was like most sites these days, it probably keyed accounts using a primary email address for the user. So, I checked the two UserEcho accounts I knew I had and confirmed they had different email addresses.

User details section of a UserEcho profile
User details section of a UserEcho profile

I edited the email address for one of the two accounts to match the other, triggering UserEcho to send a verification email3, so I followed the instructions and verified the email address change.

UserEcho table of accounts with the same email
UserEcho table of accounts with the same email

Then I returned to the User Profile screen in OzCode's UserEcho. At the bottom, below the OpenID table, I was now presented with a message saying that there were other accounts with the same email address, including a Merge button. I clicked that button and immediately, the table showed both the Google and GitHub logins.

OpenID table in UserEcho showing GitHub and Google IDs
OpenID table in UserEcho showing GitHub and Google IDs

So, there you go. If you have multiple accounts for a UserEcho product site, make sure the email addresses match and that you have verified the email address on each account, then view one and click Merge. Job done.

  1. In writing this blog and generating the screenshots, I discovered I actually had three accounts! 

  2. and maybe one Bing 

  3. just making sure you're still you 

Prerelease packages with branches, Appveyor, and MyGet

We use a workflow where Appveyor is setup for CI and then it automatically pushes newly built nuget packages to a MyGet feed for consumption. Perhaps in a future post, I will go over how to set all this up, but for now, let's assume you already have this working; you push changes to a branch in your GitHub repo, which then gets built and tested on Appveyor, before being pushed to MyGet. Everything is nice and smooth.

Unfortunately, the magic ended there. Since there is no differentiation between pushing prerelease changes and release changes, I found that I would either have to limit what branches built in on Appveyor or spend a lot of time curating MyGet to remove intermediate builds I did not want used. I knew that MyGet supported prerelease packages but no matter what I tried, I could not get Appveyor to build them. Unsurprisingly, I found this frustrating. Then I stumbled on this particular answer on StackOverflow:

However, there were some issues I had with this.

  1. It seemed wrong that I had to use an after_build or on_success step to explicitly build my nuget package
  2. I didn't want every build to be prerelease
  3. It didn't work

The first point smelled enough that I wanted to see if I could not have to do that, and that second point seemed really important.

So, I delved a little deeper and discovered that the nuspec file, which has a handy $version$ substitution for the version takes that information from the value of the AssemblyInformationalVersion attribute, which I did not have declared in my AssemblyInfo.cs. Since it was not in there, the Appveyor step declared to patch it did not do anything. This was easy to fix, so I edited my AssemblyInfo.cs to include the attribute and tried again. This time the version updated as I wanted, even without the after_build or on_success shenanigans.

However, it still was not quite right since now, every build being performed was marked as prerelease. While this is a potential workflow, where the appveyor.yml is updated when finally reaching release, what I wanted was for releases to occur when I tagged a branch. For that, I looked at tweaking how the Appveyor build version updated and what environment variables Appveyor defined that I could leverage.

It turns out that Appveyor defines APPVEYOR_REPO_TAG, which is set to true if the build was started by a tag being pushed. It also defines APPVEYOR_REPO_BRANCH containing the name of the branch being built. Armed with these two variables, I updated my appveyor.yml to have two init scripts.

The first script creates a new environment variable. If the APPVEYOR_REPO_TAG is set to true, the new variable gets set to the value of APPVEYOR_BUILD_VERSION; if not, it is set to APPVEYOR_BUILD_VERSION-APPVEYOR_REPO_BRANCH. So, for example, if the build was going to be version 2.4.0, it was not a tag, and the branch was master, then the new variable would be set to 2.4.0-master; however, if it was a tag, it would just be 2.4.0.

The second script calls the Update-AppveyorBuild cmdlet provided by Appveyor, passing the value of the new environment variable as the -Version parameter value.

These two init scripts, plus the AssemblyInformationalVersion attribute in the AssemblyInfo.cs (and corresponding assembly_information_version field under the assembly_info section of the appveyor.yml) were all I needed. Now, whenever I push to a branch, I get a new prerelease nuget package that I can use in my development coding, and whenever I create a new tag, I get a release package instead. Not only does this reduce my need to manually manage my nuget packages on MyGet, but it also means I can take advantage of the different retention policy settings between prerelease and release packages.

All in all, I find this workflow much nicer than what I had before. Hopefully some of you do too. Examples of the appveyor.yml file and associated AssemblyInfo.cs change can be seen in the following Gist.

Signing GitHub Commits With A Passphrase-protected Key and GPG2

GitHub recently added support for signed commits. The instructions for setting it up can be found on their website and I do not intend to rehash them here. I followed those instructions and they work splendidly. However, when I set mine up, I had used the version of GPG that came with my Git installation. A side effect I noticed was that if I were rebasing some code and wanted to make sure the rebased commits were still signed (by running git rebase with the -S option), I would have to enter my passphrase for the GPG key for every commit (which gets a little tedious after the first five or so).

Shows some commits on GitHub with the Verified indicator showing those that have been signed
How GitHub shows signed commits

Now, there are a couple of ways to fix this. One is easy; just don't use a passphrase protected key. Of course, that would make it a lot easier for someone to sign commits as me if they got my key file, so I decided that probably was not the best option. Instead, I did a little searching and found that GPG2 supports passphrase protected keys a little better than the version of GPG I had installed as part of my original git installation.

Using the GPG4Win website, I installed the Vanilla version1. I then had to export the key I had already setup with GitHub from my old GPG and import it into the new. Using gpg --list-keys, I obtained the 8 character ID for my key (the bit that reads BAADF00D in this example output):

Which I then used to export my keys from a Git prompt:

This gave me two files ( privatekey.txt and publickey.txt) containing text representations of the private and public keys.

Using a shell in the GPG2 pub folder ( "C:\Program Files (x86)\GNU\GnuPG\pub"), I then verified them (always a good practice, especially if you got the key from someone else) before importing them2:

And rather than give me details of the key, it showed me this error:

What was going on? I tried verifying it with the old GPG and it gave me a different but similar error:

I tried the public key export and it too gave these errors. It did not make a whole heap of sense. Trying to get to the bottom of it, I opened the key files in Visual Studio Code. Everything looked fine until I saw this at the bottom of the screen.

Encoding information from Visual Studio Code showing UTF16
Encoding information from Visual Studio Code

It turns out that Powershell writes redirected output as UTF-16 and I had not bothered to check. Thinking this might be the problem, I resaved each file as UTF-8 and tried verifying privatekey.txt again:

Success! Repeating this for the publickey.txt file gave the exact same information. With the keys verified, I was ready to import them into GPG2:

With the keys imported, I ran gpg --list-keys to verify they were there and then made sure to delete the text files.

Finally, to make sure that Git used the new GPG2 instead of the version of GPG that it came with, I edited my Git configuration:

Now, when I sign commits and rebases, instead of needing to enter my passphrase for each commit, I am prompted for the passphrase once. Lovely.

  1. You could also look at installing the command line tools from though I do not know if the results will be the same 

  2. Note that I am not showing the path to the file here for the sake of brevity, though I am sure you get the idea that you'll need to provide it 

KalamazooX 2016

It's time! #kalx16

A photo posted by Jeff Yates (@jeff.yates) on

This weekend, I attended the Kalamazoo X conference in Kalamazoo, MI. KalamazooX, or KalX (as it is more often referred by organizers and attendees alike) is "a one day, single track non-tech conference for techies", or perhaps "it is a soft skills conference", or perhaps not. You see, like a book filled with complex characters, rollercoaster plot twists, and profound revelations, it is hard to describe KalX; each description I hear is somehow right and yet completely wrong, painting KalX as something you have already experienced where speakers talk of project planning, team communication, and time management. But KalX is different. KalX is where you hear about the importance of empathy, the roots of genius, or the virtue of personal reflection. KalX might help with your soft skills, but only through indirect action, through powerful talks on why practice trumps passion or creates genius, how apathy and empathy are both needed to foster better relationships (at work or otherwise), or what it is to simply give a shit (and sometimes, to give a shit too much).

Some interesting insight into genius from Alan Stevens and a much needed personal break from tears #kalx16

A photo posted by Jeff Yates (@jeff.yates) on

Whether speaker, organizer, or attendee, KalX is catharsis in the shared and personal experience; strong emotions —anger, joy, sorrow— marked by F-bombs and tears; and unexpected moments (some uncomfortable, some reassuring) where attendees might think "me too", "that's bullshit", or "I am not alone"1.  It is in those moments that KalX shines, the moments when we are raw and exposed.

Four years ago I attended my first Kalamazoo X conference. It was then held in a classroom at a local college and there were about 50 people in attendance, including speakers and organizers2. I had no idea what to expect, so when I found myself crying, stuck in the middle of a row of people I barely knew, I felt surprised, uncomfortable, and confused3. I do not recall if I knew at that moment, but I now look back on that day as the start of what would lead to the diagnosis of my anxiety disorder, its treatment, and the continuing changes to my life that followed. That experience pushed me closer to asking for help.

Though it was for me, I would never say KalX is life-changing; each person experiences it differently and each year is different. In the safe space of peers, where the speakers, unfettered by recorded sessions, can open up about their personal experiences and the things that, in other forums, might be hidden from view for fear of judgement or isolation, KalX facilitates personal discovery. This year, I felt anxiety rise from nowhere when one speaker (Ed Finkler) started to tell my story. Ed doesn't even know me and yet there he was talking about General Anxiety Disorder (GAD), fearing entering bars to look for people as though a lion might be waiting to attack, thinking things through to find every possible outcome and worrying about all of them intensely. Though I wanted to hear more about how he coped with it all4, I was amazed to even know that there was someone out there just like me. It was scary and reassuring, and I might have been the only person in the room that thought so.

We all know I need to heed this #kalx16 (thanks, @leongersing)

A photo posted by Jeff Yates (@jeff.yates) on

When I first started writing this post, I tried to summarize the whole day, but I couldn't do justice to Christina Aldan, Ed Finkler, Kate Catlin, Jay Harris, Cory House, Leon Gersing, Lauren Scott, and Alan Stevens, or their talks on empathy, apathy, genius, passion, and more besides. It is hard to describe what they said in a way that could convey what it was like to experience it at the time, just as it is hard to describe KalX as a whole. It is even harder to describe these things to convey how someone else might have experienced the day. In realizing this and the inadequacy of phrases like "it's a soft skills conference" or "it's a non-tech conference for techies" I have wondered, how could I describe KalX in a single sentence? I don't think I could, not because KalX is some indescribable experience, but because each person finds value from it in different ways. Sometimes, no matter how hard you try, there is no apt summary, no convincing abstract; sometimes you just have to read the book for yourself.


  1. Or briefly, involuntarily emit an inappropriate laugh at that same realisation 

  2. this year had closer to 200 

  3. KalX can really sneak up on you 

  4. how I could cope with it all 

Octokit, Merge Commits, and the Story So Far

In the last post we had reduced our commits by matching them against pull requests; next, we can look for noise in the commit message content itself. Although I have been using the Octokit.NET repository as the target for testing with its low noise, high quality commit messages, we can envisage a less consistent repository that has some noisy commits. For example, how often have you seen or written commit messages like "Fixed spelling", "Fixed bug", or "Stuff"1?

How we detect these noisy commits is important; if our filtering is too simple, we remove too many things and if it is too strict, we remove too few. Rather than go deep into one specific implementation, I just want to introduce the idea of filtering based on message content. In the long term, I think it would be interesting to apply learning algorithms,  but I'm sure some simple, configurable pattern matching should suffice2.

If I run the filtering I have described so far3 on the Octokit.NET latest release, this is what we get:

The value of this is clearer if we see the commit list before processing:

The work so far has reduced a list of 135 commits down to 58, and so far, it looks like we have not lost any really useful "release note"-worthy information. However, the eagle-eyed among you may noticed that our 58 messages contain duplicate information. This is because each pull request is listed twice; once for the pull request title I inserted in place of its individual commits, and again for the merge commit that merged that pull request. These merge commits are not filtered out because they do not belong to the commits inside the pull request. Instead, they are an artifact of merging the pull request4.

At first, I thought the handy MergeCommitSha property of the pull request would help, but it turns out this refers to a test merge and is to be deprecated5. Instead, I realised that the messages I wanted to remove all had "Merge pull request #" in them, followed by the pull request number. This seems like a perfect use case for our pattern matching filtering. Since we have the pull requests, we could use their numbers to match each merge message exactly, but I decided to do the simpler thing of excluding any message starting with "Merge pull request #".

Filtering for messages that begin with "Merge pull request #" gives us a shortlist of just 31 messages:

I think this is a pretty good improvement over the raw commit list. Combining this list with links back to the relevant commits and pull requests should enable someone to discern the content of a release note much faster than using the raw commit list alone. I will leave that as an exercise or perhaps a future post. As always, thanks for reading. If you find yourself using Octokit to trawl your own repositories for release note information, I would love to hear about it in the comments.

  1. We're all friends here, you can admit it 

  2. The filtering should be configurable so that we can tailor it to the repository we are processing 

  3. excluding the last step of filtering by message content 

  4. Perhaps stating the obvious