# Настройка redmine-reporter ## Источники конфигурации Приоритет, от высшего к низшему: ``` CLI-флаги > переменные окружения > .env > YAML > кодовые дефолты ``` Если значение не задано на верхнем уровне, берётся уровень ниже. `.env` и YAML работают одновременно — можно оставить оба, можно удалить `.env` после миграции. ## YAML-конфиг Основной файл: `~/.config/redmine-reporter/config.yml`. Создаётся с правами `0600` (владелец: чтение/запись, остальные: доступ запрещён). Директория `~/.config/redmine-reporter/` — с правами `0700`. Если права файла шире `0600`, при запуске выводится предупреждение. ### Структура ```yaml redmine: url: https://red.eltex.loc api_key: ${REDMINE_API_KEY} author: "Кокос А.А." verify_ssl: true period: precision: date default_from: "2026-06-01" # default_to можно не указывать — тогда конец периода будет сегодня default_to: "2026-06-30" dynamic: false last_used: from: "2026-06-30T09:00:00" to: "2026-06-30T12:00:00" 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` (по умолчанию) | Стандартная проверка TLS средствами requests (системные CA / certifi) | | `false` | Проверка отключена — при запуске выводится предупреждение о риске MITM | | строка с путём, например `/etc/ssl/my-ca.pem` | Путь к собственному CA-bundle, передаётся в requests как есть | До версии с унификацией `verify_ssl: true` подставлял захардкоженный путь `/etc/ssl/certs/ca-certificates.crt`, который отсутствует на части дистрибутивов. Теперь `true` в YAML и `REDMINE_VERIFY=true` в env работают одинаково — оба включают стандартную проверку без привязки к конкретному пути. ### `period.precision` — точность периода Определяет, как вычисляется следующий период после фиксации: - `date` (по умолчанию) — период с точностью до дня. Следующий запуск (после `--commit`) начинается со следующего дня. - `datetime` — период с точностью до секунды. При повторном запуске time entries с `created_on` и `updated_on` ранее `last_used.to` исключаются (AND-логика: запись исключается только если **оба** поля раньше cutoff). Это предотвращает дублирование при отправке отчёта внутри рабочего дня. `last_used.from` / `last_used.to` записываются автоматически при `--commit`. Вручную редактировать не требуется. ### `period.default_to` — необязательное окончание периода Если `period.default_to` не задан, а `period.default_from` задан, инструмент использует сегодняшнюю дату в качестве конца периода. ```yaml period: default_from: "2026-07-01" # default_to отсутствует → конец периода = сегодня ``` Это предотвращает устаревание периода, когда отчёт генерируется автоматически (`--send`, `--commit`) без явного `--date`. Аналогично работает `DEFAULT_TO_DATE`: если переменная не задана, а `DEFAULT_FROM_DATE` задана, конец периода = сегодня. ### `--commit` — автофиксация периода Флаг `--commit` сохраняет использованный период в YAML-конфиг, чтобы следующий запуск автоматически начинался с нового периода. **Что делает:** 1. Генерирует отчёт как обычно. 2. Сохраняет отчёт в файл: - Если указан `--output` — по явному пути. - Если `--output` не указан — по шаблону из `output.dir` / `output.filename`. 3. Записывает `period.last_used.from` / `period.last_used.to` в YAML-конфиг. 4. При `period.precision: datetime` сохраняет текущий момент времени (ISO с секундами). 5. При `period.precision: date` сохраняет даты периода. **Поведение `period.dynamic`:** - `dynamic: true` — следующий запуск (без `--date`) вычисляет период от `last_used`: - Полный календарный месяц → следующий полный месяц. - Произвольный диапазон → та же длительность, начиная со дня после `last_used.to`. - `dynamic: false` — `--commit` перезаписывает `default_from`/`default_to` на использованный период. **Примеры:** ```bash # Июнь 2026 → следующий запуск (без --date) → июль 2026 redmine-reporter --date 2026-06-01--2026-06-30 --commit # Произвольный диапазон: 15-20 июня → следующий запуск → 21-26 июня redmine-reporter --date 2026-06-15--2026-06-20 --commit # С datetime-точностью: повторный запуск не дублирует записи redmine-reporter --commit ``` ### `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`. **Пример конфигурации:** ```yaml 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. Формирует MIME-письмо: - Тема, plain-text тело и вложение (если `attach: true`). - При `email.html: true` — дополнительно HTML-версия тела (`multipart/alternative`), сгенерированная из таблицы отчёта. 4. Отправляет через SMTP с TLS (таймаут 30 секунд). **Файл отчёта сохраняется до попытки отправки** — при ошибке SMTP файл остаётся на диске, данные не теряются. **Ошибки SMTP:** - Нет соединения → `"Не удалось подключиться к SMTP-серверу host:port"` - Неверный логин/пароль → `"Ошибка аутентификации SMTP. Проверьте логин и пароль."` - Таймаут → `"Таймаут соединения с SMTP-сервером."` - Другая ошибка → `"Ошибка отправки письма: <детали>"` Все ошибки выводятся в stderr, код возврата 1. **Примеры:** ```bash # Отправить отчёт за июнь (сохранится по шаблону 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` | Неизвестные плейсхолдеры остаются в имени как есть. Примеры: ```yaml # По умолчанию 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}` — при загрузке оно заменяется на значение переменной окружения: ```yaml redmine: api_key: ${REDMINE_API_KEY} email: smtp: password: ${SMTP_PASSWORD} ``` Это безопаснее, чем хранить секреты plaintext в YAML. Однако plaintext-секреты **не запрещены** — если вписать `api_key: "abc123"` напрямую, система примет. Права `0600` — основная защита. ### `report` — настройки содержимого отчёта Секция управляет тем, что попадает в сгенерированный отчёт. | Поле | Тип | По умолчанию | Описание | |---|---|---|---| | `no_time` | bool | `false` | Не включать затраченное время в файл отчёта | `report.no_time` применяется только в автоматических режимах (`--commit`, `--send`). При ручном `--output` YAML-настройка игнорируется — там работает только CLI-флаг `--no-time`. CLI-флаг `--no-time` всегда имеет приоритет над YAML. **Примеры:** ```yaml report: no_time: true ``` ```bash # Автоматический режим: время не выводится redmine-reporter --commit # Ручной режим: report.no_time игнорируется, время выводится redmine-reporter --output report.odt # Ручной режим с явным флагом: время не выводится redmine-reporter --output report.odt --no-time ``` ## Разрешение выходного пути Функция `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` (неизвестное расширение) → используется как есть, форматтер выбирается по расширению. ## Миграция с `.env` на YAML ### Быстрый старт ```bash # 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`, `email`). - Секреты (`REDMINE_API_KEY`, `SMTP_PASSWORD`) записывает как `${VAR}`, если переменная существует, иначе — пустая строка. - Создаёт файл с правами `0600`, директорию — с `0700`. ### Флаги миграции | Флаг | Назначение | |---|---| | `--init-config` | Создать YAML и выйти | | `--init-config --force` | Перезаписать существующий YAML | | `--config-path PATH` | Сохранить YAML по указанному пути (по умолчанию `~/.config/redmine-reporter/config.yml`) | Если `DEFAULT_TO_DATE` не задана, а `DEFAULT_FROM_DATE` задана, сгенерированный YAML будет содержать пустое `default_to`, и при запуске инструмент использует сегодняшнюю дату. ### Проверка после миграции ```bash # Запустить без .env в текущей директории cd /tmp redmine-reporter --date 2026-06-01--2026-06-30 ``` Если отработал — YAML-конфиг читается корректно. Если `REDMINE_URL is required` — проверь права: ```bash ls -la ~/.config/redmine-reporter/ # config.yml должно быть -rw------- (600) # директория должна быть drwx------ (700) ``` ### Сосуществование `.env` и YAML Можно оставить оба источника. `.env` имеет **более высокий приоритет**, чем YAML: ``` .env значения переопределяют YAML, если заданы YAML работает как базовый слой для всего, что не в .env ``` Это safe — если с YAML что-то пойдёт не так, просто положи `.env` обратно. ### Откат ```bash rm ~/.config/redmine-reporter/config.yml ``` ## `.env` (legacy) Для обратной совместимости `.env` продолжает работать без изменений. ```ini REDMINE_URL=https://red.eltex.loc REDMINE_API_KEY=your-api-key REDMINE_AUTHOR=Кокос А.А. DEFAULT_FROM_DATE=2026-06-01 DEFAULT_TO_DATE=2026-06-30 ``` Если ни `.env`, ни YAML не заданы — используются кодовые дефолты (текущий месяц как период, стандартная проверка TLS, пустой автор). ## Безопасность - YAML-конфиг: права `0600`, директория `0700`. - Права шире `0600` → warning в stderr при каждом запуске. - Секреты рекомендуется хранить через `${VAR}`, а не plaintext. - `.env` **не рекомендуется** для постоянных настроек — оставьте его только для CI/CD или временных переопределений.