# Push Webhook'ları

> GitHub, GitLab, Gitea, Bitbucket ve Confluence Data Center için kaynak başına push webhook kurmak, teslimatta ne olduğu ve bir secret'ı rotate etmek.

- Güncelleme: 2026-09-25
- Kaynak: https://contextator.com/tr/docs/push-webhooks/
- Dil: tr-TR
- Yazar: Muhammet Şafak

---
Biri bir depoya push ettiğinde otomatik olarak yeniden indeksleyin. Her git kaynağı kendi webhook
URL'sini ve kendi secret'ını alır.

```
POST http://<your-host>/api/webhooks/git/<source-id>
```

---

## Bir tane kurmak

1. Panoda git kaynağını açın (satırındaki **Edit**).
2. **Push webhook** kutusu, kopyalama düğmeleriyle birlikte URL'yi ve secret'ı gösterir.
3. Depo ayarlarında, bu URL ve bu secret ile bir **push** webhook'u ekleyin.
4. Bir şey push edin. Projenin durumu bir iki saniye içinde `queued`'a geçer.

Sunucu, git host'undan erişilebilir olmalıdır. Aynı ağdaki self-hosted bir Gitea için bu genelde
otomatiktir; GitHub.com için genel erişime açık bir adrese ya da bir tünele ihtiyacınız var.

## Sağlayıcıya göre

### GitHub
**Settings → Webhooks → Add webhook**

| Alan | Değer |
|-------|-------|
| Payload URL | webhook URL'si |
| Content type | `application/json` |
| Secret | dialogdaki secret |
| Events | *Just the push event* |

GitHub `X-Hub-Signature-256` ile imzalar.

### GitLab
**Settings → Webhooks**

| Alan | Değer |
|-------|-------|
| URL | webhook URL'si |
| Secret token | dialogdaki secret |
| Trigger | *Push events* |

GitLab secret'ın kendisini `X-Gitlab-Token`'da gönderir.

### Gitea / Forgejo / Codeberg
**Settings → Webhooks → Gitea**

| Alan | Değer |
|-------|-------|
| Target URL | webhook URL'si |
| HTTP method | `POST` |
| POST content type | `application/json` |
| Secret | dialogdaki secret |
| Trigger | *Push events* |

