#!/usr/bin/env node /** * 起錶。 * * 錶與領取鎖是兩件事:鎖用 assignee 加標籤(見 claim.js),錶只管工時。分開的理由是 * 時機不同——鎖要在開工之前就上好,錶則要等到**工作樹真的建好之後**才起。工作樹建立 * 失敗會中止整個領取,錶要是先起了,使用者就被計了一段什麼都沒做的時間, * 而工時要準正是工時報表的立足點。 * * 自己的錶跑在別顆議題上時擋下,不代勞停錶:那一段時間該記在哪顆議題上只有人知道, * 腳本自作主張會把工時記錯地方。錶已經跑在本議題上則什麼都不做——重新起錶會把已經 * 累積的時間切成兩段,而中斷後重跑正是這支腳本最常見的處境。 * * 用法: * node scripts/timer.js --repo owner/name --index 40 [--host <網址>] [--dry-run] */ import { expectOk, fetchIssue, giteaRequest, listStopwatches, main, parseFlags, parseIndex, parseRepo, preflight, resolveLogin, stopwatchElsewhere, stopwatchOnIssue, } from './lib.js'; main(async () => { const flags = parseFlags(process.argv.slice(2), { required: ['repo', 'index'], optional: ['host'], booleans: ['dry-run'], }); const repo = parseRepo(flags.repo); const index = parseIndex(flags.index); const issuePath = `/repos/${repo}/issues/${index}`; const dryRun = flags['dry-run'] === true; const login = resolveLogin({ host: flags.host }); // 試跑照樣讀現況:手寫一份固定的清單會跟實作走鐘,也說不出「這顆已經在計時了」 if (!dryRun) await preflight(login, repo); const issue = await fetchIssue(login, repo, index); const watches = await listStopwatches(login); const 已在計時 = stopwatchOnIssue(watches, repo, index) !== null; if (!已在計時 && watches.length > 0) throw stopwatchElsewhere(watches[0], '起錶'); // 已經在跑就不重起:重新起錶會把已經累積的時間切成兩段 const planned = 已在計時 ? [] : [{ method: 'POST', path: `${issuePath}/stopwatch/start`, body: {} }]; if (dryRun) { return { dryRun: true, repo, index, title: issue.title, requests: planned, 已在計時 }; } for (const { method, path, body } of planned) { expectOk(await giteaRequest(login, method, path, { body }), `${method} ${path}`); } return { repo, index: issue.number, title: issue.title, url: issue.html_url, 碼錶中: true, 已在計時, }; });