- tests/test_cli.py: fix 26 fetch_issues_with_spent_time mocks to return 3-element tuples (issue, hours, activities) matching the real signature - pyproject.toml: add [tool.pytest.ini_options] with testpaths and pythonpath so bare pytest works - tests/test_client.py: add pagination test (>100 time entries arriving in pages, hours aggregated across all pages) - tests/test_formatters.py: add structural tests — XLSX full header row and grand total row via openpyxl, HTML thead with all columns and tbody row count - add strict xfail trap-tests for known bugs: #58 (naive created_on vs aware dedup cutoff TypeError) and #59 (parse_date_range rejects datetime range from dynamic+datetime period) Closes #67
redmine-reporter
CLI-инструмент для генерации отчётов по задачам Redmine на основе записей о затраченном времени.
Проект предназначен для внутреннего использования с https://red.eltex.loc/.
Лицензия: MIT.
Возможности
- Получение time entries текущего или указанного пользователя из Redmine.
- Авторизация через Redmine API token или логин/пароль.
- Группировка задач по проекту и версии.
- Перевод статусов задач на русский язык.
- Разбивка по типам активности (
--by-activity). - Вывод в консоль (таблица / компактный вид).
- Экспорт в ODT, CSV, Markdown, HTML, JSON и Excel (.xlsx).
- Excel-отчёт с merge-ячейками по проекту/версии, итогами, автошириной, автофильтром и закреплённой шапкой.
- Сводка по времени (
--summary). - YAML-конфиг (
~/.config/redmine-reporter/config.yml): шаблон имени файла, путь по умолчанию, период, email, настройки содержимого отчёта (report.no_time). - Умное разрешение
--output: bare-формат (xlsx) → путь по шаблону, без расширения → автодописывание. --commit: автосохранение отчёта в файл + фиксация периода в YAML-конфиге для следующего запуска.--send: отправка отчёта по email через SMTP сразу после генерации.- HTML-версия тела письма при
--send, если включено в YAML-конфиге (email.html: true). - Понятные сообщения об ошибках Redmine API, SMTP и файловой системы.
- Загрузка альтернативного
.envчерез--config.
Установка
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 .
Для разработки:
pip install -e ".[dev]"
Настройка
Источники конфигурации (от высшего приоритета к низшему):
CLI-флаги > переменные окружения > .env > YAML-конфиг > кодовые дефолты
YAML-конфиг (основной способ)
# Сгенерировать YAML из текущего .env
redmine-reporter --init-config
# Редактировать под себя
vim ~/.config/redmine-reporter/config.yml
Структура:
redmine:
url: https://red.eltex.loc
api_key: ${REDMINE_API_KEY}
author: "Кокос А.А."
verify_ssl: true
period:
precision: date # date | datetime
default_from: "2026-06-01"
# default_to можно не указывать — конец периода будет сегодня
default_to: "2026-06-30"
dynamic: false
# last_used заполняется --commit (см. docs/CONFIG.md)
output:
dir: ~/reports
filename: "{author}_{from}_{to}.{ext}"
default_format: xlsx
report:
no_time: false
email:
html: false
smtp:
host: smtp.example.com
port: 587
user: bot@example.com
password: ${SMTP_PASSWORD}
tls: true
from: bot@example.com
to:
- boss@example.com
cc: []
bcc: []
subject: "Отчёт {author} за {period}"
body_text: "Во вложении отчёт."
attach: true
Шаблон output.filename поддерживает {author}, {from}, {to}, {date} (DD_MM_YYYY), {ext}.
Шаблоны email.subject и email.body_text поддерживают {author}, {period} (строка диапазона, например 2026-06-01--2026-06-30).
Подробнее: docs/CONFIG.md.
.env (legacy)
REDMINE_URL=https://red.eltex.loc/
REDMINE_API_KEY=ваш_api_token
REDMINE_AUTHOR=Иванов Иван Иванович
DEFAULT_FROM_DATE=2026-01-01
# DEFAULT_TO_DATE можно не задавать — тогда конец периода будет сегодня
DEFAULT_TO_DATE=2026-01-31
Переменные окружения:
| Переменная | Обязательность | Описание |
|---|---|---|
REDMINE_URL |
Да | URL Redmine. |
REDMINE_API_KEY |
Да, если нет логина и пароля | Redmine API token. |
REDMINE_USER |
Да, если нет токена | Логин Redmine. |
REDMINE_PASSWORD |
Да, если нет токена | Пароль Redmine. |
REDMINE_AUTHOR |
Нет | Имя автора для отчёта. |
DEFAULT_FROM_DATE |
Нет | Начальная дата периода по умолчанию (YYYY-MM-DD). |
DEFAULT_TO_DATE |
Нет | Конечная дата периода по умолчанию (YYYY-MM-DD). Если не задана, а DEFAULT_FROM_DATE задана — используется сегодняшняя дата. |
REDMINE_VERIFY |
Нет | TLS-проверка: true / false / путь к CA bundle. |
Использование
source .venv/bin/activate
Основные сценарии
Отчёт за период по умолчанию:
redmine-reporter
Произвольный период:
redmine-reporter --date 2026-02-01--2026-02-28
Другой пользователь:
redmine-reporter --user-id 42
redmine-reporter --user-login ivanov
redmine-reporter --user-name "Иванов И.И."
Переопределить URL / API-ключ:
redmine-reporter --url https://red.example.com --api-key ваш_токен
Альтернативный .env:
redmine-reporter --config /path/to/.env
Компактный / отладочный вывод:
redmine-reporter --compact
redmine-reporter --debug
Экспорт в файл
Явный путь:
redmine-reporter --output report.xlsx
redmine-reporter --output /path/to/report.odt
Только формат (путь и имя берутся из YAML-шаблона):
redmine-reporter --output xlsx # → output.dir/отчёт_01_07_2026.xlsx
redmine-reporter --output odt # → output.dir/отчёт_01_07_2026.odt
Путь без расширения (дописывается default_format из конфига):
redmine-reporter --output /tmp/report # → /tmp/report.xlsx (если default_format: xlsx)
Отправка по email (--send)
Отправить отчёт на email, указанный в YAML-конфиге (секция email):
# Сохранить по шаблону и отправить
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 --date 2026-06-01--2026-06-30 --send --commit
Если в секции email установить html: true, письмо будет отправлено в двух версиях: plain-text и HTML (таблица отчёта прямо в теле письма). Файл отчёта всё равно прикрепляется, если attach: true.
email:
html: true
Если секция email не настроена — ошибка с пояснением. При ошибке SMTP файл отчёта остаётся на диске, данные не теряются. Поддерживаются to, cc, bcc, TLS, отключение вложения (attach: false).
Фиксация периода (--commit)
# Сгенерировать, сохранить в файл по шаблону, запомнить период
redmine-reporter --commit
# С явным путём
redmine-reporter --commit --output report.xlsx
# Следующий запуск (без --date) возьмёт следующий период автоматически
redmine-reporter
# При precision=datetime запоминает момент времени
# (предотвращает дублирование записей внутри дня)
redmine-reporter --commit
Сводка и опции
Без времени / с разбивкой по активностям:
redmine-reporter --no-time
redmine-reporter --by-activity
redmine-reporter --by-activity --summary
--no-time можно задать в YAML-конфиге (report.no_time: true), чтобы автоматические режимы (--commit, --send) не включали затраченное время без явного флага. При ручном --output YAML-значение не применяется — только CLI-флаг --no-time.
Сводка:
redmine-reporter --summary
Форматы вывода
| Формат | Особенности |
|---|---|
| ODT | Заголовок с автором и месяцем, группировка по проекту/версии. |
| CSV | UTF-8 с BOM, полные значения project/version в каждой строке. |
| Markdown | Компактная таблица, повторяющиеся группы скрыты. |
| HTML | Полноценный HTML-документ с meta charset="utf-8". |
| JSON | Массив объектов: project, version, issue_id, subject, status, time. |
| Excel (.xlsx) | Merge cells, колонки Hours/Spent Time, итоги, автоширина, автофильтр, freeze panes. |
Полный список флагов
--date DATE Диапазон дат: YYYY-MM-DD--YYYY-MM-DD
--compact Компактный текстовый вывод вместо таблицы
--output PATH/FMT Путь к файлу (.odt/.csv/.md/.html/.json/.xlsx)
или bare-формат (xlsx/odt/...) — путь из конфига
--author NAME Переопределить имя автора
--no-time Не включать затраченное время в таблицу
--url URL Переопределить Redmine URL
--api-key KEY Переопределить Redmine API key
--config PATH Путь к альтернативному .env-файлу
--verbose Подробный вывод
--debug Отладочный вывод
--version Показать версию и выйти
--summary Вывести сводку по времени в stderr
--user-id ID Redmine ID пользователя для отчёта
--user-login LOGIN Логин пользователя Redmine
--user-name NAME Полное имя пользователя Redmine
--by-activity Разбить время по типам активности
--init-config Сгенерировать YAML-конфиг и выйти
--force Перезаписать существующий конфиг (с --init-config)
--config-path PATH Путь к YAML-конфигу (по умолчанию ~/.config/redmine-reporter/config.yml)
--commit Сохранить отчёт в файл и зафиксировать период в конфиге
--send Отправить отчёт по email после сохранения
Разработка
Проверки перед коммитом:
pytest
ruff check redmine_reporter tests
ruff format --check redmine_reporter tests
mypy redmine_reporter
Безопасность
- Не коммитьте
.env, API token, пароль или логин. - YAML-конфиг имеет права
0600, директория —0700. - Рекомендуется хранить секреты через
${VAR}, а не plaintext. - Используйте аккаунт с минимальными правами, достаточными для чтения time entries и задач.
- Инструмент работает только в режиме чтения и не изменяет данные в Redmine.