mr-milchick 2.0.4

CLI for merge request governance in GitLab CI pipelines
Documentation
# Fixture Testing

Fixture mode lets you run `observe`, `explain`, and `refine` without a live GitLab merge request.

Instead of loading CI context and a remote snapshot, Mr Milchick reads a local TOML fixture and runs the same downstream rendering and notification logic against that synthetic review state.

## What Fixture Mode Is For

Use `--fixture` when you want to:

- iterate on Slack notifications
- test message templates locally
- preview a summary comment without GitLab access
- reproduce a scenario for demos or debugging

## Safety Model

- `observe --fixture` never sends anything
- `explain --fixture` never sends anything
- `refine --fixture` is safe by default and uses dry-run execution
- `refine --fixture --send-notifications` can send Slack notifications
- fixture mode never mutates GitLab review state

## Sample Fixtures

The repo now ships with starter fixtures in [`fixtures/`](/Users/arthur.kovacs/Work/mr-milchick/fixtures):

- [`first-notification.toml`]/Users/arthur.kovacs/Work/mr-milchick/fixtures/first-notification.toml: a first-touch scenario that renders the lighter `first_*` notification templates
- [`update-notification.toml`]/Users/arthur.kovacs/Work/mr-milchick/fixtures/update-notification.toml: an update scenario that renders the fuller `update_*` notification templates
- [`blocking-refine.toml`]/Users/arthur.kovacs/Work/mr-milchick/fixtures/blocking-refine.toml: a blocking scenario that fails the run

## Quick Commands

Preview the planned actions and notification bodies:

```bash
cargo run -- observe --fixture fixtures/first-notification.toml
```

Print the summary comment preview, snapshot details, routing details, and notification previews:

```bash
cargo run -- explain --fixture fixtures/first-notification.toml
```

Run the refine pipeline safely with no external delivery:

```bash
cargo run -- refine --fixture fixtures/first-notification.toml
```

Actually send Slack notifications from a fixture:

```bash
MR_MILCHICK_SLACK_ENABLED=true \
MR_MILCHICK_SLACK_BOT_TOKEN=xoxb-your-slack-bot-token \
MR_MILCHICK_SLACK_CHANNEL=C0ALY38CW3X \
cargo run -- refine --fixture fixtures/first-notification.toml --send-notifications
```

Send through Slack workflow instead:

```bash
MR_MILCHICK_SLACK_ENABLED=true \
MR_MILCHICK_SLACK_WEBHOOK_URL=https://hooks.slack.com/triggers/... \
MR_MILCHICK_SLACK_CHANNEL=C0ALY38CW3X \
cargo run -- refine --fixture fixtures/update-notification.toml --send-notifications
```

Override the fixture’s notification path from the CLI when you want to compare both variants quickly:

```bash
cargo run -- observe --fixture fixtures/first-notification.toml --fixture-variant update
cargo run -- observe --fixture fixtures/update-notification.toml --fixture-variant first
```

## How Fixture Mode Interacts With Templates

Fixture mode uses the same template loading path as normal execution:

- built-in defaults still apply
- `mr-milchick.toml` overrides still apply
- invalid template fields still warn and fall back to defaults

That makes fixture mode a good way to edit `[templates.*]` sections and immediately see the result.

## Fixture File Shape

Example:

```toml
project_id = "412"
merge_request_iid = "3995"
pipeline_source = "merge_request_event"
notification_variant = "first"

[merge_request]
title = "Frontend adjustments"
url = "https://gitlab.example.com/group/project/-/merge_requests/3995"
author = "arthur"
source_branch = "feat/intentional-cleanup"
target_branch = "develop"
labels = ["frontend"]
existing_reviewers = ["principal-reviewer"]
is_draft = false
default_branch = "develop"

[[merge_request.changed_files]]
path = "apps/frontend/button.tsx"
change_type = "modified"
additions = 24
deletions = 8

[[findings]]
severity = "warning"
message = "Missing label."

[[actions]]
kind = "assign-reviewers"
reviewers = ["bob"]
```

## Supported Fields

Top-level:

- `project_id`
- `merge_request_iid`
- `pipeline_source`
- `notification_variant`

Supported `notification_variant` values:

- `first`
- `update`

`[merge_request]`:

- `title`
- `url`
- `author`
- `description`
- `source_branch`
- `target_branch`
- `labels`
- `existing_reviewers`
- `changed_files`
- `is_draft`
- `default_branch`

`[[merge_request.changed_files]]`:

- `path`
- `change_type`
- `additions`
- `deletions`

Supported `change_type` values:

- `added`
- `modified`
- `deleted`
- `renamed`
- `unknown`

`[[findings]]`:

- `severity`
- `message`

Supported `severity` values:

- `info`
- `warning`
- `blocking`

`[[actions]]`:

- `kind`
- `reviewers`
- `labels`
- `reason`

Supported `kind` values:

- `assign-reviewers`
- `add-labels`
- `remove-labels`
- `fail-pipeline`

## Testing Guidelines

- Start with `observe --fixture` while iterating on templates.
- Use `--fixture-variant first|update` when you want to compare both notification shapes against the same fixture data.
- Use `explain --fixture` when you want the GitLab summary preview plus routing context.
- Use `refine --fixture` before `--send-notifications` to confirm the message shape.
- Keep one fixture per scenario you care about:
  - first notification
  - update notification
  - blocking failure
  - multiple reviewers
  - draft merge request
- If a notification preview looks wrong, fix the fixture or template first before trying a live MR.

## Practical Workflow

1. Edit [`mr-milchick.toml`]/Users/arthur.kovacs/Work/mr-milchick/mr-milchick.toml templates.
2. Run `cargo run -- observe --fixture fixtures/first-notification.toml`.
3. Run `cargo run -- observe --fixture fixtures/update-notification.toml`.
4. Run `cargo run -- explain --fixture fixtures/first-notification.toml` if you want more context.
5. When the rendered text looks right, add Slack env vars and run `cargo run -- refine --fixture fixtures/first-notification.toml --send-notifications`.
6. Iterate on the fixture and template until the delivered message feels right.