Caretaker
Caretaker is an automated changelog generator. It works by reading the commit history for the repository and generates the changelog based on that. It requires no human intervention, and will work happily with existing repositories and their existing git histories.
Caretaker also has an advanced category mode, which allows it to parse specially crafted commit messages and split the CHANGELOG into categories (per release).
Additional features
- Converting a GitHub username tag into a link to the GitHub user (appended to the commit message).
- Automatically linking each commit message to the hash of that commit.
- Automatically linking each pull request to the pull request number.
- Can run automatically as a post-commit hook.
- Ignore commits that are shorter than a specified number of words.
- Bump verions and tag releases automatically.
For a full list of featues see the section on command line usage.
Table of contents
- Caretaker
- To-Do List <!--TOCBot-->
Installation
Installing caretaker is very simple, just execute the following command.
gem install caretaker
Command line usage
Caretaker has a number of command line options:
Usage: caretaker [-h] [-a ] [-c] [-e] [-i] [-o filename] [-r] [-s] [-u] [-w number]
| Option | Purpose | Default Value |
|---|---|---|
| -h or --help | Show the help message | N/A |
| -a or --author [Github username] | Specify the author name | |
| -b or --bump [part] | Bump the VERSION.txt to next version. | |
| -c or --config | Generate a .caretaker.cfg config file. | false |
| -e or --enable-categories | Enable the splitting of commit messages into categories | false |
| -i or --init | Initialise the repo to use caretaker | |
| -o or --output [filename] | Set the name of the output file | CHANGELOG.md |
| -r or --remove-categories | Remove categories from commit messages. --enable-categories sets this to true | false |
| -s or --silent | Turn off all output from Caretaker, aka Silent Mode | false |
| -u or --url-verification | Verify each url to ensure that the links are valid, skip any links that are not | false |
| -w or --words number | Minimum number of words needed to include a commit. | 1 |
Basic usage
Initialise the repository
This step isn't required but running the following command configures your repository to use caretaker automatically on every commit to ensure that your changelog is as up-to-date as possible.
caretaker -i
What is actually does is create a post-commit hook in your git repo which execute caretaker and adds the updated CHANGELOG.md to the commit ready for you to push.
The post-commit hook
#!/usr/bin/env bash
OUTPUT_FILE="CHANGELOG.md"
caretaker
res=$(git status --porcelain | grep "${OUTPUT_FILE}" | wc -l)
if [[ "${res}" -gt 0 ]]; then
git add "${OUTPUT_FILE}"
git commit --amend --no-edit
end
Customisation
There are a number of ways in which you can customise the way caretaker works, you can enable category mode, or change the output file from CHANGELOG.md to some other name. If you do this as part of the initialisation then the settings are retained.
Example of customised usage
caretaker -i -e -o HISTORY.md
Resulting post-commit hook
#!/usr/bin/env bash
OUTPUT_FILE="CHANGELOG.md"
caretaker -i -e -o HISTORY.md
res=$(git status --porcelain | grep "${OUTPUT_FILE}" | wc -l)
if [[ "${res}" -gt 0 ]]; then
git add "${OUTPUT_FILE}"
git commit --amend --no-edit
end
It is worth noting the final git commit command the --amend tells git to amend the last commit and add in the output file and the --no-edit tells git that we do not want to edit the commit message and to retain the previous one.
Once the initialisation is complete, you should never need to do anything else as caretaker will run automatically and keep your changelog up-to-date. You can re-run the init command at anytime if you wish to change the configuration that you are using.
If you do not want to run caretaker automatically, maybe you are just evaluating it and are not yet ready to fully automate the process, then you can run caretaker manually from the command line.
Advanced usage
Amongst other things Caretaker has a category mode (-e or --enable-categories) which allows for the grouping of changes by category. This is done by using special tags as a prefix to your commit messaged. It will parse these prefixes and group like commits together, within a specific release.
git commit -m "<category>: <message>"
Category example
git commit -m "docs: Updated the README.md to include an example."
Category list
The categories are used for splitting the changelog into logical sections. In the following table the category is what is displayed in the CHANGELOG.md (as the section header), and the patterns are the strings that it will match on when parsing the commit messages.
The matching is case-insensitive.
| Category | Patterns | Purpose |
|---|---|---|
| New Features | new features, new feature, new, feature | Any new features that have been added |
| Improvements | improvements, improvement | Any improvement or enhancement of an existing feature |
| Bug Fixes | bug fixes, bug fix, bug, bugs | Any bug fixes to existing features |
| Security Fixes | security fixes, security | Any security fixes to existing features |
| Refactor | refactor | A code change that neither fixes a bug or adds a feature |
| Style | style | A change that does not affect the meaning of the code (white-space, formatting, missing semi-colons, etc) |
| Deprecated | deprecated | Any existing feature that is being deprecated |
| Removed | removed | Any existing feature that is being removed |
| Tests | tests, test, testing | Any changes to the existing tests |
| Documentation | documentation, docs | Changes to documentation only |
| Chores | chores, chore | Changes to the build process or auxiliary tools and libraries such as documentation generation |
| Experiments | experiments, experiment | Any experiments that you are carrying out, these are things that might get added and then removed again |
| Miscellaneous | miscellaneous, misc | Anything else (this shouldn't really be required) |
| Initial Commit | initial commit, initial | A special tag for the initial commit to the repo |
| Skip | skip, ignore | A special tag to ignore adding the commit to the CHANGELOG |
Any commit without a matching category will be added to an 'Uncategorised' group.
Example category output
# Changelog
All notable changes to this project will be documented in this file.
### [Unreleased](https://github.com/WolfSoftware/caretaker/compare/v1.0.0...HEAD)
###### Documentation:
- Updated the README.md to include an example.
###### Uncategorised:
- Created an example without a prefix.
Tagging release versions
Due to the way that post-commit hooks work, if you were tag a release that tag would either be ignored or worse lost, because the commit ID changes when a 'commit amend' is carried out. In order to get around this problem Caretaker can now tag releases for you as part of its push process.
The current version is stored in 'VERSION.txt', and it is semantic version string (however it can include an optional v prefix eg v1.0.0). This version is used to 'tag' a release as part of the process. It works be comparing the current tag to the one in the file and if they are different it will tag the release with the new version.
Release handler snippet
The following code is a snippet of how the release mechanism works:
if [[ -n $RELEASE_VERSION ]]; then
git tag "${TAG_VERSION}"
fi
#{cmd}
res=$(git status --porcelain | grep "${OUTPUT_FILE}" | wc -l)
if [[ "${res}" -gt 0 ]]; then
git add "${OUTPUT_FILE}" >> /dev/null 2>&1
git commit --amend --no-edit >> /dev/null 2>&1
if [[ -n "${RELEASE_VERSION"} ]]; then
git tag -f "${TAG_VERSION}"
fi
fi
As you can see, it will tag the release, run caretaker and re-tag the release after the commit amend, ensuring that the tag persists. This is not a perfect solution, but it does work :)
The created tag is NOT pushed to the remote end, this is to allow manual pushing once the release is correct.
Bumping release versions
In order to make life as simple as possible the new version of Caretaker comes with a --bump option, this takes 1 argument of either major, minor or patch and will update the version file accordingly.
Note if the version file doesn't exist, it will be created with a default version of v0.1.0
Caretaker config file
Caretaker allows you to generate a config file (-c or --config-file) which it will read automatically, so that you do not need to provide command line flags each time you run Caretaker, this file is also read when you run Caretaker via the post-commit hook.
It will look in the base of the current git repository for the config file, if it is not found it will then check your home directory, if still not found it will check the current directory and every parent directory until it either finds a config file or runs out of directories to check. Placing the config file, for example, in your home directory will have the effect of making it global for ALL your git repositories.
The config file is called
.caretaker.yml.
You can run Caretaker with command line options and if you add the -c option it will generate the config (in the base of your git repository) with the settings you specificy.
Example config file
enable-categories: false
min-words: 1
remove-categories: false
silent: false
verify-urls: false
Github usernames
Caretaker is also able to parse commit messages for special tags which specify a GitHub username and converts those tags into a link to the user. This link appended to the commit messages.
Github username example
git commit -m "docs: This is a GitHub username example. {TGWolf}"
In addition you can set a username using the -a option:
Github username command line example
git commit -m "docs: This is a GitHub username example." -a TGWolf
You can also use the -a option along with the -i (init) option to set the username as your default for all commits.
If there is already a author tag within the commit then the -a option is ignored for that commit, it is only appended to commits with no author. This stops double entries if you enable -a after you have already tagged commits with an author.
Result
- This is a GitHub username example. [`[Author: TGWolf]`](https://github.com/TGWolf)
Pull requests and commits
Caretaker is also able to identify the difference between pull requests and commits and automatically creates a link to either the pull request number or the commit it.
Pull request linking example
- This is a normal commit. [`[17df108]`](https://github.com/WolfSoftware/caretaker/commit/17df1080a501ed1bb780aa946190d64966dc30df)
- This is a pull request. [`[#7]`](https://github.com/WolfSoftware/caretaker/pull/7)
Issues
It is also possible to specify a tag within the commit to tell caretaker that the commit relates to an issue and caretaker will create a link to that issues.
Issues link example
git commit -m "Bug: This fixes a bug in the code and resolves issue (issue-7).
Issues link result
##### Bug Fixes:
This fixes a bug in the code and resolves issue [`[#7]`](https://github.com/WolfSoftware/caretaker/issues/7)
Using caretaker in your own code
Installation
Add this line to your application's Gemfile:
gem 'caretaker'
And then execute:
$ bundle install
Or install it yourself as:
$ gem install caretaker
Usage
Load the gem
require 'caretaker'
Initialise
caretaker = Caretaker.new(output: 'HISTORY.md')
output is
optionaland will default toCHANGELOG.md
Generate a changelog
Caretaker.generate_changelog
Initialise the git repo
Caretaker.init_repo
Contributing to caretaker
Setup
After checking out the repo, run bin/setup to install dependencies. Then, run rake spec to run the tests. You can also run bin/console for an interactive prompt that will allow you to experiment.
To install this gem onto your local machine, run bundle exec rake install. To release a new version, update the version number in version.rb, and then run bundle exec rake release, which will
create a git tag for the version, push git commits and tags, and push the .gem file to rubygems.org.
Testing
For local testing make sure that you run bundle exec rspec spec and then rake install to install the gem locally.
For further information please refer to the contributing documentation.
To-Do List
- [ ] CLI option to enable/disable linking to commit hashes
- [ ] CLI option to enable/disable linking to pull requests
- [ ] CLI option to enable/disable linking to github users
- [ ] Option to allow auto-pushing of the tag to the remote origin