--- 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.4" --- # 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) - `` — e.g. `https://redmine.example.com`. - `` — the project identifier (used as `project_id`), e.g. `ivv`. (Numeric id also works.) - `` — 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 …)`. - `` / `` — the ticket / journal-note ids. ## Auth (every call) ```bash curl -s -H "X-Redmine-API-Key: $(cat )" "/…" ``` 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=&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/.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 )" -H "Content-Type: application/json" \ -d '{"issue":{"notes":"…","status_id":,"done_ratio":<0-100>}}' \ "/issues/.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/.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 `
  1. `). - Bold `*text*`, italic `_text_`, inline code `@code@`. - **⚠ A strike-through ENDS at the first `-` inside the text.** Wrapping a whole sentence that contains an arrow (`->`) closes the `` right there, leaving the tail — often the action item, "-> please clarify" — un-struck, i.e. still looking open. Inserting a single space (`. ->`) makes that dash read as an opener instead and the strike-through runs to the end. **HTML is no way out: Redmine escapes `` in journal notes and the raw tag shows.** - **Verify what you wrote actually RENDERED.** The API only tells you the source was stored. Fetch the issue page with the same API-key header and grep for `` — it renders the Textile server-side, so you see exactly what the customer sees. Worth it whenever you strike text through in place. ## 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. Any of them may be the one operating you — don't assume which, and don't assume a ticket is theirs just because they are asking about it. - **Ilja** — **senior developer**. Code, templates, SCSS, TypoScript, deployments. - **Sven** — **senior developer** and maintainer of the shared WapplerSystems extensions (`address`, `ws_slider`, `hero-item`, …). Coordinate with him before cutting a tag on one of those. - **Ranju** — **junior developer**. Also on the development side, so a ticket assigned to her is technical, not editorial. - **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//` needs the **exact** filename (a placeholder → 404 HTML). Reliable: `GET /attachments/.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.