tix-tracker 0.12.0

A terminal issue tracker: markdown + YAML frontmatter issues with a kanban TUI and CLI
Documentation
# Packaging and release

This document describes how the tix issue tracker is packaged and published as
an official Rust crate, and how it is installed by users:

- **crates.io** — `cargo install tix-tracker` (builds from source).
- **cargo-binstall** — `cargo binstall tix-tracker` (prebuilt binaries).
- **Source** — `cargo install --path .` (development), and the linked GitLab
  repository: <https://gitlab.com/thyseus/tix>.

## Naming

The crate published on crates.io is **`tix-tracker`**, not `tix`:

- The crates.io name **`tix` is already taken** by an unrelated, active crate
  (a CLI alarm clock/timer). `cargo install tix` installs that other crate, so
  this project publishes under `tix-tracker` instead.
- The **installed binary is still `tix`** — only the crate name differs.

| What                  | Value                                                     |
| --------------------- | --------------------------------------------------------- |
| crates.io package     | `tix-tracker`                                             |
| Binary                | `tix`                                                     |
| Library               | `tix` (kept so existing `tix::` code paths are unchanged) |
| Repository / homepage | https://gitlab.com/thyseus/tix                            |
| Documentation         | https://docs.rs/tix-tracker                               |

The relevant `[package]` metadata lives in `Cargo.toml`:

```toml
[package]
name = "tix-tracker"
repository = "https://gitlab.com/thyseus/tix"
homepage   = "https://gitlab.com/thyseus/tix"
documentation = "https://docs.rs/tix-tracker"
keywords   = ["issues", "kanban", "tracker", "cli", "tui"]
categories = ["command-line-utilities"]
rust-version = "1.85"            # since the crate uses edition 2024

[[bin]]
name = "tix"
path = "src/main.rs"
```

`repository` is what links the crate to the GitLab repo on the crates.io page
and is also what `cargo-binstall` uses to locate release binaries.

---

## Prerequisites

- **Rust toolchain** (edition 2024 / MSRV 1.85+), i.e. `cargo`.
- **crates.io account + API token** (next section) for publishing.
- (Optional, for binary installs) `cargo-binstall` — see
  [Binary installation]#binary-installation.

## 1. crates.io account & authentication

1. Go to <https://crates.io> and click **Sign in**.
2. Create your account by logging in with your **GitHub** or **GitLab**
   identity. crates.io has no username/password signup — OAuth only.
3. After the first login crates.io asks for a **username** (this is the name
   shown as the crate owner) and an **email address**; confirm the email.
4. Generate an API token:
   - Go to <https://crates.io/settings/tokens> → **New token**.
   - Give it a name (e.g. `tix-cli`) and a **scope**:
     - `publish-new` + `publish-update`: for publishing. Enough for either a
       new crate or updates (this is what a maintainer token should use).
     - `publish-update`: only for updating an existing crate you own.
   - Copy the token now — crates.io shows it only once.
5. Log in locally with cargo (writes the token to
   `~/.cargo/credentials.toml`, mode 0600):

   ```bash
   cargo login
   # or non-interactively:
   cargo login <token>
   ```

   Verify with `cargo login --help` and check that `$CARGO_HOME/credentials.toml`
   exists and is owned by you (cargo refuses insecure permissions).

6. **CI automation** (GitLab CI / a release pipeline): store the token as a
   masked CI/CD variable, e.g. `CARGO_REGISTRY_TOKEN`, and publish with
   `cargo publish --token "$CARGO_REGISTRY_TOKEN"`. Never commit the token.

## 2. Pre-publish checks

Before the first (or any) publish, from the repo root:

```bash
cargo fmt --check
cargo clippy --all-targets --all-features -- -D warnings
cargo test
```

Then verify exactly what would land in the crate:

```bash
cargo package --list      # list every file that will be uploaded
cargo package             # build the .crate archive (verifies it compiles + checks metadata)
cargo publish --dry-run   # run the full publish pipeline without uploading
```

Notes:

- The `[package] exclude` list keeps governance artifacts (`.kittify/`,
  `kitty-specs/`, `kitty-ops/`, `.agents/`, `.worktrees/`, `openspec/`,
  `.specify/`, `specs/`) out of the crate.
  Review `cargo package --list` output to confirm the crate contains only
  source, `README.md`, and the `LICENSE-*` files.
- `cargo publish` verifies the spam/immutability checks locally; the first
  publish also performs a package-size sanity check.

## 3. Publish to crates.io

**First publish** (creates the `tix-tracker` namespace):

```bash
cargo publish
```

Owners can be added afterwards from the crates.io dashboard
(`tix-tracker` → Owner settings → invite).

