Updates
This commit is contained in:
29
backend/src/models/jobRun.ts
Normal file
29
backend/src/models/jobRun.ts
Normal file
@@ -0,0 +1,29 @@
|
||||
import mongoose, { Schema, Document, Types } from "mongoose";
|
||||
import { JobDocument } from "./job.js";
|
||||
|
||||
export interface JobRunDocument extends Document {
|
||||
job: Types.ObjectId | JobDocument;
|
||||
status: "running" | "success" | "failed";
|
||||
logs: string[];
|
||||
startedAt: Date;
|
||||
finishedAt?: Date;
|
||||
durationMs?: number;
|
||||
createdAt: Date;
|
||||
updatedAt: Date;
|
||||
}
|
||||
|
||||
const JobRunSchema = new Schema<JobRunDocument>(
|
||||
{
|
||||
job: { type: Schema.Types.ObjectId, ref: "Job", required: true },
|
||||
status: { type: String, enum: ["running", "success", "failed"], required: true },
|
||||
logs: { type: [String], default: [] },
|
||||
startedAt: { type: Date, required: true },
|
||||
finishedAt: { type: Date },
|
||||
durationMs: { type: Number }
|
||||
},
|
||||
{ timestamps: true }
|
||||
);
|
||||
|
||||
JobRunSchema.index({ job: 1, startedAt: -1 });
|
||||
|
||||
export const JobRun = mongoose.model<JobRunDocument>("JobRun", JobRunSchema);
|
||||
@@ -2,6 +2,7 @@ import { Router } from "express";
|
||||
import { authMiddleware } from "../middleware/authMiddleware.js";
|
||||
import { Job } from "../models/job.js";
|
||||
import { jobService } from "../services/jobService.js";
|
||||
import { JobRun } from "../models/jobRun.js";
|
||||
|
||||
const router = Router();
|
||||
|
||||
@@ -16,7 +17,9 @@ router.get("/:id", async (req, res) => {
|
||||
const { id } = req.params;
|
||||
const job = await Job.findById(id).lean();
|
||||
if (!job) return res.status(404).json({ message: "Job bulunamadı" });
|
||||
return res.json(job);
|
||||
const lastRun = await JobRun.findOne({ job: id }).sort({ startedAt: -1 }).lean();
|
||||
const runCount = await JobRun.countDocuments({ job: id });
|
||||
return res.json({ job, lastRun, runCount });
|
||||
});
|
||||
|
||||
router.post("/", async (req, res) => {
|
||||
@@ -27,6 +30,8 @@ router.post("/", async (req, res) => {
|
||||
try {
|
||||
const job = await Job.create({ name, repoUrl, testCommand, checkValue, checkUnit });
|
||||
jobService.scheduleJob(job);
|
||||
// Yeni job oluşturulduğunda ilk test otomatik tetiklensin
|
||||
jobService.runJob(job._id.toString()).catch(() => undefined);
|
||||
return res.status(201).json(job);
|
||||
} catch (err) {
|
||||
return res.status(400).json({ message: "Job oluşturulamadı", error: (err as Error).message });
|
||||
|
||||
@@ -3,6 +3,7 @@ import path from "path";
|
||||
import { spawn } from "child_process";
|
||||
import { Server } from "socket.io";
|
||||
import { Job, JobDocument, TimeUnit } from "../models/job.js";
|
||||
import { JobRun } from "../models/jobRun.js";
|
||||
|
||||
const repoBaseDir = path.join(process.cwd(), "test-runs");
|
||||
|
||||
@@ -107,6 +108,8 @@ class JobService {
|
||||
private emitLog(jobId: string, line: string) {
|
||||
if (!this.io) return;
|
||||
this.io.to(`job:${jobId}`).emit("job:log", { jobId, line });
|
||||
// İlk koşu sırasında detay ekranı henüz subscribe olmamış olabilir; bu nedenle log'u yayına da gönder.
|
||||
this.io.except(`job:${jobId}`).emit("job:log", { jobId, line });
|
||||
}
|
||||
|
||||
async runJob(jobId: string) {
|
||||
@@ -114,15 +117,27 @@ class JobService {
|
||||
if (!job) return;
|
||||
|
||||
const startedAt = Date.now();
|
||||
const runLogs: string[] = [];
|
||||
const pushLog = (line: string) => {
|
||||
runLogs.push(line);
|
||||
this.emitLog(jobId, line);
|
||||
};
|
||||
|
||||
const runDoc = await JobRun.create({
|
||||
job: jobId,
|
||||
status: "running",
|
||||
startedAt: new Date()
|
||||
});
|
||||
|
||||
await Job.findByIdAndUpdate(jobId, { status: "running", lastMessage: "Çalıştırılıyor..." });
|
||||
this.emitStatus(jobId, { status: "running", lastMessage: "Çalıştırılıyor..." } as JobDocument);
|
||||
|
||||
try {
|
||||
const repoDir = await cloneOrPull(job, (line) => this.emitLog(jobId, line));
|
||||
await ensureDependencies(repoDir, (line) => this.emitLog(jobId, line));
|
||||
this.emitLog(jobId, `Test komutu çalıştırılıyor: ${job.testCommand}`);
|
||||
await runCommand(job.testCommand, repoDir, (line) => this.emitLog(jobId, line));
|
||||
this.emitLog(jobId, "Test tamamlandı: Başarılı");
|
||||
const repoDir = await cloneOrPull(job, (line) => pushLog(line));
|
||||
await ensureDependencies(repoDir, (line) => pushLog(line));
|
||||
pushLog(`Test komutu çalıştırılıyor: ${job.testCommand}`);
|
||||
await runCommand(job.testCommand, repoDir, (line) => pushLog(line));
|
||||
pushLog("Test tamamlandı: Başarılı");
|
||||
const duration = Date.now() - startedAt;
|
||||
await Job.findByIdAndUpdate(jobId, {
|
||||
status: "success",
|
||||
@@ -130,6 +145,12 @@ class JobService {
|
||||
lastDurationMs: duration,
|
||||
lastMessage: "Başarılı"
|
||||
});
|
||||
await JobRun.findByIdAndUpdate(runDoc._id, {
|
||||
status: "success",
|
||||
finishedAt: new Date(),
|
||||
durationMs: duration,
|
||||
logs: runLogs
|
||||
});
|
||||
this.emitStatus(jobId, {
|
||||
status: "success",
|
||||
lastRunAt: new Date(),
|
||||
@@ -144,7 +165,13 @@ class JobService {
|
||||
lastDurationMs: duration,
|
||||
lastMessage: (err as Error).message
|
||||
});
|
||||
this.emitLog(jobId, `Hata: ${(err as Error).message}`);
|
||||
await JobRun.findByIdAndUpdate(runDoc._id, {
|
||||
status: "failed",
|
||||
finishedAt: new Date(),
|
||||
durationMs: duration,
|
||||
logs: runLogs
|
||||
});
|
||||
pushLog(`Hata: ${(err as Error).message}`);
|
||||
this.emitStatus(jobId, {
|
||||
status: "failed",
|
||||
lastRunAt: new Date(),
|
||||
|
||||
1
backend/test-runs/6927ea6d4eeb13c399f5384e
Submodule
1
backend/test-runs/6927ea6d4eeb13c399f5384e
Submodule
Submodule backend/test-runs/6927ea6d4eeb13c399f5384e added at 4167b506aa
1
backend/test-runs/6927f441d032c5edf4ce4417
Submodule
1
backend/test-runs/6927f441d032c5edf4ce4417
Submodule
Submodule backend/test-runs/6927f441d032c5edf4ce4417 added at 4167b506aa
1
backend/test-runs/6927f4801d3a3242d50578c8
Submodule
1
backend/test-runs/6927f4801d3a3242d50578c8
Submodule
Submodule backend/test-runs/6927f4801d3a3242d50578c8 added at 4167b506aa
1
backend/test-runs/6927fa601d3a3242d5057904
Submodule
1
backend/test-runs/6927fa601d3a3242d5057904
Submodule
Submodule backend/test-runs/6927fa601d3a3242d5057904 added at 4167b506aa
1
backend/test-runs/69280287fc7de8c33147ec69
Submodule
1
backend/test-runs/69280287fc7de8c33147ec69
Submodule
Submodule backend/test-runs/69280287fc7de8c33147ec69 added at 035d049204
1
backend/test-runs/6928185ff4e571855c319cb9
Submodule
1
backend/test-runs/6928185ff4e571855c319cb9
Submodule
Submodule backend/test-runs/6928185ff4e571855c319cb9 added at 035d049204
1
backend/test-runs/69281978f4e571855c319cdb
Submodule
1
backend/test-runs/69281978f4e571855c319cdb
Submodule
Submodule backend/test-runs/69281978f4e571855c319cdb added at 4167b506aa
1
backend/test-runs/69281d3f034039681b7f35b6
Submodule
1
backend/test-runs/69281d3f034039681b7f35b6
Submodule
Submodule backend/test-runs/69281d3f034039681b7f35b6 added at 4167b506aa
Reference in New Issue
Block a user