snapshot of https://github.com/twentyhq/twenty.git (main, 2026-09-17; blobs > 131072B omitted)
Some checks failed
App Prod-Parity E2E Dispatch / dispatch (push) Failing after 10s
CD Storybook UI / build (push) Failing after 3m25s
CD Storybook UI / dispatch (push) Has been skipped
CD deploy main / website-changed-files (push) Successful in 18m8s
CI Agent Skills / changed-files-check (push) Successful in 18m9s
CI Create App E2E minimal / changed-files-check (push) Successful in 24s
CI Create App / changed-files-check (push) Successful in 26s
CI Docs / changed-files-check (push) Successful in 26s
CI Emails / changed-files-check (push) Successful in 28s
CI Example App Hello World / changed-files-check (push) Successful in 23s
CI Front / changed-files-check (push) Has been skipped
CI Example App Postcard / changed-files-check (push) Successful in 27s
CI UI / changed-files-check (push) Has been skipped
CI Utils Test / changed-files-check (push) Successful in 45s
CI Twenty Apps / discover (push) Successful in 1m3s
CD deploy main / deploy-main (push) Failing after 3s
CI Agent Skills / agent-skills-validate (push) Has been skipped
CI Create App / create-app-test (lint) (push) Has been skipped
CI Emails / emails-test (push) Has been skipped
CI Front / front-task (lingui:compile) (push) Has been skipped
CI Front / front-task (lint) (push) Has been skipped
CI Example App Postcard / example-app-postcard (push) Has been skipped
CI UI / ui-task (lint) (push) Has been skipped
CI UI / ui-task (pack-size) (push) Has been skipped
CI UI / ui-task (size) (push) Has been skipped
CI UI / ui-task (test) (push) Has been skipped
CI UI / ui-task (typecheck) (push) Has been skipped
CI Utils Test / utils-test (push) Has been skipped
CI Twenty Apps / ${{ matrix.app.name }} (push) Has been skipped
CI Emails / ci-emails-status-check (push) Successful in 2s
CI Example App Hello World / ci-example-app-hello-world-status-check (push) Successful in 2s
CI Example App Postcard / ci-example-app-postcard-status-check (push) Successful in 3s
CI UI / ui-sb-test (push) Has been skipped
CI Utils Test / ci-utils-test-status-check (push) Successful in 2s
CI Twenty Apps / ci-twenty-apps-status-check (push) Successful in 2s
CI UI / ci-ui-status-check (push) Successful in 2s
CI Desktop / desktop (push) Failing after 1m8s
Push docs to Crowdin / Push documentation to Crowdin (push) Failing after 55s
Push translations to Crowdin / Extract and upload translations (push) Failing after 5s
Push website translations to Crowdin / Extract and upload website translations (push) Failing after 5s
CI Create App / create-app-test (test) (push) Has been skipped
CI Create App / create-app-test (typecheck) (push) Has been skipped
CI Docs / docs-lint (push) Has been skipped
CI Example App Hello World / example-app-hello-world (push) Has been skipped
CI Front / front-task (lingui:extract) (push) Has been skipped
CI Front / front-task (test) (push) Has been skipped
CI Front / front-task (typecheck) (push) Has been skipped
CI UI / ui-sb-build (push) Failing after 1m32s
CI Twenty Apps / ${{ matrix.app.name }} (${{ matrix.server-source }}) (push) Has been skipped
CI Agent Skills / agent-skills-publish (push) Has been skipped
CI Create App / ci-create-app-status-check (push) Successful in 2s
CI Agent Skills / agent-skills-remote-source (push) Has been skipped
CI Create App E2E minimal / create-app-e2e-minimal (push) Has been cancelled
CI E2E Main / e2e-test (push) Has been cancelled
CI Front / front-sb-build (push) Has been cancelled
CI Front / front-build (push) Has been cancelled
CI Create App E2E minimal / ci-create-app-e2e-minimal-status-check (push) Has been cancelled
CI E2E Main / ci-e2e-main-status-check (push) Has been cancelled
CI E2E Main / notify-main-ci-failure (push) Has been cancelled
CI E2E Main / qa-scout-comment (push) Has been cancelled
CI Front / front-sb-test (push) Has been cancelled
CI Front / front-sb-screenshots (push) Has been cancelled
CI Front / ci-front-status-check (push) Has been cancelled
DPA Sub-Processor Sync / sync-subprocessors (push) Failing after 3s
AI Catalog Sync / sync-catalog (push) Failing after 2s

