@h-ai/deploy 1.0.0-beta.4 → 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 +6 -0
- package/README.ja.md +6 -0
- package/README.md +6 -0
- 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,6 +239,10 @@ SSH interruptions initially report `remoteExecution: 'unknown'`. The docker-ssh
|
|
|
237
239
|
|
|
238
240
|
### Runtime environment files and repeated deployments
|
|
239
241
|
|
|
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
|
+
|
|
240
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.
|
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,6 +237,10 @@ SSH 中断は最初に `remoteExecution: 'unknown'` とし、docker-ssh SDK は
|
|
|
235
237
|
|
|
236
238
|
### 実行環境ファイルと設定の再利用
|
|
237
239
|
|
|
240
|
+
環境フラグ・初期アカウントパスワード・転送キーリングは起動コードも直接読み取るため、同じ接頭辞の親設定があっても保持します。
|
|
241
|
+
|
|
242
|
+
配布時には HAI 親変数で隠れるすべての子項目と、`middleware.env` が提供する `.env.runtime` の重複項目を除去します。コンテナ内パスは配布設定に保存し、この除去処理で元の環境は変更しません。残った親オブジェクトまたは管理接続ファイルを編集します。
|
|
243
|
+
|
|
238
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_*` 設定のみです。既存の原生変数は自動削除せず、新しいアプリ環境から除外します。未更新サービスは以前の配布ファイルを使い続けます。
|
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 冒充新构建。
|
|
@@ -263,6 +265,10 @@ SSH 中断始终先记 `remoteExecution: 'unknown'`。docker-ssh SDK 用新连
|
|
|
263
265
|
|
|
264
266
|
Node 后端(Serv / SvelteKit SSR)默认在每次启动时重读发布目录的 `.env.runtime`,修改后 `docker restart <容器名>` 或 `podman restart <容器名>` 即可,无需重建镜像或额外 override。旧部署先用新版 CLI 发布一次。删除的字段不会从旧 Compose 注入中复活;服务器托管连接的 `middleware.env` 保持原有更高优先级,私有代理标记和 Node 启动参数仍由部署装配管理。静态 Web、中间件、端口/挂载、Nginx 路由与限额不在该重载范围;改变网关路径、端口或挂载时使用全量部署。手工修改需备份;下一次后端发布会从工程环境重新生成,需要长期保留的配置同步回源环境。
|
|
265
267
|
|
|
268
|
+
同前缀但由进程直接读取的环境标记、初始账号密码和传输密钥环仍保留;它们不属于已被父对象替代的配置。
|
|
269
|
+
|
|
270
|
+
交付配置会清除所有被 `HAI_*` 父级变量遮蔽的子项,并从 `.env.runtime` 删除由 `middleware.env` 提供的重复项。容器内路径只保存在交付配置中;清理不会改写源环境。修改时以保留下来的父对象或托管连接文件为准。
|
|
271
|
+
|
|
266
272
|
框架持久配置使用 `HAI_*` 命名。`POSTGRES_*`、`MYSQL_*`、`RUSTFS_*`、`MINIO_*`、`LDAP_*` 是中间件镜像的原生协议,必须保留原名,但只生成到私有的 `middleware-runtime.env` 并由中间件容器加载;不再写入工程环境文件或应用的 `.env.runtime`。应用增量部署沿用的 `middleware.env` 仅保存框架 `HAI_*` 配置。旧工程已保存的这些原生字段不会被自动删除,新应用环境会忽略它们;新包与旧成功基线可共存,旧服务仍读取其原交付文件。
|
|
267
273
|
|
|
268
274
|
自建或云开通的整体 `HAI_*` 配置会清除被替换的旧叶字段,例如 Redis 覆盖后不再留下 `HAI_CACHE_TYPE=memory`。全局 `~/.hai/credentials.yml` 只补缺项,不能覆盖当前环境/进程的同名键或父配置。部署先启动选中中间件,等待 PostgreSQL/MySQL/Redis/S3 健康,再启动 serv/Web;增量和失败恢复沿用此顺序,未选容器保持不变。
|
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 });
|