GitHub Actions ile Slack Bildirim Entegrasyonu Nasıl Yapılır
Bir CI/CD pipeline’ı kurdunuzda, deploy işlemlerinin sonucunu her seferinde GitHub arayüzünü açıp kontrol etmek zamanla can sıkıcı bir hal alıyor. Ekip büyüdükçe bu durum daha da kritik bir hale geliyor: kim ne zaman ne deploy etti, hangi branch’ten, başarılı mı oldu? Bu soruların cevabını anlık olarak almanın en pratik yolu, GitHub Actions’ı Slack ile entegre etmek. Bu yazıda sıfırdan gerçek dünya senaryolarına kadar her şeyi ele alacağız.
Neden Slack Bildirimi?
Ekip içinde asenkron çalışma kültürü yaygınlaştıkça, bildirimlerin doğru kanala, doğru formatta gelmesi kritik önem kazanıyor. E-posta bildirimleri gömülüp gidiyor, GitHub’ın kendi bildirim sistemi ise çoğu zaman gürültüye karışıyor.
Slack entegrasyonu sayesinde:
- Anlık görünürlük: Deploy tamamlandığında tüm ekip aynı anda haberdar oluyor
- Hata tespiti: Başarısız bir build’i saatler sonra değil, anında görüyorsunuz
- Audit trail: Hangi kullanıcı hangi branch’i ne zaman deploy etti, Slack geçmişinde kalıyor
- Aksiyon alma: Kritik bir hata olduğunda nöbetçi mühendis direkt mesajla ping’lenebiliyor
Slack App Kurulumu ve Webhook Alma
Her şeyden önce Slack tarafında bir yapılandırma yapmamız gerekiyor. İki farklı yöntem var: Incoming Webhooks ve Slack Bot API. Başlangıç için Incoming Webhooks çok daha pratik.
Incoming Webhook Oluşturma
- [api.slack.com/apps](https://api.slack.com/apps) adresine gidin
- “Create New App” butonuna tıklayın
- “From scratch” seçeneğini seçin
- App adını girin (örneğin “GitHub Actions Bot”) ve workspace’inizi seçin
- Sol menüden “Incoming Webhooks” bölümüne gidin
- “Activate Incoming Webhooks” toggle’ını aktif edin
- “Add New Webhook to Workspace” butonuna tıklayın
- Bildirimlerin gideceği kanalı seçin (örneğin #deployments)
- Oluşturulan webhook URL’ini kopyalayın
Webhook URL’i şu formatta görünür:
https://hooks.slack.com/services/T00000000/B00000000/XXXXXXXXXXXXXXXXXXXXXXXX
Bu URL’i asla doğrudan workflow dosyasına yazmayın. GitHub Secrets kullanarak saklayacağız.
GitHub Secret Ekleme
Repository’nize gidin, Settings > Secrets and variables > Actions yolunu izleyin ve “New repository secret” butonuna tıklayın.
- Secret Name:
SLACK_WEBHOOK_URL - Secret Value: Kopyaladığınız webhook URL’i
Eğer organization seviyesinde kullanmak istiyorsanız, aynı işlemi Organization Settings üzerinden yapabilirsiniz. Bu sayede tek bir secret’ı birden fazla repository’de kullanabilirsiniz.
Temel Slack Bildirimi Workflow’u
En basit haliyle bir Slack bildirimi göndermek için curl kullanabiliriz. Bu yaklaşım hiçbir üçüncü taraf action’a bağımlı olmadığı için en güvenilir yöntemlerden biri.
name: Deploy with Slack Notification
on:
push:
branches:
- main
jobs:
deploy:
runs-on: ubuntu-latest
steps:
- name: Checkout kodu al
uses: actions/checkout@v4
- name: Uygulama deploy et
run: |
echo "Deploy işlemi burada gerçekleşiyor"
# Gerçek deploy komutlarınız
- name: Slack bildirimi gönder
if: always()
run: |
STATUS="${{ job.status }}"
if [ "$STATUS" = "success" ]; then
COLOR="good"
EMOJI=":white_check_mark:"
MESSAGE="Deploy başarıyla tamamlandı!"
else
COLOR="danger"
EMOJI=":x:"
MESSAGE="Deploy başarısız oldu!"
fi
curl -X POST "${{ secrets.SLACK_WEBHOOK_URL }}"
-H 'Content-type: application/json'
--data "{
"attachments": [{
"color": "$COLOR",
"title": "$EMOJI $MESSAGE",
"fields": [
{"title": "Repository", "value": "${{ github.repository }}", "short": true},
{"title": "Branch", "value": "${{ github.ref_name }}", "short": true},
{"title": "Commit", "value": "${{ github.sha }}", "short": false},
{"title": "Tetikleyen", "value": "${{ github.actor }}", "short": true}
]
}]
}"
if: always() koşulunu kullandık. Bu önemli bir detay, çünkü önceki adım başarısız olsa bile bildirim adımının çalışmasını sağlıyor. Aksi takdirde deploy başarısız olduğunda bildirim hiç gitmez, tam da haberi en çok istediğiniz durumda.
Hazır Action Kullanımı: slackapi/slack-github-action
Daha gelişmiş ve bakımı kolay bir yapı için Slack’in resmi GitHub action’ını kullanabilirsiniz.
name: Production Deploy Pipeline
on:
push:
branches:
- main
workflow_dispatch:
jobs:
build-and-deploy:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: Node.js kurulumu
uses: actions/setup-node@v4
with:
node-version: '20'
cache: 'npm'
- name: Bağımlılıkları yükle
run: npm ci
- name: Testleri çalıştır
run: npm test
- name: Production build al
run: npm run build
- name: Sunucuya deploy et
run: |
rsync -avz ./dist/ user@production-server:/var/www/html/
- name: Başarı bildirimi gönder
if: success()
uses: slackapi/[email protected]
with:
payload: |
{
"text": ":rocket: *Production deploy tamamlandı!*",
"attachments": [
{
"color": "#36a64f",
"fields": [
{
"title": "Proje",
"value": "${{ github.repository }}",
"short": true
},
{
"title": "Deploy Eden",
"value": "${{ github.actor }}",
"short": true
},
{
"title": "Commit Mesajı",
"value": "${{ github.event.head_commit.message }}",
"short": false
},
{
"title": "Actions Link",
"value": "${{ github.server_url }}/${{ github.repository }}/actions/runs/${{ github.run_id }}",
"short": false
}
]
}
]
}
env:
SLACK_WEBHOOK_URL: ${{ secrets.SLACK_WEBHOOK_URL }}
SLACK_WEBHOOK_TYPE: INCOMING_WEBHOOK
- name: Hata bildirimi gönder
if: failure()
uses: slackapi/[email protected]
with:
payload: |
{
"text": ":fire: *Deploy BAŞARISIZ oldu! Acil kontrol gerekli!*",
"attachments": [
{
"color": "#FF0000",
"fields": [
{
"title": "Proje",
"value": "${{ github.repository }}",
"short": true
},
{
"title": "Tetikleyen",
"value": "${{ github.actor }}",
"short": true
},
{
"title": "Hata Detayı",
"value": "Actions sayfasını kontrol edin",
"short": false
},
{
"title": "Actions Link",
"value": "${{ github.server_url }}/${{ github.repository }}/actions/runs/${{ github.run_id }}",
"short": false
}
]
}
]
}
env:
SLACK_WEBHOOK_URL: ${{ secrets.SLACK_WEBHOOK_URL }}
SLACK_WEBHOOK_TYPE: INCOMING_WEBHOOK
Çok Aşamalı Pipeline’da Bildirimler
Gerçek dünya senaryolarında genellikle birden fazla job’ı olan pipeline’larla çalışırsınız. Her aşamanın durumunu ayrı ayrı bildirmek, hangi adımda problem olduğunu anında anlamanızı sağlar.
name: Multi-Stage Pipeline
on:
push:
branches: [main, staging]
jobs:
test:
runs-on: ubuntu-latest
outputs:
test_status: ${{ steps.set_status.outputs.status }}
steps:
- uses: actions/checkout@v4
- name: Python kurulumu
uses: actions/setup-python@v5
with:
python-version: '3.11'
- name: Bağımlılıkları yükle
run: pip install -r requirements.txt
- name: Unit testleri çalıştır
id: run_tests
run: pytest tests/ --tb=short
- name: Test durumunu ayarla
id: set_status
if: always()
run: |
if [ "${{ steps.run_tests.outcome }}" = "success" ]; then
echo "status=passed" >> $GITHUB_OUTPUT
else
echo "status=failed" >> $GITHUB_OUTPUT
fi
deploy:
needs: test
runs-on: ubuntu-latest
if: github.ref == 'refs/heads/main'
steps:
- uses: actions/checkout@v4
- name: Deploy işlemi
run: |
echo "Deployment komutu burada"
notify:
needs: [test, deploy]
runs-on: ubuntu-latest
if: always()
steps:
- name: Pipeline sonuç bildirimi
run: |
TEST_RESULT="${{ needs.test.result }}"
DEPLOY_RESULT="${{ needs.deploy.result }}"
# Sonuç emoji'lerini belirle
get_emoji() {
case "$1" in
"success") echo ":white_check_mark:" ;;
"failure") echo ":x:" ;;
"skipped") echo ":fast_forward:" ;;
*) echo ":question:" ;;
esac
}
TEST_EMOJI=$(get_emoji "$TEST_RESULT")
DEPLOY_EMOJI=$(get_emoji "$DEPLOY_RESULT")
# Genel durum rengini belirle
if [ "$TEST_RESULT" = "success" ] && [ "$DEPLOY_RESULT" = "success" ]; then
COLOR="good"
HEADER=":rocket: Pipeline başarıyla tamamlandı"
elif [ "$DEPLOY_RESULT" = "skipped" ] && [ "$TEST_RESULT" = "success" ]; then
COLOR="#FFA500"
HEADER=":test_tube: Testler geçti, deploy yapılmadı"
else
COLOR="danger"
HEADER=":fire: Pipeline başarısız!"
fi
curl -X POST "${{ secrets.SLACK_WEBHOOK_URL }}"
-H 'Content-type: application/json'
--data "{
"attachments": [{
"color": "$COLOR",
"title": "$HEADER",
"fields": [
{"title": "Test", "value": "$TEST_EMOJI $TEST_RESULT", "short": true},
{"title": "Deploy", "value": "$DEPLOY_EMOJI $DEPLOY_RESULT", "short": true},
{"title": "Branch", "value": "${{ github.ref_name }}", "short": true},
{"title": "Actor", "value": "${{ github.actor }}", "short": true},
{"title": "Run Link", "value": "${{ github.server_url }}/${{ github.repository }}/actions/runs/${{ github.run_id }}", "short": false}
]
}]
}"
Ortam Bazlı Bildirimler
Staging ve production için farklı Slack kanallarına bildirim göndermek, gürültüyü azaltmanın en etkili yollarından biri. Production kanalını sadece kritik değişiklikler için ayırt etmek, ekibin dikkatini doğru noktaya çekiyor.
name: Environment-Based Notifications
on:
push:
branches:
- main
- staging
jobs:
deploy:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: Ortamı belirle
id: env_check
run: |
if [ "${{ github.ref_name }}" = "main" ]; then
echo "environment=production" >> $GITHUB_OUTPUT
echo "webhook_secret=SLACK_PROD_WEBHOOK" >> $GITHUB_OUTPUT
else
echo "environment=staging" >> $GITHUB_OUTPUT
echo "webhook_secret=SLACK_STAGING_WEBHOOK" >> $GITHUB_OUTPUT
fi
- name: Deploy işlemi
run: |
ENV="${{ steps.env_check.outputs.environment }}"
echo "$ENV ortamına deploy ediliyor..."
- name: Ortama göre bildirim gönder
if: always()
run: |
ENVIRONMENT="${{ steps.env_check.outputs.environment }}"
JOB_STATUS="${{ job.status }}"
# Ortama göre webhook URL'ini seç
if [ "$ENVIRONMENT" = "production" ]; then
WEBHOOK_URL="${{ secrets.SLACK_PROD_WEBHOOK }}"
ENV_COLOR="#FF4500"
ENV_LABEL=":warning: *PRODUCTION*"
else
WEBHOOK_URL="${{ secrets.SLACK_STAGING_WEBHOOK }}"
ENV_COLOR="#4169E1"
ENV_LABEL=":test_tube: *STAGING*"
fi
if [ "$JOB_STATUS" = "success" ]; then
STATUS_TEXT="Deploy başarılı :white_check_mark:"
else
STATUS_TEXT="Deploy başarısız :x: - Acil kontrol gerekli!"
fi
curl -X POST "$WEBHOOK_URL"
-H 'Content-type: application/json'
--data "{
"text": "$ENV_LABEL - $STATUS_TEXT",
"attachments": [{
"color": "$ENV_COLOR",
"fields": [
{"title": "Ortam", "value": "$ENVIRONMENT", "short": true},
{"title": "Versiyon", "value": "${{ github.sha }}", "short": true},
{"title": "Deploy Eden", "value": "${{ github.actor }}", "short": true},
{"title": "Zaman", "value": "$(date '+%Y-%m-%d %H:%M:%S UTC')", "short": true}
]
}]
}"
Bu senaryo için GitHub Secrets’a hem SLACK_PROD_WEBHOOK hem de SLACK_STAGING_WEBHOOK eklenmiş olması gerekiyor.
Reusable Workflow ile Merkezi Bildirim Yönetimi
Birden fazla repository’de aynı bildirim mantığını kullanıyorsanız, reusable workflow yaklaşımı kod tekrarını ortadan kaldırır.
# .github/workflows/slack-notify.yml (merkezi repository'de)
name: Slack Bildirimi (Reusable)
on:
workflow_call:
inputs:
status:
required: true
type: string
environment:
required: false
type: string
default: 'unknown'
custom_message:
required: false
type: string
default: ''
secrets:
SLACK_WEBHOOK_URL:
required: true
jobs:
send-notification:
runs-on: ubuntu-latest
steps:
- name: Bildirim payload'ını hazırla ve gönder
run: |
STATUS="${{ inputs.status }}"
ENVIRONMENT="${{ inputs.environment }}"
CUSTOM_MSG="${{ inputs.custom_message }}"
case "$STATUS" in
"success")
COLOR="good"
STATUS_ICON=":white_check_mark:"
STATUS_TEXT="Başarılı"
;;
"failure")
COLOR="danger"
STATUS_ICON=":x:"
STATUS_TEXT="Başarısız"
;;
"cancelled")
COLOR="#808080"
STATUS_ICON=":no_entry_sign:"
STATUS_TEXT="İptal Edildi"
;;
*)
COLOR="#FFA500"
STATUS_ICON=":question:"
STATUS_TEXT="Bilinmeyen"
;;
esac
FOOTER_MSG="Triggered by ${{ github.actor }} on $(date '+%d.%m.%Y %H:%M') UTC"
curl -X POST "${{ secrets.SLACK_WEBHOOK_URL }}"
-H 'Content-type: application/json'
--data "{
"attachments": [{
"color": "$COLOR",
"title": "$STATUS_ICON ${{ github.repository }} - $ENVIRONMENT Deploy: $STATUS_TEXT",
"text": "$CUSTOM_MSG",
"footer": "$FOOTER_MSG",
"fields": [
{"title": "Branch", "value": "${{ github.ref_name }}", "short": true},
{"title": "Run ID", "value": "${{ github.run_id }}", "short": true},
{"title": "Workflow", "value": "${{ github.workflow }}", "short": false},
{"title": "Actions", "value": "${{ github.server_url }}/${{ github.repository }}/actions/runs/${{ github.run_id }}", "short": false}
]
}]
}"
Bu reusable workflow’u başka bir repository’den çağırmak için:
# Herhangi bir repository'deki workflow dosyası
name: Deploy
on:
push:
branches: [main]
jobs:
deploy:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: Deploy komutu
run: echo "Deploy burada"
bildirim-gonder:
needs: deploy
if: always()
uses: sirket-org/central-workflows/.github/workflows/slack-notify.yml@main
with:
status: ${{ needs.deploy.result }}
environment: production
custom_message: "Frontend v2.5.1 production'a deploy edildi."
secrets:
SLACK_WEBHOOK_URL: ${{ secrets.SLACK_WEBHOOK_URL }}
Gelişmiş Senaryo: PR Merge Bildirimi
Pull Request merge edildiğinde takımı bilgilendirmek, özellikle büyük değişiklikler için çok faydalı.
name: PR Merge Slack Bildirimi
on:
pull_request:
types: [closed]
branches:
- main
jobs:
pr-merge-notify:
if: github.event.pull_request.merged == true
runs-on: ubuntu-latest
steps:
- name: PR merge bildirimi gönder
run: |
PR_TITLE="${{ github.event.pull_request.title }}"
PR_NUMBER="${{ github.event.pull_request.number }}"
PR_AUTHOR="${{ github.event.pull_request.user.login }}"
PR_URL="${{ github.event.pull_request.html_url }}"
PR_BODY="${{ github.event.pull_request.body }}"
MERGE_COMMIT="${{ github.event.pull_request.merge_commit_sha }}"
LABELS=$(echo '${{ toJson(github.event.pull_request.labels.*.name) }}' | tr -d '[]"' | tr ',' ', ')
# PR açıklama uzunsa kırp
if [ ${#PR_BODY} -gt 200 ]; then
PR_BODY="${PR_BODY:0:200}..."
fi
curl -X POST "${{ secrets.SLACK_WEBHOOK_URL }}"
-H 'Content-type: application/json'
--data "{
"text": ":merged: *PR #$PR_NUMBER merge edildi!*",
"attachments": [{
"color": "#6f42c1",
"title": "$PR_TITLE",
"title_link": "$PR_URL",
"text": "$PR_BODY",
"fields": [
{"title": "Yazar", "value": "$PR_AUTHOR", "short": true},
{"title": "Hedef Branch", "value": "main", "short": true},
{"title": "Etiketler", "value": "$LABELS", "short": true},
{"title": "Merge Commit", "value": "${MERGE_COMMIT:0:8}", "short": true}
]
}]
}"
Dikkat Edilmesi Gereken Noktalar
Bildirimleri kurarken karşılaşabileceğiniz yaygın sorunlar ve çözümleri:
Webhook URL güvenliği
- Webhook URL’ini kesinlikle kod içine yazmayın
SLACK_WEBHOOK_URLsecret’ını repository seviyesinde değil, mümkünse environment seviyesinde tanımlayın- Sızdığını düşündüğünüz bir webhook’u Slack app ayarlarından hemen yenileyin
if: always() ve if: failure() farkı
if: always(): Job cancelled olsa bile çalışırif: failure(): Sadece önceki adım başarısız olduğunda çalışırif: success(): Sadece önceki adım başarılı olduğunda çalışır
Bildirimlerde always() kullanmak genellikle daha güvenlidir, çünkü cancel durumlarında da haberdar olursunuz.
JSON escape sorunları
Commit mesajlarında veya PR başlıklarında özel karakter olduğunda curl ile gönderilen JSON bozulabilir. Bunu önlemek için:
jqkullanarak JSON oluşturun- Mesajı bir dosyaya yazıp
@filenameile referans verin - GitHub’ın
toJson()fonksiyonundan yararlanın
Rate limiting
Slack Incoming Webhooks için saniyede 1 mesaj sınırı var. Paralel çok sayıda job bildirimi gönderiyorsanız bu sınıra takılabilirsiniz. notify job’ını tüm job’ların bitmesini bekleyecek şekilde tasarlamak bu sorunu çözer.
Gürültü yönetimi
Her push’ta bildirim göndermek bir süre sonra rahatsız edici olabiliyor. Aşağıdaki stratejiler gürültüyü azaltır:
- Sadece
mainvereleasebranch’leri için bildirim gönderin - Sadece başarısız build’ler için alert açın, başarılılar için summary kanalı kullanın
workflow_dispatchile tetiklenen manual deploy’lar için ayrı kanal kullanın- Gece saatlerindeki otomatik scheduled job’lar için sabah özeti formatını tercih edin
Sonuç
GitHub Actions ile Slack entegrasyonu, ilk bakışta küçük bir iyileştirme gibi görünse de ekip dinamiklerine katkısı oldukça büyük. Deploy süreçlerinde tam görünürlük sağlamak, hataları erken tespit etmek ve ekip içi iletişimi otomatikleştirmek; DevOps olgunluğunun önemli göstergelerinden biri.
Başlangıç için curl ile basit bir bildirim göndermekle başlayın. Sonrasında reusable workflow’lar ve ortam bazlı kanallarla yapıyı büyütün. Kritik olan, bildirimlerin anlamlı ve aksiyon alınabilir olması. Sadece “deploy başarılı” yazan bir bildirim değil, kim yaptı, ne değişti, nereye bakmalı sorularını cevaplayan zengin bir içerik hazırlamak, bu entegrasyondan gerçek değer almanızı sağlar.
