πŸ›  These Software Development Tools Will Blow Your Mind

Photo by Ben White on Unsplash

For my final post of 2019, I thought I would deal with some serious FOMO1 by adding one of my own to the legions of year-end listicles adorned by clickbait headlines. You will not believe what's at number four! Nevermore shall I lament having passed up the opportunity to proffer a subjective collection of arbitrary length for your attention. Of what engrossing subject shall this list be? Life achievements? 11 places to visit before you die? Things I have discovered when looking for other things that I have lost? Nay, it shall be tools! Tools, I say. To be specific, development tools for it is tools of software development that I use often. To be even more specific, this is a list of development tools for each of which I could write an additional list of killer features, extensions, and magical whosywotsits. I present to you a list of feature packed fancies for fruitful software fabrication. How many tools? Read on to find out2.

Visual Studio Code
code.visualstudio.com

A screenshot of the Visual Studio Code environment, showing the Extensions Marketplace on the left and a JavaScript file being edited on the right, below which is shown a terminal panel indicating code has been successfully compiled. The editor is also showing an autocomplete list of possible syntax to insert. The bottom of the screen is a status bar showing additional information about the currently opened files.

This open source, cross platform, integrated development environment (IDE) backed by Microsoft really is the best I have used so far. With its built-in terminal, text editor, and task engine, it really is an integrated environment where, if it weren't for Slack and my web browser, I would spend all of my software crafting days. In fact, if I liked the extensions that integrated Slack and web browsing into Visual Studio Code, I could use it or them too; but I don't, so I don't.

Unlike IDE's of old, Visual Studio Code – often referred to as just VS Code or Code (it's command line invocation is the delightful code the-file-I-want-to-edit.js), is implemented to avoid having opinions about the code you write. Instead, it is written to support your code dictating how you write code so that you can deftly move between projects without worrying that the settings for one team will somehow traipse all over the settings for another.

If you like vim-style editors, there's a vim emulator. If you don't like the menus, use Zen Mode or go fullscreen. Want to run tests integrated in the sidebar or the test file itself? Do that. Want to run them from a terminal or via a background task? Do that instead. I could (and probably will) write a whole new list on the best extensions to use with Visual Studio Code. It is versatile enough that I believe any developer could make it the editor they need.

Why it is great for software developers?

Either natively or via an extension, Visual Studio Code supports just about every aspect of the software development lifecycle you might encounter, on every platform that likely matters (Windows, macOS, and Linux), using any workflow that suits you. Not to mention it gets feature updates monthly and is supported by a huge community of users. It takes a little DNA from editors like Atom, Sublime, and your basic text editor, and elevates them to something, well, sublimer3.

WordPress
wordpress.org

A screenshot of a web browser showing the WordPress admin screen for choosing a theme, with several themes previewed in a grid.

When concentrating on software development tools, it is really easy for me to overlook this one – probably because it is not a software development tool, at least not from first impressions. I use WordPress for this blog; I always have. There are many alternatives out there; some more technically involved than others. I know I could use markdown in a GitHub repository; I have heard of Jekyll and Gatsby and so many other ways to generate a site; I know about Medium, but for me, WordPress wins because it has the features I need, including wide support for hosting, accessibility, themes, plugins, and autonomy from the whimsy and money-grabbing aggregation platforms like Medium.

The recent updates to the core editing experience, known as Gutenberg, have been amazing and the regular updates that are auto-applied without me raising a finger keep adding polish to an already awesome experience. I can schedule posts, manage comments, and use plugins to add syntax highlighting, footnotes, multi-factor authentication, backups, and spam filtering, to name just a few. Just as with Visual Studio Code extensions, I could write another list of plugins that I love for WordPress.

35% of the web uses WordPress, from hobby blogs to the biggest news sites online.

https://wordpress.org/

WordPress is used by over a third of the web. A third! That includes this blog, almost every site that Ann Arbor Give Camp has worked on in the past few years, and rollingstone.com! If you are considering putting together any kind of website, whether a blog, or something else, I highly recommend this freely available platform that has more versatility than Meryl Streep.

Why it is great for software developers?

