Metadata-Version: 2.4
Name: tft-request-watch
Version: 1.49.0
Summary: Wait on Testing Farm requests; restart on retriable infrastructure errors
Author-email: CKI Team <cki-project@redhat.com>
License-Expression: GPL-2.0-or-later
Project-URL: Homepage, https://gitlab.com/redhat/centos-stream/tests/kernel/tft-request-watch
Requires-Python: >=3.11
Description-Content-Type: text/markdown
License-File: LICENSE
Requires-Dist: requests
Requires-Dist: tft-cli
Requires-Dist: urllib3
Dynamic: license-file

# tft-request-watch

Wraps [Testing Farm](https://docs.testing-farm.io/) CLI with unattended request supervision.

This package can be found

- on Copr as [@cki/tft-request-watch](https://copr.fedorainfracloud.org/coprs/g/cki/tft-request-watch)
- on PyPI as [tft-request-watch](https://pypi.org/project/tft-request-watch)

The Copr packages are provided for all active Fedora releases.

The code is tested on the [supported Python versions] 3.11, 3.12 and 3.13.

[supported Python versions]: https://devguide.python.org/versions/

Benefits compared to running `testing-farm watch` directly:

- Keep polling through temporary API outages.
- Enforce a hard timeout with automatic cancellation.
- Automatically retry the whole request when known retriable infrastructure failures appear
  in `result.summary`.
- Restart only the affected plan(s) when a required test task is aborted due to an
  infrastructure issue.

## Install

```bash
# from Copr
sudo dnf copr enable @cki/tft-request-watch
sudo dnf install tft-request-watch

# from PyPI
pip install tft-request-watch

# from source
pip install git+https://gitlab.com/redhat/centos-stream/tests/kernel/tft-request-watch
```

## Usage

`tft-request-watch` provides two subcommands: `watch` and `merge`.

### watch

Wait for a Testing Farm request to finish, restarting on retriable failures.

```bash
tft-request-watch watch --request-id YOUR-REQUEST-UUID
```

The default API base is `https://api.dev.testing-farm.io/v0.1`; use `--api-url` to point
elsewhere.

Key options:

| Option                    | Description                                                  |
|---------------------------|--------------------------------------------------------------|
| `--request-id UUID`       | Request UUID to watch.                                       |
| `--dry-run`               | Skip write operations; log what would have been done.        |
| `--result-file PATH`      | Write per-run results JSON to PATH (needed for `merge`).     |
| `--required-task TASK`    | Restart if task is aborted; see below. Repeatable.           |
| `--max-restarts N`        | Maximum restart iterations (default: 3).                     |
| `--hard-timeout-hours H`  | Cancel request after H hours (default: 24).                  |

`--required-task TASK` restarts affected plans when a task result is `error` or `pending` in
the XUnit output. Use the test path without the discover alias prefix (e.g.
`/distribution/install`). Can be specified multiple times.

See `tft-request-watch watch --help` for all options including HTTP retry and timeout tuning.

#### Result file format

When `--result-file` is given, a JSON list is written with one entry per run
(original + any restarts):

```json
[
  {"id": "uuid-of-original-run", "xunit_url": "https://...", "...": "..."},
  {
    "id": "uuid-of-retry",
    "retry_of": "uuid-of-original-run",
    "restarted_plans": {"x86_64": ["/plans/tier1"]},
    "xunit_url": "https://...",
    "...": "..."
  }
]
```

`restarted_plans` identifies which `(arch, plan)` testsuites in the original XUnit were
replaced by the retry, useful for `tft-request-watch merge`.

### merge

Produce a single merged XUnit XML from a `--result-file` JSON, replacing testsuites that
were restarted with the retry results.

```bash
tft-request-watch merge result.json merged.xml
```

Fetches the XUnit XML for every run recorded in `result.json`. Testsuites annotated via
`restarted_plans` are taken from the retry; all other testsuites are kept from the original
run.

```bash
tft-request-watch merge --help
```

### Global options

| Option      | Description                        |
|-------------|------------------------------------|
| `--debug`   | Enable DEBUG logging on stderr.    |
| `--version` | Print version and exit.            |

## Development

Installing development dependencies:

```bash
pip install -e . --group dev
```

Running linting/tests:

```bash
tox
```

## Releasing

Every push to `main` automatically:

- publishes to **PyPI** via OIDC trusted publishing,
- creates a **GitLab release** (tagged `v0.42.0`, …),
- builds in **Copr** `@cki/tft-request-watch` via Packit.

The version is semver: the major component lives in
`tft_request_watch/__init__.py` and `tft-request-watch.spec` (keep in sync),
the minor is the GitLab pipeline ID, and patch is always 0
(e.g. `1.42.0`, `1.43.0`). Bump the major version in both files for
breaking changes.

The Copr project depends on `@testing-farm/stable` (for `tft-cli`) as an
external repository, so users only need `dnf copr enable @cki/tft-request-watch`.

## License

GPLv2+ — see `LICENSE`.
