Files
redmine-reporter/docs/CONFIG.md
Кокос Артем Николаевич 27d21ef639 refactor: период через period.from вместо last_used; дедуп удалён
Удалены last_used, precision, dynamic и дедупликация по created_on/updated_on. Период задаётся одним полем period.from (env FROM_DATE), окно -- от этой даты до сегодня. После успешного --commit/--send начало окна сдвигается на конец отчёта; datetime-границы --date приводятся к полным дням. Схема конфига ломающая: старые ключи игнорируются, миграция описана в документации.
2026-09-30 12:37:00 +07:00

27 KiB
Raw Permalink Blame History

Настройка redmine-reporter

Оглавление

Источники конфигурации

Приоритет, от высшего к низшему:

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-конфиге.

Что делает:

  1. Генерирует отчёт как обычно.
  2. Сохраняет отчёт в файл:
    • Если указан --output — по явному пути.
    • Если --output не указан — по шаблону из output.dir / output.filename.
  3. Запрашивает подтверждение: «Отправить? [y/N]». Ответ «y»/«yes» продолжает, иначе отправка отменяется (без сдвига периода).
  4. Формирует MIME-письмо:
    • Тема, plain-text тело и вложение (если attach: true).
    • При email.html: true — дополнительно HTML-версия тела (multipart/alternative), сгенерированная из таблицы отчёта.
  5. Отправляет через SMTP (таймаут 30 секунд). STARTTLS включается только при email.smtp.tls: true; аутентификация — только если задан email.smtp.user.
  6. При успешной отправке сдвигает начало периода.

Файл отчёта сохраняется до попытки отправки — при ошибке 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() определяет итоговый путь к файлу:

  1. --output не указан → консольный вывод.
  2. --output xlsx (bare format) → путь формируется как output.dir / output.filename с подстановкой {ext} = bare format и дат из периода.
  3. --output /path/report (без расширения) → дописывается .output.default_format.
  4. --output /path/report.csv (с расширением) → используется как есть.
  5. --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 или временных переопределений.