Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
51 lines
4.3 KiB
JavaScript
Executable File
51 lines
4.3 KiB
JavaScript
Executable File
#!/usr/bin/env node
|
|
'use strict';
|
|
// ============================================================================
|
|
// 작업 서버용 "다음 작업 반영 목록" 수집기 (v1.1.6)
|
|
//
|
|
// 관리자가 AI 분석을 보고 "다음 작업에 반영" 으로 결정하고 반영할 내용을 적은 사용자 제안·오류를
|
|
// 각 운영 서버에서 가져와 하나의 작업 목록(BACKLOG.md + backlog.json)으로 만든다.
|
|
// 다음 릴리스 작업을 시작할 때 이 파일을 읽어 요구 사항에 포함한다.
|
|
//
|
|
// 설정: ~/.config/ai-webmaker/backlog-sources.json (권한 600)
|
|
// [ { "name": "webmaker", "url": "https://webmaker.ibit.kr", "key": "<관리자 콘솔 › 설정 › 작업 서버 수집 키>" }, ... ]
|
|
// 출력: $BACKLOG_DIR (기본 ~/work/ai-webmaker-backlog) 아래 BACKLOG.md, backlog.json
|
|
// 사용: node scripts/collect-backlog.js [--mark] --mark 를 주면 가져간 글에 "수집됨" 표시를 남긴다
|
|
// node scripts/collect-backlog.js --implemented <id,id,...> --version 1.2.0 [--note "…"]
|
|
// → 릴리스에 반영한 항목을 각 서버에 "반영됨" 으로 표시 (목록에서 빠지고 사용자 화면에 버전과 함께 표시)
|
|
// 주기 실행: crontab 예) 0 * * * * node /home/master/work/WebHoting_AI_Agent/scripts/collect-backlog.js --mark >> ~/.local/state/ai-webmaker-backlog.log 2>&1
|
|
// ============================================================================
|
|
const fs = require('fs'); const path = require('path'); const os = require('os');
|
|
const CONF = process.env.BACKLOG_SOURCES || path.join(os.homedir(), '.config', 'ai-webmaker', 'backlog-sources.json');
|
|
const OUT = process.env.BACKLOG_DIR || path.join(os.homedir(), 'work', 'ai-webmaker-backlog');
|
|
const MARK = process.argv.includes('--mark');
|
|
const feedback = require('../lib/feedback'); // backlogMarkdown 재사용 (데이터 파일은 읽지 않음)
|
|
|
|
const argOf = (name) => { const i = process.argv.indexOf(name); return i > 0 ? process.argv[i + 1] : null; };
|
|
(async () => {
|
|
let sources; try { sources = JSON.parse(fs.readFileSync(CONF, 'utf8')); } catch (e) { console.error(`설정 파일을 읽지 못했습니다: ${CONF} (${e.message})`); process.exit(1); }
|
|
const impl = argOf('--implemented');
|
|
if (impl) {
|
|
// 반영 완료 표시 모드: 각 서버에 같은 ID 목록을 보낸다(그 서버에 없는 ID 는 무시됨)
|
|
const ids = impl.split(',').map((x) => x.trim()).filter(Boolean); const version = argOf('--version') || ''; const note = argOf('--note') || '';
|
|
for (const src of sources) { try { const r = await fetch(`${src.url.replace(/\/$/, '')}/api/service/backlog/implemented`, { method: 'POST', headers: { 'X-Backlog-Key': src.key, 'Content-Type': 'application/json' }, body: JSON.stringify({ ids, version, note }) }); const j = await r.json(); console.log(`${src.name}: ${r.ok ? `${j.marked}건 반영됨 표시 (v${version})` : '실패 — ' + (j.error || r.status)}`); } catch (e) { console.log(`${src.name}: 실패 — ${e.message}`); } }
|
|
return;
|
|
}
|
|
const all = []; const report = [];
|
|
for (const src of sources) {
|
|
try {
|
|
const r = await fetch(`${src.url.replace(/\/$/, '')}/api/service/backlog`, { headers: { 'X-Backlog-Key': src.key } });
|
|
const j = await r.json(); if (!r.ok) throw new Error(j.error || `HTTP ${r.status}`);
|
|
for (const x of j.items) all.push({ ...x, server: src.name, serverUrl: src.url, serverVersion: j.version });
|
|
report.push(`${src.name}: ${j.items.length}건 (v${j.version})`);
|
|
if (MARK && j.items.length) await fetch(`${src.url.replace(/\/$/, '')}/api/service/backlog/collected`, { method: 'POST', headers: { 'X-Backlog-Key': src.key, 'Content-Type': 'application/json' }, body: JSON.stringify({ ids: j.items.map((x) => x.id), by: `work-server ${os.hostname()}` }) });
|
|
} catch (e) { report.push(`${src.name}: 실패 — ${e.message}`); }
|
|
}
|
|
fs.mkdirSync(OUT, { recursive: true });
|
|
const at = new Date().toISOString();
|
|
fs.writeFileSync(path.join(OUT, 'backlog.json'), JSON.stringify({ at, sources: report, items: all }, null, 1));
|
|
const md = feedback.backlogMarkdown(all.map((x) => ({ ...x, title: `${x.title} (${x.server})` })), { server: sources.map((s) => s.name).join(', '), at });
|
|
fs.writeFileSync(path.join(OUT, 'BACKLOG.md'), md);
|
|
console.log(`[${at}] ${report.join(' / ')} → ${path.join(OUT, 'BACKLOG.md')} (${all.length}건)`);
|
|
})();
|