296 lines
13 KiB
Plaintext
296 lines
13 KiB
Plaintext
---
|
||
title: 发布
|
||
icon: 上传
|
||
description: 将你的 Twenty 应用分发到应用市场,或进行内部部署。
|
||
---
|
||
|
||
## 概览
|
||
|
||
一旦你的应用已[在本地构建并完成测试](/l/zh/developers/extend/apps/building),你可以通过两种方式进行分发:
|
||
|
||
* **部署 tar 包** — 直接将你的应用上传到特定的 Twenty 服务器,以供内部或私有使用。
|
||
* **发布到 npm** — 将你的应用在 Twenty 应用市场上架,供任何工作区发现并安装。
|
||
|
||
两种路径都从同一个**构建**步骤开始。
|
||
|
||
## 构建你的应用
|
||
|
||
Run the build command to compile your app and generate a distribution-ready `manifest.json`:
|
||
|
||
```bash filename="Terminal"
|
||
yarn twenty build
|
||
```
|
||
|
||
This compiles TypeScript sources, transpiles logic functions and front components, and writes everything to `.twenty/output/`. Add `--tarball` to also produce a `.tgz` package for manual distribution or the deploy command.
|
||
|
||
## 部署到服务器(tar 包)
|
||
|
||
对于你不希望公开的应用(专有工具、仅供企业使用的集成或实验性构建),你可以将 tar 包直接部署到某台 Twenty 服务器。
|
||
|
||
### 先决条件
|
||
|
||
在部署之前,你需要配置一个指向目标服务器的远程。 远程会将服务器 URL 和身份验证凭据本地存储在 `~/.twenty/config.json` 中。
|
||
|
||
添加远程:
|
||
|
||
```bash filename="Terminal"
|
||
yarn twenty remote add --api-url https://your-twenty-server.com --as production
|
||
```
|
||
|
||
### 部署
|
||
|
||
一步构建并将你的应用上传到服务器:
|
||
|
||
```bash filename="Terminal"
|
||
yarn twenty deploy
|
||
# To deploy to a specific remote:
|
||
# yarn twenty deploy --remote production
|
||
```
|
||
|
||
### 共享已部署的应用
|
||
|
||
<Warning>
|
||
在多个工作区之间共享私有(tarball)应用是一项 **Enterprise** 功能。 在您的工作区拥有有效的 Enterprise 密钥之前,**Distribution** 选项卡将显示升级提示,而不是共享控件。 请前往 [设置 > 管理面板 > Enterprise](/settings/admin-panel#enterprise) 以启用。
|
||
</Warning>
|
||
|
||
通过 tar 包分发的应用不会出现在公共市场中,因此同一服务器上的其他工作区无法通过浏览发现它们。 一旦您的工作区升级到企业版计划,您就可以像这样分享已部署的应用:
|
||
|
||
1. 前往 **Settings > Applications > Registrations** 并打开你的应用
|
||
2. 在 **Distribution** 选项卡中,点击 **Copy share link**
|
||
3. 将此链接分享给其他工作区的用户 — 它会将他们直接带到该应用的安装页面
|
||
|
||
该分享链接使用服务器的基础 URL(不包含任何工作区子域),因此适用于该服务器上的任意工作区。
|
||
|
||
### 版本管理
|
||
|
||
在更新已部署的 tarball 应用时,服务器要求 `package.json` 中的 `version` 必须**严格高于**(按[语义化版本](https://semver.org)排序)当前已部署的版本。 在 tar 包存储之前,重新部署相同版本或推送更低版本都会被拒绝 — 你会在 CLI 中看到 `VERSION_ALREADY_EXISTS` 错误。
|
||
|
||
要发布更新:
|
||
|
||
1. 将 `package.json` 中的 `version` 字段递增(例如:`1.2.3` → `1.2.4`、`1.3.0` 或 `2.0.0`)
|
||
2. Run `yarn twenty deploy` (or `yarn twenty deploy --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 服务器版本中引入的功能(例如在 v2.3.0 中新增的 OAuth 提供方),应当在 `package.json` 的 `engines.twenty` 字段中声明应用所需的最低服务器版本:
|
||
|
||
```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>
|
||
服务器是权威校验方——它会在 tarball 上传和工作区安装时验证 `engines.twenty`。 即使你通过带外方式部署 tarball 或从应用市场安装,服务器仍会强制执行兼容性要求。
|
||
</Note>
|
||
|
||
## 自动化 CI/CD(脚手架生成的工作流)
|
||
|
||
使用 `create-twenty-app` 生成的应用开箱即带有两个 GitHub Actions 工作流,位于 `.github/workflows/`。 当你将仓库推送到 GitHub 后即可运行——CI 无需额外设置,CD 只需要一个机密。
|
||
|
||
### CI — `ci.yml`
|
||
|
||
它会在每次向 `main` 推送以及拉取请求上自动运行你的集成测试。
|
||
|
||
**作用:**
|
||
|
||
1. 检出你的应用源代码。
|
||
2. 使用 `twentyhq/twenty/.github/actions/spawn-twenty-app-dev-test@main` 组合 action 启动一个隔离的 Twenty 测试实例(相当于 CI 中的 `yarn twenty server start --test`)。
|
||
3. 启用 Corepack,从你的 `.nvmrc` 设置 Node.js,并使用 `yarn install --immutable` 安装依赖。
|
||
4. 运行 `yarn test`,并从启动的实例传入 `TWENTY_API_URL` 和 `TWENTY_API_KEY`,以便你的测试可以与真实服务器通信。
|
||
|
||
**配置选项:**
|
||
|
||
* `TWENTY_VERSION`(环境变量,默认 `latest`)— 通过在 `ci.yml` 中编辑它来固定 CI 使用的 Twenty 服务器版本。
|
||
* 并发按 `github.ref` 分组,并会在有新的推送时取消进行中的运行。
|
||
|
||
不需要任何机密——测试实例是临时的,只在作业持续期间存在。
|
||
|
||
### CD — `cd.yml`
|
||
|
||
在每次向 `main` 推送时将你的应用部署到已配置的 Twenty 服务器;当为拉取请求添加 `deploy` 标签时,也可从该拉取请求进行部署。
|
||
|
||
**作用:**
|
||
|
||
1. 检出 PR 的 head(针对已加标签的 PR),或被推送的提交。
|
||
2. 运行 `twentyhq/twenty/.github/actions/deploy-twenty-app@main`——相当于 CI 中的 `yarn twenty deploy`。
|
||
3. 运行 `twentyhq/twenty/.github/actions/install-twenty-app@main`,将新部署的版本安装到目标工作区。
|
||
|
||
**必需的配置:**
|
||
|
||
| 设置 | 位置 | 目的 |
|
||
| ----------------------- | -------------------------------------------------------- | ---------------------------------------- |
|
||
| `TWENTY_DEPLOY_URL` | `cd.yml` 中的 `env`(默认值为 `http://localhost:3000`) | 要部署到的 Twenty 服务器。 首次使用前将其更改为你真实的服务器 URL。 |
|
||
| `TWENTY_DEPLOY_API_KEY` | GitHub 仓库 **Settings → Secrets and variables → Actions** | 在目标服务器上具有部署权限的 API 密钥。 |
|
||
|
||
<Note>
|
||
默认的 `TWENTY_DEPLOY_URL` 值 `http://localhost:3000` 只是占位符——从 GitHub 托管的 runner 无法访问任何资源。 在启用 CD 之前,将其更新为你服务器的公网 URL(或使用具有网络访问权限的自托管 runner)。
|
||
</Note>
|
||
|
||
**从 PR 触发预览部署:**
|
||
|
||
为拉取请求添加 `deploy` 标签。 在 `cd.yml` 中的 `if:` 守卫会使用该 PR 的 head 提交为其运行作业,使你能在合并前在目标服务器上验证更改。
|
||
|
||
### 固定可复用的 actions
|
||
|
||
两个工作流都引用了位于 `@main` 的可复用 actions,因此会自动获取 `twentyhq/twenty` 仓库中的 action 更新。 如果你希望构建具有确定性,请在每个 `uses:` 行中将 `@main` 替换为某个提交的 SHA 或发行标签。
|
||
|
||
## 发布到 npm
|
||
|
||
发布到 npm 可让你的应用在 Twenty 应用市场中被发现。 任何 Twenty 工作区都可以直接通过 UI 浏览、安装和升级应用市场中的应用。
|
||
|
||
### 要求
|
||
|
||
* 一个 [npm](https://www.npmjs.com) 账户
|
||
* 你在 `package.json` 的 `keywords` 数组中的 `twenty-app` 关键字(需要手动添加 — 在 `create-twenty-app` 模板中默认不包含)
|
||
|
||
```json filename="package.json"
|
||
{
|
||
"name": "twenty-app-postcard-sender",
|
||
"version": "1.0.0",
|
||
"keywords": ["twenty-app"]
|
||
}
|
||
```
|
||
|
||
### 应用市场元数据
|
||
|
||
The `defineApplication()` config supports optional fields that control how your app appears in the marketplace. Use `logoUrl` and `screenshots` to reference images from the `public/` folder:
|
||
|
||
```ts src/application-config.ts
|
||
export default defineApplication({
|
||
universalIdentifier: '...',
|
||
displayName: 'My App',
|
||
description: 'A great app',
|
||
defaultRoleUniversalIdentifier: DEFAULT_ROLE_UNIVERSAL_IDENTIFIER,
|
||
logoUrl: 'public/logo.png',
|
||
screenshots: [
|
||
'public/screenshot-1.png',
|
||
'public/screenshot-2.png',
|
||
],
|
||
});
|
||
```
|
||
|
||
See the [defineApplication accordion](/l/zh/developers/extend/apps/building#defineentity-functions) in the Building Apps page for the full list of marketplace fields (`author`, `category`, `aboutDescription`, `websiteUrl`, `termsUrl`, etc.).
|
||
|
||
#### 建议的屏幕截图尺寸
|
||
|
||
该市场会在固定的 `8:5` 容器中渲染 `screenshots`(例如,`1600×1000 px`)。
|
||
|
||
<Note>
|
||
任意纵横比的屏幕截图都会完整显示,且绝不会被裁剪,但相对于 `8:5` 明显更高或更窄的图片,两侧会出现空白边。
|
||
</Note>
|
||
|
||
### Publish
|
||
|
||
```bash filename="Terminal"
|
||
yarn twenty publish
|
||
```
|
||
|
||
要在特定的 dist-tag(例如 `beta` 或 `next`)下发布:
|
||
|
||
```bash filename="Terminal"
|
||
yarn twenty publish --tag beta
|
||
```
|
||
|
||
### 应用市场的发现机制如何运作
|
||
|
||
The Twenty server syncs its marketplace catalog from the npm registry **every hour**.
|
||
|
||
You can trigger the sync immediately instead of waiting:
|
||
|
||
```bash filename="Terminal"
|
||
yarn twenty server catalog-sync
|
||
# To target a specific remote:
|
||
# yarn twenty server catalog-sync --remote production
|
||
```
|
||
|
||
The metadata shown in the marketplace comes from your `defineApplication()` config — fields like `displayName`, `description`, `author`, `category`, `logoUrl`, `screenshots`, `aboutDescription`, `websiteUrl`, and `termsUrl`.
|
||
|
||
<Note>
|
||
如果您的应用未在 `defineApplication()` 中定义 `aboutDescription`,市场将自动使用 npm 上您的软件包的 `README.md` 作为关于页面内容。 这意味着您可以为 npm 和 Twenty 市场维护同一个 README。 如果您希望在市场中使用不同的描述,请显式设置 `aboutDescription`。
|
||
</Note>
|
||
|
||
### CI 发布
|
||
|
||
Use this GitHub Actions workflow to publish automatically on every release (uses [OIDC](https://docs.npmjs.com/trusted-publishers)):
|
||
|
||
```yaml filename=".github/workflows/publish.yml"
|
||
name: Publish
|
||
on:
|
||
release:
|
||
types: [published]
|
||
|
||
permissions:
|
||
contents: read
|
||
id-token: write
|
||
|
||
jobs:
|
||
publish:
|
||
runs-on: ubuntu-latest
|
||
steps:
|
||
- uses: actions/checkout@v4
|
||
- uses: actions/setup-node@v4
|
||
with:
|
||
node-version: "24"
|
||
registry-url: https://registry.npmjs.org
|
||
- run: yarn install --immutable
|
||
- run: npx twenty build
|
||
- run: npm publish --provenance --access public
|
||
working-directory: .twenty/output
|
||
```
|
||
|
||
对于其他 CI 系统(GitLab CI、CircleCI 等),同样适用以下三条命令:`yarn install`、`yarn twenty build`,然后在 `.twenty/output` 目录下执行 `npm publish`。
|
||
|
||
<Note>
|
||
**npm provenance** 可选,但建议启用。 使用 `--provenance` 发布会在你的 npm 列表中添加可信徽章,使用户可以验证该包是由公共 CI 流水线中的特定提交构建的。 有关设置说明,请参见 [npm provenance 文档](https://docs.npmjs.com/generating-provenance-statements)。
|
||
</Note>
|
||
|
||
## 安装应用
|
||
|
||
Once an app is published (npm) or deployed (tarball), workspaces can install it through the UI.
|
||
|
||
Go to the **Settings > Applications** page in Twenty, where both marketplace and tarball-deployed apps can be browsed and installed.
|
||
|
||
{/* TODO: add screenshot of the UI when the app is registered */}
|
||
|
||
You can also install apps from the command line:
|
||
|
||
```bash filename="Terminal"
|
||
yarn twenty install
|
||
```
|
||
|
||
<Note>
|
||
服务器在安装时强制执行 SemVer 版本控制,与部署时的规则一致:
|
||
|
||
* 尝试安装与工作区中已安装版本相同的版本将被拒绝,并返回 `APP_ALREADY_INSTALLED` 错误。
|
||
* 尝试安装低于当前已安装版本的版本将被拒绝,并返回 `CANNOT_DOWNGRADE_APPLICATION` 错误。
|
||
|
||
若要安装较新的版本,请先部署或发布它,然后重新运行 `yarn twenty install`。
|
||
</Note>
|