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:blocked label’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.

Bir yanıt yazın

E-posta adresiniz yayınlanmayacak. Gerekli alanlar * ile işaretlenmişlerdir