Um momento
0xA0Lesson 11 of 14

Releases and semantic versioning

Version with semver and conventional commits, tag releases, write release notes, and publish packages.

26 min 7-question quiz 2 code exercises
By the end of this lesson you can
  • Choose the next version with semantic versioning
  • Write conventional commit messages that tools can read
  • Create tagged releases with notes and attached files, and publish packages

Dungeon Dash players want to know: is the new version safe to install? Will my save files still work? Semantic versioning (semver) answers that in the version number itself, MAJOR.MINOR.PATCH:

BumpWhenExample
MAJORbreaking changes - users must adapt1.9.3 → 2.0.0: old save files no longer load
MINORnew features, backwards compatible1.4.2 → 1.5.0: boss battles added
PATCHbug fixes only1.4.2 → 1.4.3: wall clipping fixed

Bumping one resets the ones to its right. Pre-releases like 2.0.0-beta.1 come before 2.0.0, and versions below 1.0.0 signal “anything may change”.

Conventional commits

If commit messages say what kind of change they are, tools can pick the next version and write release notes automatically. Conventional commits use a type prefix:

1feat: add boss battles                    → minor
2fix(physics): stop wall clipping          → patch (scope in parentheses)
3docs: explain the controls                → no release by itself
4feat!: new save file format               → major (the ! means breaking)
5refactor: split the renderer
6
7BREAKING CHANGE: saves from 1.x won’t load   ← a footer also means major

Other common types: chore, test, perf, ci, build, style. Many teams enforce the format in CI, and with squash merging the PR title becomes the commit message - so it’s the PR title that has to follow the convention.

next_version.py
1import re
2
3def next_version(current, commits):
4    major, minor, patch = map(int, current.lstrip("v").split("."))
5    kinds = []
6    for message in commits:
7        match = re.match(r"(\w+)(?:\([\w-]+\))?(!)?:", message)
8        if match and (match.group(2) or "BREAKING CHANGE:" in message):
9            kinds.append("major")
10        elif match and match.group(1) == "feat":
11            kinds.append("minor")
12        elif match and match.group(1) in ("fix", "perf"):
13            kinds.append("patch")
14    if "major" in kinds:
15        return f"v{major + 1}.0.0"
16    if "minor" in kinds:
17        return f"v{major}.{minor + 1}.0"
18    if "patch" in kinds:
19        return f"v{major}.{minor}.{patch + 1}"
20    return f"v{major}.{minor}.{patch} (no release needed)"
21
22print(next_version("v1.4.2", ["fix(physics): stop wall clipping", "docs: controls"]))
23print(next_version("v1.4.2", ["feat: boss battles", "fix: typo in menu"]))
24print(next_version("v1.4.2", ["feat!: new save format"]))
25print(next_version("v1.4.2", ["chore: update dependencies"]))
Output
v1.4.3
v1.5.0
v2.0.0
v1.4.2 (no release needed)

Tags and releases

A Git tag marks a commit with a name like v1.5.0. A GitHub release builds on a tag: a title, release notes, and attached files (“assets”) like the game’s installers. GitHub can generate notes from the merged PRs since the last release, grouped by label.

cutting a release
1git tag -a v1.5.0 -m "Boss battles"
2git push origin v1.5.0
3gh release create v1.5.0 dist/*.zip --title "v1.5.0: Boss battles" --generate-notes
4gh release create v2.0.0-beta.1 --prerelease --notes "Try the new save format!"

Many projects let a workflow do this: on a tag push (on: push: tags: ["v*"]), build the game, create the release and upload the assets. And GitHub Packages hosts packages - container images on ghcr.io, npm, Maven and more - next to the code, with the same permissions.

Key takeaways

  • Semver MAJOR.MINOR.PATCH: breaking changes, features, fixes; bumping one resets the rest.

  • Conventional commits (feat, fix, feat!, BREAKING CHANGE) let tools choose versions and write notes.

  • Tags mark commits; releases add notes and downloadable assets, often created by a workflow.

  • Pre-releases like 2.0.0-beta.1 sort before 2.0.0.

Lesson quiz

7 questions · pass with 5 correct · up to 50 XP

Passing this quiz completes the lesson and keeps your streak going. Questions you miss come back in review sessions later.

Practice: automate GitHub chores with Python

Real GitHub work involves lots of small automation: matching CODEOWNERS, expanding build matrices, bumping versions, reading the API. Write those helpers in Python and run them against sample inputs - locally in your browser, with no GitHub account needed.

Exercise 1

Choose the next version

+25 XP

The first input line is the current version (like v1.4.2); the rest are conventional commit messages since then. Print the next version and why: v1.5.0 (minor: 1 feature, 2 fixes). A type followed by !, or a message containing BREAKING CHANGE:, is breaking (major); feat is minor; fix and perf are patch; anything else doesn’t trigger a release. Count features (feat), fixes (fix and perf) and breaking changes, listing only the non-zero counts in that order. With nothing releasable print v1.4.2 (no release).

  • A feature release
  • Breaking
  • Nothing to release
main.py
Loading editor…

Python runs in a sandboxed browser worker with a 60 second time limit. Its runtime loads from the Pyodide CDN; your code stays in this browser.

Exercise 2

Sort versions the semver way

+25 XP

Each input line is a version tag (an optional v, then MAJOR.MINOR.PATCH, optionally -PRERELEASE). Print them oldest first, then latest stable: v... (the newest without a pre-release part). Semver precedence:

  • compare MAJOR, MINOR, PATCH as numbers (so 1.10.0 is after 1.9.0);
  • a pre-release comes before the same version without one;
  • pre-releases compare dot-separated part by part: numeric parts as numbers, text parts alphabetically, numbers before text, and fewer parts first when all else is equal (alpha < alpha.1 < beta < beta.2 < beta.11 < rc.1).
  • Mixed tags
  • Only betas ahead
main.py
Loading editor…

Python runs in a sandboxed browser worker with a 60 second time limit. Its runtime loads from the Pyodide CDN; your code stays in this browser.

Questions about this lesson

Stuck? Ask. Figured something out? Share it. Explaining is one of the best ways to learn.

Loading posts…

Gostou da aula? 😆👍
Apoie nosso trabalho com uma doação: