battenberg


Namebattenberg JSON
Version 0.5.2 PyPI version JSON
download
home_pagehttps://github.com/zillow/battenberg
SummaryProviding updates to cookiecutter projects.
upload_time2024-11-14 20:11:40
maintainerNone
docs_urlNone
authorZillow
requires_python>=3.9
licenseApache Software License 2.0
keywords battenberg
VCS
bugtrack_url
requirements No requirements were recorded.
Travis-CI No Travis.
coveralls test coverage No coveralls.
            # Battenberg

[![image](https://img.shields.io/pypi/v/battenberg.svg)](https://pypi.python.org/pypi/battenberg)
[![image](https://img.shields.io/travis/zillow/battenberg.svg)](https://github.com/zillow/battenberg/actions)

Battenberg is a tool built atop of [Cookiecutter](https://github.com/audreyr/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](https://pypi.org/project/battenberg/) for easy consumption.

```bash
pip install battenberg
```

If you're on Mac OS X or Windows please follow the [installation guides](https://www.pygit2.org/install.html#) 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`](https://github.com/cookiecutter/cookiecutter/pull/791) 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`](https://docs.python.org/3/reference/simple_stmts.html#the-pass-statement) for example.

## Usage

Install a [Cookiecutter](https://github.com/audreyr/cookiecutter) template:

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

* `--checkout` - Specifies a target reference (branch, tag or commit) from the cookiecutter template repo, if not specified is it inferred from the default branch for the template repo.
* `-O` - Specifies an output folder path, defaults to the current directory.
* `--initial-branch` - The default branch for the newly created `git` repo, if not specified is it inferred from the default branch for the template repo.
* `--verbose` - Enables extra debug logging.

Upgrade your repository with last version of a template:

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

* `--checkout` - Specifies a target reference (branch, tag or commit) from the cookiecutter template repo, if not specified is it inferred from the default branch for the template repo.
* `--no-input` - Read in the template context from `--context-file` instead of asking the `cookiecutter` template questions again.
* `--merge-target` - Specify where to merge the eventual template updates.
* `--context-file` - Specifies where to read in the template context from, defaults to `.cookiecutter.json`.

    *Note: `--merge-target` is useful to set if you are a template owner but each cookiecut repo is owned independently. The value you pass*
    *to `--merge-target` should be the source branch for a PR that'd target `main` in the cookiecut repo so they can approve any changes.*

## 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](https://github.com/zillow/battenberg/raw/main/img/new.png)

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

![An updated project in battenberg](https://github.com/zillow/battenberg/raw/main/img/updated.png)

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

## Development

To get set up run:

```bash
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:

```bash
pytest
```

To run linting:

```bash
flake8 --config flake8.cfg battenberg
```

## Releasing a new version to PyPI

**Reminder to update [`HISTORY.md`](./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:

```bash
# 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](https://pypi.org/project/battenberg/) project.

## FAQ

* I got an error like `_pygit2.GitError: unsupported URL protocol`, how do I fix this?

    Likely you're using a `git` URL with `ssh` and have installed `pygit2` without access to the underlying `libssh2`
    library. To test this run:

    ```bash
    $ python -c "import pygit2; print(bool(pygit2.features & pygit2.GIT_FEATURE_SSH))"
    False
    ```

    To remedy this run:

    ```bash
    $ pip uninstall pygit2
    ...
    # Hopefully you have this, but this will install the compiler toolchain for OS X.
    $ xcode-select --install
    ...
    $ brew install libssh2
    ...
    $ brew install libgit2
    ...
    # The python wheels for Mac OS X for pygit2 are not built with SSH support by default so tell pip
    # to install pygit2 from source.
    $ pip install pygit2 --no-binary pygit2
    ...
    # Finally test out to ensure pygit2 picks up the SSH features.
    $ python -c "import pygit2; print(bool(pygit2.features & pygit2.GIT_FEATURE_SSH))"
    True
    ```

* Why are you using a new `.cookiecutter.json` pattern instead of using the [`replay` pattern](https://cookiecutter.readthedocs.io/en/latest/advanced/replay.html)?

    Frankly the implementation was quite convoluted to get the intentions of these features to align. With the `.cookiecutter.json` approach
    we're intended for template state to live at the project level instead of at the user level which the `replay` functionality defaults to.
    Overriding that behaviour, whilst possible was convoluted in the current `cookiecutter` API and would require upstream changes so instead
    we decided against trying to align these features.

* Why `battenberg`?

    A tribute to the shoulders this project stands on, [`cookiecutter`](https://github.com/cookiecutter/cookiecutter) &
    [`milhoja`](https://github.com/rmedaer/milhoja), and [a tasty cake](https://en.wikipedia.org/wiki/Battenberg_cake) in its own right.

## Credits

[Original code](https://github.com/rmedaer/battenberg) written by [Raphael Medaer](https://github.com/rmedaer) from an [original
idea](https://github.com/cookiecutter/cookiecutter/issues/784) of [Abdó Roig-Maranges](https://github.com/aroig).

## License

Free software: Apache Software License 2.0


# Release History

## 0.5.2 (2024-11-12)

- Update to pygit2 usage to enable usage of newer versions of the package while also maintaining backwards compatibility.

## 0.5.1 (2023-08-08)

- Update python version to 3.9+

## 0.5.0 (2023-03-31)

- Update python version to 3.7+

## 0.4.1 (2021-01-25)

- Suppress stacktrace logging when hook exits unsuccessfully (See [#23](https://github.com/zillow/battenberg/pull/23))
- Ensure we're compatible with updated `Repository.__init__` constructor (See [#23](https://github.com/zillow/battenberg/pull/23))

## 0.4.0 (2020-10-13)

- Remove `master` as the default `git` target branch terminology to promote equity and belonging. Instead rely on remote HEAD to infer default branch naming convention.
- Add in `--initial-branch` optional argument to `battenberg install` to specify the initial branch to create when initializing a new project.

## 0.3.0 (2020-05-29)

- Update `pygit2` dependency to `>= 1.0`, can now rely on `libgit2 >= 1.0` too. (See [#18](https://github.com/zillow/battenberg/pull/18))
- Add in better debug logging (See [#16](https://github.com/zillow/battenberg/pull/16))

## 0.2.3 (2020-05-19)

- Refactor removal of top-level directory after cookiecutting to avoid collisions. (See [#15](https://github.com/zillow/battenberg/pull/15))
- Set upper limit on pygit2 dependency (See [#14](https://github.com/zillow/battenberg/pull/14))

## 0.2.2 (2020-01-29)

- Fix regression that stopped injecting context when upgrading.

## 0.2.1 (2020-01-29)

- Cleans up error message when merging results in conflicts. (See [#13](https://github.com/zillow/battenberg/pull/13))

## 0.2.0 (2019-10-29)

- Adds in remote fetching of `origin/template` branch during upgrades. (See [#12](https://github.com/zillow/battenberg/pull/12))

## 0.1.1 (2019-10-17)

- Revert back to relying on mainline `cookiecutter` instead of Zillow fork. (See [#9](https://github.com/zillow/battenberg/pull/9))

## 0.1.0 (2019-10-10)

- Add in support for reading template context from `.cookiecutter.json`. (See [#2](https://github.com/zillow/battenberg/pull/2))
- Add in `--merge-target` CLI option. (See [#4](https://github.com/zillow/battenberg/pull/4))
- Expanded test coverage, added in CI/CD via Travis CI. (See [#8](https://github.com/zillow/battenberg/pull/8))

Prior to v0.1.0 `battenberg` was developed under the [`milhoja`](https://github.com/rmedaer/milhoja) project.

            

Raw data

            {
    "_id": null,
    "home_page": "https://github.com/zillow/battenberg",
    "name": "battenberg",
    "maintainer": null,
    "docs_url": null,
    "requires_python": ">=3.9",
    "maintainer_email": null,
    "keywords": "battenberg",
    "author": "Zillow",
    "author_email": null,
    "download_url": "https://files.pythonhosted.org/packages/7d/0e/8628595b3470dcb7c4c7470de865330b7f11866a493c1a87072c10e93de8/battenberg-0.5.2.tar.gz",
    "platform": null,
    "description": "# Battenberg\n\n[![image](https://img.shields.io/pypi/v/battenberg.svg)](https://pypi.python.org/pypi/battenberg)\n[![image](https://img.shields.io/travis/zillow/battenberg.svg)](https://github.com/zillow/battenberg/actions)\n\nBattenberg is a tool built atop of [Cookiecutter](https://github.com/audreyr/cookiecutter) to keep Cookiecut projects\nin sync with their parent templates. Under the hood, Battenberg relies on Git to manage the merging, diffing, and\nconflict resolution story. The first goal of Battenberg is to provide an *upgrade* feature to Cookiecutter.\n\n## Installation\n\nWe publish `battenberg` to [PyPI](https://pypi.org/project/battenberg/) for easy consumption.\n\n```bash\npip install battenberg\n```\n\nIf you're on Mac OS X or Windows please follow the [installation guides](https://www.pygit2.org/install.html#) in the `pygit2` documentation\nas well as `battenberg` relies on `libgit2` which needs to be installed first. **Please install `libgit2 >= 1.0`.**\n\nIf 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`\nif you are on Mac OS X.\n\n## Prerequistes\n\nIt is assumed that your cookiecutter template contains a `.cookiecutter.json` file at the root directory, or you can override its location by\npassing in `--context-file`. Please use the [`jsonify`](https://github.com/cookiecutter/cookiecutter/pull/791) Jinja2 extension to dump the\n`cookiecutter` template context to `.cookiecutter.json`.\n\n**Tip:** One problem `battenberg` has that as divergence between the cookiecutter template and the project itself increase as will the volume of\nconflicts needed to be manually resolved for each upgrade merge. To minimize these it is often advisable to fit templates with a\n`generate_example` boolean flag which will disable including any example code, instead replacing implementation with a\n[`pass`](https://docs.python.org/3/reference/simple_stmts.html#the-pass-statement) for example.\n\n## Usage\n\nInstall a [Cookiecutter](https://github.com/audreyr/cookiecutter) template:\n\n```bash\nbattenberg [-O <root path>] [--verbose] install [--checkout v1.0.0] [--initial-branch main] <cookiecutter template path/URL>\n```\n\n* `--checkout` - Specifies a target reference (branch, tag or commit) from the cookiecutter template repo, if not specified is it inferred from the default branch for the template repo.\n* `-O` - Specifies an output folder path, defaults to the current directory.\n* `--initial-branch` - The default branch for the newly created `git` repo, if not specified is it inferred from the default branch for the template repo.\n* `--verbose` - Enables extra debug logging.\n\nUpgrade your repository with last version of a template:\n\n```bash\nbattenberg upgrade [--checkout v1.0.0] [--no-input] [--merge-target <branch, tag or commit>] [--context-file <context filename>]\n```\n\n* `--checkout` - Specifies a target reference (branch, tag or commit) from the cookiecutter template repo, if not specified is it inferred from the default branch for the template repo.\n* `--no-input` - Read in the template context from `--context-file` instead of asking the `cookiecutter` template questions again.\n* `--merge-target` - Specify where to merge the eventual template updates.\n* `--context-file` - Specifies where to read in the template context from, defaults to `.cookiecutter.json`.\n\n    *Note: `--merge-target` is useful to set if you are a template owner but each cookiecut repo is owned independently. The value you pass*\n    *to `--merge-target` should be the source branch for a PR that'd target `main` in the cookiecut repo so they can approve any changes.*\n\n## Onboarding existing cookiecutter projects\n\nA great feature of `battenberg` is that it's relatively easy to onboard existing projects you've already cookiecut from an existing template.\nTo do this you need to follow the `battenberg install` instructions above but use the `-O` output to specify the directory of the existing\nproject and it'll create you a new `template` branch and attempt to merge just like an upgrade operation.\n\nOnce you've completed your first merge from `template` -> `main` you can then follow the `battenberg upgrade` instructions as though it was\ngenerated using `battenberg` initially.\n\n## High-level design\n\nAt 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`\nbranch 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\nto 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\nshould be used to resolve any conflicts between the upstream template and the specialized project.\n\n![A new project in battenberg](https://github.com/zillow/battenberg/raw/main/img/new.png)\n\n*This shows the repo structure immediately after running a `battenberg install <template>` command*\n\n![An updated project in battenberg](https://github.com/zillow/battenberg/raw/main/img/updated.png)\n\n*This shows the repo structure immediately after running a `battenberg upgrade` command on the previously installed project*\n\n## Development\n\nTo get set up run:\n\n```bash\npython3 -m venv env\nsource env/bin/activate\n\n# Install in editable mode so you get the updates propagated.\npip install -e .\n\n# If you want to be able to run tests & linting install via:\npip install -e \".[dev]\"\n```\n\nThen to actually perform any operations just use the `battenberg` command which should now be on your `$PATH`.\n\nTo run tests:\n\n```bash\npytest\n```\n\nTo run linting:\n\n```bash\nflake8 --config flake8.cfg battenberg\n```\n\n## Releasing a new version to PyPI\n\n**Reminder to update [`HISTORY.md`](./HISTORY.md) with a summary of any updates, especially breaking changes.**\n\nWe utilize GitHub Actions to deploy to PyPI. We've limited it to just publish on `git tags`. To release run:\n\n```bash\n# Change to the appropriate commit you want to base the release on.\nvi battenberg/__init__.py  # Update the version string.\ngit tag <version>\ngit push origin <version>\n```\n\nThen watch the build for any errors, eventually it should appear on the [`battenberg` PyPI](https://pypi.org/project/battenberg/) project.\n\n## FAQ\n\n* I got an error like `_pygit2.GitError: unsupported URL protocol`, how do I fix this?\n\n    Likely you're using a `git` URL with `ssh` and have installed `pygit2` without access to the underlying `libssh2`\n    library. To test this run:\n\n    ```bash\n    $ python -c \"import pygit2; print(bool(pygit2.features & pygit2.GIT_FEATURE_SSH))\"\n    False\n    ```\n\n    To remedy this run:\n\n    ```bash\n    $ pip uninstall pygit2\n    ...\n    # Hopefully you have this, but this will install the compiler toolchain for OS X.\n    $ xcode-select --install\n    ...\n    $ brew install libssh2\n    ...\n    $ brew install libgit2\n    ...\n    # The python wheels for Mac OS X for pygit2 are not built with SSH support by default so tell pip\n    # to install pygit2 from source.\n    $ pip install pygit2 --no-binary pygit2\n    ...\n    # Finally test out to ensure pygit2 picks up the SSH features.\n    $ python -c \"import pygit2; print(bool(pygit2.features & pygit2.GIT_FEATURE_SSH))\"\n    True\n    ```\n\n* Why are you using a new `.cookiecutter.json` pattern instead of using the [`replay` pattern](https://cookiecutter.readthedocs.io/en/latest/advanced/replay.html)?\n\n    Frankly the implementation was quite convoluted to get the intentions of these features to align. With the `.cookiecutter.json` approach\n    we're intended for template state to live at the project level instead of at the user level which the `replay` functionality defaults to.\n    Overriding that behaviour, whilst possible was convoluted in the current `cookiecutter` API and would require upstream changes so instead\n    we decided against trying to align these features.\n\n* Why `battenberg`?\n\n    A tribute to the shoulders this project stands on, [`cookiecutter`](https://github.com/cookiecutter/cookiecutter) &\n    [`milhoja`](https://github.com/rmedaer/milhoja), and [a tasty cake](https://en.wikipedia.org/wiki/Battenberg_cake) in its own right.\n\n## Credits\n\n[Original code](https://github.com/rmedaer/battenberg) written by [Raphael Medaer](https://github.com/rmedaer) from an [original\nidea](https://github.com/cookiecutter/cookiecutter/issues/784) of [Abd\u00f3 Roig-Maranges](https://github.com/aroig).\n\n## License\n\nFree software: Apache Software License 2.0\n\n\n# Release History\n\n## 0.5.2 (2024-11-12)\n\n- Update to pygit2 usage to enable usage of newer versions of the package while also maintaining backwards compatibility.\n\n## 0.5.1 (2023-08-08)\n\n- Update python version to 3.9+\n\n## 0.5.0 (2023-03-31)\n\n- Update python version to 3.7+\n\n## 0.4.1 (2021-01-25)\n\n- Suppress stacktrace logging when hook exits unsuccessfully (See [#23](https://github.com/zillow/battenberg/pull/23))\n- Ensure we're compatible with updated `Repository.__init__` constructor (See [#23](https://github.com/zillow/battenberg/pull/23))\n\n## 0.4.0 (2020-10-13)\n\n- Remove `master` as the default `git` target branch terminology to promote equity and belonging. Instead rely on remote HEAD to infer default branch naming convention.\n- Add in `--initial-branch` optional argument to `battenberg install` to specify the initial branch to create when initializing a new project.\n\n## 0.3.0 (2020-05-29)\n\n- Update `pygit2` dependency to `>= 1.0`, can now rely on `libgit2 >= 1.0` too. (See [#18](https://github.com/zillow/battenberg/pull/18))\n- Add in better debug logging (See [#16](https://github.com/zillow/battenberg/pull/16))\n\n## 0.2.3 (2020-05-19)\n\n- Refactor removal of top-level directory after cookiecutting to avoid collisions. (See [#15](https://github.com/zillow/battenberg/pull/15))\n- Set upper limit on pygit2 dependency (See [#14](https://github.com/zillow/battenberg/pull/14))\n\n## 0.2.2 (2020-01-29)\n\n- Fix regression that stopped injecting context when upgrading.\n\n## 0.2.1 (2020-01-29)\n\n- Cleans up error message when merging results in conflicts. (See [#13](https://github.com/zillow/battenberg/pull/13))\n\n## 0.2.0 (2019-10-29)\n\n- Adds in remote fetching of `origin/template` branch during upgrades. (See [#12](https://github.com/zillow/battenberg/pull/12))\n\n## 0.1.1 (2019-10-17)\n\n- Revert back to relying on mainline `cookiecutter` instead of Zillow fork. (See [#9](https://github.com/zillow/battenberg/pull/9))\n\n## 0.1.0 (2019-10-10)\n\n- Add in support for reading template context from `.cookiecutter.json`. (See [#2](https://github.com/zillow/battenberg/pull/2))\n- Add in `--merge-target` CLI option. (See [#4](https://github.com/zillow/battenberg/pull/4))\n- Expanded test coverage, added in CI/CD via Travis CI. (See [#8](https://github.com/zillow/battenberg/pull/8))\n\nPrior to v0.1.0 `battenberg` was developed under the [`milhoja`](https://github.com/rmedaer/milhoja) project.\n",
    "bugtrack_url": null,
    "license": "Apache Software License 2.0",
    "summary": "Providing updates to cookiecutter projects.",
    "version": "0.5.2",
    "project_urls": {
        "Changelog": "https://github.com/zillow/battenberg/HISTORY.md",
        "Code": "https://github.com/zillow/battenberg",
        "Documentation": "https://github.com/zillow/battenberg/README.md",
        "Homepage": "https://github.com/zillow/battenberg",
        "Issue tracker": "https://github.com/zillow/battenberg/issues"
    },
    "split_keywords": [
        "battenberg"
    ],
    "urls": [
        {
            "comment_text": "",
            "digests": {
                "blake2b_256": "7d0e8628595b3470dcb7c4c7470de865330b7f11866a493c1a87072c10e93de8",
                "md5": "0471193e404c04db6eb9b19a580eb015",
                "sha256": "20a22213481f4b4ca256d17bf9bc6bfc8baa35aa560fc63a6c29c12f1050652c"
            },
            "downloads": -1,
            "filename": "battenberg-0.5.2.tar.gz",
            "has_sig": false,
            "md5_digest": "0471193e404c04db6eb9b19a580eb015",
            "packagetype": "sdist",
            "python_version": "source",
            "requires_python": ">=3.9",
            "size": 31523,
            "upload_time": "2024-11-14T20:11:40",
            "upload_time_iso_8601": "2024-11-14T20:11:40.446466Z",
            "url": "https://files.pythonhosted.org/packages/7d/0e/8628595b3470dcb7c4c7470de865330b7f11866a493c1a87072c10e93de8/battenberg-0.5.2.tar.gz",
            "yanked": false,
            "yanked_reason": null
        }
    ],
    "upload_time": "2024-11-14 20:11:40",
    "github": true,
    "gitlab": false,
    "bitbucket": false,
    "codeberg": false,
    "github_user": "zillow",
    "github_project": "battenberg",
    "travis_ci": false,
    "coveralls": false,
    "github_actions": true,
    "lcname": "battenberg"
}
        
Elapsed time: 0.45780s