2019-12-24 15:02

Recreating GitHub's Punch Card With SVG and Ruby

Recently I searched for GitHub's punch card feature which used to be part of the Graphs aka Insights tab. It seems it's no longer available from the user interface. Luckily the GitHub API still offers an endpoint which spits out the data used by the punch card.

This is how my punch card looks like:

The data can be obtained by calling the API:

curl --request GET \
    --url https://api.github.com/repos/{username}/{reponame}/stats/punch_card \
    --header 'authorization: Bearer {personal-access-token}'

Set username to your GitHub user name, reponame to the repository name, and create a Personal Access Token.

The result of curl will be something like this:

[
  [
    0,
    0,
    0
  ],
  [
    0,
    1,
    0
  ],
  [
    0,
    2,
    0
  ],
  [
    0,
    3,
    0
  ],
  ...

The punch card statistics are delivered as an array of tuples. Each tuple looks like like [weekday, hour, nr_commits].

In order to visualize the data I looked for a way to generate SVG programmatically. The Victor Ruby gem is exactly what I needed.

A link to the full source code can be found below. It's cool though to see how easy it is to render an SVG using Ruby and Victor:

Create a new SVG:

svg = Victor::SVG.new(width: '1120', height: '370', viewBox: "0 0 1120 370")

Render the weekdays:

xoff = 130
yoff = 80
g(font_size: 18, font_family: 'Helvetica', fill: '#555') do
  %w[Sunday Monday Tuesday Wednesday Thursday Friday Saturday].each_with_index do |day, idx|
    text(day, x: xoff, y: yoff + (idx * 40), 'text-anchor': 'end')
  end
end

Render a circle:

circle(cx: 10, cy: 20, r: 10, fill: '#ccc')

The least trivial thing was to display tooltips containing the number of commits when hovering over a cell. It turns out you need to create a rect containing a title to do this. Since each circle has a different radius I decided to draw a transparent rect on top of each cell making the hit box for each tooltip as big as possible.

Full source code

Permalink — Comments or kudos? Find me on Twitter.

Check out my new product Releasewise. It's a project inbox for product owners.


2019-12-15 13:28

Changelog JSON Specification

This document attempts to describe how a changelog can be stored in JSON format. The reason for posting this specification is that I needed a public format for https://releasewise.com/, and I was unable to find anything on the web.

But first, what is a changelog? Keep A Changelog defines it as follows:

A changelog is a file which contains a curated, chronologically ordered list of notable changes for each version of a project.

I proposes the following structure:

{
  "releases": [
    {
      "version": "",
      "codename": "",
      "released": "",
      "changelog": [
        {
          "title": "",
          "released": "",
          "label": "",
          "module": "",
          "language": "",
          "author": "",
          "description_group": [
            {
              "media_type": "",
              "body": ""
            }
          ],
          "urgency": "",
          "url_group": [
            {
              "url": "",
              "title": "",
              "url_type": "",
              "media_type": ""
            }
          ]
        }
      ]
    }
  ]
}

Example of a typical changelog:

{
  "releases": [
    {
      "version": "1.2.10",
      "codename": "Big Electric Cat",
      "released": "2019/03/30",
      "changelog": [
        {
          "title": "Tasks can now be dragged between projects",
          "released": "2019/03/28",
          "label": "Added",
          "module": "ui",
          "language": "en",
          "author": "David",
          "description_group": [
            {
              "media_type": "text/plain",
              "body": "Previously you had to cut a task and paste it into a project column in order to move tasks. With this change you can now drag and drop tasks between project columns."
            }
          ],
          "urgency": "low",
          "url_group": [
            {
              "url": "https://example.com/assets/screenshot.jpg",
              "title": "Dragging and dropping a task",
              "url_type": "image",
              "media_type": "image/jpeg"
            }
          ]
        }
      ]
    }
  ]
}
  • releases[]: array of { "version", "codename", "released", "changelog" } elements
  • version: version number, preferably based on Semantic Versioning (required)
  • codename: code name
  • released: release date of version formatted as ISO 8601 date or Unreleased
  • changelog: array of entries describing new features, bug fixes, etc
    • title: short description of the feature, preferably less than 50 characters (required)
    • released: release date of change formatted as ISO 8601 date or Unreleased
    • label: see below (required)
    • module: module name, useful for mono repos
    • language: ISO 639-1 language code
    • author: name of author
    • description_group: array of { "media_type", "body" } elements
    • media_type: allowed values are text/plain, text/html, text/markdown
    • body: description of the change
    • urgency: allowed values are low, medium, high, critical indicating importance of this change
    • url_group: array of { "url", "title", "url_type", "media_type" } elements
    • url: link to web page, image, document, or other URL-addressable asset (required)
    • title: description of resource URL points to
    • url_type: allowed values are web, image, video, audio, document
    • media_type: media/MIME type

Notes on label

The Keep A Changelog site recommends:

  • Added for new features
  • Changed for changes in existing functionality
  • Deprecated for soon-to-be removed features
  • Removed for now removed features
  • Fixed for any bug fixes
  • Security in case of vulnerabilities

Other often used labels are:

  • Unreleased
  • Improved
  • Refactored
  • Performance
  • Enhancement
  • Feature
  • Other

This specification doesn't specify a required set of label values. Although this would be preferable it seems there are too many variations out in the wild.

Permalink — Comments or kudos? Find me on Twitter.

Check out my new product Releasewise. It's a project inbox for product owners.