Jiraμ Gitμ μ°λνλ μν¬νλ‘μ° μλν CLI λꡬ
κ°λ°νμμ λ°λ³΅μ μΌλ‘ κ²ͺλ λ¬Έμ λ€:
- PMμ΄ Jira ν°μΌ ν λΉ β κ°λ°μκ° μλμΌλ‘ ν°μΌ νμΈ
- ν°μΌ λ²νΈλ‘ λΈλμΉ μμ± β μλμΌλ‘ Jira μν λ³κ²½
- PR μμ± μ Jira λ§ν¬ 볡μ¬/λΆμ¬λ£κΈ°
- PR λ¨Έμ§ ν Jira μν μλ μ λ°μ΄νΈ
- λ‘컬 λΈλμΉ μ 리
μ΄ λͺ¨λ κ³Όμ μ΄ μκ°μ΄ λ§μ΄ μμλ©λλ€.
- μλ λΈλμΉ μμ±: Jira ν°μΌ λ²νΈλ‘ μλ λΈλμΉ μμ±
- μλ μν λκΈ°ν: μμ μμ/PR/λ¨Έμ§ μ Jira μν μλ μ λ°μ΄νΈ
- PR ν νλ¦Ώ μλν: Jira λ§ν¬μ ν°μΌ μ 보 μλ ν¬ν¨
- λΈλμΉ μλ μ 리: λ¨Έμ§λ λΈλμΉ μλ κ°μ§ λ° μμ
1. PM/κ°λ°μ Jira ν°μΌ ν λΉ
β
2. κ°λ°μ: jgf tickets (ν°μΌ μ‘°ν)
β
3. κ°λ°μ: jgf start EM-XXX (λΈλμΉ μμ±)
β μλ: Git λΈλμΉ μμ±
β μλ: Jira μν "In Progress"λ‘ λ³κ²½
β
4. κ°λ°μ: μ½λ© μμ
β
5. κ°λ°μ: jgf pr (PR μμ±)
β μλ: PR μ λͺ©μ ν°μΌ λ²νΈ ν¬ν¨
β μλ: PR λ³Έλ¬Έμ Jira λ§ν¬ μΆκ°
β
6. ν: μ½λ 리뷰 & λ¨Έμ§
β
7. κ°λ°μ: jgf sync (λκΈ°ν)
β μλ: λ¨Έμ§λ λΈλμΉ κ°μ§
β μλ: Jira μν "Done"μΌλ‘ λ³κ²½
β μλ: λ‘컬 λΈλμΉ μμ
Jira μν: To Do β In Progress β Done
Git λΈλμΉ: μμ β EM-XXX μμ± β PR β λ¨Έμ§ β μμ
- Git
- Jira κ³μ λ° API ν ν°
- GitHub κ³μ λ° Personal Access Token
# crates.ioμμ μ€μΉ
cargo install jgf
# λλ μμ€μμ λΉλ
git clone https://github.com/jaehafe/jgf.git
cd jgf
cargo install --path .
# macOS (Apple Silicon)
curl -L https://github.com/jaehafe/jgf/releases/latest/download/jgf-darwin-aarch64 -o jgf
chmod +x jgf
sudo mv jgf /usr/local/bin/
# macOS (Intel)
curl -L https://github.com/jaehafe/jgf/releases/latest/download/jgf-darwin-x64 -o jgf
chmod +x jgf
sudo mv jgf /usr/local/bin/
# Linux
curl -L https://github.com/jaehafe/jgf/releases/latest/download/jgf-linux-x64 -o jgf
chmod +x jgf
sudo mv jgf /usr/local/bin/
κ° νλ‘μ νΈ λ£¨νΈμμ μ€ν:
jgf init
μ΄ λͺ λ Ήμ λ κ°μ νμΌμ μμ±ν©λλ€:
{
"project": "your-project-name",
"jira": {
"url": "https://your-company.atlassian.net",
"project": "EM",
"username": "your-email@company.com" // Optional
},
"github": {
"owner": "YourOrg",
"repo": "your-repo"
},
"defaultBranch": "develop",
"prTemplate": { // Optional
"path": "custom/pr_template.md" // λλ
// "content": "μ§μ ν
νλ¦Ώ λ΄μ©..."
}
}
JIRA_TOKEN=your-jira-api-token
GITHUB_TOKEN=ghp_your_github_token
Jira API Token:
- Atlassian Account Settings μ μ
- "Create API token" ν΄λ¦
- ν ν° μ΄λ¦ μ λ ₯ ν μμ±
- ν ν° λ³΅μ¬νμ¬
.env
μ μ μ₯
GitHub Personal Access Token:
- GitHub Settings β Developer settings β Personal access tokens
- "Generate new token (classic)" ν΄λ¦
- κΆν μ ν:
repo
(μ 체) - ν ν° μμ± λ° λ³΅μ¬
# ν λΉλ λͺ¨λ ν°μΌ μ‘°ν
jgf tickets
# μνλ³ νν°λ§
jgf tickets --status "In Progress"
# μ΅λ κ°μ μ ν
jgf tickets --limit 10
μΈν°λν°λΈ λͺ¨λ:
- ν°μΌ λͺ©λ‘μμ μ ν
- "λΈλμΉ μμ± λ° In Progressλ‘ λ³κ²½" μ ν
- μλμΌλ‘ λΈλμΉ μμ± λ° Jira μν μ λ°μ΄νΈ
jgf start EM-100
μλ μν μμ :
- β develop λΈλμΉμμ μ΅μ λ³κ²½μ¬ν pull
- β
EM-100
λΈλμΉ μμ± λ° μ²΄ν¬μμ - β Jira ν°μΌμ "In Progress"λ‘ λ³κ²½
jgf pr
μλ μν μμ :
- β νμ¬ λΈλμΉμμ developμΌλ‘ PR μμ±
- β
PR μ λͺ©:
[EM-100] ν°μΌ μ λͺ©
- β νλ‘μ νΈμ PR ν νλ¦Ώ μλ νμ λ° μ μ©
- β PR λ³Έλ¬Έμ Jira λ§ν¬ λ° ν°μΌ μ 보 μλ μ½μ
- β PRμ΄ μ΄λ―Έ μ‘΄μ¬νλ©΄ λ§ν¬ μλ΄
jgf sync
μλ μν μμ :
- β develop λΈλμΉλ‘ μ ν λ° μ΅μ pull
- β λ¨Έμ§λ λΈλμΉ κ°μ§
- β ν΄λΉ Jira ν°μΌμ "Done"μΌλ‘ λ³κ²½
- β λ‘컬 λΈλμΉ μμ
# 1. ν λΉλ ν°μΌ νμΈ
$ jgf tickets
π« [1] EM-120 μ¬μ©μ νλ‘ν κΈ°λ₯ μΆκ°
μν: To Do | λ΄λΉμ: κΉκ°λ° | μ°μ μμ: High
# 2. μμ
μμ (μΈν°λν°λΈ μ ν λλ μ§μ λͺ
λ Ή)
$ jgf start EM-120
π ν°μΌ EM-120 μμ
μ μμν©λλ€
πΏ λΈλμΉ 'EM-120'κ° μμ±λκ³ μ²΄ν¬μμλμμ΅λλ€
β
ν°μΌ μνκ° 'In Progress'λ‘ λ³κ²½λμμ΅λλ€
# 3. μ½λ© μμ
...
# 4. PR μμ±
$ jgf pr
π λΈλμΉ 'EM-120'μμ 'develop'μΌλ‘ PR μμ±
β
PRμ΄ μ±κ³΅μ μΌλ‘ μμ±λμμ΅λλ€! #123
π‘ PR λ§ν¬: https://github.com/YourOrg/your-repo/pull/123
# 5. 리뷰 & λ¨Έμ§ ν
$ jgf sync
π λ¨Έμ§λ λΈλμΉ λκΈ°ν μμ
β
ν°μΌ EM-120 μνκ° 'Done'μΌλ‘ λ³κ²½λμμ΅λλ€
β
λΈλμΉ 'EM-120'κ° μμ λμμ΅λλ€
β¨ λΈλμΉ λκΈ°ν μλ£!
# μ¬λ¬ λΈλμΉμμ μμ
ν νλ²μ μ 리
$ jgf sync
π 3κ°μ ν°μΌ λΈλμΉλ₯Ό λ°κ²¬νμ΅λλ€
πΏ λΈλμΉ 'EM-118' νμΈ μ€...
β
λΈλμΉ 'EM-118'κ° λ¨Έμ§λμμ΅λλ€
> ν°μΌ EM-118λ₯Ό 'Done' μνλ‘ λ³κ²½νμκ² μ΅λκΉ? Yes
> λ‘컬 λΈλμΉ 'EM-118'λ₯Ό μμ νμκ² μ΅λκΉ? Yes
πΏ λΈλμΉ 'EM-119' νμΈ μ€...
π‘ λΈλμΉ 'EM-119'λ μμ§ λ¨Έμ§λμ§ μμμ΅λλ€
πΏ λΈλμΉ 'EM-120' νμΈ μ€...
β
λΈλμΉ 'EM-120'κ° λ¨Έμ§λμμ΅λλ€
...
κΈ°λ³Έμ μΌλ‘ λ€μ μνλ₯Ό μ§μν©λλ€:
-
To Do
/ν΄μΌ ν μΌ
-
In Progress
/μ§ν μ€
-
Done
/μλ£
νμ¬μ "In Review" μνκ° μλ κ²½μ°, PR μμ± μ μνλ₯Ό λ³κ²½νμ§ μκ³ λ¨Έμ§ ν DoneμΌλ‘λ§ λ³κ²½ν©λλ€.
- κΈ°λ³Έ:
{JIRA_TICKET_NUMBER}
(μ:EM-100
) - μμ νμμ
src/config.rs
μformat_branch_name()
ν¨μ μμ
-
νλ‘μ νΈμ PR ν νλ¦Ώ νμΌ (μλ νμ)
.github/pull_request_template.md
.github/PULL_REQUEST_TEMPLATE.md
pull_request_template.md
docs/pull_request_template.md
.gitlab/merge_request_templates/default.md
-
jgf.jsonμ μ μλ ν νλ¦Ώ
-
prTemplate.path
: 컀μ€ν κ²½λ‘ μ§μ -
prTemplate.content
: μ§μ ν νλ¦Ώ λ΄μ© μμ±
-
-
κΈ°λ³Έ λ΄μ₯ ν νλ¦Ώ
jgfλ PR ν νλ¦Ώμμ λ€μ λ³μλ₯Ό μλ μΉνν©λλ€:
-
{{TICKET_KEY}}
- Jira ν°μΌ λ²νΈ (μ: EM-100) -
{{TICKET_URL}}
- Jira ν°μΌ URL -
{{TICKET_TITLE}}
- Jira ν°μΌ μ λͺ© -
{{BRANCH_NAME}}
- νμ¬ λΈλμΉλͺ
## π« ν°μΌ
{{TICKET_URL}}
## π μμ
λ΄μ©
-
## β
체ν¬λ¦¬μ€νΈ
- [ ] ν
μ€νΈ μμ±
- [ ] λ¬Έμ μ
λ°μ΄νΈ
- [ ] μ½λ 리뷰 μμ²
κ° νλ‘μ νΈμ λ
립μ μΈ jgf.json
μ μμ±νμ¬ κ΄λ¦¬:
# Frontend νλ‘μ νΈ
cd ~/projects/frontend
jgf init # frontendμ© jgf.json μμ±
# Backend νλ‘μ νΈ
cd ~/projects/backend
jgf init # backendμ© jgf.json μμ±
# κ° νλ‘μ νΈμμ λ
립μ μΌλ‘ μλ
cd ~/projects/frontend && jgf tickets # frontend μ€μ μ¬μ©
cd ~/projects/backend && jgf tickets # backend μ€μ μ¬μ©
- νμ¬ λλ ν 리λΆν° μμλ‘ νμνμ¬
jgf.json
μ°ΎκΈ° -
jgf.json
μ΄ μμΌλ©΄ ν΄λΉ μ€μ + κ°μ μμΉμ.env
μ¬μ© - μμΌλ©΄ μ μ
.env
νμΌ μ¬μ© (λ κ±°μ λͺ¨λ)
νλ‘μ νΈμ ν¬ν¨λ μμ νμΌ:
-
jgf.json.example
- νλ‘μ νΈ μ€μ μμ -
.env.example
- ν ν° μ€μ μμ
# SSH μμ΄μ νΈ νμΈ
ssh-add -l
# SSH ν€ μΆκ°
ssh-add ~/.ssh/id_ed25519
- API ν ν°μ΄ μ¬λ°λ₯Έμ§ νμΈ
- Jira URLμ΄
https://
λ‘ μμνλμ§ νμΈ - νλ‘μ νΈ ν€(μ: EM)κ° μ ννμ§ νμΈ
- Personal Access Token κΆν νμΈ (repo κΆν νμ)
- Repository ownerμ nameμ΄ μ ννμ§ νμΈ