This commit is contained in:
2026-04-30 11:29:27 +07:00
parent db1ac0f1a2
commit 52b5eb89de
2 changed files with 129 additions and 1 deletions

128
deploy.php Normal file
View File

@@ -0,0 +1,128 @@
<?php
declare(strict_types=1);
const CONFIG_FILE = '/home/javi/.deploy-secret.php';
const PROJECT_KEY = 'hello-world';
const ALLOWED_BRANCH = 'master';
const GIT_BIN = '/usr/bin/git';
const REPO_PATH = __DIR__;
const LOG_FILE = __DIR__ . '/deploy.log';
function respond(int $code, string $message): void {
http_response_code($code);
header('Content-Type: text/plain; charset=utf-8');
echo $message;
exit;
}
function log_line(string $message): void {
$line = '[' . date('Y-m-d H:i:s') . '] ' . $message . PHP_EOL;
file_put_contents(LOG_FILE, $line, FILE_APPEND);
}
function get_header_value(string $name): ?string {
$key = 'HTTP_' . strtoupper(str_replace('-', '_', $name));
return $_SERVER[$key] ?? null;
}
if ($_SERVER['REQUEST_METHOD'] !== 'POST') {
respond(405, 'Method Not Allowed');
}
$config = require CONFIG_FILE;
if (!is_array($config) || !isset($config[PROJECT_KEY])) {
log_line('ERROR: Secret no configurado para PROJECT_KEY=' . PROJECT_KEY);
respond(500, 'Project secret not configured');
}
$secret = $config[PROJECT_KEY];
if (!is_string($secret) || $secret === '') {
log_line('ERROR: Secret inválido para PROJECT_KEY=' . PROJECT_KEY);
respond(500, 'Invalid project secret');
}
$contentType = $_SERVER['CONTENT_TYPE'] ?? '';
if (stripos($contentType, 'application/json') === false) {
log_line('ERROR: Content-Type inválido: ' . $contentType);
respond(400, 'Invalid Content-Type');
}
$payload = file_get_contents('php://input');
if (!$payload) {
log_line('ERROR: Payload vacío');
respond(400, 'Empty payload');
}
$signatureHeader = get_header_value('X-Gitea-Signature');
if (!$signatureHeader) {
log_line('ERROR: Falta header X-Gitea-Signature');
respond(403, 'Missing signature');
}
$expected = hash_hmac('sha256', $payload, $secret);
$provided = trim($signatureHeader);
if (stripos($provided, 'sha256=') === 0) {
$provided = substr($provided, 7);
}
if (!hash_equals($expected, $provided)) {
log_line('ERROR: Firma inválida');
respond(403, 'Invalid signature');
}
$data = json_decode($payload, true);
if (!is_array($data)) {
log_line('ERROR: JSON inválido');
respond(400, 'Invalid JSON');
}
$event = get_header_value('X-Gitea-Event') ?? '';
if ($event !== 'push') {
log_line('INFO: Evento ignorado: ' . $event);
respond(200, 'Ignored event');
}
$ref = $data['ref'] ?? '';
$expectedRef = 'refs/heads/' . ALLOWED_BRANCH;
if ($ref !== $expectedRef) {
log_line('INFO: Rama ignorada: ' . $ref);
respond(200, 'Ignored branch');
}
if (!is_dir(REPO_PATH)) {
log_line('ERROR: REPO_PATH no existe: ' . REPO_PATH);
respond(500, 'Repository path not found');
}
$commands = [
'cd ' . escapeshellarg(REPO_PATH) . ' && ' . GIT_BIN . ' fetch origin 2>&1',
'cd ' . escapeshellarg(REPO_PATH) . ' && ' . GIT_BIN . ' checkout ' . escapeshellarg(ALLOWED_BRANCH) . ' 2>&1',
'cd ' . escapeshellarg(REPO_PATH) . ' && ' . GIT_BIN . ' pull origin ' . escapeshellarg(ALLOWED_BRANCH) . ' 2>&1',
];
$outputAll = [];
$returnCode = 0;
foreach ($commands as $cmd) {
$output = [];
$cmdReturn = 0;
exec($cmd, $output, $cmdReturn);
$outputAll[] = '$ ' . $cmd;
$outputAll[] = implode("\n", $output);
$outputAll[] = 'exit_code=' . $cmdReturn;
if ($cmdReturn !== 0) {
$returnCode = $cmdReturn;
break;
}
}
log_line("PROJECT_KEY=" . PROJECT_KEY . "\n" . implode("\n", $outputAll) . "\n---");
if ($returnCode !== 0) {
respond(500, 'Deploy failed. Revisa deploy.log');
}
respond(200, 'Deploy OK');

View File

@@ -5,6 +5,6 @@
<title>Hola mundo</title>
</head>
<body>
<h1>Hola mundo 10</h1>
<h1>Hola mundo 11</h1>
</body>
</html>