﻿# Утилита elma365pm для CI/CD в решениях

> [HTML Version](lowcode-devops-pm.html)

Пользовательские решения можно разрабатывать короткими итерациями, чтобы поддерживать их целостность и версионность. Такой подход реализуется при помощи цикла **Разработка > Тестирование > Эксплуатация** (Develop > Test > Production). В нём решение проходит три этапа, каждый из которых выполняется в отдельной компании: dev-компания используется для разработки, test-компания — для тестирования, prod-компания — для эксплуатации готового решения.

Этот цикл осуществляется с помощью принципов **Непрерывная интеграция** (Continuous integration) и **Непрерывная сборка и выкладка** (Continuous delivery and deploy) или CI/CD. 

В ELMA365 для реализации подхода CI/CD предусмотрено несколько инструментов, которые можно использовать независимо друг от друга:

- инструмент **Непрерывная выкладка (Low-code CI / CD)** — обмен компонентами между** **компаниями из разных окружений выполняется на основе стандартных процессов экспорта и импорта. Все настройки осуществляются в интерфейсе ELMA365. Две компании связываются между собой. Затем создаётся профиль обмена: выбираются компоненты конфигурации, указывается тип операции и т. д. Профиль сохраняется, что позволяет выполнять операцию обмена несколько раз. Присутствует возможность сравнить конфигурации двух компаний и проанализировать результат выполнения операции. Процесс обмена выполняется в фоновом режиме. Подробнее о работе с инструментом читайте в статье [«Непрерывная интеграция и выкладка (Low-code CI/CD)»](low-code-ci-cd.md);

- утилита **elma365pm** — вспомогательная независимая утилита командной строки применяется совместно со сторонними сервисами контроля версий и настройки пайплайнов, например, GitLab. Утилита позволяет экспортировать в файл компонент конфигурации компании: раздел, модуль или решение. Затем работа осуществляется в стороннем сервисе, что позволяет использовать операции из High-code разработки. Компонент обновляется до новой версии, упаковывается в файл и импортируется в другую компанию. 

В этой статье описывается основной принцип работы с утилитой **elma365pm** и используемые при этом команды.

