reports/src/jira_export.php

143 lines
5.7 KiB
PHP
Raw Normal View History

global$config; #!/usr/bin/env php
<?php
/**
* @var array $config
* @var array $teams
* @var string[] $holidays
*/
use GuzzleHttp\Client;
use GuzzleHttp\Exception\GuzzleException;
use Nechaev\Reports\StatusHelper;
require __DIR__ . '/../init.php';
require __DIR__ . '/functions.php';
// --- 1. Обработка параметров командной строки ---
$options = getopt('', ['start-date:', 'end-date:']);
if (empty($options['start-date']) || empty($options['end-date'])) {
echo "Использование: php jira_export.php --start-date=ГГГГ-ММ-ДД --end-date=ГГГГ-ММ-ДД\n";
exit(1);
}
$startDate = $options['start-date'];
$endDate = $options['end-date'];
// Валидация формата дат
if (!preg_match('/^\d{4}-\d{2}-\d{2}$/', $startDate) || !preg_match('/^\d{4}-\d{2}-\d{2}$/', $endDate)) {
die("Ошибка: даты должны быть в формате ГГГГ-ММ-ДД\n");
}
// Извлекаем настройки из конфига
$jiraUrl = $config['jira']['url'];
$apiToken = $config['jira']['apiToken'];
$maxResults = $config['export']['maxResults'];
// --- 2. Инициализация клиента Guzzle ---
$client = new Client([
'base_uri' => $jiraUrl,
'headers' => [
'Authorization' => 'Bearer ' . $apiToken,
'Accept' => 'application/json',
],
]);
foreach ($teams as $team => $teamData) {
echo "Расчет для команды {$team}\n";
$filename = "{$team}_tasks_{$startDate}_to_{$endDate}.csv";
// --- 3. Подготовка JQL-запроса ---
// Запрос ищет задачи, у которых статус изменился на "Done" в указанный период.
$jql = "project in (".$teamData['projects'].") AND issuetype in standardIssueTypes() AND issuetype not in (Epic, \"Admin work\") AND resolutiondate > \"{$startDate}\" AND resolutiondate < \"{$endDate}\"";
$params = [
'jql' => $jql,
'maxResults' => $maxResults,
'fields' => 'issuetype,key,summary,assignee,resolution,aggregatetimeoriginalestimate,aggregateprogress,resolutiondate',
];
try {
// --- 4. Обработка пагинации ---
// Если задач больше, чем maxResults, Jira вернет только часть.
// Мы будем запрашивать страницы до тех пор, пока не получим все.
$allIssues = [];
$startAt = 0;
$totalFetched = 0;
do {
$response = $client->get('rest/api/2/search', [
'query' => $params + ['startAt' => $startAt]
]);
$data = json_decode($response->getBody(), true);
if (json_last_error() !== JSON_ERROR_NONE) {
throw new Exception("Ошибка декодирования JSON-ответа от Jira.");
}
$issues = $data['issues'] ?? [];
$allIssues = array_merge($allIssues, $issues);
// Обновляем счетчики для следующей итерации
$totalFetched += count($issues);
$startAt += count($issues);
echo "Получено задач: {$totalFetched} из {$data['total']}\n";
} while ($startAt < ($data['total'] ?? 0));
if (!empty($allIssues)) {
// Убираем дубликаты, там где изменения не требуются
$allIssues = filterByResolution($allIssues);
// Убираем задачи, исполнители на которых не исполнители
$allIssues = filterByExecutors($allIssues, array_keys($teamData['executors']));
//file_put_contents($filename.".json", json_encode($allIssues, JSON_PRETTY_PRINT));die();
echo "Убрали лишнее, осталось ".count($allIssues)."\n";
$task = null;
foreach ($allIssues as $i => $issue) {
$statuses = getStatusForIssue($issue['key'], $client);
//$allIssues[$i]['countStatuses'] = $statuses;
$firstDateInStatus = array_map(function($value) {
return is_array($value) && count($value) > 1 ? $value[1] : null;
}, $statuses);
$countStatus = array_map(function($value) {
return is_array($value) && count($value) > 1 ? $value[0] : null;
}, $statuses);
$task = new \Nechaev\Reports\Task(
$issue["fields"]["issuetype"]["name"],
$issue['key'],
$issue["fields"]["summary"],
$issue["fields"]["assignee"]["name"],
$issue["fields"]["aggregatetimeoriginalestimate"],
$issue["fields"]["aggregateprogress"]["progress"],
StatusHelper::getDataByStatus($firstDateInStatus, StatusHelper::getInWorkStatuses()),
$issue["fields"]["resolutiondate"],
StatusHelper::getDataByStatus($countStatus, StatusHelper::getInReviewStatuses()),
StatusHelper::getDataByStatus($countStatus, StatusHelper::getInTestingStatuses()),
);
file_put_contents($filename, $task, FILE_APPEND | LOCK_EX);
}
// --- 5. Сохранение в файл ---
echo "Данные успешно сохранены в файл: {$filename}\n";
} else {
echo "За указанный период завершенных задач не найдено.\n";
}
} catch (GuzzleException | Exception $e) {
echo "Ошибка: " . $e->getMessage() . "\n";
}
}