diff --git a/README.md b/README.md index 5d5aab6..4bbd969 100644 --- a/README.md +++ b/README.md @@ -1,16 +1,16 @@ # ahab -A wrapper around `docker compose` for our dockerized django projects, so the +A wrapper around `docker compose` for our dockerized Django projects, so the same commands work in every repository. -## installing +## Installing -You will need rust installed. Clone repo and run: +You will need Rust installed. Clone repo and run: ```bash cargo install --path . ``` -## what it makes of a project +## What it makes of a project `ahab status` prints the services it picked, the containers behind them, the credentials it would use and what the store holds, reporting whatever it cannot @@ -30,11 +30,11 @@ store: /home/you/.local/share/ahab/git.aflabs.org/urnik/afurnik `ahab link check` lists what a sandbox can still read ``` -## seeing what it runs +## Seeing what it runs -`-v` prints each docker command as it runs, `--dry-run` prints the ones it would +`-v` prints each Docker command as it runs, `--dry-run` prints the ones it would run without running them, and `-q` prints only what was asked for, dropping the -progress along the way (compose's own progress included). All work before or +progress along the way (Compose's own progress included). All work before or after the subcommand. ```bash @@ -46,18 +46,18 @@ ahab -q postgres dump ./dump Nothing is written under `--dry-run`, filesystem included: `link add` and `django make-command` say what they would do and leave the tree alone. -## exit codes +## Exit codes -- `0` — it ran and had nothing to report -- `1` — it could not finish -- `2` — the arguments were wrong -- `4` — it ran fine and found something worth reporting, i.e. +- `0` — It ran and had nothing to report +- `1` — It could not finish +- `2` — The arguments were wrong +- `4` — It ran fine and found something worth reporting, i.e. `link check --exit-code` with anything outside the store -## shell completion +## Shell completion -`ahab completions ` writes a completion script to stdout, for bash, -elvish, fish, powershell or zsh: +`ahab completions ` writes a completion script to stdout, for Bash, +Elvish, Fish, PowerShell or Zsh: ```bash ahab completions zsh > ~/.local/share/zsh/completions/_ahab @@ -76,25 +76,25 @@ SHELL_COMPLETIONS_DIR_FISH=~/.config/fish/completions \ `SHELL_COMPLETIONS_DIR` writes every shell into one directory instead. -## the compose file +## The compose file -`ahab` does not pass `-f`. docker compose finds the file itself, so set -docker's own `COMPOSE_FILE` when it is not in the working directory, including +`ahab` does not pass `-f`. Docker Compose finds the file itself, so set +Docker's own `COMPOSE_FILE` when it is not in the working directory, including its `base.yaml:override.yaml` form. A project's `.env` is a good place for it, -since docker reads that too: +since Docker reads that too: ``` COMPOSE_FILE=docker/docker-compose.yaml ``` -## service detection +## Service detection `ahab` finds the services it needs in `docker compose config`, so they can be named anything: -- **postgres**: the service whose image is a postgres flavour, matching +- **postgres**: The service whose image is a Postgres flavour, matching `postg`, `timescale`, `pgvector` or `citus` -- **django**: the service that both builds an image and sets +- **django**: The service that both builds an image and sets `DJANGO_SETTINGS_MODULE`. Where more than one does — a worker beside the web service, say — the one publishing ports wins @@ -103,15 +103,15 @@ lists the services it looked at rather than guessing. Two services that both build and set the settings module are ambiguous unless exactly one of them publishes ports. -`POSTGRES_USER` and `POSTGRES_DB` are read off the detected postgres service, so +`POSTGRES_USER` and `POSTGRES_DB` are read off the detected Postgres service, so `dropdb`, `createdb`, `pg_restore` and `pg_dump` use the role and database the project declares, falling back to `db` when it declares neither. Both have to be names: `ahab` hands them to those tools as a role and a database, and libpq -reads a database name holding an `=` or a url as a whole connection string, +reads a database name holding an `=` or a URL as a whole connection string, which would send a dump to whatever server it names. A value that could be read as something other than a name is refused rather than passed on. -## django +## Django ```bash ahab django run # in a fresh container, through the entrypoint @@ -131,11 +131,11 @@ written for pytest, so a wrong guess reads as a pass. Name the runner instead: ahab django run pytest -x tests/ ``` -## postgres +## Postgres ```bash ahab postgres dump # pg_dump, custom format -ahab postgres dump -F plain # pg_dump, plain sql +ahab postgres dump -F plain # pg_dump, plain SQL ahab postgres dump -F tar # pg_dump, tar ahab postgres dump -F directory # pg_dump, a directory of files ahab postgres dump -F cluster # pg_dumpall, roles and all databases @@ -148,7 +148,7 @@ A dump is written `0600` and under a name of its own until it is complete, then renamed over the target: a cluster dump carries every role's password hash, and the default `0644` would hand it to anyone else with an account on the machine. -`psql` passes its arguments through and only asks docker for a terminal when it +`psql` passes its arguments through and only asks Docker for a terminal when it has one to hand over, so both of these work: ```bash @@ -159,14 +159,14 @@ ahab postgres psql -tAc 'select count(*) from auth_user' | wc -l The format of a dump being imported is read from the file rather than its name. A custom format dump starts with `PGDMP` and a tar one with `toc.dat`, both of which go to `pg_restore`, as does a directory produced by `pg_dump -Fd`. -Anything else is treated as sql and fed to `psql` with `ON_ERROR_STOP` and +Anything else is treated as SQL and fed to `psql` with `ON_ERROR_STOP` and `--single-transaction`, so a bad file rolls back instead of half applying. A whole cluster dump from `pg_dumpall` is recognised by its header and handled differently again: it creates its own databases and carries role statements, so the database is dropped but not recreated, the dump goes to `psql` connected to `postgres`, and it runs without `ON_ERROR_STOP` because roles that already exist report errors that are expected. Any error it does not expect is reported and -fails the import, since psql without `ON_ERROR_STOP` exits 0 having applied +fails the import, since `psql` without `ON_ERROR_STOP` exits 0 having applied only part of the dump. Gzipped dumps are decompressed on the way in, whichever of the three they hold. A cluster that has never held the database yet is a valid target either way, so importing into a fresh one works. @@ -174,7 +174,7 @@ valid target either way, so importing into a fresh one works. `import` stops the project before it starts, so an import that fails leaves it stopped and says so: `docker compose up` brings it back. -## link +## Link `ahab link` moves untracked paths out of the repository into an out-of-repo store and symlinks them back, so a sandbox that mounts the repository sees a @@ -195,7 +195,7 @@ where it was, and the store keeps nothing. A second checkout linking the same path is left with a dangling symlink, since there is only ever one stored copy. `list` says what state each stored path is in, which `check` cannot see because -it asks git about the repository rather than reading the store: +it asks Git about the repository rather than reading the store: ``` $ ahab link list @@ -215,7 +215,7 @@ there is nothing to undo for a path whose symlink is gone. end with a NUL, and the two paths of a symlink leading elsewhere are separated by one as well, the way `git status -z` reports a rename. -`check` looks at tracked paths too, since git tracks symlinks and one can lead +`check` looks at tracked paths too, since Git tracks symlinks and one can lead out of the repository without appearing in any untracked listing. `add` cannot externalize a tracked path, so all `check` can do is report it, under the code `T>`. @@ -227,17 +227,17 @@ the store, called the repository clean. The store lives under `${XDG_DATA_HOME:-$HOME/.local/share}/ahab////`, derived -from the git `origin` remote, or `_local/` when there is no remote to +from the Git `origin` remote, or `_local/` when there is no remote to name it after. Its directories are created `0700`: it exists to hold what should not be readable from the repository, and on a shared machine the default `0755` would leave that to whoever else has an account. A store path derived from a remote, or a checkout name, that needed characters replacing carries a short fingerprint of the original, so two of them cannot land on one directory. -## configuration +## Configuration Currently `ahab` respects the following environment variables. -- `AHAB_LINK_ROOT`: where `ahab link` keeps its store - the same as `--store`, +- `AHAB_LINK_ROOT`: Where `ahab link` keeps its store — the same as `--store`, which takes precedence, and defaults to `${XDG_DATA_HOME:-$HOME/.local/share}/ahab`. `ahab status` reads it too, so it reports the store the link commands use