Adding changelogs to blog posts
This week I published a post (a collection of today-I-learn nuggets) that I might further update in the future. For the updates I'd love to add a changelog to the post bottom, and also add the last updated to the post top. However: I store posts in Markdown with a frontmatter; and the frontmatter contains the date
field; and the one field is not sufficient to capture the changes. So here's how I changed the frontmatter and how I migrated existing posts.
Storing the changelog #
First, I discovered that Markdown frontmatters are, in fact, full-fledged YAML. So I can store a complex data structure, such as a list of maps in there. I think this is a really cool feature of frontmatters. Here's a new frontmatter shape:
---
title: "Typescript & NodeJS: Collection of TILs"
changelog: # 🎉
- date: 2021-03-30
change: postUpdated
detail: >
Added 3 TILs: absolute imports in Webstorm,
const assertions and
checking string literal types at runtime
- date: 2021-03-29
change: postPublished
# ... rest of the frontmatter ...
---
# ... content of the post...
Updating the static-site generator #
I use NextJS for this blog. NextJS is a React-based static site generator. I use NextJS together with Typescript. I have an interface representing a post, so I expanded it as follows:
interface ChangelogItem {
date: string // string because of NextJS serializion
change: "postPublished" | "postUpdated"
detail?: string
}
interface Post {
changelog: ChangelogItem[]
publishedOn?: string
lastUpdatedOn?: string
// ...
}
I updated the code that parses the frontmatter and also updated the React component that generates the site.
Migrating existing posts #
Ok, so that should do for new posts. However, I have around 50 existing posts with a, now obsolete, date
field:
---
title: "A post with an obsolete date"
date: 2021-03-30 # <----- this needs to be migrated to a new shape
tags: engineering
---
Lorem ipsum dolor
What I needed is to migrate the old frontmatters into a new shape. So I summed my favorite awk
to do the heavy lifting:
# content of migrate-to-change-log.awk
BEGIN { delims = 0 }
# count the delimiters to determine if we are inside the frontmatter
/---/ { delims++; }
{
if (delims == 1 && /^date:/) {
printf "changeLog:\\n - date: %s\\n change: postPublished\\n",$2
} else {
print
}
}
Once I had the awk
script down, I migrated all posts with:
echo *.md | xargs -n1 gawk -i inplace -f migrate-to-change-log.awk
Here's an outcome on the sample post:
---
title: "some title"
changeLog: # 🎉🎉🎉
- date: 2021-03-30
change: postPublished
tags: engineering
---
Lorem ipsum dolor
Using git instead? #
When writing this post, it occurred to me that instead of the frontmatter, git can also be used as a data source for the changelog. For this to work, I would have to exclude refactoring commits, which change the post structure. For example, a commit that replaces the date
field with the changeLog
field. Or a commit that moves the file around. I'll keep this idea in the background mind for now.
- ← Previous post: Changelog of this blog (meta)
- → Next post: Building cathedrals
This blog is written by Marcel Krcah, an independent consultant for product-oriented software engineering. If you like what you read, sign up for my newsletter