Der Bearbeiter eines Tickets sagt, um welche ART von Arbeit es geht. Die Rollen sind ueber alle TYPO3-Projekte hinweg dieselben, deshalb gehoeren sie in die Skill und nicht in ein Projektgedaechtnis, das nur fuer ein Projekt geladen wird. Festgehalten: Ilja und Sven entwickeln, Corinna macht Design und den Grossteil der redaktionellen Arbeit, Eva fuehrt das Projekt und aendert redaktionell im Kleinen. Daraus folgen zwei Regeln, die sich in der Praxis bewaehrt haben: ein redaktionelles Ticket nicht stillschweigend selbst erledigen, aber CSS und Code auch dann uebernehmen, wenn das Ticket jemand anderem zugewiesen ist - Tickets mischen beides oft, also nach der Natur der einzelnen Punkte aufteilen und sagen, welche Haelfte man liegen laesst. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
95 lines
6.3 KiB
Markdown
95 lines
6.3 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.3"
|
|
---
|
|
|
|
# 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.
|
|
Two or three sentences is the norm: what is done, where to check it. No commit hashes, no file names,
|
|
no before/after measurements — the customer did not ask how, only whether.
|
|
- **No icons, emoji or decorative symbols in ticket text** (no ✅/✔/→/⚠, no bullets made of glyphs).
|
|
Plain sentences, plus Textile markup where it carries meaning (strike-through, bold). Team rule.
|
|
- **Never set or change `assigned_to_id`.** Post the note and the status, leave the assignee alone —
|
|
reassigning is the user's call and a wrong one pulls a colleague into a ticket that isn't theirs.
|
|
Note that `status_id` and `done_ratio` are fine to set; only ownership is off limits.
|
|
- 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.
|
|
|
|
## Who does what — the same team across all TYPO3 projects
|
|
The assignee tells you what KIND of work a ticket is. These roles hold across projects, so read them
|
|
before deciding whether a ticket is yours to act on.
|
|
|
|
- **Ilja** (the user) and **Sven** — the **developers**. Code, templates, SCSS, TypoScript,
|
|
deployments. Sven maintains the shared WapplerSystems extensions, so coordinate with him before
|
|
cutting a tag on one of those.
|
|
- **Corinna** — **design and the bulk of editorial work**. Content tickets (texts, images, page
|
|
structure) are hers.
|
|
- **Eva** — **project management**, plus light editorial changes. Typically the one who maintains a
|
|
Sammelticket's item list and re-assigns tickets.
|
|
|
|
Consequences:
|
|
- **A ticket assigned to Corinna or Eva is editorial — don't silently do the work.** Report what you
|
|
found if it helps, but leave the change to them.
|
|
- **CSS and code are yours even when the ticket is assigned to someone else.** Tickets often mix the
|
|
two: split them by the NATURE of each item, not by the assignee, do the technical half, and say
|
|
plainly which half you left alone and why.
|
|
- This is also why the assignee must never be changed by you (above): it encodes the routing.
|
|
|
|
## 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.
|