Skip to content

Releasing basic projects

This tutorial will take you step by step through the process of:

  1. Documenting changes to a package
  2. Adding those changes to a changelog
  3. Updating version numbers
  4. Creating releases on GitHub

Prerequisites

  • Git: The git CLI must be available in your terminal. It’s helpful if you know the basics of commits and tags.
  • A text editor: for editing Markdown and JSON files. Visual Studio Code is a good free choice.
  • Familiarity with a command line terminal, like “Terminal” on macOS or “PowerShell” Windows
  • A GitHub account (you can use an alternative, but the results will be different)
  • Install Knope

Creating a project

Create a new directory for this tutorial and initialize a Git repository:

Terminal window
mkdir knope-tutorial # create a new directory
cd knope-tutorial # change into the new directory
git init # initialize Git

Now open the directory in your text editor and create two files:

CHANGELOG.md
# Changelog
This is where the changes in each release are documented.
package.json
{
"name": "pizza-builder",
"version": "1.0.0"
}

This is simulating a JavaScript package—in a real package you’d have a lot more info in your package.json file, but version is all that Knope needs. This package is starting at version 1.0.0, as you make changes, the version will increase depending on the type of change.

Knope needs a GitHub repository to publish releases. You can create one with the GitHub CLI.

Terminal window
gh repo create --private knope-tutorial --source .

Little changes

Start by documenting a small change using a conventional commit.

Terminal window
git commit --allow-empty -m "fix: No longer crashes when you add pineapple"

You’ve just documented a bug fix using a commit message!

Knope can give a preview of the next release:

Terminal window
knope release --dry-run
Example output from Knope
Would add the following to package.json: 1.0.1
Would add the following to CHANGELOG.md:
## 1.0.1 (2024-03-24)
### Fixes
- No longer crashes when you add pineapple
Would add files to git:
package.json
CHANGELOG.md
Would run git commit -m "chore: prepare release 1.0.1"
Would run git push
Would create a release on GitHub with name 1.0.1 (2024-03-24) and tag v1.0.1 and body:
## Fixes
- No longer crashes when you add pineapple

According to that output, Knope will:

  1. Set the version of the package in package.json to 1.0.1
  2. Add a new section to CHANGELOG.md with the documented changes
  3. Commit those changes to Git and push to the remote repo
  4. Create a new release on GitHub

Time to release it for real!

Creating a release

Running the release workflow again without the --dry-run option causes Knope to do everything it promised to.

Terminal window
knope release
? No GitHub token found, generate one from https://github.com/settings/tokens with `repo` permissions and input here

Knope wants to create that GitHub release, but it needs access to GitHub! Go ahead and generate a token with the link it provided, then paste it into your terminal.

Now that the workflow has complete, the package.json has the new version number:

package.json
{
"name": "pizza-builder",
"version": "1.0.1"
}

The CHANGELOG.md has the message from the commit:

CHANGELOG.md
# Changelog
This is where the changes in each release are documented.
## 1.0.1 (2023-11-01)
### Fixes
- No longer crashes when you add pineapple

And that same content is in a new GitHub release:

Terminal window
gh release view --web

GitHub release

More complex changes

Conventional commits are great for simple changes, you just start your commit with fix: or feat: . For changes that take more than a few words to describe, though, changesets are a better fit:

Terminal window
knope document-change

You’ll get a choice of the type of change. The terms are from semantic versioning, so minor is what you’ll want for a new feature:

? What type of change is this?
major
> minor
patch
[↑↓ to move, enter to select, type to filter]

After selecting minor with the enter key, you can summarize the new feature:

> What type of change is this? minor
? What is a short summary of this change? Add calzones
[This will be used as a header in the changelog]

This created a new Markdown file which you can fill in with more details:

.changeset/add_calzones.md
---
default: minor
---
# Add calzones
In addition to building Pizzas, you can now build calzones! Just use the new `--calzone` option!
> Pizza? Never heard of it. That's what people will be saying in 20 years, because pizza is old news. Pizza is your grandfather's calzone.

You can also add a conventional commit into the same release:

Terminal window
git commit --allow-empty -m 'feat: Added the `olives` topping'

A dry run will explain what Knope will do:

Terminal window
knope release --dry-run
Example output from Knope
Would delete: .changeset/add_calzones.md
Would add the following to package.json: 1.1.0
Would add the following to CHANGELOG.md:
## 1.1.0 (2023-11-02)
### Features
- Added the `olives` topping
#### Add calzones
In addition to building Pizzas, you can now build calzones! Just use the new `--calzone` option!
> Pizza? Never heard of it. That's what people will be saying in 20 years, because pizza is old news. Pizza is your grandfather's calzone.
### Fixes
- No longer crashes when you add pineapple
Would add files to git:
package.json
CHANGELOG.md
.changeset/add_calzones.md
Would run git commit -m "chore: prepare release 1.1.0"
Would run git push
Would create a release on GitHub with name 1.1.0 (2023-11-02) and tag v1.1.0 and body:
## Features
- Added the `olives` topping
### Add calzones
In addition to building Pizzas, you can now build calzones! Just use the new `--calzone` option!
> Pizza? Never heard of it. That's what people will be saying in 20 years, because pizza is old news. Pizza is your grandfather's calzone.
## Fixes
- No longer crashes when you add pineapple

Uh oh, Knope is including the fix from the last version! That’s because Knope uses Git tags to figure out which conventional commits to include in a release. The release is on GitHub, but not in the local file system! You can fix that by pulling the tags:

Terminal window
git pull --tags
knope release --dry-run
Example output from Knope
Would delete: .changeset/add_calzones.md
Would add the following to package.json: 1.1.0
Would add the following to CHANGELOG.md:
## 1.1.0 (2023-11-02)
### Features
- Added the `olives` topping
#### Add calzones
In addition to building Pizzas, you can now build calzones! Just use the new `--calzone` option!
> Pizza? Never heard of it. That's what people will be saying in 20 years, because pizza is old news. Pizza is your grandfather's calzone.
Would add files to git:
package.json
CHANGELOG.md
.changeset/add_calzones.md
Would run git commit -m "chore: prepare release 1.1.0"
Would run git push
Would create a release on GitHub with name 1.1.0 (2023-11-02) and tag v1.1.0 and body:
## Features
- Added the `olives` topping
### Add calzones
In addition to building Pizzas, you can now build calzones! Just use the new `--calzone` option!
> Pizza? Never heard of it. That's what people will be saying in 20 years, because pizza is old news. Pizza is your grandfather's calzone.

Much better! Now that Knope knows when 1.0.1 was, it can ignore the changes from that release. Time to create this release for real:

Terminal window
knope release
gh release view --web

GitHub release

This illustrates one of the big advantages to changesets, you can write as much Markdown content as you need to describe a change. There could be code snippets, screenshots, even collapsible sections!

Finishing up

You’ve done it! You documented both simple changes (with conventional commits) and complex changes (with changesets). Then, you released them by updating the changelog, bumping the version, and creating a GitHub release, all with a single command!

You already have the basic skills necessary to start speeding up your release processes, but you can take it a step further by releasing in GitHub Actions.