The Python package [Cookiecutter](https://github.com/cookiecutter/cookiecutter) assists in creating directory structure for whatever purpose you need such as for example a new Python project, an Ansible role or a `docker-compose` project - anything really that benefits from a unifirm reproducible directory structure. If you've ever wanted to put project structure best practices into version control then Cookiecutter's here to help.
Cookiecutter is governed by so-called Cookiecutter templates, most of its magic inside Cookiecutter templates happens via the [Jinja2 template engine](https://palletsprojects.com/p/jinja/). You'll feel right at home if you're familiar with Ansible.
Each subdirectory in this repo is a Cookiecutter template, you'll recognize them from their telltale `cookiecutter.json` files. Directories usually also have a readme file explaining more about each individual template.
To change Cookiecutter templates get yourself an environment then make, test and commit your changes. First things first, the environment.
## Environment
Get yourself a Python virtual environment. In this example we're assuming you're running a Linux operating system and you'll be using [pyenv](https://github.com/pyenv/pyenv) to manage virtual environments.
### pyenv
- Install pyenv with what they are calling their automatic installer. Feel free to also read up on pyenv on their [GitHub project page](https://github.com/pyenv/pyenv).
```
curl https://pyenv.run | bash
```
- Following the installer's instruction add at least the following commands to your `~/.bashrc` file
- You will also likely want to add this line which will make sure pyenv auto-activates venvs when you navigate into certain directories. More on that down at [venv](#venv).
```
eval "$(pyenv virtualenv-init -)"
```
- Also make sure `~/.bashrc` gets loaded for example by including this in a `~/.bash_profile` file
```
[[ -f ~/.bashrc ]] && . ~/.bashrc
```
- Reload `~/.bashrc`
```
source ~/.bashrc
```
### Python
- Update pyenv's package list
```
pyenv update
```
- Pick a Python version you like, for example copy-paste `3.11.4`:
```
pyenv install --list | less
...
3.10.12
3.11.0
3.11-dev
3.11.1
3.11.2
3.11.3
3.11.4
3.12.0b2
3.12-dev
3.13-dev
...
```
- Install Python, wait for compilation to finish on your machine
- Create a virtual environment where `3.11.4` is the Python version you want to use in this venv and `cookiecutter-3.11.4` is the name of your venv. Adding or dropping the Python version from your venv name comes down to personal preference.
```
pyenv virtualenv 3.11.4 cookiecutter-3.11.4
```
- In your repo path `~/py-cookiecutter-templates` create a `.python-version` file to tell pyenv to always activate your desired venv when inside this dir.
```
cd ~/py-cookiecutter-templates
pyenv local cookiecutter-3.11.4
```
pyenv will immediately prefix your shell's `${PS1}` prompt with the venv name.
Make some code changes, for example to the Docker Compose Cookiecutter template. When you're happy run your local Cookiecutter template to see how your changes are rendering.
- Create `/tmp/cookiecutter-docker-compose`
```
mkdir '/tmp/cookiecutter-docker-compose'
```
- Render a Docker Compose directory into your output directory, answer Cookiecutter's prompts:
- Observe that in `/tmp/cookiecutter-docker-compose` you now have your rendered Docker Compose dir:
```
# tree /tmp/cookiecutter-docker-compose
/tmp/cookiecutter-docker-compose
└── mydir
├── build-context
│ ├── mycomponent_one
│ │ ├── docker-data
│ │ ├── Dockerfile
│ │ └── extras
│ └── mycomponent_two
│ ├── docker-data
│ ├── Dockerfile
│ └── extras
├── common-settings.yml
├── docker-compose.override.yml
├── docker-compose.yml
└── env
└── fqdn_context.env.example
```
- For rapid testing you will most likely want to not type prompt answers repeatedly. Give them as command line arguments instead, also specify `--no-input` to suppress prompts:
```
cookiecutter ~/py-cookiecutter-templates \
--no-input \
--directory docker-compose \
--output-dir /tmp/cookiecutter-docker-compose \
project_slug=mydir \
service=myservice \
component_list=mycomponent_one,mycomponent_two \
context=ux_novosibirsk
```
## Commit prep
When you're about ready to commit changes into this repo check the following bullet points.
- Did you update the [Cookiecutter template README.md file](docker-compose/README.md), here for example for Docker Compose?
- Change in behavior?
- An updated example directory layout?
- Updated example file content?
- Did you commit a new completely rendered example directory structure into [docker-compose/examples](docker-compose/examples) dir?
- Did you change something that affects existing example directories? If so rerender them.