cleanUrl: "/jira"

ScriptRunner

[Jobs] 임직원 정보 동기화 프로세스

사내 API를 활용해서, 지라 계정에 임직원 정보를 맵핑해주는 배치를 Groovy 로 작성

Source Code

import com.atlassian.jira.component.ComponentAccessor;
import com.atlassian.jira.issue.MutableIssue;
import com.atlassian.jira.issue.*;
import com.atlassian.jira.issue.customfields.*;
import com.atlassian.jira.user.UserPropertyManager;
import com.atlassian.jira.user.*;
import com.atlassian.jira.user.util.UserUtil;
import groovy.json.*;
import org.apache.http.client.methods.*;
import org.apache.http.entity.*;
import org.apache.http.impl.client.*;

def userPropertyManager = ComponentAccessor.userPropertyManager;

UserUtil userUtil = ComponentAccessor.getUserUtil();

def url = "<https://xxxxx.com/api/service/findByEmail?email=>"
int qty = 0
int activeCount = 0;
int inactiveCount = 0;
int failCount = 0;
for(ApplicationUser u in userUtil.getUsers())
{
    if(!u.isActive()) {
        inactiveCount++;
        continue;
    }
    else activeCount++;
   
    //log.warn(u)
    //log.warn(u.emailAddress)   
    if(u.emailAddress != null) {
        def get = new HttpGet(url+u.emailAddress)
        get.addHeader("host", "xxxxxxx.com")
        get.addHeader("apikey", "xxxxxxxxxxxxxxxxxx")
        get.addHeader("content-type", "application/json")
        def client = HttpClientBuilder.create().build()
        def response = client.execute(get)        
        if(response.getStatusLine().getStatusCode() == 200) {
            def bufferedReader = new BufferedReader(new InputStreamReader(response.getEntity().getContent()))
			def jsonResponse = bufferedReader.getText()
			def slurper = new JsonSlurper()
			def resultMap = slurper.parseText(jsonResponse)            
            if(resultMap["recordset"] != null) {
                try {                                        
                	resultMap["recordset"]["teamName"] != null ? userPropertyManager.getPropertySet(u).setString('jira.meta.team', resultMap.recordset[0].teamName) : null;    
                    resultMap["recordset"]["jobClassCode"] != null ? userPropertyManager.getPropertySet(u).setString('jira.meta.jobClassCode', resultMap.recordset[0].jobClassCode) : null;    
                }
                catch(Exception e)
                {
                    failCount++;
                    log.warn("error user:"+u)
                    log.error(e)
				}                
            }
        }
    }
}

log.warn("active: "+activeCount + "\\nfail: "+failCount + "\\ninactive: "+inactiveCount);

[Behaviours] 특정 필드 제한 걸기

사용자의 특성, 프로젝트 별, 필드 조건에 맞게, 지라내에서 수정 또는 볼 수 없도록 세세한 조정 가능

특정 사용자 제외

특정 사용자 제외

특정 컨디션에 맞게 스크립트 실행

특정 컨디션에 맞게 스크립트 실행

[Workflows] 워크프로우를 좀 더 상세하게 컨트롤 가능

JSINCLUDER

Javascript 를 지라의 특정 페이지, 프로젝트에 주입해서 사용 할 수 있음

스크립트 주입

/*
Created by Phil 2020.07.06
WORKING VERSION
jsincluder issues in function footer column
*/
try {

    let currentIdx = 0, ghxIssuesInEpicTableTRRows = 1, estimate = 0;

    function timedevide(value) {
        var week = 0;
        var day = 0;
        var hour = 0;

        hour = parseFloat(value % 40);     //시간 계산
        day = parseInt(hour / 8);        //날 계산
        week = parseInt((value - hour) / 40); // 주 계산
        if (9 < hour < 40) {           // 시간이 9~40시간 사이일 경우 계산
            hour = hour - (day * 8)
        }
        else if (8 <= hour <= 9) {    // 시간이 8~9 시간일 경우 계산
            hour = hour - 8
        }
        return {                       // 결과값 리턴
            h: +hour.toFixed(4),
            d: +day.toFixed(4),
            w: +week.toFixed(4)
        }
    }

    const loopForever = () => {

        if (currentIdx < ghxIssuesInEpicTableTRRows) {
            // console.log('currentIdx: '+currentIdx+' ghxIssuesInEpicTableTRRows: '+ghxIssuesInEpicTableTRRows);
            setTimeout(loopForever, 500);
            // console.log('loop');
        } else {
            // console.log('currentIdx: '+currentIdx+' ghxIssuesInEpicTableTRRows: '+ghxIssuesInEpicTableTRRows);
            var actions2 = AJS.$('#ghx-issues-in-epic-table tbody');
            AJS.$(actions2).before('<thead><tr class="issuerow"><th></th><th>Key</th><th>Summary</th><th></th><th>Status</th><th>Assignee</th><th>Due Date</th><th>Original<br/>Estimate</th><th></th></tr></thead>');
            AJS.$(actions2).after('<tfoot><tr class="issuerow"><td></td><td></td><td></td><td></td><td>총공수</td><td>' + +(estimate / 160).toFixed(4) + '</td><td>Sum</td><td>' + timedevide(estimate).w + "Week " + timedevide(estimate).d + "Day " + timedevide(estimate).h + "Hour " + '</td><td></td></tr></tfoot>');
        }
    }
    AJS.$(document).ready(function () {
        try {
            //Updated 2020.07.06 by Phil              
            let rows = AJS.$('#ghx-issues-in-epic-table tr');
            ghxIssuesInEpicTableTRRows = rows.length;
            // console.log("total row: "+ghxIssuesInEpicTableTRRows);
            if (rows.length > 0) {
                loopForever();
            }
            rows.each(function () {   
                // 여기에 있으면 getJson 보다 먼저 처리됨
                // currentIdx = currentIdx + 1;   
                var row = this;
                var value;
                var issueKey = AJS.$(this).attr("data-issuekey");
                if (issueKey) {
                    AJS.$.getJSON(AJS.contextPath() + '/rest/api/latest/issue/' + issueKey, function (data) {
                        value = 0;
                        if (data.fields.aggregatetimeoriginalestimate) {
                            value = data.fields.aggregatetimeoriginalestimate / 3600;    
                            estimate = estimate + value;
                        }
                        else
                        {
                            value = 0;
                        }                        
                        
                        var actions = AJS.$(row).find('td.issue_actions');
                        duedate = data.fields.duedate;
                        AJS.$(actions).before('<td class="nav">' + duedate + '</td>');
                        AJS.$(actions).before('<td class="nav">' + timedevide(value).w + "Week " + timedevide(value).d + "Day " + timedevide(value).h + "Hour " + '</td>');
                        // console.log("index: "+currentIdx + " value:" +value);
                        currentIdx = currentIdx + 1;
                    });
                }
                else
                {
                    // console.log(AJS.$(this));
                    currentIdx = currentIdx + 1;
                }
                // console.log('estimate: '+estimate);
            });
        } catch (error1) {
            alert(`다음과 같은 에러가 발생했습니다: ${error1.name}: ${error1.message}`);
            // console.log(error1);
        }

    });

} catch (error) {
    alert(`다음과 같은 에러가 발생했습니다: ${error.name}: ${error.message}`);
    // console.log(error);
}