Gems, NuGet, CI, and the Ghost Content API v2.0

Full article

This was a week of firsts. It started with having to add some tests for a new feature to one of our many test suites at work, and finding the logic we'd need for those new tests were spread across several Ruby projects. Time for some copypasta!!

Not really, luckily. I've got limited experience with Ruby, so although I'd heard of and used gems I'd never created one. Turns out, it's super easy to make your own gem. If you're familiar with the .NET ecosystem, it's as straightforward as creating a class library and then either referencing the code locally or uploading it to NuGet. Too bad, I do love pasta...

NuGet Package Manager

Speaking of NuGet, I uploaded my GhostSharp project (a C# wrapper around the Ghost API) and you can check it out here. This was my first experience uploading to the popular package manager, and it wasn't too bad. The team behind the Ghost blog recently released an updated Content API (an Admin API is in the works too), so I took the opportunity to update GhostSharp from using v0.1 to v2.0.

I also took the opportunity to change the .NET Framework I was using, to increase the portability of my app, first switching from .NET 4.x to .NET Core, and then finally to .NET Standard which appears to be the LCD if you're trying to build a library that can be referenced from all .NET implementations.

After publishing to NuGet, I created a quick little WPF app that used it. Works great! (whew)

<Window x:Class="WpfApp2.MainWindow"
        mc:Ignorable="d" Title="MainWindow" Height="450" Width="800">
        <Image x:Name="banner" />
        <TextBlock HorizontalAlignment="Center" x:Name="title"
                   FontSize="40" FontWeight="Bold" Foreground="Orange" />
using GhostSharp;
using System;
using System.Windows;
using System.Windows.Media.Imaging;

namespace WpfApp2
    public partial class MainWindow : Window
        public MainWindow()

            var gs = new GhostAPI("", "your-key");
            var post = gs.GetPostBySlug("the-5-stages-of-debugging-grief");

            title.Text = post.Title;
            banner.Source = new BitmapImage(new Uri(post.FeatureImage));

Also, if you happen to have some JSON that you'd like to convert into C# classes, here's a great tool I stumbled across. I think there's a way to do this from within Visual Studio too, but I can't remember the shortcut at the moment.

You can find out more about creating your own NuGet packages here:

Travis CI

Finally, I took the opportunity to configure Travis CI to build my project and run the 250 integration / unit tests I wrote. Have you ever noticed the "build | passing" badge at the top of GitHub projects, like I have in the GhostSharp repo?

It's somewhat easy to set this up, but it definitely took a fair amount of reading and playing with the build script that goes in the travis.yml file which Travis CI uses to do the build. They've got some decent documentation for getting started, but I found their examples to not be all that helpful - or at least, it wasn't as simple as copy/pasting, especially when it comes to running NUnit tests.

In the end, I figured it out - and it ended being far easier than I thought it'd be! Since my GhostSharp.Tests test project has a reference to the GhostSharp project, I just had to change to that directory, do a restore (to grab NuGet packages), a build, and finally a test to run the full suite.

dist: xenial
language: csharp
solution: GhostSharp.sln
mono: none
dotnet: 2.2.104
  - cd GhostSharp.Tests
  - dotnet restore
  - dotnet build
  - dotnet test

I also configured Travis to securely store a Ghost Content API Key I created just for this purpose, and it feeds it to the C# project during the build, where it can be easily read in using Environment.GetEnvironmentVariable.

It's awesome that every push I make will now run my full test suite to make sure I didn't break anything. Check out the builds here.

Other reading that may (or may not) be helpful:


Grant Winney

I write when I've got something to share - a personal project, a solution to a difficult problem, or just an idea. We learn by doing and sharing. We've all got something to contribute.

Comments / Reactions