Удалены last_used, precision, dynamic и дедупликация по created_on/updated_on. Период задаётся одним полем period.from (env FROM_DATE), окно -- от этой даты до сегодня. После успешного --commit/--send начало окна сдвигается на конец отчёта; datetime-границы --date приводятся к полным дням. Схема конфига ломающая: старые ключи игнорируются, миграция описана в документации.
27 KiB
Настройка redmine-reporter
Оглавление
- Источники конфигурации
- YAML-конфиг
- Структура
redmine.verify_ssl— проверка TLS-сертификатаperiod.from— начало окна отчёта--date— формат диапазона- Авто-сдвиг начала периода
- Миграция старых ключей периода
email— настройка отправки по почте--send— отправка отчёта по emailoutput— путь и имя файла по умолчанию- Подстановка переменных окружения
report— настройки содержимого отчётаreport.status_translation— перевод статусов
- Разрешение выходного пути
- Миграция с
.envна YAML .env(legacy)- Безопасность
Источники конфигурации
Приоритет, от высшего к низшему:
CLI-флаги > переменные окружения > .env > YAML > кодовые дефолты
Нюанс с override при автозагрузке .env и --config — см.
Сосуществование .env и YAML.
Если значение не задано на верхнем уровне, берётся уровень ниже. .env и YAML
работают одновременно — можно оставить оба, можно удалить .env после миграции.
YAML-конфиг
Основной файл: ~/.config/redmine-reporter/config.yml.
Создаётся с правами 0600 (владелец: чтение/запись, остальные: доступ запрещён).
Директория ~/.config/redmine-reporter/ — с правами 0700.
Если права файла шире 0600, при запуске выводится предупреждение.
Структура
redmine:
url: https://red.eltex.loc
api_key: ${REDMINE_API_KEY}
author: "Кокос А.А."
verify_ssl: true
period:
from: "2026-06-01"
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
redmine.verify_ssl — проверка TLS-сертификата
Управляет проверкой TLS-сертификата Redmine. Семантика едина с переменной
окружения REDMINE_VERIFY:
| Значение | Поведение |
|---|---|
true (по умолчанию) |
Проверка по системному хранилищу CA операционной системы (через truststore) — корпоративные CA, добавленные в ОС, работают без настройки |
false |
Проверка отключена — при запуске выводится предупреждение о риске MITM |
строка с путём, например /etc/ssl/my-ca.pem |
Путь к собственному CA-bundle, передаётся в requests как есть |
До версии с унификацией verify_ssl: true подставлял захардкоженный путь
/etc/ssl/certs/ca-certificates.crt, который существует только в
Debian/Ubuntu. Теперь true в YAML и REDMINE_VERIFY=true в env работают
одинаково — оба включают проверку по системному хранилищу CA на любой ОС
(через truststore), без привязки к конкретному пути.
period.from — начало окна отчёта
Единственный ключ периода в YAML. Дата в формате YYYY-MM-DD:
period:
from: "2026-06-01"
Окно отчёта — from..сегодня: конец окна всегда сегодняшняя дата и отдельно
не настраивается. Переменная окружения FROM_DATE задаёт то же начало и имеет
приоритет над YAML:
--date > FROM_DATE (env) > period.from (YAML) > 1-е число текущего месяца
Разрешение начала окна:
| Условие | Начало окна |
|---|---|
from не задан (FROM_DATE и period.from пусты) |
1-е число текущего месяца |
from — корректная дата |
from |
from позже сегодняшней даты |
сегодня (окно «сегодня--сегодня») |
from некорректна (не YYYY-MM-DD) |
warning в stderr + 1-е число текущего месяца |
Граничный день (день коммита) становится началом следующего окна и потому
перечитывается: уже отправленные записи этого дня повторятся в следующем
отчёте. Это осознанное следствие отсутствия дедупликации; зато поздние
записи, добавленные в Redmine в день коммита после отправки, не теряются.
Повторный запуск --commit/--send в тот же день даёт окно
«сегодня--сегодня».
period.from записывается автоматически при --commit/--send; вручную
редактировать не требуется.
--date — формат диапазона
Флаг --date задаёт диапазон явно и переопределяет все остальные источники.
Каждая граница — дата YYYY-MM-DD или datetime YYYY-MM-DDTHH:MM:SS:
2026-06-01--2026-06-30;2026-06-30T09:00:00--2026-06-30T12:00:00.
Время в границах отбрасывается — окно всегда состоит из полных дней, так как
гранулярность Redmine — день. Границы можно смешивать (дата + datetime).
Начало позже конца (start > end) — ошибка.
Авто-сдвиг начала периода
--commit и --send генерируют отчёт, сохраняют его в файл (по --output
или по шаблону output.dir/output.filename) и сдвигают начало окна.
--send дополнительно отправляет отчёт по email (см.
ниже).
После успешного --commit (файл сохранён) или реальной отправки --send
(подтверждение «y» + успешная отправка) в конфиг пишется
period.from = <конец окна отчёта>. Следующий запуск без --date начинает
окно с граничного дня последнего отчёта.
Сдвиг НЕ происходит:
- если за период нет time entries (отчёт пуст — выход до сохранения);
- при отказе от подтверждения отправки в
--send(ответ не «y»/«yes»); - при ошибке SMTP в
--send(соединение, аутентификация, таймаут); - при ошибке сохранения файла отчёта.
Исключение: при явном --commit (сочетание --send --commit) отказ от
подтверждения отправки сдвиг не отменяет: окно всё равно сдвигается по
--commit.
При сочетании --send --commit ошибка SMTP подавляет и сдвиг по --commit:
файл остаётся сохранён, но начало периода не двигается.
Примеры:
# Окно 1--30 июня → следующий запуск (без --date) начнётся с 30 июня
redmine-reporter --date 2026-06-01--2026-06-30 --commit
# Произвольный диапазон 15--20 июня → следующее окно с 20 июня
redmine-reporter --date 2026-06-15--2026-06-20 --commit
# Отправить и сдвинуть окно (только при подтверждении «y» и успехе)
redmine-reporter --date 2026-06-01--2026-06-30 --send --commit
--commit/--send перезаписывают только period.from; остальные секции и
ключи YAML сохраняются. Файл перезаписывается через yaml.dump —
пользовательские комментарии и ручное форматирование теряются.
Миграция старых ключей периода
Старые ключи периода больше не читаются и тихо игнорируются при загрузке — их можно удалить из YAML:
period.last_used(включаяfrom/to);period.precision;period.dynamic;period.default_from/period.default_to.
Env DEFAULT_FROM_DATE / DEFAULT_TO_DATE заменены на FROM_DATE; конец
периода больше не настраивается (всегда сегодня). Дедупликация time entries
по created_on/updated_on удалена.
email — настройка отправки по почте
Секция email используется флагом --send. Если секция не настроена или smtp.host
пуст, --send завершится с ошибкой «Email не настроен».
Все поля:
| Поле | Тип | По умолчанию | Описание |
|---|---|---|---|
smtp.host |
строка | "" |
Адрес SMTP-сервера |
smtp.port |
число | 587 |
Порт SMTP |
smtp.user |
строка | "" |
Логин для аутентификации |
smtp.password |
строка | "" |
Пароль (рекомендуется ${SMTP_PASSWORD}) |
smtp.tls |
bool | true |
Использовать STARTTLS |
from |
строка | "" |
Адрес отправителя |
to |
список | [] |
Основные получатели |
cc |
список | [] |
Копия |
bcc |
список | [] |
Скрытая копия (не отображается в заголовках письма) |
subject |
строка | "Отчёт {author} за {period}" |
Тема письма |
body_text |
строка | "Во вложении отчёт." |
Текст письма (plain text) |
attach |
bool | true |
Прикреплять файл отчёта. Если false — только текст |
html |
bool | false |
Добавить HTML-версию тела письма (multipart/alternative) |
Подстановки в subject и body_text:
| Плейсхолдер | Описание | Пример |
|---|---|---|
{author} |
Имя автора из конфига или --author |
Кокос А.А. |
{period} |
Строка диапазона дат | 2026-06-01--2026-06-30 |
MIME-тип вложения определяется по расширению файла:
| Расширение | MIME-тип |
|---|---|
.xlsx |
application/vnd.openxmlformats-officedocument.spreadsheetml.sheet |
.odt |
application/vnd.oasis.opendocument.text |
.csv |
text/csv |
.html |
text/html |
.json |
application/json |
.md |
text/markdown |
Неизвестное расширение → application/octet-stream.
Пример конфигурации:
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
- team-lead@example.com
cc:
- manager@example.com
bcc: []
subject: "Отчёт {author} за {period}"
body_text: "Во вложении отчёт за период {period}."
attach: true
--send — отправка отчёта по email
Флаг --send сохраняет отчёт в файл, отправляет его через SMTP и сдвигает
начало периода при подтверждении и успешной отправке (см.
Авто-сдвиг). Требует настроенную
секцию email в YAML-конфиге.
Что делает:
- Генерирует отчёт как обычно.
- Сохраняет отчёт в файл:
- Если указан
--output— по явному пути. - Если
--outputне указан — по шаблону изoutput.dir/output.filename.
- Если указан
- Запрашивает подтверждение: «Отправить? [y/N]». Ответ «y»/«yes» продолжает, иначе отправка отменяется (без сдвига периода).
- Формирует MIME-письмо:
- Тема, plain-text тело и вложение (если
attach: true). - При
email.html: true— дополнительно HTML-версия тела (multipart/alternative), сгенерированная из таблицы отчёта.
- Тема, plain-text тело и вложение (если
- Отправляет через SMTP (таймаут 30 секунд). STARTTLS включается только при
email.smtp.tls: true; аутентификация — только если заданemail.smtp.user. - При успешной отправке сдвигает начало периода.
Файл отчёта сохраняется до попытки отправки — при ошибке SMTP файл остаётся на диске, данные не теряются.
Ошибки SMTP:
- Нет соединения →
"Не удалось подключиться к SMTP-серверу host:port" - Неверный логин/пароль →
"Ошибка аутентификации SMTP. Проверьте логин и пароль." - Таймаут →
"Таймаут соединения с SMTP-сервером." - Другая ошибка →
"Ошибка отправки письма: <детали>"
Все ошибки выводятся в stderr, код возврата 1.
Примеры:
# Отправить отчёт за июнь (сохранится по шаблону output.filename)
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
Совместимость с другими флагами:
| Комбинация | Поведение |
|---|---|
--send |
Сохранить по шаблону → отправить |
--send --output X |
Сохранить в X → отправить |
--send --commit |
Сохранить → подтвердить → отправить → сдвинуть начало периода |
--send с email.html: true |
Письмо с plain-text + HTML-таблицей |
--send без email в конфиге |
Ошибка, exit 1 |
--send при ошибке SMTP |
Файл сохранён, ошибка в stderr, exit 1 |
output — путь и имя файла по умолчанию
Секция управляет тем, куда и с каким именем сохраняется отчёт, когда --output не содержит полного пути.
Правила разрешения --output:
Аргумент --output |
Поведение |
|---|---|
/полный/путь/report.xlsx |
Используется как есть, конфиг игнорируется |
xlsx (bare format: xlsx, odt, csv, md, html, json) |
Путь = output.dir + output.filename, расширение = bare format |
/tmp/report (путь без расширения) |
Дописывается .default_format → /tmp/report.xlsx |
Шаблон имени файла:
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 |
Неизвестные плейсхолдеры остаются в имени как есть.
Примеры:
# По умолчанию
filename: "{author}_{from}_{to}.{ext}" # → Кокос_А.А._2026-06-01_2026-06-30.xlsx
# Русский формат даты
filename: "отчёт_{date}.{ext}" # → отчёт_30_06_2026.xlsx
# Без автора, только диапазон
filename: "report_{from}--{to}.{ext}" # → report_2026-06-01--2026-06-30.xlsx
Подстановка переменных окружения
В любом строковом значении YAML можно использовать ${VAR} — при загрузке
оно заменяется на значение переменной окружения:
redmine:
api_key: ${REDMINE_API_KEY}
email:
smtp:
password: ${SMTP_PASSWORD}
Это безопаснее, чем хранить секреты plaintext в YAML. Однако plaintext-секреты
не запрещены — если вписать api_key: "abc123" напрямую, система примет.
Права 0600 — основная защита.
report — настройки содержимого отчёта
Секция управляет тем, что попадает в сгенерированный отчёт.
| Поле | Тип | По умолчанию | Описание |
|---|---|---|---|
no_time |
bool | false |
Не включать затраченное время в файл отчёта |
status_translation |
map[str,str] | {} |
Переопределение/дополнение перевода статусов |
report.no_time применяется только в автоматических режимах (--commit, --send).
При ручном --output YAML-настройка игнорируется — там работает только CLI-флаг --no-time.
CLI-флаг --no-time всегда имеет приоритет над YAML.
Примеры:
report:
no_time: true
# Автоматический режим: время не выводится
redmine-reporter --commit
# Ручной режим: report.no_time игнорируется, время выводится
redmine-reporter --output report.odt
# Ручной режим с явным флагом: время не выводится
redmine-reporter --output report.odt --no-time
report.status_translation — перевод статусов
По умолчанию статусы Redmine переводятся встроенным словарём
(New → В работе, Closed → Закрыто и т.д.). Секция
report.status_translation переопределяет отдельные переводы и/или
добавляет новые статусы; не указанные здесь статусы переводятся
встроенным словарём, а совсем неизвестные выводятся как есть.
report:
status_translation:
"New": "Новая"
"Wait Release": "Ожидает релиза"
"Custom Status": "Кастомный статус"
Разрешение выходного пути
Функция resolve_output_path() определяет итоговый путь к файлу:
--outputне указан → консольный вывод.--output xlsx(bare format) → путь формируется какoutput.dir / output.filenameс подстановкой{ext}= bare format и дат из периода.--output /path/report(без расширения) → дописывается.output.default_format.--output /path/report.csv(с расширением) → используется как есть.--output /path/report.xyz(неизвестное расширение) → ошибка «Неизвестный формат файла», exit 1.
Миграция с .env на YAML
Быстрый старт
# 1. Генерируем YAML из текущего .env
redmine-reporter --init-config
# 2. Проверяем, что создалось
cat ~/.config/redmine-reporter/config.yml
# 3. Редактируем под себя (шаблон имени, период, etc.)
vim ~/.config/redmine-reporter/config.yml
Что делает --init-config
- Читает текущие значения из
.envи переменных окружения. - Формирует YAML со всеми секциями (
redmine,period,output,report,email). - В конец файла дописывает закомментированный пример
report.status_translation. - Секреты (
REDMINE_API_KEY,SMTP_PASSWORD) записывает как${VAR}, если переменная существует, иначе — пустая строка. - Создаёт файл с правами
0600, директорию — с0700.
Флаги миграции
| Флаг | Назначение |
|---|---|
--init-config |
Создать YAML и выйти |
--init-config --force |
Перезаписать существующий YAML |
--config-path PATH |
Путь к YAML-конфигу: загрузка при запуске, запись при --init-config и --commit (по умолчанию ~/.config/redmine-reporter/config.yml) |
Если задана FROM_DATE, сгенерированный YAML будет содержать period.from с
этим значением.
Проверка после миграции
# Запустить без .env в текущей директории
cd /tmp
redmine-reporter --date 2026-06-01--2026-06-30
Если отработал — YAML-конфиг читается корректно. Если REDMINE_URL is required —
проверь права:
ls -la ~/.config/redmine-reporter/
# config.yml должно быть -rw------- (600)
# директория должна быть drwx------ (700)
Сосуществование .env и YAML
Можно оставить оба источника. .env имеет более высокий приоритет, чем YAML:
.env значения переопределяют YAML, если заданы
YAML работает как базовый слой для всего, что не в .env
Автозагрузка .env (без --config) не перебивает реальные переменные
окружения (override=False). Исключение — --config FILE: указанный .env
загружается с override=True и перебивает переменные окружения (но не CLI-флаги).
Это safe — если с YAML что-то пойдёт не так, просто положи .env обратно.
Откат
rm ~/.config/redmine-reporter/config.yml
.env (legacy)
Для обратной совместимости .env продолжает работать как раньше, кроме ключей
периода: DEFAULT_FROM_DATE заменён на FROM_DATE, DEFAULT_TO_DATE удалён
(см. Миграция старых ключей периода).
REDMINE_URL=https://red.eltex.loc
REDMINE_API_KEY=your-api-key
REDMINE_AUTHOR=Кокос А.А.
FROM_DATE=2026-06-01
Если ни .env, ни YAML не заданы — используются кодовые дефолты (текущий месяц
как период, стандартная проверка TLS, пустой автор).
Безопасность
- YAML-конфиг: права
0600, директория0700. - Права шире
0600→ warning в stderr при каждом запуске. - Секреты рекомендуется хранить через
${VAR}, а не plaintext. .envне рекомендуется для постоянных настроек — оставьте его только для CI/CD или временных переопределений.