Created
August 11, 2022 07:36
-
-
Save supernovel/0d23db57d0077b8e3d4bfaba17ab8db4 to your computer and use it in GitHub Desktop.
커밋에 있는 지라 이슈를 기반으로 변경 사항 내용을 만든다.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import "https://deno.land/x/dotenv@v3.2.0/load.ts"; | |
import * as Line from "https://deno.land/x/line@v1.0.1/mod.ts"; | |
import uniq from "https://esm.sh/lodash@4.17.21/uniq?no-dts"; | |
import lodashGet from "https://esm.sh/lodash@4.17.21/get?no-dts"; | |
import * as log from "https://deno.land/std/log/mod.ts"; | |
import { render } from "https://deno.land/x/mustache_ts@v0.4.1.1/mustache.ts"; | |
await log.setup({ | |
handlers: { | |
stringFmt: new log.handlers.FileHandler("DEBUG", { | |
filename: "./changelog_builder_log.txt", | |
formatter: "[{levelName}] {msg}", | |
}), | |
}, | |
loggers: { | |
default: { | |
level: "DEBUG", | |
handlers: ["stringFmt"], | |
}, | |
}, | |
}); | |
const logger = log.getLogger(); | |
const defaultOutputTemplate = ` | |
{{#issues}} | |
- {{id}} {{summary}} | |
{{/issues}} | |
`; | |
// 지라 이슈 타입 정의 | |
class JiraIssue { | |
id!: string; | |
summary!: string | |
// deno-lint-ignore ban-types | |
static fromJson(json: object): JiraIssue { | |
const issue = new JiraIssue(); | |
issue.id = lodashGet(json, "key"); | |
issue.summary = lodashGet(json, "fields.summary"); | |
return issue; | |
} | |
} | |
// 커밋 로그 가져오기 | |
const getCommitLogs = async (startCommitHash: string): Promise<string> => { | |
const process = Deno.run({ | |
cmd: ["git", "--no-pager", "log", `${startCommitHash}..HEAD`], | |
stdout: "piped", | |
}); | |
const stdout = new TextDecoder().decode(await process.output()); | |
process.close(); | |
return stdout; | |
} | |
// 커밋 로그로 부터 지라 이슈 넘버 가져오기 | |
const getJiraIssueIdsFromCommitLogs = (commitLogs: string): string[] => { | |
const matchedIterator = commitLogs.matchAll(/[A-Za-z]+\-\d+/g); | |
const matchedList = [...matchedIterator].flat().map((item) => item.toUpperCase()); | |
const uniqueIssueKey: string[] = uniq(matchedList); | |
return uniqueIssueKey.sort(); | |
} | |
// 지라 이슈 정보 가져오기 | |
const getJiraIssueFromServer = async (jiraIssueId: string, { | |
jiraApiUsername, | |
jiraApiToken | |
}: { | |
jiraApiUsername: string, | |
jiraApiToken: string | |
}): Promise<JiraIssue> => { | |
const jiraApiKey = btoa(`${jiraApiUsername}:${jiraApiToken}`); | |
const response = await fetch(`https://lucentblock.atlassian.net/rest/api/latest/issue/${jiraIssueId}`, { | |
headers: { | |
"Authorization": `Basic ${jiraApiKey}` | |
} | |
}); | |
const body = await response.json(); | |
return JiraIssue.fromJson(body); | |
} | |
// 메인 커멘드 정의 | |
class MainCommand extends Line.MainCommand { | |
public signature = "changelog-builder"; | |
public options = { | |
"-ch [value], --commit-hash [value]": "가져올 커밋 메세지의 시작점", | |
"--jira-api-username [value]": "지라 API 유저 이메일", | |
"--jira-api-token [value]": "지라 API 유저 토큰", | |
}; | |
public async handle(): Promise<void> { | |
const startCommitHash = this.option("--commit-hash") || Deno.env.get("CB_COMMIT_HASH"); | |
const jiraApiUsername = this.option("--jira-api-username") || Deno.env.get("CB_JIRA_API_USERNAME"); | |
const jiraApiToken = this.option("--jira-api-token") || Deno.env.get("CB_JIRA_API_TOKEN"); | |
if(startCommitHash == null) { | |
logger.error(` | |
가져올 커밋 시작점인 --commit-hash 를 설정해야 합니다. | |
`); | |
return; | |
} | |
if(jiraApiUsername == null) { | |
logger.error(` | |
--jira-api-username 또는 CB_JIRA_API_USERNAME 환경 변수 설정이 필요합니다. | |
보통 지라 계정 이메일로 설정 하시면 됩니다. | |
`); | |
return; | |
} | |
if(jiraApiToken == null) { | |
logger.error(` | |
--jira-api-token 또는 CB_JIRA_API_TOKEN 환경 변수 설정이 필요합니다. | |
아래 링크에서 발급받으시면 됩니다. | |
https://id.atlassian.com/manage-profile/security/api-tokens | |
`); | |
return; | |
} | |
const commitLogs = await getCommitLogs(startCommitHash as string); | |
const jiraIssueIds = await getJiraIssueIdsFromCommitLogs(commitLogs); | |
const result = await Promise.all(jiraIssueIds.map(async (jiraIssueId) => { | |
try{ | |
return await getJiraIssueFromServer(jiraIssueId, { | |
jiraApiUsername: jiraApiUsername as string, | |
jiraApiToken: jiraApiToken as string, | |
}); | |
}catch(error){ | |
logger.error(`Request ${jiraIssueId} issue error. => ${error.message}`); | |
} | |
})); | |
const jiraIssueList = result.filter((item) => item != null) as JiraIssue[]; | |
console.log( | |
render( | |
defaultOutputTemplate, | |
{ | |
issues: jiraIssueList | |
}, | |
), | |
); | |
} | |
} | |
// cli 설정 정의 | |
const cli = new Line.CLI({ | |
name: "Changelog builder CLI", | |
description: ` | |
commit log를 기준으로 jira 이슈 키를 가져와 CHANGELOG.md 파일을 업데이트 합니다. | |
--jira-api-username, --jira-api-token 옵션을 통해 Jira API 인증 정보를 설정 해야합니다. | |
또는 environment 변수를 통해서도 API 인증 정보 설정이 가능합니다. | |
API 인증 정보 발급: https://id.atlassian.com/manage-profile/security/api-tokens | |
`, | |
version: "v1.0.0", | |
command: MainCommand, | |
}); | |
cli.run(); |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment