The letter A styled as Alchemists logo. lchemists
Published August 1, 2024 Updated September 11, 2026
Cover
Milestones

Milestones (a.k.a. tags, versions, releases) are critical to any software engineering team deploying changes to production while ensuring high quality. The problem is every team has their own custom, inconsistent, and cobbled together process. The answer can be categorized as follows:

  • Consistency

  • Automation

  • Communication

Let’s delve into each category so we can level you up by using modern tooling!

Consistency

Lack of consistency — the first problem — stems from two sub-problems: versioning and release notes. Each is explained below.

Versions

Versions (i.e. Git Tags) are simple — and powerful — yet many teams fail to use them correctly or not use them at all. Here’s a few examples seen in the wild:

2024-06-01
2024-6-5
v1.0.0
1.2
2.0 (2024-06-29)
0.1.0-beta.1
hotfix-2.1
demo-release

The above suffers from the following issues:

  • ❌ Inconsistent date/times in various formats.

  • ❌ Redundant v prefix.

  • ❌ Partial version information (major and minor) without patch information.

  • ❌ Partial version plus date/time.

  • ❌ Redundant pre-release and/or metadata suffixes for pre 1.0.0 versions.

  • ❌ Random string prefixes or random strings in general.

  • ❌ Can’t be chronologically sorted in any coherent manner.

Open source projects tend to do better in this regard but many use the redundant v prefix and some use pre-release and/or maintenance suffixes which, yes, the Semantic Versioning specification supports. Unfortunately, pre-release and maintenance versions add more noise than value since you can always checkout the main main branch or use a specific commit SHA if you need to live on the edge. There is little use for the pollution of needless versions. So, to solve this mess, enter Milestoner:

Cover

The Milestoner gem automates the calculation of your next version based on Git Trailers and enforces Strict Semantic Versioning by using the Versionaire gem. For example, let’s say you previously released 0.1.0 and made five patch commits since that release. You could use the following to calculate what your next version will be:

milestoner --next  # 0.1.1

To publish the next version, use:

milestoner --publish

With Milestoner you always get a consistent version that adheres to Strict Semantic Versioning. That’s a huge advantage and one less thing you have to worry about. We’ll make more use of Milestoner shortly but, first, we need to look at the release notes associated with a version.

Release Notes

Release notes detail and communicate what your milestone is composed of. Sadly, many teams manually build these notes by hand for each and every milestone. That’s a lot of work that can be automated!

Before we talk about automation, let’s compare/contrast a few existing open source projects. We’ll focus on three in particular: Node, Rust, and Ruby. In addition, we can use a rubric to grade release note quality via the following 25 criteria:

  • ✅ Uses project logo.

  • ✅ Uses project label.

  • ✅ Uses Strict Semantic Versioning.

  • ✅ Uses tag date.

  • ✅ Uses tag signature.

  • ✅ Uses tag author avatar.

  • ✅ Uses tag author full name.

  • ✅ Links to tag author.

  • ✅ Uses commit category icon.

  • ✅ Uses commit subject.

  • ✅ Uses commit categories.

  • ✅ Links to commit author, collaborators, and/or signers (if applicable).

  • ✅ Links to commit file count (commit).

  • ✅ Includes commit line stats (insertions/deletions).

  • ✅ Links to issue.

  • ✅ Links to code review.

  • ✅ Uses commit message with ASCII Doc or Markdown formatting.

  • ✅ Uses commit signature.

  • ✅ Uses commit fingerprint/key.

  • ✅ Uses commit date/time.

  • ✅ Uses Git Notes (optional).

  • ✅ Uses Git Trailers.

  • ✅ Includes tag totals (commits, files, deletions, and insertions).

  • ✅ Includes tag duration.

  • ✅ Links to previous/next versions.

Given the above, we can now study a few prominent open source projects and see how they measure up to this rubric.

Node

Screenshot

Node

Rubric

  • ✅ Uses project logo.

  • ✅ Uses project label.

  • ❌ Uses Strict Semantic Versioning.

  • ✅ Uses tag date.

  • ✅ Uses tag signature.

  • ✅ Uses tag author avatar.

  • ✅ Uses tag author full name.

  • ❌ Links to tag author.

  • ❌ Uses commit category icon.

  • ⚠️ Uses commit subject.

  • ❌ Uses commit categories.

  • ❌ Links to commit author, collaborators, and/or signers (if applicable).

  • ❌ Links to commit file count (commit).

  • ❌ Includes commit line stats (insertions/deletions).

  • ❌ Links to issue.

  • ✅ Links to code review.

  • ❌ Uses commit message with ASCII Doc or Markdown formatting.

  • ❌ Uses commit signature.

  • ❌ Uses commit fingerprint/key.

  • ❌ Uses commit date/time.

  • ❌ Uses Git Notes (optional).

  • ⚠️ Uses Git Trailers.

  • ❌ Includes tag totals (commits, files, deletions, and insertions).

  • ❌ Includes tag duration.

  • ✅ Links to previous/next versions.

