C# - JIRA에 등록된 Project의 Version 항목 추가하는 방법
사내에서 이슈 관리 시스템인 JIRA를 사용하면서 불편한 점이 하나 나왔는데요. 이슈 생성할 때, Version 항목이 미리 등록되어 있지 않으면 그걸 또 등록하러 가야 한다는 것입니다. 이런 불편함을, 제품의 빌드 스크립트에서 버전을 JIRA에 등록하는 방법으로 해결할 수 있습니다. 그리고 이를 위해 JIRA REST API를 사용하게 된 것입니다.
C# - JIRA REST API 사용 정리
; https://www.sysnet.pe.kr/2/0/11566
자, 그럼 시작해 볼까요? ^^
우선, 해당 프로젝트에 등록된 모든 버전을 가져오는 version API를,
/rest/api/2/project/{projectIdOrKey}/versions
; https://docs.atlassian.com/software/jira/docs/api/REST/6.1.4/#d2e231
다음과 같이 작성할 수 있습니다.
public async Task<string> GetVersions(string projectKey)
{
string url = _baseUrl + $"project/{projectKey}/versions";
HttpResponseMessage hrm = await _httpClient.GetAsync(url);
string text = await hrm.Content.ReadAsStringAsync();
return text;
}
출력 결과로부터
json2csharp을 통해 다음과 같은 Entity 클래스를 구하고,
public class Version /* RootObject */
{
public string self { get; set; }
public string id { get; set; }
public string name { get; set; }
public bool archived { get; set; }
public bool released { get; set; }
public string releaseDate { get; set; }
public string userReleaseDate { get; set; }
public int projectId { get; set; }
public bool? overdue { get; set; }
public string description { get; set; }
public string startDate { get; set; }
public string userStartDate { get; set; }
}
API를 다시 다음과 같은 코드로 바꿀 수 있습니다.
public async Task<Version[]> GetVersions(string projectKey)
{
string url = _baseUrl + $"project/{projectKey}/versions";
HttpResponseMessage hrm = await _httpClient.GetAsync(url);
string text = await hrm.Content.ReadAsStringAsync();
Version [] versionList = Newtonsoft.Json.JsonConvert.DeserializeObject<Version[]>(text);
return versionList;
}
이를 기반으로, "버전 이름"에 해당하는 항목이 등록되어 있는지 알 수 있는 API를 제공할 수 있습니다.
public async Task<Version> GetVersionByName(string projectKey, string versionName)
{
Version [] versions = await GetVersions(projectKey);
return versions.FirstOrDefault((e) => e.name == versionName);
}
만약 없다면 새롭게 등록해야 하는데요, 이를 위한 REST API는 다음과 같습니다.
/rest/api/2/version
; https://docs.atlassian.com/software/jira/docs/api/REST/6.1.4/#d2e3548
이때 POST로 Json 데이터를 보내야 하는데 다음과 같은 형식입니다.
{
"description": "An excellent version",
"name": "New Version 1",
"archived": false,
"released": true,
"releaseDate": "2010-07-06",
"userReleaseDate": "6/Jul/2010",
"project": "PXA",
"projectId": 10000
}
POST 데이터의 예제가 저렇게 나오긴 하지만 약간의 규칙이 있습니다.
- releaseDate와 userReleaseDate는 동시에 보낼 수 없음. (즉, releaseDate만 보내면 됨)
- projectId가 있으면 project 항목은 안 보내도 됨
- 만약 startDate 필드가 있다면 반드시 releaseDate 날짜 보다 이전이어야 함.
여기서 애매한 것이, "projectId" 필드입니다. 보통 "project"는 JIRA 웹 사이트에서 이슈 번호를 통해 쉽게 인지를 하고 있지만 projectId의 경우에는 모르는 경우가 많습니다. 따라서 projectKey로 Id를 구해주는 API를 하나 만들어 두는 것이 좋습니다.
/rest/api/2/project/{projectIdOrKey}
; https://docs.atlassian.com/software/jira/docs/api/REST/6.1.4/#d2e208
public async Task<Project> GetProjectByKey(string projectKey)
{
string url = _baseUrl + $"project/{projectKey}";
HttpResponseMessage hrm = await _httpClient.GetAsync(url);
string text = await hrm.Content.ReadAsStringAsync();
Project project = Newtonsoft.Json.JsonConvert.DeserializeObject<Project>(text);
return project;
}
이쯤에서 우리가 구현하고 싶은 코드를 정리해 보면 다음과 같습니다.
{
string newVersionName = "myapp-1.0.1";
string projectKey = "myProject";
Project project = await jira.GetProjectByKey(projectKey);
if (project == null)
{
Console.WriteLine("NO Project: " + projectKey);
return;
}
JiraEntity.Version result = await jira.GetVersionByName(projectKey, newVersionName);
if (result == null)
{
// 기존에 등록된 버전이 없다면 신규 등록
JiraEntity.Version version = new JiraEntity.Version();
version.name = newVersionName;
version.projectId = Int32.Parse(project.id);
version.description = versionDesc;
version.startDate = DateTime.Now.ToString("yyyy-MM-dd");
SetReleaseDate(version, releaseDate);
result = await jira.CreateVersion(version);
if (result != null)
{
return;
}
}
else
{
// 기존에 등록된 버전이 있다면 업데이트
result.description = versionDesc;
SetReleaseDate(result, releaseDate);
result = await jira.UpdateVersion(result);
if (result != null)
{
return;
}
}
}
static void SetReleaseDate(JiraEntity.Version version, string releaseDate)
{
if (releaseDate == null)
{
return;
}
version.releaseDate = releaseDate;
version.released = true;
}
이를 위해 새로운 버전을 등록하는 CreateVersion 메서드는 이렇게 만들어 주고,
public async Task<JiraEntity.Version> CreateVersion(JiraEntity.Version version)
{
string url = _baseUrl + "version";
string postData = Newtonsoft.Json.JsonConvert.SerializeObject(version);
StringContent content = new StringContent(postData, Encoding.UTF8, "application/json");
HttpResponseMessage hrm = await _httpClient.PostAsync(url, content);
string text = await hrm.Content.ReadAsStringAsync();
JiraEntity.Version registeredVersion = Newtonsoft.Json.JsonConvert.DeserializeObject<JiraEntity.Version>(text);
return registeredVersion;
}
기존 버전 정보를 업데이트하는 UpdateVersion 메서드는 다음의 REST API를,
/rest/api/2/version/{id}
; https://docs.atlassian.com/software/jira/docs/api/REST/6.1.4/#d2e3578
PUT으로 호출하면 되므로 이렇게 만들어 줍니다.
public async Task<JiraEntity.Version> UpdateVersion(JiraEntity.Version version)
{
string url = _baseUrl + "version/" + version.id;
MakeVersionPutValid(version);
string postData = Newtonsoft.Json.JsonConvert.SerializeObject(version);
StringContent content = new StringContent(postData, Encoding.UTF8, "application/json");
HttpResponseMessage hrm = await _httpClient.PutAsync(url, content);
string text = await hrm.Content.ReadAsStringAsync();
JiraEntity.Version registeredVersion = Newtonsoft.Json.JsonConvert.DeserializeObject<JiraEntity.Version>(text);
return registeredVersion;
}
뭐... 이 정도까지 했으니, 이제 JIRA 정도는 자유자재로 다루실 수 있겠죠?!!! ^^
(
첨부 파일은 이 글의 예제 코드를 포함합니다.)
참고로, REST API에 Post 호출을 했는데 다음과 같은 "HTTP Status 415 - Unsupported Media Type" 오류가 반환된다면?
<html><head><title>Apache Tomcat/7.0.29 - Error report</title><style><!--H1 {font-family:Tahoma,Arial,sans-serif;color:white;background-color:#525D76;font-size:22px;} H2 {font-family:Tahoma,Arial,sans-serif;color:white;background-color:#525D76;font-size:16px;} H3 {font-family:Tahoma,Arial,sans-serif;color:white;background-color:#525D76;font-size:14px;} BODY {font-family:Tahoma,Arial,sans-serif;color:black;background-color:white;} B {font-family:Tahoma,Arial,sans-serif;color:white;background-color:#525D76;} P {font-family:Tahoma,Arial,sans-serif;background:white;color:black;font-size:12px;}A {color : black;}A.name {color : black;}HR {color : #525D76;}--></style> </head><body><h1>HTTP Status 415 - Unsupported Media Type</h1><HR size="1" noshade="noshade"><p><b>type</b> Status report</p><p><b>message</b> <u>Unsupported Media Type</u></p><p><b>description</b> <u>The server refused this request because the request entity is in a format not supported by the requested resource for the requested method (Unsupported Media Type).</u></p><HR size="1" noshade="noshade"><h3>Apache Tomcat/7.0.29</h3></body></html>
Post 요청 헤더에 "application/json"을 설정하지 않아서 그런 것입니다.
[이 글에 대해서 여러분들과 의견을 공유하고 싶습니다. 틀리거나 미흡한 부분 또는 의문 사항이 있으시면 언제든 댓글 남겨주십시오.]