--- title: Публикация icon: upload description: Распространяйте своё приложение Twenty в маркетплейсе или разверните его для внутреннего использования. --- ## Обзор После того как ваше приложение [собрано и протестировано локально](/l/ru/developers/extend/apps/getting-started/concepts), у вас есть два пути для его распространения: * **Разверните tar-архив** — загрузите своё приложение напрямую на конкретный сервер Twenty для внутреннего или частного использования. * **Опубликовать в npm** — разместите ваше приложение в маркетплейсе Twenty, чтобы любое рабочее пространство могло его найти и установить. Оба пути начинаются с одного и того же шага **build**. ## Сборка вашего приложения Выполните команду сборки, чтобы скомпилировать приложение и сгенерировать готовый к распространению `manifest.json`: ```bash filename="Terminal" yarn twenty dev:build ``` Это компилирует исходные файлы TypeScript, транспилирует функции логики и фронтенд-компоненты и записывает всё в `.twenty/output/`. Добавьте `--tarball`, чтобы также создать пакет `.tgz` для ручного распространения или для команды publish. ## Развертывание на сервер (tarball) Для приложений, которые вы не хотите делать общедоступными — собственные инструменты, интеграции только для предприятий или экспериментальные сборки — вы можете развернуть tarball напрямую на сервер Twenty. ### Требования Перед развертыванием вам нужен настроенный remote, указывающий на целевой сервер. Remotes локально хранят URL сервера и учётные данные аутентификации в `~/.twenty/config.json`. Добавьте remote: ```bash filename="Terminal" yarn twenty remote:add --url https://your-twenty-server.com --as production ``` ### Развертывание Соберите и загрузите ваше приложение на сервер в одном шаге: ```bash filename="Terminal" yarn twenty app:publish --private # To deploy to a specific remote: # yarn twenty app:publish --private --remote production ``` ### Общий доступ к развернутому приложению Приложения в формате tarball не отображаются в публичном маркетплейсе, поэтому другие рабочие пространства на том же сервере не найдут их при просмотре. Чтобы поделиться развернутым приложением: 1. Перейдите в **Настройки > Приложения > Регистрации** и откройте ваше приложение 2. На вкладке **Распространение** нажмите **Копировать ссылку для общего доступа** 3. Поделитесь этой ссылкой с пользователями в других рабочих пространствах — она ведёт их прямо на страницу установки приложения Ссылка общего доступа использует базовый URL сервера (без какого-либо поддомена рабочего пространства), поэтому она работает для любого рабочего пространства на сервере. ### Управление версиями При обновлении уже развернутого tarball-приложения сервер требует, чтобы значение `version` в `package.json` было **строго выше** (согласно упорядочиванию по [semver](https://semver.org)), чем текущая развернутая версия. Повторное развёртывание той же версии или публикация более низкой версии отклоняются до сохранения tarball — в CLI вы увидите ошибку `VERSION_ALREADY_EXISTS`. Чтобы выпустить обновление: 1. Увеличьте значение поля `version` в вашем `package.json` (например: `1.2.3` → `1.2.4`, `1.3.0` или `2.0.0`). 2. Выполните `yarn twenty app:publish --private` (или `yarn twenty app:publish --private --remote production`) 3. Рабочие пространства, в которых приложение установлено и для него включено автообновление (на вкладке «Настройки» приложения), обновляются автоматически в фоновом режиме; в остальных рабочих пространствах пользователи увидят доступное обновление в своих настройках Пререлизные теги работают как ожидается: повышение версии `1.0.0-rc.1` → `1.0.0-rc.2` допускается, а финальный релиз вроде `1.0.0` корректно распознаётся как более высокий, чем `1.0.0-rc.5`. Версия в `package.json` должна сама по себе быть корректной строкой semver. {/* TODO: add screenshot of the Upgrade button */} ### Совместимость версий сервера Если ваше приложение использует функцию, появившуюся в конкретной версии сервера Twenty (например, провайдеры OAuth, добавленные в v2.3.0), следует объявить минимальную требуемую версию сервера с помощью поля `engines.twenty` в `package.json`: ```json filename="package.json" { "name": "twenty-my-app", "version": "1.0.0", "engines": { "node": "^24.5.0", "twenty": ">=2.3.0" } } ``` Значение — это стандартный [диапазон semver](https://github.com/npm/node-semver#ranges). Типовые шаблоны: | Диапазон | Значение | | ---------------------------------- | -------------------------------------------------- | | `>=2.3.0` | Любой сервер версии 2.3.0 и новее | | `>=2.3.0 \<3.0.0` | 2.3.0 или новее, но ниже следующей мажорной версии | | `^2.3.0` | То же, что и `>=2.3.0 \<3.0.0` | **Что происходит при развёртывании и установке:** * Если `engines.twenty` задано и версия целевого сервера не удовлетворяет диапазону, развёртывание (загрузка tarball-архива) или установка отклоняются с ошибкой `SERVER_VERSION_INCOMPATIBLE` и сообщением, указывающим как требуемый диапазон, так и фактическую версию сервера. * Если `engines.twenty` **не задано**, приложение принимается на сервере любой версии (обратная совместимость с существующими приложениями). * Если на сервере `APP_VERSION` не задано, проверка пропускается. Сервер выполняет окончательную проверку — он проверяет `engines.twenty` как при загрузке tarball-архива, так и при установке в рабочем пространстве. Если вы развёртываете tarball вне стандартного процесса или устанавливаете из маркетплейса, сервер всё равно принудительно проверяет совместимость. ## Автоматизированный CI/CD (рабочие процессы, сгенерированные шаблоном) Приложения, созданные с помощью `create-twenty-app`, «из коробки» включают три рабочих процесса GitHub Actions в каталоге `.github/workflows/`. CI запускается без какой-либо настройки, для CD требуется один секрет, а публикация в npm требует однократной настройки доверенного издателя npm (trusted-publisher). ### CI — `ci.yml` Автоматически запускает интеграционные тесты при каждом пуше в `main` и для каждого pull request. **Что делает:** 1. Извлекает исходный код вашего приложения. 2. Запускает изолированный тестовый экземпляр Twenty с помощью составного действия `twentyhq/twenty/.github/actions/spawn-twenty-app-dev-test@main` (эквивалент для CI `yarn twenty docker:start --test`). 3. Включает Corepack, настраивает Node.js на основе вашего `.nvmrc` и устанавливает зависимости с помощью `yarn install --immutable`. 4. Запускает `yarn test`, передавая `TWENTY_API_URL` и `TWENTY_API_KEY` из запущенного экземпляра, чтобы ваши тесты могли взаимодействовать с реальным сервером. **Параметры конфигурации:** * `TWENTY_VERSION` (переменная окружения, по умолчанию `latest`) — зафиксируйте версию сервера Twenty, используемую в CI, отредактировав это значение в `ci.yml`. * Параллельные запуски группируются по `github.ref` и отменяют выполняющиеся прогоны при новых пушах. Секреты не требуются — тестовый экземпляр эфемерен и существует только на время выполнения задания. ### CD — `cd.yml` Разворачивает ваше приложение на настроенном сервере Twenty при каждом пуше в `main` и, при необходимости, из pull request при наличии метки `deploy`. **Что делает:** 1. Извлекает head-коммит PR (для PR с меткой) или запушенный коммит. 2. Запускает `twentyhq/twenty/.github/actions/deploy-twenty-app@main` — эквивалент для CI `yarn twenty app:publish --private`. 3. Запускает `twentyhq/twenty/.github/actions/install-twenty-app@main`, чтобы новая развернутая версия была установлена в целевое рабочее пространство. **Обязательная конфигурация:** | Настройка | Где | Назначение | | ----------------------- | --------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------------------------- | | `TWENTY_DEPLOY_URL` | `env` в `cd.yml` (по умолчанию `http://localhost:3000`) | Сервер Twenty, на который выполняется деплой. Перед первым использованием замените это на URL вашего реального сервера. | | `TWENTY_DEPLOY_API_KEY` | В репозитории GitHub — **Settings → Secrets and variables → Actions** | Ключ API с правом деплоя на целевом сервере. | Значение `TWENTY_DEPLOY_URL` по умолчанию — `http://localhost:3000` — это заглушка: с хостируемого GitHub раннера к ней не будет доступа. Перед включением CD замените его на публичный URL вашего сервера (или используйте self-hosted раннер с сетевым доступом). **Запуск предварительного деплоя из PR:** Добавьте к pull request метку `deploy`. Условие `if:` в `cd.yml` запустит задачу для этого PR, используя его head-коммит, что позволит проверить изменение на целевом сервере до слияния. ### Публикация — `publish.yml` Публикует ваше приложение в npm с указанием происхождения (provenance), когда вы отправляете тег версии (например, `v1.0.0`), или когда вы запускаете рабочий процесс вручную на вкладке Actions. **Что делает:** 1. Клонирует ваше приложение, настраивает Node.js и обновляет npm (для доверенной публикации требуется npm версии 11.5.1 или новее). 2. Запускает `yarn twenty app:publish`, который собирает приложение и публикует `.twenty/output` в npm. В CI он автоматически добавляет `--provenance` и `--access public`, поэтому в рабочем процессе флаги не требуются. **Первоначальная настройка:** На npmjs.com откройте свой пакет > **Settings → Trusted Publisher** и зарегистрируйте этот репозиторий, указав рабочий процесс `publish.yml` (см. [документацию по доверенной публикации в npm](https://docs.npmjs.com/trusted-publishers)). Публикация с provenance подтверждает, какой репозиторий GitHub собрал пакет, а также позволяет вам заявить права на ваше приложение в маркетплейсе Twenty. npm принимает подтверждение происхождения только из **публичных** репозиториев с исходным кодом. Если вы публикуете из приватного репозитория, npm отклоняет пакет подтверждения происхождения OIDC с ошибкой `E422 ... Ошибка `Unsupported GitHub Actions source repository visibility: "private"`. Чтобы публиковать из приватного репозитория, отключите подтверждение происхождения, установив `TWENTY_APP_PUBLISH_DISABLE_PROVENANCE: 'true'`в`env`шага публикации (закомментированная подсказка включена в сгенерированный`publish.yml\`): ```yaml filename=".github/workflows/publish.yml" - name: Publish to npm env: TWENTY_APP_PUBLISH_DISABLE_PROVENANCE: 'true' run: yarn twenty app:publish ``` ### Закрепление версий повторно используемых действий Рабочие процессы `ci.yml` и `cd.yml` ссылаются на повторно используемые действия с указанием `@main`, поэтому обновления действий в репозитории `twentyhq/twenty` подхватываются автоматически. Если вам нужны детерминированные сборки, замените `@main` на SHA коммита или тег релиза в каждой строке `uses:`. ## Публикация в npm Публикация в npm делает ваше приложение видимым в маркетплейсе Twenty. Любое рабочее пространство Twenty может просматривать, устанавливать и обновлять приложения из маркетплейса непосредственно из интерфейса. ### Требования * Учётная запись [npm](https://www.npmjs.com) * Ключевое слово `twenty-app` в массиве `keywords` вашего `package.json` (добавьте его вручную — по умолчанию оно не включено в шаблон `create-twenty-app`) ```json filename="package.json" { "name": "twenty-app-postcard-sender", "version": "1.0.0", "keywords": ["twenty-app"] } ``` ### Метаданные маркетплейса Конфигурация `defineApplication()` поддерживает необязательные поля, которые определяют, как ваше приложение отображается в маркетплейсе. Используйте `logo` и `galleryImages`, чтобы ссылаться на изображения из папки `public/`: ```ts src/application-config.ts export default defineApplication({ universalIdentifier: '...', displayName: 'My App', description: 'A great app', logo: 'public/logo.png', galleryImages: [ 'public/screenshot-1.png', 'public/screenshot-2.png', ], }); ``` См. [аккордеон defineApplication](/l/ru/developers/extend/apps/config/application#marketplace-metadata) на странице «Создание приложений» для полного списка полей маркетплейса (`author`, `category`, `aboutDescription`, `websiteUrl`, `termsUrl` и т. д.). #### Рекомендуемые размеры изображений галереи Маркетплейс отображает `galleryImages` в контейнере с фиксированным соотношением сторон `8:5` (например, `1600×1000 px`). Изображения галереи с любым соотношением сторон отображаются полностью и никогда не обрезаются, но всё, что значительно выше или уже, чем `8:5`, будет иметь пустые поля по бокам. #### Ограничение размера изображения Файл `logo` и каждый файл из `galleryImages` не должны превышать **10 MB**. Более крупные файлы пропускаются при повторном размещении ваших опубликованных ресурсов на маркетплейсе, поэтому они не будут отображаться. ### Публикация ```bash filename="Terminal" yarn twenty app:publish ``` Чтобы опубликовать с определённым dist-tag (например, `beta` или `next`): ```bash filename="Terminal" yarn twenty app:publish --tag beta ``` ### Как работает обнаружение приложений в маркетплейсе Сервер Twenty синхронизирует каталог маркетплейса из реестра npm **каждый час**. Вы можете запустить синхронизацию немедленно, вместо ожидания: ```bash filename="Terminal" yarn twenty dev:catalog-sync # To target a specific remote: # yarn twenty dev:catalog-sync --remote production ``` Метаданные, отображаемые в маркетплейсе, берутся из вашей конфигурации `defineApplication()` — см. раздел [Метаданные маркетплейса](#marketplace-metadata) выше. Если ваше приложение не определяет `aboutDescription` в `defineApplication()`, маркетплейс автоматически использует `README.md` вашего пакета из npm в качестве содержимого страницы «О приложении». Это означает, что вы можете поддерживать единый README как для npm, так и для маркетплейса Twenty. Если вы хотите другое описание в маркетплейсе, явно задайте `aboutDescription`. ### Публикация через CI Сгенерированный выше рабочий процесс `publish.yml` автоматически публикует в npm по тегам версий, с provenance. Поскольку `yarn twenty app:publish` при запуске в CI добавляет за вас `--provenance` и `--access public`, в рабочем процессе не нужны флаги npm — требуется только однократная настройка доверенного издателя. Для других систем CI (GitLab CI, CircleCI и т. д.) запустите `yarn install`, затем `yarn twenty app:publish`. Provenance создается, когда среда может выпустить токен OIDC, и в противном случае автоматически пропускается. **npm provenance** добавляет значок доверия к вашему пакету в npm, позволяя пользователям проверить, что пакет был собран из конкретного коммита в общедоступном конвейере CI. Это также то, что позволяет вам заявить права на ваше приложение в маркетплейсе Twenty. Подробности см. в [документации по npm provenance](https://docs.npmjs.com/generating-provenance-statements). ## Установка приложений После публикации приложения (npm) или его развертывания (tarball) рабочие пространства могут установить его через интерфейс. Перейдите на страницу **Настройки > Приложения** в Twenty, где можно просматривать и устанавливать как приложения из маркетплейса, так и развернутые через tarball. {/* TODO: add screenshot of the UI when the app is registered */} Вы также можете устанавливать приложения из командной строки: ```bash filename="Terminal" yarn twenty app:install ``` Сервер при установке применяет версионирование semver, аналогичное правилам при развёртывании: * Установка той же версии, которая уже установлена в вашем рабочем пространстве, отклоняется с ошибкой `APP_ALREADY_INSTALLED`. * Установка версии ниже текущей отклоняется с ошибкой `CANNOT_DOWNGRADE_APPLICATION`. Чтобы установить более новую версию, сначала разверните или опубликуйте её, затем снова выполните `yarn twenty app:install`.