mirror of
git://f0xx.org/android_cast
synced 2026-07-29 04:57:40 +03:00
sync BE
This commit is contained in:
@@ -24,6 +24,7 @@ return [
|
|||||||
],
|
],
|
||||||
'build' => [
|
'build' => [
|
||||||
'docker_image' => 'androidcast-ci:latest',
|
'docker_image' => 'androidcast-ci:latest',
|
||||||
|
'docker_bin' => '/usr/bin/docker',
|
||||||
'ci_version' => '00.01.00.1000',
|
'ci_version' => '00.01.00.1000',
|
||||||
'repo_root' => '/workspace',
|
'repo_root' => '/workspace',
|
||||||
'artifacts_root' => '/workspace/out/builds',
|
'artifacts_root' => '/workspace/out/builds',
|
||||||
|
|||||||
@@ -74,6 +74,7 @@ if ($view === 'build' && isset($_GET['id'])) {
|
|||||||
BuildRunner::finalizeFromArtifacts((int) $build['id']);
|
BuildRunner::finalizeFromArtifacts((int) $build['id']);
|
||||||
$build = BuildRepository::getById((int) $_GET['id']);
|
$build = BuildRepository::getById((int) $_GET['id']);
|
||||||
}
|
}
|
||||||
|
$health = BuildRepository::healthSummary();
|
||||||
$view = 'build';
|
$view = 'build';
|
||||||
$pageTitle = 'Build ' . ($build['build_code'] ?? '');
|
$pageTitle = 'Build ' . ($build['build_code'] ?? '');
|
||||||
require __DIR__ . '/../views/layout.php';
|
require __DIR__ . '/../views/layout.php';
|
||||||
|
|||||||
@@ -116,7 +116,7 @@ SQL);
|
|||||||
$running = (int) $pdo->query("SELECT COUNT(*) FROM builds WHERE status = 'running'")->fetchColumn();
|
$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();
|
$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();
|
$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 [
|
return [
|
||||||
'docker' => $dockerOk ? 'ok' : 'down',
|
'docker' => $dockerOk ? 'ok' : 'down',
|
||||||
'running' => $running,
|
'running' => $running,
|
||||||
|
|||||||
@@ -2,8 +2,37 @@
|
|||||||
declare(strict_types=1);
|
declare(strict_types=1);
|
||||||
|
|
||||||
final class BuildRunner {
|
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 {
|
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 {
|
public static function generateBuildCode(): string {
|
||||||
@@ -91,7 +120,13 @@ YAML;
|
|||||||
BuildRepository::update($id, ['log_path' => $logPath]);
|
BuildRepository::update($id, ['log_path' => $logPath]);
|
||||||
|
|
||||||
if (!self::dockerAvailable()) {
|
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'];
|
return BuildRepository::getById($id) ?? ['id' => $id, 'build_code' => $buildCode, 'status' => 'failed'];
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -106,6 +141,7 @@ YAML;
|
|||||||
$env = [
|
$env = [
|
||||||
'BUILD_ID=' . $id,
|
'BUILD_ID=' . $id,
|
||||||
'BUILD_LOG_FILE=' . escapeshellarg($logPath),
|
'BUILD_LOG_FILE=' . escapeshellarg($logPath),
|
||||||
|
'BUILD_LOG_STDOUT_ONLY=1',
|
||||||
'BUILD_WORK_DIR=' . escapeshellarg($repo),
|
'BUILD_WORK_DIR=' . escapeshellarg($repo),
|
||||||
'BUILD_OUT_DIR=' . escapeshellarg($dir),
|
'BUILD_OUT_DIR=' . escapeshellarg($dir),
|
||||||
'ANDROIDCAST_CI_VERSION=' . escapeshellarg((string) cfg('build.ci_version', '00.01.00.1000')),
|
'ANDROIDCAST_CI_VERSION=' . escapeshellarg((string) cfg('build.ci_version', '00.01.00.1000')),
|
||||||
|
|||||||
@@ -14,6 +14,13 @@ if ($pipelineYaml === '') {
|
|||||||
· <span class="error-text"><?= h($build['error_message']) ?></span>
|
· <span class="error-text"><?= h($build['error_message']) ?></span>
|
||||||
<?php endif; ?>
|
<?php endif; ?>
|
||||||
</p>
|
</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">
|
<div class="build-actions card card--lift" style="margin-bottom:12px">
|
||||||
<h2>Actions</h2>
|
<h2>Actions</h2>
|
||||||
|
|||||||
@@ -5,6 +5,7 @@
|
|||||||
# ./scripts/docker-build-runner.sh --build-id 42 --workdir /path/to/repo
|
# ./scripts/docker-build-runner.sh --build-id 42 --workdir /path/to/repo
|
||||||
#
|
#
|
||||||
# Env: see ci-build-and-publish-ota.sh
|
# Env: see ci-build-and-publish-ota.sh
|
||||||
|
# When invoked from PHP (BUILD_LOG_STDOUT_ONLY=1), log via stdout only — parent redirects to build.log.
|
||||||
set -euo pipefail
|
set -euo pipefail
|
||||||
|
|
||||||
ROOT="$(cd "$(dirname "${BASH_SOURCE[0]}")/.." && pwd)"
|
ROOT="$(cd "$(dirname "${BASH_SOURCE[0]}")/.." && pwd)"
|
||||||
@@ -14,27 +15,49 @@ BUILD_ID="${BUILD_ID:-local}"
|
|||||||
LOG_FILE="${BUILD_LOG_FILE:-${ROOT}/out/builds/${BUILD_ID}/build.log}"
|
LOG_FILE="${BUILD_LOG_FILE:-${ROOT}/out/builds/${BUILD_ID}/build.log}"
|
||||||
WORK_DIR="${BUILD_WORK_DIR:-${ROOT}}"
|
WORK_DIR="${BUILD_WORK_DIR:-${ROOT}}"
|
||||||
OUT_DIR="${BUILD_OUT_DIR:-${WORK_DIR}/out/builds/${BUILD_ID}}"
|
OUT_DIR="${BUILD_OUT_DIR:-${WORK_DIR}/out/builds/${BUILD_ID}}"
|
||||||
|
LOG_STDOUT_ONLY="${BUILD_LOG_STDOUT_ONLY:-0}"
|
||||||
|
|
||||||
mkdir -p "$(dirname "$LOG_FILE")" "$OUT_DIR"
|
mkdir -p "$(dirname "$LOG_FILE")" "$OUT_DIR"
|
||||||
|
|
||||||
echo "[runner] image=${IMAGE} ci_version=${CI_VERSION} build_id=${BUILD_ID}" | tee -a "$LOG_FILE"
|
log() {
|
||||||
echo "[runner] workdir=${WORK_DIR} out=${OUT_DIR}" | tee -a "$LOG_FILE"
|
if [[ "$LOG_STDOUT_ONLY" == "1" ]]; then
|
||||||
|
echo "$@"
|
||||||
|
else
|
||||||
|
echo "$@" | tee -a "$LOG_FILE"
|
||||||
|
fi
|
||||||
|
}
|
||||||
|
|
||||||
|
run_logged() {
|
||||||
|
if [[ "$LOG_STDOUT_ONLY" == "1" ]]; then
|
||||||
|
"$@"
|
||||||
|
else
|
||||||
|
"$@" 2>&1 | tee -a "$LOG_FILE"
|
||||||
|
fi
|
||||||
|
}
|
||||||
|
|
||||||
|
# Git 2.35+ refuses repos owned by another uid (PHP-FPM nginx vs deploy user).
|
||||||
|
git_safe() {
|
||||||
|
git -c safe.directory="${WORK_DIR}" "$@"
|
||||||
|
}
|
||||||
|
|
||||||
|
log "[runner] image=${IMAGE} ci_version=${CI_VERSION} build_id=${BUILD_ID}"
|
||||||
|
log "[runner] workdir=${WORK_DIR} out=${OUT_DIR}"
|
||||||
|
|
||||||
if [[ -n "${GIT_REF:-}" ]] && [[ -d "${WORK_DIR}/.git" ]]; then
|
if [[ -n "${GIT_REF:-}" ]] && [[ -d "${WORK_DIR}/.git" ]]; then
|
||||||
echo "[runner] syncing git ref=${GIT_REF}" | tee -a "$LOG_FILE"
|
log "[runner] syncing git ref=${GIT_REF}"
|
||||||
git -C "${WORK_DIR}" fetch origin --prune 2>&1 | tee -a "$LOG_FILE" || true
|
run_logged git_safe -C "${WORK_DIR}" fetch origin --prune || true
|
||||||
git -C "${WORK_DIR}" checkout "${GIT_REF}" 2>&1 | tee -a "$LOG_FILE" || true
|
run_logged git_safe -C "${WORK_DIR}" checkout "${GIT_REF}"
|
||||||
git -C "${WORK_DIR}" pull --rebase origin "${GIT_REF}" 2>&1 | tee -a "$LOG_FILE" || true
|
run_logged git_safe -C "${WORK_DIR}" pull --rebase origin "${GIT_REF}" || true
|
||||||
git -C "${WORK_DIR}" rev-parse HEAD 2>&1 | tee -a "$LOG_FILE" || true
|
run_logged git_safe -C "${WORK_DIR}" rev-parse HEAD
|
||||||
fi
|
fi
|
||||||
|
|
||||||
docker build \
|
run_logged docker build \
|
||||||
--build-arg ANDROIDCAST_CI_VERSION="${CI_VERSION}" \
|
--build-arg ANDROIDCAST_CI_VERSION="${CI_VERSION}" \
|
||||||
-t "$IMAGE" \
|
-t "$IMAGE" \
|
||||||
-f "${ROOT}/Dockerfile" \
|
-f "${ROOT}/Dockerfile" \
|
||||||
"${ROOT}" 2>&1 | tee -a "$LOG_FILE"
|
"${ROOT}"
|
||||||
|
|
||||||
docker run --rm \
|
run_logged docker run --rm \
|
||||||
-v "${WORK_DIR}:/workspace" \
|
-v "${WORK_DIR}:/workspace" \
|
||||||
-v "${ROOT}/out:/workspace/out" \
|
-v "${ROOT}/out:/workspace/out" \
|
||||||
-w /workspace \
|
-w /workspace \
|
||||||
@@ -50,6 +73,6 @@ docker run --rm \
|
|||||||
-e GIT_SHA="${GIT_SHA:-}" \
|
-e GIT_SHA="${GIT_SHA:-}" \
|
||||||
-e RELEASE_NOTES="${RELEASE_NOTES:-}" \
|
-e RELEASE_NOTES="${RELEASE_NOTES:-}" \
|
||||||
"$IMAGE" \
|
"$IMAGE" \
|
||||||
./scripts/ci-build-and-publish-ota.sh 2>&1 | tee -a "$LOG_FILE"
|
./scripts/ci-build-and-publish-ota.sh
|
||||||
|
|
||||||
echo "[runner] finished build_id=${BUILD_ID}" | tee -a "$LOG_FILE"
|
log "[runner] finished build_id=${BUILD_ID}"
|
||||||
|
|||||||
Reference in New Issue
Block a user