@h-ai/deploy 1.0.0-beta.2 → 1.0.0-beta.4
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 +22 -8
- package/README.ja.md +23 -9
- package/README.md +24 -10
- package/dist/deploy-runtime-env.mjs +58 -0
- package/dist/index.d.ts +71 -4
- package/dist/index.js +540 -91
- package/dist/index.js.map +1 -1
- package/package.json +4 -4
package/README.en.md
CHANGED
|
@@ -22,14 +22,14 @@ Delivery roles are `serv` for a separate API backend, `web` for a static or SSR
|
|
|
22
22
|
|
|
23
23
|
```sh
|
|
24
24
|
pnpm build
|
|
25
|
-
pnpm build --target
|
|
26
|
-
pnpm build --target
|
|
25
|
+
pnpm build --target image
|
|
26
|
+
pnpm build --target image --images web
|
|
27
27
|
pnpm build --target desktop --platform windows --arch x64
|
|
28
28
|
```
|
|
29
29
|
|
|
30
30
|
#### Build options
|
|
31
31
|
|
|
32
|
-
`--target` selects compile (default),
|
|
32
|
+
`--target` selects compile (default), image, app or desktop. `--images serv|web|serv,web` selects images. `--runtime auto|podman|docker` selects the local engine; auto prefers reachable Podman. `--network` overrides build networking, `--no-http-proxy` disables inherited Podman proxies, and `--sqlite-prebuild-mirror` selects a trusted HTTP(S) binary mirror. Native `--platform` and `--arch` require the matching host SDK and Rust toolchain. Builds do not load deployment environments or runtime secrets.
|
|
33
33
|
|
|
34
34
|
#### Describe packaging in hai.json
|
|
35
35
|
|
|
@@ -85,7 +85,7 @@ The SDK generates matching Nginx paths, runtime configuration URLs, SSR health c
|
|
|
85
85
|
|
|
86
86
|
#### Prepare the environment and destination
|
|
87
87
|
|
|
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`. 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.
|
|
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
90
|
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
91
|
|
|
@@ -116,6 +116,8 @@ SSH settings are saved in `.env.<environment>.local`. `--bundle-only` offers to
|
|
|
116
116
|
|
|
117
117
|
Runtime lockfile dependencies and configuration determine middleware. Choose defaults, custom connections or keep settings. With complete target-environment settings, `--yes` preserves values without asking again or provisioning cloud resources again; interactive mode still lets you select the scope. --skip-middleware skips configuration/provisioning. SQLite, memory cache and local storage need no external images. Complete bundles automatically include self-hosted middleware images. External services still require reachable destinations; cloud provisioning is not an offline operation.
|
|
118
118
|
|
|
119
|
+
Default and custom modes preserve effective settings for the same backend, including pool, operation log, public storage URLs/prefixes, Redis retry and vector search options absent from the form. Managed services replace connection selectors and credentials; old URLs, TLS/cluster modes and credentials cannot override the new service. SMTP senders and LDAP attribute mappings remain. Switching backends clears incompatible fields. Missing fields already saved in parent JSON need recovery from the original configuration or backup: restore `publicEndpoint` in the highest-priority `HAI_STORAGE`, then rebuild and deploy the bundle. Editing YAML or leaf variables hidden by that parent JSON cannot repair an old bundle.
|
|
120
|
+
|
|
119
121
|
#### Direct private object storage access
|
|
120
122
|
|
|
121
123
|
Self-hosted S3 uses an internal endpoint. Set `_storage.yml` publicEndpoint to an external address such as `https://app.example.com/delivery/files`. Nginx exposes `/delivery/files/<bucket>/...`, removes the proxy directory and forwards the original bucket URI, signature query and Host directly to storage:9000. Files bypass Serv; omitting the directory retains root bucket routes. A route may sit under the website directory; API, asset and health conflicts fail packaging. Storage ports/consoles remain private, buffering/signature logs are disabled, and S3 handles authorization and cross-origin CORS. External ingress must retain the full entry path and Host so only the SDK gateway removes the prefix.
|
|
@@ -148,7 +150,7 @@ S3 `createBucket` defaults to `false`. Self-hosted S3 deployments set `HAI_STORA
|
|
|
148
150
|
pnpm run deploy --env prod --build --bundle-only
|
|
149
151
|
```
|
|
150
152
|
|
|
151
|
-
Each delivery creates one `.hai/deploy/<environment>/bundle-<project>-<deploymentId>-<version>/` directory containing only the tar, deploy.sh, deploy.ps1, deploy-target.json, read-target.awk, deploy-local.sh and README.txt. Compose, runtime environments, web.conf and manifest.json remain inside the tar; the external README also records the deployment ID. Copy that directory as a unit. Explicit `--output release-prod.tar` produces `release-prod-<version>/release-prod-<version>.tar` relative to the command directory, with all companion files alongside it. The tar includes selected application/middleware images, configurations, private environment files, checksums, README and apply.sh. Before running either upload script, open `deploy-target.json` in the operation directory and use its per-field descriptions to edit and check the server, SSH user and port, private key and known-hosts files, remote directory and other settings. Run deploy.ps1 on Windows or deploy.sh on Linux/macOS; both scripts read this JSON to upload over SSH and execute the same server workflow. Running deploy.sh locally requires sh, awk, ssh and scp. Use `sh deploy.sh HOST [PORT] [USER]` to override the connection address, or pass `-IdentityFile` to deploy.ps1 to override its private key. Both scripts support HAI_DEPLOY_IDENTITY_FILE and HAI_DEPLOY_KNOWN_HOSTS_FILE to override key and known-hosts paths. After moving to another computer or operating system, update these paths to files on that computer.
|
|
153
|
+
Each delivery creates one `.hai/deploy/<environment>/bundle-<project>-<deploymentId>-<version>/` directory containing only the tar, deploy.sh, deploy.ps1, deploy-target.json, read-target.awk, deploy-local.sh and README.txt. Compose, runtime environments, web.conf and manifest.json remain inside the tar; the external README also records the deployment ID. Copy that directory as a unit. Explicit `--output release-prod.tar` produces `release-prod-<version>/release-prod-<version>.tar.gz` relative to the command directory, with all companion files alongside it. The tar includes selected application/middleware images, configurations, private environment files, checksums, README and apply.sh. Before running either upload script, open `deploy-target.json` in the operation directory and use its per-field descriptions to edit and check the server, SSH user and port, private key and known-hosts files, remote directory and other settings. Run deploy.ps1 on Windows or deploy.sh on Linux/macOS; both scripts read this JSON to upload over SSH and execute the same server workflow. Running deploy.sh locally requires sh, awk, ssh and scp. Use `sh deploy.sh HOST [PORT] [USER]` to override the connection address, or pass `-IdentityFile` to deploy.ps1 to override its private key. Both scripts support HAI_DEPLOY_IDENTITY_FILE and HAI_DEPLOY_KNOWN_HOSTS_FILE to override key and known-hosts paths. After moving to another computer or operating system, update these paths to files on that computer.
|
|
152
154
|
|
|
153
155
|
Offline upload supports key and password authentication. `deploy-target.json` stores only the authentication choice and `passwordEnv` name (default `HAI_DEPLOY_PROVIDER_SSH_PASSWORD`), never the password value. Supply the password in the operator machine environment; it reaches only the current SSH/SCP child processes, not application environments, the tar or manifest. Windows can also read the persisted user environment. Windows needs PowerShell 5+ and OpenSSH; Linux/macOS uses sh, awk, ssh and scp. Neither uploader needs Node/pnpm. Target edits apply only to that delivery directory and never write back to the project; new deliveries use the saved project environment.
|
|
154
156
|
|
|
@@ -188,6 +190,16 @@ After the server passes local health checks and commits `current`, the SDK separ
|
|
|
188
190
|
|
|
189
191
|
Complete bundles include self-hosted middleware archives and matching architecture; server startup never pulls images. Linux needs Docker/Podman, Docker Compose v2 or podman-compose 1.6.0+ (supports --pull never), sh, tar, sha256sum, awk, curl, util-linux flock and filesystem/container permissions. Protect private bundle contents. Keep volume identities stable across versions. Verify actual offline startup, login, refresh, restart and persistence. HTTPS, certificates, DNS and external services need separate preparation.
|
|
190
192
|
|
|
193
|
+
### Build and packaging improvements
|
|
194
|
+
|
|
195
|
+
Image builds run at most two images concurrently by default; use `--concurrency 1` to reduce resource use. Dependency installation precedes source copies, and each side copies only its required source. Runtime images omit application declaration files, source maps and README files. Packaging validates and reuses middleware archives by image content ID and hashes application archives while copying. Delivery defaults to `.tar.gz`; explicit `--output release.tar` keeps an uncompressed archive. README is only outside the archive. Successful deployment removes its incoming upload/extraction, retains recovery configuration in releases, and keeps images in the container engine.
|
|
196
|
+
|
|
197
|
+
### Optional HTTPS certificates
|
|
198
|
+
|
|
199
|
+
`pnpm run deploy` offers no HTTPS, existing PEM certificate/key paths, or Let’s Encrypt for every container template. Relative paths resolve from the project root. Certificates are checked for domain, validity and key matching, then copied into private releases. A pinned official Certbot image handles issuance and renewal checks every 12 hours, with automatic Nginx reload. It requires terms acceptance, a real email, public DNS, port 80 and CA connectivity. Isolated servers use existing certificates. Certificate state stays on the server; keys stay out of application images. `--yes` reuses saved settings.
|
|
200
|
+
|
|
201
|
+
Configure `hai.json.deploy.provider.expose.https` or private environment overrides. Defaults are HTTPS 443 and HTTP redirection; omission retains HTTP. Enabling/disabling HTTPS or changing mode, domain, ports or supplied certificates requires a full deployment. See the [HTTPS guide](../../docs/usage/configuration/delivery.md#可选https证书). Plans use `root` for the project and `serviceDir` for the service source/configuration directory, exposing only public certificate metadata.
|
|
202
|
+
|
|
191
203
|
### SDK
|
|
192
204
|
|
|
193
205
|
```ts
|
|
@@ -225,6 +237,8 @@ SSH interruptions initially report `remoteExecution: 'unknown'`. The docker-ssh
|
|
|
225
237
|
|
|
226
238
|
### Runtime environment files and repeated deployments
|
|
227
239
|
|
|
240
|
+
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
|
+
|
|
228
242
|
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.
|
|
229
243
|
|
|
230
244
|
Whole `HAI_*` configuration supplied by sidecars or provisioners clears superseded leaf variables: Redis overrides no longer leave `HAI_CACHE_TYPE=memory`. Global `~/.hai/credentials.yml` fills missing settings only, respecting existing environment/process keys and parent objects. Deployment starts selected middleware and waits for PostgreSQL/MySQL/Redis/S3 health before serv/Web; incremental deployment and recovery use the same order and preserve unselected containers.
|
|
@@ -243,7 +257,7 @@ The server persists managed middleware passwords in `<remoteDir>/managed-secrets
|
|
|
243
257
|
|
|
244
258
|
## Read-only deployment plan
|
|
245
259
|
|
|
246
|
-
`createDeploymentPlan(appDir, config, options)` initializes no provider, generates no credentials/output and connects to no target. It shares real scanning, environment resolution, resource naming and artifact checksums, reporting versions, build ID, selected/retained services, source files/key names, baseline requirements and recovery paths without values or SSH credentials. Unread remote current is not-inspected; execution still strictly requires a successful baseline for partial updates. Compose recovery does not undo database changes/migrations. CLI: `hai deploy --env prod --plan`.
|
|
260
|
+
`createDeploymentPlan(appDir, config, options)` initializes no provider, generates no credentials/output and connects to no target. It shares real scanning, environment resolution, resource naming and artifact checksums, reporting project `root`, service source/configuration `serviceDir`, versions, build ID, selected/retained services, source files/key names, baseline requirements and recovery paths without values or SSH credentials. Unread remote current is not-inspected; execution still strictly requires a successful baseline for partial updates. Compose recovery does not undo database changes/migrations. CLI: `hai deploy --env prod --plan`.
|
|
247
261
|
|
|
248
262
|
Use `--plan --inspect-remote` (SDK inspectRemote:true) to read current and the successful release directory over SSH. It reports verified/missing/unavailable and the actual recovery release ID without target writes.
|
|
249
263
|
|
|
@@ -257,11 +271,11 @@ Use `importDeploymentSecrets({ directory, inputFile, runtime })` or run `hai dep
|
|
|
257
271
|
|
|
258
272
|
## Request policy files and trusted proxies
|
|
259
273
|
|
|
260
|
-
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.
|
|
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. 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.
|
|
261
275
|
|
|
262
276
|
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.
|
|
263
277
|
|
|
264
|
-
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.
|
|
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. 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-运维独立管理文件修改后重启生效).
|
|
265
279
|
|
|
266
280
|
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.
|
|
267
281
|
|
package/README.ja.md
CHANGED
|
@@ -22,14 +22,14 @@
|
|
|
22
22
|
|
|
23
23
|
```sh
|
|
24
24
|
pnpm build
|
|
25
|
-
pnpm build --target
|
|
26
|
-
pnpm build --target
|
|
25
|
+
pnpm build --target image
|
|
26
|
+
pnpm build --target image --images web
|
|
27
27
|
pnpm build --target desktop --platform windows --arch x64
|
|
28
28
|
```
|
|
29
29
|
|
|
30
30
|
#### build のオプション
|
|
31
31
|
|
|
32
|
-
`--target` は compile(既定)、
|
|
32
|
+
`--target` は compile(既定)、image、app、desktop を選択します。`--images serv|web|serv,web` は対象イメージを、`--runtime auto|podman|docker` はローカルエンジンを選択します。auto は接続可能な Podman を優先します。`--network` は構築ネットワーク、`--no-http-proxy` は Podman のプロキシ継承無効、`--sqlite-prebuild-mirror` は信頼できる HTTP(S) バイナリ配布元です。ネイティブ配布物には対象 OS の SDK と Rust ツールチェーンが必要です。構築時にデプロイ環境や秘密情報を読み込みません。
|
|
33
33
|
|
|
34
34
|
#### hai.json でパッケージの構成を指定する
|
|
35
35
|
|
|
@@ -85,7 +85,7 @@ SDKは対応するNginx、実行時設定URL、SSRヘルスチェック、公開
|
|
|
85
85
|
|
|
86
86
|
#### 環境と接続先を用意する
|
|
87
87
|
|
|
88
|
-
既定の配置名はプロジェクトルート(最も近い `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` を生成します。接続先ディレクトリ、配布物、Compose プロジェクト、API/Web/ミドルウェアのコンテナー、ボリューム、サーバー認証状態のファイル名、増分基準で同じ名前を使います。実際のプロジェクト名に含まれる `-serv` は削除しません。
|
|
88
|
+
既定の配置名はプロジェクトルート(最も近い `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` は削除しません。
|
|
89
89
|
|
|
90
90
|
成果物形式4・5はprimaryService(serv/web)と、工程全体のブラウザー構成を示すhasWebを記録します。形式5には非ルートのwebBasePathも含まれます。同一オリジンAPIプロキシはserv + webの場合だけ生成します。形式1~3は再構築が必要です。既存デプロイをバックアップし、プロジェクト名・ボリューム・管理対象の認証情報を確認してから、新しい完全デプロイの基準を作成してください。プロジェクト間のデータ移行は自動化しません。完全デプロイでは同じComposeプロジェクトの旧サービスコンテナーを削除するため、deploy-target.json.directoryの変更だけでは移行できません。
|
|
91
91
|
|
|
@@ -114,6 +114,8 @@ SSH 設定は選択環境の `.env.<環境>.local` に保存します。`--bundl
|
|
|
114
114
|
|
|
115
115
|
実行依存と設定に基づき、既定、自分の接続、設定維持を選びます。対象環境の設定が完全なら、`--yes` は値を保持し、再入力やクラウド資源の再作成を行いません。対話モードでは今回の処理範囲を選べます。--skip-middleware は設定と開通を省略します。SQLite、メモリーキャッシュ、ローカル保存には外部イメージがありません。完全配布物には自前ミドルウェアのイメージも自動で含めます。外部サービスは接続先への到達性が必要で、クラウド開通はオフライン処理ではありません。
|
|
116
116
|
|
|
117
|
+
既定とカスタムは同じバックエンドの有効な設定を保持します。フォームにない接続プール、操作ログ、ストレージ公開 URL/接頭辞、Redis 再試行、ベクトル検索設定も対象です。自前構成とクラウド開通は接続先・認証だけを更新し、古い URL、TLS/クラスター設定、認証情報を引き継ぎません。SMTP 送信元と LDAP 属性対応は保持します。バックエンド変更時は非互換項目を除去します。旧版が親 JSON から削除した項目は自動復元できません。元の設定やバックアップから最優先の `HAI_STORAGE` に `publicEndpoint` などを戻して配布物を再作成してください。親 JSON に隠された YAML や末端変数だけの変更では直りません。
|
|
118
|
+
|
|
117
119
|
#### 非公開オブジェクトストレージへの直接アクセス
|
|
118
120
|
|
|
119
121
|
自前 S3 の endpoint は内部接続先です。publicEndpoint に `https://app.example.com/delivery/files` などの外部アドレスを設定できます。Nginx は `/delivery/files/<bucket>/...` を受け、入口パスだけを除去し、本来のバケット URI、署名クエリ、Host を保持して storage:9000 に転送します。Serv を経由せず、パス省略時は従来のルートバケット形式です。サイト配下に置けますが API、資源、ヘルスパスの競合は拒否します。ポートと管理コンソールは非公開、バッファリングと署名ログは無効です。認可と CORS は S3 に設定し、外部プロキシは入口パスと Host を保持してください。
|
|
@@ -146,7 +148,7 @@ S3 の `createBucket` は既定で `false` です。自前 S3 には `HAI_STORAG
|
|
|
146
148
|
pnpm run deploy --env prod --build --bundle-only
|
|
147
149
|
```
|
|
148
150
|
|
|
149
|
-
毎回 `.hai/deploy/<環境>/bundle-<プロジェクト>-<配置ID>-<版>/` を一つ生成し、外側には tar、deploy.sh、deploy.ps1、deploy-target.json、read-target.awk、deploy-local.sh、README.txt だけを保存します。Compose、実行環境、web.conf、manifest.json は tar 内に置き、外側の README にも配置 ID を記録します。ディレクトリ全体をコピーしてください。`--output release-prod.tar` は作業ディレクトリを基準に `release-prod-<版>/release-prod-<版>.tar` を生成し、付属ファイルも同じ場所に置きます。tar は選択アプリ・ミドルウェアのイメージ、設定、秘密の環境ファイル、チェックサム、README、apply.sh を含みます。アップロードスクリプトの実行前に、操作ディレクトリの `deploy-target.json` を開き、各項目の説明に従ってサーバー、SSH ユーザーとポート、秘密鍵・指紋ファイル、リモートディレクトリなどを変更・確認します。Windows は deploy.ps1、Linux/macOS は deploy.sh を実行します。どちらも同じ JSON を読み、SSH 転送後に同じサーバー処理を実行します。ローカルで deploy.sh を実行するには sh、awk、ssh、scp が必要です。`sh deploy.sh ホスト [ポート] [ユーザー]` で接続先を、deploy.ps1 の `-IdentityFile` で秘密鍵を上書きできます。両方のスクリプトで HAI_DEPLOY_IDENTITY_FILE と HAI_DEPLOY_KNOWN_HOSTS_FILE による鍵・指紋ファイルのパスの上書きも可能です。別の PC・OS に移す場合、これらのパスを移動先の実ファイルに合わせます。
|
|
151
|
+
毎回 `.hai/deploy/<環境>/bundle-<プロジェクト>-<配置ID>-<版>/` を一つ生成し、外側には tar、deploy.sh、deploy.ps1、deploy-target.json、read-target.awk、deploy-local.sh、README.txt だけを保存します。Compose、実行環境、web.conf、manifest.json は tar 内に置き、外側の README にも配置 ID を記録します。ディレクトリ全体をコピーしてください。`--output release-prod.tar` は作業ディレクトリを基準に `release-prod-<版>/release-prod-<版>.tar.gz` を生成し、付属ファイルも同じ場所に置きます。tar は選択アプリ・ミドルウェアのイメージ、設定、秘密の環境ファイル、チェックサム、README、apply.sh を含みます。アップロードスクリプトの実行前に、操作ディレクトリの `deploy-target.json` を開き、各項目の説明に従ってサーバー、SSH ユーザーとポート、秘密鍵・指紋ファイル、リモートディレクトリなどを変更・確認します。Windows は deploy.ps1、Linux/macOS は deploy.sh を実行します。どちらも同じ JSON を読み、SSH 転送後に同じサーバー処理を実行します。ローカルで deploy.sh を実行するには sh、awk、ssh、scp が必要です。`sh deploy.sh ホスト [ポート] [ユーザー]` で接続先を、deploy.ps1 の `-IdentityFile` で秘密鍵を上書きできます。両方のスクリプトで HAI_DEPLOY_IDENTITY_FILE と HAI_DEPLOY_KNOWN_HOSTS_FILE による鍵・指紋ファイルのパスの上書きも可能です。別の PC・OS に移す場合、これらのパスを移動先の実ファイルに合わせます。
|
|
150
152
|
|
|
151
153
|
オフラインアップロードは鍵とパスワードの両方に対応します。`deploy-target.json` に保存するのは認証方式と `passwordEnv` 名(既定 `HAI_DEPLOY_PROVIDER_SSH_PASSWORD`)だけで、パスワード値は含めません。操作する PC の環境から与え、今回の SSH/SCP 子プロセスだけに渡します。アプリ環境、tar、manifest には入りません。Windows では永続化したユーザー環境も参照できます。Windows は PowerShell 5+ と OpenSSH、Linux/macOS は sh、awk、ssh、scp が必要で、どちらも Node/pnpm は不要です。target の変更はその配布ディレクトリだけに適用し、プロジェクトには書き戻しません。新しい配布物は保存済みの環境設定を使います。
|
|
152
154
|
|
|
@@ -186,6 +188,16 @@ SDK はサーバー内の正常性確認と `current` 更新後、操作端末
|
|
|
186
188
|
|
|
187
189
|
完全 tar は自前ミドルウェアのアーカイブと一致するアーキテクチャを含み、起動時にレジストリーへ接続しません。Linux に Docker/Podman、Docker Compose v2 または podman-compose 1.6.0 以降、sh、tar、sha256sum、awk、curl、util-linux の flock、ディレクトリ・コンテナー権限が必要です。秘密設定を安全に転送し、版間でボリューム識別を保持します。外部ネットワークを切って起動、ログイン、再読込、再起動と永続化を検証します。HTTPS、証明書、DNS、外部サービスは別途用意します。
|
|
188
190
|
|
|
191
|
+
### 構築と配布の最適化
|
|
192
|
+
|
|
193
|
+
イメージは既定で最大 2 件を並列構築し、`--concurrency 1` で資源使用量を抑えます。ソースの前に依存をインストールし、各端で必要なソースだけをコピーします。実行イメージからアプリの型宣言・source map・README を除去します。ミドルウェアのアーカイブはイメージ内容 ID で検証・再利用し、コピーと同時にハッシュを計算します。配布の既定は `.tar.gz`、明示的な `--output release.tar` は非圧縮です。README は外側だけに保持します。成功後に今回の incoming アップロードと展開先を削除し、release に復旧設定、エンジンにイメージを保持します。
|
|
194
|
+
|
|
195
|
+
### 任意の HTTPS 証明書
|
|
196
|
+
|
|
197
|
+
`pnpm run deploy` は全コンテナーテンプレートで HTTPS なし、既存 PEM 証明書・秘密鍵、Let’s Encrypt を選択できます。相対パスは工程ルート基準です。ドメイン・期限・鍵一致を検証して配布物にコピーします。版を固定した公式 Certbot イメージで申請し、12 時間ごとに更新を確認して Nginx を再読み込みします。利用規約の承認、実際のメール、公的 DNS、80 番ポート、CA 接続が必要です。隔離環境では既存証明書を使います。状態はサーバーに保持し、秘密鍵をアプリイメージに含めません。`--yes` は保存設定を使います。
|
|
198
|
+
|
|
199
|
+
`hai.json.deploy.provider.expose.https` または環境別秘密設定で指定します。既定は HTTPS 443 と HTTP リダイレクト、省略時は HTTP です。有効/無効・モード・ドメイン・ポート・持込証明書の変更は完全デプロイが必要です。[HTTPS 設定](../../docs/usage/configuration/delivery.md#可选https证书)を参照してください。計画では `root` が工程ルート、`serviceDir` がサービスのソース・設定ディレクトリです。
|
|
200
|
+
|
|
189
201
|
### SDK
|
|
190
202
|
|
|
191
203
|
```ts
|
|
@@ -223,6 +235,8 @@ SSH 中断は最初に `remoteExecution: 'unknown'` とし、docker-ssh SDK は
|
|
|
223
235
|
|
|
224
236
|
### 実行環境ファイルと設定の再利用
|
|
225
237
|
|
|
238
|
+
Node バックエンド(Serv / SvelteKit SSR)は起動ごとに配布先の `.env.runtime` を既定で読み直します。編集後に `docker restart <コンテナー>` または `podman restart <コンテナー>` を実行し、イメージ再構築や追加 override は不要です。既存配置は新 CLI で一度デプロイしてください。削除した設定を旧 Compose 環境から復活させず、管理接続の `middleware.env` を優先します。私有プロキシ識別と Node 起動引数は配置設定のままです。静的 Web・ミドルウェア・ポート/マウント・Nginx の経路と制限は従来手順で更新します。ゲートウェイの経路、ポート、マウントの変更は全量デプロイを行います。手動変更をバックアップし、継続する値は元の環境にも反映してください。次のバックエンド配置時に再生成されます。
|
|
239
|
+
|
|
226
240
|
フレームワークの永続設定は `HAI_*` を使います。`POSTGRES_*`、`MYSQL_*`、`RUSTFS_*`、`MINIO_*`、`LDAP_*` はミドルウェアイメージ必須の名前を維持し、非公開の `middleware-runtime.env` にだけ生成してミドルウェアに渡します。プロジェクト環境ファイルやアプリの `.env.runtime` には新規保存しません。増分アプリ更新用の `middleware.env` は `HAI_*` 設定のみです。既存の原生変数は自動削除せず、新しいアプリ環境から除外します。未更新サービスは以前の配布ファイルを使い続けます。
|
|
227
241
|
|
|
228
242
|
サイドカーやクラウドの `HAI_*` オブジェクトで置換した古い子変数は除去し、Redis 選択後に `HAI_CACHE_TYPE=memory` を残しません。グローバル `~/.hai/credentials.yml` は不足値のみ補い、環境・プロセスの同名キーや親設定を上書きしません。選択したミドルウェアを起動し PostgreSQL/MySQL/Redis/S3 の正常性を確認後、serv/Web を起動します。増分と復旧も同じ順序で、未選択のコンテナーは維持します。
|
|
@@ -233,7 +247,7 @@ Podman では設定済みの healthcheck を明示的に実行して状態を再
|
|
|
233
247
|
|
|
234
248
|
作成時に `.env.dev/.env.test/.env.prod` ごとに別の初期管理者パスワードと転送鍵リングを生成し、Git に保存します。クローン後も環境ごとに共有し、ローカル秘密ファイルやプロセス環境で上書きできます。transport 有効アプリの `HAI_CRYPTO_TRANSPORT_SERVERKEYRING` が不足・不正ならアップロード前に設定元を案内します。同じ環境の全ノードは環境ファイルまたは Secret Manager の上書きから同じ有効リングを読み込み、ノードごとに生成しないでください。CLI 完了時はログレベルによらず `HAI_ADMIN_DEFAULT_PASSWORD` の実際の保存元を案内し、値は表示しません。初回管理者作成時だけ有効です。 オフライン入口でも、サーバーの非公開 `.env.runtime` 内のパスワード変数の場所を案内します。
|
|
235
249
|
|
|
236
|
-
|
|
250
|
+
配布ごとに起動時読み込み用の `.hai/deploy/<環境>/bundle-.../.env.runtime` を生成します。これは生成物であり、設定の保存元ではありません。`NODE_ENV` の既定値は対象環境に従い、`test` は `test`、`dev/development` は `development`、`prod/production` とその他は `production` です。環境設定の明示的な `NODE_ENV` が優先され、構築の最適化モードとは別です。旧配布物は再度パッケージ化してください。
|
|
237
251
|
|
|
238
252
|
プロジェクトルートの `hai.json.deploy` に配置構造、`.env.<環境>` に公開設定、`.env.<環境>.local` に SSH とミドルウェアの認証情報を保存します。環境ファイルは既定でプロジェクト/workspace ルート、変更時は `--env-dir` を指定します。設定後は `pnpm run deploy --env test --build --bundle-only --yes` で再入力を省略でき、ミドルウェア設定を保持する場合は `--skip-middleware` を追加します。対話式 bundle-only は最後に SSH 設定の保存・変更を確認します。配布物の `deploy-target.json` の編集はプロジェクトに反映されません。
|
|
239
253
|
|
|
@@ -241,7 +255,7 @@ Podman では設定済みの healthcheck を明示的に実行して状態を再
|
|
|
241
255
|
|
|
242
256
|
## 読み取り専用デプロイ計画
|
|
243
257
|
|
|
244
|
-
`createDeploymentPlan(appDir, config, options)` は Provider 初期化、認証情報・出力作成、対象への接続を行いません。実際の走査、環境解決、命名と checksum
|
|
258
|
+
`createDeploymentPlan(appDir, config, options)` は Provider 初期化、認証情報・出力作成、対象への接続を行いません。実際の走査、環境解決、命名と checksum 検証を共用し、工程 `root`、サービスのソース・設定 `serviceDir`、版、ビルド ID、更新・保持範囲、設定元とキー名、基準要件と復旧先を返します。値と SSH 認証情報を除外します。未読の current は not-inspected とし、部分更新は実行時に成功基準を厳密に要求します。Compose 復旧は DB データや移行を戻しません。CLI は `hai deploy --env prod --plan`。
|
|
245
259
|
|
|
246
260
|
`--plan --inspect-remote`(SDK inspectRemote:true)で SSH 経由の current と成功ディレクトリーを読み取り、verified/missing/unavailable と復旧リリース ID を示します。対象への書込は行いません。
|
|
247
261
|
|
|
@@ -255,11 +269,11 @@ Podman では設定済みの healthcheck を明示的に実行して状態を再
|
|
|
255
269
|
|
|
256
270
|
## リクエストポリシーファイルと信頼する代理
|
|
257
271
|
|
|
258
|
-
Serv の `http.access` と SvelteKit の `access` は独立した yml/yaml を参照できます。配備は `HAI_SERV`、`HAI_SERV_HTTP_ACCESS`、`HAI_KIT_ACCESS` などの環境上書きを含む実効設定を読み、検証済みの正規化スナップショットを配布物へ含めます。実行時は `/run/hai/request-access.yml` を Compose の読み取り専用マウントで参照し、工程の元の参照先は変更しません。SHA-256
|
|
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 検証に含まれ、ファイル不足・不正はアップロード前に失敗します。アップロードするアーカイブとそのポリシースナップショットは整合性検証の対象です。SDK 管理のスナップショットを置き換える場合は新しい配布物を作成します。配置済み Node バックエンドのマウント済み `.env.runtime` は上記手順で編集・再起動できます。インライン規則の変更ではスナップショットや Nginx 設定は書き換わりません。
|
|
259
273
|
|
|
260
274
|
全量とバックエンドを含む増分は独自のスナップショットを持ち、フロントエンドだけの増分は旧バックエンドのマウントを維持します。失敗時は前回成功した Compose とポリシーへ復旧します。非 root コンテナでも私有リリースディレクトリ内のファイルを読み取れます。イメージと設定の復旧は DB 移行や実施済み業務を取り消しません。
|
|
261
275
|
|
|
262
|
-
運用側でルールを変更して再起動で反映する場合は、配布物の外で読み取り専用ファイルを管理し、Compose override で同じ `/run/hai/request-access.yml` のマウントを置き換えます。この外部ファイルは SDK
|
|
276
|
+
運用側でルールを変更して再起動で反映する場合は、配布物の外で読み取り専用ファイルを管理し、Compose override で同じ `/run/hai/request-access.yml` のマウントを置き換えます。この外部ファイルは SDK の自動復旧対象外です。初回マウント適用はコンテナ再作成、以後のファイル変更は再起動で反映できます。Compose の `env_file` だけで環境変数を注入する独自コンテナは、変更後に再作成します。通常イメージ再構築は不要です。SDK の Node バックエンドはマウント済み `.env.runtime` を再起動時に読み取ります。[設定と実測の境界](../../docs/usage/configuration/request-access.md#44-运维独立管理文件修改后重启生效)を参照してください。
|
|
263
277
|
|
|
264
278
|
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)に例と確認手順を記載しています。
|
|
265
279
|
|
package/README.md
CHANGED
|
@@ -22,18 +22,18 @@
|
|
|
22
22
|
|
|
23
23
|
```sh
|
|
24
24
|
pnpm build
|
|
25
|
-
pnpm build --target
|
|
26
|
-
pnpm build --target
|
|
25
|
+
pnpm build --target image
|
|
26
|
+
pnpm build --target image --images web
|
|
27
27
|
pnpm build --target desktop --platform windows --arch x64
|
|
28
28
|
```
|
|
29
29
|
|
|
30
|
-
源码编译、镜像构建、桌面打包分别对应 compile/
|
|
30
|
+
源码编译、镜像构建、桌面打包分别对应 compile/image/desktop。构建不选择部署环境、不注入运行期密钥。原生安装包在对应操作系统准备 SDK 与 Rust 工具链后构建。
|
|
31
31
|
|
|
32
32
|
#### build 的可选参数
|
|
33
33
|
|
|
34
34
|
| 参数 | 用途 |
|
|
35
35
|
| -------------------------- | ----------------------------------------- |
|
|
36
|
-
| `--target` | compile(默认)、
|
|
36
|
+
| `--target` | compile(默认)、image、app、desktop |
|
|
37
37
|
| `--images` | serv、web 或 serv,web;只构建导出所选镜像 |
|
|
38
38
|
| `--runtime` | auto(优先 Podman)、podman、docker |
|
|
39
39
|
| `--network` | 容器构建网络,默认引擎设置 |
|
|
@@ -98,7 +98,7 @@ SDK据制品生成Nginx目录、运行配置入口、SSR健康路径和返回URL
|
|
|
98
98
|
|
|
99
99
|
#### 先准备环境与部署目标
|
|
100
100
|
|
|
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`。远端目录、交付包、Compose 项目、API/Web/中间件容器、数据卷、服务器凭据状态及增量基线统一使用该名称;不会按字符串删除真实项目名中的 `-serv`。
|
|
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
103
|
制品格式4和5都记录primaryService(serv/web),hasWeb表示完整工程是否包含浏览器端;格式5另记录非根目录webBasePath。只有serv + web才生成同源API代理。格式1至3制品须重新构建。旧部署先备份并核对项目名、数据卷和受管凭据,再切换到新的完整部署基线;工具不自动跨项目迁移数据。完整部署仍会按Compose规则清理同项目的旧服务容器,不能仅修改deploy-target.json.directory完成迁移。
|
|
104
104
|
|
|
@@ -127,6 +127,8 @@ SSH 参数保存到选中环境的 `.env.<环境>.local`。`--bundle-only` 在
|
|
|
127
127
|
|
|
128
128
|
根据锁文件运行依赖和模块配置识别数据库、缓存、文件存储、向量库、LDAP、邮件等。逐项选择默认、自定义或保持。目标环境已有完整配置时,`--yes` 保持原值,不重新输入或重复云开通;交互模式仍可选择本次处理范围。配置完备可用 `--skip-middleware` 跳过向导和开通。SQLite、Memory cache、本地存储不产生外部镜像;Compose 自建服务的镜像自动加入完整交付包。外部服务仍需目标网络可达,云开通不属于完全离线部署。
|
|
129
129
|
|
|
130
|
+
默认和自定义模式均保留同后端的有效配置,包括表单未展示的连接池、操作日志、存储公开端点/前缀、Redis 重试和向量检索选项。自建与云开通仅重新定稿实际连接和认证;旧 URL、TLS/集群模式与凭据不能覆盖新服务,SMTP 发件人和 LDAP 属性映射继续保留。切换后端时清除不兼容字段。旧向导已保存的缺字段父 JSON 不会自动恢复:须从原配置或备份补回最高优先级 `HAI_STORAGE` 中的 `publicEndpoint` 等字段,再重新打包部署;只改被父 JSON 覆盖的 YAML/叶变量无效。
|
|
131
|
+
|
|
130
132
|
#### 私有对象存储直连
|
|
131
133
|
|
|
132
134
|
自建 S3 的 `endpoint` 使用 Compose 内部地址,浏览器地址用 `_storage.yml` 的 `publicEndpoint` 配置,例如 `https://app.example.com/delivery/files`。Nginx 对外开放 `/delivery/files/<bucket>/...`,去掉 `/delivery/files` 后将原始桶 URI、签名查询与 Host 直接转发 storage:9000,文件不经过 Serv;省略目录时继续使用根桶路径。入口可位于网站目录内,API/资源/健康路径冲突会在打包前失败。存储端口与控制台不公开,对象缓冲和签名日志关闭;S3 负责私有桶授权和跨源 CORS。外层代理须保留完整入口路径与 Host,只由 SDK 网关去掉前缀。
|
|
@@ -169,7 +171,7 @@ S3 的 `createBucket` 默认为 `false`;部署器为自建 S3 注入 `HAI_STOR
|
|
|
169
171
|
pnpm run deploy --env prod --build --bundle-only
|
|
170
172
|
```
|
|
171
173
|
|
|
172
|
-
每次交付只生成一个 `.hai/deploy/<环境>/bundle-<项目>-<部署ID>-<版本>/` 目录,外层仅保留 tar、deploy.sh、deploy.ps1、deploy-target.json、read-target.awk、deploy-local.sh 和 README.txt;Compose、运行环境、web.conf 和 manifest.json 仅保存在 tar 内,README 同时记录部署 ID,直接整体复制即可。显式 `--output release-prod.tar` 按命令执行目录生成 `release-prod-<版本>/release-prod-<版本>.tar`,其他文件仍在同一交付目录。包包含所选应用/中间件镜像、服务配置、私有环境、校验和、README 和 apply.sh。运行上传脚本前,先打开操作目录的 `deploy-target.json`,按其中逐项说明修改并核对服务器、SSH 用户和端口、私钥及指纹文件、远程目录等配置。Windows 运行 deploy.ps1,Linux/macOS 运行 deploy.sh;两个脚本均读取该 JSON,通过 SSH 上传后执行同一服务器流程。本机运行 deploy.sh 需 sh、awk、ssh、scp;可用 `sh deploy.sh 主机 [端口] [用户]` 覆盖连接地址,或给 deploy.ps1 传入 `-IdentityFile` 覆盖私钥。两个脚本均支持用 HAI_DEPLOY_IDENTITY_FILE、HAI_DEPLOY_KNOWN_HOSTS_FILE 覆盖私钥及指纹文件路径。换电脑或操作系统后,这些路径必须指向当前电脑上的实际文件。
|
|
174
|
+
每次交付只生成一个 `.hai/deploy/<环境>/bundle-<项目>-<部署ID>-<版本>/` 目录,外层仅保留 tar、deploy.sh、deploy.ps1、deploy-target.json、read-target.awk、deploy-local.sh 和 README.txt;Compose、运行环境、web.conf 和 manifest.json 仅保存在 tar 内,README 同时记录部署 ID,直接整体复制即可。显式 `--output release-prod.tar` 按命令执行目录生成 `release-prod-<版本>/release-prod-<版本>.tar.gz`,其他文件仍在同一交付目录。包包含所选应用/中间件镜像、服务配置、私有环境、校验和、README 和 apply.sh。运行上传脚本前,先打开操作目录的 `deploy-target.json`,按其中逐项说明修改并核对服务器、SSH 用户和端口、私钥及指纹文件、远程目录等配置。Windows 运行 deploy.ps1,Linux/macOS 运行 deploy.sh;两个脚本均读取该 JSON,通过 SSH 上传后执行同一服务器流程。本机运行 deploy.sh 需 sh、awk、ssh、scp;可用 `sh deploy.sh 主机 [端口] [用户]` 覆盖连接地址,或给 deploy.ps1 传入 `-IdentityFile` 覆盖私钥。两个脚本均支持用 HAI_DEPLOY_IDENTITY_FILE、HAI_DEPLOY_KNOWN_HOSTS_FILE 覆盖私钥及指纹文件路径。换电脑或操作系统后,这些路径必须指向当前电脑上的实际文件。
|
|
173
175
|
|
|
174
176
|
离线上传支持密钥和密码认证。`deploy-target.json` 只保存认证方式及 `passwordEnv` 名称(默认 `HAI_DEPLOY_PROVIDER_SSH_PASSWORD`),不保存密码值。密码由操作机环境提供,仅传给本次 SSH/SCP 子进程,不进入应用环境、tar 或 manifest;Windows 也可读取用户持久环境。Windows 入口要求 PowerShell 5+ 和 OpenSSH,Linux/macOS 使用 sh、awk、ssh、scp,两者均不需要 Node/pnpm。修改 target 只影响当前交付目录,不回写工程;新交付仍使用工程保存的环境配置。
|
|
175
177
|
|
|
@@ -212,6 +214,16 @@ SDK 在服务器本地健康通过并提交 `current` 后,还从操作机检
|
|
|
212
214
|
- 包含私有配置,安全搬运,不提交 Git;持久化卷身份跨版本稳定。
|
|
213
215
|
- 实际断外网验证启动、登录、页面刷新、重启与数据持久化。生产 HTTPS、证书、DNS 和外部服务需另行准备。
|
|
214
216
|
|
|
217
|
+
### 构建与交付优化
|
|
218
|
+
|
|
219
|
+
镜像默认最多并行两项,`--concurrency 1` 可降低资源占用。Dockerfile 在复制源码前安装依赖;前后端仅复制各自必要源码,复用安装层和驱动缓存。运行镜像移除应用自身的声明文件、源码映射和说明文件。打包按镜像内容 ID 复用并校验中间件归档,复制应用镜像时同时计算摘要。默认交付压缩为 `.tar.gz`,显式 `--output release.tar` 可保留未压缩格式;README 仅保留外层一份。成功部署后清理本次 incoming 上传和解包目录,release 保留恢复配置和状态,镜像由容器引擎保存。
|
|
220
|
+
|
|
221
|
+
### 可选 HTTPS 证书
|
|
222
|
+
|
|
223
|
+
`pnpm run deploy` 为所有容器模板统一提供“不启用 / 已有 PEM 证书和私钥路径 / Let’s Encrypt”。相对路径以工程根为基准,已有证书校验域名、有效期和密钥匹配后复制到私有发布包。Let’s Encrypt 使用固定版本官方 Certbot 镜像申请,每 12 小时检查续期,Nginx 自动重载。需要确认服务条款、真实邮箱、公网 DNS、80 端口和 CA 网络;隔离环境使用已有证书。证书状态保留在服务器,私钥不进入应用镜像。`--yes` 复用保存配置。
|
|
224
|
+
|
|
225
|
+
配置为 `hai.json.deploy.provider.expose.https`,也可用环境私有文件覆盖。默认 HTTPS 443、HTTP 跳转开启,未配置保持 HTTP;启停或更改模式、域名、端口、本地证书需全量部署。配置和续期边界见[HTTPS 手册](../../docs/usage/configuration/delivery.md#可选https证书)。`--plan` 的 `root` 表示工程根,`serviceDir` 表示部署服务源码与配置目录,仅显示公开证书元数据。
|
|
226
|
+
|
|
215
227
|
### SDK
|
|
216
228
|
|
|
217
229
|
```ts
|
|
@@ -249,6 +261,8 @@ SSH 中断始终先记 `remoteExecution: 'unknown'`。docker-ssh SDK 用新连
|
|
|
249
261
|
|
|
250
262
|
### 运行环境文件与重复部署
|
|
251
263
|
|
|
264
|
+
Node 后端(Serv / SvelteKit SSR)默认在每次启动时重读发布目录的 `.env.runtime`,修改后 `docker restart <容器名>` 或 `podman restart <容器名>` 即可,无需重建镜像或额外 override。旧部署先用新版 CLI 发布一次。删除的字段不会从旧 Compose 注入中复活;服务器托管连接的 `middleware.env` 保持原有更高优先级,私有代理标记和 Node 启动参数仍由部署装配管理。静态 Web、中间件、端口/挂载、Nginx 路由与限额不在该重载范围;改变网关路径、端口或挂载时使用全量部署。手工修改需备份;下一次后端发布会从工程环境重新生成,需要长期保留的配置同步回源环境。
|
|
265
|
+
|
|
252
266
|
框架持久配置使用 `HAI_*` 命名。`POSTGRES_*`、`MYSQL_*`、`RUSTFS_*`、`MINIO_*`、`LDAP_*` 是中间件镜像的原生协议,必须保留原名,但只生成到私有的 `middleware-runtime.env` 并由中间件容器加载;不再写入工程环境文件或应用的 `.env.runtime`。应用增量部署沿用的 `middleware.env` 仅保存框架 `HAI_*` 配置。旧工程已保存的这些原生字段不会被自动删除,新应用环境会忽略它们;新包与旧成功基线可共存,旧服务仍读取其原交付文件。
|
|
253
267
|
|
|
254
268
|
自建或云开通的整体 `HAI_*` 配置会清除被替换的旧叶字段,例如 Redis 覆盖后不再留下 `HAI_CACHE_TYPE=memory`。全局 `~/.hai/credentials.yml` 只补缺项,不能覆盖当前环境/进程的同名键或父配置。部署先启动选中中间件,等待 PostgreSQL/MySQL/Redis/S3 健康,再启动 serv/Web;增量和失败恢复沿用此顺序,未选容器保持不变。
|
|
@@ -259,7 +273,7 @@ Podman 部署会主动执行容器已有的 healthcheck 并重新核对状态,
|
|
|
259
273
|
|
|
260
274
|
生成时为 `.env.dev/.env.test/.env.prod` 分别生成独立的初始管理员密码和传输密钥环;环境文件随项目提交,克隆后可共享,并可通过本机私有文件或进程环境覆盖。启用 transport 的应用缺少/错误配置 `HAI_CRYPTO_TRANSPORT_SERVERKEYRING` 时,部署在上传前指出配置来源;同一环境的所有节点复用同一有效密钥环,可直接加载环境文件,也可通过 Secret Manager 覆盖;不为每个节点临时生成。CLI 完成部署后提示 `HAI_ADMIN_DEFAULT_PASSWORD` 的实际来源,不打印密码,不依赖日志级别;该密码仅在首次创建管理员时生效。 离线入口也会提示服务器私有 `.env.runtime` 中的密码变量位置。
|
|
261
275
|
|
|
262
|
-
每次交付仍生成 `.hai/deploy/<环境>/bundle-.../.env.runtime
|
|
276
|
+
每次交付仍生成 `.hai/deploy/<环境>/bundle-.../.env.runtime`,供后端启动预加载(静态 Web 仍用 Compose env_file);它是生成产物,不是配置记忆源。`NODE_ENV` 默认随目标环境选择:`test` → `test`,`dev/development` → `development`,`prod/production` 及其他模式 → `production`。环境文件中显式设置的 `NODE_ENV` 仍优先于该默认值;`--build` 的构建优化模式不决定运行环境。旧交付包不会自动改写,需重新打包。
|
|
263
277
|
|
|
264
278
|
项目根 `hai.json.deploy` 保存部署结构,`.env.<环境>` 保存公共配置,`.env.<环境>.local` 保存 SSH 及中间件秘密值。环境文件默认来自项目/workspace 根,`--env-dir` 可指定目录。完整配置后可使用 `pnpm run deploy --env test --build --bundle-only --yes` 无交互复用;只想保留现有中间件配置时追加 `--skip-middleware`。交互式仅打包会在最后询问是否保存或修改 SSH 信息;修改交付目录的 `deploy-target.json` 不会回写工程。
|
|
265
279
|
|
|
@@ -267,17 +281,17 @@ Podman 部署会主动执行容器已有的 healthcheck 并重新核对状态,
|
|
|
267
281
|
|
|
268
282
|
## 请求策略文件与可信代理
|
|
269
283
|
|
|
270
|
-
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
|
|
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 校验,无效或缺失文件在上传前失败。待上传的归档和其中的策略快照参与完整性校验,不应手工修改;替换 SDK 策略快照时重新打包部署。已部署 Node 后端挂载的 `.env.runtime` 可以按“运行配置重载”修改并重启,改变内联规则不会重写策略快照或 Nginx 配置。
|
|
271
285
|
|
|
272
286
|
全量与包含后端的增量都交付自己的快照;仅更新前端时保留后端原挂载。失败恢复使用旧成功发布的 Compose 和策略文件。运行账号无需 root:发布目录私有,策略文件在受限目录内以只读权限供容器读取。回滚镜像和策略不撤销数据库迁移或已经产生的业务效果。
|
|
273
287
|
|
|
274
|
-
如需由运维独立改规则、重启后生效,可在交付之外管理只读文件,并用 Compose override 替换同一 `/run/hai/request-access.yml` 挂载。该外部文件不参与 SDK
|
|
288
|
+
如需由运维独立改规则、重启后生效,可在交付之外管理只读文件,并用 Compose override 替换同一 `/run/hai/request-access.yml` 挂载。该外部文件不参与 SDK 自动回滚,首次附加挂载需要重新创建容器;后续文件修改后重启即可。自行维护且只用 Compose `env_file` 注入环境的容器,修改该文件仍需重新创建,通常无需重建镜像;这与 SDK 默认挂载读取的后端 `.env.runtime` 不同。步骤与验证边界见[独立文件重启配置](../../docs/usage/configuration/request-access.md#44-运维独立管理文件修改后重启生效)。
|
|
275
289
|
|
|
276
290
|
受管 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)。
|
|
277
291
|
|
|
278
292
|
## 只读部署计划
|
|
279
293
|
|
|
280
|
-
`createDeploymentPlan(appDir, config, options)` 不初始化 Provider、不生成中间件凭据、不创建输出目录、不连接目标。复用实际扫描、环境解析、资源名称与制品 checksum
|
|
294
|
+
`createDeploymentPlan(appDir, config, options)` 不初始化 Provider、不生成中间件凭据、不创建输出目录、不连接目标。复用实际扫描、环境解析、资源名称与制品 checksum 校验,返回工程根 `root`、部署服务目录 `serviceDir`、版本、构建 ID、范围、保留服务、配置文件与变量名、基线要求和恢复目录,省略所有变量值与 SSH 凭据。远端 current 未读取时明确 not-inspected;局部更新仍由执行端严格要求成功基线。Compose 恢复不会回退数据库数据或迁移。CLI 对应 `hai deploy --env prod --plan`。
|
|
281
295
|
|
|
282
296
|
需要目标基线事实时使用 `--plan --inspect-remote`(SDK inspectRemote:true),仅通过 SSH 读取 current 及成功发布目录,报告 verified/missing/unavailable 和实际恢复发布 ID,不写目标。
|
|
283
297
|
|
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
/** Node 后端默认启动预加载:每次启动读取发布环境,再加载服务器托管连接配置。 */
|
|
2
|
+
import { Buffer } from 'node:buffer'
|
|
3
|
+
import { closeSync, constants, fstatSync, openSync, readSync } from 'node:fs'
|
|
4
|
+
import process from 'node:process'
|
|
5
|
+
import { parseEnv } from 'node:util'
|
|
6
|
+
|
|
7
|
+
const maximumBytes = 1024 * 1024
|
|
8
|
+
|
|
9
|
+
/** 复用 Node dotenv 解析;拒绝特殊文件、链接、超限与不可读文件,不输出秘密。 */
|
|
10
|
+
function readEnvironment(name) {
|
|
11
|
+
let descriptor
|
|
12
|
+
try {
|
|
13
|
+
descriptor = openSync(new URL(name, import.meta.url), constants.O_RDONLY | constants.O_NONBLOCK | (constants.O_NOFOLLOW ?? 0))
|
|
14
|
+
}
|
|
15
|
+
catch {
|
|
16
|
+
throw new Error('Runtime environment file is missing or not readable')
|
|
17
|
+
}
|
|
18
|
+
try {
|
|
19
|
+
const stat = fstatSync(descriptor)
|
|
20
|
+
if (!stat.isFile() || stat.size > maximumBytes)
|
|
21
|
+
throw new Error('Runtime environment file must be a regular file no larger than 1 MiB')
|
|
22
|
+
const buffer = Buffer.alloc(maximumBytes + 1)
|
|
23
|
+
let length = 0
|
|
24
|
+
while (length < buffer.length) {
|
|
25
|
+
const count = readSync(descriptor, buffer, length, buffer.length - length, null)
|
|
26
|
+
if (!count)
|
|
27
|
+
break
|
|
28
|
+
length += count
|
|
29
|
+
}
|
|
30
|
+
if (length > maximumBytes)
|
|
31
|
+
throw new Error('Runtime environment file exceeds 1 MiB')
|
|
32
|
+
try {
|
|
33
|
+
const text = buffer.subarray(0, length).toString('utf8')
|
|
34
|
+
const values = parseEnv(text)
|
|
35
|
+
// 交付序列化对同时含单/双引号的字符串使用 JSON 转义;避免 Node 截断转义引号。
|
|
36
|
+
for (const match of text.matchAll(/^(?:export\s+)?([A-Za-z_]\w*)\s*=\s*("(?:[^"\\\r\n]|\\.)*")\s*(?:#[^\r\n]*)?$/gm)) {
|
|
37
|
+
try {
|
|
38
|
+
values[match[1]] = JSON.parse(match[2])
|
|
39
|
+
}
|
|
40
|
+
catch { /* 普通 dotenv 双引号仍按 Node 原生规则解析。 */ }
|
|
41
|
+
}
|
|
42
|
+
return values
|
|
43
|
+
}
|
|
44
|
+
catch {
|
|
45
|
+
throw new Error('Runtime environment file could not be parsed')
|
|
46
|
+
}
|
|
47
|
+
}
|
|
48
|
+
finally {
|
|
49
|
+
closeSync(descriptor)
|
|
50
|
+
}
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
// 托管连接优先级沿用原 env_file 顺序;删除应用字段不会从旧容器环境复活。
|
|
54
|
+
const values = { ...readEnvironment('./.env.runtime'), ...readEnvironment('./middleware.env') }
|
|
55
|
+
// 启动参数与私有代理身份属于部署装配,不由可编辑的业务环境覆盖。
|
|
56
|
+
delete values.NODE_OPTIONS
|
|
57
|
+
delete values.HAI_DEPLOY_PRIVATE_PROXY
|
|
58
|
+
Object.assign(process.env, values)
|
package/dist/index.d.ts
CHANGED
|
@@ -102,11 +102,26 @@ declare const SshConfigSchema: z.ZodObject<{
|
|
|
102
102
|
strictHostKeyChecking: z.ZodDefault<z.ZodBoolean>;
|
|
103
103
|
connectTimeoutSeconds: z.ZodDefault<z.ZodNumber>;
|
|
104
104
|
}, z.core.$strip>;
|
|
105
|
-
/**
|
|
105
|
+
/** HTTP 端口及可选 HTTPS 入口;Let's Encrypt 使用 HTTP-01,HTTP 必须映射 80。 */
|
|
106
106
|
declare const PortExposeSchema: z.ZodObject<{
|
|
107
107
|
type: z.ZodDefault<z.ZodLiteral<"port">>;
|
|
108
108
|
containerPort: z.ZodDefault<z.ZodNumber>;
|
|
109
109
|
hostPort: z.ZodNumber;
|
|
110
|
+
https: z.ZodOptional<z.ZodDiscriminatedUnion<[z.ZodObject<{
|
|
111
|
+
certificateFile: z.ZodString;
|
|
112
|
+
privateKeyFile: z.ZodString;
|
|
113
|
+
domain: z.ZodString;
|
|
114
|
+
port: z.ZodDefault<z.ZodNumber>;
|
|
115
|
+
redirectHttp: z.ZodDefault<z.ZodBoolean>;
|
|
116
|
+
type: z.ZodLiteral<"files">;
|
|
117
|
+
}, z.core.$strip>, z.ZodObject<{
|
|
118
|
+
domain: z.ZodString;
|
|
119
|
+
email: z.ZodEmail;
|
|
120
|
+
acceptTerms: z.ZodLiteral<true>;
|
|
121
|
+
port: z.ZodDefault<z.ZodNumber>;
|
|
122
|
+
redirectHttp: z.ZodDefault<z.ZodBoolean>;
|
|
123
|
+
type: z.ZodLiteral<"letsencrypt">;
|
|
124
|
+
}, z.core.$strip>], "type">>;
|
|
110
125
|
}, z.core.$strip>;
|
|
111
126
|
/** docker-ssh 部署平台配置 */
|
|
112
127
|
declare const DockerSshProviderConfigSchema: z.ZodObject<{
|
|
@@ -137,6 +152,21 @@ declare const DockerSshProviderConfigSchema: z.ZodObject<{
|
|
|
137
152
|
type: z.ZodDefault<z.ZodLiteral<"port">>;
|
|
138
153
|
containerPort: z.ZodDefault<z.ZodNumber>;
|
|
139
154
|
hostPort: z.ZodNumber;
|
|
155
|
+
https: z.ZodOptional<z.ZodDiscriminatedUnion<[z.ZodObject<{
|
|
156
|
+
certificateFile: z.ZodString;
|
|
157
|
+
privateKeyFile: z.ZodString;
|
|
158
|
+
domain: z.ZodString;
|
|
159
|
+
port: z.ZodDefault<z.ZodNumber>;
|
|
160
|
+
redirectHttp: z.ZodDefault<z.ZodBoolean>;
|
|
161
|
+
type: z.ZodLiteral<"files">;
|
|
162
|
+
}, z.core.$strip>, z.ZodObject<{
|
|
163
|
+
domain: z.ZodString;
|
|
164
|
+
email: z.ZodEmail;
|
|
165
|
+
acceptTerms: z.ZodLiteral<true>;
|
|
166
|
+
port: z.ZodDefault<z.ZodNumber>;
|
|
167
|
+
redirectHttp: z.ZodDefault<z.ZodBoolean>;
|
|
168
|
+
type: z.ZodLiteral<"letsencrypt">;
|
|
169
|
+
}, z.core.$strip>], "type">>;
|
|
140
170
|
}, z.core.$strip>;
|
|
141
171
|
trustedEdgeProxies: z.ZodOptional<z.ZodArray<z.ZodUnion<readonly [z.ZodIPv4, z.ZodIPv6, z.ZodCIDRv4, z.ZodCIDRv6]>>>;
|
|
142
172
|
}, z.core.$strip>;
|
|
@@ -182,6 +212,21 @@ declare const ProviderConfigSchema: z.ZodDiscriminatedUnion<[z.ZodObject<{
|
|
|
182
212
|
type: z.ZodDefault<z.ZodLiteral<"port">>;
|
|
183
213
|
containerPort: z.ZodDefault<z.ZodNumber>;
|
|
184
214
|
hostPort: z.ZodNumber;
|
|
215
|
+
https: z.ZodOptional<z.ZodDiscriminatedUnion<[z.ZodObject<{
|
|
216
|
+
certificateFile: z.ZodString;
|
|
217
|
+
privateKeyFile: z.ZodString;
|
|
218
|
+
domain: z.ZodString;
|
|
219
|
+
port: z.ZodDefault<z.ZodNumber>;
|
|
220
|
+
redirectHttp: z.ZodDefault<z.ZodBoolean>;
|
|
221
|
+
type: z.ZodLiteral<"files">;
|
|
222
|
+
}, z.core.$strip>, z.ZodObject<{
|
|
223
|
+
domain: z.ZodString;
|
|
224
|
+
email: z.ZodEmail;
|
|
225
|
+
acceptTerms: z.ZodLiteral<true>;
|
|
226
|
+
port: z.ZodDefault<z.ZodNumber>;
|
|
227
|
+
redirectHttp: z.ZodDefault<z.ZodBoolean>;
|
|
228
|
+
type: z.ZodLiteral<"letsencrypt">;
|
|
229
|
+
}, z.core.$strip>], "type">>;
|
|
185
230
|
}, z.core.$strip>;
|
|
186
231
|
trustedEdgeProxies: z.ZodOptional<z.ZodArray<z.ZodUnion<readonly [z.ZodIPv4, z.ZodIPv6, z.ZodCIDRv4, z.ZodCIDRv6]>>>;
|
|
187
232
|
}, z.core.$strip>], "type">;
|
|
@@ -257,6 +302,21 @@ declare const DeployConfigSchema: z.ZodObject<{
|
|
|
257
302
|
type: z.ZodDefault<z.ZodLiteral<"port">>;
|
|
258
303
|
containerPort: z.ZodDefault<z.ZodNumber>;
|
|
259
304
|
hostPort: z.ZodNumber;
|
|
305
|
+
https: z.ZodOptional<z.ZodDiscriminatedUnion<[z.ZodObject<{
|
|
306
|
+
certificateFile: z.ZodString;
|
|
307
|
+
privateKeyFile: z.ZodString;
|
|
308
|
+
domain: z.ZodString;
|
|
309
|
+
port: z.ZodDefault<z.ZodNumber>;
|
|
310
|
+
redirectHttp: z.ZodDefault<z.ZodBoolean>;
|
|
311
|
+
type: z.ZodLiteral<"files">;
|
|
312
|
+
}, z.core.$strip>, z.ZodObject<{
|
|
313
|
+
domain: z.ZodString;
|
|
314
|
+
email: z.ZodEmail;
|
|
315
|
+
acceptTerms: z.ZodLiteral<true>;
|
|
316
|
+
port: z.ZodDefault<z.ZodNumber>;
|
|
317
|
+
redirectHttp: z.ZodDefault<z.ZodBoolean>;
|
|
318
|
+
type: z.ZodLiteral<"letsencrypt">;
|
|
319
|
+
}, z.core.$strip>], "type">>;
|
|
260
320
|
}, z.core.$strip>;
|
|
261
321
|
trustedEdgeProxies: z.ZodOptional<z.ZodArray<z.ZodUnion<readonly [z.ZodIPv4, z.ZodIPv6, z.ZodCIDRv4, z.ZodCIDRv6]>>>;
|
|
262
322
|
}, z.core.$strip>], "type">;
|
|
@@ -663,7 +723,7 @@ interface DeployCommandState {
|
|
|
663
723
|
*/
|
|
664
724
|
interface DeployAppOptions {
|
|
665
725
|
/** 接收实际执行阶段,用于终端进度显示;不包含凭据或配置原文。 */
|
|
666
|
-
onProgress?: (stage: 'packaging' | 'preflight' | 'images' | 'dependencies' | 'start' | 'health' | 'complete') => void;
|
|
726
|
+
onProgress?: (stage: 'packaging' | 'preflight' | 'images' | 'dependencies' | 'start' | 'https' | 'health' | 'complete') => void;
|
|
667
727
|
/** 只更新指定的 Compose 服务;省略时完整制品部署全部,部分制品只部署其镜像。 */
|
|
668
728
|
selectedServices?: string[];
|
|
669
729
|
/** 打包中间件镜像所用的本地引擎,auto 优先 Podman。 */
|
|
@@ -942,7 +1002,7 @@ declare const deploy: DeployFunctions;
|
|
|
942
1002
|
* const message = deployM('deploy_sshRequired')
|
|
943
1003
|
* ```
|
|
944
1004
|
*/
|
|
945
|
-
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", 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", options?: _h_ai_core.MessageOptions) => string;
|
|
946
1006
|
|
|
947
1007
|
/**
|
|
948
1008
|
* 部署中间件的后端与连接字段目录,供扫描、CLI 和容器规划共同使用。
|
|
@@ -1022,6 +1082,7 @@ declare function describeMiddlewareBackend(backend: MiddlewareBackend): string;
|
|
|
1022
1082
|
|
|
1023
1083
|
/**
|
|
1024
1084
|
* 查看与执行入口相同的扫描、环境、项目身份和制品校验结果。远端 current 只报告为待执行时核验。
|
|
1085
|
+
* 输出 root 是工程根,serviceDir 是读取运行配置、扫描依赖的部署服务目录。
|
|
1025
1086
|
* @example
|
|
1026
1087
|
* ```ts
|
|
1027
1088
|
* import { createDeploymentPlan } from '@h-ai/deploy'
|
|
@@ -1038,7 +1099,7 @@ declare function createDeploymentPlan(appDir: string, input: DeployConfigInput,
|
|
|
1038
1099
|
data: {
|
|
1039
1100
|
projectName: string;
|
|
1040
1101
|
root: string;
|
|
1041
|
-
|
|
1102
|
+
serviceDir: string;
|
|
1042
1103
|
environment: string;
|
|
1043
1104
|
target: {
|
|
1044
1105
|
provider: "docker-ssh";
|
|
@@ -1047,6 +1108,11 @@ declare function createDeploymentPlan(appDir: string, input: DeployConfigInput,
|
|
|
1047
1108
|
directory: string | undefined;
|
|
1048
1109
|
runtime: "auto" | "docker" | "podman";
|
|
1049
1110
|
hostPort: number;
|
|
1111
|
+
https: {
|
|
1112
|
+
type: "files" | "letsencrypt";
|
|
1113
|
+
domain: string;
|
|
1114
|
+
port: number;
|
|
1115
|
+
} | undefined;
|
|
1050
1116
|
} | {
|
|
1051
1117
|
provider: "vercel";
|
|
1052
1118
|
host?: undefined;
|
|
@@ -1054,6 +1120,7 @@ declare function createDeploymentPlan(appDir: string, input: DeployConfigInput,
|
|
|
1054
1120
|
directory?: undefined;
|
|
1055
1121
|
runtime?: undefined;
|
|
1056
1122
|
hostPort?: undefined;
|
|
1123
|
+
https?: undefined;
|
|
1057
1124
|
};
|
|
1058
1125
|
artifact: {
|
|
1059
1126
|
directory: string;
|