59ce47e729
Small, generic skill for reading/updating a self-hosted Redmine over its REST API from the CLI: API-key-in-header auth (never inline the secret), issues/journals/attachments endpoints, editing a journal note in place, the collection-ticket pattern, Textile (not Markdown) formatting + localized statuses, and the team posting-style rules (minimal customer-visible notes — strike through or "erledigt", never the bug's cause; don't post unless asked). Distilled from the IVV Redmine notes. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
68 lines
4.5 KiB
Markdown
68 lines
4.5 KiB
Markdown
---
|
|
name: redmine-issue-workflow
|
|
description: "Read and update issues on a self-hosted Redmine via its REST API from the CLI — list/read tickets, add notes, change status, edit an existing journal note in place, and download attachments. Use when a project tracks its work/bugs in Redmine and you need to look up 'the next fixes', check a ticket's details, mark work done, or maintain a collection ('Sammelticket') ticket. Covers: API-key auth via header (never inline the secret), the issues/journals/attachments endpoints, Textile (NOT Markdown) formatting, localized statuses, and the posting-style rules (keep customer-visible notes minimal — strike through or 'erledigt', don't write the bug's cause; don't post unless asked)."
|
|
metadata:
|
|
author: Wappler
|
|
version: "1.0"
|
|
---
|
|
|
|
# Redmine issue workflow (REST API, CLI)
|
|
|
|
Read and update a self-hosted **Redmine** project's issues over its REST API from the shell. Redmine
|
|
is where the team tracks bugs / "next fixes"; you look tickets up, and — only when asked — mark work done.
|
|
|
|
## Placeholders (keep the concrete values in project memory, not here)
|
|
- `<REDMINE_URL>` — e.g. `https://redmine.example.com`.
|
|
- `<PROJECT_SLUG>` — the project identifier (used as `project_id`), e.g. `ivv`. (Numeric id also works.)
|
|
- `<API_KEY_FILE>` — a **chmod 600** file holding the per-user REST API key (from Redmine → *My account
|
|
→ API access key*). **Never inline the key** — always read it in the header via `$(cat …)`.
|
|
- `<ISSUE_ID>` / `<JOURNAL_ID>` — the ticket / journal-note ids.
|
|
|
|
## Auth (every call)
|
|
```bash
|
|
curl -s -H "X-Redmine-API-Key: $(cat <API_KEY_FILE>)" "<REDMINE_URL>/…"
|
|
```
|
|
Keeps the secret out of the command line (auto-mode/secret guards block a literal key).
|
|
|
|
## Read
|
|
- **Open issues (the "next fixes"):**
|
|
`GET /issues.json?project_id=<PROJECT_SLUG>&status_id=open&sort=priority:desc&limit=100`
|
|
(`status_id=open` = all non-closed; `sort=updated_on:desc` to see the newest activity.)
|
|
- **One issue with its notes:** `GET /issues/<ISSUE_ID>.json?include=journals,attachments`.
|
|
- Pipe JSON through `python3 -c "import sys,json;…"` to print `id / status / subject / assignee / notes`.
|
|
- **Statuses may be localized.** A German instance uses: **Fehler** = bug (open), **Gewünscht** =
|
|
wishlist/requested, **Empfohlen** = recommended, **Abnahme** = ready for customer sign-off. Confirm the
|
|
instance's own status names via `GET /issue_statuses.json` before setting one by id.
|
|
|
|
## Update (only when the user asks — see posting style)
|
|
- **Add a note / change status / progress** on an issue:
|
|
```bash
|
|
curl -s -X PUT -H "X-Redmine-API-Key: $(cat <API_KEY_FILE>)" -H "Content-Type: application/json" \
|
|
-d '{"issue":{"notes":"…","status_id":<N>,"done_ratio":<0-100>}}' \
|
|
"<REDMINE_URL>/issues/<ISSUE_ID>.json" # → 204 No Content on success
|
|
```
|
|
- **Edit an EXISTING journal note in place** (e.g. a collection ticket's item list that one person keeps
|
|
appending to): `PUT /journals/<JOURNAL_ID>.json` with `{"journal":{"notes":"…"}}` → 204. Get the
|
|
journal id from the issue's `include=journals`.
|
|
- **Collection / "Sammelticket" pattern:** one ticket stays open and holds a numbered item list (often in
|
|
a single journal note). As items are done, **strike them through** and the ticket stays open for more.
|
|
|
|
## Formatting — Textile, NOT Markdown
|
|
Redmine renders **Textile** by default. Consequences:
|
|
- Strike-through = `-text-` (Markdown `~~…~~` does nothing).
|
|
- A leading `#` is an **ordered-list** item, not a heading (Markdown `#` headings render as `<ol><li>`).
|
|
- Bold `*text*`, italic `_text_`, inline code `@code@`.
|
|
|
|
## Posting style (team rules — important)
|
|
- **Don't post unless asked.** The user often does the Redmine updates themselves; offer/confirm first.
|
|
- **Keep customer-visible notes minimal. Do NOT write out the bug's cause / technical explanation** in the
|
|
ticket. To mark something done, **strike the item through** (`-…-`) or just write **"erledigt"** beside
|
|
it, where appropriate. The detailed root-cause/fix belongs in your own notes/memory, not the ticket.
|
|
- Before posting a status change, prefer to draft the (short, German if the project is German) note and
|
|
confirm the target status with the user.
|
|
|
|
## Attachments
|
|
`GET /attachments/download/<id>/<name>` needs the **exact** filename (a placeholder → 404 HTML). Reliable:
|
|
`GET /attachments/<id>.json` → read `content_url` → `curl -L` THAT with the API-key header. Attached
|
|
"screenshots" are often browser print-to-PDF files — readable directly once downloaded.
|