--- name: gitea-issue-labels-and-pr-curl-traps description: "Dankclaw Gitea API curl traps: PR create needs Content-Type application/json (fake \"[Head]: Required\"), issue labels only via POST /issues/N/labels (PATCH labels silently dropped), token from URL-format secret file." --- Operate Dankclaw Gitea (`http://192.168.0.143:3000`, repo `dank/franksign` and siblings) with curl without the three traps that produce misleading errors. ## Token extraction (URL-format store, NOT key=value) `~/.config/secrets/gitea` is one line: `http://user:TOKEN@192.168.0.143:3000`. `cat`-ing it yields the whole URL, not the token. ```bash TOK=$(sed -n 's|.*://[^:]*:\([^@]*\)@.*|\1|p' ~/.config/secrets/gitea | head -1) ``` Never pass the token as a `-H` argument (world-readable in `/proc//cmdline`). Write a 600-perm curl config: ```bash printf 'header = "Authorization: token %s"\n' "$TOK" > /tmp/g.cfg ``` ## Trap 1 — PR create answers `"[Head]: Required"` when the body is the problem Two independent causes, both look like a missing field: 1. No `Content-Type: application/json` header → Gitea parses the raw JSON as form data, sees no `head`, returns 422 `[Head]: Required`. 2. Putting `data = "@/tmp/body.json"` inside a `-K` curl config does **not** expand the `@`. Fix: add `header = "Content-Type: application/json"` to the config and pass `--data @/tmp/body.json` on the command line: ```bash curl -s -K /tmp/g.cfg -X POST --data @/tmp/pr.json \ "http://192.168.0.143:3000/api/v1/repos/dank/franksign/pulls" ``` ## Trap 2 — issue label assignment via PATCH /issues/N is silently dropped `PATCH /api/v1/repos/{o}/{r}/issues/{n}` with `{"labels":[id]}` returns **200/201 with the issue JSON**, yet a follow-up GET shows `labels: []` (it can even clear existing labels). Labels are a subresource: ```bash curl -s -K /tmp/g.cfg -X POST --data '{"labels":[4]}' \ "http://192.168.0.143:3000/api/v1/repos/dank/franksign/issues/18/labels" ``` 200 returns the assigned label array. Resolve label names→ids via `GET /repos/{o}/{r}/labels` (franksign canonical five: ids 2–6; `ready-for-agent` = 4). ## Verification law Both traps fail *successfully*. After any label/PR write, GET the resource and check the field changed; never trust the status code alone. ## Cleanup `rm -f` the temp config + body files (config holds the token).