Repository navigation
Automation Recipes zh TW
English · 繁體中文
三個「不是用鍵盤操作 Taiga」的可執行範例。三者都依賴 JSON contract:--json 提供
穩定形狀、--fields 縮小回應、--no-input 確保不會卡在提示等待輸入,並以 exit code 判斷發生了什麼事。
三個範例都需要在環境中設定 TAIGA_API_URL 與 TAIGA_TOKEN,或先用
taiga auth login 登入。
這裡的陷阱是每次失敗都開一張新 issue。先搜尋,已經有開著的就改成留言。
# .github/workflows/report-failure.yml
name: Report failures to Taiga
on:
workflow_run:
workflows: ["CI"]
types: [completed]
jobs:
report:
if: ${{ github.event.workflow_run.conclusion == 'failure' }}
runs-on: ubuntu-latest
env:
TAIGA_API_URL: ${{ secrets.TAIGA_API_URL }}
TAIGA_TOKEN: ${{ secrets.TAIGA_TOKEN }}
TAIGA_PROJECT: example-project
steps:
- run: curl -fsSL https://raw.githubusercontent.com/KoukeNeko/taiga-cli/main/scripts/install.sh | sh
- name: Open or update the issue
run: |
export PATH="$HOME/.local/bin:$PATH"
subject="CI failed on ${{ github.ref_name }}"
run_url="${{ github.event.workflow_run.html_url }}"
# --fields 讓回應只含腳本會讀的欄位。
existing=$(taiga search "$subject" --type issue --json --fields ref,subject --no-input |
jq -r --arg s "$subject" 'first(.items[] | select(.subject == $s) | .ref) // empty')
if [ -n "$existing" ]; then
taiga issue comment "$existing" --body "Failed again: $run_url" --json --no-input
else
taiga issue create --subject "$subject" \
--description "First failure: $run_url" \
--type Bug --json --no-input
fi值得抄的是兩個細節,而不是整個檔案。--fields ref,subject 讓腳本只解析它真正用到的欄位,所以上游新增
欄位不會改變它的行為。另外它完全不重試:寫入途中連線中斷時 taiga 會以 11 結束,而不是開出兩張
issue,該步驟隨即明確失敗 —— 對一個回報用的 job 來說,這正是我們要的結果。
--json 的輸出是穩定的封包結構,所以今天寫的 jq 運算式之後仍然可用。
#!/usr/bin/env sh
set -eu
# 未指派且未關閉的 issue。
taiga issue list --limit 200 --json --fields ref,subject,status,assignee,is_closed --no-input |
jq -r '.items[]
| select(.is_closed == false and (.assignee // "") == "")
| "#\(.ref)\t\(.status)\t\(.subject)"'要依結果分支時,判斷 exit code 而不是比對訊息文字:
if taiga issue view 42 --json --fields ref,version --no-input > /tmp/issue.json; then
version=$(jq -r '.data.version' /tmp/issue.json)
else
case $? in
3) echo "尚未認證" >&2 ;;
5) echo "issue 42 不存在" >&2 ;;
9) echo "Taiga 無法連線,可安全重試" >&2 ;;
*) echo "未預期的失敗" >&2 ;;
esac
exit 1
fi完整對照表見 JSON Contract。對腳本最重要的三個是 6(別人先改了這筆資料)、 9(傳輸問題,可安全重試)與 11(寫入可能已經送達,不要重試)。
Agent 不應該用猜的來判斷一個指令能不能無人監督執行 —— 直接問工具。
taiga schema issue create --json --no-input{
"data": {
"command": "issue create",
"safety": "write",
"idempotency": "non_idempotent",
"input_schema": { "...": "JSON Schema draft 2020-12" },
"output_schema": { "...": "..." }
},
"meta": { "contract": 1 }
}safety 與 idempotency 是 agent 需要的兩個欄位:read 可以直接執行,write 需要做決定,而
non_idempotent 代表失敗的嘗試不可以直接重送。
寫入前先排練一次。--dry-run 仍會連線 Taiga —— 它會把狀態名稱解析成 ID、確認 assignee 存在 —— 但保證
不會有任何寫入請求離開這個行程:
taiga issue edit 42 --status "In progress" --assignee alice --dry-run --json --no-input{
"plan": {
"action": "edit",
"target": "example-project#42",
"would_write": true,
"performed": false,
"changes": {
"assignee": "alice",
"base_version": 7,
"description": null,
"priority": "",
"severity": "",
"status": "In progress",
"subject": null,
"type": ""
}
},
"meta": { "contract": 1 }
}所有可編輯欄位都會出現,不論你有沒有指定,所以請讀取你在意的鍵,不要假設這個物件只包含你傳入的項目。
接著才真正寫入,並處理兩種「不是成功」的回應:
if taiga issue edit 42 --status "In progress" --base-version 7 --json --no-input; then
echo "已套用"
else
case $? in
6) echo "別人先改了,重新讀取後再決定" >&2 ;;
11) echo "寫入可能已生效,重試前先確認" >&2 ;;
*) exit 1 ;;
esac
fi明確傳入 --base-version 是在表達意圖:這個變更要套用在版本 7 上,否則就拒絕。不指定時指令會自己讀取
目前版本 —— 那通常是人想要的行為,但很少是無人監督的 agent 該依賴的。
以下逐字紀錄是真的,對著 Taiga 6.10.2 伺服器、由兩個行為者編輯同一張 issue 抓下來的。它重要是因為 Taiga 是逐欄位比對版本 —— 比鎖定寬鬆,而且很容易被想成別的樣子。
$ taiga issue view 4 --json --fields ref,subject,status,version
{"data":{"ref":4,"status":"New","subject":"Refresh tokens on 401","version":1},"meta":{"contract":1}}
# 此時另一人在網頁 UI 改了 subject
$ taiga issue edit 4 --status "In progress" --base-version 1
Updated issue atlas-commerce#4: Refresh tokens on 401 and 403 (version 3)
$ echo $?
0這次寫入以版本 1 為基礎卻仍然成功,因為對方動的是 subject,而這個指令動的是 status。對方的文字保留、
這次的狀態變更生效,版本前進了兩次。
# 另一人先把 status 改成 In progress
$ taiga issue edit 5 --status Closed --base-version 1
Error: version: The version doesn't match with the current one
$ echo $?
6$ taiga --json issue edit 5 --status Closed --base-version 1
{"error":{"code":"occ_conflict","message":"version: The version doesn't match with the current one","retryable":false,"details":{"version":"The version doesn't match with the current one"},"upstream_status":400},"meta":{"contract":1}}沒有任何東西被覆寫,也沒有任何重試。對腳本而言,面對 exit 6 的正確反應是重新讀取該筆資料再做決定 —— 對方的值很可能才是對的。
Getting started
Command reference
- Projects
- Members and Roles
- Work Items
- Sprints
- Wiki Pages
- Attachments
- Metadata and Custom Fields
- Search, Timeline and Stats
- Batch Operations
- Automation Recipes
- Alternatives
- Webhooks
- Account and Integrations
Operations