Tasks in the "Wishlist" bucket version are now excluded from the list and summary entirely (no due date, noise backlog); exact case match, tasks without a version are unaffected. Document --my-tasks in README and the user guide (sorting, summary metrics, OSC 8 links, stream separation); all examples use synthetic data. Declare ruff known-first-party in pyproject so the lint result is CWD-independent.
26 KiB
Руководство пользователя redmine-reporter
Оглавление
- Установка
- Первоначальная настройка
- Выбор периода
- Отчёт за другого пользователя
- Список открытых задач
- Экспорт в файл
- Содержимое отчёта
- Отправка по email
- Скользящее окно периода
- Справочник флагов
- Устранение неполадок
- См. также
Установка
Требуется Python >= 3.10.
git clone https://git.akokos.ru/artem.kokos/redmine-reporter.git
cd redmine-reporter
python3 -m venv .venv
source .venv/bin/activate
pip install --upgrade pip
pip install .
Проверка:
redmine-reporter --version
Перед каждым запуском активируйте окружение: source .venv/bin/activate.
Первоначальная настройка
- Убедитесь, что в текущей директории есть
.envсREDMINE_URLиREDMINE_API_KEY(или задайте эти переменные в окружении). - Сгенерируйте YAML-конфиг:
redmine-reporter --init-config
Результат: файл ~/.config/redmine-reporter/config.yml (права 0600, директория 0700) со всеми секциями и закомментированным примером report.status_translation. Секреты, заданные в окружении, записываются как ${VAR}.
- Если файл уже существует — ошибка; для перезаписи добавьте
--force:
redmine-reporter --init-config --force
- Нестандартное расположение конфига:
redmine-reporter --init-config --config-path /etc/redmine-reporter/config.yml
--config-path задаёт путь и для загрузки YAML, и для записи при --init-config и --commit.
- Откройте файл и заполните минимум:
redmine.url,redmine.api_key,redmine.author.
--init-config несовместим с флагами отчёта (--date, --output, --compact, --summary, --user-id/--user-login/--user-name, --no-time, --by-activity, --send) — указывайте его отдельно.
Полный референс всех секций и переменных: CONFIG.md.
Выбор периода
Окно отчёта — диапазон дат from..to. Конец (to) всегда сегодняшняя дата,
если диапазон не задан явно через --date.
Приоритет начала окна (от высшего к низшему):
--date— явный диапазон (полностью переопределяет окно).FROM_DATE(env) — начало; конец — сегодня.period.from(YAML) — начало; конец — сегодня.- Ничего не задано — текущий месяц: с 1-го числа по сегодня.
Форматы --date:
# Даты
redmine-reporter --date 2026-06-01--2026-06-30
# Дата-время (границы флорятся до полных дней)
redmine-reporter --date 2026-06-01T09:00:00--2026-06-01T18:00:00
Границы с временем округляются до дат — отчёт строится за полные дни диапазона.
Границы можно смешивать (дата + дата-время). Начало позже конца
(start > end) — ошибка.
Краевые случаи:
fromпозже сегодняшней даты — окно «сегодня--сегодня».fromнекорректна (неYYYY-MM-DD) — warning + текущий месяц.
Отчёт за другого пользователя
Без флагов отчёт строится за текущего пользователя.
redmine-reporter --user-id 42
redmine-reporter --user-login ivanov
redmine-reporter --user-name "Иванов Иван Иванович"
Правила:
- Флаги
--user-id,--user-login,--user-nameвзаимоисключающие: укажите только один, иначе ошибка. - Все три принимают одно значение. Число или строка из цифр → поиск по ID. Иначе — точное регистрозависимое совпадение логина.
- Если по логину совпадений нет — поиск по имени. Одно совпадение → пользователь найден.
- Несколько совпадений по имени → ошибка «Multiple users match...» со списком логинов (при дублях логина — ID).
- Ноль совпадений → ошибка «User '...' not found...».
Список открытых задач
--my-tasks -- отдельный режим: вместо отчёта по затраченному времени выводит
открытые задачи, назначенные на вас, по всем проектам. Отчётное окно периода
к режиму не применяется.
redmine-reporter --my-tasks # задачи владельца API-ключа
redmine-reporter --my-tasks --user-id 42 # чужой список по ID
redmine-reporter --my-tasks --user-login ivanov # по логину
Правила:
--user-id/--user-login/--user-nameвыбирают, чей список показать; по умолчанию -- владелец API-ключа. Разрешение пользователей то же, что для отчёта (см. Отчёт за другого пользователя).--url,--api-key,--config,--config-path,--verbose,--debugработают как обычно.- Совмещение с отчётными флагами (
--date,--output,--compact,--summary,--no-time,--by-activity,--commit,--send) -- ошибка «--my-tasks cannot be used with report-generating flags.», exit 1. - Задачи в версии
Wishlistисключаются из режима целиком: не попадают ни в таблицу, ни в сводку.
Сортировка -- от срочного к менее срочному:
- Приоритет
P1..P5: меньший номер срочнее; неизвестное имя приоритета получает низший ранг. - Внутри приоритетной группы -- срок версии (due date) по возрастанию.
- Задачи без версии или без срока -- в конец своей приоритетной группы.
- При прочих равных -- по возрастанию ID.
Таблица печатается в stdout, сводка -- в stderr перед таблицей. При
перенаправлении (redmine-reporter --my-tasks > tasks.txt) в файл попадает
только таблица.
Колонки таблицы: ID | Тема | Статус | Приор. | Версия | Срок. Пример (синтетические данные, ID в терминале кликабелен):
ID Тема Статус Приор. Версия Срок
---- -------------------------------- -------------- -------- -------- --------------
101 Критический дефект сборки образа В работе P1 v2.4.0 2026-10-15 (!)
102 Обновить документацию API Новая P2 v2.5.0 2026-12-01
103 Ревью pull request Обратная связь P3 - -
- ID -- гиперссылка (OSC 8) на страницу задачи
<url>/issues/<id>: в терминалах с поддержкой кликабельна, без поддержки остаётся обычным номером. - Срок -- дата релиза целевой версии; просроченный (раньше сегодняшней даты) помечается
(!). - Пустые «Версия» и «Срок» -- прочерк
-. - Статусы переводятся на русский тем же словарём, что и в отчётах: встроенный словарь +
report.status_translation(см. Перевод статусов).
Сводка (пример с синтетическими данными):
Открытых: 3 | просроченных: 1 | без версии: 1 | без срока: 0 | потрачено: 12.5h | оценка: 8h (по 2 из 3)
- «просроченных» -- задачи со сроком версии раньше сегодняшней даты.
- «без версии» -- задачи без целевой версии; «без срока» -- задачи с версией, но без известной даты релиза.
- «потрачено» -- сумма полей
spent_hoursзадач списка. - «оценка» -- сумма полей
estimated_hours; «(по N из M)» -- у скольких задач из списка есть оценка. Если оценок нет ни у одной задачи, блок «оценка» не выводится.
Сроки версий дозагружаются отдельным запросом на каждую уникальную версию списка. Недоступная версия -- предупреждение в stderr и пустой срок у её задач, вывод не прерывается.
Пустой список (в том числе когда все открытые задачи попали в исключаемую
версию Wishlist): «ℹ️ Открытых задач нет.» (stderr), exit 0.
Экспорт в файл
Флаг --output определяется по четырём правилам:
| Аргумент | Результат |
|---|---|
--output xlsx (bare-формат: xlsx, odt, csv, md, html, json, регистронезависимо) |
Путь = output.dir + шаблон output.filename из YAML, расширение = указанный формат |
--output /tmp/report (путь без расширения) |
Дописывается . + output.default_format → /tmp/report.xlsx |
--output /tmp/report.csv (путь с любым расширением) |
Используется как есть |
--output /tmp/report.xyz (неизвестное расширение) |
Ошибка «Неизвестный формат файла: '.xyz'. Поддерживаются: .odt, .csv, .md, .html, .json, .xlsx», exit 1 |
Формат .odt требует установленного пакета odfpy (устанавливается по умолчанию) — иначе отдельная ошибка.
Примеры:
redmine-reporter --output xlsx # по шаблону в output.dir
redmine-reporter --output 2026-06-report # → 2026-06-report.xlsx (если default_format: xlsx)
redmine-reporter --output reports/june.csv # как есть
Плейсхолдеры output.filename:
| Плейсхолдер | Описание | Пример |
|---|---|---|
{author} |
Имя автора, пробелы → _ |
Кокос_А.А. |
{from} |
Начало периода, YYYY-MM-DD |
2026-06-01 |
{to} |
Конец периода, YYYY-MM-DD |
2026-06-30 |
{date} |
Конец периода, DD_MM_YYYY |
30_06_2026 |
{ext} |
Расширение без точки | xlsx |
Неизвестные плейсхолдеры остаются в имени как есть.
Нюансы с путями:
~в явном--outputраскрывает шелл, а не программа:redmine-reporter --output ~/report.xlsxработает, а в кавычках ("~/report.xlsx") — нет.expanduserприменяется только кoutput.dirиз YAML.
Содержимое отчёта
--no-time
Убирает затраченное время из отчёта. Физически удаляет колонку времени только CSV. XLSX, HTML, ODT, Markdown, JSON и консольный вывод оставляют пустые колонки/поля; в XLSX дополнительно пропадают строки итогов по версиям/проектам/всего.
redmine-reporter --output report.xlsx --no-time
YAML-настройка report.no_time действует только в автоматических режимах (--commit, --send). При ручном --output работает только CLI-флаг.
--by-activity
Разбивка затраченного времени по типам активности. В JSON-отчёте добавляется поле activities.
redmine-reporter --by-activity
--summary
Печатает сводку в stderr (после отчёта):
total— суммарное время;project:*— время по каждому проекту;activity:*— время по каждой активности (только при одновременном--by-activity).
Версии в сводку не входят.
redmine-reporter --by-activity --summary
--compact
Компактный текстовый вывод в консоль вместо таблицы:
redmine-reporter --compact
Перевод статусов
Статусы задач переводятся встроенным словарём; секция report.status_translation переопределяет или дополняет переводы. Подробно: CONFIG.md.
Отправка по email
Требуется секция email в YAML-конфиге (см. CONFIG.md).
redmine-reporter --date 2026-06-01--2026-06-30 --send
redmine-reporter --date 2026-06-01--2026-06-30 --output report.xlsx --send
redmine-reporter --send --commit
Факты:
- Файл отчёта сохраняется на диск ДО отправки: при ошибке SMTP файл остаётся на месте.
- Перед отправкой запрашивается подтверждение «Отправить? [y/N]»; ответ «y»/«yes» продолжает, иначе отправка отменяется (без сдвига периода, если не задан явный
--commit). - При успешной отправке начало периода сдвигается (см. Скользящее окно периода); при отмене (если не задан явный
--commit) или ошибке SMTP — без сдвига. - Секция
emailотсутствует илиsmtp.hostпуст → ошибка «Email не настроен. Добавьте секцию 'email' в конфиг...», exit 1. email.html: true→ письмоmultipart/alternative: plain-text + HTML-таблица отчёта в теле.- Файл прикрепляется при
attach: true; MIME-тип определяется по расширению, неизвестное →application/octet-stream. - Получатели
bccуказываются только в envelope (не видны в заголовках письма). - STARTTLS применяется только при
smtp.tls: true; аутентификация на SMTP-сервере — только если заданsmtp.user. - Таймаут соединения с SMTP — 30 секунд.
Точные тексты ошибок:
- «Ошибка аутентификации SMTP. Проверьте логин и пароль.»
- «Таймаут соединения с SMTP-сервером.»
- «Ошибка отправки письма: ...»
- «Не удалось подключиться к SMTP-серверу host:port»
Скользящее окно периода
После успешного --commit (файл сохранён) или реальной отправки --send
(подтверждение «y» + успех) окно отчёта сдвигается вперёд: в конфиг пишется
period.from = <конец окна>. Следующий запуск без --date
начинается с граничного дня последнего отчёта.
Типичный цикл:
# 1. Отчёт за июнь 2026: сохранить, отправить, сдвинуть начало на 30 июня
redmine-reporter --date 2026-06-01--2026-06-30 --send --commit
# 2. Следующий запуск без --date берёт окно с 30 июня по сегодня
redmine-reporter --send --commit
Граничный день: начало следующего окна совпадает с днём коммита, поэтому этот
день перечитывается. Записи дня коммита, уже попавшие в прошлый отчёт,
повторятся (дедупликации по created_on/updated_on нет — это осознанное
следствие), зато поздние записи, добавленные в Redmine в этот день после
отправки, не теряются.
Повторный запуск --commit/--send в тот же день даёт окно
«сегодня--сегодня», которое повторно включает уже отправленные записи этого
дня.
Важно: --commit/--send перезаписывают только period.from; остальные
ключи YAML сохраняются, но пользовательские комментарии теряются
(перезапись через yaml.dump).
Справочник флагов
| Флаг | Описание |
|---|---|
--date |
Явный диапазон: границы — дата YYYY-MM-DD или datetime YYYY-MM-DDTHH:MM:SS. Время отбрасывается (полные дни), границы можно смешивать; start > end — ошибка. |
--compact |
Компактный текстовый вывод в консоль вместо таблицы. |
--output |
Путь к файлу (.odt/.csv/.md/.html/.json/.xlsx) или bare-формат — тогда путь берётся из YAML-шаблона; без флага — вывод в консоль (stdout). |
--author |
Переопределить имя автора отчёта. |
--no-time |
Не включать затраченное время в отчёт. |
--url |
Переопределить URL Redmine. |
--api-key |
Переопределить API-ключ Redmine. |
--config |
Путь к альтернативному .env-файлу. |
--verbose |
Подробный вывод; показывает traceback при ошибках. |
--debug |
Отладочный вывод; показывает traceback при ошибках. |
--version |
Показать версию и выйти. |
--summary |
Сводка по времени в stderr: total, project:*, activity:* (версии не печатаются). |
--user-id |
Отчёт за пользователя по ID. |
--user-login |
Отчёт за пользователя по логину (точное регистрозависимое совпадение). |
--user-name |
Отчёт за пользователя по имени. |
--by-activity |
Разбивка времени по типам активности (в JSON — поле activities). |
--init-config |
Сгенерировать YAML-конфиг из текущего .env/окружения и выйти. |
--force |
Перезаписать существующий YAML-конфиг (только с --init-config). |
--config-path |
Путь к YAML-конфигу: загрузка, запись --init-config и --commit. По умолчанию ~/.config/redmine-reporter/config.yml. |
--commit |
Сохранить отчёт в файл и сдвинуть начало периода (period.from = конец окна) в YAML. |
--send |
Отправить отчёт по email после сохранения файла; при подтверждении и успехе сдвинуть начало периода. |
--my-tasks |
Вместо отчёта вывести открытые задачи, назначенные на вас (или на пользователя из --user-id/--user-login/--user-name): таблица с сортировкой по срочности + сводка в stderr. Несовместим с --date, --output, --compact, --summary, --no-time, --by-activity, --commit, --send. Подробнее: Список открытых задач. |
Устранение неполадок
| Ошибка | Причина | Решение |
|---|---|---|
| «REDMINE_URL must use HTTPS...» (exit 1) | URL Redmine не по HTTPS | Укажите https:// в redmine.url / REDMINE_URL / --url. |
| «Authentication failed: invalid API key, login or password. Check REDMINE_API_KEY / REDMINE_USER / REDMINE_PASSWORD.» | Неверный или отсутствующий API-ключ, логин или пароль | Проверьте redmine.api_key / --api-key (или REDMINE_USER / REDMINE_PASSWORD). |
| «User '...' not found...» | Пользователь не найден ни по ID, ни по логину, ни по имени | Проверьте написание; логин сравнивается точно с учётом регистра. |
| «Multiple users match...» | По имени найдено несколько пользователей (или несколько дублей логина) | Используйте --user-login с логином из списка или уточните числовой ID для --user-id. |
Указано несколько --user-* |
Флаги взаимоисключающие | Оставьте только один из --user-id / --user-login / --user-name. |
| «--my-tasks cannot be used with report-generating flags.» (exit 1) | --my-tasks совмещён с отчётными флагами (--date, --output, --compact, --summary, --no-time, --by-activity, --commit, --send) |
Запускайте режим отдельно: список задач и отчёт -- разные команды (см. Список открытых задач). |
| «Неизвестный формат файла: '.xyz'. Поддерживаются: .odt, .csv, .md, .html, .json, .xlsx» (exit 1) | --output с неизвестным расширением |
Используйте одно из поддерживаемых расширений. |
Ошибка про odfpy при .odt |
Пакет odfpy не установлен |
pip install odfpy или выберите другой формат. |
| «Email не настроен. Добавьте секцию 'email' в конфиг...» (exit 1) | --send без секции email в YAML или с пустым smtp.host |
Добавьте секцию email (см. CONFIG.md). |
| «Ошибка аутентификации SMTP. Проверьте логин и пароль.» | Неверные smtp.user/smtp.password |
Проверьте логин и пароль в конфиге. |
| «Таймаут соединения с SMTP-сервером.» | Сервер не ответил за 30 секунд | Проверьте сеть, smtp.host и smtp.port. |
| «Не удалось подключиться к SMTP-серверу host:port» | Нет соединения с SMTP | Проверьте smtp.host, smtp.port и доступность сервера. |
| «Ошибка отправки письма: ...» | Прочая ошибка SMTP | Смотрите детали после двоеточия; файл отчёта уже сохранён на диске. |
| Предупреждение о правах конфига при старте | Права config.yml шире 0600 |
chmod 600 ~/.config/redmine-reporter/config.yml. |
| Предупреждение о MITM при старте | verify_ssl: false / REDMINE_VERIFY=false — проверка TLS отключена |
Включите проверку или используйте только в доверенной сети. |
«⚠️ Could not load version ...: Due date will be empty for its issues.» в режиме --my-tasks |
Версия из списка задач недоступна (нет прав, удалена, сбой сети) | Некритично: срок этой версии останется пустым; проверьте права доступа к проекту версии. |
| Не виден traceback при ошибке | Traceback показывается только с --verbose/--debug |
Повторите запуск с --debug. |
API-ключ в текстах ошибок маскируется (***).