Пример организации цикла разработки и выкладки с использованием системы контроля версий GitLab и нескольких окружений dev-test-prod приведён в [ELMA365 Community](https://community.elma365.com/ru/threads/1784/).

## Загрузка утилиты

Нажмите на ссылку, чтобы загрузить утилиту **elma365pm** для различных операционных систем, совместимую с поставками ELMA365 SaaS и последней версией ELMA365 On-Premises:

- [Linux](https://dl.elma365.com/elma365pm/latest/elma365pm.linux.amd64.zip);

- [Windows](https://dl.elma365.com/elma365pm/latest/elma365pm.windows.amd64.zip);

- [macOS (архитектура Intel x64)](https://dl.elma365.com/elma365pm/latest/elma365pm.darwin.amd64.zip);

- [macOS (архитектура ARM x64, процессор M1)](https://dl.elma365.com/elma365pm/latest/elma365pm.darwin.arm64.zip).

После загрузки распакуйте **.exe**-файл.

## Доступные команды утилиты

Работа с утилитой **elma365pm** осуществляется с помощью выполнения команд в командной строке. Команды могут использоваться с доступными флагами. Они прописываются после наименования команды. 

После загрузки утилиты вы можете запросить справочную информацию, выполнив команду:

````
elma365pm --help

````
Подробная инструкция для каждой команды вызывается следующим образом:

````
elma365pm <command> --help

````
Ниже приведены доступные команды и флаги.

### Распаковать пакет экспорта в файловую систему

| | |
|------|------|
| **Команда** | `elma365pm unpack`  |
| **Пример команды** | `elma365pm unpack --src=String --out=String` |
| **Доступные флаги** | 
| `\--src=String` | Вместо `String` укажите путь до компонента. |
| `\--out=String` | Вместо `String` укажите папку файловой системы, куда распаковывать пакет. |
| `\--experimental-restruct` | Используйте флаг с осторожностью.<br>По умолчанию структура каталогов и файлов после распаковки пакета экспорта соответствует внутренней структуре такого пакета.   <br>Примените флаг, чтобы реструктурировать пакет для повышения наглядности. <br>Тогда при распаковке сформируется иерархическая структура решения. Например, файл с описанием приложения будет находиться в каталоге раздела, каталог раздела — в каталоге решения, описания переносимых сервисов или методов API в каталоге модуля и т. д. |


### Упаковать папку в пакет .e365



| | |
|------|------|
| **Команда** | `elma365pm pack`  |
| **Пример команды** | `elma365pm pack --src=String --out=String` |
| **Доступные флаги** | 
| `\--src=String` | Вместо `String` укажите папку файловой системы, где хранится распакованный пакет. |
| `\--out=String` | Вместо `String` укажите файл, куда запаковывается пакет. |
| `\--version-up` | Обновление версии пакета. |


### Экспортировать компонент из ELMA365

Вы можете экспортировать раздел, решение, модуль или конфигурацию. Для каждого из этих действий используется своя команда.

| | |
|------|------|
| **Пример команды для экспорта раздела** | 
| `elma365pm export namespace --token=STRING --host=STRING --out=STRING`<br>или<br>`elma365pm export ns --token=STRING --host=STRING --out=STRING`<br> | 
| **Пример команды для экспорта решения** | 
| `elma365pm export solution --token=STRING --host=STRING --out=STRING`<br>или<br>`elma365pm export sln --token=STRING --host=STRING --out=STRING`<br> | 
| **Пример команды для экспорта модуля** | 
| `elma365pm export module --token=STRING --host=STRING --out=STRING`<br>или<br>`elma365pm export mod --token=STRING --host=STRING --out=STRING`<br> | 
| **Пример команды для экспорта конфигурации** | 
| `elma365pm export configuration --token=STRING --host=STRING --out=STRING`<br>или<br>`elma365pm export cfg --token=STRING --host=STRING --out=STRING`<br> | 
| **Доступные флаги для команд экспорта** | 
| `\--token=String` | Вместо `String` укажите [токен авторизации](360016488452.md), созданный в ELMA365 в разделе **Администрирование**. |
| `\--host=String` | Вместо `String` укажите адрес хоста ELMA365. |
| `\--out=String` | Вместо `String` укажите директорию файловой системы, куда экспортируется пакет. |
| `\--code=String` | Вместо `String` укажите код идентификатора экспортируемого компонента. |
| `\--dts` | Флаг управляет генерацией файлов **d.ts**, которые активируют подсказки IDE по типам языка TypeScript в скриптах. По умолчанию генерация этих файлов отключена.<br>**Важно:** для пакетов с множеством компонентов генерация может занять продолжительное время. |
| `\--experimental-restruct` | Реструктурировать пакет для отображения логической иерархии файлов. Используйте с осторожностью. |
| `\--allow-deps=true/false` | Применяется при экспорте решений. Позволяет выгрузить решение с добавленными связями с компонентами другого решения. Подробнее читайте в разделе [«Особенности использования утилиты»](#export-use). |


### Импортировать объекты в ELMA365



| | |
|------|------|
| **Команда** | `elma365pm import`  |
| **Пример команды** | `elma365pm import --token=STRING --host=STRING --src=STRING` |
| **Доступные флаги** | 
| `\--token=String` | Вместо `String` укажите [токен авторизации](360016488452.md), созданный в ELMA365 в разделе **Администрирование**. |
| `\--host=String` | Вместо `String` укажите адрес хоста ELMA365. |
| `\--src=String` | Вместо `String` укажите директорию файловой системы для упаковки и импорта. |
| `\--version-up` | Обновление версии пакета. |
| `\--replace-org-struct` | Замена организационной структуры. Используется только при импорте конфигурации компании. |
| `\--force` | Принудительный импорт при наличии конфликтов. Используйте с осторожностью, конфликт может означать, что данные на целевом хосте повреждены. |
| `\--fail-on-conflict` | Вывод в коде выхода ненулевого кода ошибки, если при принудительном импорте пакета возникли конфликты. Используется только с флагом \[OBJECT\]. |
| `\--exclude-upgrade-permissions` | Сохранение настроенных прав доступа для раздела, решения и конфигурации. При импорте этих компонентов права доступа остаются прежними и не обновляются. |


### Проверить пакет на пригодность к импорту

| | |
|------|------|
| **Команда** | `elma365pm check`  |
| **Пример команды** | `elma365pm check --token=STRING --host=STRING --src=STRING` |
| **Доступные флаги** | 
| `\--token=String` | Вместо `String` укажите [токен авторизации](360016488452.md), созданный в ELMA365 в разделе **Администрирование**. |
| `\--host=String` | Вместо `String` укажите адрес хоста ELMA365. |
| `\--src=String` | Вместо `String` укажите директорию файловой системы для упаковки и импорта. |
| `\--version-up` | Обновление версии пакета. |


### Посмотреть версию утилиты

| | |
|------|------|
| **Команда** | `elma365pm version` |
| **Доступные флаги** | 
| `\--json ` | Вывод информации в JSON. |


### Флаги, доступные для всех команд

| | |
|------|------|
| `\--help` | Справочная информация о команде. |
| `\--debug` | Вывод подробных логов выполнения операции. |
| `\--timeout` | Ожидание выполнения операции. По умолчанию задано значение 5 минут. Изменяется в случае обработки объёмного пакета. Пример: `elma365pm export solution --timeout=10m`. |




## Особенности использования утилиты

Обратите внимание на особенности работы с утилитой **elma365pm**:

1. С помощью утилиты нельзя экспортировать или импортировать [платные системные решения](solution.md).

2. Чтобы экспортировать решение с настроенными [связями с компонентами другого решения](export-solution-file.md#add-dependencies), в команде экспорта применяется параметр \[OBJECT\] со значением \[OBJECT\]: 

````
elma365pm export solution --token=TOKEN --host=https://dev-elma365.myorg  
\--out=my\_solution --code=my\_solution\_code --allow-deps=true 

````
Если не использовать параметр \[OBJECT\] или установить для него значение \[OBJECT\], решение со связанными компонентами не экспортируется.

## Пример использования утилиты

Для примера в качестве инфраструктуры хранения исходного кода и непрерывной сборки используется сервис GitLab. Это наиболее популярный продукт с возможностью разворачивания своего сервера в закрытом контуре.

Рассмотрим основные этапы непрерывной сборки и выкладки на примере решения **Служебные записки** (\[OBJECT\]). 

1. Разработчик решения выполняет работу в компании с dev-окружением.

2. После окончания разработки необходимо выгрузить решение в папку репозитория в файловой системе. Для этого используется команда:

````
elma365pm export solution --token=TOKEN --host=https://dev15-elma365.myorg  
\--out=Internal\_Documents --code=Internal\_Documents

````
Токен для экспорта и импорта создаётся [администратором системы](360006871932.md#administrators) в разделе **Администрирование > Токены**.

После выполнения этой команды в папке **/Internal\_Documents** будут содержаться файлы решения **Служебные записки**. 

3. Затем разработчик использует инструменты работы с репозиторием git, согласно внутреннему регламенту.

В нашем примере он фиксирует свои изменения (commit) в отдельную рабочую ветку (branch) и отправляет их в общий репозиторий (push) на сервис GitLab. Далее на сервере в рабочем репозитории создаётся запрос на слияние своей ветки в общую ветку develop.

4. После проверки и согласования ветки разработчика осуществляется слияния. 

5. В процессе автоматической сборки решения на ветке develop выполняется:

- упаковка артефакта решения в файл **.e365** для тестирования:

````
elma365pm pack --src=procurement --out=dist/procurement.e365

- ````
загрузка решения в компанию с test-окружением:

````
elma365pm import --token=TEST-TOKEN --host=https://test-elma365.myorg  
\--src=Internal\_Documents --version-up --force

````
Чтобы проигнорировать ошибки импорта и выполнить принудительную загрузку в примере используется флаг \[OBJECT\].

6. После тестирования решения загружается для эксплуатации в компанию с prod-окружением: 

````
elma365pm import --token=PRODUCTION-TOKEN --host=https://elma365.myorg  
\--src=Internal\_Documents --version-up

````
Подробнее о применении утилиты **elma365pm **и работе с ней** **на примере читайте на [официальном сайте ELMA365](https://elma365.com/ru/news/tool-for-creating-lowcode-devops-practices/).

## Файловая структура решения

При распаковке решения в файлы командой \[OBJECT\] вы увидите в целевой папке структуру решения. Для примера используется готовое бизнес-решение [Служебные записки](memos.md).

Файловая структура

````
PS InternalDocuments> tree /F  
   
│   package.json  
│  
├───appViews  
│   │   manifest.json  
│   │  
│   ├───entities  
│   │   └───InternalDocuments  
│   │           document\_type.json  
│   │           serviceNote.json  
│   │  
│   └───resources  
│       └───entities  
│           └───InternalDocuments  
│                   document\_type.json.po  
│                   serviceNote.json.po  
│  
├───groups  
│   │   manifest.json  
│   │  
│   └───entities  
│       └───InternalDocuments  
│               27b37284-0ab0-4d9e-8b39-893938770deb.json  
│  
├───pages  
│   │   manifest.json  
│   │  
│   ├───entities  
│   │   ├───global  
│   │   │       InternalDocuments.json  
│   │   │  
│   │   └───InternalDocuments  
│   │           document\_type.json  
│   │           link\_9556a21b-ef8b-4dd6-ad43-2a6d81dd5fda.json  
│   │           sep\_adab5a75-98bf-46f2-af6e-4a67866260a6.json  
│   │           sep\_ffe43b88-2ee2-42b0-939a-d4f88a435c98.json  
│   │           serviceNote.json  
│   │  
│   └───resources  
│       ├───global  
│       │       InternalDocuments.widgets.json  
│       │  
│       └───InternalDocuments  
│               document\_type.widgets.json  
│               link\_9556a21b-ef8b-4dd6-ad43-2a6d81dd5fda.widgets.json  
│               sep\_adab5a75-98bf-46f2-af6e-4a67866260a6.widgets.json  
│               sep\_ffe43b88-2ee2-42b0-939a-d4f88a435c98.widgets.json  
│               serviceNote.widgets.json  
│  
├───permissionsSettings  
│   │   manifest.json  
│   │  
│   └───entities  
│       ├───global  
│       │       InternalDocuments.pagePermissions.json  
│       │  
│       └───InternalDocuments  
│           │   document\_type.pagePermissions.json  
│           │   document\_type.permissionSettings.json  
│           │   document\_type@\_\_directory.permissionSettings.json  
│           │   link\_9556a21b-ef8b-4dd6-ad43-2a6d81dd5fda.pagePermissions.json  
│           │   sep\_adab5a75-98bf-46f2-af6e-4a67866260a6.pagePermissions.json  
│           │   sep\_ffe43b88-2ee2-42b0-939a-d4f88a435c98.pagePermissions.json  
│           │   serviceNote.pagePermissions.json  
│           │   serviceNote.permissionSettings.json  
│           │   serviceNote@\_\_directory.permissionSettings.json  
│           │  
│           └───serviceNote  
│                   \_process\_serviceNoteProcessing.permissionSettings.json  
│  
├───processor  
│   │   manifest.json  
│   │  
│   ├───entities  
│   │   └───InternalDocuments.serviceNote  
│   │           serviceNoteProcessing.json  
│   │           serviceNoteProcessing.ts  
│   │  
│   └───resources  
│       └───InternalDocuments.serviceNote  
│               serviceNoteProcessing.po  
│               serviceNoteProcessing.runtime  
│  
├───templates  
│   │   manifest.json  
│   │  
│   ├───entities  
│   │   └───InternalDocuments.serviceNote  
│   │           accb6290-4c06-44c3-8ce1-fe0721fab4e2  
│   │  
│   └───resources  
│       └───InternalDocuments.serviceNote  
│           └───accb6290-4c06-44c3-8ce1-fe0721fab4e2  
│                   Служебная записка.docx  
│  
└───widgets  
    │   manifest.json  
    │  
    ├───entities  
    │   ├───InternalDocuments.document\_type  
    │   │       \_create  
    │   │       \_create.client.ts  
    │   │       \_create.server.ts  
    │   │  
    │   └───InternalDocuments.serviceNote  
    │           form\_20d7fc9f-744b-4c5b-9e63-ad6cb52d8f73  
    │           form\_20d7fc9f-744b-4c5b-9e63-ad6cb52d8f73.client.ts  
    │           form\_20d7fc9f-744b-4c5b-9e63-ad6cb52d8f73.server.ts  
    │           form\_bd63ceb5-914e-406a-90e3-d513b9258ed4  
    │           form\_bd63ceb5-914e-406a-90e3-d513b9258ed4.client.ts  
    │           form\_bd63ceb5-914e-406a-90e3-d513b9258ed4.server.ts  
    │           form\_c4663ece-c7bb-4926-8cc0-1272029cb586  
    │           form\_c4663ece-c7bb-4926-8cc0-1272029cb586.client.ts  
    │           form\_c4663ece-c7bb-4926-8cc0-1272029cb586.server.ts  
    │           form\_dd59c19d-84ff-45ef-b393-db8726a154a8  
    │           form\_dd59c19d-84ff-45ef-b393-db8726a154a8.client.ts  
    │           form\_dd59c19d-84ff-45ef-b393-db8726a154a8.server.ts  
    │           form\_f51fd1ff-a3ce-4e1d-b7ca-5fd5e324e08b  
    │           form\_f51fd1ff-a3ce-4e1d-b7ca-5fd5e324e08b.client.ts  
    │           form\_f51fd1ff-a3ce-4e1d-b7ca-5fd5e324e08b.server.ts  
    │           \_create  
    │           \_create.client.ts  
    │           \_create.server.ts  
    │           \_view  
    │           \_view.client.ts  
    │           \_view.server.ts  
    │  
    └───resources  
        ├───InternalDocuments.document\_type  
        │       \_create.po  
        │  
        └───InternalDocuments.serviceNote  
                form\_20d7fc9f-744b-4c5b-9e63-ad6cb52d8f73.po  
                form\_bd63ceb5-914e-406a-90e3-d513b9258ed4.po  
                form\_c4663ece-c7bb-4926-8cc0-1272029cb586.po  
                form\_dd59c19d-84ff-45ef-b393-db8726a154a8.po  
                form\_f51fd1ff-a3ce-4e1d-b7ca-5fd5e324e08b.po  
                \_create.po  
                \_view.po
````

````
На верхнем уровне находятся папки сервисов, т. к. архитектура системы микросервисная. В каждой папке сервиса обычно есть файл \[OBJECT\] и две папки \[OBJECT\] и \[OBJECT\]. В корне также лежит файл \[OBJECT\], в котором описаны основные данные выгруженного решения или раздела.

В основном файлы в структуре делятся на три типа:

1. **Файлы описаний конфигурации** — это файлы формата **.json** или файлы без расширения, также являющиеся JSON-файлами. В этих файлах можно найти описание полей и настройки приложения, описание процесса, виджеты и модули.

2. **Файлы скриптов** — это файлы формата **.ts**, в которых хранятся тексты скриптов процессов, виджетов, модулей. 

Файлы скриптов распаковываются для удобного просмотра и совместного ревью кода. Содержимое этих файлов не упаковывается в пакет при импорте. Вы можете редактировать распакованные файлы скриптов, а также использовать файлы-автодополнения для удобства работы в редакторах кода.

3. **Прочие файлы ресурсов или локализации**. Такие файлы обычно находятся в папке \[OBJECT\]. Локализация пакетов решений в будущем будет переработана, поэтому сейчас файлы локализации используются ровно один раз при первом импорте пакета. Вы можете вносить изменения прямо в эти файлы, и они будут упакованы утилитой.