1
0
mirror of git://f0xx.org/android_cast synced 2026-07-29 04:18:09 +03:00
This commit is contained in:
Anton Afanasyeu
2026-06-05 16:31:21 +02:00
parent b29d95ccf6
commit a7e71bb39c
6 changed files with 83 additions and 15 deletions

View File

@@ -24,6 +24,7 @@ return [
],
'build' => [
'docker_image' => 'androidcast-ci:latest',
'docker_bin' => '/usr/bin/docker',
'ci_version' => '00.01.00.1000',
'repo_root' => '/workspace',
'artifacts_root' => '/workspace/out/builds',

View File

@@ -74,6 +74,7 @@ if ($view === 'build' && isset($_GET['id'])) {
BuildRunner::finalizeFromArtifacts((int) $build['id']);
$build = BuildRepository::getById((int) $_GET['id']);
}
$health = BuildRepository::healthSummary();
$view = 'build';
$pageTitle = 'Build ' . ($build['build_code'] ?? '');
require __DIR__ . '/../views/layout.php';

View File

@@ -116,7 +116,7 @@ SQL);
$running = (int) $pdo->query("SELECT COUNT(*) FROM builds WHERE status = 'running'")->fetchColumn();
$failed = (int) $pdo->query("SELECT COUNT(*) FROM builds WHERE status = 'failed' AND created_at > (NOW() - INTERVAL 7 DAY)")->fetchColumn();
$passed = (int) $pdo->query("SELECT COUNT(*) FROM builds WHERE status = 'passed' AND created_at > (NOW() - INTERVAL 7 DAY)")->fetchColumn();
$dockerOk = trim((string) shell_exec('docker info >/dev/null 2>&1 && echo ok')) === 'ok';
$dockerOk = BuildRunner::dockerAvailable();
return [
'docker' => $dockerOk ? 'ok' : 'down',
'running' => $running,

View File

@@ -2,8 +2,37 @@
declare(strict_types=1);
final class BuildRunner {
public static function dockerBinary(): string {
$configured = trim((string) cfg('build.docker_bin', ''));
if ($configured !== '' && is_executable($configured)) {
return $configured;
}
foreach (['/usr/bin/docker', '/usr/local/bin/docker'] as $path) {
if (is_executable($path)) {
return $path;
}
}
$which = trim((string) shell_exec('command -v docker 2>/dev/null'));
return $which !== '' ? $which : 'docker';
}
public static function dockerAvailable(): bool {
return trim((string) shell_exec('docker info >/dev/null 2>&1 && echo ok')) === 'ok';
$bin = escapeshellarg(self::dockerBinary());
return trim((string) shell_exec("{$bin} info >/dev/null 2>&1 && echo ok")) === 'ok';
}
public static function dockerCheckDetail(): string {
$bin = self::dockerBinary();
$sock = '/var/run/docker.sock';
$parts = ['bin=' . $bin];
if (!is_executable($bin)) {
$parts[] = 'bin_not_executable';
}
if (!is_readable($sock)) {
$parts[] = 'sock_not_readable';
}
$parts[] = self::dockerAvailable() ? 'info_ok' : 'info_failed';
return implode(', ', $parts);
}
public static function generateBuildCode(): string {
@@ -91,7 +120,13 @@ YAML;
BuildRepository::update($id, ['log_path' => $logPath]);
if (!self::dockerAvailable()) {
self::failBuild($id, 'Docker daemon not available', $logPath);
$detail = self::dockerCheckDetail();
self::failBuild(
$id,
'Docker daemon not available (' . $detail . '). '
. 'Ensure docker service is running and PHP-FPM user (nginx) is in group docker, then restart php-fpm.',
$logPath
);
return BuildRepository::getById($id) ?? ['id' => $id, 'build_code' => $buildCode, 'status' => 'failed'];
}
@@ -106,6 +141,7 @@ YAML;
$env = [
'BUILD_ID=' . $id,
'BUILD_LOG_FILE=' . escapeshellarg($logPath),
'BUILD_LOG_STDOUT_ONLY=1',
'BUILD_WORK_DIR=' . escapeshellarg($repo),
'BUILD_OUT_DIR=' . escapeshellarg($dir),
'ANDROIDCAST_CI_VERSION=' . escapeshellarg((string) cfg('build.ci_version', '00.01.00.1000')),

View File

@@ -14,6 +14,13 @@ if ($pipelineYaml === '') {
· <span class="error-text"><?= h($build['error_message']) ?></span>
<?php endif; ?>
</p>
<?php
$healthDocker = ($health['docker'] ?? '') === 'ok';
$dockerFail = str_contains((string) ($build['error_message'] ?? ''), 'Docker daemon not available');
if ($status === 'failed' && $dockerFail && $healthDocker):
?>
<p class="muted graphs-footnote">Ecosystem health reports <strong>Docker: ok</strong> now. The log below is from this failed run — use <strong>Re-run</strong> (do not only refresh).</p>
<?php endif; ?>
<div class="build-actions card card--lift" style="margin-bottom:12px">
<h2>Actions</h2>