mirror of
git://f0xx.org/ac/ac-ms-build
synced 2026-07-29 02:58:48 +03:00
initial
This commit is contained in:
55
public/api/build_actions.php
Normal file
55
public/api/build_actions.php
Normal file
@@ -0,0 +1,55 @@
|
||||
<?php
|
||||
declare(strict_types=1);
|
||||
require_once __DIR__ . '/../../src/bootstrap.php';
|
||||
Auth::check();
|
||||
|
||||
if ($_SERVER['REQUEST_METHOD'] !== 'POST') {
|
||||
json_out(['ok' => false, 'error' => 'POST required'], 405);
|
||||
}
|
||||
|
||||
$raw = file_get_contents('php://input') ?: '{}';
|
||||
$body = json_decode($raw, true);
|
||||
if (!is_array($body)) {
|
||||
$body = $_POST;
|
||||
}
|
||||
|
||||
$action = (string) ($body['action'] ?? '');
|
||||
$buildId = (int) ($body['build_id'] ?? 0);
|
||||
if ($buildId <= 0) {
|
||||
json_out(['ok' => false, 'error' => 'build_id required'], 400);
|
||||
}
|
||||
|
||||
$user = Auth::user();
|
||||
$userId = isset($user['id']) ? (int) $user['id'] : null;
|
||||
|
||||
try {
|
||||
if ($action === 'stop') {
|
||||
$ok = BuildRunner::stopBuild($buildId);
|
||||
json_out(['ok' => $ok, 'build' => BuildRepository::getById($buildId)]);
|
||||
}
|
||||
if ($action === 'rerun') {
|
||||
$build = BuildRunner::rerunBuild($buildId, null, $userId);
|
||||
json_out(['ok' => true, 'build' => $build]);
|
||||
}
|
||||
if ($action === 'force_rerun') {
|
||||
$build = BuildRunner::forceRerun($buildId, $userId);
|
||||
json_out(['ok' => true, 'build' => $build]);
|
||||
}
|
||||
if ($action === 'rerun_as') {
|
||||
$override = is_array($body['params'] ?? null) ? $body['params'] : [];
|
||||
$build = BuildRunner::rerunBuild($buildId, $override, $userId);
|
||||
json_out(['ok' => true, 'build' => $build]);
|
||||
}
|
||||
if ($action === 'rerun_from_failed') {
|
||||
$build = BuildRunner::rerunFromFailed($buildId, $userId, false);
|
||||
json_out(['ok' => true, 'build' => $build, 'resume_from' => BuildRunner::detectFailedStep($buildId)]);
|
||||
}
|
||||
if ($action === 'rerun_with_ssh') {
|
||||
$build = BuildRunner::rerunFromFailed($buildId, $userId, true);
|
||||
json_out(['ok' => true, 'build' => $build, 'resume_from' => BuildRunner::detectFailedStep($buildId)]);
|
||||
}
|
||||
json_out(['ok' => false, 'error' => 'unknown_action'], 400);
|
||||
} catch (Throwable $e) {
|
||||
error_log('build_actions: ' . $e->getMessage());
|
||||
json_out(['ok' => false, 'error' => $e->getMessage()], 500);
|
||||
}
|
||||
39
public/api/build_log.php
Normal file
39
public/api/build_log.php
Normal file
@@ -0,0 +1,39 @@
|
||||
<?php
|
||||
declare(strict_types=1);
|
||||
require_once __DIR__ . '/../../src/bootstrap.php';
|
||||
Auth::check();
|
||||
|
||||
$id = (int) ($_GET['id'] ?? 0);
|
||||
$offset = (int) ($_GET['offset'] ?? 0);
|
||||
$full = isset($_GET['full']) && $_GET['full'] === '1';
|
||||
$download = isset($_GET['download']) && $_GET['download'] === '1';
|
||||
if ($id <= 0) {
|
||||
json_out(['ok' => false, 'error' => 'id required'], 400);
|
||||
}
|
||||
$build = BuildRepository::getById($id);
|
||||
if (!$build) {
|
||||
json_out(['ok' => false, 'error' => 'not found'], 404);
|
||||
}
|
||||
$logPath = $build['log_path'] ?? null;
|
||||
if ($download) {
|
||||
if (!$logPath || !is_file($logPath)) {
|
||||
json_out(['ok' => false, 'error' => 'log not found'], 404);
|
||||
}
|
||||
$code = preg_replace('/[^a-zA-Z0-9._-]+/', '_', (string) ($build['build_code'] ?? 'build'));
|
||||
header('Content-Type: text/plain; charset=utf-8');
|
||||
header('Content-Disposition: attachment; filename="' . $code . '.log"');
|
||||
readfile($logPath);
|
||||
exit;
|
||||
}
|
||||
$tail = $full
|
||||
? BuildRunner::readLogFull($logPath)
|
||||
: BuildRunner::readLogTail($logPath, $offset);
|
||||
if ($build['status'] === 'running' && $tail['eof'] && is_file(BuildRunner::artifactDir($id) . '/BUILD_INFO.json')) {
|
||||
BuildRunner::finalizeFromArtifacts($id);
|
||||
$build = BuildRepository::getById($id);
|
||||
}
|
||||
json_out([
|
||||
'ok' => true,
|
||||
'build' => $build,
|
||||
'log' => $tail,
|
||||
]);
|
||||
27
public/api/build_trigger.php
Normal file
27
public/api/build_trigger.php
Normal file
@@ -0,0 +1,27 @@
|
||||
<?php
|
||||
declare(strict_types=1);
|
||||
require_once __DIR__ . '/../../src/bootstrap.php';
|
||||
Auth::check();
|
||||
|
||||
if ($_SERVER['REQUEST_METHOD'] !== 'POST') {
|
||||
json_out(['ok' => false, 'error' => 'POST required'], 405);
|
||||
}
|
||||
|
||||
$raw = file_get_contents('php://input') ?: '{}';
|
||||
$params = json_decode($raw, true);
|
||||
if (!is_array($params)) {
|
||||
$params = $_POST;
|
||||
}
|
||||
|
||||
$params['pipeline_yaml'] = BuildRunner::resolvePipelineYaml($params);
|
||||
$params['run_tests'] = !empty($params['run_tests']);
|
||||
$params['run_native'] = array_key_exists('run_native', $params) ? !empty($params['run_native']) : true;
|
||||
$params['run_apk'] = array_key_exists('run_apk', $params) ? !empty($params['run_apk']) : true;
|
||||
$params['auto_ota'] = !empty($params['auto_ota']);
|
||||
$params['auto_deploy'] = !empty($params['auto_deploy']);
|
||||
$params['ota_channel'] = $params['ota_channel'] ?? 'staging';
|
||||
$params['gradle_task'] = $params['gradle_task'] ?? 'assembleDebug';
|
||||
|
||||
$user = Auth::user();
|
||||
$build = BuildRunner::enqueue($params, isset($user['id']) ? (int) $user['id'] : null);
|
||||
json_out(['ok' => true, 'build' => $build]);
|
||||
7
public/api/builds.php
Normal file
7
public/api/builds.php
Normal file
@@ -0,0 +1,7 @@
|
||||
<?php
|
||||
declare(strict_types=1);
|
||||
require_once __DIR__ . '/../../src/bootstrap.php';
|
||||
Auth::check();
|
||||
BuildRunner::reconcileRunningBuilds();
|
||||
BuildRunner::reconcileQueuedBuilds();
|
||||
json_out(['ok' => true, 'builds' => BuildRepository::listRecent(10)]);
|
||||
4
public/api/health.php
Normal file
4
public/api/health.php
Normal file
@@ -0,0 +1,4 @@
|
||||
<?php
|
||||
declare(strict_types=1);
|
||||
require_once __DIR__ . '/../../src/bootstrap.php';
|
||||
json_out(['ok' => true, 'health' => BuildRepository::healthSummary()]);
|
||||
51
public/api/heartbeat.php
Normal file
51
public/api/heartbeat.php
Normal file
@@ -0,0 +1,51 @@
|
||||
<?php
|
||||
declare(strict_types=1);
|
||||
require_once __DIR__ . '/../../src/bootstrap.php';
|
||||
|
||||
header('Content-Type: application/json; charset=utf-8');
|
||||
|
||||
if (($_SERVER['REQUEST_METHOD'] ?? 'GET') !== 'POST') {
|
||||
http_response_code(405);
|
||||
echo json_encode(['error' => 'method_not_allowed']);
|
||||
exit;
|
||||
}
|
||||
|
||||
$raw = file_get_contents('php://input') ?: '';
|
||||
$req = json_decode($raw, true);
|
||||
if (!is_array($req)) {
|
||||
http_response_code(400);
|
||||
echo json_encode(['error' => 'invalid_json']);
|
||||
exit;
|
||||
}
|
||||
|
||||
$heartbeat = $req['heartbeat'] ?? [];
|
||||
if (!is_array($heartbeat)) {
|
||||
$heartbeat = [];
|
||||
}
|
||||
|
||||
$type = (string)($heartbeat['type'] ?? 'generic');
|
||||
$srvEpoch = time();
|
||||
$srvTz = date('O');
|
||||
|
||||
$resp = [
|
||||
'heartbeat' => [
|
||||
'type' => $type,
|
||||
'server_date' => $srvEpoch,
|
||||
'server_tz' => $srvTz,
|
||||
],
|
||||
];
|
||||
|
||||
if ($type === 'ntp') {
|
||||
$clientDate = (int)($heartbeat['date'] ?? 0);
|
||||
$clientTz = (string)($heartbeat['tz'] ?? '');
|
||||
$resp['heartbeat']['client_date'] = $clientDate;
|
||||
$resp['heartbeat']['client_tz'] = $clientTz;
|
||||
$resp['heartbeat']['correction_seconds'] = $clientDate > 0 ? ($srvEpoch - $clientDate) : null;
|
||||
$resp['heartbeat']['enabled'] = true;
|
||||
}
|
||||
|
||||
if ($type === 'ip') {
|
||||
$resp['heartbeat']['external_ip'] = $_SERVER['HTTP_X_FORWARDED_FOR'] ?? ($_SERVER['REMOTE_ADDR'] ?? '');
|
||||
}
|
||||
|
||||
echo json_encode($resp, JSON_UNESCAPED_SLASHES | JSON_UNESCAPED_UNICODE);
|
||||
Reference in New Issue
Block a user