As I mentioned earlier, WordPress seems entirely unrelated to software development (unless you are writing themes and plugins for WordPress4). However, I have learned that writing a blog about ones technical exploits is an absolutely amazing software development tool. I never realised how much I could learn just by trying to teach someone else. I used to think a blog was about its readers and being right; I have come to learn that a blog is merely its writer, being. The act of writing a blog is where its value lies. Writing this blog identifies gaps in my knowledge, personal biases, and more. It can shine a light on my laziness, focus the my mind on a gnarly problem, and provide a scaffold from which to hang my personal growth. There are numerous times where writing posts for this blog (including some I never published) has helped me become a better software engineer. The fact that sometimes, someone reads it and finds it useful, entertaining, or infuriating is really just a bonus.

Write a blog. Hold an opinion. It is worth it.

GitHub
github.com

A screenshot of the GitHub organization's page on GitHub. The screen shows the GitHub logo (the octocat) and information including geographical location, URL, contact email, and several tabs giving more information about the organization's repositories, packages, people, and projects. The repositories tab is selected.

For some readers, this may seem a pointless entry. Using GitHub for collaborative software development is so incredibly common that suggesting folks should use it seems a bit like suggesting folks should try breathing air5. Though there are alternatives such as GitLab, GitKracken6, or BitBucket, GitHub is almost ubiquitous. I do not recall an open source project that I have interacted with recently that was not hosted on GitHub7. With the recent changes allowing private and public repositories for personal accounts, the addition of GitHub Actions for automating all kinds of workflows – free to open source, and some great improvements to code review that have been released or are in beta, GitHub is an absolutely fantastic tool for those developing software. Add to that the integrations with other tools that I use like Visual Studio Code, Slack, and third-party issue trackers such as Jira, and GitHub shines. Many feared that its acquisition by Microsoft would doom it to failure, yet the Microsoft of today is a wonderful curator of open source goodies, and it seems that we all get to reap the benefits.

Why it is great for software developers?

Free backup of your source code, code reviews, automated workflows, and more, all on a tried and tested platform with a huge community. Not only that, but if you want, you get to collaborate, build, and present work with that community8.

πŸ€·πŸ»β€β™‚οΈ That's it…

I don't know about you, but lists are exhausting. I've only written about three things and I'm already done with everything and ready for a lie down. I do stand by this list though. I really thought about what to put on it, considering the various tools I have used, not only because I have to, but because I want to. I would choose these tools from the very start of a new project unlike some others I use that, while I like them, are specific to a technology (such as React Developer Tools), are only what I use because the circumstances call for it, or are not really that standout against alternatives that I could be using.

Of course, this is all my personal opinion drawn from my personal experience; you have absolutely no obligation to agree with me. In fact, you have every right to use anything but the things I mentioned above, remaining in your state of willful ignorance, knowing you are wrong, unwilling to accept the truth as a way of life 😈. Just kidding, these are development tools, not religions – what works for you, works for you. These work for me. Perhaps you agree and want to pat me on the back from my excellent choices, maybe you care to tell me your preferred alternatives or shout at me about mine, or perhaps you read the footnotes and really have something to say about privilege, toxicity, and portfolios – feel free to engage in the comments; let's talk πŸ€—.

And with that, I bid you well until the πŸŽ†New Year and all the productive software shenanigans that await us in 2020. πŸ™‡πŸ»β€β™‚οΈ

  1. Fear Of Missing Out – a most annoying acronym, I find; why? no idea []
  2. it's three, three tools []
  3. don't you roll your eyes at me []
  4. PHP? Ew! []
  5. you really should, it is to die for []
  6. mention-worthy, if only for the pun []
  7. before GitHub, it was SourceForge, before the DevShare debacle – https://en.wikipedia.org/wiki/SourceForge []
  8. Side Note: I think it is perfectly fine not to have a portfolio; some of the best developers I know do not have any public source, or fancy stuff to show off. This weird obsession some folks have with portfolios feels like another toxic manifestation of privilege in the software development world, and I don't care for it. Let's share what we want (and are able) to share, and accept that if we don't, that doesn't mean we're shit developers. πŸ’™ []

πŸ™‡πŸ»β€β™‚οΈ Introducing checksync

Photo by Clint Adair on Unsplash

Have you ever written code in more than one place that needs to stay in sync? Perhaps there is a tool in your framework of choice that can generate multiple files from a single source of truth, like T4 templates in the .NET world; perhaps not. Even if there is such a tool, it adds a layer of complexity that is not necessarily easy to grok. If you look at the output files or the template itself, it may not be clear what files are affected or related.

