ํ ํ๋ก์ ํธ๋ฅผ ํ๋ค ๋ณด๋ฉด PR์ด ์ฌ๋ผ์จ ๋ค ๋ฆฌ๋ทฐ๊ฐ ์ง์ฐ๋๋ ๊ฒฝ์ฐ๊ฐ ์ข ์ข ์๋ค. ๋ฐ์ ์ผ์ ์์์ PR์ ๊น๋จน๊ธฐ๋ ํ๊ณ , ์ธ์ ๊น์ง ๋ฆฌ๋ทฐํด์ผ ํ๋์ง ๊ธฐ์ค์ด ์์ผ๋ฉด ์์ฐ์ค๋ฝ๊ฒ ํ์ง๋ถ์ง๋๊ธฐ๋ ํ๋ค. ์ด๋ฌํ ๋ฌธ์ ๋ฅผ ํ์์ ์ธ์งํ๊ณ , ์ฝ๋ ๋ฆฌ๋ทฐ์ 2์ผ์ด๋ผ๋ ์ ํ ์๊ฐ์ ๋๊ธฐ๋ก ํ๋ค. ํ์ง๋ง, ๊ฒฐ๊ตญ ์ด๊ฒ๋ ๋จธ๋ฆฌ๋ก ๊ธฐ์ตํด์ผ ํ๋ ๋ฌธ์ ์๋ค.
๊ทธ๋์ PR์ ๋ง๊ฐ์ผ์ ์๊ฐ์ ์ผ๋ก ํ์ํด์ฃผ๋ฉด ์ด๋จ๊น ์๊ฐํ๋ค. D-2, D-1, D-Day ๊ฐ์ ๋ผ๋ฒจ์ด PR์ ๋ถ์ด์์ผ๋ฉด ๋ฆฌ๋ทฐ์ด ์ ์ฅ์์๋ ๊ธฐ์ตํ์ง ์์๋ ์ฝ๊ฒ ํ์ธํ ์ ์๊ณ , ๋จ์ ๊ธฐ๊ฐ์ ๋ํด์ ๊ธด๋ฐํจ์ ๋๋ ์ ์์ ๊ฒ์ด๋ค.
๋์ ํ๊ธฐ ์ ์ ๋จผ์ ์ด๋ฏธ ์๋ ์ก์ ๋ผ์ด๋ธ๋ฌ๋ฆฌ๋ค์ ์ฐพ์๋ณด์๋ค. ์ ๋ ฅํ๋ ํ๋ณด๊ฐ ๋ค์ด๋ฒ์์ ๋ง๋ d-day-labeler์๋๋ฐ, ์ด๊ฑด ๋ง๊ฐ์ผ์ ๋ฐ๋ก ์ง์ ํ ์ ์์๊ณ ํน์ PR์ ๋ํด์ ๋ผ๋ฒจ์ ์ ๋ฐ์ดํธ ํ ์๊ฐ ์์๋ค. ์ฆ, ๋ชจ๋ PR์ ๋ํด์๋ง ๋ผ๋ฒจ ์ ๋ฐ์ดํธ๋ฅผ ์ง์ํ๋ ์คํฌ๋ฆฝํธ์๋ค.
์ฐ๋ฆฌ ํ์ ๋ง๊ฒ ์ปค์คํ ํ๋ ๋ฐฉ์์ด ํ์ํ๊ณ , ๊ทธ๋์ ์ง์ GitHub Actions๋ฅผ ๋ผ์ด๋ธ๋ฌ๋ฆฌ๋ก ๋ง๋ค์ด๋ณด์๋ค.
์๋ฐ๋ฅผ ์ ํํ ์ด์
๊ธฐ๋ณธ์ ์ผ๋ก ์ก์ ์คํฌ๋ฆฝํธ์ ๋ชจ๋ ๊ณผ์ ์ ์๋ฐ์คํฌ๋ฆฝํธ๋ ํ์ ์คํฌ๋ฆฝํธ๋ก ๋ง๋ค ์๋ ์๋ค. ๊ทธ๋ฆฌ๊ณ ์ด๋ฌํ ์ก์ ์คํฌ๋ฆฝํธ ๋ด์ ๋ชฐ์๋ฃ๋ ๋ฐฉ์์ด ์ซ๋ค๋ฉด GitHub Actions Toolkit์ ์ด์ฉํด GitHub Actions์ ํนํ๋ ํธ์ ๊ธฐ๋ฅ๊ณผ ํจ๊ป ๋ผ์ด๋ธ๋ฌ๋ฆฌ ํํ๋ก ๋ง๋ค์ด ์ฌ์ฉํ ์๋ ์๋ค.
ํ์ง๋ง, ๋ ๋ฐฉ์ ๋ชจ๋ ๊ณต์์ ์ผ๋ก ์๋ฐ์คํฌ๋ฆฝํธ์ ํ์ ์คํฌ๋ฆฝํธ๋ง ์ง์ํ๋ค. ๊ทผ๋ฐ ๋ณธ์ธ์ด ์๋ฐ์คํฌ๋ฆฝํธ๋ฅผ ์ ๋ชจ๋ฅด๊ธฐ๋ ํด์ ํ์ฌ ์ํฉ์์๋ ๊ฐ๋ ์ฑ๊ณผ ์ฌ์ฌ์ฉ์ฑ ์ธก๋ฉด์์ ๋งค์ฐ ๋นํจ์จ์ ์ด๋ผ๊ณ ํ๋จํ๋ค. ๊ทธ๋์ ์ต์ํ ์๋ฐ๋ฅผ ์ด์ฉํด ๋ง๋๋ ๋ฐฉ๋ฒ์ ์๊ฐํ๋ค.
์๋ฐ๋ ์ก์ ์ ๋ง๋ค๋ ค๋ฉด Docker container action ๋ฐฉ์์ ์จ์ผ ํ๋ค. ์ด๋ GitHub Actions runner์ JVM์ด ์์ผ๋ ์ง์ Docker ํ๊ฒฝ์ ๊ตฌ์ฑํ๊ณ , ๊ทธ ์์์ ์๋ฐ ์ฑ์ ์คํํ๋ ๋ฐฉ์์ด๋ค. ๋จ์ ์ด๊ธฐ๋ ํ๋ค๋ง ํด๋น ์์ ์ด ์๋๊ฐ ์ค์ํ ์ก์ ์ด ์๋๊ธฐ๋ ํด์ ์ถฉ๋ถํ ํธ๋ ์ด๋์คํ ๊ฐ๋ฅํ ์ง์ ์ด๋ผ๊ณ ์๊ฐํ๋ค.
๊ฐ๋ฐ ๊ณผ์
์๊ตฌ์ฌํญ์ ๋จผ์ ์ ๋ฆฌํด๋ณด์๋ค.
- PR์ด ์์ฑ๋ ๋ ์๋์ผ๋ก ๋ผ๋ฒจ์ ๋ถ์ธ๋ค.
- ๊ธฐ๋ณธ์ ์ผ๋ก D-2์ ๋ผ๋ฒจ์ ๋ถ์ธ๋ค.
- ๋งค์ผ ์์ ์ ๊ธฐ์กด์ ์กด์ฌํ๋ PR์ ๋ผ๋ฒจ ์ ๋ณด๋ฅผ ๊ฐ์ ธ์จ๋ค.
- ๋ผ๋ฒจ ์ ๋ณด๋ฅผ ํ ๋๋ก D-1, D-Day, Over-Due ๋ผ๋ฒจ๋ก ์
๋ฐ์ดํธ ํ๋ค.
- ์ด๋, ์ด๋ฏธ Over-Due๋ผ๋ฉด ๋ผ๋ฒจ์ ์
๋ฐ์ดํธ ํ์ง ์๋๋ค.
- D-n ๊ด๋ จ ๋ผ๋ฒจ์ด ์๋ค๋ฉด, D-2 ๋ผ๋ฒจ๋ก ์
๋ฐ์ดํธํ๋ค.
- PR์ ๋ฆฌ๋ทฐ๊ฐ ๋ฌ๋ฆฌ๋ฉด ๋ผ๋ฒจ์ D-2๋ก ์
๋ฐ์ดํธ ํ๋ค.
๊ฐ๋จํ๊ฒ ์๊ตฌ์ฌํญ์ ๋จผ์ ์ ๋ฆฌํ๊ณ ๋์ ์ฝ๋๋ฅผ ๋ฐ๋ก ์์ฑํ๊ธฐ๋ณด๋ค๋ ์์ฆ ์กฐ์ํธ๋์ '์ค๋ธ์ ํธ' ์ฑ ์ ๋ค์ ์ฝ๊ณ ์์ด์ '์ฑ ์ ์ฃผ๋ ์ค๊ณ(RDD)' ๊ด์ ์ผ๋ก ์ ๊ทผํด๋ณด์๋ค. ๋จผ์ , ๋์ฌ๋งํ ๋๋ฉ์ธ ์ฉ์ด๋ค์ ์ ๋ฆฌํด๋ณด์๋๋ฐ ์์ฃผ ๊ฐ๋จํ๋ค.
- PullRequest
- Label
์ด์ธ์๋ ๋ง๊ฐ์ผ, ์์ฑ์ผ, ๊ฒฝ๊ณผ์ผ ๊ฐ์ ์ฉ์ด๋ค๋ ์๊ฐํ๋๋ฐ, ๊ตฌํ ์ธ๋ถ์ฌํญ ๊ฐ์์ ์ ์ธํ๋ค. ๊ทธ ํ์๋ ์์คํ ์ด ์ํํด์ผ ํ ๋ฉ์์ง๋ฅผ ๋์ถํ๋ค.
PR์ ๋ผ๋ฒจ์ ๋ถ์ฌ๋ผ
์ด ๋ฉ์์ง๋ฅผ ๋ฐ์ ์ ์ ํ ์ญํ ์ PullRequest๋ค. PR์ด ์์ ์ ์ ๋ณด๋ฅผ ๊ฐ์ฅ ์ ์๊ณ ์์ผ๋๊น. ๊ทธ๋ฐ๋ฐ PR์ด ๋ฉ์์ง๋ฅผ ๋ฐ์์ ๋ ํผ์ ํ ์ ์๋ ๊ฒ๋ค์ด ์๋ค. ์ด๋ค ๋ผ๋ฒจ์ ๋ถ์ฌ์ผ ํ๋์ง ๊ณ์ฐํ๋ ์ฑ ์๊ณผ ์ค์ ๋ก ๋ผ๋ฒจ์ ๋ถ์ฐฉํ๋ ์ฑ ์์ด ํ์ํ๊ณ ์ด ์์ ์์ ์๋ก์ด ๊ฐ์ฒด๊ฐ ๋์ถ๋๋ค.
- LabelPolicy: ๊ธฐ์ค์ผ ๊ธฐ๋ฐ์ผ๋ก ๋ผ๋ฒจ์ ๊ณ์ฐํ๋ ์ฑ ์
- LabelAttacher: ์ค์ ๋ก ๋ผ๋ฒจ์ ๋ถ์ฐฉํ๋ ์ฑ ์
PR์ ์ด ๋ ๊ฐ์ง๋ฅผ ๊ฐ๊ฐ LabelPolicy์ LabelAttacher์๊ฒ ์์ํ๋ค. LabelAttacher๋ GitHub API๋ฅผ ํธ์ถํด์ผ ํ๋๋ฐ, ์ด๊ฑด ์ธํ๋ผ ๊ด์ฌ์ฌ๋ค. ๋๋ฉ์ธ์ด ์ธํ๋ผ๋ฅผ ์๋ฉด ์ ๋๋ ์ธํฐํ์ด์ค๋ก ๋ถ๋ฆฌํ๊ณ ๊ตฌํ์ฒด๋ฅผ ์ธ๋ถ๋ก ๋บ๋ค.

