Introduction
I've been looking for a simple way to show my existing users when I release a new version of my project. Since it's hosted on github, github already offers me an easy way to post such updates. I just need an easy way to grab it. Then, decide on a friendly way to show it!
I'm talking about what you see when you click on the Releases
tab on any github project. Something like this:
What for?
Here are some possible Scenarios you'll find this helpful for:
- Provide a more meaningful About box (see below)
- Unintrusively notify users that they don't have the most up-to-date version
- Easily point users to download the latest version of your application
- An auto-updater that downloads and installs your latest version (stable or beta)
What Information to grab
On github, when you create a release, in adition to the name, description, you can attach binaries (which would be your setup kit(s)). For each release, they will be shown below the description.
When I create a new release, I make sure the tag matches the release number (in our case, 1.5.1
), like this:
We can later grab the above info:
- version information (such as,
1.5.1
)
- short description (such as, "New logs, show updates from github, added aliases")
- long description (what's shown below the short description)
- download links (if possible, separated onto 32-bit / 64-bit setup kits)
Github already provides an API for this (it returs a json-formatted page). What I was surprised to see is that there's no C# wrapper to give me easy access to it. So, I made one.
Update: Turns out there is a C# Wrapper - thanks to Brisingr Aerowing for pointing it out! The official release is found here. Two things to note about oktokit:
- the latest source code is huge and seems to have a lot of dependencies;
- the library is released under MIT License
For each github project, the API provided by github is at this page:
https: // api.github.com / repos / github_username / github_project / releases
You can take a look at any github project and see that there's quite a bit of info there. I decided to only grab only what I've explained above.
Using my C# wrapper in your code is literally a few lines of code. First, get to your project:
var info = new read_github_release(github_username, github_project);
var info = new read_github_release("jtorjo", "logwizard");
My code will read and parse all the releases from this project. To access them, I've provided 3 functions:
public List<release_info> beta_releases();
public List<release_info> stable_releases();
public List<release_info> release_before();
For beta_releases()
and stable_releases()
, it's the versions that have been released since the version the user has installed on his machine. I grab that (version the user has) from your assembly (the Product Version)
. Namely, it's the version you have in your AssemblyInfo.cs :
[assembly: AssemblyVersion("1.3.0.0")]
Similarly, the release_before()
, contains all versions up-to-and-including to what the user has installed on his machine. Use this to show to the user - information about the current version.
Finally, the release_info
is quite easy to access:
public class release_info {
public string version;
public string short_description;
public string long_description;
public bool is_stable ;
public bool is_beta ;
public List<string> features { get { ... } }
public string friendly_url = "";
public List<string> download_url = new List<string>();
public string download_32bit_url { ... }
public string download_64bit_url { ... }
}
Constraints
The github tag name is what I return as release_info.version
. It must match your application version (Product Version
). This is so I can easily know which versions are older and which newer than what the user has installed.
To mark a binary as being 64-bit, just write "64-bit" or"64bit" somewhere in its name before uploading it. Otherwise, I consider it a 32-bit binary.
What's stable / beta?
A version is :
stable
or beta
, if the version name is valid. A valid version number is anything you can write as the Product Version (major.minor.build.minor_build
). Valid names are "1.2", "1.3.0", "1.4.4.12". Invalid names are "v2", "1.3.4a", "MyCoolRelease".
- Anything that is not stable or beta, I consider
interim
. An interim is something you release but consider to be pre-beta or just a release candidate. You can use this to create releases that don't show up as a possible update, until a stable or beta supercedes it.
- A version is
beta
, if the short description contains "(beta)" at the end.
- Note that you can release a version and mark it as
beta
, and after a while mark to mark it stable
. Just later on edit it, and remove the "(beta)" from its short description.
Even though I think the above is a pretty simple convention, you can still override how a version is to be considered stable
or beta
:
public delegate bool is_good_version_func(Dictionary<string, object> ver);
public is_good_version_func is_stable, is_beta;
The argument that is passed to each delegate is the JSON-parsed information.
Using it in code
You decide how to use it in code. Here's a possibility:
var info = new read_github_release("jtorjo", "logwizard");
var new_releases = info.beta_releases();
var cur_release = info.release_before();
var stable_ver = new_releases.FirstOrDefault(x => x.is_stable);
downloadStable64.Enabled = stable_ver != null && stable_ver.download_64bit_url != "";
downloadStable32.Enabled = stable_ver != null && stable_ver.download_32bit_url != "";
stable.Text = stable_ver != null ? friendly_ver_string(stable_ver) : "Congratulations! ...";
if (stable_ver != null)
stableGroup.Text += " (" + stable_ver.version + ")";
var beta_ver = new_releases.FirstOrDefault(x => x.is_beta);
downloadBeta64.Enabled = beta_ver != null && beta_ver.download_64bit_url != "";
downloadBeta32.Enabled = beta_ver != null && beta_ver.download_32bit_url != "";
beta.Text = beta_ver != null ? friendly_ver_string(beta_ver) : "Congratulations! ...";
if (beta_ver != null)
betaGroup.Text += " (" + beta_ver.version + ")";
current.Text = concatenate(cur_release.Select(friendly_ver_string), "\r\n\r\n");
currentGroup.Text += " (" + version() + ")";
private string friendly_ver_string(read_github_release.release_info ver) {
string friendly = "[" + ver.version + "] " + ver.short_description + " ";
if (!ver.is_stable && !ver.is_beta)
friendly += "(interim)";
friendly += "\r\n";
friendly += concatenate(ver.features.Select(x =>"* " + x), "\r\n");
return friendly;
}
This will generate something similar to this (you will find the above code in the source code I've provided):
Points of Interest
It's quite easy to parse the JSON answer given by github, especially using the cool fastJSON lib. If you want to add more meaningful info to release_info, take a look at:
private release_info to_release(Dictionary<string, object> ver) ;
There's more information about what github API here.
History
- Nov 10, 2015 - Initial version