At Khan Academy, we have a linter, written in Python, that is executed whenever we create a new diff for review. It runs across a subset of our files and looks for blocks of text that are marked up with a custom comment format that identifies those blocks as being synchronized with other target blocks. Included in that markup is a checksum of the target block content such that if the target changes, we will get an error from the linter. This is our signal to check if further changes are need and then update the checksums that are invalidated. The only bugbear folks seem to have is that instead of offering an option to auto-fix checksums in need of update, it outputs a perl script that has to be copied and run for that purpose.

Small bugbear aside, this tool is fantastic. It enables us to link code blocks that need to be synchronized and catches when we change them with reasonably low overhead. Though I believe it is hugely useful, it is sadly custom to our codebase. I have long wanted to address that and create an open source version for everyone to use. checksync is that open source version.

πŸ€” The Requirements

Before writing checksync, I started out with the following requirements:

  • It should work with existing marked up code in the Khan Academy codebase; specifically,
    1. File paths are relative to the project root directory
    2. Checksums are calculated using Adler-32
    3. Both // and # style comments are used to comment the markup tags
    4. Start tag format is:
      sync-start:<ID> <CHECKSUM> <TARGET_FILE_PATH>
    5. End tag format is:
      sync-end:<ID>
    6. Multiple start tags can exist for the same tag ID but with different target files
    7. Sync tags are not included in the checksum'd content
    8. An extra line of blank content is included in the checksum'd content (due to a holdover from an earlier implementation)
    9. .gitignore files should be ignored
    10. Additional files can be ignored
  • It should be comparably performant to the existing linter
    • The linter ran over the entire Khan Academy website codebase in less than 15 seconds
  • It should auto-update invalid checksums if asked to do so
  • It should output file paths such that editors like Visual Studio Code can open them on the correct line
  • It should support more comment styles
  • It should generally support any text file
  • It should run on Node 8 and above
    • Some of our projects are still using Node 8 and I wanted to support those uses

With these requirements in mind, I implemented checksync (and ancesdir, which I ended up needing to ensure project root-relative file paths). By making it compatible with the existing Khan Academy linter, I could leverage the existing Khan Academy codebase to help measure performance and verify that things worked correctly. After a few changes to address various bugs and performance issues, it is still mildly slower than the Python equivalent, but the added features it provides more than make up for that (especially the fact that it is available to folks outside of our organization).

πŸŽ‰ Check It Out

checksync includes a --help option to get information on usage. I have included the output below to give an overview of usage and the options available to customize how checksync runs.

checksync --help
checksync βœ… πŸ”—

Checksync uses tags in your files to identify blocks that need to remain
synchronised. It works on any text file as long as it can find the tags.

Tag Format

Each tagged block is identified by one or more sync-start tags and a single
sync-end tag.

The sync-start tags take the form:

    <comment> sync-start:<marker_id> <?checksum> <target_file>

The sync-end tags take the form:

    <comment> sync-end:<marker_id>

Each marker_idcan have multiple sync-start tags, each with a different
target file, but there must be only one corresponding sync-endtag.

Where:

    <comment>       is one of the comment tokens provided by the --comment
                    argument

    <marker_id>     is the unique identifier for this marker

    <checksum>      is the expected checksum of the corresponding block in
                    the target file

    <target_file>   is the path from your package root to the target file
                    with a corresponding sync block with the same marker_id

Usage

checksync <arguments> <include_globs>

Where:

    <arguments>       are the arguments you provide (see below)

    <include_globs>   are glob patterns for identifying files to check

Arguments

    --comments,-c      A string containing comma-separated tokens that
                       indicate the start of lines where tags appear.
                       Defaults to "//,#".

    --dry-run,-n       Ignored unless supplied with --update-tags.

    --help,-h          Outputs this help text.

    --ignore,-i        A string containing comma-separated globs that identify
                       files that should not be checked.

    --ignore-files     A comma-separated list of .gitignore-like files that
                       provide path patterns to be ignored. These will be
                       combined with the --ignore globs.
                       Ignored if --no-ignore-file is present.
                       Defaults to .gitignore.

    --no-ignore-file   When true, does not use any ignore file. This is
                       useful when the default value for --ignore-file is not
                       wanted.

    --root-marker,-m   By default, the root directory (used to generate
                       interpret and generate target paths for sync-start
                       tags) for your project is determined by the nearest
                       ancestor directory to the processed files that
                       contains a package.json file. If you want to
                       use a different file or directory to identify your
                       root directory, specify that using this argument.
                       For example, --root-marker .gitignore would mean
                       the first ancestor directory containing a
                       .gitignore file.

    --update-tags,-u   Updates tags with incorrect target checksums. This
                       modifies files in place; run with --dry-run to see what
                       files will change without modifying them.

    --verbose          More details will be added to the output when this
                       option is provided. This is useful when determining if
                       provided glob patterns are applying as expected, for
                       example.

