191 lines
8.4 KiB
PHP
191 lines
8.4 KiB
PHP
<?php
|
|
header("Content-Type: application/json; charset=utf-8");
|
|
$input = json_decode(file_get_contents("php://input"), true) ?: [];
|
|
$step = $input["step"] ?? $_GET["step"] ?? "full";
|
|
$task = $input["task"] ?? "";
|
|
|
|
$secrets=[];
|
|
foreach(file("/etc/weval/secrets.env",2|4) as $l){if(strpos($l,"=")!==false){list($k,$v)=explode("=",$l,2);$secrets[trim($k)]=trim($v," \t\"'");}}
|
|
|
|
function llm($prompt, $secrets) {
|
|
$ch=curl_init("https://api.cerebras.ai/v1/chat/completions");
|
|
curl_setopt_array($ch,[CURLOPT_POST=>true,CURLOPT_POSTFIELDS=>json_encode(["model"=>"qwen-3-235b-a22b-instruct-2507","messages"=>[["role"=>"system","content"=>"WEVIA DevOps Pipeline. French. Concise."],["role"=>"user","content"=>$prompt]],"max_tokens"=>500,"temperature"=>0.2]),CURLOPT_HTTPHEADER=>["Content-Type: application/json","Authorization: Bearer ".($secrets["CEREBRAS_API_KEY"]??"")],CURLOPT_RETURNTRANSFER=>true,CURLOPT_TIMEOUT=>12]);
|
|
$r=curl_exec($ch);curl_close($ch);
|
|
return json_decode($r,true)["choices"][0]["message"]["content"]??"";
|
|
}
|
|
|
|
$trace = [];
|
|
|
|
// STEP 1: ANALYZE REQUEST + WIKI + L99
|
|
if ($step === "full" || $step === "analyze") {
|
|
// Read wiki
|
|
$wikiFiles = glob("/opt/weval-l99/wiki/*.json");
|
|
$wikiCount = count($wikiFiles);
|
|
$recentWiki = [];
|
|
foreach (array_slice($wikiFiles, -5) as $wf) {
|
|
$d = json_decode(@file_get_contents($wf), true);
|
|
$recentWiki[] = $d["title"] ?? basename($wf);
|
|
}
|
|
|
|
// Read L99
|
|
$l99 = json_decode(@file_get_contents("/var/www/html/api/l99-results.json") ?: "{}", true);
|
|
|
|
// Scan servers
|
|
$ram = trim(shell_exec("free -h | grep Mem | awk '{print $3\"/\"$2}'"));
|
|
$disk = trim(shell_exec("df -h / | tail -1 | awk '{print $5}'"));
|
|
$docker = trim(shell_exec("docker ps -q 2>/dev/null | wc -l"));
|
|
$git = trim(shell_exec("cd /var/www/html && git status --short 2>/dev/null | wc -l"));
|
|
$gitBranch = trim(shell_exec("cd /var/www/html && git branch --show-current 2>/dev/null"));
|
|
|
|
// Scan architecture
|
|
$fastLines = count(file("/var/www/html/api/weval-ia-fast.php"));
|
|
$autoLines = count(file("/var/www/html/api/wevia-autonomous.php"));
|
|
|
|
$analysis = [
|
|
"task" => $task,
|
|
"wiki" => ["count" => $wikiCount, "recent" => $recentWiki],
|
|
"l99" => ["passed" => $l99["passed"] ?? "?", "total" => $l99["total"] ?? "?"],
|
|
"infra" => ["ram" => $ram, "disk" => $disk, "docker" => $docker, "dirty_files" => $git, "branch" => $gitBranch],
|
|
"codebase" => ["fast_lines" => $fastLines, "auto_lines" => $autoLines],
|
|
];
|
|
|
|
// LLM analysis
|
|
if ($task) {
|
|
$analysis["llm_analysis"] = llm("Dev request: $task\nInfra: RAM=$ram Disk=$disk Docker=$docker\nL99: {$l99['passed']}/{$l99['total']}\nFast.php: $fastLines lines\nAnalyze: what files to modify, risks, approach.", $secrets);
|
|
}
|
|
|
|
$trace[] = ["step" => "analyze", "data" => $analysis];
|
|
if ($step === "analyze") { echo json_encode($analysis, JSON_UNESCAPED_UNICODE); exit; }
|
|
}
|
|
|
|
// STEP 2: GOLD BACKUP
|
|
if ($step === "full" || $step === "backup") {
|
|
$timestamp = date("Ymd-His");
|
|
$backupDir = "/opt/wevads/vault/gold-$timestamp/";
|
|
@mkdir($backupDir, 0777, true);
|
|
shell_exec("cp /var/www/html/api/weval-ia-fast.php $backupDir 2>/dev/null");
|
|
shell_exec("cp /var/www/html/api/wevia-autonomous.php $backupDir 2>/dev/null");
|
|
shell_exec("cp /var/www/html/wevia-master.html $backupDir 2>/dev/null");
|
|
shell_exec("cd $backupDir && md5sum * > checksums.md5 2>/dev/null");
|
|
$trace[] = ["step" => "backup", "dir" => $backupDir, "files" => count(glob("$backupDir*"))];
|
|
if ($step === "backup") { echo json_encode(["backup" => $backupDir, "files" => count(glob("$backupDir*"))]); exit; }
|
|
}
|
|
|
|
// STEP 3: GIT SNAPSHOT
|
|
if ($step === "full" || $step === "snapshot") {
|
|
$gitStatus = shell_exec("cd /var/www/html && git add -A && git status --short 2>&1");
|
|
$dirty = substr_count($gitStatus, "\n");
|
|
if ($dirty > 0) {
|
|
shell_exec("cd /var/www/html && git commit -m 'PIPELINE: pre-dev snapshot' 2>&1");
|
|
}
|
|
$hash = trim(shell_exec("cd /var/www/html && git rev-parse --short HEAD 2>/dev/null"));
|
|
$trace[] = ["step" => "snapshot", "hash" => $hash, "dirty" => $dirty];
|
|
}
|
|
|
|
// STEP 4: L99 PRE-TEST
|
|
if ($step === "full" || $step === "pretest") {
|
|
$py = 'import asyncio
|
|
from playwright.async_api import async_playwright
|
|
async def t():
|
|
async with async_playwright() as p:
|
|
b=await p.chromium.launch(headless=True,args=["--no-sandbox"])
|
|
results=[]
|
|
pages={"master":"https://weval-consulting.com/wevia-master.html","cortex":"https://weval-consulting.com/wevia-cortex.html","site":"https://weval-consulting.com/"}
|
|
for name,url in pages.items():
|
|
pg=await b.new_page()
|
|
try:
|
|
await pg.goto(url,timeout=10000)
|
|
await pg.wait_for_timeout(2000)
|
|
title=await pg.title()
|
|
errors=[]
|
|
pg.on("pageerror",lambda e:errors.append(1))
|
|
await pg.wait_for_timeout(500)
|
|
await pg.screenshot(path=f"/tmp/l99-pre-{name}.png")
|
|
results.append({"page":name,"title":title,"errors":len(errors),"ok":True})
|
|
except Exception as e:
|
|
results.append({"page":name,"error":str(e)[:80],"ok":False})
|
|
await pg.close()
|
|
await b.close()
|
|
import json;print(json.dumps(results))
|
|
asyncio.run(t())';
|
|
$out = shell_exec("timeout 30 python3 -c " . escapeshellarg($py) . " 2>&1");
|
|
$preTests = json_decode($out, true) ?: [];
|
|
$prePassed = count(array_filter($preTests, function($t){return $t["ok"];}));
|
|
$trace[] = ["step" => "pretest", "passed" => $prePassed, "total" => count($preTests), "results" => $preTests];
|
|
}
|
|
|
|
// STEP 5: DEV (placeholder — actual dev done by caller)
|
|
if ($step === "full") {
|
|
$trace[] = ["step" => "dev", "status" => "ready", "note" => "Development phase — modify files now"];
|
|
}
|
|
|
|
// STEP 6: POST-TEST (L99 + NonReg)
|
|
if ($step === "full" || $step === "posttest") {
|
|
// PHP lint all modified files
|
|
$phpFiles = glob("/var/www/html/api/*.php");
|
|
$lintErrors = 0;
|
|
foreach ($phpFiles as $pf) {
|
|
$lint = shell_exec("php -l $pf 2>&1");
|
|
if (strpos($lint, "Errors") !== false) $lintErrors++;
|
|
}
|
|
|
|
// Playwright visual test
|
|
$postPy = 'import asyncio,json
|
|
from playwright.async_api import async_playwright
|
|
async def t():
|
|
async with async_playwright() as p:
|
|
b=await p.chromium.launch(headless=True,args=["--no-sandbox"])
|
|
pg=await b.new_page(viewport={"width":1400,"height":900})
|
|
await pg.goto("https://weval-consulting.com/wevia-master.html",timeout=10000)
|
|
await pg.wait_for_timeout(3000)
|
|
items=await pg.eval_on_selector_all(".sb-item","e=>e.length")
|
|
await pg.screenshot(path="/tmp/l99-post-master.png")
|
|
await b.close()
|
|
print(json.dumps({"sidebar":items,"ok":True}))
|
|
asyncio.run(t())';
|
|
$postOut = shell_exec("timeout 20 python3 -c " . escapeshellarg($postPy) . " 2>&1");
|
|
$postResult = json_decode($postOut, true) ?: ["ok" => false];
|
|
|
|
$trace[] = ["step" => "posttest", "lint_errors" => $lintErrors, "visual" => $postResult];
|
|
}
|
|
|
|
// STEP 7: COMMIT + PUSH TO ALL REPOS
|
|
if ($step === "full" || $step === "push") {
|
|
$msg = $input["commit_msg"] ?? "PIPELINE: auto-commit " . date("Y-m-d H:i");
|
|
|
|
// Local git
|
|
$gitResult = shell_exec("cd /var/www/html && git add -A && git commit -m " . escapeshellarg($msg) . " 2>&1");
|
|
|
|
// GitHub
|
|
$ghPush = shell_exec("cd /var/www/html && git push github main 2>&1 | tail -1");
|
|
|
|
// Get commit hash
|
|
$hash = trim(shell_exec("cd /var/www/html && git rev-parse --short HEAD 2>/dev/null"));
|
|
|
|
$trace[] = ["step" => "push", "hash" => $hash, "github" => strpos($ghPush, "->") !== false ? "OK" : $ghPush];
|
|
}
|
|
|
|
// STEP 8: WIKI UPDATE
|
|
if ($step === "full" || $step === "wiki") {
|
|
$wiki = [
|
|
"title" => "PIPELINE-" . date("Ymd-His"),
|
|
"date" => date("c"),
|
|
"task" => $task,
|
|
"steps" => count($trace),
|
|
"results" => array_map(function($t){return ["step"=>$t["step"],"ok"=>true];}, $trace),
|
|
];
|
|
file_put_contents("/opt/weval-l99/wiki/PIPELINE-" . date("Ymd-His") . ".json", json_encode($wiki));
|
|
$trace[] = ["step" => "wiki", "entries" => count(glob("/opt/weval-l99/wiki/*.json"))];
|
|
}
|
|
|
|
// STEP 9: FINAL STATUS
|
|
$pipeline = [
|
|
"task" => $task,
|
|
"steps" => count($trace),
|
|
"trace" => $trace,
|
|
"status" => "COMPLETE",
|
|
"timestamp" => date("c"),
|
|
];
|
|
|
|
echo json_encode($pipeline, JSON_UNESCAPED_UNICODE);
|