**Subsequent releases** — bump the `version` in `Cargo.toml` (SemVer, see
[Release checklist](#release-checklist)), update `CHANGELOG.md`, then republish:

```bash
cargo publish
```

After a successful publish the crate and its README appear on
<https://crates.io/crates/tix-tracker> (allow a couple of minutes for the index
to update).

### docs.rs

docs.rs builds the `tix` library automatically on every publish (the crate's
`documentation` metadata points at it):
<https://docs.rs/tix-tracker>. If a docs build ever fails, trigger a rebuild
from the docs.rs dashboard — do **not** republish just to fix docs.

## 4. `cargo install tix-tracker` (users, from source)

Any user with a Rust toolchain installs the latest version:

```bash
cargo install tix-tracker
```

The `tix` binary lands in `~/.cargo/bin` (or `$CARGO_BIN_DIR`).

- Pin a version: `cargo install tix-tracker --version 0.1.0`
- Reproducible builds from the lockfile: `cargo install tix-tracker --locked`
- The crate ships a `tix` library **and** the `tix` binary; `cargo install`
  builds the binary and ignores the library's public API.

## 5. Binary installation: `cargo binstall tix-tracker`

`cargo-binstall` downloads prebuilt binaries instead of compiling, so installs
are seconds, not minutes, and don't require a Rust toolchain. It is a drop-in
replacement for `cargo install` for most cases.

### Users

```bash
cargo install cargo-binstall --locked   # one-time install of binstall
cargo binstall tix-tracker              # -> downloads the prebuilt binary
```

If no prebuilt binary exists for your platform/version, binstall falls back to
a source build via `cargo install` (it asks first).

### Maintainers: publishing prebuilt binaries

`cargo-binstall` reads the `[package.metadata.binstall]` section in
`Cargo.toml`:

```toml
[package.metadata.binstall]
pkg-url = "{ repo }/-/releases/v{ version }/downloads/{ name }-{ target }-v{ version }{ archive-suffix }"
bin-dir = "{ name }-{ target }-v{ version }/{ bin }{ binary-ext }"
pkg-fmt = "tgz"
```

It expands to, for example, version `0.1.0` on `x86_64 Linux`:

- URL: `https://gitlab.com/thyseus/tix/-/releases/v0.1.0/downloads/tix-tracker-x86_64-unknown-linux-gnu-v0.1.0.tgz`
- Path inside the archive: `tix-tracker-x86_64-unknown-linux-gnu-v0.1.0/tix`

So for every release you must attach one **`.tgz` archive per target**, named
exactly like the URL above, each containing a `tix` binary (plus optional
manpages, shell completions, etc.) unpacked into the `name-target-vversion/`
directory.

Manual build + upload example:

```bash
# for each target triple you support:
rustup target add x86_64-unknown-linux-gnu
cargo build --release --target x86_64-unknown-linux-gnu
mkdir -p "tix-tracker-x86_64-unknown-linux-gnu-v0.2.0"
cp target/x86_64-unknown-linux-gnu/release/tix "tix-tracker-x86_64-unknown-linux-gnu-v0.2.0/"
tar -czf tix-tracker-x86_64-unknown-linux-gnu-v0.2.0.tgz tix-tracker-x86_64-unknown-linux-gnu-v0.2.0

# attach to the GitLab release for tag v0.1.0 (needs `glab auth login`):
glab release create v0.1.0 \
   tix-tracker-x86_64-unknown-linux-gnu-v0.1.0.tgz \
   tix-tracker-aarch64-unknown-linux-gnu-v0.1.0.tgz \
   tix-tracker-x86_64-apple-darwin-v0.1.0.tgz \
   tix-tracker-aarch64-apple-darwin-v0.1.0.tgz
```

That manual flow is enough to make `cargo binstall tix-tracker` work. Prefer to
automate it (GitLab CI job that builds on a tag and creates the release), so
source and binaries ship together — see the
[Release checklist](#release-checklist).

#### GitLab release asset notes

- GitLab's **permanent download links**
  (`.../-/releases/<tag>/downloads/<file>`) are what binstall hits. For files
  uploaded directly as release attachments, the permanent link keeps the
  original filename, so the names must match the template above.
  - If you create the assets as GitLab _links_ instead (API only), set the
    link's `filepath` to the same name.
- gitlab.com has this permanently-linked-assets behavior out of the box.
- `binstall` also ships sensible _defaults_ for GitLab
  (`.../-/releases/{version}/downloads/binaries/...`); we pin an explicit
  `pkg-url`/`bin-dir` instead so the file naming is under our control.

#### Verifying the binary install

Before publishing a release, test the URL resolution locally against the
working tree:

```bash
cargo binstall tix-tracker --manifest-path Cargo.toml --verbose --dry-run
```

After publishing, verify end-to-end on a clean machine (or after removing your
local copy):

```bash
cargo binstall tix-tracker --verbose   # or just: cargo binstall tix-tracker
tix --version
```

## Release checklist

For each new version:

1. Bump `version` in `Cargo.toml` (SemVer; `breaking → major`,
   `feature → minor`, otherwise patch). Keep `Cargo.lock` in sync —
   `cargo metadata --no-deps` reflects the new version.
2. Add a `[x.y.z] — date` entry in `CHANGELOG.md` and move unreleased notes up.
3. Run `cargo fmt --check`, `cargo clippy -- -D warnings`, `cargo test`,
   `cargo package`.
4. `cargo publish` (steps 1–4 of this document).
5. Tag and release on GitLab with the same version:

   ```bash
   git tag -a v0.1.0 -m "tix-tracker 0.1.0"
   git push origin v0.1.0
   glab release create v0.1.0 <prebuilt-archives...>
   ```

   The tag must be `v<version>` — both the binstall `pkg-url` template and the
   GitLab default scheme expect it.

6. Attach the prebuilt archives (each target), then verify
   `cargo binstall tix-tracker` on at least one platform.
7. Confirm docs.rs built: <https://docs.rs/tix-tracker>.

## Yanking a broken release

If a published version is broken and cannot be fixed by a patch quickly, yank
it (removes it from new resolution; existing installs stay):

```bash
cargo yank tix-tracker --version 0.1.0
```

Always yank _after_ publishing a fixed version, so `cargo install tix-tracker`
resolves to the good one. To undo: `cargo yank --undo`.