Skip to content

[Feature] 지라 연동 중복 해결 최종 확인 #7

[Feature] 지라 연동 중복 해결 최종 확인

[Feature] 지라 연동 중복 해결 최종 확인 #7

name: Sync GitHub Issue To Jira
on:
issues:
types: [labeled]
permissions:
issues: write
jobs:
create-jira-issue:
runs-on: ubuntu-latest
steps:
- name: Decide whether to create a Jira issue
id: prepare
uses: actions/github-script@v7
with:
script: |
const validTypes = {
bug: "Bug",
feature: "Story",
maintenance: "Task"
};
const issue = context.payload.issue;
const labels = issue.labels.map((label) => label.name.toLowerCase());
const issueTypeCandidates = [
issue.issue_type?.name,
issue.issueType?.name,
issue.type?.name,
issue.type_name,
]
.filter(Boolean)
.map((name) => String(name).toLowerCase());
let matchedLabel = null;
if (context.payload.action === "labeled") {
const currentLabel = context.payload.label.name.toLowerCase();
if (validTypes[currentLabel]) {
matchedLabel = currentLabel;
}
}
if (!matchedLabel) {
matchedLabel = Object.keys(validTypes).find((label) => labels.includes(label)) ?? null;
}
if (!matchedLabel) {
matchedLabel =
Object.keys(validTypes).find((label) => issueTypeCandidates.includes(label)) ?? null;
}
if (!matchedLabel) {
core.info(`No matching label or issue type found. labels=${labels.join(",")} issueTypes=${issueTypeCandidates.join(",")}`);
core.setOutput("should_create", "false");
return;
}
const comments = await github.paginate(github.rest.issues.listComments, {
owner: context.repo.owner,
repo: context.repo.repo,
issue_number: issue.number,
per_page: 100,
});
const existingJiraComment = comments.find((comment) =>
comment.body.includes("Jira issue:")
);
if (existingJiraComment) {
core.info("Jira issue already linked. Skipping.");
core.setOutput("should_create", "false");
return;
}
core.setOutput("should_create", "true");
core.setOutput("jira_issue_type", validTypes[matchedLabel]);
- name: Resolve Jira project
id: resolve_project
if: steps.prepare.outputs.should_create == 'true'
env:
JIRA_BASE_URL: ${{ secrets.JIRA_BASE_URL }}
JIRA_EMAIL: ${{ secrets.JIRA_EMAIL }}
JIRA_API_TOKEN: ${{ secrets.JIRA_API_TOKEN }}
JIRA_PROJECT_KEY: ${{ secrets.JIRA_PROJECT_KEY }}
run: |
if [ -z "$JIRA_BASE_URL" ]; then echo "Error: JIRA_BASE_URL is empty"; exit 1; fi
if [ -z "$JIRA_PROJECT_KEY" ]; then echo "Error: JIRA_PROJECT_KEY is empty"; exit 1; fi
response=$(mktemp)
http_code=$(curl -sS -o "$response" -w "%{http_code}" \
--request GET \
--url "$JIRA_BASE_URL/rest/api/2/project/$JIRA_PROJECT_KEY" \
--user "$JIRA_EMAIL:$JIRA_API_TOKEN" \
--header "Accept: application/json")
if [ "$http_code" -lt 200 ] || [ "$http_code" -ge 300 ]; then
echo "Failed to resolve Jira project '$JIRA_PROJECT_KEY' with status $http_code"
cat "$response"
exit 1
fi
jira_project_id=$(jq -r '.id' "$response")
jira_project_key=$(jq -r '.key' "$response")
if [ -z "$jira_project_id" ] || [ "$jira_project_id" = "null" ]; then
echo "Jira project id not found while resolving project '$JIRA_PROJECT_KEY'"
cat "$response"
exit 1
fi
echo "Resolved Jira project key: $jira_project_key"
echo "jira_project_id=$jira_project_id" >> "$GITHUB_OUTPUT"
- name: Create Jira issue
id: create_jira
if: steps.prepare.outputs.should_create == 'true'
env:
JIRA_BASE_URL: ${{ secrets.JIRA_BASE_URL }}
JIRA_EMAIL: ${{ secrets.JIRA_EMAIL }}
JIRA_API_TOKEN: ${{ secrets.JIRA_API_TOKEN }}
JIRA_PROJECT_ID: ${{ steps.resolve_project.outputs.jira_project_id }}
JIRA_ISSUE_TYPE: ${{ steps.prepare.outputs.jira_issue_type }}
GITHUB_REPOSITORY_NAME: ${{ github.repository }}
GITHUB_ISSUE_NUMBER: ${{ github.event.issue.number }}
GITHUB_ISSUE_TITLE: ${{ github.event.issue.title }}
GITHUB_ISSUE_BODY: ${{ github.event.issue.body }}
GITHUB_ISSUE_URL: ${{ github.event.issue.html_url }}
GITHUB_ISSUE_AUTHOR: ${{ github.event.issue.user.login }}
run: |
normalized_issue_body=$(printf '%s\n' "$GITHUB_ISSUE_BODY" | perl -ne '
BEGIN {
$in_code_block = 0;
}
if (/^```([[:alnum:]_+-]+)?\s*$/) {
if (!$in_code_block) {
$language = defined $1 ? $1 : "";
if ($language ne "") {
print "{code:$language}\n";
} else {
print "{code}\n";
}
$in_code_block = 1;
} else {
print "{code}\n";
$in_code_block = 0;
}
next;
}
if (!$in_code_block) {
s/^##### /h4. /;
s/^#### /h3. /;
s/^### /h2. /;
s/^## /h1. /;
s/^# /h1. /;
}
print;
')
description=$(printf '%s\n' \
"|| 항목 || 내용 ||" \
"| 저장소 | $GITHUB_REPOSITORY_NAME |" \
"| 이슈 번호 | #$GITHUB_ISSUE_NUMBER |" \
"| 작성자 | $GITHUB_ISSUE_AUTHOR |" \
"" \
"$normalized_issue_body")
payload=$(jq -n \
--arg projectId "$JIRA_PROJECT_ID" \
--arg issueType "$JIRA_ISSUE_TYPE" \
--arg summary "$GITHUB_ISSUE_TITLE" \
--arg description "$description" \
'{
fields: {
project: { id: $projectId },
issuetype: { name: $issueType },
summary: $summary,
description: $description,
labels: ["Server"]
}
}')
response=$(mktemp)
http_code=$(curl -sS -o "$response" -w "%{http_code}" \
--request POST \
--url "$JIRA_BASE_URL/rest/api/2/issue" \
--user "$JIRA_EMAIL:$JIRA_API_TOKEN" \
--header "Accept: application/json" \
--header "Content-Type: application/json" \
--data "$payload")
if [ "$http_code" -lt 200 ] || [ "$http_code" -ge 300 ]; then
echo "Jira issue creation failed with status $http_code"
cat "$response"
exit 1
fi
jira_key=$(jq -r '.key' "$response")
if [ -z "$jira_key" ] || [ "$jira_key" = "null" ]; then
echo "Jira issue key not found in response"
cat "$response"
exit 1
fi
echo "jira_key=$jira_key" >> "$GITHUB_OUTPUT"
echo "jira_url=$JIRA_BASE_URL/browse/$jira_key" >> "$GITHUB_OUTPUT"
- name: Add GitHub issue web link to Jira
if: steps.create_jira.outputs.jira_key != ''
env:
JIRA_BASE_URL: ${{ secrets.JIRA_BASE_URL }}
JIRA_EMAIL: ${{ secrets.JIRA_EMAIL }}
JIRA_API_TOKEN: ${{ secrets.JIRA_API_TOKEN }}
JIRA_KEY: ${{ steps.create_jira.outputs.jira_key }}
GITHUB_ISSUE_NUMBER: ${{ github.event.issue.number }}
GITHUB_ISSUE_URL: ${{ github.event.issue.html_url }}
run: |
payload=$(jq -n \
--arg url "$GITHUB_ISSUE_URL" \
--arg title "GitHub Issue #$GITHUB_ISSUE_NUMBER" \
'{
object: {
url: $url,
title: $title
}
}')
response=$(mktemp)
http_code=$(curl -sS -o "$response" -w "%{http_code}" \
--request POST \
--url "$JIRA_BASE_URL/rest/api/2/issue/$JIRA_KEY/remotelink" \
--user "$JIRA_EMAIL:$JIRA_API_TOKEN" \
--header "Accept: application/json" \
--header "Content-Type: application/json" \
--data "$payload")
if [ "$http_code" -lt 200 ] || [ "$http_code" -ge 300 ]; then
echo "Failed to add Jira remote link with status $http_code"
cat "$response"
exit 1
fi
- name: Comment Jira link on GitHub issue
if: steps.create_jira.outputs.jira_key != ''
uses: actions/github-script@v7
env:
JIRA_KEY: ${{ steps.create_jira.outputs.jira_key }}
JIRA_URL: ${{ steps.create_jira.outputs.jira_url }}
with:
script: |
await github.rest.issues.createComment({
owner: context.repo.owner,
repo: context.repo.repo,
issue_number: context.issue.number,
body: `Jira issue: [${process.env.JIRA_KEY}](${process.env.JIRA_URL})`,
});