Серверный скрипт для импорта тасок из JIRA в SDLC SimpleOne v2

Серверный скрипт для импорта тасок из JIRA в SDLC SimpleOne

//Нужно создать запиcи с данными названиями в таблице sys_property, и поставить ваши value
let token = ss.getProperty('itg.jira_token');//Корректный токен к проекту JIRA
let pda_project_id = ss.getProperty('itg.project_id');// Запись в таблице pda_project
const projectKey = ss.getProperty('itg.project_key')//Key для проекта в JIRA
let pda_product_module_id = ss.getProperty('itg.product_module_id')//Запись в таблице pda_module_id
let pda_product_id = ss.getProperty('itg.product_id')//Запись в таблице pda_product
//let pda_release_id = "";//расскомментируйте, если нужен release id //Запись в таблице pda_release

let baseBrowserUrl = `https://example.com/browse/`
//Нужно написать типы тасок для импорта
// Sub-task можно не писать, в данном скрипте, они создаются при импорте тасок и привязываются к ним
let wantIssueType = "Task";// [Epic, Bug, Task, Story, Sub-task] 
let startNum = "0"
let maxNum = "150"// Пишите корректное количество всех тасок из JIRA

function setTable(issueType) {
    const typeMapping = {
        'Epic': "pda_epic",
        'Bug': "pda_defect",
        'Story': "pda_user_story",
        'Task': "pda_task",
        'Sub-task': "pda_subtask"
    };

    return typeMapping[issueType] || "Unknown"; // Return the mapped value or "Unknown" if the issue type is not found
}
// Fetch issue keys based on JQL query with specific statuses
const baseUrl = 'https://example.com/rest/api/2';


const statusQuery = 'status in ("Backlog","In Review", "In Progress","Selected for Development")';// PUL
const issueTypeQuery = `issuetype = ${wantIssueType}`
const groupQuery = `project = ${projectKey} AND ${statusQuery} AND ${issueTypeQuery}`;
const encodedGroupQuery = encodeURIComponent(groupQuery);
const jqlQuery = `jql=${encodedGroupQuery}&startAt=${startNum}&maxResults=${maxNum}`;
const request = sws.restRequestV1();
request.setRequestUrl(`${baseUrl}/search?${jqlQuery}`);

request.setRequestMethod('GET');
request.setRequestHeader('Authorization', 'Bearer ' + token);

let subTasks;
const response = request.execute();
let dataJson = JSON.parse(response.getBody());
let issueKeys = [];
dataJson.issues.forEach(issue => {
    issueKeys.push(issue.key);
});

fetchAndProcessIssues(issueKeys);

function fetchAndProcessIssues(issueKeys) {
    issueKeys.forEach(issueKey => {
        let issueUrl = `${baseUrl}/issue/${issueKey}`;

        const request = sws.restRequestV1();
        request.setRequestUrl(issueUrl);
        request.setRequestMethod('GET');
        request.setRequestHeader('Authorization', 'Bearer ' + token);
        const response = request.execute();
        let dataJson = JSON.parse(response.getBody());
        let assigneeName = dataJson.fields.assignee ? dataJson.fields.assignee.name : 'Unassigned';
     // ss.info(dataJson.fields.subtasks[0]);
      // ss.info(JSON.stringify(dataJson,null,2))
        let issueFields = {
            subtasks: dataJson.fields.subtasks[0],
            assignee: assigneeName,
            status: dataJson.fields.status ? dataJson.fields.status.name : '',
            priority: dataJson.fields.priority.name ? dataJson.fields.priority.name : '',
            reporter: dataJson.fields.reporter.emailAddress ? dataJson.fields.reporter.emailAddress : '',
            dueDate: dataJson.fields.duedate ? dataJson.fields.duedate : '',
            labels: dataJson.fields.labels ? dataJson.fields.labels : [],
            environment: dataJson.fields.environment ? dataJson.fields.environment : '',
            fixVersions:dataJson.fields.fixVersions.name ? dataJson.fields.fixVersions.name : [],
            components:dataJson.fields.components ? dataJson.fields.components : [],
            key: dataJson.key ? dataJson.key : "",
            description: dataJson.fields.description ? dataJson.fields.description : '',
            creator: dataJson.fields.creator ? dataJson.fields.creator.name : '',
            summary: dataJson.fields.summary ? dataJson.fields.summary : '',
            created: dataJson.fields.created,
            updated: dataJson.fields.updated,
            epic_link: dataJson.fields.customfield_10014 ? dataJson.fields.customfield_10014 : '',
            comments: dataJson.fields.comment ? dataJson.fields.comment.comments : [],
            attachments: dataJson.fields.attachment ? dataJson.fields.attachment : [],
        };
        createTask(issueKey, issueFields);
    });
}

