@h-ai/deploy 1.0.0-beta.3 → 1.0.0-beta.5
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.en.md +9 -3
- package/README.ja.md +9 -3
- package/README.md +9 -3
- package/dist/index.d.ts +2 -2
- package/dist/index.js +80 -13
- package/dist/index.js.map +1 -1
- package/package.json +4 -4
package/README.en.md
CHANGED
|
@@ -87,6 +87,8 @@ The SDK generates matching Nginx paths, runtime configuration URLs, SSR health c
|
|
|
87
87
|
|
|
88
88
|
The default deployment name comes from `package.json.name` at the project root (the nearest `hai.json` or lockfile directory), rejecting missing or invalid names, with an explicit environment appended. A fullstack `hai-delivery` project scanned at `packages/hai-delivery-serv` with `--env test` generates `/opt/hai/apps/hai-delivery-test` and `bundle-hai-delivery-test-<deploymentId>-<version>.tar.gz`. Remote directories, bundles, the Compose project, API/Web/middleware containers, data volumes, server credential state and incremental baselines share this name. Actual project names ending in `-serv` are preserved.
|
|
89
89
|
|
|
90
|
+
For a gateway that only exposes `/somepath/`, build with `PUBLIC_BASE_PATH=/somepath` and explicitly place Serv `http.apiPrefix`, health/readiness, docs and storage `publicEndpoint` under that prefix. The SDK generates proxy paths and browser API configuration from those effective settings. Preserve the prefix at the edge; handle internal probes and root ACME challenges separately. [Complete configuration and checks](../../docs/usage/configuration/delivery.md#所有对外业务路径必须带同一目录).
|
|
91
|
+
|
|
90
92
|
Artifact formats 4 and 5 record primaryService (serv/web); hasWeb describes the complete browser topology. Format 5 also records a non-root webBasePath. Only serv + web generates a same-origin API proxy. Rebuild artifacts using formats 1–3. Back up the existing deployment and verify project identity, volumes and managed credentials before establishing a new full deployment baseline. Tools do not migrate data across projects. Full deployments still remove obsolete service containers under the same Compose project; editing deploy-target.json.directory alone does not migrate resources.
|
|
91
93
|
|
|
92
94
|
For existing projects, update build.images names in hai.json, Dockerfile filenames and references first. Rename API service directories/packages and dependent references to -serv, then reinstall dependencies and build a complete artifact. Renaming archives or editing manifest files does not replace a new build.
|
|
@@ -237,7 +239,11 @@ SSH interruptions initially report `remoteExecution: 'unknown'`. The docker-ssh
|
|
|
237
239
|
|
|
238
240
|
### Runtime environment files and repeated deployments
|
|
239
241
|
|
|
240
|
-
|
|
242
|
+
Environment flags, initial account passwords and the transport key ring are also read directly by startup code. They remain available even when a similarly named configuration parent exists.
|
|
243
|
+
|
|
244
|
+
Delivery removes every HAI child variable hidden by a parent and omits settings supplied by `middleware.env` from `.env.runtime`. Container paths stay in delivery files; pruning leaves the source environment intact. Edit the retained parent object or managed connection file.
|
|
245
|
+
|
|
246
|
+
Node backends (Serv / SvelteKit SSR) reread the release `.env.runtime` on every start by default. Edit it, then run `docker restart <container>` or `podman restart <container>`; no image rebuild or extra override is needed. Existing deployments need one deployment with the new CLI. Removed settings do not survive through stale Compose injection. Managed connections in `middleware.env` retain precedence; private proxy identity and Node startup options remain deployment settings. Static Web, middleware, ports/mounts, and Nginx routes and limits keep their existing update flow. Gateway path, port or mount changes require a full deployment. Back up manual edits and copy permanent changes into the source environment; the next backend deployment regenerates the file.
|
|
241
247
|
|
|
242
248
|
Persisted framework configuration uses `HAI_*` names. Native `POSTGRES_*`, `MYSQL_*`, `RUSTFS_*`, `MINIO_*`, and `LDAP_*` variables keep the names required by middleware images, but are generated only in private `middleware-runtime.env`, loaded by middleware containers. They are no longer saved to project environment files or the application's `.env.runtime`. The `middleware.env` retained for incremental application updates contains framework `HAI_*` settings only. Previously saved native entries are not deleted automatically and are excluded from new application environments. Existing services keep their original release files when a new bundle is deployed incrementally.
|
|
243
249
|
|
|
@@ -271,11 +277,11 @@ Use `importDeploymentSecrets({ directory, inputFile, runtime })` or run `hai dep
|
|
|
271
277
|
|
|
272
278
|
## Request policy files and trusted proxies
|
|
273
279
|
|
|
274
|
-
Serv `http.access` and SvelteKit `access` can reference separate yml/yaml files. Deployment reads effective application configuration, including environment overrides such as `HAI_SERV`, `HAI_SERV_HTTP_ACCESS` and `HAI_KIT_ACCESS`, validates the file and includes a normalized snapshot in the bundle. Runtime configuration points to `/run/hai/request-access.yml` with a read-only Compose mount. The project retains its original file reference. The snapshot participates in SHA-256 verification; missing or invalid files fail before upload.
|
|
280
|
+
Serv `http.access` and SvelteKit `access` can reference separate yml/yaml files. Deployment reads effective application configuration, including environment overrides such as `HAI_SERV`, `HAI_SERV_HTTP_ACCESS` and `HAI_KIT_ACCESS`, validates the file and includes a normalized snapshot in the bundle. Runtime configuration points to `/run/hai/request-access.yml` with a read-only Compose mount. The project retains its original file reference. The snapshot participates in SHA-256 verification; missing or invalid files fail before upload. The upload archive and its policy snapshot are integrity-checked inputs; replacing the SDK-managed snapshot requires a new bundle and deployment. The deployed Node backend reads its mounted `.env.runtime` on restart as described above. Inline rule changes do not rewrite the policy snapshot or Nginx configuration.
|
|
275
281
|
|
|
276
282
|
Full deployments and backend increments carry their own snapshot; frontend-only increments retain the backend mount. Failed deployment recovery uses the previous successful release's Compose and policy file. Non-root containers can read the policy inside a private release directory. Image and policy rollback does not undo database migrations or completed business effects.
|
|
277
283
|
|
|
278
|
-
For operator-managed rules that reload on restart, manage a read-only file outside the bundle and use a Compose override to replace the same `/run/hai/request-access.yml` mount. SDK rollback does not restore this external file. Recreate the container once to apply the mount; later file changes require a restart.
|
|
284
|
+
For operator-managed rules that reload on restart, manage a read-only file outside the bundle and use a Compose override to replace the same `/run/hai/request-access.yml` mount. SDK rollback does not restore this external file. Recreate the container once to apply the mount; later file changes require a restart. A custom container that only injects variables through Compose `env_file` still needs recreation after file changes, usually without rebuilding the image. SDK Node backends instead read the mounted `.env.runtime` on restart. See [mounted policy setup and verification](../../docs/usage/configuration/request-access.md#44-运维独立管理文件修改后重启生效).
|
|
279
285
|
|
|
280
286
|
Managed Compose sets `HAI_DEPLOY_PRIVATE_PROXY=1` only when a Web/gateway proxy fronts a backend without public ports. Serv/Kit default `trustedProxies: auto` uses container networks there and ignores forwarded headers on other hosts. Generated Nginx overwrites client-supplied forwarding headers with the actual peer. For an upstream load balancer, explicitly set Docker SSH Provider `trustedEdgeProxies` to its IPs/CIDRs; omitting it trusts no upstream, and `[]` explicitly selects the same behavior. Source addresses lost before Nginx cannot be reconstructed, including some rootless forwarding environments. See the [request access handbook](../../docs/usage/configuration/request-access.md) for examples and verification.
|
|
281
287
|
|
package/README.ja.md
CHANGED
|
@@ -77,6 +77,8 @@ pnpm build --target desktop --platform windows --arch x64
|
|
|
77
77
|
|
|
78
78
|
#### サイトの公開ディレクトリー
|
|
79
79
|
|
|
80
|
+
`/somepath/` のみを公開する場合、`PUBLIC_BASE_PATH=/somepath` でビルドし、Serv の `http.apiPrefix`、ヘルス/準備確認、ドキュメントとストレージ `publicEndpoint` を同じディレクトリに明示設定します。SDK は実効設定からプロキシとブラウザ API アドレスを生成します。外側では接頭辞を保持し、内部プローブとルートの ACME 検証は別に扱います。[設定と検証](../../docs/usage/configuration/delivery.md#所有对外业务路径必须带同一目录)。
|
|
81
|
+
|
|
80
82
|
既定はサイトルートです。`https://example.com/yyy/`で公開する場合は、アプリ構築プロセスで`PUBLIC_BASE_PATH=/yyy`を明示します。CLIは形式5を生成し、webBasePathを保存します。これは構築情報であり、デプロイ環境で上書きする設定ではありません。各区間はASCII英数字・`_`・`.`・`-`のみ、末尾の斜線や単独の`.`/`..`区間は使用できません。形式5対応のCLI/Deployが必要で、旧ツールは拒否します。形式番号を手で変更しないでください。
|
|
81
83
|
|
|
82
84
|
SDKは対応するNginx、実行時設定URL、SSRヘルスチェック、公開URLを生成します。追加のゲートウェイは接頭辞を保持します。同一オリジンAPIはServのhttp.apiPrefixで別に決まり、CORSの許可元はスキーム・ホスト・ポートだけです。独立Viteサイトは設定済みの外部APIアドレスを維持します。servだけの部分構築も含め、全量・部分構築で同じPUBLIC_BASE_PATHを使用します。増分では置換前に不一致を拒否し、ディレクトリー変更には全量デプロイを使います。復旧時は旧公開のヘルスパスを検証します。[設定・フレームワークの違い・実行画面](../../docs/usage/configuration/delivery.md#网站部署在子目录)を参照してください。
|
|
@@ -235,7 +237,11 @@ SSH 中断は最初に `remoteExecution: 'unknown'` とし、docker-ssh SDK は
|
|
|
235
237
|
|
|
236
238
|
### 実行環境ファイルと設定の再利用
|
|
237
239
|
|
|
238
|
-
|
|
240
|
+
環境フラグ・初期アカウントパスワード・転送キーリングは起動コードも直接読み取るため、同じ接頭辞の親設定があっても保持します。
|
|
241
|
+
|
|
242
|
+
配布時には HAI 親変数で隠れるすべての子項目と、`middleware.env` が提供する `.env.runtime` の重複項目を除去します。コンテナ内パスは配布設定に保存し、この除去処理で元の環境は変更しません。残った親オブジェクトまたは管理接続ファイルを編集します。
|
|
243
|
+
|
|
244
|
+
Node バックエンド(Serv / SvelteKit SSR)は起動ごとに配布先の `.env.runtime` を既定で読み直します。編集後に `docker restart <コンテナー>` または `podman restart <コンテナー>` を実行し、イメージ再構築や追加 override は不要です。既存配置は新 CLI で一度デプロイしてください。削除した設定を旧 Compose 環境から復活させず、管理接続の `middleware.env` を優先します。私有プロキシ識別と Node 起動引数は配置設定のままです。静的 Web・ミドルウェア・ポート/マウント・Nginx の経路と制限は従来手順で更新します。ゲートウェイの経路、ポート、マウントの変更は全量デプロイを行います。手動変更をバックアップし、継続する値は元の環境にも反映してください。次のバックエンド配置時に再生成されます。
|
|
239
245
|
|
|
240
246
|
フレームワークの永続設定は `HAI_*` を使います。`POSTGRES_*`、`MYSQL_*`、`RUSTFS_*`、`MINIO_*`、`LDAP_*` はミドルウェアイメージ必須の名前を維持し、非公開の `middleware-runtime.env` にだけ生成してミドルウェアに渡します。プロジェクト環境ファイルやアプリの `.env.runtime` には新規保存しません。増分アプリ更新用の `middleware.env` は `HAI_*` 設定のみです。既存の原生変数は自動削除せず、新しいアプリ環境から除外します。未更新サービスは以前の配布ファイルを使い続けます。
|
|
241
247
|
|
|
@@ -269,11 +275,11 @@ Podman では設定済みの healthcheck を明示的に実行して状態を再
|
|
|
269
275
|
|
|
270
276
|
## リクエストポリシーファイルと信頼する代理
|
|
271
277
|
|
|
272
|
-
Serv の `http.access` と SvelteKit の `access` は独立した yml/yaml を参照できます。配備は `HAI_SERV`、`HAI_SERV_HTTP_ACCESS`、`HAI_KIT_ACCESS` などの環境上書きを含む実効設定を読み、検証済みの正規化スナップショットを配布物へ含めます。実行時は `/run/hai/request-access.yml` を Compose の読み取り専用マウントで参照し、工程の元の参照先は変更しません。SHA-256
|
|
278
|
+
Serv の `http.access` と SvelteKit の `access` は独立した yml/yaml を参照できます。配備は `HAI_SERV`、`HAI_SERV_HTTP_ACCESS`、`HAI_KIT_ACCESS` などの環境上書きを含む実効設定を読み、検証済みの正規化スナップショットを配布物へ含めます。実行時は `/run/hai/request-access.yml` を Compose の読み取り専用マウントで参照し、工程の元の参照先は変更しません。SHA-256 検証に含まれ、ファイル不足・不正はアップロード前に失敗します。アップロードするアーカイブとそのポリシースナップショットは整合性検証の対象です。SDK 管理のスナップショットを置き換える場合は新しい配布物を作成します。配置済み Node バックエンドのマウント済み `.env.runtime` は上記手順で編集・再起動できます。インライン規則の変更ではスナップショットや Nginx 設定は書き換わりません。
|
|
273
279
|
|
|
274
280
|
全量とバックエンドを含む増分は独自のスナップショットを持ち、フロントエンドだけの増分は旧バックエンドのマウントを維持します。失敗時は前回成功した Compose とポリシーへ復旧します。非 root コンテナでも私有リリースディレクトリ内のファイルを読み取れます。イメージと設定の復旧は DB 移行や実施済み業務を取り消しません。
|
|
275
281
|
|
|
276
|
-
運用側でルールを変更して再起動で反映する場合は、配布物の外で読み取り専用ファイルを管理し、Compose override で同じ `/run/hai/request-access.yml` のマウントを置き換えます。この外部ファイルは SDK
|
|
282
|
+
運用側でルールを変更して再起動で反映する場合は、配布物の外で読み取り専用ファイルを管理し、Compose override で同じ `/run/hai/request-access.yml` のマウントを置き換えます。この外部ファイルは SDK の自動復旧対象外です。初回マウント適用はコンテナ再作成、以後のファイル変更は再起動で反映できます。Compose の `env_file` だけで環境変数を注入する独自コンテナは、変更後に再作成します。通常イメージ再構築は不要です。SDK の Node バックエンドはマウント済み `.env.runtime` を再起動時に読み取ります。[設定と実測の境界](../../docs/usage/configuration/request-access.md#44-运维独立管理文件修改后重启生效)を参照してください。
|
|
277
283
|
|
|
278
284
|
Web/gateway 入口がありバックエンドのポートが非公開の場合だけ、管理 Compose は `HAI_DEPLOY_PRIVATE_PROXY=1` を設定します。この構成の `trustedProxies: auto` はコンテナネットワークを採用し、他のホストでは転送ヘッダーを無視します。生成 Nginx は実接続元で転送ヘッダーを上書きします。外側の負荷分散器は Docker SSH Provider の `trustedEdgeProxies` に実 IP/CIDR を明記してください。省略時は上流を信頼せず、`[]` も同じ動作です。Nginx 到達前に失われた源 IP は復元できず、一部の rootless 構成も実測が必要です。[リクエスト制御手引き](../../docs/usage/configuration/request-access.md)に例と確認手順を記載しています。
|
|
279
285
|
|
package/README.md
CHANGED
|
@@ -100,6 +100,8 @@ SDK据制品生成Nginx目录、运行配置入口、SSR健康路径和返回URL
|
|
|
100
100
|
|
|
101
101
|
默认部署名取工程根(最近的 `hai.json` 或锁文件所在目录)的 `package.json.name`,缺失时报错,再附加显式环境后缀。例如 fullstack 工程 `hai-delivery` 扫描 `packages/hai-delivery-serv`,`--env test` 生成 `/opt/hai/apps/hai-delivery-test` 和 `bundle-hai-delivery-test-<部署ID>-<版本>.tar.gz`。远端目录、交付包、Compose 项目、API/Web/中间件容器、数据卷、服务器凭据状态及增量基线统一使用该名称;不会按字符串删除真实项目名中的 `-serv`。
|
|
102
102
|
|
|
103
|
+
全站仅开放 `/somepath/` 时,构建设置 `PUBLIC_BASE_PATH=/somepath`,并将 Serv 的 `http.apiPrefix`、健康/就绪和文档路径及存储 `publicEndpoint` 显式配置到同一目录。SDK 按这些有效配置生成代理和浏览器 API 地址;外层网关保留前缀,内部探活和 ACME 根路径单独处理。[完整配置与验收](../../docs/usage/configuration/delivery.md#所有对外业务路径必须带同一目录)。
|
|
104
|
+
|
|
103
105
|
制品格式4和5都记录primaryService(serv/web),hasWeb表示完整工程是否包含浏览器端;格式5另记录非根目录webBasePath。只有serv + web才生成同源API代理。格式1至3制品须重新构建。旧部署先备份并核对项目名、数据卷和受管凭据,再切换到新的完整部署基线;工具不自动跨项目迁移数据。完整部署仍会按Compose规则清理同项目的旧服务容器,不能仅修改deploy-target.json.directory完成迁移。
|
|
104
106
|
|
|
105
107
|
迁移已有工程时,先同步 hai.json 的 build.images 名称、Dockerfile 文件名与引用;API workspace 的服务目录、包名和依赖引用统一为 -serv,并重新安装依赖。随后重新构建完整制品;不要仅改归档文件名或手工修改 manifest 冒充新构建。
|
|
@@ -261,7 +263,11 @@ SSH 中断始终先记 `remoteExecution: 'unknown'`。docker-ssh SDK 用新连
|
|
|
261
263
|
|
|
262
264
|
### 运行环境文件与重复部署
|
|
263
265
|
|
|
264
|
-
Node 后端(Serv / SvelteKit SSR)默认在每次启动时重读发布目录的 `.env.runtime`,修改后 `docker restart <容器名>` 或 `podman restart <容器名>` 即可,无需重建镜像或额外 override。旧部署先用新版 CLI 发布一次。删除的字段不会从旧 Compose 注入中复活;服务器托管连接的 `middleware.env` 保持原有更高优先级,私有代理标记和 Node 启动参数仍由部署装配管理。静态 Web
|
|
266
|
+
Node 后端(Serv / SvelteKit SSR)默认在每次启动时重读发布目录的 `.env.runtime`,修改后 `docker restart <容器名>` 或 `podman restart <容器名>` 即可,无需重建镜像或额外 override。旧部署先用新版 CLI 发布一次。删除的字段不会从旧 Compose 注入中复活;服务器托管连接的 `middleware.env` 保持原有更高优先级,私有代理标记和 Node 启动参数仍由部署装配管理。静态 Web、中间件、端口/挂载、Nginx 路由与限额不在该重载范围;改变网关路径、端口或挂载时使用全量部署。手工修改需备份;下一次后端发布会从工程环境重新生成,需要长期保留的配置同步回源环境。
|
|
267
|
+
|
|
268
|
+
同前缀但由进程直接读取的环境标记、初始账号密码和传输密钥环仍保留;它们不属于已被父对象替代的配置。
|
|
269
|
+
|
|
270
|
+
交付配置会清除所有被 `HAI_*` 父级变量遮蔽的子项,并从 `.env.runtime` 删除由 `middleware.env` 提供的重复项。容器内路径只保存在交付配置中;清理不会改写源环境。修改时以保留下来的父对象或托管连接文件为准。
|
|
265
271
|
|
|
266
272
|
框架持久配置使用 `HAI_*` 命名。`POSTGRES_*`、`MYSQL_*`、`RUSTFS_*`、`MINIO_*`、`LDAP_*` 是中间件镜像的原生协议,必须保留原名,但只生成到私有的 `middleware-runtime.env` 并由中间件容器加载;不再写入工程环境文件或应用的 `.env.runtime`。应用增量部署沿用的 `middleware.env` 仅保存框架 `HAI_*` 配置。旧工程已保存的这些原生字段不会被自动删除,新应用环境会忽略它们;新包与旧成功基线可共存,旧服务仍读取其原交付文件。
|
|
267
273
|
|
|
@@ -281,11 +287,11 @@ Podman 部署会主动执行容器已有的 healthcheck 并重新核对状态,
|
|
|
281
287
|
|
|
282
288
|
## 请求策略文件与可信代理
|
|
283
289
|
|
|
284
|
-
Serv 的 `http.access`、SvelteKit 的 `access` 可引用独立 yml/yaml。部署读取应用实际生效配置,包括 `.env.<环境>` / 私有覆盖中的 `HAI_SERV`、`HAI_SERV_HTTP_ACCESS` 或 `HAI_KIT_ACCESS`,校验文件后把规范化快照放入交付包。运行环境改为 `/run/hai/request-access.yml`,Compose 只读挂载;工程的原始文件引用不会被容器路径覆盖。快照参加 SHA-256
|
|
290
|
+
Serv 的 `http.access`、SvelteKit 的 `access` 可引用独立 yml/yaml。部署读取应用实际生效配置,包括 `.env.<环境>` / 私有覆盖中的 `HAI_SERV`、`HAI_SERV_HTTP_ACCESS` 或 `HAI_KIT_ACCESS`,校验文件后把规范化快照放入交付包。运行环境改为 `/run/hai/request-access.yml`,Compose 只读挂载;工程的原始文件引用不会被容器路径覆盖。快照参加 SHA-256 校验,无效或缺失文件在上传前失败。待上传的归档和其中的策略快照参与完整性校验,不应手工修改;替换 SDK 策略快照时重新打包部署。已部署 Node 后端挂载的 `.env.runtime` 可以按“运行配置重载”修改并重启,改变内联规则不会重写策略快照或 Nginx 配置。
|
|
285
291
|
|
|
286
292
|
全量与包含后端的增量都交付自己的快照;仅更新前端时保留后端原挂载。失败恢复使用旧成功发布的 Compose 和策略文件。运行账号无需 root:发布目录私有,策略文件在受限目录内以只读权限供容器读取。回滚镜像和策略不撤销数据库迁移或已经产生的业务效果。
|
|
287
293
|
|
|
288
|
-
如需由运维独立改规则、重启后生效,可在交付之外管理只读文件,并用 Compose override 替换同一 `/run/hai/request-access.yml` 挂载。该外部文件不参与 SDK
|
|
294
|
+
如需由运维独立改规则、重启后生效,可在交付之外管理只读文件,并用 Compose override 替换同一 `/run/hai/request-access.yml` 挂载。该外部文件不参与 SDK 自动回滚,首次附加挂载需要重新创建容器;后续文件修改后重启即可。自行维护且只用 Compose `env_file` 注入环境的容器,修改该文件仍需重新创建,通常无需重建镜像;这与 SDK 默认挂载读取的后端 `.env.runtime` 不同。步骤与验证边界见[独立文件重启配置](../../docs/usage/configuration/request-access.md#44-运维独立管理文件修改后重启生效)。
|
|
289
295
|
|
|
290
296
|
受管 Compose 只有存在 Web/gateway 代理且后端没有公开端口时,才设置 `HAI_DEPLOY_PRIVATE_PROXY=1`。Serv/Kit 默认 `trustedProxies: auto` 在此采用容器网段,其他宿主默认忽略转发头。生成 Nginx 用实际对端覆盖客户端提交的转发头;外层负载均衡需在 Docker SSH Provider 的 `trustedEdgeProxies` 显式配置真实 IP/CIDR,省略时不信任上游,`[]` 同样关闭信任。根本未传到 Nginx 的源 IP 无法恢复,Podman rootless 等环境应实际核验入口日志。完整示例和验证步骤见[请求访问控制手册](../../docs/usage/configuration/request-access.md)。
|
|
291
297
|
|
package/dist/index.d.ts
CHANGED
|
@@ -635,7 +635,7 @@ interface DeployResult {
|
|
|
635
635
|
bundlePath?: string;
|
|
636
636
|
/** 手工搬运和启动说明;仅打包不代表服务器已运行。 */
|
|
637
637
|
instructions?: string;
|
|
638
|
-
/**
|
|
638
|
+
/** 保留的有效环境变量名;packaged 状态仅表示交付计划,尚未在服务器设置。 */
|
|
639
639
|
envVarsSet: string[];
|
|
640
640
|
/** 部署 Provider 名称(如 vercel / docker-ssh),容器部署时返回 */
|
|
641
641
|
provider?: string;
|
|
@@ -1002,7 +1002,7 @@ declare const deploy: DeployFunctions;
|
|
|
1002
1002
|
* const message = deployM('deploy_sshRequired')
|
|
1003
1003
|
* ```
|
|
1004
1004
|
*/
|
|
1005
|
-
declare const deployM: (key: "deploy_notInitialized" | "deploy_initFailed" | "deploy_unsupportedProviderType" | "deploy_unsupportedProvisionerType" | "deploy_configTokenRequired" | "deploy_authRequired" | "deploy_authFailed" | "deploy_projectCreateFailed" | "deploy_uploadFailed" | "deploy_deployFailed" | "deploy_provisionFailed" | "deploy_adapterMissing" | "deploy_scanFailed" | "deploy_envVarFailed" | "deploy_credentialError" | "deploy_credentialInvalidKey" | "deploy_credentialSaved" | "deploy_credentialLoaded" | "deploy_configError" | "deploy_credentialMissing" | "deploy_apiError" | "deploy_fileUploadFailed" | "deploy_provisionNoResult" | "deploy_recoveryFailure" | "deploy_recoverySuggestion" | "deploy_commandTimeout" | "deploy_commandFailed" | "deploy_remoteConnectFailed" | "deploy_remoteRuntimeMissing" | "deploy_imageTransferFailed" | "deploy_healthCheckFailed" | "deploy_invalidEnvironment" | "deploy_environmentMissing" | "deploy_environmentReadFailed" | "deploy_environmentWriteFailed" | "deploy_multipleApplications" | "deploy_purposeSqlite" | "deploy_purposeDatabase" | "deploy_purposeMemory" | "deploy_purposeLocal" | "deploy_purposeCache" | "deploy_purposeStorage" | "deploy_purposeVector" | "deploy_purposeDisabled" | "deploy_purposeLdap" | "deploy_purposeConsole" | "deploy_purposeEmail" | "deploy_purposeSms" | "deploy_webProxyInvalid" | "deploy_webBaseConflict" | "deploy_storageProxyInvalid" | "deploy_storagePublicEndpointInvalid" | "deploy_storageBackendRequired" | "deploy_artifactInvalid" | "deploy_sshRequired" | "deploy_sshPasswordInvalid" | "deploy_sshAskpassFailed" | "deploy_sshAskpassCleanupFailed" | "deploy_targetAuth" | "deploy_targetPasswordEnv" | "deploy_bundleInstructions" | "deploy_bundleMetadata" | "deploy_targetHost" | "deploy_targetPort" | "deploy_targetUsername" | "deploy_targetIdentityFile" | "deploy_targetKnownHostsFile" | "deploy_targetStrictHostKeyChecking" | "deploy_targetConnectTimeoutSeconds" | "deploy_targetDirectory" | "deploy_targetBundle" | "deploy_bundleOnlyContainer" | "deploy_selectedContainerOnly" | "deploy_selectionInvalid" | "deploy_imageVersionRequired" | "deploy_bundleRuntimeRequired" | "deploy_bundleFailed" | "deploy_configFileInvalid" | "deploy_configFileUnreadable" | "deploy_bundleNameInvalid" | "deploy_localStopped" | "deploy_localUnknown" | "deploy_localNotStarted" | "deploy_commandOutputFailed" | "deploy_commandInputFailed" | "deploy_commandTreeActive" | "deploy_commandExecutionFailed" | "deploy_remoteUnknown" | "deploy_remoteFinished" | "deploy_bundleDirectoryExists" | "deploy_bundleFull" | "deploy_bundlePartial" | "deploy_bundleSelection" | "deploy_transportBodyLimitInvalid" | "deploy_transportKeyRingInvalid" | "deploy_uploadPasswordPrompt" | "deploy_uploadPasswordUnavailable" | "deploy_uploadPasswordCancelled" | "deploy_uploadPasswordInvalid" | "deploy_managedSecretsInvalid" | "deploy_secretImportFailed" | "deploy_projectNameRequired" | "deploy_projectNameOverrideRemoved" | "deploy_requestAccessInvalid" | "deploy_httpsPortsInvalid" | "deploy_httpsCertificateInvalid", options?: _h_ai_core.MessageOptions) => string;
|
|
1005
|
+
declare const deployM: (key: "deploy_notInitialized" | "deploy_initFailed" | "deploy_unsupportedProviderType" | "deploy_unsupportedProvisionerType" | "deploy_configTokenRequired" | "deploy_authRequired" | "deploy_authFailed" | "deploy_projectCreateFailed" | "deploy_uploadFailed" | "deploy_deployFailed" | "deploy_provisionFailed" | "deploy_adapterMissing" | "deploy_scanFailed" | "deploy_envVarFailed" | "deploy_credentialError" | "deploy_credentialInvalidKey" | "deploy_credentialSaved" | "deploy_credentialLoaded" | "deploy_configError" | "deploy_credentialMissing" | "deploy_apiError" | "deploy_fileUploadFailed" | "deploy_provisionNoResult" | "deploy_recoveryFailure" | "deploy_recoverySuggestion" | "deploy_commandTimeout" | "deploy_commandFailed" | "deploy_remoteConnectFailed" | "deploy_remoteRuntimeMissing" | "deploy_imageTransferFailed" | "deploy_healthCheckFailed" | "deploy_invalidEnvironment" | "deploy_environmentMissing" | "deploy_environmentReadFailed" | "deploy_environmentWriteFailed" | "deploy_multipleApplications" | "deploy_purposeSqlite" | "deploy_purposeDatabase" | "deploy_purposeMemory" | "deploy_purposeLocal" | "deploy_purposeCache" | "deploy_purposeStorage" | "deploy_purposeVector" | "deploy_purposeDisabled" | "deploy_purposeLdap" | "deploy_purposeConsole" | "deploy_purposeEmail" | "deploy_purposeSms" | "deploy_webProxyInvalid" | "deploy_webBaseConflict" | "deploy_storageProxyInvalid" | "deploy_storagePublicEndpointInvalid" | "deploy_storageBackendRequired" | "deploy_artifactInvalid" | "deploy_sshRequired" | "deploy_sshPasswordInvalid" | "deploy_sshAskpassFailed" | "deploy_sshAskpassCleanupFailed" | "deploy_targetAuth" | "deploy_targetPasswordEnv" | "deploy_bundleInstructions" | "deploy_bundleMetadata" | "deploy_targetHost" | "deploy_targetPort" | "deploy_targetUsername" | "deploy_targetIdentityFile" | "deploy_targetKnownHostsFile" | "deploy_targetStrictHostKeyChecking" | "deploy_targetConnectTimeoutSeconds" | "deploy_targetDirectory" | "deploy_targetBundle" | "deploy_bundleOnlyContainer" | "deploy_selectedContainerOnly" | "deploy_selectionInvalid" | "deploy_imageVersionRequired" | "deploy_bundleRuntimeRequired" | "deploy_bundleFailed" | "deploy_configFileInvalid" | "deploy_configFileUnreadable" | "deploy_bundleNameInvalid" | "deploy_localStopped" | "deploy_localUnknown" | "deploy_localNotStarted" | "deploy_commandOutputFailed" | "deploy_commandInputFailed" | "deploy_commandTreeActive" | "deploy_commandExecutionFailed" | "deploy_remoteUnknown" | "deploy_remoteFinished" | "deploy_bundleDirectoryExists" | "deploy_bundleFull" | "deploy_bundlePartial" | "deploy_bundleSelection" | "deploy_transportBodyLimitInvalid" | "deploy_transportKeyRingInvalid" | "deploy_uploadPasswordPrompt" | "deploy_uploadPasswordUnavailable" | "deploy_uploadPasswordCancelled" | "deploy_uploadPasswordInvalid" | "deploy_managedSecretsInvalid" | "deploy_secretImportFailed" | "deploy_projectNameRequired" | "deploy_projectNameOverrideRemoved" | "deploy_requestAccessInvalid" | "deploy_httpsPortsInvalid" | "deploy_httpsCertificateInvalid" | "deploy_bundleRuntime" | "deploy_bundleHttpOnly" | "deploy_bundleHttps" | "deploy_bundleAcme" | "deploy_bundleAccounts" | "deploy_bundleDirectories", options?: _h_ai_core.MessageOptions) => string;
|
|
1006
1006
|
|
|
1007
1007
|
/**
|
|
1008
1008
|
* 部署中间件的后端与连接字段目录,供扫描、CLI 和容器规划共同使用。
|
package/dist/index.js
CHANGED
|
@@ -176,7 +176,13 @@ var en_US_default = {
|
|
|
176
176
|
deploy_projectNameOverrideRemoved: "Deployment identity comes from the root package.json.name; remove the obsolete projectName override.",
|
|
177
177
|
deploy_requestAccessInvalid: "Invalid request access policy ({field}). Check fields, IP addresses, timezones and time windows. For a file reference, use readable YAML no larger than 1 MiB. Fix the configuration and create a new bundle.",
|
|
178
178
|
deploy_httpsPortsInvalid: "HTTP and HTTPS ports must differ; Let\u2019s Encrypt HTTP-01 requires host port 80.",
|
|
179
|
-
deploy_httpsCertificateInvalid: "Invalid HTTPS certificate. Check readable PEM files, matching unencrypted private key, validity dates and domain, then repackage."
|
|
179
|
+
deploy_httpsCertificateInvalid: "Invalid HTTPS certificate. Check readable PEM files, matching unencrypted private key, validity dates and domain, then repackage.",
|
|
180
|
+
deploy_bundleRuntime: "Runtime configuration and activation:\nThis release record: {directory}/releases/{deploymentId}\nNode backends read the file mounted at /run/hai/.env.runtime. Incremental deployments may retain an older record; current alone does not identify it. Inspect Source with docker inspect --format '{{json .Mounts}}' <container>.\nFor ordinary backend settings: back up, edit that file, run docker restart <container> (or Podman), then verify health and affected business flows. HAI parents override children; managed connections in middleware.env take precedence.\nStatic Web/middleware settings injected by Compose env_file require container recreation. Ports, mounts, Nginx routes/limits and HTTPS layout require a new full deployment bundle. Changing the website base also requires rebuilding artifacts.\nCopy permanent edits back to the packaging source environment; the next release regenerates these files.",
|
|
181
|
+
deploy_bundleHttpOnly: "HTTPS: disabled. This bundle exposes HTTP port {port}, contains no certificate attachment and will not request a certificate on the server.",
|
|
182
|
+
deploy_bundleHttps: "HTTPS: enabled, https://{domain}:{port}; mode {mode}.\nServer certificate: {certificates}/fullchain.pem; private key: {certificates}/privkey.pem. Mounted read-only at /etc/nginx/tls/.\nEdit expose.https in HAI_DEPLOY_PROVIDER in the packaging environment .env.{environment}.local, or the unshadowed hai.json.deploy.provider.expose.https. Enable/disable, mode, domain or port changes require a new full bundle; editing .env.runtime and restarting does not issue a certificate for a new domain.",
|
|
183
|
+
deploy_bundleAcme: "Persistent Certbot state: {state}; current certificate entry: {state}/live/{domain}. Packaging does not contact the CA; issuance runs during server deployment, followed by automatic renewal. Public port 80 and root /.well-known/acme-challenge/ must remain reachable independently of the business context path.",
|
|
184
|
+
deploy_bundleAccounts: "Initial account variables (names and sources only; passwords omitted):\n{sources}\nApplications with matching bootstrap logic use HAI_CONFIG_ADMIN_PASSWORD to create the config_admin configuration administrator. HAI_ADMIN_DEFAULT_PASSWORD, HAI_AUDIT_ADMIN_PASSWORD and HAI_BUSINESS_OPERATOR_PASSWORD belong to the other template roles.\nFullstack creation generates independent initial passwords per environment. Packaging reads the selected environment and process overrides; server deployment does not generate new application account passwords. Startup creates missing configured accounts; changing variables does not reset existing passwords or restore old roles. Custom applications without this bootstrap follow their own implementation.",
|
|
185
|
+
deploy_bundleDirectories: "Server directory guide (root {directory}):\nincoming/: uploaded archive and .contents extraction; this upload is removed after success, retained after failure or unknown execution for diagnosis.\nreleases/{deploymentId}/: runtime files and recovery records. images/ is not copied here; images live in the container engine and database/object data in volumes.\ncompose.json defines services; compose-entry.json, proxy-entry.json and compose-files combine full/incremental releases and proxy overrides.\n.env.runtime, middleware.env, middleware-runtime.env and runtime-env.mjs load application/middleware environments; web.conf is the proxy and request-access.yml the verified policy snapshot.\nmanifest.json, image-list, services, dependencies, layout, web-base-path, storage-routing and health-paths record artifacts and probes. apply.sh and resolve-*.sh apply and validate state; SHA256SUMS verifies delivery content.\nmanaged-* and state-backends describe bundle credential candidates and volume/backend bindings. Root managed-secrets.env holds long-lived server credentials; persistent-backends is the backend ledger. Back them up together with data volumes.\ncurrent is a text file containing the last locally successful server release ID. Inspect result-{deploymentId}.json stage/exitCode/recoveryStatus and steps-{deploymentId}.jsonl; a release directory alone does not prove success.\nActive containers and incremental composition may reference older releases. Check every active mount and compose-files before cleanup; retaining only current is insufficient."
|
|
180
186
|
};
|
|
181
187
|
|
|
182
188
|
// messages/ja-JP.json
|
|
@@ -286,7 +292,13 @@ var ja_JP_default = {
|
|
|
286
292
|
deploy_projectNameOverrideRemoved: "\u30C7\u30D7\u30ED\u30A4\u8B58\u5225\u540D\u306F\u5DE5\u7A0B\u30EB\u30FC\u30C8\u306E package.json.name \u304B\u3089\u53D6\u5F97\u3057\u307E\u3059\u3002\u65E7 projectName \u4E0A\u66F8\u304D\u5F15\u6570\u3092\u524A\u9664\u3057\u3066\u304F\u3060\u3055\u3044\u3002",
|
|
287
293
|
deploy_requestAccessInvalid: "\u30EA\u30AF\u30A8\u30B9\u30C8\u30A2\u30AF\u30BB\u30B9\u8A2D\u5B9A\uFF08{field}\uFF09\u304C\u7121\u52B9\u3067\u3059\u3002\u30D5\u30A3\u30FC\u30EB\u30C9\u3001IP\u3001\u30BF\u30A4\u30E0\u30BE\u30FC\u30F3\u3001\u6642\u9593\u5E2F\u3092\u78BA\u8A8D\u3057\u3066\u304F\u3060\u3055\u3044\u3002\u30D5\u30A1\u30A4\u30EB\u306F\u8AAD\u307F\u53D6\u308A\u53EF\u80FD\u306A 1 MiB \u4EE5\u4E0B\u306E YAML \u3092\u6307\u5B9A\u3057\u3001\u4FEE\u6B63\u5F8C\u306B\u518D\u30D1\u30C3\u30B1\u30FC\u30B8\u3057\u3066\u304F\u3060\u3055\u3044\u3002",
|
|
288
294
|
deploy_httpsPortsInvalid: "HTTP \u3068 HTTPS \u306E\u30DD\u30FC\u30C8\u306F\u7570\u306A\u308B\u5FC5\u8981\u304C\u3042\u308A\u307E\u3059\u3002Let\u2019s Encrypt HTTP-01 \u306B\u306F\u30DB\u30B9\u30C8\u306E\u30DD\u30FC\u30C8 80 \u304C\u5FC5\u8981\u3067\u3059\u3002",
|
|
289
|
-
deploy_httpsCertificateInvalid: "HTTPS \u8A3C\u660E\u66F8\u304C\u7121\u52B9\u3067\u3059\u3002PEM \u30D5\u30A1\u30A4\u30EB\u3001\u6697\u53F7\u5316\u3055\u308C\u3066\u3044\u306A\u3044\u79D8\u5BC6\u9375\u3068\u306E\u4E00\u81F4\u3001\u6709\u52B9\u671F\u9593\u3001\u30C9\u30E1\u30A4\u30F3\u3092\u78BA\u8A8D\u3057\u3001\u518D\u4F5C\u6210\u3057\u3066\u304F\u3060\u3055\u3044\u3002"
|
|
295
|
+
deploy_httpsCertificateInvalid: "HTTPS \u8A3C\u660E\u66F8\u304C\u7121\u52B9\u3067\u3059\u3002PEM \u30D5\u30A1\u30A4\u30EB\u3001\u6697\u53F7\u5316\u3055\u308C\u3066\u3044\u306A\u3044\u79D8\u5BC6\u9375\u3068\u306E\u4E00\u81F4\u3001\u6709\u52B9\u671F\u9593\u3001\u30C9\u30E1\u30A4\u30F3\u3092\u78BA\u8A8D\u3057\u3001\u518D\u4F5C\u6210\u3057\u3066\u304F\u3060\u3055\u3044\u3002",
|
|
296
|
+
deploy_bundleRuntime: "\u5B9F\u884C\u8A2D\u5B9A\u306E\u5909\u66F4\u3068\u53CD\u6620\uFF1A\n\u4ECA\u56DE\u306E\u914D\u5099\u8A18\u9332\uFF1A{directory}/releases/{deploymentId}\nNode \u30D0\u30C3\u30AF\u30A8\u30F3\u30C9\u306F /run/hai/.env.runtime \u306B\u5B9F\u969B\u306B\u30DE\u30A6\u30F3\u30C8\u3055\u308C\u305F\u30D5\u30A1\u30A4\u30EB\u3092\u8AAD\u307F\u307E\u3059\u3002\u5DEE\u5206\u914D\u5099\u3067\u306F\u53E4\u3044\u8A18\u9332\u3092\u53C2\u7167\u3059\u308B\u305F\u3081 current \u3060\u3051\u3067\u306F\u5224\u5B9A\u3067\u304D\u307E\u305B\u3093\u3002docker inspect --format '{{json .Mounts}}' <\u30B3\u30F3\u30C6\u30CA\u540D> \u306E Source \u3092\u78BA\u8A8D\u3057\u3066\u304F\u3060\u3055\u3044\u3002\n\u901A\u5E38\u306E\u30D0\u30C3\u30AF\u30A8\u30F3\u30C9\u8A2D\u5B9A\u306F\u30D0\u30C3\u30AF\u30A2\u30C3\u30D7\u5F8C\u306B\u7DE8\u96C6\u3057\u3001docker restart <\u30B3\u30F3\u30C6\u30CA\u540D>\uFF08Podman \u3082\u540C\u69D8\uFF09\u3067\u53CD\u6620\u3057\u3066\u30D8\u30EB\u30B9\u3068\u696D\u52D9\u3092\u78BA\u8A8D\u3057\u307E\u3059\u3002HAI \u89AA\u8A2D\u5B9A\u3068 middleware.env \u306E\u7BA1\u7406\u63A5\u7D9A\u304C\u512A\u5148\u3057\u307E\u3059\u3002\nCompose env_file \u306E\u9759\u7684 Web\u30FB\u30DF\u30C9\u30EB\u30A6\u30A7\u30A2\u8A2D\u5B9A\u306F\u30B3\u30F3\u30C6\u30CA\u518D\u4F5C\u6210\u3001\u30DD\u30FC\u30C8\u30FB\u30DE\u30A6\u30F3\u30C8\u30FBNginx \u7D4C\u8DEF/\u4E0A\u9650\u30FBHTTPS \u69CB\u6210\u306F\u65B0\u3057\u3044\u5168\u91CF\u914D\u5099\u304C\u5FC5\u8981\u3067\u3059\u3002\u30B5\u30A4\u30C8 base \u306E\u5909\u66F4\u306F\u5236\u54C1\u3082\u518D\u69CB\u7BC9\u3057\u307E\u3059\u3002\n\u6052\u4E45\u7684\u306A\u5909\u66F4\u306F\u5143\u306E\u74B0\u5883\u3078\u623B\u3057\u3066\u304F\u3060\u3055\u3044\u3002\u6B21\u56DE\u914D\u5099\u3067\u30D5\u30A1\u30A4\u30EB\u304C\u518D\u751F\u6210\u3055\u308C\u307E\u3059\u3002",
|
|
297
|
+
deploy_bundleHttpOnly: "HTTPS\uFF1A\u7121\u52B9\u3002HTTP \u30DD\u30FC\u30C8 {port} \u306E\u307F\u3092\u516C\u958B\u3057\u3001\u8A3C\u660E\u66F8\u306F\u540C\u68B1\u305B\u305A\u3001\u30B5\u30FC\u30D0\u30FC\u3067\u3082\u7533\u8ACB\u3057\u307E\u305B\u3093\u3002",
|
|
298
|
+
deploy_bundleHttps: "HTTPS\uFF1A\u6709\u52B9\u3001https://{domain}:{port}\u3001\u30E2\u30FC\u30C9 {mode}\u3002\n\u30B5\u30FC\u30D0\u30FC\u8A3C\u660E\u66F8\uFF1A{certificates}/fullchain.pem\u3001\u79D8\u5BC6\u9375\uFF1A{certificates}/privkey.pem\u3002\u30B3\u30F3\u30C6\u30CA\u306E /etc/nginx/tls/ \u306B\u8AAD\u307F\u53D6\u308A\u5C02\u7528\u3067\u30DE\u30A6\u30F3\u30C8\u3057\u307E\u3059\u3002\n\u914D\u5E03\u5143 .env.{environment}.local \u306E HAI_DEPLOY_PROVIDER \u5185 expose.https\u3001\u307E\u305F\u306F\u4E0A\u66F8\u304D\u3055\u308C\u3066\u3044\u306A\u3044 hai.json.deploy.provider.expose.https \u3092\u7DE8\u96C6\u3057\u307E\u3059\u3002\u6709\u52B9/\u7121\u52B9\u3001\u30E2\u30FC\u30C9\u3001\u30C9\u30E1\u30A4\u30F3\u3001\u30DD\u30FC\u30C8\u5909\u66F4\u306F\u65B0\u3057\u3044\u5168\u91CF\u914D\u5099\u304C\u5FC5\u8981\u3067\u3059\u3002.env.runtime \u306E\u7DE8\u96C6\u3068\u518D\u8D77\u52D5\u3067\u306F\u65B0\u30C9\u30E1\u30A4\u30F3\u306E\u8A3C\u660E\u66F8\u3092\u7533\u8ACB\u3057\u307E\u305B\u3093\u3002",
|
|
299
|
+
deploy_bundleAcme: "Certbot \u6C38\u7D9A\u72B6\u614B\uFF1A{state}\u3001\u73FE\u5728\u306E\u8A3C\u660E\u66F8\u5165\u53E3\uFF1A{state}/live/{domain}\u3002\u30D1\u30C3\u30B1\u30FC\u30B8\u6642\u306F CA \u306B\u63A5\u7D9A\u305B\u305A\u3001\u30B5\u30FC\u30D0\u30FC\u914D\u5099\u6642\u306B\u7533\u8ACB\u3057\u3001\u305D\u306E\u5F8C\u81EA\u52D5\u66F4\u65B0\u3057\u307E\u3059\u3002\u516C\u958B\u30DD\u30FC\u30C8 80 \u3068\u30EB\u30FC\u30C8 /.well-known/acme-challenge/ \u306F\u696D\u52D9 context path \u3068\u5225\u306B\u5230\u9054\u53EF\u80FD\u306B\u3057\u3066\u304F\u3060\u3055\u3044\u3002",
|
|
300
|
+
deploy_bundleAccounts: "\u521D\u671F\u30A2\u30AB\u30A6\u30F3\u30C8\u5909\u6570\uFF08\u540D\u524D\u3068\u53D6\u5F97\u5143\u306E\u307F\u3001\u30D1\u30B9\u30EF\u30FC\u30C9\u975E\u8868\u793A\uFF09\uFF1A\n{sources}\n\u5BFE\u5FDC\u3059\u308B\u521D\u671F\u5316\u3092\u6301\u3064\u30A2\u30D7\u30EA\u3067\u306F HAI_CONFIG_ADMIN_PASSWORD \u304C config_admin \u8A2D\u5B9A\u7BA1\u7406\u8005\u3092\u4F5C\u6210\u3057\u307E\u3059\u3002HAI_ADMIN_DEFAULT_PASSWORD\u3001HAI_AUDIT_ADMIN_PASSWORD\u3001HAI_BUSINESS_OPERATOR_PASSWORD \u306F\u4ED6\u306E\u30C6\u30F3\u30D7\u30EC\u30FC\u30C8\u5F79\u5272\u306B\u5BFE\u5FDC\u3057\u307E\u3059\u3002\nFullstack \u4F5C\u6210\u6642\u306B\u74B0\u5883\u3054\u3068\u306E\u72EC\u7ACB\u521D\u671F\u30D1\u30B9\u30EF\u30FC\u30C9\u3092\u751F\u6210\u3057\u3001\u914D\u5E03\u6642\u306F\u9078\u629E\u74B0\u5883\u3068\u30D7\u30ED\u30BB\u30B9\u4E0A\u66F8\u304D\u3092\u8AAD\u307F\u307E\u3059\u3002\u30B5\u30FC\u30D0\u30FC\u914D\u5099\u3067\u65B0\u305F\u306B\u751F\u6210\u3057\u307E\u305B\u3093\u3002\u8A2D\u5B9A\u304C\u3042\u308B\u672A\u4F5C\u6210\u30A2\u30AB\u30A6\u30F3\u30C8\u3092\u8D77\u52D5\u6642\u306B\u4F5C\u308A\u3001\u65E2\u5B58\u306E\u30D1\u30B9\u30EF\u30FC\u30C9\u3084\u5909\u66F4\u5F8C\u306E\u5F79\u5272\u306F\u5909\u6570\u5909\u66F4\u3067\u623B\u3057\u307E\u305B\u3093\u3002\u72EC\u81EA\u30A2\u30D7\u30EA\u306F\u5B9F\u88C5\u306B\u5F93\u3044\u307E\u3059\u3002",
|
|
301
|
+
deploy_bundleDirectories: "\u30B5\u30FC\u30D0\u30FC\u30C7\u30A3\u30EC\u30AF\u30C8\u30EA\uFF08\u30EB\u30FC\u30C8 {directory}\uFF09\uFF1A\nincoming/\uFF1A\u30A2\u30C3\u30D7\u30ED\u30FC\u30C9\u3068 .contents \u5C55\u958B\u5148\u3002\u6210\u529F\u6642\u306B\u4ECA\u56DE\u5206\u3092\u524A\u9664\u3057\u3001\u5931\u6557\u30FB\u5B9F\u884C\u4E0D\u660E\u6642\u306F\u8ABF\u67FB\u7528\u306B\u4FDD\u6301\u3057\u307E\u3059\u3002\nreleases/{deploymentId}/\uFF1A\u5B9F\u884C\u30D5\u30A1\u30A4\u30EB\u3068\u5FA9\u65E7\u8A18\u9332\u3002images/ \u306F\u30B3\u30D4\u30FC\u305B\u305A\u30A4\u30E1\u30FC\u30B8\u306F\u30B3\u30F3\u30C6\u30CA\u30A8\u30F3\u30B8\u30F3\u3001DB\u30FB\u30AA\u30D6\u30B8\u30A7\u30AF\u30C8\u30C7\u30FC\u30BF\u306F\u30DC\u30EA\u30E5\u30FC\u30E0\u306B\u4FDD\u5B58\u3057\u307E\u3059\u3002\ncompose.json \u306F\u30B5\u30FC\u30D3\u30B9\u5B9A\u7FA9\u3001compose-entry.json\u30FBproxy-entry.json\u30FBcompose-files \u306F\u5168\u91CF/\u5DEE\u5206\u3068\u30D7\u30ED\u30AD\u30B7\u4E0A\u66F8\u304D\u306E\u7D44\u5408\u305B\u3067\u3059\u3002\n.env.runtime\u30FBmiddleware.env\u30FBmiddleware-runtime.env\u30FBruntime-env.mjs \u306F\u74B0\u5883\u3001web.conf \u306F\u30D7\u30ED\u30AD\u30B7\u3001request-access.yml \u306F\u691C\u8A3C\u6E08\u307F\u30DD\u30EA\u30B7\u30FC\u3067\u3059\u3002\nmanifest.json\u30FBimage-list\u30FBservices\u30FBdependencies\u30FBlayout\u30FBweb-base-path\u30FBstorage-routing\u30FBhealth-paths \u306F\u5236\u54C1/\u4F9D\u5B58/\u30D7\u30ED\u30FC\u30D6\u3001apply.sh\u30FBresolve-*.sh \u306F\u914D\u5099\u3068\u72B6\u614B\u691C\u8A3C\u3001SHA256SUMS \u306F\u914D\u5E03\u6574\u5408\u6027\u7528\u3067\u3059\u3002\nmanaged-*\u30FBstate-backends \u306F\u5019\u88DC\u8CC7\u683C\u60C5\u5831\u3068\u30DC\u30EA\u30E5\u30FC\u30E0/\u30D0\u30C3\u30AF\u30A8\u30F3\u30C9\u306E\u5BFE\u5FDC\u3067\u3059\u3002\u30EB\u30FC\u30C8 managed-secrets.env \u306F\u6C38\u7D9A\u8CC7\u683C\u60C5\u5831\u3001persistent-backends \u306F\u53F0\u5E33\u3067\u3001\u30C7\u30FC\u30BF\u30DC\u30EA\u30E5\u30FC\u30E0\u3068\u4E00\u7DD2\u306B\u30D0\u30C3\u30AF\u30A2\u30C3\u30D7\u3057\u307E\u3059\u3002\ncurrent \u306F\u6700\u5F8C\u306B\u30B5\u30FC\u30D0\u30FC\u5185\u3067\u6210\u529F\u3057\u305F ID \u306E\u30C6\u30AD\u30B9\u30C8\u30D5\u30A1\u30A4\u30EB\u3067\u3059\u3002result-{deploymentId}.json \u306E stage/exitCode/recoveryStatus \u3068 steps-{deploymentId}.jsonl \u3092\u78BA\u8A8D\u3057\u3001release \u306E\u5B58\u5728\u3060\u3051\u3067\u6210\u529F\u3068\u5224\u65AD\u3057\u307E\u305B\u3093\u3002\n\u5DEE\u5206\u69CB\u6210\u3068\u5B9F\u884C\u30B3\u30F3\u30C6\u30CA\u306F\u53E4\u3044 release \u3092\u53C2\u7167\u3067\u304D\u307E\u3059\u3002\u6574\u7406\u524D\u306B\u5168 Mounts \u3068 compose-files \u3092\u78BA\u8A8D\u3057\u3001current \u4EE5\u5916\u3092\u4E00\u5F8B\u524A\u9664\u3057\u306A\u3044\u3067\u304F\u3060\u3055\u3044\u3002"
|
|
290
302
|
};
|
|
291
303
|
|
|
292
304
|
// messages/zh-CN.json
|
|
@@ -396,7 +408,13 @@ var zh_CN_default = {
|
|
|
396
408
|
deploy_projectNameOverrideRemoved: "\u90E8\u7F72\u9879\u76EE\u540D\u7EDF\u4E00\u6765\u81EA\u5DE5\u7A0B\u6839 package.json.name\uFF1B\u8BF7\u79FB\u9664\u65E7 projectName \u8986\u76D6\u53C2\u6570\u3002",
|
|
397
409
|
deploy_requestAccessInvalid: "\u8BF7\u6C42\u8BBF\u95EE\u7B56\u7565\u914D\u7F6E\u65E0\u6548\uFF08{field}\uFF09\u3002\u8BF7\u68C0\u67E5\u5B57\u6BB5\u3001IP\u3001\u65F6\u533A\u53CA\u65F6\u95F4\u7A97\u53E3\uFF1B\u5982\u5F15\u7528\u6587\u4EF6\uFF0C\u8BF7\u786E\u8BA4\u6587\u4EF6\u53EF\u8BFB\u3001\u683C\u5F0F\u4E3A YAML \u4E14\u4E0D\u8D85\u8FC7 1 MiB\u3002\u4FEE\u6B63\u540E\u91CD\u65B0\u6253\u5305\u3002",
|
|
398
410
|
deploy_httpsPortsInvalid: "HTTP \u4E0E HTTPS \u7AEF\u53E3\u5FC5\u987B\u4E0D\u540C\uFF1BLet\u2019s Encrypt \u7684 HTTP-01 \u5165\u53E3\u5FC5\u987B\u4F7F\u7528\u5BBF\u4E3B\u673A 80 \u7AEF\u53E3\u3002",
|
|
399
|
-
deploy_httpsCertificateInvalid: "HTTPS \u8BC1\u4E66\u65E0\u6548\uFF1A\u8BF7\u6838\u5BF9 PEM \u6587\u4EF6\u53EF\u8BFB\u3001\u8BC1\u4E66\u4E0E\u672A\u52A0\u5BC6\u79C1\u94A5\u5339\u914D\u3001\u8BC1\u4E66\u6709\u6548\u671F\u53CA\u57DF\u540D\uFF0C\u7136\u540E\u91CD\u65B0\u6253\u5305\u3002"
|
|
411
|
+
deploy_httpsCertificateInvalid: "HTTPS \u8BC1\u4E66\u65E0\u6548\uFF1A\u8BF7\u6838\u5BF9 PEM \u6587\u4EF6\u53EF\u8BFB\u3001\u8BC1\u4E66\u4E0E\u672A\u52A0\u5BC6\u79C1\u94A5\u5339\u914D\u3001\u8BC1\u4E66\u6709\u6548\u671F\u53CA\u57DF\u540D\uFF0C\u7136\u540E\u91CD\u65B0\u6253\u5305\u3002",
|
|
412
|
+
deploy_bundleRuntime: "\u8FD0\u884C\u914D\u7F6E\u4E0E\u751F\u6548\uFF1A\n\u672C\u6B21\u53D1\u5E03\u8BB0\u5F55\uFF1A{directory}/releases/{deploymentId}\nNode \u540E\u7AEF\u8BFB\u53D6\u5B9E\u9645\u6302\u8F7D\u5230 /run/hai/.env.runtime \u7684\u6587\u4EF6\uFF1B\u589E\u91CF\u90E8\u7F72\u53EF\u80FD\u7EE7\u7EED\u5F15\u7528\u65E7\u8BB0\u5F55\uFF0C\u4E0D\u80FD\u53EA\u6309 current \u63A8\u65AD\u3002\u7528 docker inspect --format '{{json .Mounts}}' <\u5BB9\u5668\u540D> \u67E5\u770B Source\u3002\n\u666E\u901A\u540E\u7AEF\u914D\u7F6E\uFF1A\u5907\u4EFD\u3001\u4FEE\u6539\u8BE5\u6587\u4EF6\uFF0C\u7136\u540E docker restart <\u5BB9\u5668\u540D>\uFF08Podman \u540C\u7406\uFF09\uFF0C\u6838\u9A8C\u5065\u5EB7\u4E0E\u76F8\u5173\u4E1A\u52A1\u3002HAI \u7236\u5BF9\u8C61\u4F18\u5148\u4E8E\u53F6\u5B50\uFF0Cmiddleware.env \u7684\u6258\u7BA1\u8FDE\u63A5\u4F18\u5148\u3002\nCompose env_file \u6CE8\u5165\u7684\u9759\u6001 Web/\u4E2D\u95F4\u4EF6\u73AF\u5883\u53D8\u66F4\u9700\u8981\u91CD\u5EFA\u5BB9\u5668\uFF1B\u7AEF\u53E3\u3001\u6302\u8F7D\u3001Nginx \u8DEF\u7531/\u9650\u989D\u3001HTTPS \u5E03\u5C40\u9700\u8981\u91CD\u65B0\u751F\u6210\u5168\u91CF\u90E8\u7F72\u5305\u3002\u7F51\u7AD9 base \u53D8\u5316\u8FD8\u9700\u8981\u91CD\u65B0\u6784\u5EFA\u5236\u54C1\u3002\n\u624B\u5DE5\u4FEE\u6539\u540C\u6B65\u56DE\u6253\u5305\u6E90\u73AF\u5883\uFF1B\u4E0B\u6B21\u53D1\u5E03\u4F1A\u91CD\u65B0\u751F\u6210\u3002",
|
|
413
|
+
deploy_bundleHttpOnly: "HTTPS\uFF1A\u672A\u542F\u7528\u3002\u672C\u5305\u4EC5\u53D1\u5E03 HTTP \u7AEF\u53E3 {port}\uFF0C\u6CA1\u6709\u8BC1\u4E66\u9644\u4EF6\uFF0C\u4E5F\u4E0D\u4F1A\u5728\u670D\u52A1\u5668\u7533\u8BF7\u8BC1\u4E66\u3002",
|
|
414
|
+
deploy_bundleHttps: "HTTPS\uFF1A\u5DF2\u542F\u7528\uFF0Chttps://{domain}:{port}\uFF1B\u6A21\u5F0F {mode}\u3002\n\u670D\u52A1\u5668\u8BC1\u4E66\uFF1A{certificates}/fullchain.pem\uFF1B\u79C1\u94A5\uFF1A{certificates}/privkey.pem\u3002\u5BB9\u5668\u53EA\u8BFB\u6302\u8F7D\u5230 /etc/nginx/tls/\u3002\n\u4FEE\u6539\u672C\u5730\u6253\u5305\u73AF\u5883 .env.{environment}.local \u7684 HAI_DEPLOY_PROVIDER \u4E2D expose.https\uFF0C\u6216\u672A\u88AB\u8986\u76D6\u7684 hai.json.deploy.provider.expose.https\u3002\u542F\u505C\u3001\u5207\u6362\u6A21\u5F0F/\u57DF\u540D/\u7AEF\u53E3\u540E\u751F\u6210\u65B0\u7684\u5168\u91CF\u90E8\u7F72\u5305\uFF1B\u4FEE\u6539 .env.runtime \u5E76\u91CD\u542F\u4E0D\u80FD\u89E6\u53D1\u65B0\u57DF\u540D\u7B7E\u53D1\u3002",
|
|
415
|
+
deploy_bundleAcme: "Certbot \u6301\u4E45\u72B6\u6001\uFF1A{state}\uFF1B\u5F53\u524D\u8BC1\u4E66\u5165\u53E3\uFF1A{state}/live/{domain}\u3002\u6253\u5305\u4E0D\u8BF7\u6C42 CA\uFF0C\u670D\u52A1\u5668\u90E8\u7F72\u65F6\u7533\u8BF7\uFF0C\u4E4B\u540E\u81EA\u52A8\u7EED\u671F\u3002\u516C\u7F51 80 \u7AEF\u53E3\u53CA\u6839\u8DEF\u5F84 /.well-known/acme-challenge/ \u5FC5\u987B\u53EF\u8FBE\uFF0C\u4E0D\u80FD\u53EA\u5141\u8BB8\u4E1A\u52A1 context path\u3002",
|
|
416
|
+
deploy_bundleAccounts: "\u521D\u59CB\u8D26\u53F7\u53D8\u91CF\uFF08\u53EA\u5217\u540D\u79F0\u548C\u6765\u6E90\uFF0C\u4E0D\u663E\u793A\u5BC6\u7801\uFF09\uFF1A\n{sources}\nHAI_CONFIG_ADMIN_PASSWORD \u4F9B\u6709\u76F8\u5E94\u5F15\u5BFC\u903B\u8F91\u7684\u5E94\u7528\u521B\u5EFA config_admin \u914D\u7F6E\u7BA1\u7406\u5458\uFF1BHAI_ADMIN_DEFAULT_PASSWORD\u3001HAI_AUDIT_ADMIN_PASSWORD\u3001HAI_BUSINESS_OPERATOR_PASSWORD \u5BF9\u5E94\u5176\u4ED6\u6A21\u677F\u804C\u8D23\u8D26\u53F7\u3002\nCLI \u521B\u5EFA Fullstack \u65F6\u4E3A\u5404\u73AF\u5883\u751F\u6210\u72EC\u7ACB\u521D\u59CB\u5BC6\u7801\uFF1B\u6253\u5305\u8BFB\u53D6\u6240\u9009\u73AF\u5883\u4E0E\u8FDB\u7A0B\u8986\u76D6\uFF0C\u4E0D\u4F1A\u56E0\u670D\u52A1\u5668\u90E8\u7F72\u518D\u751F\u6210\u5E94\u7528\u8D26\u53F7\u5BC6\u7801\u3002\u6709\u914D\u7F6E\u4E14\u8D26\u53F7\u7F3A\u5931\u65F6\u7531\u5E94\u7528\u542F\u52A8\u5F15\u5BFC\uFF1B\u5DF2\u6709\u8D26\u53F7\u4E0D\u4F1A\u56E0\u4FEE\u6539\u53D8\u91CF\u91CD\u7F6E\u5BC6\u7801\u6216\u6062\u590D\u65E7\u804C\u8D23\u3002\u65E0\u76F8\u5E94\u5F15\u5BFC\u903B\u8F91\u7684\u81EA\u5B9A\u4E49\u5E94\u7528\u4EE5\u81EA\u8EAB\u5B9E\u73B0\u4E3A\u51C6\u3002",
|
|
417
|
+
deploy_bundleDirectories: "\u670D\u52A1\u5668\u76EE\u5F55\u8BF4\u660E\uFF08\u6839\u76EE\u5F55 {directory}\uFF09\uFF1A\nincoming/\uFF1A\u4E0A\u4F20\u5F52\u6863\u548C .contents \u89E3\u5305\u76EE\u5F55\uFF1B\u6210\u529F\u540E\u6E05\u7406\u672C\u6B21\u5185\u5BB9\uFF0C\u5931\u8D25\u6216\u6267\u884C\u672A\u77E5\u65F6\u4FDD\u7559\u6392\u969C\u8BC1\u636E\u3002\nreleases/{deploymentId}/\uFF1A\u672C\u6B21\u8FD0\u884C\u6587\u4EF6\u548C\u6062\u590D\u8BB0\u5F55\uFF1B\u4E0D\u590D\u5236 images/\uFF0C\u955C\u50CF\u5BFC\u5165\u5BB9\u5668\u5F15\u64CE\uFF0C\u6570\u636E\u5E93\u548C\u5BF9\u8C61\u6570\u636E\u4FDD\u5B58\u5728\u6570\u636E\u5377\u3002\ncompose.json \u662F\u670D\u52A1\u5B9A\u4E49\uFF1Bcompose-entry.json\u3001proxy-entry.json\u3001compose-files \u7EC4\u5408\u5168\u91CF/\u589E\u91CF\u53CA\u4EE3\u7406\u8986\u76D6\u3002\n.env.runtime\u3001middleware.env\u3001middleware-runtime.env\u3001runtime-env.mjs \u8D1F\u8D23\u5E94\u7528\u4E0E\u4E2D\u95F4\u4EF6\u73AF\u5883\uFF1Bweb.conf \u662F\u4EE3\u7406\uFF0Crequest-access.yml \u662F\u6821\u9A8C\u540E\u7684\u7B56\u7565\u5FEB\u7167\u3002\nmanifest.json\u3001image-list\u3001services\u3001dependencies\u3001layout\u3001web-base-path\u3001storage-routing\u3001health-paths \u662F\u5236\u54C1\u3001\u4F9D\u8D56\u548C\u63A2\u6D3B\u5143\u6570\u636E\uFF1Bapply.sh\u3001resolve-*.sh \u6267\u884C\u53D1\u5E03\u53CA\u72B6\u6001\u6838\u9A8C\uFF1BSHA256SUMS \u6821\u9A8C\u4EA4\u4ED8\u5185\u5BB9\u3002\nmanaged-*\u3001state-backends \u63CF\u8FF0\u672C\u5305\u7684\u51ED\u636E\u5019\u9009\u548C\u5377/\u540E\u7AEF\u7ED1\u5B9A\u3002\u6839\u76EE\u5F55 managed-secrets.env \u662F\u670D\u52A1\u5668\u957F\u671F\u51ED\u636E\uFF0Cpersistent-backends \u662F\u957F\u671F\u540E\u7AEF\u8D26\u672C\uFF0C\u987B\u4E0E\u6570\u636E\u5377\u6210\u5957\u5907\u4EFD\u3002\ncurrent \u662F\u6700\u540E\u670D\u52A1\u5668\u672C\u5730\u6210\u529F\u53D1\u5E03 ID \u7684\u666E\u901A\u6587\u672C\u6587\u4EF6\uFF1B\u67E5\u770B result-{deploymentId}.json \u7684 stage/exitCode/recoveryStatus \u548C steps-{deploymentId}.jsonl \u5224\u65AD\u672C\u6B21\u7ED3\u679C\u3002\u4EC5\u51FA\u73B0 release \u76EE\u5F55\u4E0D\u4EE3\u8868\u6210\u529F\u3002\n\u589E\u91CF\u90E8\u7F72\u548C\u8FD0\u884C\u5BB9\u5668\u53EF\u80FD\u5F15\u7528\u65E7 release\uFF1B\u6E05\u7406\u524D\u6838\u5BF9\u6240\u6709\u6D3B\u52A8\u6302\u8F7D\u548C compose-files\uFF0C\u4E0D\u80FD\u53EA\u4FDD\u7559 current\u3002"
|
|
400
418
|
};
|
|
401
419
|
|
|
402
420
|
// src/deploy-i18n.ts
|
|
@@ -639,6 +657,13 @@ function mergeEnvironmentLayers(layers, prefix) {
|
|
|
639
657
|
}
|
|
640
658
|
return result;
|
|
641
659
|
}
|
|
660
|
+
function describeDeploymentVariableSources(directory, environment, values, names) {
|
|
661
|
+
const files = [`.env.${environment}.local`, ".env.local", `.env.${environment}`, ".env"].map((name) => ({ path: join(directory, name), values: environmentFile(join(directory, name)) }));
|
|
662
|
+
return names.filter((name) => values[name]).map((name) => {
|
|
663
|
+
const source = process6.env[name] !== void 0 ? "process.env" : files.find((file) => Object.hasOwn(file.values, name))?.path;
|
|
664
|
+
return `${name}: ${source ?? ".env.runtime"}`;
|
|
665
|
+
}).join("\n");
|
|
666
|
+
}
|
|
642
667
|
function loadDeploymentConfig(name, path, values) {
|
|
643
668
|
try {
|
|
644
669
|
const content = readFileSync(path, "utf8");
|
|
@@ -3509,8 +3534,18 @@ async function createDeploymentBundle(options) {
|
|
|
3509
3534
|
const selection = deployM("deploy_bundleSelection", { params: { mode, services: selected.join(", ") } });
|
|
3510
3535
|
const instructions = `${selection}
|
|
3511
3536
|
${deployM("deploy_bundleInstructions", { params: instructionParams })}`;
|
|
3537
|
+
const runtimeGuide = deployM("deploy_bundleRuntime", { params: { directory: `${config.remote.baseDir}/${projectName}`, deploymentId: options.deploymentId } });
|
|
3538
|
+
const https = config.expose.https;
|
|
3539
|
+
const serverDirectory = `${config.remote.baseDir}/${projectName}`;
|
|
3540
|
+
const certificates = https?.type === "files" ? `${serverDirectory}/releases/${options.deploymentId}/tls` : `${serverDirectory}/https/certificates/${https?.domain}`;
|
|
3541
|
+
const httpsGuide = https ? deployM("deploy_bundleHttps", { params: { domain: https.domain, port: https.port, mode: https.type, certificates, environment } }) + (https.type === "letsencrypt" ? `
|
|
3542
|
+
${deployM("deploy_bundleAcme", { params: { state: `${serverDirectory}/https/acme`, domain: https.domain } })}` : "") : deployM("deploy_bundleHttpOnly", { params: { port: config.expose.hostPort } });
|
|
3543
|
+
const accountGuide = deployM("deploy_bundleAccounts", { params: { sources: options.accountSources || "\u2014" } });
|
|
3544
|
+
const guides = [runtimeGuide, httpsGuide, accountGuide, deployM("deploy_bundleDirectories", { params: { directory: serverDirectory, deploymentId: options.deploymentId } })].join("\n\n");
|
|
3512
3545
|
const readme = `${deployM("deploy_bundleMetadata", { params: { version: artifact.appVersion, buildId: artifact.buildId, deploymentId: options.deploymentId, compose: "compose.json" } })}
|
|
3513
3546
|
${instructions}
|
|
3547
|
+
|
|
3548
|
+
${guides}
|
|
3514
3549
|
`;
|
|
3515
3550
|
const checksums = [];
|
|
3516
3551
|
for (const file of files)
|
|
@@ -3561,6 +3596,7 @@ ${instructions}
|
|
|
3561
3596
|
rmSync(join(directory, file), { force: true });
|
|
3562
3597
|
return { bundlePath: output, instructions: `${selection}
|
|
3563
3598
|
${deployM("deploy_bundleInstructions", { params: { ...instructionParams, file: output } })}
|
|
3599
|
+
${guides}
|
|
3564
3600
|
${scripts}`, startName: "apply.sh" };
|
|
3565
3601
|
} finally {
|
|
3566
3602
|
rmSync(staging, { recursive: true, force: true });
|
|
@@ -3752,6 +3788,15 @@ var IMAGES = {
|
|
|
3752
3788
|
smtp: "docker.io/axllent/mailpit:v1.27.4",
|
|
3753
3789
|
nginx: "docker.io/nginxinc/nginx-unprivileged:1.29.8-alpine"
|
|
3754
3790
|
};
|
|
3791
|
+
var PROCESS_ENV_KEYS = /* @__PURE__ */ new Set([
|
|
3792
|
+
"HAI_CORE_ENV",
|
|
3793
|
+
"HAI_CRYPTO_TRANSPORT_SERVERKEYRING",
|
|
3794
|
+
"HAI_ADMIN_DEFAULT_PASSWORD",
|
|
3795
|
+
"HAI_AUDIT_ADMIN_PASSWORD",
|
|
3796
|
+
"HAI_CONFIG_ADMIN_PASSWORD",
|
|
3797
|
+
"HAI_BUSINESS_OPERATOR_PASSWORD",
|
|
3798
|
+
"HAI_E2E"
|
|
3799
|
+
]);
|
|
3755
3800
|
var CONTAINER_ENV_KEYS = /* @__PURE__ */ new Set([
|
|
3756
3801
|
"POSTGRES_USER",
|
|
3757
3802
|
"POSTGRES_PASSWORD",
|
|
@@ -4149,7 +4194,7 @@ function generateWebProxyConfig(port, apiPrefix, options = {}) {
|
|
|
4149
4194
|
const webBasePath = options.webBasePath ?? "";
|
|
4150
4195
|
const apiPath = apiPrefix.replace(/\/+$/, "");
|
|
4151
4196
|
const backendPaths = [...new Set(options.backendPaths ?? ["/health"])];
|
|
4152
|
-
if (!/^\/[\w
|
|
4197
|
+
if (!/^\/[\w.-]+(?:\/[\w.-]+)*$/.test(apiPrefix) || apiPrefix.split("/").some((part) => part === "." || part === "..") || ![port, webPort].every((value) => Number.isInteger(value) && value >= 1 && value <= 65535) || backendPaths.includes(`${webBasePath}/`) || backendPaths.some((path) => !/^\/[\w./-]*$/.test(path) || path.includes("//") || path.split("/").some((part) => part === "." || part === "..") || path === `${webBasePath}/runtime-config.js` || path === "/_hai/web-health") || webBasePath && (backendPaths.includes(webBasePath) || webBasePath === apiPath || webBasePath.startsWith(`${apiPath}/`))) {
|
|
4153
4198
|
throw new Error("Invalid web proxy target");
|
|
4154
4199
|
}
|
|
4155
4200
|
const webLocation = renderWebLocation(webBasePath);
|
|
@@ -4314,8 +4359,19 @@ ${renderWebLocation(webBasePath)} location = ${webBasePath}/runtime-config.js {
|
|
|
4314
4359
|
}
|
|
4315
4360
|
`;
|
|
4316
4361
|
}
|
|
4317
|
-
function serializeEnvFile(env) {
|
|
4318
|
-
|
|
4362
|
+
function serializeEnvFile(env, overrides = {}) {
|
|
4363
|
+
const effective = { ...env, ...overrides };
|
|
4364
|
+
return `${Object.entries(env).filter(([name]) => {
|
|
4365
|
+
if (Object.hasOwn(overrides, name))
|
|
4366
|
+
return false;
|
|
4367
|
+
if (!name.startsWith("HAI_") || PROCESS_ENV_KEYS.has(name) || name.startsWith("HAI_E2E_"))
|
|
4368
|
+
return true;
|
|
4369
|
+
for (let at = name.indexOf("_", 4); at !== -1; at = name.indexOf("_", at + 1)) {
|
|
4370
|
+
if (Object.hasOwn(effective, name.slice(0, at)))
|
|
4371
|
+
return false;
|
|
4372
|
+
}
|
|
4373
|
+
return true;
|
|
4374
|
+
}).map(([key, value]) => {
|
|
4319
4375
|
let literal = value;
|
|
4320
4376
|
if (/[\s#$'"]/.test(value)) {
|
|
4321
4377
|
if (value.startsWith("{") || value.startsWith("["))
|
|
@@ -4357,7 +4413,7 @@ function prepareRequestAccess(options) {
|
|
|
4357
4413
|
var HEALTH_MAX_ATTEMPTS = 40;
|
|
4358
4414
|
function servicePath(value, fallback) {
|
|
4359
4415
|
const path = value ?? fallback;
|
|
4360
|
-
if (typeof path !== "string" || !/^\/[\w./-]*$/.test(path) || path.
|
|
4416
|
+
if (typeof path !== "string" || !/^\/[\w./-]*$/.test(path) || path.includes("//") || path.split("/").some((part) => part === "." || part === ".."))
|
|
4361
4417
|
throw new Error("Invalid service endpoint path");
|
|
4362
4418
|
return path;
|
|
4363
4419
|
}
|
|
@@ -4581,7 +4637,7 @@ function createDockerSshProvider(config, container) {
|
|
|
4581
4637
|
const http = server.data.http;
|
|
4582
4638
|
const cors = server.data.cors;
|
|
4583
4639
|
const apiPrefix = http?.apiPrefix ?? "/api/v1";
|
|
4584
|
-
if (typeof apiPrefix !== "string" || !/^\/[\w
|
|
4640
|
+
if (typeof apiPrefix !== "string" || !/^\/[\w.-]+(?:\/[\w.-]+)*$/.test(apiPrefix) || apiPrefix.split("/").some((part) => part === "." || part === "..")) {
|
|
4585
4641
|
return err(HaiDeployError.CONFIG_ERROR, deployM("deploy_webProxyInvalid"));
|
|
4586
4642
|
}
|
|
4587
4643
|
if (webBasePath && ([...backendPaths, "/_hai/web-health"].includes(webBasePath) || webBasePath === apiPrefix.replace(/\/+$/, "") || webBasePath.startsWith(`${apiPrefix.replace(/\/+$/, "")}/`)))
|
|
@@ -4631,7 +4687,17 @@ function createDockerSshProvider(config, container) {
|
|
|
4631
4687
|
mkdirSync(artifactDir, { mode: 448 });
|
|
4632
4688
|
chmodSync(artifactDir, 448);
|
|
4633
4689
|
const envPath = join(artifactDir, ".env.runtime");
|
|
4634
|
-
|
|
4690
|
+
const nodeRuntime = primaryService === "serv" || scan.isSvelteKit;
|
|
4691
|
+
const startupOverrides = nodeRuntime ? { NODE_OPTIONS: "", HAI_DEPLOY_PRIVATE_PROXY: "" } : {};
|
|
4692
|
+
const runtimeEnvironment = serializeEnvFile(env, { ...sidecar.env, ...startupOverrides });
|
|
4693
|
+
const middlewareEnv = serializeEnvFile(sidecar.env, Object.fromEntries(Object.entries(env).filter(([name2]) => !Object.hasOwn(sidecar.env, name2))));
|
|
4694
|
+
const envVarsSet = [.../* @__PURE__ */ new Set([
|
|
4695
|
+
...Object.keys(parseEnv(runtimeEnvironment)),
|
|
4696
|
+
...Object.keys(parseEnv(middlewareEnv)),
|
|
4697
|
+
...nodeRuntime ? ["NODE_OPTIONS"] : [],
|
|
4698
|
+
...hasWebProxy || gateway ? ["HAI_DEPLOY_PRIVATE_PROXY"] : []
|
|
4699
|
+
])];
|
|
4700
|
+
writeFileSync(envPath, runtimeEnvironment, { mode: 384 });
|
|
4635
4701
|
if (requestAccessSnapshot)
|
|
4636
4702
|
writeFileSync(join(artifactDir, "request-access.yml"), requestAccessSnapshot, { mode: 384 });
|
|
4637
4703
|
writeFileSync(join(artifactDir, "middleware-runtime.env"), serializeEnvFile(sidecar.containerEnv), { mode: 384 });
|
|
@@ -4652,7 +4718,7 @@ function createDockerSshProvider(config, container) {
|
|
|
4652
4718
|
containerPort,
|
|
4653
4719
|
primaryService,
|
|
4654
4720
|
requestAccessPolicy: requestAccessSnapshot !== void 0,
|
|
4655
|
-
nodeRuntime
|
|
4721
|
+
nodeRuntime,
|
|
4656
4722
|
nodeOptions: env.NODE_OPTIONS,
|
|
4657
4723
|
sidecar,
|
|
4658
4724
|
web: hasWebProxy ? { imageRef: web?.imageRef ?? "localhost/hai-unselected:0", containerPort: webContainerPort } : void 0,
|
|
@@ -4691,14 +4757,15 @@ function createDockerSshProvider(config, container) {
|
|
|
4691
4757
|
proxyService,
|
|
4692
4758
|
storageRouting,
|
|
4693
4759
|
containerPort,
|
|
4694
|
-
middlewareEnv
|
|
4760
|
+
middlewareEnv,
|
|
4761
|
+
accountSources: describeDeploymentVariableSources(options?.envDir ?? scan.envDir ?? appDir, options?.environment ?? "prod", env, ["HAI_ADMIN_DEFAULT_PASSWORD", "HAI_AUDIT_ADMIN_PASSWORD", "HAI_CONFIG_ADMIN_PASSWORD", "HAI_BUSINESS_OPERATOR_PASSWORD"]),
|
|
4695
4762
|
healthPaths,
|
|
4696
4763
|
httpsAssets,
|
|
4697
4764
|
output: join(artifactDir, `${name}.tar${compressed ? ".gz" : ""}`),
|
|
4698
4765
|
cacheDirectory: join(resolveProjectDirectory(appDir), ".hai", "cache", "images")
|
|
4699
4766
|
});
|
|
4700
4767
|
if (options?.bundleOnly)
|
|
4701
|
-
return ok({ url: "", deploymentId, status: "packaged", provider: "docker-ssh", healthCheck: "skipped", envVarsSet
|
|
4768
|
+
return ok({ url: "", deploymentId, status: "packaged", provider: "docker-ssh", healthCheck: "skipped", envVarsSet, ...bundle });
|
|
4702
4769
|
if (!ssh)
|
|
4703
4770
|
return err(HaiDeployError.CONFIG_ERROR, deployM("deploy_sshRequired"));
|
|
4704
4771
|
const ping = await ssh.ping();
|
|
@@ -4784,7 +4851,7 @@ ${terminal ? deployM("deploy_remoteFinished", { params: { stage: terminal.stage,
|
|
|
4784
4851
|
status: "ready",
|
|
4785
4852
|
provider: "docker-ssh",
|
|
4786
4853
|
healthCheck: "passed",
|
|
4787
|
-
envVarsSet
|
|
4854
|
+
envVarsSet,
|
|
4788
4855
|
bundlePath: bundle.bundlePath
|
|
4789
4856
|
};
|
|
4790
4857
|
logger5.info("docker-ssh deployment complete", { url: applicationUrl, deploymentId });
|