Добавлена инструкция по установке
This commit is contained in:
parent
1983c88f8f
commit
f5b547e8ce
9 changed files with 524 additions and 0 deletions
22
configs/configs.examples/calendar-enhancer.jsonc
Normal file
22
configs/configs.examples/calendar-enhancer.jsonc
Normal file
|
|
@ -0,0 +1,22 @@
|
|||
{
|
||||
// TODO:
|
||||
"useForProjects": [
|
||||
"Test project name 1",
|
||||
"Test project name 2"
|
||||
],
|
||||
|
||||
// TODO:
|
||||
"customFields": [
|
||||
{
|
||||
"dateFormat": "yyyy-MM-dd HH:mm",
|
||||
"customFieldName": "Название кастомного поля 1",
|
||||
"alias": "Название кастомного поля 1"
|
||||
}
|
||||
],
|
||||
|
||||
"descriptionCalendarParams": {
|
||||
"title": "Календарь:",
|
||||
"lineRegexp": "(?<=\\*\\ ).+"
|
||||
},
|
||||
"calendarEventsKey": "calendar"
|
||||
}
|
||||
14
configs/configs.examples/current-user-rules.jsonc
Normal file
14
configs/configs.examples/current-user-rules.jsonc
Normal file
|
|
@ -0,0 +1,14 @@
|
|||
{
|
||||
"New": "dev",
|
||||
"In Progress": "dev",
|
||||
"Re-opened": "dev",
|
||||
"Code Review": "cr",
|
||||
"Resolved": "qa",
|
||||
"Testing": "qa",
|
||||
"Wait Release": "dev",
|
||||
"Pending": "dev",
|
||||
"Feedback": "qa",
|
||||
"Closed": "dev",
|
||||
"Rejected": "dev",
|
||||
"*": "dev"
|
||||
}
|
||||
24
configs/configs.examples/eccm-config.jsonc
Normal file
24
configs/configs.examples/eccm-config.jsonc
Normal file
|
|
@ -0,0 +1,24 @@
|
|||
// TODO:
|
||||
{
|
||||
"currentVersions": ["1", "0.1"],
|
||||
"projectName": "Test project name 1",
|
||||
"currentIssuesStatuses": ["In Progress", "Re-opened", "Code Review", "Resolved", "Testing", "Feedback"],
|
||||
"groups": [
|
||||
{
|
||||
"name": "Dev backend",
|
||||
"people": [
|
||||
"User Developer"
|
||||
]
|
||||
},
|
||||
{
|
||||
"name": "QA",
|
||||
"people": [
|
||||
"Redmine Admin"
|
||||
]
|
||||
}
|
||||
],
|
||||
"dailyTime": {
|
||||
"hour": 10,
|
||||
"minute": 30
|
||||
}
|
||||
}
|
||||
50
configs/configs.examples/issue-event-emitter-config.jsonc
Normal file
50
configs/configs.examples/issue-event-emitter-config.jsonc
Normal file
|
|
@ -0,0 +1,50 @@
|
|||
{
|
||||
|
||||
// "mailListener": {
|
||||
// "issueNumberParser": "\\b(?<=#)\\d+\\b",
|
||||
// "imapSimpleConfig": {
|
||||
// "imap": {
|
||||
// "user": "",
|
||||
// "password": "",
|
||||
// "host": "",
|
||||
// "port": 143,
|
||||
// // tls: true,
|
||||
// "autotls": "always",
|
||||
// "authTimeout": 5000
|
||||
// }
|
||||
// },
|
||||
// "updateInterval": 180000, // 3 min
|
||||
// "boxName": "INBOX"
|
||||
// },
|
||||
|
||||
"rssListener": {
|
||||
"subscriptions": [
|
||||
{
|
||||
"url": "https://REDMINE_HOST/projects/proj/activity.atom?key=....", // TODO
|
||||
"issueNumberParser": "\\b(?<=#)\\d+\\b"
|
||||
},
|
||||
{
|
||||
"url": "https://REDMINE_HOST/activity.atom?key=....", // TODO
|
||||
"issueNumberParser": "\\b(?<=#)\\d+\\b"
|
||||
}
|
||||
],
|
||||
"updateInterval": 10000 // 10 sec
|
||||
},
|
||||
|
||||
"issueChangesQueue": {
|
||||
"updateInterval": 5000, // 5 sec
|
||||
"itemsLimit": 3
|
||||
},
|
||||
"redmineUrlPrefix": "https://REDMINE_API_TOKEN@REDMINE_HOST", // TODO
|
||||
"redmineUrlPublic": "https://REDMINE_HOST", // TODO
|
||||
"webhooks": [],
|
||||
|
||||
"couchDb": {
|
||||
"url": "http://admin:password@localhost:5984", // <- TODO: Указать host, port, username и password для доступа к couchdb
|
||||
"dbs": {
|
||||
"users": "redmine_users",
|
||||
"issues": "redmine_issues",
|
||||
"dashboards": "dashboards"
|
||||
}
|
||||
}
|
||||
}
|
||||
18
configs/configs.examples/main-config.jsonc
Normal file
18
configs/configs.examples/main-config.jsonc
Normal file
|
|
@ -0,0 +1,18 @@
|
|||
{
|
||||
"couchDb": {
|
||||
"dbs": {
|
||||
"changes": "redmine_changes",
|
||||
"userMetaInfo": "user_meta_info",
|
||||
"eccmDailyReports": "eccm_daily_reports",
|
||||
"eccmDailyReportsUserComments": "eccm_daily_reports_user_comments"
|
||||
}
|
||||
},
|
||||
"telegramBotToken": "....", // <- TODO: Указать token от бота telegram
|
||||
"personalMessageTemplate": "{{{issue_url}}} {{{sender_name}}}:\n\n{{{message}}}",
|
||||
"periodValidityNotification": 43200000, // 12h
|
||||
"tagManager": {
|
||||
"updateInterval": 15000,
|
||||
"updateItemsLimit": 3,
|
||||
"tagsCustomFieldName": "Tags"
|
||||
}
|
||||
}
|
||||
225
configs/configs.examples/redmine-status-changes-config.jsonc
Normal file
225
configs/configs.examples/redmine-status-changes-config.jsonc
Normal file
|
|
@ -0,0 +1,225 @@
|
|||
// TODO: Указать правила для формирования сообщений с уведомлениями об изменениях статусов
|
||||
[
|
||||
{
|
||||
"default": false,
|
||||
"from": "New",
|
||||
"to": "In Progress",
|
||||
"messages": [
|
||||
{
|
||||
"recipient": "dev",
|
||||
"changes_message": "{{dev.name}} взял в работу задачу #{{issue_id}}"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"default": false,
|
||||
"from": "In Progress",
|
||||
"to": "Code Review",
|
||||
"messages": [
|
||||
{
|
||||
"recipient": "dev",
|
||||
"changes_message": "{{dev.name}} завершил разработку по задаче #{{issue_id}} и передал на ревью {{cr.name}}"
|
||||
},
|
||||
{
|
||||
"recipient": "cr",
|
||||
"changes_message": "{{cr.name}} получил задачу #{{issue_id}} на ревью от {{dev.name}}",
|
||||
"notification_message": "<a href=\"{{ issue_url }}\">{{ issue_tracker }} #{{ issue_id }}</a> {{issue_subject}}:\n{{dev.name}} завершил разработку по задаче и передал вам на ревью\n\n{{journal_note}}"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"default": false,
|
||||
"from": "Code Review",
|
||||
"to": "Re-opened",
|
||||
"messages": [
|
||||
{
|
||||
"recipient": "cr",
|
||||
"changes_message": "{{cr.name}} вернул задачу #{{issue_id}} на доработку {{dev.name}}"
|
||||
},
|
||||
{
|
||||
"recipient": "dev",
|
||||
"changes_message": "{{dev.name}} получил задачу #{{issue_id}} на доработку после завершения ревью {{cr.name}}",
|
||||
"notification_message": "<a href=\"{{ issue_url }}\">{{ issue_tracker }} #{{ issue_id }}</a> {{ issue_subject }}:\n{{cr.name}} вернул вам с ревью на доработку задачу\n\n{{journal_note}}"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"default": false,
|
||||
"from": "Re-opened",
|
||||
"to": "In Progress",
|
||||
"messages": [
|
||||
{
|
||||
"recipient": "dev",
|
||||
"changes_message": "{{dev.name}} продолжил работу над задачей #{{issue_id}}"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"default": false,
|
||||
"from": "Code Review",
|
||||
"to": "Resolved",
|
||||
"messages": [
|
||||
{
|
||||
"recipient": "cr",
|
||||
"changes_message": "{{cr.name}} завершил ревью задачи {{issue_id}} и передал её на тест {{qa.name}}"
|
||||
},
|
||||
{
|
||||
"recipient": "qa",
|
||||
"changes_message": "{{qa.name}} получил на тест задачу #{{issue_id}} после разработки {{dev.name}} и ревью {{cr.name}}",
|
||||
"notification_message": "<a href=\"{{ issue_url }}\">{{ issue_tracker }} #{{ issue_id }}</a> {{ issue_subject }}:\n{{dev.name}} завершил разработку по задаче, а {{cr.name}} выполнил ревью и передали теперь вам для проверки\n\n{{journal_note}}"
|
||||
},
|
||||
{
|
||||
"recipient": "dev",
|
||||
"notification_message": "<a href=\"{{ issue_url }}\">{{ issue_tracker }} #{{ issue_id }}</a> {{ issue_subject }}:\n{{cr.name}} выполнил ревью вашей задачи и передал далее на проверку {{qa.name}}\n\n{{journal_note}}"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"default": false,
|
||||
"from": "Re-opened",
|
||||
"to": "Code Review",
|
||||
"messages": [
|
||||
{
|
||||
"recipient": "dev",
|
||||
"changes_message": "{{dev.name}} выполнил доработки и перевёл задачу #{{issue_id}} на ревью {{cr.name}}"
|
||||
},
|
||||
{
|
||||
"recipient": "cr",
|
||||
"changes_message": "{{cr.name}} получил задачу #{{issue_id}} на повторное ревью от {{dev.name}}",
|
||||
"notification_message": "<a href=\"{{ issue_url }}\">{{ issue_tracker }} #{{ issue_id }}</a> {{ issue_subject }}:\n{{dev.name}} выполнил по задаче доработки и теперь вы можете сделать ревью\n\n{{journal_note}}"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"default": false,
|
||||
"from": "Resolved",
|
||||
"to": "Closed",
|
||||
"messages": [
|
||||
{
|
||||
"recipient": "qa",
|
||||
"changes_message": "{{qa.name}} протестировал задачу #{{issue_id}} и закрыл"
|
||||
},
|
||||
{
|
||||
"recipient": "dev",
|
||||
"notification_message": "<a href=\"{{ issue_url }}\">{{ issue_tracker }} #{{ issue_id }}</a> {{ issue_subject }}:\n{{qa.name}} проверил и закрыл вашу задачу"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"default": false,
|
||||
"from": "Testing",
|
||||
"to": "Re-opened",
|
||||
"messages": [
|
||||
{
|
||||
"recipient": "qa",
|
||||
"changes_message": "{{qa.name}} вернул задачу #{{issue_id}} на доработку {{dev.name}}"
|
||||
},
|
||||
{
|
||||
"recipient": "dev",
|
||||
"changes_message": "{{dev.name}} получил от {{qa.name}} задачу #{{issue_id}} на доработку",
|
||||
"notification_message": "<a href=\"{{ issue_url }}\">{{ issue_tracker }} #{{ issue_id }}</a> {{ issue_subject }}:\n{{qa.name}} вернул вам с тестирования задачу на доработку\n\n{{journal_note}}"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"default": false,
|
||||
"from": "Resolved",
|
||||
"to": "Re-opened",
|
||||
"messages": [
|
||||
{
|
||||
"recipient": "qa",
|
||||
"changes_message": "{{qa.name}} вернул задачу #{{issue_id}} на доработку {{dev.name}}"
|
||||
},
|
||||
{
|
||||
"recipient": "dev",
|
||||
"changes_message": "{{dev.name}} получил от {{qa.name}} задачу #{{issue_id}} на доработку",
|
||||
"notification_message": "<a href=\"{{ issue_url }}\">{{ issue_tracker }} #{{ issue_id }}</a> {{ issue_subject }}:\n{{qa.name}} вернул вам с тестирования задачу на доработку\n\n{{journal_note}}"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"default": false,
|
||||
"from": "Resolved",
|
||||
"to": "Testing",
|
||||
"messages": [
|
||||
{
|
||||
"recipient": "qa",
|
||||
"changes_message": "{{qa.name}} начал проверять задачу #{{issue_id}}"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"default": false,
|
||||
"from": "Testing",
|
||||
"to": "Closed",
|
||||
"messages": [
|
||||
{
|
||||
"recipient": "qa",
|
||||
"changes_message": "{{qa.name}} протестировал задачу #{{issue_id}} и закрыл"
|
||||
},
|
||||
{
|
||||
"recipient": "dev",
|
||||
"notification_message": "<a href=\"{{ issue_url }}\">{{ issue_tracker }} #{{ issue_id }}</a> {{ issue_subject }}:\n{{qa.name}} проверил и закрыл вашу задачу"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"default": false,
|
||||
"to": "Rejected",
|
||||
"messages": [
|
||||
{
|
||||
"recipient": "initiator",
|
||||
"changes_message": "{{initiator.name}} изменил статус задачи {{issue_id}} с {{old_status.name}} на {{new_status.name}} (dev - {{dev.name}}, cr - {{cr.name}}, qa - {{qa.name}})"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"default": true,
|
||||
"messages": [
|
||||
{
|
||||
"recipient": "initiator",
|
||||
"changes_message": "{{initiator.name}} изменил статус задачи #{{issue_id}} с {{old_status.name}} на {{new_status.name}} (dev - {{dev.name}}, cr - {{cr.name}}, qa - {{qa.name}})"
|
||||
},
|
||||
{
|
||||
"recipient": "dev",
|
||||
"notification_message": "<a href=\"{{ issue_url }}\">{{ issue_tracker }} #{{ issue_id }}</a> {{ issue_subject }}:\n{{initiator.name}} изменил статус задачи с {{old_status.name}} на {{new_status.name}}"
|
||||
},
|
||||
{
|
||||
"recipient": "current_user",
|
||||
"notification_message": "<a href=\"{{ issue_url }}\">{{ issue_tracker }} #{{ issue_id }}</a> {{ issue_subject }}:\n{{initiator.name}} изменил статус задачи с {{old_status.name}} на {{new_status.name}}"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"default": false,
|
||||
"new_issue": true,
|
||||
"from": "New",
|
||||
"to": "New",
|
||||
"messages": [
|
||||
{
|
||||
"recipient": "author",
|
||||
"changes_message": "{{author.name}} создал новую задачу #{{issue_id}} {{#if current_user}}для {{current_user.name}}{{/if}}"
|
||||
},
|
||||
{
|
||||
"recipient": "current_user",
|
||||
"notification_message": "<a href=\"{{ issue_url }}\">{{ issue_tracker }} #{{ issue_id }}</a> {{ issue_subject }}:\n{{author.name}} создал новую задачу и назначил её на вас"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"default": false,
|
||||
"from": "Re-opened",
|
||||
"to": "Resolved",
|
||||
"messages": [
|
||||
{
|
||||
"recipient": "dev",
|
||||
"changes_message": "{{dev.name}} перевёл задачу #{{issue_id}} на повторную проверку {{qa.name}}"
|
||||
},
|
||||
{
|
||||
"recipient": "qa",
|
||||
"changes_message": "{{qa.name}} получил задачу #{{issue_id}} на повторную проверку от {{dev.name}}",
|
||||
"notification_message": "<a href=\"{{ issue_url }}\">{{ issue_tracker }} #{{ issue_id }}</a> {{ issue_subject }}:\n{{dev.name}} выполнил по задаче доработки и теперь вы можете проверить повторно\n\n{{journal_note}}"
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
60
configs/configs.examples/redmine-statuses-config.jsonc
Normal file
60
configs/configs.examples/redmine-statuses-config.jsonc
Normal file
|
|
@ -0,0 +1,60 @@
|
|||
// TODO: Указать какие статусы могут быть в вашем Redmine
|
||||
[
|
||||
{
|
||||
"id": 1,
|
||||
"name": "New"
|
||||
},
|
||||
{
|
||||
"id": 4,
|
||||
"name": "In Progress"
|
||||
},
|
||||
{
|
||||
"id": 5,
|
||||
"name": "Re-opened"
|
||||
},
|
||||
{
|
||||
"id": 6,
|
||||
"name": "Code Review"
|
||||
},
|
||||
{
|
||||
"id": 7,
|
||||
"name": "Resolved"
|
||||
},
|
||||
{
|
||||
"id": 8,
|
||||
"name": "Testing"
|
||||
},
|
||||
{
|
||||
"id": 9,
|
||||
"name": "Wait Release"
|
||||
},
|
||||
{
|
||||
"id": 10,
|
||||
"name": "Pending"
|
||||
},
|
||||
{
|
||||
"id": 11,
|
||||
"name": "Feedback"
|
||||
}
|
||||
|
||||
// {
|
||||
// "id": 5,
|
||||
// "name": "Closed",
|
||||
// "is_closed": true
|
||||
// },
|
||||
// {
|
||||
// "id": 6,
|
||||
// "name": "Rejected",
|
||||
// "is_closed": true
|
||||
// },
|
||||
// {
|
||||
// "id": 7,
|
||||
// "name": "Confirming"
|
||||
// },
|
||||
// {
|
||||
// "id": 12,
|
||||
// "name": "Frozen",
|
||||
// "is_closed": true
|
||||
// },
|
||||
// ...
|
||||
]
|
||||
|
|
@ -0,0 +1,4 @@
|
|||
// deprecated
|
||||
{
|
||||
"path": "/path/to/eltex-redmine-issue-event-emitter/configs/kanban-boards"
|
||||
}
|
||||
107
docs/Установка.md
Normal file
107
docs/Установка.md
Normal file
|
|
@ -0,0 +1,107 @@
|
|||
# Установка
|
||||
|
||||
Инструкция для установки приложения
|
||||
|
||||
## Требования к системе
|
||||
|
||||
Требования к окружению для сборки и запуска приложения:
|
||||
|
||||
- CouchDB в качестве хранилища данных
|
||||
- NodeJS для сборки и запуска backend-а и frontend-а
|
||||
|
||||
Доступы к внешним системам:
|
||||
|
||||
- Токен для подключения telegram-бота
|
||||
- Токен для доступа к API Redmine
|
||||
|
||||
## Подготовка и запуск couchdb
|
||||
|
||||
CouchDB необходим для хранения данных.
|
||||
|
||||
Для запуска можно воспользоваться любым удобным сопособом.
|
||||
|
||||
Пример с помощью docker-compose
|
||||
|
||||
1. `docker-compose.yml`:
|
||||
|
||||
```yaml
|
||||
version: '3.1'
|
||||
|
||||
services:
|
||||
couchdb:
|
||||
image: apache/couchdb:latest
|
||||
restart: always
|
||||
ports:
|
||||
- 127.0.0.1:5984:5984
|
||||
volumes:
|
||||
- ./couchdb-data:/opt/couchdb/data
|
||||
environment:
|
||||
- COUCHDB_USER
|
||||
- COUCHDB_PASSWORD
|
||||
```
|
||||
|
||||
2. Так же нужно указать имя и пароль с помощью файла `.env`:
|
||||
|
||||
```
|
||||
COUCHDB_USER=admin
|
||||
COUCHDB_PASSWORD=password
|
||||
```
|
||||
|
||||
3. Создать папку `couchdb-data` для вольюма определённого для контейнера в `docker-compose.yml`:
|
||||
|
||||
```shell
|
||||
mkdir couchdb-data
|
||||
```
|
||||
|
||||
4. Для запуска воспользоваться командой:
|
||||
|
||||
```shell
|
||||
docker-compose up -d
|
||||
```
|
||||
|
||||
## Установка зависимостей для backend-а и frontend-а
|
||||
|
||||
Backend и frontend написаны на языке typescript. Для загрузки и запуска необходимо выполнить:
|
||||
|
||||
```shell
|
||||
cd $PROJECT_DIR && npm install
|
||||
cd $PROJECT_DIR/frontend && npm install
|
||||
```
|
||||
|
||||
## Настройка
|
||||
|
||||
Нужно скопировать все конфигурационные файлы `CONFIG_NAME.jsonc.dist` в `CONFIG_NAME.jsonc`:
|
||||
|
||||
```shell
|
||||
cd $PROJECT_DIR/configs/
|
||||
|
||||
cp calendar-enhancer.jsonc.dist calendar-enhancer.jsonc
|
||||
cp current-user-rules.jsonc.dist current-user-rules.jsonc
|
||||
cp eccm-config.jsonc.dist eccm-config.jsonc
|
||||
cp issue-event-emitter-config.jsonc.dist issue-event-emitter-config.jsonc
|
||||
cp main-config.jsonc.dist main-config.jsonc
|
||||
cp redmine-status-changes-config.jsonc.dist redmine-status-changes-config.jsonc
|
||||
cp redmine-statuses-config.jsonc.dist redmine-statuses-config.jsonc
|
||||
cp simple-kanban-board-config.jsonc.dist simple-kanban-board-config.jsonc
|
||||
```
|
||||
|
||||
Или можно взять за основу файлы из папки `$PROJECT_DIR/configs/configs.example/` или в качестве примеров для заполнения. В этих файлах можно обратить внимание на строчки с TODO и рекоментациями что нужно указать в конфигурационном файле. Там могут встречаться такие рекомендации как:
|
||||
|
||||
* Указать host, port, username и password для доступа к couchdb
|
||||
* Указать token от бота telegram
|
||||
|
||||
## Запуск приложения
|
||||
|
||||
1. Нужно сделать сборку frontend-а:
|
||||
|
||||
```shell
|
||||
cd $PROJECT_DIR/frontend/ && npm run build
|
||||
```
|
||||
|
||||
2. Сделать сборку или можно просто запустить backend:
|
||||
|
||||
```shell
|
||||
cd $PROJECT_DIR/ && npm run start
|
||||
```
|
||||
|
||||
Если нужно запустить приложение с явным указанием порта, то можно воспользоваться переменной окружения `PORT`.
|
||||
Loading…
Reference in a new issue