[feat] spi status shows active service pins
- Dominant language
- Python
- Stars
- 0
- Forks
- 2
- Avg merge
- 7h 6m
- Merged PRs (30d)
- 107
Description
### Problem
`spi status` gives no sign that a service is pinned. During a Borrow, Prove, Restore run on dks (danielscholl-osdu/partition run 34519766164) the only clues in the human output were the `partition` HelmRelease reading Progressing and a fork digest on the `osdu-partition` pods. An operator who wants to know whether the environment is borrowed, by whom, and since when has to read `spi status --json` and look for `images.pinnedServices`, which lists names only.
The snapshot already decodes the pins: `src/spi/status.py` builds `ImageState.pinned_services` from `decode_pins(image_lock)`, and `to_dict` emits it as `pinnedServices`. `render_status` and `get_summary` never read it.
### Proposed solution
1. Carry the decoded `ServicePin` objects on the snapshot instead of names only. Keep `pinnedServices` in the JSON envelope as the sorted name list it is today, and add a `pins` map keyed by service with `digest`, `ephemeral`, `runId`, `sourceRepo`, `sourceSha`, `sourceRunUrl`, `appliedAt`, and `canonicalDigest`, all straight from `ServicePin` fields.
2. Render a `Pinned Services` table in `render_status` after the Helm Releases table, only when at least one pin exists. Columns: Service, Image (the pinned repository and first 19 digest characters), Origin (`describe_pin` from `src/spi/pins.py`, which already formats MR, run, and operator pins), Canonical (first 19 characters of `canonical_digest`), Age (from `applied_at` via `age_str`).
3. Append `| PINNED: ` to the counts line in `get_summary`, styled like the existing SUSPENDED and MAINTENANCE markers, and list the pinned service names on their own line in the Summary panel.
4. Tests in `tests/test_status.py`: a snapshot with one ephemeral run pin and one operator pin renders the table with both rows and the summary marker; a snapshot with no pins renders neither; the JSON envelope carries the new `pins` map and the unchanged `pinnedServices` list.
Pin data comes from the lock annotation that status already reads. No new cluster reads.
### Alternatives considered
Pointing operators at `spi service list`. It answers the question but only for someone who already suspects a pin; status is where a borrowed environment should announce itself.
Verify with `uv run pre-commit run --all-files`, then `uv run spi status` against an environment with an active pin (`uv run spi service pin partition --image --ephemeral --run-id ...` then `uv run spi service reset partition --if-run `).
Contributor guide
Research direction
Start in src/spi/status.py to trace the snapshot, render_status, get_summary, and JSON serialization, then read ServicePin and describe_pin in src/spi/pins.py. Run the focused tests in tests/test_status.py first. Done means ephemeral and operator pins appear in the table and summary, unpinned snapshots show neither, and the JSON keeps pinnedServices while adding the pins map.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- python
- Domain
- cli, devops
- Issue type
- Feature
- Difficulty
- 3/5
- Estimated time
- 1-2 days
- Activity status
- Active
- Clarity
- Clearly specified
- Newbie friendliness
- 78/100