React Uygulamalarını Ubuntu 16.04 Üzerinde Webhook ve Slack ile Otomatik Dağıtma
Giriş
Günümüz modern web geliştirme süreçlerinde, uygulamaların hızlı ve güvenilir bir şekilde canlı ortama alınması kritik öneme sahiptir. Özellikle React gibi popüler ön yüz kütüphaneleriyle geliştirilen uygulamaların dağıtımı, manuel adımlarla yapıldığında zaman alıcı, hataya açık ve verimsiz olabilir. Sürekli Entegrasyon ve Sürekli Dağıtım (CI/CD) yaklaşımları bu sorunlara çözüm sunar. Bu makalede, bir React uygulamasını Ubuntu 16.04 sunucusu üzerinde, Git deposundaki her “push” işleminde otomatik olarak dağıtmak için Webhook’ları ve dağıtım sürecinin durumunu Slack üzerinden bildirmek için entegrasyonu nasıl kuracağımızı ayrıntılı olarak inceleyeceğiz. Ubuntu 16.04, uzun süreli destek (LTS) sağlayan ve birçok üretim ortamında hala kullanılan kararlı bir işletim sistemidir. Bu kurulum, geliştiricilere zaman kazandırırken, dağıtım sürecini standartlaştırarak olası hataları minimize etmeyi amaçlamaktadır. Otomatik dağıtım, ekiplerin daha sık ve güvenle sürüm çıkarmasına olanak tanır, bu da ürün geliştirme döngüsünü hızlandırır.
Ön Koşullar ve Gerekli Araçlar
Bu rehbere başlamadan önce aşağıdaki ön koşulların yerine getirilmiş olması gerekmektedir:
Ubuntu 16.04 Sunucusu
Uygulamanızı barındıracak ve webhook sunucusunu çalıştıracak bir Ubuntu 16.04 sunucusuna ihtiyacınız var. Sunucuya SSH erişiminizin olduğundan ve sudo yetkilerine sahip bir kullanıcıyla oturum açabildiğinizden emin olun. Bu sunucu üzerinde gerekli tüm yazılımları kuracağız ve React uygulamasını çalıştıracağız.
Node.js ve npm
React uygulamaları Node.js çalışma zamanı ortamını ve npm (Node Package Manager) paket yöneticisini gerektirir. Ayrıca, webhook sunucumuz da Node.js üzerinde çalışacaktır. Sunucunuzda Node.js ve npm’in kurulu olması gerekmektedir.
Git
Kaynak kodunuzu yönetmek için Git sürüm kontrol sistemine ihtiyacımız var. React uygulamanızın kodu bir Git deposunda (GitHub, GitLab, Bitbucket vb.) barındırılmalıdır. Sunucuda da Git’in kurulu olması, depoyu klonlamak ve güncellemeleri çekmek için gereklidir.
Nginx
Nginx, hem React uygulamanız için ters proxy (reverse proxy) görevi görecek hem de webhook sunucunuza gelen istekleri yönlendirecektir. Bu, uygulamanızın 80 veya 443 portu üzerinden erişilebilir olmasını sağlar ve aynı zamanda birden fazla servisi tek bir sunucu üzerinde yönetmenize olanak tanır.
PM2
PM2, Node.js uygulamaları için gelişmiş bir üretim süreci yöneticisidir. Uygulamalarınızın sürekli çalışmasını sağlar, çökme durumunda otomatik olarak yeniden başlatır ve yük dengeleme gibi özellikler sunar. Hem React uygulamasını (build sonrası statik dosyaları Nginx sunsa da, bazı durumlarda SSR için Node.js tabanlı sunucu gerekebilir veya webhook sunucusu için) hem de webhook sunucumuzu PM2 ile yöneteceğiz.
Slack Çalışma Alanı ve Gelen Webhook
Dağıtım süreçlerinin bildirimlerini almak için bir Slack çalışma alanına ve bu çalışma alanında yapılandırılmış bir “Gelen Webhook” entegrasyonuna ihtiyacınız olacak. Bu, uygulamanızın veya webhook sunucunuzun Slack kanalına mesaj göndermesini sağlar.
GitHub/GitLab/Bitbucket Hesabı
React uygulamanızın kaynak kodunu barındıran bir Git deposu hizmeti. Bu hizmetler, depoya her “push” yapıldığında belirli bir URL’ye HTTP POST isteği gönderme yeteneği olan webhook’ları yapılandırmanıza olanak tanır.
Proje Yapılandırması ve Sunucu Hazırlığı
React Uygulaması Oluşturma (veya Mevcut Uygulama)
Eğer mevcut bir React uygulamanız yoksa, create-react-app ile yeni bir proje oluşturabilirsiniz:
npx create-react-app my-react-app
cd my-react-app
Mevcut bir uygulamanız varsa, projenizin kök dizininde olduğunuzdan emin olun. Uygulamanızın package.json dosyasında build komutunun tanımlı olduğundan emin olun (genellikle react-scripts build şeklindedir). Bu komut, üretim için optimize edilmiş statik dosyaları oluşturacaktır.
Git Deposu Oluşturma
React uygulamanızın kodunu GitHub, GitLab veya Bitbucket gibi bir hizmette bir Git deposuna yükleyin.
git init
git add .
git commit -m "Initial commit"
git remote add origin
git push -u origin master
Bu adımlar, yerel projenizi uzak bir depoya bağlar.
Sunucuya SSH Erişimi
Sunucunuza SSH ile bağlanın:
ssh user@your_server_ip
user yerine kendi kullanıcı adınızı, your_server_ip yerine sunucunuzun IP adresini yazın.
Node.js ve npm Kurulumu
Ubuntu 16.04 üzerinde Node.js’nin en son sürümünü kurmak için NodeSource deposunu kullanmak en iyisidir:
curl -sL https://deb.nodesource.com/setup_16.x | sudo -E bash -
sudo apt-get install -y nodejs
Kurulumu doğrulayın:
node -v
npm -v
Git Kurulumu
Git, genellikle Ubuntu sistemlerinde önceden yüklüdür. Değilse, kolayca kurabilirsiniz:
sudo apt-get update
sudo apt-get install git -y
Kurulumu doğrulayın:
git --version
Nginx Kurulumu ve Temel Yapılandırması
Nginx’i kurun:
sudo apt-get update
sudo apt-get install nginx -y
Nginx’in çalıştığından emin olun:
sudo systemctl start nginx
sudo systemctl enable nginx
sudo systemctl status nginx
Şimdi React uygulamanız için bir Nginx yapılandırma dosyası oluşturun. Öncelikle, uygulamanızın dağıtılacağı dizini hazırlayalım.
PM2 Kurulumu
PM2’yi global olarak kurun:
sudo npm install pm2@latest -g
PM2’nin sistem başlangıcında otomatik olarak başlamasını sağlayın:
sudo pm2 startup systemd
pm2 save
Bu komutlar, PM2’nin sunucu yeniden başlatıldığında uygulamalarınızı otomatik olarak başlatmasını sağlar.
Uygulama Dizini Oluşturma ve İzinler
React uygulamanızı sunucuda barındıracağınız bir dizin oluşturun. Örneğin:
sudo mkdir -p /var/www/my-react-app
sudo chown -R user:user /var/www/my-react-app # user yerine kendi kullanıcı adınız
Bu dizine Git deponuzu klonlayın:
cd /var/www/my-react-app
git clone .
Klonlama işleminden sonra, bağımlılıkları yükleyin ve uygulamayı derleyin:
npm install
npm run build
Nginx yapılandırması için, React uygulamasının build çıktısının bulunduğu dizini işaret etmemiz gerekecek (genellikle /var/www/my-react-app/build).
Şimdi Nginx yapılandırma dosyasını oluşturalım:
sudo nano /etc/nginx/sites-available/my-react-app
İçeriği aşağıdaki gibi doldurun (alan adınızı ve uygulama dizininizi güncellemeyi unutmayın):
server {
listen 80;
server_name your_domain_or_ip; # Alan adınızı veya IP adresinizi buraya yazın
root /var/www/my-react-app/build; # React uygulamanızın build çıktısının yolu
index index.html index.htm;
location / {
try_files $uri $uri/ /index.html; # React router için gerekli
}
# SSL yapılandırması daha sonra eklenebilir
# listen 443 ssl;
# ssl_certificate /etc/letsencrypt/live/your_domain/fullchain.pem;
# ssl_certificate_key /etc/letsencrypt/live/your_domain/privkey.pem;
}
Yapılandırmayı etkinleştirin ve Nginx’i yeniden başlatın:
sudo ln -s /etc/nginx/sites-available/my-react-app /etc/nginx/sites-enabled/
sudo nginx -t
sudo systemctl restart nginx
Artık your_domain_or_ip adresine gittiğinizde React uygulamanızı görmelisiniz.
Webhook Sunucusu Kurulumu
Webhook Nedir ve Neden Kullanılır?
Webhook, bir olay meydana geldiğinde belirli bir URL’ye otomatik olarak HTTP POST isteği gönderen bir mekanizmadır. Git depolarında, bir kod “push” edildiğinde, bir “pull request” açıldığında veya kapatıldığında gibi olayları tetiklemek için kullanılırlar. Bizim senaryomuzda, Git deposuna her “push” yapıldığında, depo hizmeti (GitHub, GitLab vb.) webhook sunucumuza bir bildirim gönderecek ve bu bildirim dağıtım sürecimizi tetikleyecektir. Bu, manuel müdahaleye gerek kalmadan otomatik dağıtım sağlar.
Basit Bir Webhook Sunucusu Oluşturma (Node.js ve Express ile)
Webhook sunucumuzu /var/www/webhook-server gibi ayrı bir dizinde oluşturalım.
sudo mkdir -p /var/www/webhook-server
sudo chown -R user:user /var/www/webhook-server
cd /var/www/webhook-server
Yeni bir Node.js projesi başlatın ve gerekli paketleri yükleyin:
npm init -y
npm install express body-parser crypto axios
* express: Web sunucusu oluşturmak için.
* body-parser: Gelen POST isteklerinin gövdesini ayrıştırmak için.
* crypto: Webhook’un güvenliğini sağlamak için gizli anahtarı doğrulamak için.
* axios: Slack’e bildirim göndermek için HTTP istekleri yapmak için.
Şimdi index.js dosyasını oluşturalım:
// /var/www/webhook-server/index.js
const express = require('express');
const bodyParser = require('body-parser');
const crypto = require('crypto');
const { exec } = require('child_process');
const axios = require('axios');
const app = express();
const port = 3001; // Webhook sunucusunun çalışacağı port
// Güvenlik için ortam değişkenlerini kullanın
const WEBHOOK_SECRET = process.env.WEBHOOK_SECRET || 'YOUR_SECRET_KEY'; // GitHub/GitLab'da tanımlayacağınız gizli anahtar
const SLACK_WEBHOOK_URL = process.env.SLACK_WEBHOOK_URL || 'YOUR_SLACK_WEBHOOK_URL'; // Slack gelen webhook URL'niz
const DEPLOY_SCRIPT_PATH = process.env.DEPLOY_SCRIPT_PATH || '/var/www/my-react-app/deploy.sh'; // Dağıtım betiğinizin yolu
// JSON payload'ları için body-parser
app.use(bodyParser.json());
// Slack'e bildirim gönderme fonksiyonu
const sendSlackNotification = async (message, color = '#36a64f') => {
try {
await axios.post(SLACK_WEBHOOK_URL, {
attachments: [{
fallback: message,
color: color,
pretext: 'Dağıtım Bildirimi',
text: message,
ts: Math.floor(new Date().getTime() / 1000)
}]
});
console.log('Slack bildirimi gönderildi.');
} catch (error) {
console.error('Slack bildirimi gönderilirken hata oluştu:', error.message);
}
};
// Webhook endpoint
app.post('/webhook', (req, res) => {
const signature = req.headers['x-hub-signature'] || req.headers['x-gitlab-token']; // GitHub veya GitLab başlığı
const event = req.headers['x-github-event'] || req.headers['x-gitlab-event'];
// GitHub için güvenlik kontrolü (GitLab için farklı bir yöntem gerekebilir)
if (event === 'push' && signature) {
const hmac = crypto.createHmac('sha1', WEBHOOK_SECRET);
const digest = 'sha1=' + hmac.update(JSON.stringify(req.body)).digest('hex');
if (digest !== signature) {
console.warn('Webhook imzası doğrulanamadı. Yetkisiz erişim denemesi.');
return res.status(403).send('Webhook imzası geçersiz.');
}
} else if (event === 'push' && req.headers['x-gitlab-token']) {
// GitLab için güvenlik kontrolü
if (req.headers['x-gitlab-token'] !== WEBHOOK_SECRET) {
console.warn('GitLab Webhook tokenı doğrulanamadı. Yetkisiz erişim denemesi.');
return res.status(403).send('Webhook tokenı geçersiz.');
}
} else {
console.warn('Desteklenmeyen veya imzasız webhook isteği.');
return res.status(400).send('Webhook isteği geçersiz.');
}
// Sadece master/main branch'e yapılan push'ları dinle
const branch = req.body.ref.split('/').pop();
if (branch !== 'master' && branch !== 'main') {
console.log(Push ${branch} dalına yapıldı, dağıtım atlanıyor.);
return res.status(200).send('Başka bir dala push yapıldı, dağıtım atlandı.');
}
console.log('Webhook tetiklendi, dağıtım başlatılıyor...');
sendSlackNotification(Dağıtım başlatılıyor... Git commit: ${req.body.head_commit.message} (${req.body.head_commit.id.substring(0, 7)}), '#FFD700'); // Sarı renk
// Dağıtım betiğini çalıştır
exec(bash ${DEPLOY_SCRIPT_PATH}, (error, stdout, stderr) => {
if (error) {
console.error(Dağıtım hatası: ${error});
sendSlackNotification(Dağıtım BAŞARISIZ oldu: ${error.message}, '#FF0000'); // Kırmızı renk
return res.status(500).send('Dağıtım hatası.');
}
if (stderr) {
console.error(Dağıtım stderr: ${stderr});
sendSlackNotification(Dağıtım tamamlandı (stderr mevcut): ${stderr}, '#FFA500'); // Turuncu renk
}
console.log(Dağıtım başarılı: ${stdout});
sendSlackNotification(Dağıtım BAŞARILI!, '#008000'); // Yeşil renk
res.status(200).send('Dağıtım başlatıldı.');
});
});
app.listen(port, () => {
console.log(Webhook sunucusu http://localhost:${port} adresinde çalışıyor.);
});
Güvenlik Notu: WEBHOOK_SECRET ve SLACK_WEBHOOK_URL gibi hassas bilgileri doğrudan kodda tutmak yerine ortam değişkenleri veya bir yapılandırma dosyası aracılığıyla yönetmek en iyi uygulamadır. PM2 ile başlatırken ortam değişkenlerini ayarlayacağız.
Webhook Sunucusunu PM2 ile Yönetme
Webhook sunucusunun sürekli çalışmasını sağlamak için PM2’yi kullanın.
Öncelikle, ortam değişkenlerini ayarlayacağımız bir .env dosyası oluşturalım (veya doğrudan PM2 start komutunda belirtebiliriz):
nano /var/www/webhook-server/.env
İçeriği:
WEBHOOK_SECRET=your_super_secret_key_for_webhook
SLACK_WEBHOOK_URL=https://hooks.slack.com/services/T00000000/B00000000/XXXXXXXXXXXXXXXXXXXXXXXX
DEPLOY_SCRIPT_PATH=/var/www/my-react-app/deploy.sh
Şimdi PM2 ile webhook sunucusunu başlatın:
cd /var/www/webhook-server
pm2 start index.js --name webhook-server --env ./.env
pm2 save
pm2 save komutu, PM2’nin mevcut uygulamaları kaydetmesini ve sunucu yeniden başlatıldığında otomatik olarak başlatmasını sağlar.
Nginx ile Webhook Sunucusuna Reverse Proxy Kurulumu
Webhook sunucumuz 3001 portunda çalışıyor. Dışarıdan erişilebilir hale getirmek için Nginx’i ters proxy olarak yapılandırmamız gerekiyor.
Nginx yapılandırma dosyasını düzenleyin:
sudo nano /etc/nginx/sites-available/my-react-app # veya yeni bir dosya oluşturabilirsiniz
Aşağıdaki location bloğunu mevcut server bloğunun içine ekleyin:
location /webhook {
proxy_pass http://localhost:3001;
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection 'upgrade';
proxy_set_header Host $host;
proxy_cache_bypass $http_upgrade;
}
Nginx yapılandırmasını test edin ve yeniden başlatın:
sudo nginx -t
sudo systemctl restart nginx
Artık your_domain_or_ip/webhook adresine yapılan istekler, 3001 portundaki webhook sunucunuza yönlendirilecektir.
Uygulama Dağıtım Betiği (Deployment Script)
Webhook sunucumuzun çalıştıracağı dağıtım betiğini /var/www/my-react-app/deploy.sh yolunda oluşturalım. Bu betik, Git deposundan en son kodu çekecek, bağımlılıkları yükleyecek, React uygulamasını derleyecek ve Nginx’in statik dosyaları sunmasını sağlayacaktır.
#!/bin/bash
APP_DIR="/var/www/my-react-app"
LOG_FILE="$APP_DIR/deploy.log"
SLACK_WEBHOOK_URL="YOUR_SLACK_WEBHOOK_URL" # Ortam değişkeninden de okunabilir, ama betik içinde de tanımlanabilir.
Slack'e bildirim gönderme fonksiyonu (betik içinde)
send_slack_notification() {
local message=$1
local color=$2
curl -X POST -H 'Content-type: application/json' --data "{
\"attachments\": [{
\"fallback\": \"$message\",
\"color\": \"$color\",
\"pretext\": \"Dağıtım Bildirimi (Beti̇k)\",
\"text\": \"$message\",
\"ts\": $(date +%s)
}]
}" $SLACK_WEBHOOK_URL >> $LOG_FILE 2>&1
}
echo "----------------------------------------------------" >> $LOG_FILE
echo "$(date): Dağıtım betiği başlatıldı." >> $LOG_FILE
cd $APP_DIR || { echo "$(date): APP_DIR'a geçilemedi. Çıkılıyor." >> $LOG_FILE; send_slack_notification "Dağıtım BAŞARISIZ: APP_DIR'a geçilemedi." "#FF0000"; exit 1; }
Git pull
echo "$(date): Git pull yapılıyor..." >> $LOG_FILE
git pull origin master >> $LOG_FILE 2>&1 || { echo "$(date): Git pull başarısız oldu." >> $LOG_FILE; send_slack_notification "Dağıtım BAŞARISIZ: Git pull hatası." "#FF0000"; exit 1; }
echo "$(date): Git pull tamamlandı." >> $LOG_FILE
npm install
echo "$(date): npm bağımlılıkları yükleniyor..." >> $LOG_FILE
npm install --prefix $APP_DIR >> $LOG_FILE 2>&1 || { echo "$(date): npm install başarısız oldu." >> $LOG_FILE; send_slack_notification "Dağıtım BAŞARISIZ: npm install hatası." "#FF0000"; exit 1; }
echo "$(date): npm bağımlılıkları yüklendi." >> $LOG_FILE
npm run build
echo "$(date): React uygulaması derleniyor..." >> $LOG_FILE
npm run build --prefix $APP_DIR >> $LOG_FILE 2>&1 || { echo "$(date): npm run build başarısız oldu." >> $LOG_FILE; send_slack_notification "Dağıtım BAŞARISIZ: npm run build hatası." "#FF0000"; exit 1; }
echo "$(date): React uygulaması başarıyla derlendi." >> $LOG_FILE
Nginx'in statik dosyaları yeniden yüklemesi için bir şeye ihtiyacı yok, build dizini değiştiğinde otomatik olarak yeni dosyaları sunar.
Ancak, eğer Nginx yapılandırması değiştiyse veya cache temizlenmesi gerekiyorsa:
sudo systemctl reload nginx >> $LOG_FILE 2>&1
echo "$(date): Dağıtım başarıyla tamamlandı." >> $LOG_FILE
send_slack_notification "Dağıtım BAŞARILI!" "#008000"
exit 0
Önemli Notlar:
* APP_DIR ve SLACK_WEBHOOK_URL değişkenlerini kendi değerlerinizle güncelleyin.
* deploy.sh betiğine çalıştırma izni verin: chmod +x /var/www/my-react-app/deploy.sh
* Betik içindeki npm install --prefix $APP_DIR ve npm run build --prefix $APP_DIR komutları, betiğin çalıştığı dizin farklı olsa bile doğru uygulama dizininde çalışmasını sağlar.
* Bu betik, sudo gerektiren komutlar (Nginx reload gibi) içermiyor. Eğer kullanıcınızın bu komutları çalıştırması gerekiyorsa, sudoers dosyasında uygun izinleri ayarlamanız gerekebilir veya bu komutları sudo ile çalıştırmanız gerekebilir. Ancak Nginx statik dosyaları doğrudan sunduğu için genellikle reload işlemine gerek kalmaz.
Git Deposu Webhook Yapılandırması
Şimdi Git deponuzda (GitHub, GitLab, Bitbucket) webhook’u yapılandırma zamanı.
GitHub İçin:
1. Deponuzda “Settings” (Ayarlar) sekmesine gidin.
2. Sol menüden “Webhooks” (Webhook’lar) seçeneğini tıklayın.
3. “Add webhook” (Webhook ekle) düğmesine tıklayın.
4. Payload URL: http://your_domain_or_ip/webhook adresini girin (HTTPS kullanıyorsanız https ile başlayın).
5. Content type: application/json olarak seçin.
6. Secret: WEBHOOK_SECRET olarak belirlediğiniz gizli anahtarı girin. Bu anahtar, webhook sunucunuzun isteğin GitHub’dan geldiğini doğrulamak için kullanılır.
7. Which events would you like to trigger this webhook?: Sadece “Just the push event” (Sadece push olayı) seçeneğini işaretleyin.
8. “Add webhook” düğmesine tıklayın.
GitLab İçin:
1. Deponuzda “Settings” (Ayarlar) -> “Webhooks” (Webhook’lar) bölümüne gidin.
2. URL: http://your_domain_or_ip/webhook adresini girin.
3. Secret Token: WEBHOOK_SECRET olarak belirlediğiniz gizli anahtarı girin.
4. Trigger: “Push events” (Push olayları) seçeneğini işaretleyin. İsterseniz belirli dallar için filtreleme yapabilirsiniz.
5. “Add webhook” düğmesine tıklayın.
Bitbucket İçin:
1. Deponuzda “Repository settings” (Depo ayarları) -> “Webhooks” (Webhook’lar) bölümüne gidin.
2. “Add webhook” (Webhook ekle) düğmesine tıklayın.
3. Title: Webhook’unuza bir isim verin (örn. “React Dağıtım”).
4. URL: http://your_domain_or_ip/webhook adresini girin.
5. Secret: WEBHOOK_SECRET olarak belirlediğiniz gizli anahtarı girin.
6. Triggers: “Repository push” (Depo push) olayını seçin.
7. “Save” (Kaydet) düğmesine tıklayın.
Slack Entegrasyonu Detayları
Slack entegrasyonu, dağıtım sürecinin her adımını ve sonucunu ekip üyelerine anında bildirerek şeffaflık ve hızlı geri bildirim sağlar.
Slack Gelen Webhook Oluşturma
1. Slack çalışma alanınızda “Apps” (Uygulamalar) bölümüne gidin (veya https://yourworkspace.slack.com/apps/manage adresine gidin).
2. “Incoming Webhooks” (Gelen Webhook’lar) uygulamasını arayın ve ekleyin.
3. Gelen Webhook’u yapılandırın. Bildirimlerin gönderileceği bir kanal seçin (örn. #deployments).
4. Yapılandırmayı kaydettikten sonra size bir “Webhook URL” verilecektir. Bu URL, SLACK_WEBHOOK_URL değişkeni için kullanacağınız adrestir. Bu URL’yi gizli tutun.
Webhook Sunucusunda Slack Bildirimlerini Tetikleme
Yukarıdaki index.js dosyasında sendSlackNotification fonksiyonunu zaten tanımladık. Bu fonksiyon, dağıtımın başlangıcında, başarısız olduğunda ve başarılı olduğunda Slack’e mesaj göndermek için kullanılır.
* Başlangıç: sendSlackNotification('Dağıtım başlatılıyor...', '#FFD700'); (Sarı)
* Başarısız: sendSlackNotification('Dağıtım BAŞARISIZ oldu...', '#FF0000'); (Kırmızı)
* Başarılı: sendSlackNotification('Dağıtım BAŞARILI!', '#008000'); (Yeşil)
Bu mesajlar, ilgili Slack kanalında dağıtımın anlık durumunu gösterir.
Test ve Doğrulama
Tüm kurulumları tamamladıktan sonra sisteminizi test etme zamanı.
1. React uygulamanızda küçük bir değişiklik yapın. Örneğin, src/App.js dosyasındaki bir metni değiştirin.
2. Değişikliği Git deposuna gönderin:
git add .
git commit -m "Test: Webhook dağıtımını test ediyorum."
git push origin master
3. Slack bildirimlerini kontrol edin. Kısa bir süre sonra Slack kanalınızda “Dağıtım başlatılıyor…”, ardından “Dağıtım BAŞARILI!” mesajlarını görmelisiniz. Eğer bir hata varsa, hata mesajını ve kırmızı renkli bildirimi görürsünüz.
4. Tarayıcınızda React uygulamanızın URL’sini ziyaret edin. Yaptığınız değişikliğin canlıda güncellenmiş olduğunu görmelisiniz. Eğer güncellenmediyse, tarayıcı önbelleğini temizlemeyi deneyin veya Nginx loglarını kontrol edin.
5. Sunucu loglarını kontrol edin.
* Webhook sunucusu logları: pm2 logs webhook-server
* Dağıtım betiği logları: /var/www/my-react-app/deploy.log
* Nginx hata logları: /var/log/nginx/error.log
Güvenlik Hususları
Otomatik dağıtım sistemleri, doğru şekilde yapılandırılmazsa önemli güvenlik riskleri taşıyabilir.
1. Webhook Gizli Anahtarı (Secret Key): Webhook’unuz için güçlü ve tahmin edilemez bir gizli anahtar kullanın. Bu anahtar, gelen isteklerin gerçekten Git hizmetinizden geldiğini doğrulamak için kullanılır. Webhook sunucunuzdaki WEBHOOK_SECRET değişkenini asla varsayılan veya basit bir değerle bırakmayın. Ortam değişkenleri aracılığıyla güvenli bir şekilde yönetin.
2. SSH Anahtarları: Git deposundan kod çekerken SSH anahtarlarını kullanmak, kullanıcı adı/şifre yerine daha güvenli bir yöntemdir. Sunucunuzda Git kullanıcısı için bir SSH anahtarı oluşturun ve bunu Git hizmetinize (GitHub, GitLab) ekleyin.
3. Sunucu Güvenlik Duvarı (UFW): Sunucunuzda güvenlik duvarını etkinleştirin ve sadece gerekli portlara (80, 443, 22) erişime izin verin. Webhook sunucunuzun çalıştığı portu (örn. 3001) sadece localhost üzerinden erişilebilir yapın ve Nginx’in bu portu dış dünyaya açmasına izin verin.
sudo ufw enable
sudo ufw allow ssh
sudo ufw allow http
sudo ufw allow https
# Eğer Nginx webhook'u proxy etmiyorsa ve doğrudan açmak gerekiyorsa:
# sudo ufw allow 3001/tcp
4. Düşük Ayrıcalıklı Kullanıcılar: Dağıtım betiğini ve webhook sunucusunu çalıştıran kullanıcının minimum ayrıcalıklara sahip olduğundan emin olun. root kullanıcısı yerine özel bir dağıtım kullanıcısı oluşturmak daha güvenlidir.
5. HTTPS Kullanımı (Let’s Encrypt): Webhook URL’nizin HTTPS ile korunması zorunludur. Bu, gönderilen verilerin şifrelenmesini sağlar ve “man-in-the-middle” saldırılarını önler. Let’s Encrypt ile ücretsiz SSL sertifikaları alabilir ve Nginx’i HTTPS için yapılandırabilirsiniz.
sudo apt-get install certbot python-certbot-nginx -y
sudo certbot --nginx -d your_domain_or_ip
Bu komutlar, Nginx yapılandırmanızı otomatik olarak HTTPS için güncelleyecektir. Webhook URL’nizi de https://your_domain_or_ip/webhook olarak değiştirmeyi unutmayın.
Sorun Giderme ve İpuçları
Dağıtım sürecinde karşılaşabileceğiniz yaygın sorunlar ve çözüm yolları:
1. Webhook Tetiklenmiyor:
* Git deposu ayarlarındaki webhook URL’sini kontrol edin. Doğru IP adresi/alan adı ve /webhook yolunu içerdiğinden emin olun.
* Gizli anahtarın (secret key) hem Git deposunda hem de webhook sunucunuzda aynı olduğundan emin olun.
* Nginx’in webhook sunucusuna doğru şekilde proxy yaptığından emin olun. Nginx loglarını (/var/log/nginx/error.log, /var/log/nginx/access.log) kontrol edin.
* Webhook sunucusunun çalıştığından emin olun: pm2 status webhook-server.
* Güvenlik duvarının (UFW) Nginx’in 80/443 portlarına erişimi engellemediğinden emin olun.
2. Dağıtım Betiği Çalışmıyor veya Hata Veriyor:
* deploy.sh betiğinin çalıştırma iznine sahip olduğundan emin olun: chmod +x /var/www/my-react-app/deploy.sh.
* Betiğin içindeki yolların (APP_DIR vb.) doğru olduğundan emin olun.
* deploy.log dosyasını kontrol edin. Betiğin çıktısı ve hataları buraya yazılacaktır.
* npm install veya npm run build komutlarının manuel olarak çalıştırıldığında hata verip vermediğini kontrol edin.
* Webhook sunucusu loglarını (pm2 logs webhook-server) kontrol edin. exec komutunun çıktısı burada görünebilir.
3. React Uygulaması Güncellenmiyor:
* npm run build komutunun başarıyla çalıştığından ve yeni dosyaları /var/www/my-react-app/build dizinine yazdığından emin olun.
* Nginx yapılandırmasının root dizininin doğru build klasörünü işaret ettiğinden emin olun.
* Tarayıcı önbelleğini temizleyin veya farklı bir tarayıcıda deneyin.
4. Slack Bildirimleri Gelmiyor:
* SLACK_WEBHOOK_URL değişkeninin doğru ve aktif bir Slack gelen webhook URL’si olduğundan emin olun.
* Webhook sunucusu loglarını kontrol edin; Slack’e POST isteği yapılırken bir hata oluşup oluşmadığını kontrol edin.
* Curl komutuyla manuel olarak Slack’e mesaj göndermeyi deneyerek URL’nin çalıştığını doğrulayın.
Sonuç
Bu makalede, React uygulamalarını Ubuntu 16.04 sunucusu üzerinde Webhook’lar ve Slack entegrasyonu ile otomatik olarak dağıtmanın kapsamlı bir yolunu inceledik. Node.js ve Express ile basit bir webhook sunucusu oluşturduk, PM2 ile süreç yönetimini sağladık, Nginx ile ters proxy yapılandırdık ve dağıtım sürecini otomatikleştiren bir shell betiği yazdık. Ayrıca, güvenlik hususlarına ve yaygın sorun giderme ipuçlarına da değindik.
Bu kurulum, geliştiricilerin kodlarını daha hızlı ve güvenle canlıya almasını sağlayarak manuel dağıtımın getirdiği hataları ve zaman kaybını ortadan kaldırır. Slack entegrasyonu sayesinde ekip üyeleri, dağıtım süreçlerinin durumu hakkında anında bilgi sahibi olur. Otomatik dağıtım, modern yazılım geliştirme pratiklerinin temel bir bileşeni olup, sürekli entegrasyon ve sürekli teslimat (CI/CD) döngülerinin ayrılmaz bir parçasıdır. Bu sistem, daha verimli, daha güvenilir ve daha şeffaf bir geliştirme süreci sunar. Gelecekte, bu kurulumu HTTPS ile daha da güçlendirmek ve belki de daha gelişmiş CI/CD araçlarıyla (Jenkins, GitLab CI/CD, GitHub Actions gibi) entegre etmek, süreci daha da optimize edebilir.
