#feature: some update
This commit is contained in:
@@ -92,10 +92,12 @@ class JenkinsClient
|
||||
];
|
||||
}
|
||||
|
||||
$path = $this->getJobPath($jobName).(empty($parameters) ? '/build' : '/buildWithParameters');
|
||||
$path = $this->getJobPath($jobName).'/build?delay=0sec';
|
||||
$url = $this->host.$path;
|
||||
|
||||
try {
|
||||
$jobInfo = $this->getJobInfo($jobName);
|
||||
$nextBuildNumber = isset($jobInfo['nextBuildNumber']) ? (int) $jobInfo['nextBuildNumber'] : null;
|
||||
$request = $this->http();
|
||||
$crumb = $this->getCrumb();
|
||||
if ($crumb) {
|
||||
@@ -104,12 +106,20 @@ class JenkinsClient
|
||||
|
||||
$response = empty($parameters)
|
||||
? $request->post($url)
|
||||
: $request->asForm()->post($url, $parameters);
|
||||
: $request->asForm()->post($url, [
|
||||
'json' => json_encode([
|
||||
'parameter' => $this->buildFormParameters($parameters),
|
||||
'statusCode' => '303',
|
||||
'redirectTo' => '.',
|
||||
], JSON_UNESCAPED_UNICODE),
|
||||
'Submit' => 'Build',
|
||||
]);
|
||||
|
||||
if ($response->successful() || $response->status() === 201) {
|
||||
return [
|
||||
'success' => true,
|
||||
'queue_url' => $response->header('Location'),
|
||||
'build_number' => $nextBuildNumber,
|
||||
'status' => $response->status(),
|
||||
];
|
||||
}
|
||||
@@ -158,6 +168,143 @@ class JenkinsClient
|
||||
return $result;
|
||||
}
|
||||
|
||||
public function getBuildStatus(string $jobName, ?string $queueUrl = null, ?int $buildNumber = null): array
|
||||
{
|
||||
if (! $this->isConfigured()) {
|
||||
Log::warning('Jenkins client is not configured');
|
||||
|
||||
return [
|
||||
'success' => false,
|
||||
'status' => 'UNKNOWN',
|
||||
'message' => 'Jenkins not configured',
|
||||
];
|
||||
}
|
||||
|
||||
$queueItem = null;
|
||||
if ($queueUrl && ! $buildNumber) {
|
||||
$queueItem = $this->getQueueItem($queueUrl);
|
||||
if (! $queueItem) {
|
||||
return [
|
||||
'success' => false,
|
||||
'status' => 'UNKNOWN',
|
||||
'queue_url' => $queueUrl,
|
||||
'message' => '无法获取 Jenkins 队列状态',
|
||||
];
|
||||
}
|
||||
|
||||
if ($queueItem['cancelled'] ?? false) {
|
||||
return [
|
||||
'success' => true,
|
||||
'status' => 'ABORTED',
|
||||
'result' => 'ABORTED',
|
||||
'completed' => true,
|
||||
'queue_url' => $queueUrl,
|
||||
];
|
||||
}
|
||||
|
||||
if (empty($queueItem['executable']['number'])) {
|
||||
return [
|
||||
'success' => true,
|
||||
'status' => 'PENDING',
|
||||
'building' => true,
|
||||
'completed' => false,
|
||||
'queue_url' => $queueUrl,
|
||||
'message' => $queueItem['why'] ?? null,
|
||||
];
|
||||
}
|
||||
|
||||
$buildNumber = (int) $queueItem['executable']['number'];
|
||||
}
|
||||
|
||||
if (! $buildNumber) {
|
||||
return [
|
||||
'success' => false,
|
||||
'status' => 'UNKNOWN',
|
||||
'queue_url' => $queueUrl,
|
||||
'message' => '缺少 Jenkins 构建号',
|
||||
];
|
||||
}
|
||||
|
||||
$buildInfo = $this->getBuildInfo($jobName, $buildNumber);
|
||||
if (! $buildInfo) {
|
||||
return [
|
||||
'success' => true,
|
||||
'status' => 'PENDING',
|
||||
'building' => true,
|
||||
'completed' => false,
|
||||
'build_number' => $buildNumber,
|
||||
'queue_url' => $queueUrl,
|
||||
'message' => $this->findQueuedItem($jobName) ? '等待 Jenkins 开始构建' : '等待 Jenkins 创建构建',
|
||||
];
|
||||
}
|
||||
|
||||
$building = (bool) ($buildInfo['building'] ?? false);
|
||||
$result = $buildInfo['result'] ?? null;
|
||||
|
||||
return [
|
||||
'success' => true,
|
||||
'status' => $building ? 'BUILDING' : ($result ?? 'UNKNOWN'),
|
||||
'result' => $result,
|
||||
'building' => $building,
|
||||
'completed' => ! $building && ! empty($result),
|
||||
'build_number' => $buildNumber,
|
||||
'build_url' => $buildInfo['url'] ?? ($queueItem['executable']['url'] ?? null),
|
||||
'queue_url' => $queueUrl,
|
||||
];
|
||||
}
|
||||
|
||||
public function cancelBuild(string $jobName, ?string $queueUrl = null, ?int $buildNumber = null): array
|
||||
{
|
||||
if (! $this->isConfigured()) {
|
||||
Log::warning('Jenkins client is not configured');
|
||||
|
||||
return [
|
||||
'success' => false,
|
||||
'message' => 'Jenkins not configured',
|
||||
];
|
||||
}
|
||||
|
||||
if ($queueUrl && ! $buildNumber) {
|
||||
$queueItem = $this->getQueueItem($queueUrl);
|
||||
if (! empty($queueItem['executable']['number'])) {
|
||||
$buildNumber = (int) $queueItem['executable']['number'];
|
||||
} else {
|
||||
$queueId = $this->extractQueueId($queueUrl);
|
||||
if (! $queueId) {
|
||||
return [
|
||||
'success' => false,
|
||||
'message' => '无法识别 Jenkins 队列 ID',
|
||||
];
|
||||
}
|
||||
|
||||
return [
|
||||
...$this->post('/queue/cancelItem?id='.rawurlencode($queueId), 'Jenkins queue cancel'),
|
||||
'cancelled_queue' => true,
|
||||
];
|
||||
}
|
||||
}
|
||||
|
||||
$queueItem = $this->findQueuedItem($jobName);
|
||||
if (! empty($queueItem['id'])) {
|
||||
return [
|
||||
...$this->post('/queue/cancelItem?id='.rawurlencode((string) $queueItem['id']), 'Jenkins queue cancel'),
|
||||
'cancelled_queue' => true,
|
||||
];
|
||||
}
|
||||
|
||||
if (! $buildNumber) {
|
||||
return [
|
||||
'success' => false,
|
||||
'message' => '缺少 Jenkins 构建号',
|
||||
];
|
||||
}
|
||||
|
||||
return [
|
||||
...$this->post($this->getJobPath($jobName)."/{$buildNumber}/stop", 'Jenkins build stop'),
|
||||
'stopping_build' => true,
|
||||
];
|
||||
}
|
||||
|
||||
private function request(string $path): ?array
|
||||
{
|
||||
if (! $this->isConfigured()) {
|
||||
@@ -191,6 +338,60 @@ class JenkinsClient
|
||||
}
|
||||
}
|
||||
|
||||
private function post(string $path, string $operation): array
|
||||
{
|
||||
$url = $this->host.$path;
|
||||
|
||||
try {
|
||||
$request = $this->http();
|
||||
$crumb = $this->getCrumb();
|
||||
if ($crumb) {
|
||||
$request = $request->withHeaders([$crumb['field'] => $crumb['crumb']]);
|
||||
}
|
||||
|
||||
$response = $request->post($url);
|
||||
if ($response->successful() || in_array($response->status(), [201, 302], true)) {
|
||||
return [
|
||||
'success' => true,
|
||||
'status' => $response->status(),
|
||||
];
|
||||
}
|
||||
|
||||
Log::warning($operation.' failed', [
|
||||
'url' => $url,
|
||||
'status' => $response->status(),
|
||||
'body' => $response->body(),
|
||||
]);
|
||||
|
||||
return [
|
||||
'success' => false,
|
||||
'message' => 'Jenkins 返回状态码 '.$response->status(),
|
||||
'status' => $response->status(),
|
||||
];
|
||||
} catch (\Throwable $e) {
|
||||
Log::error($operation.' error', [
|
||||
'url' => $url,
|
||||
'error' => $e->getMessage(),
|
||||
]);
|
||||
|
||||
return [
|
||||
'success' => false,
|
||||
'message' => $e->getMessage(),
|
||||
];
|
||||
}
|
||||
}
|
||||
|
||||
private function buildFormParameters(array $parameters): array
|
||||
{
|
||||
return collect($parameters)
|
||||
->map(fn ($value, $name) => [
|
||||
'name' => $name,
|
||||
'value' => $value,
|
||||
])
|
||||
->values()
|
||||
->all();
|
||||
}
|
||||
|
||||
private function requestBody(string $path, bool $allowMethodNotAllowed = false): ?string
|
||||
{
|
||||
if (! $this->isConfigured()) {
|
||||
@@ -278,6 +479,55 @@ class JenkinsClient
|
||||
return $parameters;
|
||||
}
|
||||
|
||||
private function getQueueItem(string $queueUrl): ?array
|
||||
{
|
||||
$path = $this->normalizeJenkinsPath($queueUrl);
|
||||
$path = rtrim($path, '/').'/api/json';
|
||||
|
||||
return $this->request($path);
|
||||
}
|
||||
|
||||
private function findQueuedItem(string $jobName): ?array
|
||||
{
|
||||
$queue = $this->request('/queue/api/json');
|
||||
if (empty($queue['items']) || ! is_array($queue['items'])) {
|
||||
return null;
|
||||
}
|
||||
|
||||
$normalizedJobName = trim($jobName, '/');
|
||||
$lastSegment = basename(str_replace('\\', '/', $normalizedJobName));
|
||||
|
||||
foreach ($queue['items'] as $item) {
|
||||
$task = $item['task'] ?? [];
|
||||
$taskName = $task['fullName'] ?? $task['name'] ?? '';
|
||||
|
||||
if ($taskName === $normalizedJobName || $taskName === $lastSegment) {
|
||||
return $item;
|
||||
}
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
private function normalizeJenkinsPath(string $pathOrUrl): string
|
||||
{
|
||||
$path = parse_url($pathOrUrl, PHP_URL_PATH) ?: $pathOrUrl;
|
||||
$query = parse_url($pathOrUrl, PHP_URL_QUERY);
|
||||
|
||||
return $query ? "{$path}?{$query}" : $path;
|
||||
}
|
||||
|
||||
private function extractQueueId(string $queueUrl): ?string
|
||||
{
|
||||
if (preg_match('#/queue/item/(\d+)#', $queueUrl, $matches)) {
|
||||
return $matches[1];
|
||||
}
|
||||
|
||||
parse_str(parse_url($queueUrl, PHP_URL_QUERY) ?: '', $query);
|
||||
|
||||
return isset($query['id']) ? (string) $query['id'] : null;
|
||||
}
|
||||
|
||||
private function http(): PendingRequest
|
||||
{
|
||||
return Http::timeout($this->timeout)
|
||||
|
||||
Reference in New Issue
Block a user