๊ทธ ๊ฒฐ๊ณผ ์ด๋ฌํ ํํ์ ๋๋ฉ์ธ ํ๋ ฅ ๊ตฌ์กฐ๋ฅผ ๋ง๋ค ์ ์์๋ค. ๊ทธ๋ฆฌ๊ณ PR์ ๊ฐ์ ธ์ ์ฒ๋ฆฌํ๋ ์กฐ์จ์ด ํ์ํ๋๋ฐ, ์ด ์ฑ ์์ LabelingService๊ฐ ๋งก์๋ค. PR ๋ชฉ๋ก์ ๊ฐ์ ธ์ค๋ ์ฑ ์์ PullRequestRepository ์ธํฐํ์ด์ค๋ก ๋ถ๋ฆฌํ๋ค.
์ฒ์์ ๋ง๊ฐ์ผ์ D-2๋ก ๊ณ ์ ํด๋์๋๋ฐ, ํ๋ง๋ค ์ฝ๋๋ฆฌ๋ทฐ ๋ฌธํ๊ฐ ๋ค๋ฅผ ์ ์๋ค๋ ์๊ฐ์ด ๋ค์๋ค. ์ด๋ค ํ์ 3์ผ, ์ด๋ค ํ์ 5์ผ์ ๊ธฐ์ค์ผ๋ก ์ผ์ ์๋ ์์ผ๋๊น. ๊ทธ๋์ deadline-days๋ฅผ ์ธ๋ถ์์ ๋ฐ๋๋ก ์ค๊ณ๋ฅผ ๋ฐ๊ฟจ๋ค. LabelPolicy ์์ฑ ์ ์ฃผ์ ๋ฐ๋ ๋ฐฉ์์ด๋ผ ๋๋ฉ์ธ ๋ก์ง์ ์ ํ ๊ฑด๋๋ฆฌ์ง ์์๋ ๋๋ค.
LabelPolicy labelPolicy = new LabelPolicy(Long.parseLong(deadline));
5์ผ๋ก ์ค์ ํ๋ฉด D-5 → D-4 → D-3 → D-2 → D-1 → D-Day → OVER-DUE ํ๋ฆ์ผ๋ก ๋์ํ๋ค.
Docker container action ๊ตฌ์ฑ
์๋ฐ ์ฑ์ GitHub Actions์์ ์คํํ๋ ค๋ฉด Docker ํ๊ฒฝ์ด ํ์ํ๋ค. ๋ฉํฐ ์คํ ์ด์ง ๋น๋๋ก ์ต์ข ์ด๋ฏธ์ง๋ฅผ ๊ฐ๋ณ๊ฒ ์ ์งํ๋ค.
FROM gradle:8.5-jdk21 AS build
WORKDIR /app
COPY . .
RUN gradle jar --no-daemon
FROM eclipse-temurin:21-jre-jammy
WORKDIR /app
COPY --from=build /app/build/libs/deadline-labeler-0.0.1.jar app.jar
ENTRYPOINT ["java", "-jar", "/app/app.jar"]
์ฒซ ๋ฒ์งธ ์คํ ์ด์ง์์ ๋น๋ํ๊ณ , ๋ ๋ฒ์งธ ์คํ ์ด์ง์์ jar๋ง ๊ฐ์ ธ์ ์คํํ๋ค. ์ต์ข ์ด๋ฏธ์ง์ Gradle์ด๋ ์์ค ์ฝ๋๊ฐ ํฌํจ๋์ง ์๋๋ค. ํ ๊ฐ์ง ๋น ์ง ๊ฒ ์์๋๋ฐ, jar ํ์คํฌ์ Main-Class๋ฅผ ๋ช ์ํ์ง ์์ผ๋ฉด java -jar๋ก ์คํํ ๋ ์ง์ ์ ์ ๋ชป ์ฐพ๋๋ค.
tasks.jar {
manifest {
attributes["Main-Class"] = "Main"
}
from(configurations.runtimeClasspath.get().map {
if (it.isDirectory) it else zipTree(it)
})
duplicatesStrategy = DuplicatesStrategy.EXCLUDE
}
action.yml
๊ตฌ์ฑ ์ก์ ์ ์ธํฐํ์ด์ค๋ฅผ ์ ์ํ๋ ํ์ผ์ด๋ค. ์ธ๋ถ์์ ์ด๋ค ๊ฐ์ ๋๊ธธ ์ ์๋์ง, ๊ทธ๋ฆฌ๊ณ ์ด๋ป๊ฒ ์คํ๋๋์ง๋ฅผ ๋ช ์ํ๋ค.
name: 'PR Deadline Labeler'
description: 'PR ์ฝ๋๋ฆฌ๋ทฐ ๋ง๊ฐ์ผ ๊ธฐ๋ฐ์ผ๋ก ๋ผ๋ฒจ์ ์๋ ๋ถ์ฐฉํฉ๋๋ค.'
inputs:
github-token:
required: true
description: 'Github ์ ๊ทผ์ ์ํ ํ ํฐ'
base-date:
required: false
description: '์
๋ฐ์ดํธ๋ฅผ ์ํ ๊ธฐ์ค์ผ์'
pr-number:
required: false
description: '์
๋ฐ์ดํธํ๊ณ ์ ํ๋ PR ๋ฒํธ'
deadline-days:
required: false
default: '2'
description: '์ฝ๋๋ฆฌ๋ทฐ ์ต๋ ๋ง๊ฐ์ผ ์ง์ '
runs:
using: 'docker'
image: 'Dockerfile'
runs.using: 'docker'๋ก ์ค์ ํ๋ฉด GitHub Actions๊ฐ ๋ ํฌ์งํ ๋ฆฌ์ ๋ช ์๋ Dockerfile์ ๋น๋ํ๊ณ ์คํํ๋ค. inputs์ ์ ์๋ ๊ฐ๋ค์ ์ปจํ ์ด๋ ์์์ 'INPUT_๋ณ์๋ช 'ํํ์ ํ๊ฒฝ๋ณ์๋ก ์ฃผ์ ๋๋ค. ์๋ฅผ ๋ค์ด 'github-token'์ 'INPUT_GITHUB-TOKEN'์ผ๋ก ์ ๊ทผํ ์ ์๋ค.
String token = System.getenv("INPUT_GITHUB-TOKEN");
์ํฌํ๋ก์ฐ ๊ตฌ์ฑ
์ธ ๊ฐ์ง ํธ๋ฆฌ๊ฑฐ์์ ๋์ํ๋๋ก ์๋ํ๋ค. ๊ฐ๊ฐ pull request ์์ฑ, cron ์ค์ผ์ค, pull request ๋ฆฌ๋ทฐ ๋ฑ๋ก ์์ ์ด๋ค.
on:
pull_request:
types: [opened]
schedule:
- cron: '0 15 * * *' # KST 00:00
pull_request_review:
types: [submitted]
๊ฐ ํธ๋ฆฌ๊ฑฐ๋ณ๋ก ์ ์ ํ baseDate๋ฅผ ์ก์ ์ ๋๊ฒจ์ค๋ค. ์ก์ ์ ํธ๋ฆฌ๊ฑฐ๋ฅผ ๋ชจ๋ฅด๊ณ baseDate๋ง ๋ฐ๋๋ค. ๊ถํ ์ค์ ๋ ๋น ๋จ๋ฆฌ๋ฉด ์ ๋๋ค. ๊ธฐ๋ณธ์ ์ผ๋ก GITHUB_TOKEN์ ์ฝ๊ธฐ ๊ถํ๋ง ์์ด์ ๋ผ๋ฒจ ์ฐ๊ธฐ๊ฐ ์ ๋๋ค.
permissions:
issues: write
pull-requests: write
๋ง์น๋ฉฐ
์ ๋ง ํ์ ํ์์ ์ํด์ ๊ฐ๋ฐ์ ํ๋ค๋ณด๋ ๋๊ฒ ์ฌ๋ฐ๋ ๊ฒฝํ์ด์๋ค. ๊ทธ๋ฆฌ๊ณ , ์ด๋ฌํ ์ก์ ์ผ๋ก ๊ฐ์ ธ์ฌ ๋ณํ๊ฐ ๊ต์ฅํ ๊ธฐ๋๊ฐ ๋๋ค. ๊ธฐํ๊ฐ ๋๋ค๋ฉด ์ด๋ฅผ ๋ฐ๋ก ๊ธ๋ก ์์ฑํ ์๊ฐ์ด๋ค.
๊ฐ๋ฐ ์๊ธฐ๋ฅผ ์ข ํ์๋ฉด ์ฑ ์ ์ฃผ๋ ์ค๊ณ๋ฅผ ์ ๋๋ก ํด๋ณธ ๊ฒ์ ์ฒ์์ธ๋ฐ ์ฑ ์ ์ฃผ๋ ์ค๊ณ๋ก ์์ํ๋ ์ฝ๋ ์์ฑ ์ ์ ๊ตฌ์กฐ๊ฐ ๋ช ํํด์ก๋ค. ๋๋ฉ์ธ์ด ์ธํ๋ผ๋ฅผ ์ ํ ๋ชจ๋ฅด๋ ๊ตฌ์กฐ๋ฅผ ์์ฐ์ค๋ฝ๊ฒ ๋ง๋ค ์ ์์๊ณ , ์ด๋์ ์ด๋ค ์ฝ๋๊ฐ ์์ด์ผ ํ๋์ง ๊ณ ๋ฏผํ ํ์๊ฐ ์์๋ค.
์กฐ์ํธ๋์ ์ฝ๋ ๋ฐฐ์น๋ฅผ ๋ฐ๋ก ๋๊ณ ๊ฐ์ฒด์งํฅ์ ๋งํ ์๋ ์๋ค ํ๋๋ฐ, ์ด๋ฒ์๋ ๋จ์ํ๊ธฐ ๋๋ฌธ์ ์์ฐ์ค๋ฝ๊ฒ ํ๋ ฅ์ ๊ตฌ์กฐ๊ฐ ๊ทธ๋๋ก ์ฝ๋์ ๋ฐฐ์น์ ์๋ง์ง ์์๋ ์ถ๋ค. ์ด์จ๋ ์ด๋ ๊ฒ ์๋ฐ์คํฌ๋ฆฝํธ ์์ด ์๋ฐ๋ก๋ GitHub Actions์ ๋ง๋ค ์ ์๋ค. Docker container action์ด๋ผ๋ ๋ฐฉ์์ด ์์ผ๋๊น.
ํ์ฌ ๊ฐ์ข ๋ฒ๊ทธ๋ฅผ ์์ ํ๊ณ v1.0.0๊ฐ ๋ฆด๋ฆฌ์ฆ๋๊ณ , ๋ค๋ฅธ ๋ ํฌ์์ ์๋์ฒ๋ผ ๋ฐ๋ก ์ฌ์ฉํ ์ ์๋ค.
- uses: kkiseug/pr-deadline-labeler@v1
with:
github-token: ${{ secrets.GITHUB_TOKEN }}
base-date: ${{ github.event.pull_request.created_at }}
pr-number: ${{ github.event.pull_request.number }}
deadline-days: 5
GitHub - kkiseug/pr-deadline-labeler: PR์ D-Day ๋ผ๋ฒจ์ ๋ฑ๋ก ๋ฐ ๊ด๋ฆฌํด์ฃผ๋ ์ก์ ๋ผ์ด๋ธ๋ฌ๋ฆฌ
PR์ D-Day ๋ผ๋ฒจ์ ๋ฑ๋ก ๋ฐ ๊ด๋ฆฌํด์ฃผ๋ ์ก์ ๋ผ์ด๋ธ๋ฌ๋ฆฌ. Contribute to kkiseug/pr-deadline-labeler development by creating an account on GitHub.
github.com
'๊ฐ๋ฐ' ์นดํ ๊ณ ๋ฆฌ์ ๋ค๋ฅธ ๊ธ
| Fielding์ด ๋งํ๋ ์ง์ง REST API (0) | 2026.03.20 |
|---|---|
| 1๊ฐ์ ์ฌ๊ณ ๊ฐ ์์ ๋ ๋์์ 100๋ช ์ ์ฌ์ฉ์๊ฐ ์์ฒญํ๋ฉด? (2) | 2026.03.17 |
| ๊ฐ๋น์ง ์ปฌ๋ ํฐ (0) | 2026.02.09 |
| ํ๋ ฅ, ์ฑ ์, ์ญํ (0) | 2026.02.08 |
| ์ค๋ธ์ ํธ 1-2์ฅ ์๊ฐ ์ ๋ฆฌ ๋ฐ DND ๊ณ ๋ฏผ (3) | 2026.02.07 |