Jira를 사용하다 보면 이슈를 생성할 때 설명 항목에 자주 쓰는 내용들이 있습니다. 예를 들면, 현재 사용하는 프로젝트의 버그 이슈에서 버그에 대한 상세한 설명, 참고 사항 등이 있죠. 현재 사용하고 있는 프로젝트에서는 아래와 같은 내용을 버그 티켓 생성시 작성하고 있습니다.
예시: 버그 이슈 설명(Description) 내용
1 2 3 4 5 6 7 8 9 10
(QA 환경) 환경 설명 (상세 설명) 상세 설명 (참고) 참고 설명 (영상) 영상 링크 (기대 결과) 기대 결과 설명
이러한 내용을 항상 이슈 생성시 마다 작성하는 것도 번거롭고, 각 작성자가 입력하는 내용도 일정하지 않을 때가 있었습니다. 이런 상황들을 개선해보고자 기본 값, 템플릿을 설정할 수 있는지 확인해보았고 다른 Jira 앱(플러그인)들이 있지만 현재 설치되어있는 ScriptRunner로 개선해보았습니다.
ScriptRunner로 설명 항목 기본 값 설정 Flow
ScriptRunner에는 많은 기능들이 있지만 그 중에서 Behaviours 기능을 사용하여 특정 항목의 기본 값 설정을 해보겠습니다. 순서는 다음과 같이 진행합니다. (ScriptRunner 가이드 문서 - Setting Field Defaults에도 있는 내용이니 참고해주세요!)
Jira > Manage apps > Behaviours 이동
Add Behaviours 추가
Add Mapping - 프로젝트 및 이슈 타입 설정
Fields 설정 > Initialiser 스크립트 설정
Add Behaviours 추가
첫 번째 설정으로 이동하는 단계는 스킵하고 Behaviours를 추가하는 것 부터 진행하겠습니다. 위에 있던 이미지 항목대로 behaviour 이름을 입력해주고 Add 버튼을 누르면 끝입니다.
Add Mapping - 프로젝트 및 이슈 타입 설정
Choose projects: 프로젝트는 기본 값 설정이 필요한 프로젝트를 선택하여 지정해주시면 됩니다.
Choose Issue types: 모든 이슈 타입 또는 특정 이슈 타입에 대해서 지정할 수 있습니다.
이 설정으로 behaviour가 동작할 프로젝트, 이슈 타입이 맵핑되었습니다.
Fields 설정 > Initialiser 스크립트 설정
Add Behaviours 화면에서 만든 behaviour 항목에 있는 Fields를 눌러 설정을 진행합니다. 처음에는 Initialiser Function이 없다고 나오는데 Create initialiser를 눌러 생성해주세요. 생성하고 나면 위와 같은 스크립트를 입력할 수 있는 항목을 볼 수 있습니다. 스크립트를 입력해볼까요?
if (getActionName() != "Create Issue") { return// not the initial action, so don't set default values }
def desc = getFieldById(DESCRIPTION); if (!desc.getValue()) { desc.setFormValue("test form"); }
스크립트는 심플해서 설명할 내용은 많지 않네요.
Create Issue 타입의 액션이 아니면 스크립트 실행 중지
getFieldById()를 가져오고 setFormValue() 함수를 통해 이슈 생성시 form에 기본 값을 입력
스크립트러너 가이드 문서에 있는 내용이 더 복잡한 내용을 담고 있어 다른 항목의 기본 값 설정시 참고하시면 좋을 것 같습니다. 기본 값 설정시 setFormValue() 함수에 string 값으로 설정해주시면 됩니다. 이미지와 스크립트가 다른 것은 설명 값이 있는지 유무를 확인하는 정도이니 설정시 참고부탁드립니다. 😀
설명 항목 기본 값 설정시 참고
설명 항목 기본 값 설정하면서 몇가지 참고할 만한 사항이 있습니다.
기본적으로 설명 항목은 HTML 값을 인식하기에 줄바꿈이 필요할 경우 <br/>을 입력해서 설정해주시면 됩니다.
h1, h2와 같은 항목도 마찬가지로 <h2>, <h3>로 입력해서 설정해주시면 됩니다.
만약 현재 Jira 시스템에 JEditor가 설치되어 사용중일 경우 JEditor 기능을 사용하여 기본 값을 설정해주셔야 합니다.
이건 ScriptRunner 기능보다는 JEditor 내용이니 다른 포스트에서 다뤄보겠습니다.
마무리
ScriptRunner 기능 중에 Behaviours 기능을 이용하여 기본 값 설정을 해보았습니다. 사실 다른 Jira 앱을 통해서 쉽게 설정할 수 있는데 ScriptRunner는 코드를 입력해야하는 점이 어려울 수 있겠다는 생각이 드네요. (그만큼 커스텀할 수 있는 것이 많아서 좋긴 하지만요. ㅎㅎ)
다른 항목에 대한 기본 값 설정은 가이드 문서를 참고해주시구요. 다른 유용한 기능이 있다면 포스팅해보겠습니다. 긴글 읽어주셔서 감사합니다. 👍
관련 포스트: Bulk remove change Jira issue links 위 포스트에서는 이슈에 걸려있는 모든 링크를 삭제하는 것을 공유드렸었습니다. 이번 포스트에서는 이슈에 걸려있는 링크 중에 특정 타입의 링크를 삭제하는 방법을 공유해보겠습니다.
이슈 - 이슈 링크
Jira에서 이슈와 이슈를 연결해주는 이슈 링크, 전의 포스트에서는 링크를 그냥 다 삭제하는 포스트였기에 자세히 다루지는 않았지만 이번 포스트에서는 링크 타입에 대해 알아야 정확하게 삭제할 수 있기에 조금 더 자세히 설명해보고자 합니다.
위와 같이 이슈 링크 속성에는 Name, Outward Description, Inward Description 항목이 있습니다.
한국어 버전으로는 이슈 링크 속성 이름이 명확한지 모르겠지만 다음과 같네요. 이름(Name), 가르키는 입장 설명(Outward Desc), 받는 입장 설명(Inward Desc)
Jira 시스템에 기본적으로 있는 이슈 링크 타입은 4개로 Blocks, Cloners, Duplicate, Relates 이렇게 구성되어 있습니다. 각각 링크 타입 항목들을 보면 이슈와 이슈를 연결했을 때 각 이슈에 보이는 링크의 이름이 다르게 보일 수 있도록 설정할 수 있습니다.
이슈 링크 타입을 확인했으니 이슈 링크 타입에 따라 삭제할 수 있게 되었습니다. 사실 위 링크 확인 스크립트 코드에서 타입과 inward/outward 만 확인해서 이슈 링크 삭제 함수만 사용하면 우리가 원하는 링크 삭제가 가능합니다.
이슈 링크 타입 확인 & 삭제
이슈 링크 타입을 확인하는 것 자체는 어렵지 않습니다. issueLinkObj.getIssueLinkType().getName()로 이름을 확인하면 되니까요. 다만 Inward, Outward 링크 타입을 확인해야하는데, 삭제할 때에 아래 옵션을 선택할 수 있도록 함수를 만들어야겠네요.
// issueLink - the issue link to remove // remoteUser - needed for creation of change items void removeIssueLink(IssueLink issueLink, ApplicationUser remoteUser)
최근 특정 Jira 이슈에 연결된 이슈들을 삭제해야하는 일이 있었습니다. (한 작업 이슈에 확인한 버그를 모두 링크를 달고 링크된 버그 이슈들을 보다가 링크 타입이 잘못된 것도 있는 등의 이슈가 있어 수정이 필요했습니다.) Bulk로 링크들을 삭제하는 기능이 있는지 찾아보았는데 없더군요. 그래서 스크립트러너로 가능한지 찾아보았습니다.
다행히, 당연하게도 이미 같은 고민을 했던 사람들이 있었고 아틀라시안 커뮤니티 채널에 해결방법이 있었습니다. 기본 Jira 기능에는 없지만 스크립트러너를 사용해서 가능하다는 것이었죠.
제가 현재 사용하고 있는 Jira 버전은 8.5여서 위 링크의 8.x 코드를 보면서 설명해보고자 합니다. (위 링크에 7.13 버전에서 사용할 수 있는 코드도 있으니 참고해서 쓰시면 됩니다.)
removeIssueLinks() 함수도 위 issueLinkManager에서 볼 수 있는데요.
1 2 3 4 5 6
int removeIssueLinks(Issue issue, ApplicationUser remoteUser) // Parameters: // issue - the Issue // remoteUser - the remote user // Returns: // The total number of issuelinks deleted.
모든 링크를 삭제하고자하는 이슈와 삭제할 때 필요한 사용자를 받아 함수가 동작합니다.
스크립트 결과
맨 처음 이미지를 보여드렸던 이슈의 키를 JQL로 입력하고 실행해보겠습니다. “key=PUBGTEST-112”로 입력하고 스크립트 콘솔에서 테스트 해보았습니다.
Timing: Elapsed: 4949 ms / CPU time: 531 ms 동작하는데 생각보다 시간이 많이 걸리긴 하네요. (약 5초 정도 걸리는 것으로 보이는데 링크 삭제가 오래걸리는 것인지 다른 것이 오래걸리는 것인지는 봐야겠습니다.)
실행 결과로는 이슈의 히스토리에 아래와 같이 남았습니다.
링크가 걸려있는 이슈의 모든 이슈 링크들이 삭제되었습니다! 👍
문제 해결!
제가 했던 하나의 이슈만 링크를 삭제할 수도 있고 JQL로 검색된 모든 이슈들의 모든 링크를 삭제할 수 있습니다. 다만 여기서 제가 원했던 것은 모든 링크의 삭제가 아니라 특정 타입의 링크들만 삭제하고 싶었던 것이어서 다음 포스트에서는 특정 링크 타입의 링크를 삭제하는 내용으로 한번 더 다뤄봐야겠습니다.
레이블과 변경전 레이블 배열, 변경후 레이블 배열을 받아 레이블이 변경되었는지 확인합니다. 추가적으로 isCaseSensitive 인수를 통해 레이블의 대소문자를 구분하여 확인합니다. 확인 후, 받은 유저들을 이슈의 와쳐 필드에 추가 또는 삭제합니다. (watchUsers(), unwatchUsers() 함수로) 이슈가 업데이트될 경우에만 호출되는 함수입니다. 생성시에는 아래에 있는 labelWatchCreated() 함수가 호출됩니다.
labelWatchCreated(label, users, isCaseSensitive)
이슈 생성시에는 변경된 사항이 없기에 issue Created 이벤트를 받아 처리해야했습니다. 추가 함수를 통해 이슈 생성시에도 와쳐가 추가될 수 있도록 만든 함수입니다.
labelWatch() 함수처럼 레이블과 유저를 받고 받은 레이블이 값에 있을 경우 유저를 이슈의 와쳐 필드에 추가합니다.
앞서 Label 값을 가져오는 것과 비교해서 달라진 것은 아래 코드와 addLabel() 함수 입니다. def user = ComponentAccessor.getUserManager().getUserByKey("pubg-helper"); 위 코드는 Label을 추가할 사용자를 결정하기 위해 사용자 객체를 아이디로 가져온 것입니다.
ScriptRunner의 Listener 기능에서 Label 수정/추가 기능을 사용할 때, 위 코드를 통해 업데이트하는 사용자를 동적으로 변경할 수 있습니다.
Label 값을 가져오고 추가/설정하는 것은 어렵지 않은 것 같습니다. (커스텀 필드 수정에 비해서요) 다만 골라서 삭제하는 기능은 없어 setLabels와 기존에 있는 값을 비교해서 삭제하는 것으로 삭제할 수는 있어 보이네요. (그렇게 어려워 보이지는 않을 것 같긴 하네요.)
저는 특정 이벤트가 발생할 경우 Label을 추가하는 정도로만 Listener에 Custom Listener를 추가하여 사용하고 있습니다. 이 Label을 사용하여 보드를 만들어 사용하시는 분이 있는데 잘 사용하고 있다고 하네요. :)