GitHub Issues ve Projects ile Etkili Görev Yönetimi
Bir ekibin gerçek anlamda birlikte çalışabilmesi için ortak bir hafızaya ihtiyacı var. Bu hafıza kimi ekiplerde Jira olur, kimi ekiplerde Trello, kimi ekiplerde ise bir köşede tozlanan Excel dosyası. Ama eğer zaten GitHub üzerinde kod geliştiriyorsanız, görev takibini de aynı ekosisteme taşımak çok daha mantıklı. GitHub Issues ve Projects tam bu noktada devreye giriyor, ve bir kez düzgün kurgulandığında ekibin verimliliğini ciddi ölçüde artırıyor.
Bu yazıda sıfırdan bir sysadmin ya da DevOps ekibinin GitHub üzerinde görev yönetimini nasıl kurması gerektiğini, hangi yapıları kullanması gerektiğini ve özellikle otomasyon konusunda nelerin mümkün olduğunu anlatacağım. Teorik değil, sahadan gelen bir perspektifle.
GitHub Issues: Sadece Bug Takibi Değil
Çoğu ekip Issues’u yalnızca bug bildirimi için kullanıyor. Bu, bir araba satın alıp sadece market alışverişi için kullanmaya benziyor. Issues, bir ekibin tüm çalışma birimlerini temsil edebilir:
- Yeni bir özellik geliştirme
- Altyapı değişikliği talebi
- Güvenlik açığı bildirimi
- Teknik borç kaydı
- Dokümantasyon eksikliği
- Soruşturulması gereken bir performans sorunu
Önce Issues’un temel yapısını oturtmak gerekiyor.
Label Sistemi Kurmak
Varsayılan label’lar (bug, enhancement, documentation vs.) çoğu ekip için yetersiz. Özellikle sysadmin ve DevOps ortamlarında daha granüler bir yapıya ihtiyaç duyulur.
GitHub CLI ile label yönetimi yapmak komut satırından çok daha hızlı:
# gh CLI kurulu değilse
sudo apt install gh
gh auth login
# Mevcut label'ları listele
gh label list --repo orginizasyon/repo-adi
# Yeni label ekle
gh label create "infra:network" --color "#0075ca" --description "Ağ altyapısıyla ilgili görevler"
gh label create "infra:storage" --color "#e4e669" --description "Depolama sistemleri"
gh label create "priority:critical" --color "#d93f0b" --description "Üretimi etkileyen kritik sorun"
gh label create "priority:high" --color "#e99695" --description "Bu sprint içinde tamamlanmalı"
gh label create "team:backend" --color "#c2e0c6" --description "Backend ekibi sorumluluğu"
gh label create "status:blocked" --color "#cccccc" --description "Başka bir göreve bağımlı"
Bir label taksonomisi oluştururken şu grupları düşünebilirsiniz:
- Tip grubu:
type:bug,type:feature,type:chore,type:security - Alan grubu:
area:ci-cd,area:monitoring,area:kubernetes,area:database - Öncelik grubu:
priority:critical,priority:high,priority:medium,priority:low - Durum grubu:
status:blocked,status:in-review,status:needs-info - Takım grubu:
team:platform,team:backend,team:dba
Bu yapı sayesinde “Kubernetes ile ilgili kritik, şu an bloklanmış görevleri” tek bir filtreyle görebilirsiniz.
Issue Template’leri Oluşturmak
Ekipteki herkesin farklı formatta issue açması kaos yaratır. Template’ler bu kaosa düzen getirir. .github/ISSUE_TEMPLATE/ dizini altına YAML dosyaları koyarak bunu çözebilirsiniz.
mkdir -p .github/ISSUE_TEMPLATE
Altyapı değişikliği için örnek bir template:
# .github/ISSUE_TEMPLATE/infra_change.yml
name: Altyapı Değişikliği
description: Sunucu, ağ veya servis değişikliği talebi
title: "[INFRA] "
labels: ["type:chore", "area:infra"]
assignees: []
body:
- type: markdown
attributes:
value: "## Altyapı Değişikliği Talebi"
- type: input
id: affected_systems
attributes:
label: Etkilenen Sistemler
description: Hangi sunucular veya servisler etkilenecek?
placeholder: "prod-web-01, prod-web-02, load-balancer"
validations:
required: true
- type: textarea
id: change_description
attributes:
label: Değişiklik Açıklaması
description: Ne değiştirilecek ve neden?
validations:
required: true
- type: dropdown
id: change_window
attributes:
label: Planlanan Değişiklik Penceresi
options:
- Mesai saatleri (09:00-18:00)
- Mesai dışı (18:00-23:00)
- Bakım penceresi (Cumartesi 02:00-06:00)
validations:
required: true
- type: checkboxes
id: rollback_plan
attributes:
label: Geri Alma Planı
options:
- label: Rollback prosedürü tanımlandı
required: true
- label: Etkilenen servis sahipleri bilgilendirildi
required: false
Bu yapı, birisi yeni bir issue açmak istediğinde GitHub arayüzünde ona form gösterir. Eksik bilgiyle issue açılmasının önüne geçer.
GitHub Projects: Modern Proje Yönetimi
GitHub Projects’in v2 versiyonu (artık sadece “Projects” olarak geçiyor) önceki haline kıyasla çok daha güçlü. Tablo ve kanban görünümü arasında geçiş yapabilir, custom field’lar ekleyebilir ve otomasyon kurabilirsiniz.
Proje Oluşturma ve Yapılandırma
# GitHub CLI ile proje oluştur (organization seviyesinde)
gh project create --owner "orginizasyon-adi" --title "Q4 Platform Roadmap" --format json
# Projedeki itemları listele
gh project item-list 1 --owner "orginizasyon-adi" --format json
# Issue'yu projeye ekle
gh project item-add 1 --owner "orginizasyon-adi" --url https://github.com/orginizasyon/repo/issues/42
Custom Field’lar
Projects’in gücü burada. Kanban sütunlarının ötesinde, kendi veri alanlarınızı ekleyebilirsiniz:
- Sprint (iteration field): Hangi sprint’e ait?
- Story Points (number field): Tahmini efor
- Deployment Env (single select): dev, staging, prod
- Team (single select): platform, backend, dba
- Due Date (date field): Teslim tarihi
Bu field’lar sayesinde projenizi dilediğiniz şekilde filtreleyip gruplayabilirsiniz. “Bu sprint’te platform ekibinin prod’a gidecek görevleri” gibi sorgular saniyeler içinde çalışır.
Görünüm Stratejisi
Tek bir proje içinde birden fazla görünüm (view) oluşturabilirsiniz:
- Sprint Board: Kanban formatında, sadece aktif sprint’in işleri
- Backlog: Tablo formatında, önceliğe göre sıralı
- By Team: Takıma göre gruplandırılmış tablo
- Blocked Items: Sadece
status:blockedlabel’lı itemlar
Her takım üyesi kendi görünümüne odaklanabilir, yöneticiler ise üst düzey görünümden ilerlemeyi takip edebilir.
Milestones ile Sprint Yönetimi
Milestones, belirli bir tarihe bağlı hedefleri temsil eder. Sprint yönetimi için milestones’u şu şekilde kullanabilirsiniz:
# Yeni milestone oluştur
gh api repos/orginizasyon/repo/milestones
--method POST
--field title="Sprint 23 - Kasım 2024"
--field due_on="2024-11-30T23:59:59Z"
--field description="Monitoring stack upgrade ve K8s node havuzu genişletme"
# Mevcut milestone'ları listele
gh api repos/orginizasyon/repo/milestones
# Issue'ya milestone ata
gh issue edit 42 --milestone "Sprint 23 - Kasım 2024"
Milestone’ların en güzel yanı ilerleme barı. Kaç issue açık, kaçı kapalı, yüzde kaç tamamlandı, bunu tek bakışta görürsünüz. Sprint bitişine yakın açık item’ların durumunu gözden geçirmek için haftalık standuplarda bu görünümü açmak oldukça etkili.
GitHub Actions ile İş Akışı Otomasyonu
Asıl güç buradan geliyor. Manuel olarak label eklemek, atamak, proje güncellemek yerine bunu otomatize ettiğinizde ekibin yükü azalır ve tutarlılık artar.
PR Açıldığında Otomatik İşlemler
# .github/workflows/issue-automation.yml
name: Issue ve PR Otomasyonu
on:
issues:
types: [opened, labeled]
pull_request:
types: [opened, closed, review_requested]
jobs:
auto-assign-project:
runs-on: ubuntu-latest
if: github.event_name == 'issues' && github.event.action == 'opened'
steps:
- name: Issue'yu projeye otomatik ekle
uses: actions/[email protected]
with:
project-url: https://github.com/orgs/orginizasyon/projects/5
github-token: ${{ secrets.PROJECT_TOKEN }}
auto-label-pr:
runs-on: ubuntu-latest
if: github.event_name == 'pull_request' && github.event.action == 'opened'
steps:
- uses: actions/labeler@v4
with:
repo-token: ${{ secrets.GITHUB_TOKEN }}
configuration-path: .github/labeler.yml
Labeler için konfigürasyon:
# .github/labeler.yml
area:kubernetes:
- changed-files:
- any-glob-to-any-file:
- "k8s/**/*"
- "helm/**/*"
area:ci-cd:
- changed-files:
- any-glob-to-any-file:
- ".github/workflows/**/*"
- "Jenkinsfile"
area:monitoring:
- changed-files:
- any-glob-to-any-file:
- "monitoring/**/*"
- "grafana/**/*"
- "prometheus/**/*"
Issue Kapandığında İlgili Branch’i Temizleme
# .github/workflows/cleanup-on-close.yml
name: Issue Kapandığında Temizlik
on:
issues:
types: [closed]
jobs:
notify-slack:
runs-on: ubuntu-latest
steps:
- name: Slack bildirimi gönder
uses: slackapi/[email protected]
with:
payload: |
{
"text": "Issue kapatıldı: #${{ github.event.issue.number }} - ${{ github.event.issue.title }}",
"username": "GitHub Bot"
}
env:
SLACK_WEBHOOK_URL: ${{ secrets.SLACK_WEBHOOK_URL }}
Stale Issue Yönetimi
Uzun süre hareketsiz kalan issue’lar backlog kirliliği yaratır. Bunu otomatize etmek için:
# .github/workflows/stale.yml
name: Hareketsiz Issue Yönetimi
on:
schedule:
- cron: '0 9 * * 1' # Her Pazartesi 09:00 UTC
jobs:
stale:
runs-on: ubuntu-latest
steps:
- uses: actions/stale@v8
with:
repo-token: ${{ secrets.GITHUB_TOKEN }}
stale-issue-message: |
Bu issue 60 gündür güncellenmedi. Hala geçerliyse lütfen yorum ekleyin
veya bir milestone'a atayın. 14 gün içinde güncelleme olmazsa kapatılacak.
close-issue-message: |
60 gün hareketsizlik nedeniyle otomatik olarak kapatıldı.
Hala geçerliyse yeniden açabilirsiniz.
stale-issue-label: 'status:stale'
days-before-stale: 60
days-before-close: 14
exempt-issue-labels: 'priority:critical,status:blocked'
Gerçek Dünya Senaryosu: DevOps Ekibi Workflow’u
Bir örnek üzerinden gidelim. 5 kişilik bir platform ekibi, iki haftalık sprintlerle çalışıyor. Şöyle bir akış kurabilirler:
1. Issue açılır: Biri bir altyapı değişikliği talebi açar. Template sayesinde tüm gerekli bilgileri doldurur. GitHub Actions otomatik olarak issue’yu aktif projeye ekler ve status:triage label’ını atar.
2. Triage: Ekip lideri haftalık triage toplantısında (ya da async olarak) issue’yu inceler, uygun label’ları ekler, sprint milestone’una atar ve bir ekip üyesine assign eder.
3. Geliştirme başlar: Atanan kişi issue üzerinde çalışmaya başlarken status:in-progress label’ını ekler. Branch ismini feat/issue-42-redis-cluster-upgrade gibi açar.
4. PR oluşturulur: PR açılırken issue’ya referans verilir:
# PR açarken issue referansı
gh pr create
--title "Redis cluster upgrade - 6.2'den 7.0'a"
--body "Closes #42
## Yapılan Değişiklikler
- Redis 7.0 için Helm chart güncellendi
- Sentinel konfigürasyonu yeniden yapılandırıldı
- Smoke test eklendi
## Test Adımları
1. Staging'de deploy edildi ve 48 saat gözlemlendi
2. Failover senaryoları test edildi"
--reviewer "platform-lead,dba-team"
Closes #42 ifadesi PR merge edildiğinde issue’yu otomatik kapatır.
5. PR merge, issue kapanır: Issue kapanınca Projects’teki durum otomatik olarak “Done” sütununa geçer (built-in otomasyon). Slack bildirimi gönderilir.
Bu akış manuel müdahaleyi minimuma indirir. Ekip, araç yönetimiyle değil, asıl işiyle uğraşır.
GitHub CLI ile Batch İşlemler
Zaman zaman toplu işlemler yapmanız gerekir. Örneğin eski bir milestone’u kapatmak, onlarca issue’yu yeni sprint’e taşımak gibi:
#!/bin/bash
# Belirli bir milestone'daki açık issue'ları yeni milestone'a taşı
OLD_MILESTONE="Sprint 22 - Ekim 2024"
NEW_MILESTONE="Sprint 23 - Kasım 2024"
REPO="orginizasyon/repo"
# Açık issue'ları listele ve yeni milestone'a ata
gh issue list
--repo "$REPO"
--milestone "$OLD_MILESTONE"
--state open
--json number
--jq '.[].number' |
while read issue_number; do
echo "Issue #$issue_number taşınıyor..."
gh issue edit "$issue_number"
--repo "$REPO"
--milestone "$NEW_MILESTONE"
sleep 0.5 # Rate limit için bekle
done
echo "Taşıma tamamlandı."
Benzer şekilde, bir takım üyesinin ayrılması durumunda tüm assign’larını başka birine devretmek için:
#!/bin/bash
# Assign devri
OLD_USER="eski-kullanici"
NEW_USER="yeni-kullanici"
REPO="orginizasyon/repo"
gh issue list
--repo "$REPO"
--assignee "$OLD_USER"
--state open
--json number
--jq '.[].number' |
while read issue_number; do
gh issue edit "$issue_number"
--repo "$REPO"
--remove-assignee "$OLD_USER"
--add-assignee "$NEW_USER"
echo "Issue #$issue_number devredildi."
done
İpuçları ve Sık Yapılan Hatalar
Ekiplerin bu yapıyı kurarken düştüğü bazı tuzaklar var:
Çok karmaşık label sistemi: 50 farklı label oluşturmak kaos yaratır. Başlangıçta 15-20 label yeterli, zamanla organik olarak büyüsün.
Template’leri zorla doldurmak: Her alan required: true yapılırsa insanlar template’i bypass etmeye başlar. Sadece gerçekten kritik olan alanları zorunlu yapın.
Milestone’ları unutmak: Sprint sonunda kapatılmayan milestone’lar birikte kalmaya başlar. Her sprint başında önceki milestone’u review edin ve kapatın ya da itemları taşıyın.
Projects otomasyonunu abartmak: Her şeyi otomatize etmeye çalışmak, bazen manuel kontrolü ortadan kaldırır ve ekip anlamlı kararlar vermek yerine otomasyonun çıktılarını onaylamaya başlar. Kritik geçişler (örneğin “In Progress” -> “Done”) manuel onay gerektirebilir.
PR ile issue bağlantısını kurmamak: Closes, Fixes, Resolves anahtar kelimeleri olmadan açılan PR’lar, issue’yu otomatik kapatmaz. Ekiple bu konvansiyonu paylaşmak önemli.
Raporlama ve Görünürlük
Sprint sonunda ekibin neler yaptığını raporlamak için GitHub’ın GraphQL API’sini kullanabilirsiniz:
# Bir milestone'daki kapalı issue'ların listesi
gh api graphql -f query='
{
repository(owner: "orginizasyon", name: "repo") {
milestone(number: 5) {
title
closedAt
issues(states: CLOSED, first: 50) {
nodes {
number
title
closedAt
assignees(first: 3) {
nodes {
login
}
}
labels(first: 5) {
nodes {
name
}
}
}
}
}
}
}' | jq '.data.repository.milestone.issues.nodes[] | {number, title, assignee: .assignees.nodes[0].login}'
Bu çıktıyı sprint retrospektif toplantılarında kullanabilir, ya da otomatik olarak Confluence’a ya da bir Markdown dosyasına yazabilirsiniz.
Sonuç
GitHub Issues ve Projects, doğru kurulduğunda ekstra bir araç gerektirmeden tam işlevsel bir görev yönetim sistemi oluşturmanızı sağlar. Kodunuzun yaşadığı yerle görev takibini aynı platforma taşımak, bağlam kayıplarını önler. PR ile issue arasındaki doğal bağlantı, kimin ne için ne değiştiğini anlamayı kolaylaştırır.
Başlangıçta her şeyi mükemmel kurmaya çalışmayın. Önce temel label sistemi ve issue template’lerini kurun. İki üç sprint sonra ekibin hangi bilgilere ihtiyaç duyduğunu anlarsınız, o zaman custom field’lar ve otomasyon katmanını eklersiniz. Sistemin organik olarak büyümesine izin verin; ekibin benimsemediği bir workflow, ne kadar mükemmel kurulursa kurulsun, haftalar içinde terk edilir.
Son olarak şunu söyleyeyim: Bu yapının değeri, ekip disipliniyle doğru orantılı. Araçlar sadece zemin hazırlar, ama issue’ları güncel tutmak, PR’larda issue referansı vermek ve milestoneları düzenli temizlemek ekip kültürünün parçası haline gelmedikçe hiçbir otomasyon işe yaramaz.