Score: 9 / 25 = 36%

Notes

A score of 35% isn’t great. That said, you’ll soon find Node scores higher than Rust or Ruby mostly due to project logo and tag information. There is some categorization of commits and even commit subjects but they are more machine readable than human readable and your commits should always be human readable while Git Trailers are meant for machine readability.

Rust

Screenshot

Rust

Rubric

  • ❌ Uses project logo.

  • ✅ Uses project label.

  • ✅ Uses Strict Semantic Versioning.

  • ❌ Uses tag date.

  • ❌ Uses tag signature.

  • ✅ Uses tag author avatar.

  • ❌ Uses tag author full name.

  • ✅ Links to tag author.

  • ❌ Uses commit category icon.

  • ❌ Uses commit subject.

  • ❌ Uses commit categories.

  • ❌ Links to commit author, collaborators, and/or signers (if applicable).

  • ❌ Links to commit file count (commit).

  • ❌ Includes commit line stats (insertions/deletions).

  • ❌ Links to issue.

  • ✅ Links to code review.

  • ❌ Uses commit message with ASCII Doc or Markdown formatting.

  • ❌ Uses commit signature.

  • ❌ Uses commit fingerprint/key.

  • ❌ Uses commit date/time.

  • ❌ Uses Git Notes (optional).

  • ❌ Uses Git Trailers.

  • ❌ Includes tag totals (commits, files, deletions, and insertions).

  • ❌ Includes tag duration.

  • ❌ Links to previous/next versions.

Score: 5 / 25 = 20%

Notes

A score of 22% is slightly worse than what we saw with Node. Sadly, only basic project information is provided. Worse, the bulk of information links to GitHub code reviews, not the commits themselves which means we lose the benefit of good Git Commit Anatomy. Git should be our source of truth, not Github because, if we lose internet access, we shouldn’t be dependent upon a remote server. Referencing code reviews and/or issues is worthwhile but that information belongs in Git Trailers.

Ruby

Screenshot

Ruby

Rubric

  • ❌ Uses project logo.

  • ❌ Uses project label.

  • ❌ Uses Strict Semantic Versioning.

  • ❌ Uses tag date.

  • ❌ Uses tag signature.

  • ✅ Uses tag author avatar.

  • ❌ Uses tag author full name.

  • ✅ Links to tag author.

  • ❌ Uses commit category icon.

  • ❌ Uses commit subject.

  • ❌ Uses commit categories.

  • ❌ Links to commit author, collaborators, and/or signers (if applicable).

  • ❌ Links to commit file count (commit).

  • ❌ Includes commit line stats (insertions/deletions).

  • ✅ Links to issue.

  • ❌ Links to code review.

  • ❌ Uses commit message with ASCII Doc or Markdown formatting.

  • ❌ Uses commit signature.

  • ❌ Uses commit fingerprint/key.

  • ❌ Uses commit date/time.

  • ❌ Uses Git Notes (optional).

  • ❌ Uses Git Trailers.

  • ❌ Includes tag totals (commits, files, deletions, and insertions).

  • ❌ Includes tag duration.

  • ❌ Links to previous/next versions.

Score: 3 / 25 = 12%

Notes

At 12%, Ruby is at the bottom of the barrel. Much like Rust, Ruby only provides the bare minimum of information. Also, instead of linking to code reviews, Ruby links to issues. As mentioned with Rust, associating a commit with an issue is great but should be supplied via the Git Trailers. When we don’t focus on good Git Commit Anatomy, we lose the what and why of the changes being made and that’s what makes good release notes so valuable.

Milestoner

Screenshot

Milestoner