This commit is contained in:
upstream-mirror
2026-09-17 23:28:13 +05:00
commit e7da97194a
32688 changed files with 4208681 additions and 0 deletions

View File

@@ -0,0 +1,293 @@
---
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. Рабочие пространства, в которых приложение установлено и для него включено автообновление (на вкладке «Настройки» приложения), обновляются автоматически в фоновом режиме; в остальных рабочих пространствах пользователи увидят доступное обновление в своих настройках
<Note>
Пререлизные теги работают как ожидается: повышение версии `1.0.0-rc.1` → `1.0.0-rc.2` допускается, а финальный релиз вроде `1.0.0` корректно распознаётся как более высокий, чем `1.0.0-rc.5`. Версия в `package.json` должна сама по себе быть корректной строкой semver.
</Note>
{/* 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` не задано, проверка пропускается.
<Note>
Сервер выполняет окончательную проверку — он проверяет `engines.twenty` как при загрузке tarball-архива, так и при установке в рабочем пространстве. Если вы развёртываете tarball вне стандартного процесса или устанавливаете из маркетплейса, сервер всё равно принудительно проверяет совместимость.
</Note>
## Автоматизированный 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 с правом деплоя на целевом сервере. |
<Note>
Значение `TWENTY_DEPLOY_URL` по умолчанию — `http://localhost:3000` — это заглушка: с хостируемого GitHub раннера к ней не будет доступа. Перед включением CD замените его на публичный URL вашего сервера (или используйте self-hosted раннер с сетевым доступом).
</Note>
**Запуск предварительного деплоя из 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.
<Note>
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
```
</Note>
### Закрепление версий повторно используемых действий
Рабочие процессы `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`).
<Note>
Изображения галереи с любым соотношением сторон отображаются полностью и никогда не обрезаются, но всё, что значительно выше или уже, чем `8:5`, будет иметь пустые поля по бокам.
</Note>
#### Ограничение размера изображения
Файл `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) выше.
<Note>
Если ваше приложение не определяет `aboutDescription` в `defineApplication()`, маркетплейс автоматически использует `README.md` вашего пакета из npm в качестве содержимого страницы «О приложении». Это означает, что вы можете поддерживать единый README как для npm, так и для маркетплейса Twenty. Если вы хотите другое описание в маркетплейсе, явно задайте `aboutDescription`.
</Note>
### Публикация через 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, и в противном случае автоматически пропускается.
<Note>
**npm provenance** добавляет значок доверия к вашему пакету в npm, позволяя пользователям проверить, что пакет был собран из конкретного коммита в общедоступном конвейере CI. Это также то, что позволяет вам заявить права на ваше приложение в маркетплейсе Twenty. Подробности см. в [документации по npm provenance](https://docs.npmjs.com/generating-provenance-statements).
</Note>
## Установка приложений
После публикации приложения (npm) или его развертывания (tarball) рабочие пространства могут установить его через интерфейс.
Перейдите на страницу **Настройки > Приложения** в Twenty, где можно просматривать и устанавливать как приложения из маркетплейса, так и развернутые через tarball.
{/* TODO: add screenshot of the UI when the app is registered */}
Вы также можете устанавливать приложения из командной строки:
```bash filename="Terminal"
yarn twenty app:install
```
<Note>
Сервер при установке применяет версионирование semver, аналогичное правилам при развёртывании:
* Установка той же версии, которая уже установлена в вашем рабочем пространстве, отклоняется с ошибкой `APP_ALREADY_INSTALLED`.
* Установка версии ниже текущей отклоняется с ошибкой `CANNOT_DOWNGRADE_APPLICATION`.
Чтобы установить более новую версию, сначала разверните или опубликуйте её, затем снова выполните `yarn twenty app:install`.
</Note>