And here is a simple example (taken from the checksync code repository) of running checksync against a directory with two files, using the defaults. The two files are given below to show how they are marked up for use with checksync. In this example, the checksums do not match the tagged content (though you are not expected to know that just by looking at the files – that's what checksync is for).

// This is a a javascript (or similar language) file

// sync-start:update_me 45678 __examples__/checksums_need_updating/b.py
const someCode = "does a thing";
console.log(someCode);
// sync-end:update_me
# Test file in Python style

# sync-start:update_me 4567 __examples__/checksums_need_updating/a.js
code = 1
# sync-end:update_me
Example output showing mismatched checksums

Additional examples that demonstrate various synchronization conditions and error cases can be found in the checksync code repository. To give checksync a try for yourself:

I hope you find this tool useful, and if you do or you have any questions, please do comment on this blog.

C#7: Tools

I have spent the first couple of months of 2017 learning about the new features in C#7. This would not have been possible without some tools to help me play around with the new language syntax and associated types. Since we have to wait a little longer until Visual Studio 2017 is released, I thought you might like to know what tools I have been using to tinker in all things C#7.

LINQPad Beta

Link: http://www.linqpad.net/Download.aspx#beta

While early releases of Visual Studio 2017 (scheduled for release on March 7th) support the language, I initially found the release candidate to be unstable and frustrating. Not only that, but it can be cumbersome to spin up a quick example using Visual Studio, so I turned to my trusty friend, LINQPad.

LINQPad Beta showing me my return is missing a ref
LINQPad Beta showing me my return is missing a ref

I cannot recommend LINQPad enough, it is a fantastic tool for prototyping, poking around data sources, and more besides, like tinkering with language features you don't yet understand. While LINQPad's current release only supports the C# language up to version 61, the beta release also supports C# version 7. Not only can you use the language, but with the fantastic analysis window, you can see how Roslyn breaks down each part of the code. If you want to get started quickly, easily play around with the cool new features, and have a powerful tool for digging deeper as the need arises, the LINQPad beta is the tool to get.

Visual Studio 2017 RC

Link: https://www.visualstudio.com/downloads/

Visual Studio 2017 RC splash
Visual Studio 2017 RC splash

Yes, I know I said it was unstable and frustrating, but that was before, way back in January. These days the RC is much, much better and with the release date set for March 7th, there was never a better time to install Visual Studio 2017 RC and get a head start on getting to know some of the new things it can do, including C# 7. Tuples are fun, but poking around with them in the debugger is funner.

OzCode

Link: https://oz-code.com/

Pattern matching in OzCode
Pattern matching in OzCode

It is no secret that I love OzCode, the magical debugging extension for Visual Studio. It is so well-known that they asked me to be part of their OzCode Magician community program. So, it should come as no surprise that I have been using OzCode in my exploration of C#7. As the Visual Studio 2017 RC has matured, the clever people over at CodeValue have been creating previews of OzCode version 3, including amazing LINQ debugging support. Recently, I got to try an internal build thatΒ included support for all the cool new things in C#7.

OzCode 3 will be released on March 7th, the same day as Visual Studio 2017.

Documentation

Link: https://docs.microsoft.com/dotnet/articles/csharp/csharp-7

Never underestimate the power of reading documentation, it is one of the best tools out there. For my C#7 posts, I relied heavily on the new docs.microsoft.com site, specifically the .NET articles on C#. Not only is this a fantastic resource, but it has built-in support for commenting on the documentation so that you can ask questions and contribute to their improvement.

In Conclusion

This is the entire list of tools I used for my C#7 investigations. Try them out and get an early start on C#7 fun before the March 7th release of all the C#7 goodness. Happy tinkering and if you stumble on any useful tools, please share in the comments!

  1. It also supports SQL, F#, and VB []

OzCode: Reveal With Reveal

In my last post, I revealed that I am a magician; an OzCode magician1. I also revealed the new LINQ support currently in EAP. Since that was two reveals in one, I thought that I would look at another OzCodeΒ feature today coincidentally called Reveal.

I remember this specific feature as "favourites for properties" although I am reliably informed by the OzCode team, their website, and their documentation that it is in fact called "Reveal"2. Reveal was the feature that first lured me into regular use of OzCode and if it is the only feature you use, you will still wonder how you really survived without it.

When debugging, we can spend lots of time drilling down into objects to find the value of various properties and sub-properties. This can get especially tiresome when we're looking at a few similar objects since we repeat the same steps. Although pinning certain values is helpful, it does not really solve the initial issue of drilling down to find the thing to pin.

With Reveal, we can make life much simpler by elevating the details of an object to itsΒ summary; like an on-the-fly custom ToStringΒ implementation. Not only does this help with looking at one item, but it really helps with collections of similar items. For example3:

Animated GIF showing how to use Reveal in OzCode
Animated GIF showing how to use Reveal in OzCode

Any properties that are "revealed" carry across to the rest of the debug sessionΒ and beyond;Β once you have revealed some properties, they stay revealed until you decide you do not want them to be anymore, even across debug sessions.

Animated GIF showing how the revealed properties remain revealed
Animated GIF showing how the revealed properties remain revealed

You can even see (and change) your revealed properties directly within the LINQ analysis window.

Animated GIF of using Reveal inside the new LINQ analysis feature of OzCode
Animated GIF of using Reveal inside the new LINQ analysis feature of OzCode

Finally, revealed properties propagate up the object hierarchy allowing you to surface values from deeper in your object tree. This can really be a huge time saver, especially since the revealed properties are remembered across sessions.Β No more hovering over multiple things to find what you're looking for and no more writingΒ custom ToStringΒ overrides, debug visualizers,Β or other workarounds.

Hopefully, thisΒ overview of Reveal in OzCode has demonstrated not only why I love it so much, but also how valuable it can be. I genuinely believe OzCodeΒ to be an essential tool in any .NET developer's kit, but since you may mistake me for some corporate shill, you should not take my word for it; tryΒ OzCode out for yourself with a free trial (or take part in the EAP). Stop performing workarounds and start performing magic.

  1. Read as Sean Connery as James Bond []
  2. and apparently it doesn't matter how often I tell them they are wrong []
  3. To demonstrate, I am using the handy demo app from OzCode, which you can find onΒ GitHub []

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:

Fix the credit format 
Release notes for release 0.17.0 
Merge pull request #972 from naveensrinivasan/json-serialization

Json serialization for Unicode 
Merge pull request #976 from octokit/elbaloo-better-merge-exception-rebased

better merge exception rebased 
Merge pull request #973 from naveensrinivasan/appveyornuget

Generate nuget packages on appveyor 
Merge pull request #917 from alfhenrik/feature-webhookhelper

Add helper class for creating web hooks 
Merge pull request #807 from octokit/codeformatter

added a tailored CodeFormatter to Octokit 
Merge pull request #956 from octokit/vs2015-support

VS2015 migration 
Merge pull request #921 from naveensrinivasan/samples

Adds octokit samples 
Merge branch 'gitignore-exception' 
Merge pull request #918 from willsb/download-timeout

Adds overloads to GetArchive for adding custom timeouts 
Merge pull request #957 from octokit/clean-up-some-fixes

clean up some pending PRs 
Merge pull request #943 from naveensrinivasan/AssetDownload

Fixes for Downloading ReleaseAsset zip File 
Merge pull request #942 from alfhenrik/bug-repohasissues

Make NewRepository.HasIssues nullable as it's optional 
Merge pull request #940 from naveensrinivasan/build-sh

Created build.sh 
Merge pull request #929 from elbaloo/issue-389

Add .com links to PrivateRepositoryQuotaExceededException 
Merge pull request #927 from naveensrinivasan/octokit-logo

Updated with the logo 
Merge pull request #922 from naveensrinivasan/fixes-for-fake-warning

Fixes for FAKE Xunit warning 
Merge pull request #919 from adamralph/system-framework-assembly

add System to required framework assemblies for net45 
Merge pull request #909 from willsb/disposable-repositories

Disposable repositories 
Merge pull request #916 from octokit/consolidate-committer-info

Consolidate committer info 
Merge pull request #915 from octokit/docs

Add a bunch of XML doc comments 
Merge pull request #907 from naveensrinivasan/encodedcontent-public-#861

Making Encodedcontent public #861 
Merge pull request #908 from khellang/clarify-failing-convention-tests

Clarify why convention tests are failing 
Merge pull request #906 from naveensrinivasan/update-readme

Updated the readme with reactive octokit. 
Merge pull request #903 from willsb/commit-committer

Changes GitHubCommit.Author/Committer 
Merge pull request #902 from naveensrinivasan/build-mono

Build fix for Xamarin Studio Solution 
Merge pull request #901 from alfhenrik/feature-issueeventsurl#885

Add Events URL to the Issue class. 
Merge pull request #900 from alfhenrik/update-testtargetnames-in-docs

Updated test target names in the shipping releases doc 
Merge pull request #898 from octokit/release

Release of v0.16 - ironic ties 
better merge exception rebased 
Generate nuget packages on appveyor  
Json serialization for Unicode 
Add helper class for creating web hooks 
added a tailored CodeFormatter to Octokit 
VS2015 migration 
clean up some pending PRs 
Fixes for Downloading ReleaseAsset zip File  
Adds overloads to GetArchive for adding custom timeouts  
Make NewRepository.HasIssues nullable as it's optional 
Created build.sh 
Gitignore exception 
Add .com links to PrivateRepositoryQuotaExceededException 
Updated with the logo 
Adds octokit samples 
Fixes for FAKE Xunit warning 
add System to required framework assemblies for net45 
Disposable repositories 
Consolidate committer info 
Add a bunch of XML doc comments 
Making Encodedcontent public #861 
Clarify why convention tests are failing 
Updated the readme with reactive octokit. 
Changes GitHubCommit.Author/Committer 
Build fix for Xamarin Studio Solution 
Add Events URL to the Issue class. 
Updated test target names in the shipping releases doc 
Release of v0.16 - ironic ties 

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

Fix the credit format 
Release notes for release 0.17.0 
Merge pull request #972 from naveensrinivasan/json-serialization

Json serialization for Unicode 
Merge pull request #976 from octokit/elbaloo-better-merge-exception-rebased

better merge exception rebased 
Merge branch 'better-merge-exception-rebased' of https://github.com/elbaloo/octokit.net into elbaloo-better-merge-exception-rebased 
Merge pull request #973 from naveensrinivasan/appveyornuget

Generate nuget packages on appveyor 
The test targets were deleting the nuget packages

The test targets were deleting the nuget packages so had to include the
CreatePackages at the end. 
Removed the disable on PR. 
Create packages in turn calls build app

Create packages in turn calls build app so no need to call it. 
appveyor nuget packages

appveyor nuget packages 
Checked for the serialized data

Compared if the serialized data has what was expected. Not just
deserialized data. 
Tests for Unicode character serialization

Tests for Unicode character serialization 
Fixes for json serialization bug

Fixes for json serialization issue when unicode is present. 
Merge pull request #917 from alfhenrik/feature-webhookhelper

Add helper class for creating web hooks 
A bit of code cleanup 
Add unit test to ensure correct message is returned when duplicate keys exists. 
Throw exception with helpful message if duplicate webhook config values exists. 
Fix up XML comments as per PR review 
Conform NewRepositoryWebHook to new request model guidelines 
Update existing integration test to use new web hook helper class 
Add unit tests 
Add helper class to create a web hook.

Fixes octokit/octokit.net#914 
Merge pull request #807 from octokit/codeformatter

added a tailored CodeFormatter to Octokit 
aaaand format the code 
skip unicode character editing 
format the code in the script 
local install of code formatter 
Merge pull request #956 from octokit/vs2015-support

VS2015 migration 
Merge pull request #921 from naveensrinivasan/samples

Adds octokit samples 
Merge branch 'gitignore-exception' 
Merge pull request #918 from willsb/download-timeout

Adds overloads to GetArchive for adding custom timeouts 
a bit more cleanup of the README 
one more malformed xml-docs tag 
Merge branch 'master' into vs2015-support 
Merge pull request #957 from octokit/clean-up-some-fixes

clean up some pending PRs 
address feedback 
added tests for the merged qualifier 
added "Merged" in searchissues which allows search repos by merged date with existing syntax.
it generates a CA1502 code excessive complexity warning and i suppressed it. 
Fixed the problem in the constructor. 
run build fixproject 
Added NewArbitraryMarkdown class, RenderArbitraryMakrdown method and unit tests for it. 
added assignee property to pull request. 
tidy up some xml-docs while i'm in here 
actually some real errors 
just suppressing some warnings, nbd 
update README to indicate we're using VS2015 
update the target to use netcore451 
bump the ToolsVersion 
bump to netcore451 
tweak ignore file 
update to the latest MSBuild scripts 
Merge branch 'master' into better-merge-exception-rebased 
Merge pull request #943 from naveensrinivasan/AssetDownload

Fixes for Downloading ReleaseAsset zip File 
Fixed the spacing

Fixed the spacing of comma and aligned the arguments. 
Fixes for Downloading ReleaseAsset zip File #854

This commit  addressed the `BuildResponse`  wasn't handling
response `content-type` `application/octet-stream` for binary items. 
Merge branch 'master' into download-timeout 
Make new merge exceptions inherit from 'Octokit.ApiException'
Affect 'Octokit.PullRequestNotMergeableException'
and 'Octokit.PullRequestMismatchException' 
Merge pull request #942 from alfhenrik/bug-repohasissues

Make NewRepository.HasIssues nullable as it's optional 
Make HasIssues nullable as it's optional 
Merge pull request #940 from naveensrinivasan/build-sh

Created build.sh 
Created build.sh

Included build.sh to build form non-windows 
:poop:

brainfart 
Add tests for merge exceptions to PullRequestsClientTests 
Add System.Net namespace used to check for HttpStatusCode in PullRequestClient.Task<PullRequestMerge> Merge(string, string, int, MergePullRequest) 
sketching out the exception necessary when raising specific merge exceptions 
Changes the way the exception is verified 
Merge pull request #929 from elbaloo/issue-389

Add .com links to PrivateRepositoryQuotaExceededException 
Add .com links to PrivateRepositoryQuotaExceededException

Add following links:
- 'Deleting a repository' at https://help.github.com/articles/deleting-a-repository/
- 'What plan should I use?' at https://help.github.com/articles/what-plan-should-i-choose/ 
Merge pull request #927 from naveensrinivasan/octokit-logo

Updated with the logo 
Changed the octokit logo to smaller size 
Updated with the logo

Updated it with the logo 
Validate Linqpad Samples as part of CI

Validates Linqpad Samples as part of CI for every commit. 
Removed the integration test options

Removed the integration test options because lprun has compileonly
option. 
The nuget package includes the samples

This will include the samples in the nuget package. 
Throwing proper exception on RepositoresClient 
Merge pull request #922 from naveensrinivasan/fixes-for-fake-warning

Fixes for FAKE Xunit warning 
Merge remote-tracking branch 'origin/fixes-for-fake-warning' into fixes-for-fake-warning

Conflicts:
  build.fsx 
Fixes for fake warning

Fixes for the FAKE warning 
Adds InvalidGitIgnoreTemplateException 
Fixes for fake warning

Fixes for the FAKE warning 
Including LINQPad.exe

Including LINQPad.exe to compile the samples after every commit 
Fixed the command line args

Fixed the args parameter to compile using lprun.exe 
linqpad samples

Linqpad samples 
Removes integer overload

Plus extra ensures 
Merge pull request #919 from adamralph/system-framework-assembly

add System to required framework assemblies for net45 
add System to required framework assemblies for net45 
Adds overloads for adding custom timeouts 
Merge pull request #909 from willsb/disposable-repositories

Disposable repositories 
Merge pull request #916 from octokit/consolidate-committer-info

Consolidate committer info 
Merge remote-tracking branch 'octokit/master' into disposable-repositories

Conflicts:
  Octokit.Tests.Integration/Clients/DeploymentStatusClientTests.cs
  Octokit.Tests.Integration/Clients/DeploymentsClientTests.cs
  Octokit.Tests.Integration/Clients/PullRequestsClientTests.cs 
Refactors the remaining test classes 
Add doc comments for Author and Committer 
Move Committer into Common folder

This object is used both in requests and responses. 
Add a README for model objects 
Replace SignatureResponse and CommitEntity with Committer

A recent PR added CommitEntity but we already had
SignatureResponse expressly for this purpose.

So this commit renames SignatureResponse to Committer
and removes CommitEntity and replaces it with Committer. 
Merge pull request #915 from octokit/docs

Add a bunch of XML doc comments 
Add this PR number for these fixes

So meta! 
Add Description to OrganizationUpdate 
Add Before property to NotificationsRequest 
Added Description property to NewTeam

Teams can have descriptions! 
Added Content property to NewTreeItem 
Add a bunch of doc comments

We get a lot of build output because of missing XML comments that we
ignore. I'd like to stop ignoring them. To do that, we need to doc the
:poop: out of everything. 
Deployment state is required for deployment status

Breaking change. This constructor parameter is now required. 
Add missing properties to NewDeployment

Added `RequiredContexts`, `Environment`, and `Task` parameters. Removed
the obsolete `Force` parameter.
Also made ref a required constructor parameter. This is a breaking
change. 
Add the ability to create a readonly deploy key 
Rename Message to CommitMessage

According to the docs
(https://developer.github.com/v3/pulls/#merge-a-pull-request-merge-button),
this should be sent as "commit_message" thus we need to name it
`CommitMessage`
Fixes #913 
Refactors tests up to PullRequestsClientTests 
Adds common properties to RepositoryContext

A lot of classes use the name and the owner of the repository, so for
consistency I added those as properties of the Context 
Refactors a whole bunch of tests 
Refactors AssigneesClient and CommitsClient tests 
Refactors BranchesClientTests 
Refactors StatisticsClient 
Refactors GithubClient and RepositoryContents 
Merge pull request #907 from naveensrinivasan/encodedcontent-public-#861

Making Encodedcontent public #861 
Refactors RepositoriesClientTests

Changes the tests in RepositoriesClientTests to use the new using block
syntax 
RepositoryContext class and Extension methods 
fix for making the setter private

fix for making the setter private 
Merge pull request #908 from khellang/clarify-failing-convention-tests

Clarify why convention tests are failing 
Clarify why convention tests are failing 
Making EncodedContent public

Making EncodedContent public to get the raw bytes of a file. #861 
Merge branch 'octokit/master' of https://github.com/naveensrinivasan/octokit.net into octokit/master 
Merge pull request #906 from naveensrinivasan/update-readme

Updated the readme with reactive octokit. 
Update read with reactive octokit.

Updated the readme to include the nuget reference to Octokit.Reactive 
Merge pull request #903 from willsb/commit-committer

Changes GitHubCommit.Author/Committer 
Merge pull request #902 from naveensrinivasan/build-mono

Build fix for Xamarin Studio Solution 
Merge pull request #901 from alfhenrik/feature-issueeventsurl#885

Add Events URL to the Issue class. 
Makes integrations tests happy 
Build fix for Xamarin Studio Solution

Build fix for Xamarin Studio Solution 
Creates CommitEntity for GitHubCommit

Creates the entity that corresponds to the actual payload returned by
the server to represent the Author and Committer of a commit 
Merge pull request #900 from alfhenrik/update-testtargetnames-in-docs

Updated test target names in the shipping releases doc 
Add Events URL to the Issue class. 
Update the names of the test targets 
Merge branch 'master' into octokit/master 
Merge pull request #898 from octokit/release

Release of v0.16 - ironic ties 
Update FAKE and SourceLink 

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:

Fix the credit format 
Release notes for release 0.17.0 
Merge branch 'gitignore-exception' 
better merge exception rebased 
Generate nuget packages on appveyor  
Json serialization for Unicode 
Add helper class for creating web hooks 
added a tailored CodeFormatter to Octokit 
VS2015 migration 
clean up some pending PRs 
Fixes for Downloading ReleaseAsset zip File  
Adds overloads to GetArchive for adding custom timeouts  
Make NewRepository.HasIssues nullable as it's optional 
Created build.sh 
Gitignore exception 
Add .com links to PrivateRepositoryQuotaExceededException 
Updated with the logo 
Adds octokit samples 
Fixes for FAKE Xunit warning 
add System to required framework assemblies for net45 
Disposable repositories 
Consolidate committer info 
Add a bunch of XML doc comments 
Making Encodedcontent public #861 
Clarify why convention tests are failing 
Updated the readme with reactive octokit. 
Changes GitHubCommit.Author/Committer 
Build fix for Xamarin Studio Solution 
Add Events URL to the Issue class. 
Updated test target names in the shipping releases doc 
Release of v0.16 - ironic ties 

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 []
  5. https://developer.github.com/v3/pulls/ []