Rubric

  • ✅ Uses project logo.

  • ✅ Uses project label.

  • ✅ Uses Strict Semantic Versioning.

  • ✅ Uses tag date.

  • ✅ Uses tag signature.

  • ✅ Uses tag author avatar.

  • ✅ Uses tag author full name.

  • ✅ Links to tag author.

  • ✅ Uses commit category icon.

  • ✅ Uses commit subject.

  • ✅ Uses commit categories.

  • ✅ Links to commit author, collaborators, and/or signers (if applicable).

  • ✅ Links to commit file count (commit).

  • ✅ Includes commit line stats (insertions/deletions).

  • ✅ Links to issue.

  • ⚠️ Links to code review.

  • ✅ Uses commit message with ASCII Doc or Markdown formatting.

  • ✅ Uses commit signature.

  • ✅ Uses commit fingerprint/key.

  • ✅ Uses commit date/time.

  • ✅ Uses Git Notes (optional).

  • ✅ Uses Git Trailers.

  • ✅ Includes tag totals (commits, files, deletions, and insertions).

  • ✅ Includes tag duration.

  • ✅ Links to previous/next versions.

Score: 24.5 / 25 = 98%

Notes

In this case, Milestoner is used to build release notes for itself but could be used for any language, any project. A score of 96% makes Milestoner the leader in terms of release note quality. So why isn’t Milestoner at 100%? Well, Milestoner only has partial support for code reviews because this requires making API calls to the various source servers like GitHub, GitLab, Bitbucket, etc.

Automation

Automation is the second major problem teams face which tends to be manual, semi-automatic, or a complex pipeline of automation depending on the stack. This can be broken down into the following sub-categories:

  • Manual (or Semi-Automatic): Costs time, money, and lack of consistency. This also requires continuous maintenance and training of new engineers to the team.

  • Automatic (but Complex): Costs money in terms of maintenance and upkeep while becoming a bottleneck to all teams since there tends to be one team that owns and maintains this process.

What we need is a powerful but simple tool anyone can use for open source, internal projects, and so forth. Milestoner aims to solve that need. To shed more light on Milestoner, let’s look at how Milestoner is architected and how it can be incorporated into your own workflow.

Architecture

The following image diagrams the architecture that Milestoner is built upon. There is no need to break down each individual gem as you can explore more when you have time. Despite not being shown here, Hanami Views is what makes the rendering of release notes possible.

Architecture

The impression to be made here is that Milestoner is a gem, yes, but more like a mini-application all wrapped up as a Command Line Interface (CLI) using Ruby. You don’t need to build complex applications to pull this off but rather leverage the building blocks of smaller and highly specialized gems that do one thing extremely well. In other words, the S in SOLID design (i.e. Single Responsibility Principle).

Workflow

The following shows a typical workflow:

Workflow

This workflow is broken down as follows:

  1. Code Quality: The Caliber and Git Lint gems are a subset of Code Quality tooling that allows you to prevent garbage from coming in while keeping the quality of code high.

  2. Implementation: Assuming you are implementing a solution in Ruby, you might want to build a project skeleton using:

  3. Deployment: Once all code quality checks have passed and work is complete, you can use Milestoner to tag, build release notes, and deploy your work.

As you can see, Milestoner is the last — but critical — step of your workflow. The best part is, once you have this tooling in place, code quality and deployment is fully automated. This allows you to focus on what you do best, which is staying focused on building creative solutions which delight your customers.

Communication

Communication is the third and trickiest of all problems to solve because the root of the problem isn’t usually technical but cultural. Streamlining how you communicate is critical. The following illustrates the multiple channels of communication when working as a team:

Communication

This breaks down as follows:

  1. Engineers: Communication starts with the engineering team by figuring out which bug and/or features to prioritize.

  2. Issues: While working on issues, there might be some communication on clarifications, status updates, blockers, and so forth.

  3. Code Review: Once the work is done, the team will review, discus, and/or suggest further improvements.

  4. Source Control: All thoughts and ideas — as preserved via good Git Commit Anatomy — is preserved for historical and future discussion.

  5. Continuous Integration: Notifications will be sent if the build is green or red.

    • Deployment: Notifications will be sent if the deploy passes or fails.

    • Release Notes: Details and preserves what went into the release.

  6. Recipients: Engineers, stakeholders, and/or customers receive news of new developments and/or changes.

While Milestoner can’t solve all of your communication needs, it definitely reduces the number of communication channels needed because now you can send the same information to engineers, stakeholders, and/or customers. Even better, deployment and release note generation can be collapsed down to a single process.

Conclusion

We’ve learned to think about your own processes in terms of being consistent, automated, and communicative. Maybe you already have this buttoned down but, if not, add Milestoner to your workflow so you can do more with less.