From 9d476a43fa019f76b15ac8e634890b60643a06f2 Mon Sep 17 00:00:00 2001 From: Pavel Gnedov Date: Tue, 20 Feb 2024 16:56:41 +0700 Subject: [PATCH] =?UTF-8?q?=D0=94=D0=BE=D0=B1=D0=B0=D0=B2=D0=BB=D0=B5?= =?UTF-8?q?=D0=BD=20=D0=B2=D1=81=D0=BF=D0=BE=D0=BC=D0=BE=D0=B3=D0=B0=D1=82?= =?UTF-8?q?=D0=B5=D0=BB=D1=8C=D0=BD=D1=8B=D0=B9=20=D1=81=D0=BA=D1=80=D0=B8?= =?UTF-8?q?=D0=BF=D1=82=20=D0=B4=D0=BB=D1=8F=20=D0=BF=D1=80=D0=B8=D0=BD?= =?UTF-8?q?=D1=83=D0=B4=D0=B8=D1=82=D0=B5=D0=BB=D1=8C=D0=BD=D0=BE=D0=B9=20?= =?UTF-8?q?=D1=81=D0=B8=D0=BD=D1=85=D1=80=D0=BE=D0=BD=D0=B8=D0=B7=D0=B0?= =?UTF-8?q?=D1=86=D0=B8=D0=B8=20=D1=81=D1=83=D0=BC=D0=BC=D0=B8=D1=80=D1=83?= =?UTF-8?q?=D1=8E=D1=89=D0=B8=D1=85=20=D0=B7=D0=B0=D0=B4=D0=B0=D1=87?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- tools/sync-root-issues.mjs | 135 +++++++++++++++++++++++++++++++++++++ 1 file changed, 135 insertions(+) create mode 100644 tools/sync-root-issues.mjs diff --git a/tools/sync-root-issues.mjs b/tools/sync-root-issues.mjs new file mode 100644 index 0000000..02a9f41 --- /dev/null +++ b/tools/sync-root-issues.mjs @@ -0,0 +1,135 @@ +import { parse } from 'jsonc-parser'; +import { readFileSync } from 'fs'; +import { parseArgs } from 'util'; +import { createInterface } from 'readline/promises'; + +const helpMsg = ` +Синхронизация суммирующих задач + +* --config=sync-root-issues.jsonc - конфигурационный файл для постановки задачи на выполнение синхронизации +* --yes - автоматически отвечать 'y' + +Пример конфигурационного файла: + +{ + "redmineUrl": "http://redmine.my-company.local", + "redmineToken": "... ... ...", + "eventEmitterUrl": "http://localhost:3000", + + "rootIds": [ + 123001, + 130012 + ] +} +`; + +var args = parseArgs({ + options: { + config: { + type: 'string', + }, + yes: { + type: 'boolean', + }, + }, +}); + +if (!args?.values?.config) { + console.log(helpMsg); + process.exit(0); +} + +function readConfig(fileName) { + const rawData = readFileSync(fileName, { encoding: 'utf8' }); + return parse(rawData); +} + +var config = readConfig(args.values.config); + +function getAllRootIssueIds(issues, res) { + for (let i = 0; i < issues.length; i++) { + const issue = issues[i]; + if (issue.children && issue.children.length > 0) { + res.push(issue.id); + getAllRootIssueIds(issue.children, res); + } + } + return res; +} + +async function loadIssueFromRedmine(issueId) { + const token = config?.redmineToken || ''; + const redmineUrl = config?.redmineUrl || ''; + const url = `${redmineUrl}/issues/${issueId}.json?include=children`; + const resp = await fetch(url, { + headers: { + 'X-Redmine-API-Key': token, + }, + }); + const data = await resp.json(); + return data?.issue || null; +} + +async function loadAllRootIssueIds() { + const rootIssueIds = config?.rootIds || []; + const rootIssues = []; + for (let i = 0; i < rootIssueIds.length; i++) { + const rootIssueId = rootIssueIds[i]; + const issue = await loadIssueFromRedmine(rootIssueId); + if (issue) { + rootIssues.push(issue); + } + } + const allRootIssueIds = getAllRootIssueIds(rootIssues, []); + return allRootIssueIds; +} + +async function questionYesOrNo(question, yesMsg, noMsg) { + const readline = createInterface({ + input: process.stdin, + output: process.stdout, + }); + const answer = await readline.question(`\n${question} (y/n)\n> `); + const res = answer == 'y'; + readline.close(); + console.log(res ? `\n${yesMsg}` : `\n${noMsg}`); + return res; +} + +async function main() { + console.log( + `Конфигурационный файл:\n${JSON.stringify(config, null, ' ')}\n`, + ); + if (!args.values.yes) { + const res = await questionYesOrNo( + 'Продолжаем?', + 'Продолжаем...', + 'Прервано', + ); + if (!res) process.exit(); + } + const rootIds = await loadAllRootIssueIds(); + console.log(`Задачи для синхронизации - ${JSON.stringify(rootIds)}`); + if (!args.values.yes) { + const res = await questionYesOrNo( + 'Продолжаем?', + 'Продолжаем...', + 'Прервано', + ); + if (!res) process.exit(); + } + console.log(`Отправка задач на синхронизацию...`); + await await fetch( + `${config.eventEmitterUrl}/redmine-event-emitter/append-issues`, + { + method: 'POST', + headers: { + 'Content-Type': 'application/json', + }, + body: JSON.stringify(rootIds), + }, + ); + console.log(`Синхронизация запущена`); +} + +await main();