PRs welcome!
- Consider starting a discussion to see if there's interest in what you want to do.
- Submit PRs from feature branches on forks.
- Ensure PRs pass all CI checks.
- Maintain or increase test coverage.
- Make
develop
the default branch. - Merge PRs into
develop
. Configure repository settings so that branches are deleted automatically after PRs are merged. - Only merge to
main
if fast-forwarding fromdevelop
. - Enable branch protection on
develop
andmain
. - Set up a release workflow. Here's an example release workflow, controlled by Git tags:
- Bump the version number in
pyproject.toml
withpoetry version
and commit the changes todevelop
. - Push to
develop
and verify all CI checks pass. - Fast-forward merge to
main
, push, and verify all CI checks pass. - Create an annotated and signed Git tag
- Follow SemVer guidelines when choosing a version number.
- List PRs and commits in the tag message:
git log --pretty=format:"- %s (%h)" "$(git describe --abbrev=0 --tags)"..HEAD
- Omit the leading
v
(use1.0.0
instead ofv1.0.0
) - Example:
git tag -a -s 1.0.0
- Push the tag. GitHub Actions will build and push the Python package and Docker images.
- Bump the version number in
- Why use Git? Git enables creation of multiple versions of a code repository called branches, with the ability to track and undo changes in detail.
- Install Git by downloading from the website, or with a package manager like Homebrew. Configure Git to connect to GitHub with SSH
- Then Fork this repo
- Create a branch in your fork.
- Commit your changes with a properly-formatted Git commit message.
- Create a pull request (PR) to incorporate your changes into the upstream project you forked.
-
Python code is formatted with Black. Configuration for Black is stored in pyproject.toml.
-
Python imports are organized automatically with isort.
- The isort package organizes imports in three sections:
- Standard library
- Dependencies
- Project
- Within each of those groups,
import
statements occur first, thenfrom
statements, in alphabetical order. - You can run isort from the command line with
poetry run isort .
. - Configuration for isort is stored in pyproject.toml.
- The isort package organizes imports in three sections:
-
Other web code (JSON, Markdown, YAML) is formatted with Prettier.
-
Code style is enforced with pre-commit, which runs Git hooks.
-
Configuration is stored in .pre-commit-config.yaml.
-
Pre-commit can run locally before each commit (hence "pre-commit"), or on different Git events like
pre-push
. -
Pre-commit is installed in the Poetry environment. To use:
# after running `poetry install` path/to/repo ❯ poetry shell # install hooks that run before each commit path/to/repo .venv ❯ pre-commit install # and/or install hooks that run before each push path/to/repo .venv ❯ pre-commit install --hook-type pre-push
-
Pre-commit is also useful as a CI tool. The GitHub Actions workflows run pre-commit hooks with GitHub Actions.
-
This project uses Poetry for dependency management.
- Automatic virtual environment management: Poetry automatically manages the
virtualenv
for the application. - Automatic dependency management: rather than having to run
pip freeze > requirements.txt
, Poetry automatically manages the dependency file (called pyproject.toml), and enables SemVer-level control over dependencies like npm. Poetry also manages a lockfile (called poetry.lock), which is similar to package-lock.json for npm. Poetry uses this lockfile to automatically track specific versions and hashes for every dependency. - Dependency resolution: Poetry will automatically resolve any dependency version conflicts. pip did not have dependency resolution until the end of 2020.
- Dependency separation: Poetry can maintain separate lists of dependencies for development and production in the pyproject.toml. Production installs can skip development dependencies to speed up Docker builds.
- Builds: Poetry has features for easily building the project into a Python package.
The recommended installation method is through the Poetry custom installer, which vendorizes dependencies into an isolated environment, and allows you to update Poetry with poetry self update
.
You can also install Poetry however you prefer to install your user Python packages (pipx install poetry
, pip install --user poetry
, etc). Use the standard update methods with these tools (pipx upgrade poetry
, pip install --user --upgrade poetry
, etc).
# Basic usage: https://python-poetry.org/docs/basic-usage/
poetry install # create virtual environment and install dependencies
poetry show --tree # list installed packages
poetry add PACKAGE@VERSION # add a package to production dependencies, like pip install
poetry add PACKAGE@VERSION --dev # add a package to development dependencies
poetry update # update dependencies (not available with standard tools)
poetry version # list or update version of this package
poetry shell # activate the virtual environment, like source venv/bin/activate
poetry run COMMAND # run a command within the virtual environment
poetry env info # manage environments: https://python-poetry.org/docs/managing-environments/
poetry config virtualenvs.in-project true # configure Poetry to install virtualenvs into .venv
poetry export -f requirements.txt > requirements.txt --dev # export dependencies
-
Docker is a technology for running lightweight virtual machines called containers.
- An image is the executable set of files read by Docker.
- A container is a running image.
- The Dockerfile tells Docker how to build the container.
-
- Ubuntu Linux: follow the instructions for Ubuntu Linux, making sure to follow the postinstallation steps to activate the Docker daemon.
- macOS and Windows: install Docker Desktop (available via Homebrew with
brew cask install docker
).
-
Expand this details element for more useful Docker commands.
# Log in with Docker Hub credentials to pull images docker login # List images docker images # List running containers: can also use `docker container ls` docker ps # View logs for the most recently started container docker logs -f $(docker ps -q -n 1) # View logs for all running containers docker logs -f $(docker ps -aq) # Inspect a container (web in this example) and return the IP Address docker inspect web | grep IPAddress # Stop a container docker stop # container hash # Stop all running containers docker stop $(docker ps -aq) # Remove a downloaded image docker image rm # image hash or name # Remove a container docker container rm # container hash # Prune images docker image prune # Prune stopped containers (completely wipes them and resets their state) docker container prune # Prune everything docker system prune # Open a shell in the most recently started container (like SSH) docker exec -it $(docker ps -q -n 1) /bin/bash # Or, connect as root: docker exec -u 0 -it $(docker ps -q -n 1) /bin/bash # Copy file to/from container: docker cp [container_name]:/path/to/file destination.file