refactor(ui,docs): Job terimini Test olarak güncelle #2
30
README.md
30
README.md
@@ -21,7 +21,7 @@
|
|||||||
- **Korumalı Endpoint'ler**: JWT middleware ile korunan API endpoint'leri
|
- **Korumalı Endpoint'ler**: JWT middleware ile korunan API endpoint'leri
|
||||||
- **Environment Security**: Hassas bilgilerin güvenli .env dosyasında saklanması
|
- **Environment Security**: Hassas bilgilerin güvenli .env dosyasında saklanması
|
||||||
|
|
||||||
### 📊 Job Yönetim Sistemi
|
### 🧪 Test Yönetim Sistemi
|
||||||
- **Repository Otomasyonu**: Otomatik git clone/pull işlemleri
|
- **Repository Otomasyonu**: Otomatik git clone/pull işlemleri
|
||||||
- **Zaman Tabanlı Çalıştırma**: Dakika/saat/gün bazında otomatik test çalıştırma
|
- **Zaman Tabanlı Çalıştırma**: Dakika/saat/gün bazında otomatik test çalıştırma
|
||||||
- **Real-time Durum Güncellemesi**: Socket.io ile anlık durum takibi
|
- **Real-time Durum Güncellemesi**: Socket.io ile anlık durum takibi
|
||||||
@@ -38,7 +38,7 @@
|
|||||||
### ⚡ Gerçek Zamanlı İletişim
|
### ⚡ Gerçek Zamanlı İletişim
|
||||||
- **WebSocket Bağlantısı**: Socket.io ile sürekli iletişim
|
- **WebSocket Bağlantısı**: Socket.io ile sürekli iletişim
|
||||||
- **Sayaç Yayınınlaması**: Global sayaç ve işlemler
|
- **Sayaç Yayınınlaması**: Global sayaç ve işlemler
|
||||||
- **Canlı Güncellemeler**: Job durumlarının anlık bildirilmesi
|
- **Canlı Güncellemeler**: Test durumlarının anlık bildirilmesi
|
||||||
- **Ping/Pong**: Bağlantı kontrolü
|
- **Ping/Pong**: Bağlantı kontrolü
|
||||||
|
|
||||||
### 🎨 Modern Arayüz
|
### 🎨 Modern Arayüz
|
||||||
@@ -202,24 +202,24 @@ docker compose up -d --build
|
|||||||
- **Şifre**: `supersecret`
|
- **Şifre**: `supersecret`
|
||||||
3. Giriş yap butonuna tıklayın
|
3. Giriş yap butonuna tıklayın
|
||||||
|
|
||||||
### Job Yönetimi
|
### Test Yönetimi
|
||||||
|
|
||||||
#### Yeni Job Oluşturma
|
#### Yeni Test Oluşturma
|
||||||
1. **Dashboard** menüsünden **Jobs** sayfasına gidin
|
1. **Dashboard** menüsünden **Tests** sayfasına gidin
|
||||||
2. **Yeni Job** butonuna tıklayın
|
2. **Yeni Test** butonuna tıklayın
|
||||||
3. Job bilgilerini girin:
|
3. Test bilgilerini girin:
|
||||||
- **Job Adı**: Tanımlayıcı bir isim
|
- **Test Adı**: Tanımlayıcı bir isim
|
||||||
- **Repository URL**: GitHub repository adresi
|
- **Repository URL**: GitHub repository adresi
|
||||||
- **Test Komutu**: Çalıştırılacak komut (örn: `npm test`)
|
- **Test Komutu**: Çalıştırılacak komut (örn: `npm test`)
|
||||||
- **Kontrol Aralığı**: Test sıklığı (dakika/saat/gün)
|
- **Kontrol Aralığı**: Test sıklığı (dakika/saat/gün)
|
||||||
- **Kontrol Değeri**: Sayısal değer
|
- **Kontrol Değeri**: Sayısal değer
|
||||||
4. Kaydet butonuna tıklayın
|
4. Kaydet butonuna tıklayın
|
||||||
|
|
||||||
#### Job İzleme
|
#### Test İzleme
|
||||||
- **Jobs Listesi**: Tüm job'ların durumunu gösterir
|
- **Tests Listesi**: Tüm test'lerin durumunu gösterir
|
||||||
- **Real-time Durum**: Socket.io ile anlık güncellemeler
|
- **Real-time Durum**: Socket.io ile anlık güncellemeler
|
||||||
- **Log Akışı**: Test çıktılarını canlı izleme
|
- **Log Akışı**: Test çıktılarını canlı izleme
|
||||||
- **Manuel Çalıştırma**: Job'u anında tetikleme
|
- **Manuel Çalıştırma**: Test'i anında tetikleme
|
||||||
|
|
||||||
### Deployment Yönetimi
|
### Deployment Yönetimi
|
||||||
1. **Deployments** sayfasına gidin
|
1. **Deployments** sayfasına gidin
|
||||||
@@ -250,7 +250,7 @@ docker compose up -d --build
|
|||||||
|
|
||||||
### 📖 API Referansı
|
### 📖 API Referansı
|
||||||
- **Authentication API'leri**: `/auth/login`, `/auth/me`
|
- **Authentication API'leri**: `/auth/login`, `/auth/me`
|
||||||
- **Job Yönetim API'leri**: CRUD operasyonları, manuel çalıştırma
|
- **Test Yönetim API'leri**: CRUD operasyonları, manuel çalıştırma
|
||||||
- **Deployment API'leri**: `/deployments`, `/deployments/:id`, `/deployments/scan`, `/deployments/branches`
|
- **Deployment API'leri**: `/deployments`, `/deployments/:id`, `/deployments/scan`, `/deployments/branches`
|
||||||
- **Webhook Endpoint**: `/api/deployments/webhook/:token`
|
- **Webhook Endpoint**: `/api/deployments/webhook/:token`
|
||||||
- **WebSocket Olayları**: Real-time iletişim ve durum güncellemeleri
|
- **WebSocket Olayları**: Real-time iletişim ve durum güncellemeleri
|
||||||
@@ -393,12 +393,12 @@ docker compose logs mongo
|
|||||||
|
|
||||||
### Mevcut Durum (v1.0)
|
### Mevcut Durum (v1.0)
|
||||||
- ✅ Temel CI/CD platformu
|
- ✅ Temel CI/CD platformu
|
||||||
- ✅ Real-time job yönetimi
|
- ✅ Real-time test yönetimi
|
||||||
- ✅ Modern web arayüzü
|
- ✅ Modern web arayüzü
|
||||||
- ✅ Konteyner orkestrasyonu
|
- ✅ Konteyner orkestrasyonu
|
||||||
|
|
||||||
### Gelecek Planlar
|
### Gelecek Planlar
|
||||||
- 🔄 **Multi-branch Support**: Farklı branch'ler için job yönetimi
|
- 🔄 **Multi-branch Support**: Farklı branch'ler için test yönetimi
|
||||||
- 🔔 **Bildirim Sistemi**: E-posta ve Slack bildirimleri
|
- 🔔 **Bildirim Sistemi**: E-posta ve Slack bildirimleri
|
||||||
- 📊 **Dashboard İstatistikleri**: Performans ve kullanım metrikleri
|
- 📊 **Dashboard İstatistikleri**: Performans ve kullanım metrikleri
|
||||||
- 🛡️ **Güvenlik İyileştirmeleri**: 2FA ve rate limiting
|
- 🛡️ **Güvenlik İyileştirmeleri**: 2FA ve rate limiting
|
||||||
@@ -406,7 +406,7 @@ docker compose logs mongo
|
|||||||
- 📝 **Custom Test Commands**: Esnek test komutu yapılandırması
|
- 📝 **Custom Test Commands**: Esnek test komutu yapılandırması
|
||||||
|
|
||||||
### E-post Listesi
|
### E-post Listesi
|
||||||
- 📊 **Dashboard İstatistikleri**: Job performans grafikleri
|
- 📊 **Dashboard İstatistikleri**: Test performans grafikleri
|
||||||
- 🔔 **Bildirim Kanalları**: Slack, Discord, Teams entegrasyonu
|
- 🔔 **Bildirim Kanalları**: Slack, Discord, Teams entegrasyonu
|
||||||
- 🔄 **Pipeline Integration**: GitHub Actions, GitLab CI entegrasyonu
|
- 🔄 **Pipeline Integration**: GitHub Actions, GitLab CI entegrasyonu
|
||||||
- 🏗️ **Template System**: Hazır proje şablonları
|
- 🏗️ **Template System**: Hazır proje şablonları
|
||||||
|
|||||||
@@ -22,7 +22,7 @@ export function DashboardLayout() {
|
|||||||
const navigation = useMemo(
|
const navigation = useMemo(
|
||||||
() => [
|
() => [
|
||||||
{ label: "Home", to: "/home", icon: faHouse },
|
{ label: "Home", to: "/home", icon: faHouse },
|
||||||
{ label: "Jobs", to: "/jobs", icon: faFlaskVial },
|
{ label: "Tests", to: "/jobs", icon: faFlaskVial },
|
||||||
{ label: "Deployments", to: "/deployments", icon: faRocket },
|
{ label: "Deployments", to: "/deployments", icon: faRocket },
|
||||||
{ label: "Settings", to: "/settings", icon: faGear }
|
{ label: "Settings", to: "/settings", icon: faGear }
|
||||||
],
|
],
|
||||||
|
|||||||
@@ -54,7 +54,7 @@ export function HomePage() {
|
|||||||
recentRuns: [],
|
recentRuns: [],
|
||||||
totals: { successRate: 0, totalRuns: 0 }
|
totals: { successRate: 0, totalRuns: 0 }
|
||||||
});
|
});
|
||||||
setError("Job metrikleri alınamadı");
|
setError("Test metrikleri alınamadı");
|
||||||
}
|
}
|
||||||
|
|
||||||
if (deployResult.status === "fulfilled") {
|
if (deployResult.status === "fulfilled") {
|
||||||
|
|||||||
@@ -79,7 +79,7 @@ export function JobDetailPage() {
|
|||||||
checkUnit: data.job.checkUnit
|
checkUnit: data.job.checkUnit
|
||||||
});
|
});
|
||||||
})
|
})
|
||||||
.catch(() => setError("Job bulunamadı"))
|
.catch(() => setError("Test bulunamadı"))
|
||||||
.finally(() => setLoading(false));
|
.finally(() => setLoading(false));
|
||||||
}, [id]);
|
}, [id]);
|
||||||
|
|
||||||
@@ -174,14 +174,14 @@ export function JobDetailPage() {
|
|||||||
|
|
||||||
const handleDelete = async () => {
|
const handleDelete = async () => {
|
||||||
if (!job?._id) return;
|
if (!job?._id) return;
|
||||||
const ok = window.confirm("Bu job'ı silmek istediğinize emin misiniz?");
|
const ok = window.confirm("Bu testi silmek istediğinize emin misiniz?");
|
||||||
if (!ok) return;
|
if (!ok) return;
|
||||||
try {
|
try {
|
||||||
await deleteJob(job._id);
|
await deleteJob(job._id);
|
||||||
toast.success("Job silindi");
|
toast.success("Test silindi");
|
||||||
navigate("/jobs", { replace: true });
|
navigate("/jobs", { replace: true });
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
toast.error("Job silinemedi");
|
toast.error("Test silinemedi");
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -203,7 +203,7 @@ export function JobDetailPage() {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
await updateJob(job._id, payload);
|
await updateJob(job._id, payload);
|
||||||
toast.success("Job güncellendi");
|
toast.success("Test güncellendi");
|
||||||
setJob((prev) =>
|
setJob((prev) =>
|
||||||
prev
|
prev
|
||||||
? {
|
? {
|
||||||
@@ -281,8 +281,8 @@ export function JobDetailPage() {
|
|||||||
className="h-10 w-10 transition hover:bg-emerald-100"
|
className="h-10 w-10 transition hover:bg-emerald-100"
|
||||||
onClick={handleEdit}
|
onClick={handleEdit}
|
||||||
disabled={!job}
|
disabled={!job}
|
||||||
title="Job'ı düzenle"
|
title="Testi düzenle"
|
||||||
aria-label="Job'ı düzenle"
|
aria-label="Testi düzenle"
|
||||||
>
|
>
|
||||||
<FontAwesomeIcon icon={faPen} className="h-4 w-4 text-foreground" />
|
<FontAwesomeIcon icon={faPen} className="h-4 w-4 text-foreground" />
|
||||||
</Button>
|
</Button>
|
||||||
@@ -292,8 +292,8 @@ export function JobDetailPage() {
|
|||||||
className="h-10 w-10 transition hover:bg-red-100"
|
className="h-10 w-10 transition hover:bg-red-100"
|
||||||
onClick={handleDelete}
|
onClick={handleDelete}
|
||||||
disabled={!job}
|
disabled={!job}
|
||||||
title="Job'ı sil"
|
title="Testi sil"
|
||||||
aria-label="Job'ı sil"
|
aria-label="Testi sil"
|
||||||
>
|
>
|
||||||
<FontAwesomeIcon icon={faTrash} className="h-4 w-4 text-foreground" />
|
<FontAwesomeIcon icon={faTrash} className="h-4 w-4 text-foreground" />
|
||||||
</Button>
|
</Button>
|
||||||
@@ -317,7 +317,7 @@ export function JobDetailPage() {
|
|||||||
</div>
|
</div>
|
||||||
)}
|
)}
|
||||||
<div className="flex w-full items-center gap-2">
|
<div className="flex w-full items-center gap-2">
|
||||||
<CardTitle>{job?.name || "Job Detayı"}</CardTitle>
|
<CardTitle>{job?.name || "Test Detayı"}</CardTitle>
|
||||||
<span className="inline-flex items-center gap-2 rounded-full border border-border bg-muted/50 px-3 py-1 text-xs font-semibold text-foreground">
|
<span className="inline-flex items-center gap-2 rounded-full border border-border bg-muted/50 px-3 py-1 text-xs font-semibold text-foreground">
|
||||||
<FontAwesomeIcon icon={faRepeat} className="h-3.5 w-3.5 text-foreground/80" />
|
<FontAwesomeIcon icon={faRepeat} className="h-3.5 w-3.5 text-foreground/80" />
|
||||||
{runCount} test
|
{runCount} test
|
||||||
@@ -368,7 +368,7 @@ export function JobDetailPage() {
|
|||||||
<div className="w-full max-w-lg rounded-lg border border-border bg-card card-shadow">
|
<div className="w-full max-w-lg rounded-lg border border-border bg-card card-shadow">
|
||||||
<div className="flex items-center justify-between border-b border-border px-5 py-4">
|
<div className="flex items-center justify-between border-b border-border px-5 py-4">
|
||||||
<div className="space-y-1">
|
<div className="space-y-1">
|
||||||
<div className="text-lg font-semibold text-foreground">Job Güncelle</div>
|
<div className="text-lg font-semibold text-foreground">Test Güncelle</div>
|
||||||
<div className="text-sm text-muted-foreground">Değişiklikler kaydedildiğinde test yeniden tetiklenecek.</div>
|
<div className="text-sm text-muted-foreground">Değişiklikler kaydedildiğinde test yeniden tetiklenecek.</div>
|
||||||
</div>
|
</div>
|
||||||
<Button variant="ghost" size="icon" onClick={() => setEditOpen(false)}>
|
<Button variant="ghost" size="icon" onClick={() => setEditOpen(false)}>
|
||||||
@@ -377,7 +377,7 @@ export function JobDetailPage() {
|
|||||||
</div>
|
</div>
|
||||||
<div className="space-y-4 px-5 py-4">
|
<div className="space-y-4 px-5 py-4">
|
||||||
<div className="space-y-2">
|
<div className="space-y-2">
|
||||||
<Label htmlFor="name">Job Name</Label>
|
<Label htmlFor="name">Test Name</Label>
|
||||||
<Input
|
<Input
|
||||||
id="name"
|
id="name"
|
||||||
value={form.name}
|
value={form.name}
|
||||||
|
|||||||
@@ -58,7 +58,7 @@ export function JobsPage() {
|
|||||||
const data = await fetchJobs();
|
const data = await fetchJobs();
|
||||||
setJobs(data);
|
setJobs(data);
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
toast.error("Jobs alınamadı");
|
toast.error("Testler alınamadı");
|
||||||
} finally {
|
} finally {
|
||||||
setLoading(false);
|
setLoading(false);
|
||||||
}
|
}
|
||||||
@@ -145,11 +145,11 @@ export function JobsPage() {
|
|||||||
j._id === updated._id ? { ...updated, runCount: j.runCount ?? updated.runCount } : j
|
j._id === updated._id ? { ...updated, runCount: j.runCount ?? updated.runCount } : j
|
||||||
)
|
)
|
||||||
);
|
);
|
||||||
toast.success("Job güncellendi");
|
toast.success("Test güncellendi");
|
||||||
} else {
|
} else {
|
||||||
const created = await createJob(payload);
|
const created = await createJob(payload);
|
||||||
setJobs((prev) => [{ ...created, runCount: created.runCount ?? 0 }, ...prev]);
|
setJobs((prev) => [{ ...created, runCount: created.runCount ?? 0 }, ...prev]);
|
||||||
toast.success("Job oluşturuldu");
|
toast.success("Test oluşturuldu");
|
||||||
}
|
}
|
||||||
setModalOpen(false);
|
setModalOpen(false);
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
@@ -163,9 +163,9 @@ export function JobsPage() {
|
|||||||
setRunningId(id);
|
setRunningId(id);
|
||||||
try {
|
try {
|
||||||
await runJob(id);
|
await runJob(id);
|
||||||
toast.success("Job çalıştırılıyor");
|
toast.success("Test çalıştırılıyor");
|
||||||
} catch {
|
} catch {
|
||||||
toast.error("Job çalıştırılamadı");
|
toast.error("Test çalıştırılamadı");
|
||||||
} finally {
|
} finally {
|
||||||
setRunningId(null);
|
setRunningId(null);
|
||||||
}
|
}
|
||||||
@@ -185,18 +185,18 @@ export function JobsPage() {
|
|||||||
<>
|
<>
|
||||||
<div className="flex items-center justify-between gap-4">
|
<div className="flex items-center justify-between gap-4">
|
||||||
<div>
|
<div>
|
||||||
<h2 className="text-xl font-semibold text-foreground">Jobs</h2>
|
<h2 className="text-xl font-semibold text-foreground">Tests</h2>
|
||||||
</div>
|
</div>
|
||||||
<Button onClick={handleOpenNew} className="gap-2">
|
<Button onClick={handleOpenNew} className="gap-2">
|
||||||
<FontAwesomeIcon icon={faPlus} className="h-4 w-4" />
|
<FontAwesomeIcon icon={faPlus} className="h-4 w-4" />
|
||||||
New Job
|
New Test
|
||||||
</Button>
|
</Button>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div className="grid gap-4">
|
<div className="grid gap-4">
|
||||||
{loading && (
|
{loading && (
|
||||||
<div className="rounded-md border border-border bg-muted/30 px-4 py-3 text-sm text-muted-foreground">
|
<div className="rounded-md border border-border bg-muted/30 px-4 py-3 text-sm text-muted-foreground">
|
||||||
Jobs yükleniyor...
|
Testler yükleniyor...
|
||||||
</div>
|
</div>
|
||||||
)}
|
)}
|
||||||
{!loading && jobs.length === 0 && (
|
{!loading && jobs.length === 0 && (
|
||||||
@@ -280,9 +280,9 @@ export function JobsPage() {
|
|||||||
<div className="w-full max-w-lg rounded-lg border border-border bg-card card-shadow">
|
<div className="w-full max-w-lg rounded-lg border border-border bg-card card-shadow">
|
||||||
<div className="flex items-center justify-between border-b border-border px-5 py-4">
|
<div className="flex items-center justify-between border-b border-border px-5 py-4">
|
||||||
<div className="space-y-1">
|
<div className="space-y-1">
|
||||||
<div className="text-lg font-semibold text-foreground">{isEdit ? "Job Güncelle" : "Yeni Job"}</div>
|
<div className="text-lg font-semibold text-foreground">{isEdit ? "Test Güncelle" : "Yeni Test"}</div>
|
||||||
<div className="text-sm text-muted-foreground">
|
<div className="text-sm text-muted-foreground">
|
||||||
Detayları girin, Jobs listesi canlı olarak güncellenecek.
|
Detayları girin, Tests listesi canlı olarak güncellenecek.
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<Button variant="ghost" size="icon" onClick={handleClose}>
|
<Button variant="ghost" size="icon" onClick={handleClose}>
|
||||||
@@ -291,7 +291,7 @@ export function JobsPage() {
|
|||||||
</div>
|
</div>
|
||||||
<div className="space-y-4 px-5 py-4">
|
<div className="space-y-4 px-5 py-4">
|
||||||
<div className="space-y-2">
|
<div className="space-y-2">
|
||||||
<Label htmlFor="name">Job Name</Label>
|
<Label htmlFor="name">Test Name</Label>
|
||||||
<Input
|
<Input
|
||||||
id="name"
|
id="name"
|
||||||
value={form.name}
|
value={form.name}
|
||||||
|
|||||||
Reference in New Issue
Block a user