function createTask(issueKey, issueFields) {
 let insert_table = setTable(wantIssueType);
  const issue_table = new SimpleRecord(insert_table);
  if (insert_table === "pda_user_story") {// If User Story 
    issue_table.pda_im_as = "Я как...";
    issue_table.pda_want  = "Хочу...";
    issue_table.pda_in_order_to  = "Для того, чтобы...";
    issue_table.pda_acceptance_criteria  = issueFields.description || " ";// Бывает description пустой
    }
  
  if (insert_table != "pda_user_story") {// If User Story 
    issue_table.description = issueFields.description;
   }
  
  issue_table.subject = issueFields.summary;
  issue_table.description = issueFields.description;
  issue_table.short_description = issueFields.key;
  issue_table.assigned_user = getUserByLogin(issueFields.assignee);
  issue_table.caller = getUserByLogin(issueFields.creator);
  issue_table.opened_at = formatDate(issueFields.created);
  issue_table.state = setState(issueFields.status);
  issue_table.priority = setPriority(issueFields.priority);
  issue_table.pda_project_id = pda_project_id;
 // issue_table.pda_release_id = pda_release_id;//Если нужен релих, то нужно раскомментировать
  issue_table.pda_product_id = pda_product_id;
  issue_table.pda_product_module_id = pda_product_module_id;
  issue_table.pda_rank = 10;
  issue_table.comments = `${baseBrowserUrl}${issueKey}`;
  issue_table.work_notes = `
  Reporter: ${issueFields.reporter}
  IssueKey: ${issueFields.key}
  Updated: ${formatDate(issueFields.updated)}
  Created: ${formatDate(issueFields.created)}
  Labels: ${issueFields.labels}
  Environment: ${issueFields.environment}
  FixVersions: ${issueFields.fixVersions}
  Components: ${issueFields.components}
  Due date: ${issueFields.dueDate}
  Epic Link: ${issueFields.epic_link}
  `;
  const insertedRecordId = issue_table.insert();
  if (insertedRecordId === 0) {
    ss.info(issue_table.getErrors());
    
  }
  if (insert_table === "pda_epic") {//insertedRecordId
   const epicIssueKeys = getEpicIssues(issueFields.key);
    ss.info(epicIssueKeys);
    
 issue_table.short_description = `Child General Task ${epicIssueKeys}` // Here need Array But Now

    
    let updatedRecord = issue_table.update()

for (let i = 0; i < epicIssueKeys.length; i++) {
  getChildTask(epicIssueKeys[i],updatedRecord);
}
   }
  if (issueFields.subtasks) {
  getSubTask(issueFields.subtasks,issueFields,issueFields.key,insertedRecordId)
}
  insertComments(issueFields.comments, issue_table, insertedRecordId);
  getAttachUrl(issueFields.attachments, issue_table, insertedRecordId);
}


//Функция привязывания сабтаски к таски
function getSubTask(subtasks, issueFields, key, parent_id) {
       if (subtasks.key) {
        request.setRequestUrl(`https://example.com/rest/api/2/issue/${key}/subtask`);
        request.setRequestMethod('GET');
        request.setRequestHeader('Authorization', 'Bearer ' + token);
        const response = request.execute();
        let dataJson = JSON.parse(response.getBody());
        dataJson.forEach(subtaskData => {
            const subtaskInfo = {
                id: subtaskData.id || "",
                key: subtaskData.key || "",
                summary: subtaskData.fields.summary || "",
                status: subtaskData.fields.status.name || "",
            };

            const subtask = new SimpleRecord("pda_subtask");
            subtask.parent_id = parent_id;
            subtask.subject = subtaskInfo.summary;
            subtask.description = subtaskInfo.summary;
            subtask.comments = `https://example.com/browse/${subtaskInfo.key}` || "";
            subtask.short_description = subtaskInfo.key;
            subtask.assigned_user = getUserByLogin(issueFields.assignee);
            subtask.caller = getUserByLogin(issueFields.creator);
            subtask.opened_at = formatDate(issueFields.created);
            subtask.state = setState(subtaskInfo.status);
            subtask.priority = setPriority(issueFields.priority);
            subtask.pda_project_id = pda_project_id;
            subtask.pda_product_id = pda_product_id;
            subtask.pda_product_module_id = pda_product_module_id;
            subtask.pda_rank = 10;
            subtask.work_notes = `
                Reporter: ${issueFields.reporter}
                IssueKey: ${issueFields.key}
                Updated: ${formatDate(issueFields.updated)}
                Created: ${formatDate(issueFields.created)}
                Labels: ${issueFields.labels}
                Environment: ${issueFields.environment}
                FixVersions: ${issueFields.fixVersions}
                Components: ${issueFields.components}
                Due date: ${issueFields.dueDate}
                Epic Link: ${issueFields.epic_link}
            `;
            subtask.insert();
        });
    } else {
        ss.info('No subtasks found for issue key: ' + key);
    }
}

