135 lines
3.5 KiB
JavaScript
135 lines
3.5 KiB
JavaScript
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();
|