Using ScriptCS to automate release notes
How I replaced a dodgy bash shellscript with some ScriptCS magic to generate release notes from our Git and Jira repositories.
My project needs release notes containing information like the Jira tickets resolved in the release, the number and scale of the source code changes, etc. This information is provided both to our testers so they know what has changed, and also to our clients internal change control board.
We use a number of products and services to build the applications in the solution:
- GitHub for source control,
- Jira for bug and work item tracking,
- TeamCity for build automation, issuing version numbers and source code tagging, and
- OctopusDeploy for deployment automation.
A real challenge was to mash up information from these systems to provide the internal traceability on the contents of the build.
###First Attempt
Logically the best way to solve this problem is using a shell script right?
At least that was my first thought more than 3 years ago…strange decision I know but then again my opinions at the time weren’t great.
The main reason was that I was, and still am, using the Git bash shell and wanted an easy way to just
After much mucking around with redirecting STDOUT to files for sorting, searching and filtering (sed, greg, awk) I got it working and moved on.
Fast forward 18 months and it was broken and I had no idea how to fix it - time for a rewrite.
###Better Attempt
Haven’t mentioned ScriptCS yet have I? awesome project and really really useful - go check it out.
One of the bug bears with my first attempt (other than it breaking) was that I had to rely on the devs, or me changing commit messages, to ensure that there was enough information in the commits to describe the Jira tickets. Nuts to that.
Armed with ScriptCS my goal was to build a small script which could easily extract the following in a word document:
- All commits between two version tags provided as arguments
- All Jira tickets referenced in the commits
- Specific details (summary, components, epic) of the referenced Jira tickets
- File diffs (not particularly useful but still…)
The script was pretty straight-forward really - using the following libraries to extract, interrogate and transform the data into the format that I needed.
The only problem that it didnt work, at least not straight away due to issues with ScriptCS struggling to load the native assemblies required for the LibGit2Sharp nuget package.
Using LibGit2Sharp to extract the commits between the tags was pretty simply - find the tags, exectute a search and then consume the data. The only gotcha was the ordering of the search parameters as you’re walking backwards from the current HEAD of the repository:
Once I had the commits I was interested in extracting the Jira tickets was a snap (take that Awk!) and in no time I was using the JiraRestClient to retrieve the data I needed from the Jira REST API.
JiraRestClient comes with a predefined set of fields which are retrieved when you interrogate the API, however the list of Components (which we use to classify different areas of our systems) is not one of them. Luckily, the API allows you to extend the IssueFields class to de-serialise any of the additional information which is returned by the REST API:
The final piece of the puzzle was to export the data into a word document so it can be issued - so it was back to the old faithful the OpenXml SDK. Again, if you haven’t played with this before go and have a look, it’s a really neat framework for manipulating or creating documents or document fragments and it isn’t limited to just Word documents.
I’ve used OpenXml for a bunch of things over the years; from mass producing lab sample labels to automating database documentation and the process is pretty simple.
- Open the document
- Find and modify the elements youj want to change using the Queryable’s provided.
- Do something with the output.
The tricky bit when dealing with OpenXml for me has always been tables - there isn’t really a nice way to bind data in such a way that the rows are created automatically and the ordering of columns isn’t so sensitive as it would be if you are manually adding rows and expecting columns to be a in a certain sequence.
My solution was to bind the columns of the table to the property names of the object through the text contained in the heading column:
This solution works reasonably nicely as it allows the columns to be re-ordered or additional columns added without having to changed the script (unless we need to pull down more data from Jira)
###Ideal Solution?
When I started down this path I really wanted something just to replace the old bash script that had stopped working. However by the end what I really wanted was something that was integrated into our build and deployment process to automate the whole process with the additional benefits of being able to retain the release notes against the release in octopusDeploy.
Thats my ideal solution, but for now what I have is Good Enough.