Home

Awesome

Battenberg

image image

Battenberg is a tool built atop of Cookiecutter to keep Cookiecut projects in sync with their parent templates. Under the hood, Battenberg relies on Git to manage the merging, diffing, and conflict resolution story. The first goal of Battenberg is to provide an upgrade feature to Cookiecutter.

Installation

We publish battenberg to PyPI for easy consumption.

pip install battenberg

If you're on Mac OS X or Windows please follow the installation guides in the pygit2 documentation as well as battenberg relies on libgit2 which needs to be installed first. Please install libgit2 >= 1.0.

If you use SSH to connect to git, please also install libssh2 prior to installing libgit2!! Most like you can do this via brew install libssh2 if you are on Mac OS X.

Prerequistes

It is assumed that your cookiecutter template contains a .cookiecutter.json file at the root directory, or you can override its location by passing in --context-file. Please use the jsonify Jinja2 extension to dump the cookiecutter template context to .cookiecutter.json.

Tip: One problem battenberg has that as divergence between the cookiecutter template and the project itself increase as will the volume of conflicts needed to be manually resolved for each upgrade merge. To minimize these it is often advisable to fit templates with a generate_example boolean flag which will disable including any example code, instead replacing implementation with a pass for example.

Usage

Install a Cookiecutter template:

battenberg [-O <root path>] [--verbose] install [--checkout v1.0.0] [--initial-branch main] <cookiecutter template path/URL>

Upgrade your repository with last version of a template:

battenberg upgrade [--checkout v1.0.0] [--no-input] [--merge-target <branch, tag or commit>] [--context-file <context filename>]

Onboarding existing cookiecutter projects

A great feature of battenberg is that it's relatively easy to onboard existing projects you've already cookiecut from an existing template. To do this you need to follow the battenberg install instructions above but use the -O output to specify the directory of the existing project and it'll create you a new template branch and attempt to merge just like an upgrade operation.

Once you've completed your first merge from template -> main you can then follow the battenberg upgrade instructions as though it was generated using battenberg initially.

High-level design

At a high level battenberg attempts to provide a continuous history between the upstream template project and the cookiecut project. It does this by maintaining a disjoint template branch which battenberg attempts to keep in sync with the upstream template, it therefore will contain no project-specific changes beyond replacing the template values. Then changes to the template are incorporated into the main and other branches via a git merge --allow-unrelated-histories command for each template update pulled in. This merge commit should be used to resolve any conflicts between the upstream template and the specialized project.

A new project in battenberg

This shows the repo structure immediately after running a battenberg install <template> command

An updated project in battenberg

This shows the repo structure immediately after running a battenberg upgrade command on the previously installed project

Development

To get set up run:

python3 -m venv env
source env/bin/activate

# Install in editable mode so you get the updates propagated.
pip install -e .

# If you want to be able to run tests & linting install via:
pip install -e ".[dev]"

Then to actually perform any operations just use the battenberg command which should now be on your $PATH.

To run tests:

pytest

To run linting:

flake8 --config flake8.cfg battenberg

Releasing a new version to PyPI

Reminder to update HISTORY.md with a summary of any updates, especially breaking changes.

We utilize GitHub Actions to deploy to PyPI. We've limited it to just publish on git tags. To release run:

# Change to the appropriate commit you want to base the release on.
vi battenberg/__init__.py  # Update the version string.
git tag <version>
git push origin <version>

Then watch the build for any errors, eventually it should appear on the battenberg PyPI project.

FAQ

Credits

Original code written by Raphael Medaer from an original idea of Abdó Roig-Maranges.

License

Free software: Apache Software License 2.0