Skip to main content

README.md

# hexorcist_update

The local client for [Hexorcist](https://hexorcist.net) — it fetches a project's
**upgrade plan** and applies the safe, lockfile-only part (`mix deps.update`),
optionally test-gated, leaving the `mix.lock` change as a reviewable diff.

Think Dependabot/Renovate, but driven by Hexorcist's analysis and run **on your
machine or CI** — no GitHub integration, no auto-push.

## Install

```sh
mix archive.install hex hexorcist_update
# or straight from this repo:
mix archive.install git https://git.sr.ht/~sbr/hexorcist
# or from a local checkout (build the .ez, then install it):
cd hexorcist && mix archive.build && mix archive.install ./hexorcist_update-*.ez
```

It installs as a global Mix archive (so `mix hexorcist.update` works in any
project), with **no runtime dependencies** (uses OTP `:httpc` + `:json`), so it
won't touch your project's dependency tree.

## Updating

Archives don't auto-update — reinstall to move to a newer version.

```sh
mix archive               # list installed archives (look for hexorcist_update-X.Y.Z)

# From Hex or git, pulling the latest published version:
mix archive.install hex hexorcist_update --force
mix archive.install git https://git.sr.ht/~sbr/hexorcist --force

# From a local checkout — rebuild the .ez from current source first:
cd hexorcist && git pull && mix archive.build
mix archive.install ./hexorcist_update-*.ez --force
```

`--force` overwrites the installed copy without prompting. Reinstalling the
**same** version replaces it in place; after a **version bump**, remove the old
one so it doesn't linger alongside the new:

```sh
mix archive.uninstall hexorcist_update-0.3.0
```

## Usage

Run it inside your project's git checkout. The token is a secret (keep it in your
environment); the project id can live in the repo:

```sh
# .hexorcist.exs — commit this so the project id travels with the repo
[project: "de4faba9-2d6c-4f9e-99fa-905b10a6f419"]
```

```sh
export HEXORCIST_TOKEN=hxo_...   # account token (Settings page); never commit this

mix hexorcist.update             # apply lockfile updates, leave a diff
mix hexorcist.update --test      # ...and roll back if `mix test` fails
mix hexorcist.update --edit-mix  # also raise mix.exs constraints for blocked majors
mix hexorcist.update --dry-run   # just print the plan; change nothing
mix hexorcist.update --commit    # commit the change (never pushes)
```

| Flag / env | Meaning |
|---|---|
| `--project` / `HEXORCIST_PROJECT` / `:project` in `.hexorcist.exs` | Project public id (required) |
| `--token` / `HEXORCIST_TOKEN` | Account token (required; **never** put in the file) |
| `--url` / `HEXORCIST_URL` / `:url` in `.hexorcist.exs` | Base URL (default `https://hexorcist.net`) |

Resolution order is **flag → env → `.hexorcist.exs`**. The config file is parsed
as a literal (never `eval`'d), so a cloned repo's config can't execute code.
| `--test` | Run `mix test`; roll back `mix.lock` on failure |
| `--commit` | `git commit` the change (never pushes) |
| `--dry-run` | Print the plan only |

## Scope

By default only **lockfile** updates are applied — versions that already fit your
`mix.exs` constraints. Updates blocked by a constraint are **reported**, and with
`--edit-mix` their literal `{:dep, "~> x.y"}` constraint is raised (à la
Renovate's `mix` manager) — in the root `mix.exs` or, for an umbrella, whichever
`apps/*/mix.exs` declare the dep. Anything not safely rewritable (non-`~>`,
ambiguous, or transitive deps) is reported as a suggestion rather than edited,
and an edit that doesn't actually unlock the dep is reverted.

## License

BSD-3-Clause