function getEpicIssues(key) {
    const childIssuesArr = [];
    const request = sws.restRequestV1();
    const token = ss.getProperty('itg.jira_token');
    request.setRequestUrl(`https://example.com/rest/api/2/search?jql=issuetype%20%3D%20task%20AND%20%22Epic%20Link%22%20%3D%20${key}%20AND%20status%20in%20(%22Backlog%22,%22In%20Review%22,%20%22In%20Progress%22,%22Selected%20for%20Development%22)`);
    request.setRequestMethod('GET');
    request.setRequestHeader('Authorization', 'Bearer ' + token);
    
    const response = request.execute();
    const dataJson = JSON.parse(response.getBody());

    dataJson.issues.forEach(issue => {
        childIssuesArr.push(issue.key);
    });

    return childIssuesArr; // Return the array of issue keys
}


function getChildTask(key,updatedRecord){
const forRecord = new SimpleRecord('pda_task')
forRecord.addEncodedQuery(`(short_descriptionLIKE${key})`);
forRecord.setLimit(1);
forRecord.query();
if (forRecord.next()){
   // ss.info(forRecord.sys_id)
  const task = new SimpleRecord('pda_task');
  let current_task = task.get(forRecord.sys_id);
  current_task.parent_id = updatedRecord
  current_task.update()
}}





function getUserByLogin(login) {
    const employee = new SimpleRecord('employee');
    employee.addEncodedQuery(`(username=${login})`);
    employee.setLimit(1);
    employee.query();

    while (employee.next()) {
        return employee.sys_id;
    }

    return ''; 
}

function setState(status) { // 'status in ("Backlog","In Review", "In Progress","Selected for Development")'
    const mapping = {
      //Статус Jira: Статус SimpleOne
        "Backlog": "new",
        "In Review": "review",
        "In Progress": "development",
        "Selected for Development": "backlog",
        "Done": "done",//Это только для перенесенных сабтасок, не для тасок
    };

    return mapping[status] || "";
}


function setPriority(priority) {
    const mapping = {//High, Medium, Low
        "High": "high",
        "Medium": "medium",
        "Low": "low"
    };

    return mapping[priority] || "";
}

function insertComments(comments, issue_table, sys_id) {
    const reversedComments = comments.reverse();

    return reversedComments.map(comment => {
        const body = `
            Comment Author Email: ${comment.updateAuthor.emailAddress}
            Comment Created At: ${formatDate(comment.updated)}
            Comment Body:
            \n${comment.body}\n
        `;
        issue_table.get(sys_id);
        issue_table.work_notes = body;
        issue_table.update();
    }).join('\n');
}

function getAttachUrl(attachments, issue_table, sys_id) {
    let stringUrl = '';
    attachments.forEach(attachment => {
        stringUrl += attachment.content + '\n';
    });
    issue_table.get(sys_id);
    issue_table.work_notes = stringUrl;
    issue_table.update();
    //ss.info(stringUrl);
}


function formatDate(inputDate) {
    const date = new Date(inputDate);
    const year = date.getFullYear();
    const month = String(date.getMonth() + 1).padStart(2, '0');
    const day = String(date.getDate()).padStart(2, '0');
    const hours = String(date.getHours()).padStart(2, '0');
    const minutes = String(date.getMinutes()).padStart(2, '0');
    const seconds = String(date.getSeconds()).padStart(2, '0');

    const formattedDate = `${year}-${month}-${day} ${hours}:${minutes}:${seconds}`;

    return formattedDate;
}




2 лайка