`X-Gitea-Signature` ile imzalanır (daha yeni sürümler `X-Hub-Signature-256`'yı da gönderir).

### Bitbucket Cloud
**Repository settings → Webhooks → Add webhook**, *Repository push* üzerinde tetiklenecek şekilde,
dialogdaki secret ile. `X-Hub-Signature` ile imzalanır.

---

## Confluence Data Center

Bir git host'u değil, ama Data Center üzerindeki bir [Confluence](/tr/docs/confluence/) kaynağı için
aynı fikir, kendi URL'siyle (ADR-0085):

```
POST http://<your-host>/api/webhooks/confluence/<source-id>
```

Bir Confluence kaynağının **siz açana kadar hiçbir webhook'u yoktur**; o ana kadar her teslimat
`401 not_enabled` ile reddedilir ve hiçbir şey saklanmaz.

1. Confluence kaynağını **Edit** edin ve *Confluence webhook* kutusunda **Turn on**'ı seçin. Bir secret
   üretilir; **Copy URL** ve **Copy secret**.
2. Confluence'ta, **Administration → Webhooks → Create a webhook**: URL'yi ve secret'ı yapıştırın ve
   sayfa olaylarını seçin (created, updated, removed, restored, moved).

Confluence her teslimatı `X-Hub-Signature: sha256=<gövdenin HMAC-SHA256'sı>` ile imzalar; eşleşmeyen
biri `401 invalid_signature` ile reddedilir. Yorumlar, etiketler, ekler, beğeniler, kullanıcı ve grup
değişiklikleri ve **blog yazıları** neyin indekslendiğini değiştiremez — bunlar `200` ile yanıtlanır ve
yok sayılır. Bunun dışındaki her şey, izin değişiklikleri ve bu build'in tanımadığı bir olay dahil, bir
çalışmayı kuyruğa alır.

Bir düzenleme patlaması tek bir çalışma olur, ve çalışmalar en az `WEBHOOK_MIN_INTERVAL_MINUTES` kadar
arayla gerçekleşir (varsayılan 5): bir webhook kaynağı saniyeler içinde değil **yakında** gösterir. Bir
reddediş olmayan her yanıt `200`'dür, çünkü Confluence başka her şeyi bir başarısızlık sayar ve bir
dizi başarısızlıktan sonra teslim etmeyi durdurur. Açıldıktan sonra, düğme **New secret** okur ve
secret'ı değiştirir; **Turn off** onu kaldırır (`DELETE …/webhook-secret`), ve teslimatlar yeniden
reddedilir.

Her şeyi görmez — Confluence'ın vazgeçtiği bir teslimat, bir olay olmadan hesaba okunamaz hale gelen bir
sayfa, tekrarlanan başarısızlıklardan sonra Confluence'ın saatlerce atladığı teslimatlar — bu yüzden
**senkronizasyon aralığını açık tutun**; bir sonraki zamanlanmış senkronizasyon webhook'un kaçırdığını
yakalar. Confluence Cloud bunları bir Forge ya da Connect uygulaması olmadan gönderemez — bkz.
[Confluence](/tr/docs/confluence/#nasıl-taze-tutulur).

---

## Teslimatta ne olur

1. İmza, o kaynağın secret'ına göre doğrulanır — **başka her şeyden önce**.
2. Payload'daki branch'ler, kaynağın branch'iyle karşılaştırılır. Başka bir branch'e push yok
   sayılır.
3. Projenin bir yeniden indekslemesi kuyruğa alınır; bu, o projenin (yalnızca bu kaynağın değil) her
   kaynağını senkronize eder.

Yanıtlar: `202` kuyruğa alındı · `200` yok sayıldı (başka branch) · `401 invalid_signature` ·
`404` bilinmeyen kaynak.

## Secret'ı rotate etmek

Kaynak dialogundaki **Regenerate**, yeni bir secret üretir ve eskisini hemen geçersiz kılar. Yeniyi
depo ayarlarına yapıştırın; siz bunu yapana kadar teslimatlar `401` döner.

## Güvenlik notları

- Bu endpoint, `/api/*`'ın ne bir hesap ne de `ADMIN_TOKEN` alan tek parçasıdır — git host'u
  hiçbirini tutamaz. Tüm savunması, herhangi bir iş kuyruğa alınmadan önce ham gövdeye karşı
  constant-time bir karşılaştırmayla doğrulanan imzadır.
- Her kaynağın kendi secret'ı vardır, bu yüzden bir sızıntı yalnızca bir kaynağı etkiler ve kendi
  başına rotate edilir.
- Sızdırılmış bir secret'ın izin verdiği en kötü şey, o kaynağın projesi için yeniden indeksleme
  çalışmaları tetiklemektir. Endpoint hiçbir veriyi açığa çıkarmaz.

## Sorun giderme

| Belirti | Neden |
|---------|-------|
| `401 invalid_signature` | Depo ayarlarındaki secret, şu anda saklanan ile aynı değil. Yeniden kopyalayın ya da yeniden üretip yenisini yapıştırın |
| Teslimat başarılı ama hiçbir şey indekslenmiyor | Push, kaynağınkinden farklı bir branch'e yapılmış. Kaynak dialogundaki branch'i kontrol edin |
| Git host URL'ye ulaşamıyor | Sunucu internetten erişilebilir değil. Bir tünel kullanın ya da zamanlanmış bir `POST /api/projects/:id/reindex`'e geri dönün |
| `404` | Kaynak silinmiş, ya da bir git kaynağı değil |
| Confluence: `401 not_enabled` | Kaynağın webhook'u kapalı. *Confluence webhook* kutusunda **Turn on**'a basın ve yeni secret'ı Confluence'a yapıştırın |

## Webhook olmadan

Zamanlanmış herhangi bir job, aynı şeyi [Admin API](/tr/docs/admin-api/) üzerinden yapabilir:

```bash
curl -X POST http://localhost:3444/api/projects/$PROJECT_ID/reindex \
     -H "Authorization: Bearer $ADMIN_TOKEN"
```

`ADMIN_TOKEN`, böyle bir job için kimlik bilgisidir — betikler için tasarlanmıştır ve bir session
cookie'si bir cron girdisinin tutabileceği bir şey değildir. Bkz. [Admin API](/tr/docs/admin-api/).

İndeksleme artımlı olduğu için, bunu birkaç dakikada bir çalıştırmak, hiçbir şey değişmediğinde
neredeyse hiçbir şeye mal olmaz — Notion de bu kuraldan muaf değil, farklı: doğrulandıktan sonra kendi
push webhook'unu da teslim eder, ama secret yukarıdaki kalıbın tersi yönde akar. Bunun nasıl
doğrulandığı ve senkronizasyon için ne anlama geldiği için bkz.
[Notion](/tr/docs/notion/#senkronize-tutmak).
