3 releases
Uses new Rust 2024
| 0.1.2 | Sep 2, 2025 |
|---|---|
| 0.1.1 | Sep 2, 2025 |
| 0.1.0 | Sep 2, 2025 |
#1184 in Development tools
81KB
1.5K
SLoC
JGF (Jira Git Flow) π
Jiraμ Gitμ μ°λνλ μν¬νλ‘μ° μλν CLI λꡬ
π λ¬Έμ μν©
κ°λ°νμμ λ°λ³΅μ μΌλ‘ κ²ͺλ λ¬Έμ λ€:
- PMμ΄ Jira ν°μΌ ν λΉ β κ°λ°μκ° μλμΌλ‘ ν°μΌ νμΈ
- ν°μΌ λ²νΈλ‘ λΈλμΉ μμ± β μλμΌλ‘ Jira μν λ³κ²½
- PR μμ± μ Jira λ§ν¬ 볡μ¬/λΆμ¬λ£κΈ°
- PR λ¨Έμ§ ν Jira μν μλ μ λ°μ΄νΈ
- λ‘컬 λΈλμΉ μ 리
μ΄ λͺ¨λ κ³Όμ μ΄ μκ°μ΄ λ§μ΄ μμλ©λλ€.
β¨ JGFκ° ν΄κ²°νλ κ²
- μλ λΈλμΉ μμ±: 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 β λ¨Έμ§ β μμ
π μ€μΉ λ°©λ²
Prerequisites
- Git
- Jira κ³μ λ° API ν ν°
- GitHub κ³μ λ° Personal Access Token
μ€μΉ μ΅μ
Option 1: Cargoλ₯Ό ν΅ν μ€μΉ (Rust νμ)
# crates.ioμμ μ€μΉ
cargo install jgf
# λλ μμ€μμ λΉλ
git clone https://github.com/jaehafe/jgf.git
cd jgf
cargo install --path .
Option 2: λ°μ΄λ리 μ§μ λ€μ΄λ‘λ (Rust λΆνμ)
# 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
μ΄ λͺ λ Ήμ λ κ°μ νμΌμ μμ±ν©λλ€:
1. jgf.json - νλ‘μ νΈ μ€μ (Gitμ μ»€λ° κ°λ₯)
{
"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": "μ§μ ν
νλ¦Ώ λ΄μ©..."
}
}
2. .env - ν ν° μ 보
JIRA_TOKEN=your-jira-api-token
GITHUB_TOKEN=ghp_your_github_token
API ν ν° λ°κΈ λ°©λ²
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(μ 체) - ν ν° μμ± λ° λ³΅μ¬
π μ¬μ©λ²
1. ν λΉλ ν°μΌ μ‘°ν λ° μμ μμ
# ν λΉλ λͺ¨λ ν°μΌ μ‘°ν
jgf tickets
# μνλ³ νν°λ§
jgf tickets --status "In Progress"
# μ΅λ κ°μ μ ν
jgf tickets --limit 10
μΈν°λν°λΈ λͺ¨λ:
- ν°μΌ λͺ©λ‘μμ μ ν
- "λΈλμΉ μμ± λ° In Progressλ‘ λ³κ²½" μ ν
- μλμΌλ‘ λΈλμΉ μμ± λ° Jira μν μ λ°μ΄νΈ
2. νΉμ ν°μΌμΌλ‘ μμ μμ
jgf start EM-100
μλ μν μμ :
- β develop λΈλμΉμμ μ΅μ λ³κ²½μ¬ν pull
- β
EM-100λΈλμΉ μμ± λ° μ²΄ν¬μμ - β Jira ν°μΌμ "In Progress"λ‘ λ³κ²½
3. PR μμ±
jgf pr
μλ μν μμ :
- β νμ¬ λΈλμΉμμ developμΌλ‘ PR μμ±
- β
PR μ λͺ©:
[EM-100] ν°μΌ μ λͺ© - β νλ‘μ νΈμ PR ν νλ¦Ώ μλ νμ λ° μ μ©
- β PR λ³Έλ¬Έμ Jira λ§ν¬ λ° ν°μΌ μ 보 μλ μ½μ
- β PRμ΄ μ΄λ―Έ μ‘΄μ¬νλ©΄ λ§ν¬ μλ΄
4. λ¨Έμ§ ν λκΈ°ν
jgf sync
μλ μν μμ :
- β develop λΈλμΉλ‘ μ ν λ° μ΅μ pull
- β λ¨Έμ§λ λΈλμΉ κ°μ§
- β ν΄λΉ Jira ν°μΌμ "Done"μΌλ‘ λ³κ²½
- β λ‘컬 λΈλμΉ μμ
π― μ€μ μ¬μ© μλ리μ€
μλλ¦¬μ€ 1: μ κΈ°λ₯ κ°λ°
# 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'κ° μμ λμμ΅λλ€
β¨ λΈλμΉ λκΈ°ν μλ£!
μλλ¦¬μ€ 2: μ¬λ¬ ν°μΌ λμ μμ
# μ¬λ¬ λΈλμΉμμ μμ
ν νλ²μ μ 리
$ jgf sync
π 3κ°μ ν°μΌ λΈλμΉλ₯Ό λ°κ²¬νμ΅λλ€
πΏ λΈλμΉ 'EM-118' νμΈ μ€...
β
λΈλμΉ 'EM-118'κ° λ¨Έμ§λμμ΅λλ€
> ν°μΌ EM-118λ₯Ό 'Done' μνλ‘ λ³κ²½νμκ² μ΅λκΉ? Yes
> λ‘컬 λΈλμΉ 'EM-118'λ₯Ό μμ νμκ² μ΅λκΉ? Yes
πΏ λΈλμΉ 'EM-119' νμΈ μ€...
π‘ λΈλμΉ 'EM-119'λ μμ§ λ¨Έμ§λμ§ μμμ΅λλ€
πΏ λΈλμΉ 'EM-120' νμΈ μ€...
β
λΈλμΉ 'EM-120'κ° λ¨Έμ§λμμ΅λλ€
...
π’ νμ¬λ³ 컀μ€ν°λ§μ΄μ§
Jira μν λ§€ν
κΈ°λ³Έμ μΌλ‘ λ€μ μνλ₯Ό μ§μν©λλ€:
To Do/ν΄μΌ ν μΌIn Progress/μ§ν μ€Done/μλ£
νμ¬μ "In Review" μνκ° μλ κ²½μ°, PR μμ± μ μνλ₯Ό λ³κ²½νμ§ μκ³ λ¨Έμ§ ν DoneμΌλ‘λ§ λ³κ²½ν©λλ€.
λΈλμΉ λ€μ΄λ°
- κΈ°λ³Έ:
{JIRA_TICKET_NUMBER}(μ:EM-100) - μμ νμμ
src/config.rsμformat_branch_name()ν¨μ μμ
PR ν νλ¦Ώ κΈ°λ₯
ν νλ¦Ώ μ°μ μμ
-
νλ‘μ νΈμ PR ν νλ¦Ώ νμΌ (μλ νμ)
.github/pull_request_template.md.github/PULL_REQUEST_TEMPLATE.mdpull_request_template.mddocs/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 μμ΄μ νΈ νμΈ
ssh-add -l
# SSH ν€ μΆκ°
ssh-add ~/.ssh/id_ed25519
Jira API μ€λ₯
- API ν ν°μ΄ μ¬λ°λ₯Έμ§ νμΈ
- Jira URLμ΄
https://λ‘ μμνλμ§ νμΈ - νλ‘μ νΈ ν€(μ: EM)κ° μ ννμ§ νμΈ
GitHub API μ€λ₯
- Personal Access Token κΆν νμΈ (repo κΆν νμ)
- Repository ownerμ nameμ΄ μ ννμ§ νμΈ
Dependencies
~21β37MB
~543K SLoC