I’ve got a good working version of my starter python library template. This is both a cookiecutter template and a self-bootstrapping GitHub template.

In substance this is a differently opinionated version of simonw’s python library template and approach to GitHub templating. There are more details on exactly the default features included on the repo page itself.

More fiddly is some small changes in how the templating process works, most of which are overkill for this library, but solve some problems I’ve run into with more complicated templates.

This repo combines the double repo approach (a cookiecutter repo and a GitHub template repo that clones the cookiecutter repo) into one repo that can do both.

I’m using pytest and a GitHub Action to do automated tests on the health of the template itself. When the template is updated, a GitHub Action tries to clone the template, and then run the internal test suite of the instance of the template.

Having the two repos in the same place also gives new workarounds to the problem of copying across GitHub Actions into the new instance. GitHub Actions does not let an action create a new or change an existing action, just delete them. This means that a new instance where the template contains GitHub Actions can’t automatically be committed to GitHub by a repo. One way of solving this is doubling up: both the cookiecutter and the GitHub Actions repo contain the GitHub Actions for the new template. This means that when the cookiecutter is run, it does not modify or add any actions because they are already in place. This approach lets you have just one set of files. I store the actions outside the cookiecutter folder (so they are already in place when GitHub uses the template). To keep this working with cookiecutter, a cookiecutter hook copies them into the new instance from the template directory.

The GitHub bootstrapping method works through an action that only unfolds the template when the current repo name does not match the repo that is the source of the template. So when the repo is created through a template, it’s a new push event, that triggers a GitHub Action, that then can see it is no longer in its home repo, and triggers the bootstrap. I’ve generalised this a bit - rather than exactly matching the origin, the bootstrap process will run in any repo that doesn’t end with `-auto-template`. This makes it a bit easier to fork, and create new variations on without needing to make changes to all the template_level actions every time.

Header image: Dall-e prompt (A robot looking confused working with scissors and paste)