@h-ai/deploy 0.1.0-alpha.66 → 0.1.0-alpha.68

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 CHANGED
@@ -2,78 +2,161 @@
2
2
 
3
3
  [简体中文](README.md) | [English](README.en.md) | [日本語](README.ja.md)
4
4
 
5
- Deploy consumes existing artifacts. It never compiles source or builds images. Build once, deploy the same images to multiple environments.
5
+ ## Introduction
6
6
 
7
- Follow the [usage guide](../../docs/usage/README.en.md) for the complete creation, development, build, and deployment workflow. This page focuses on deployment requirements, the SDK, and module development.
7
+ Deploy existing images or Vercel prebuilt output, including complete offline bundles, selected service updates, SSH automation and platform upload scripts. The SDK consumes artifacts; CLI --build explicitly orchestrates build then deployment.
8
8
 
9
- ## Build
9
+ ## Core features
10
10
 
11
- Node `^22.22.2 || ^24.15.0 || >=26.0.0`, pnpm 12.11.2; Windows: `pnpm.cmd`. Node 20 / pnpm 9.5.0 are unsupported.
11
+ - Build, package, upload over SSH, start services and check access from one CLI command.
12
+ - Include application and self-hosted middleware images, or update selected services.
13
+ - Deliver offline tar bundles with Windows/Linux/macOS operator scripts, step results and recovery on failure.
14
+
15
+ ## Getting started
16
+
17
+ ### Prepare build artifacts
18
+
19
+ Projects include deployment tooling by default; use `hai create my-app --no-deploy` to opt out. The deployment SDK is a development dependency and is excluded from runtime images.
12
20
 
13
21
  ```sh
14
- pnpm build # source only; no environment selection
15
- pnpm build --target docker # reachable Podman first, then Docker
16
- pnpm build --target docker --runtime docker
22
+ pnpm build
23
+ pnpm build --target docker
24
+ pnpm build --target docker --images web
17
25
  pnpm build --target desktop --platform windows --arch x64
18
26
  ```
19
27
 
20
- `hai.build.json` describes Docker targets and Tauri directories. Images and SHA-256 manifest are under `.hai/build/docker/<buildId>`. API/Web share one build ID; latest changes only after complete success. Tauri runs on the matching Windows/Linux/macOS host with Rust targets, SDKs and packaging tools installed; installers are under `src-tauri/target/<target>/release/bundle`. Build has no dev/test/prod mode and excludes deployment credentials.
28
+ #### Build options
21
29
 
22
- Versions come from the application root package.json.version. For version 1.2.3, archives are app-1.2.3.tar/web-1.2.3.tar and Compose is docker-compose-1.2.3.yml. Manifest version: 2 is its format; appVersion is the application version. --output release-prod.tar becomes release-prod-1.2.3.tar, and Tauri receives the same root version. See the [complete guide](../../docs/usage/README.en.md) for defaults and examples.
30
+ `--target` selects compile (default), docker or desktop. `--images app|web|app,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.
23
31
 
24
- ## Deployment
32
+ #### Describe packaging in hai.build.json
25
33
 
26
- ```sh
27
- pnpm run deploy --env test
28
- pnpm run deploy --env prod --artifact-dir .hai/build/docker/<buildId> --skip-middleware
29
- pnpm run deploy --env prod --bundle-only --output release-prod.tar
30
- # equivalent fullstack CLI invocation
31
- pnpm exec hai deploy packages/my-app-serv --env prod --env-dir .
34
+ ```json
35
+ { "images": [{ "name": "app", "context": ".", "dockerfile": "images/app.Dockerfile", "containerPort": 3000 }, { "name": "web", "context": ".", "dockerfile": "images/web.Dockerfile", "containerPort": 8080 }] }
32
36
  ```
33
37
 
34
- Requires matching `@h-ai/cli` / `@h-ai/deploy`, `_deploy.yml`, lockfile and `.env.<mode>`. Missing environment files stop deployment. Public `.env`, `.env.dev/test/prod` and documented `.env.example` are committed; private `.env.local` is ignored. Priority: process > local > mode > base. SSH fields/tokens can be stored in private `HAI_DEPLOY_PROVIDER` JSON. Bundle-only needs no SSH config or local container engine.
38
+ Each image has its own Dockerfile. Web runtime assets live in images/web/. Dockerfiles retain internal build/runtime stages; configuration does not select stages. Omit absent images and add desktop directories only for native projects.
39
+
40
+ Generated `web.conf` sets `client_max_body_size 2129920` (2 MiB + 32 KiB) for the API location and disables `proxy_request_buffering` / `proxy_buffering`. This admits encrypted JSON produced from the transport's 1 MiB plaintext budget; the application still checks its smaller 16 KiB handshake, 4 KiB public key and 1 MiB plaintext budgets incrementally. Custom proxies must admit that ciphertext budget and propagate cancellation. Raising a proxy limit does not replace serv/kit's bounded reads; large uploads need an explicit separate route and size policy.
41
+
42
+ Bodyless authenticated envelopes use X-Hai-Transport. Generated proxies set large_client_header_buffers 4 32k and proxy_buffer_size 32k to admit these headers; custom proxies must preserve and admit them.
43
+
44
+ Dependency inputs are prepared under images/dependencies/ from package manifests, local archives and patches. Combine pnpm store caching with stable dependency layers. Source changes should reuse downloaded packages. Empty caches still permit online builds. Windows node_modules cannot supply Linux native dependencies. Offline builds additionally require base images, tools and matching ABI/architecture/libc binaries.
45
+
46
+ The root package.json.version identifies the application. `.hai/build/docker/<buildId>/` contains manifest format 3, selected image archives and SHA-256. partial marks incremental builds and hasWeb records topology. appContainerPort and webContainerPort retain explicitly configured app/web listening ports, including the image left out of a partial build. Omitted ports keep the deployment defaults. Rebuilding the same application version is allowed; unique build IDs/image references distinguish contents. Publish the local build pointer only after all exports succeed. Pin base images, middleware and tools; do not use latest.
47
+
48
+ ### Deploy artifacts
49
+
50
+ #### Prepare the environment and destination
51
+
52
+ Prepare `.env.<environment>` and the service config/_deploy.yml. Fullstack deploy scripts point to packages/<project>-serv; API workspaces use apps/<project>-service. Artifact lookup remains rooted at the build configuration.
53
+
54
+ ```yaml
55
+ provider:
56
+ type: docker-ssh
57
+ expose:
58
+ hostPort: 18080
59
+ container:
60
+ s3Engine: rustfs
61
+ ```
62
+
63
+ For direct deployment, the wizard asks for missing server, SSH user, optional key/fingerprint files and public port settings using readable labels, and reuses complete settings. Local connection settings go to .env.local; private keys are referenced by path. `--bundle-only` skips SSH connection questions; fill in `deploy-target.json` before uploading later.
64
+
65
+ #### Configure only the middleware the application needs
66
+
67
+ Runtime lockfile dependencies and configuration determine middleware. Choose defaults, custom connections or keep settings. --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.
68
+
69
+ #### Deployment options
35
70
 
36
- The wizard traverses only lockfile runtime dependencies, excluding dev/peer. Select default, custom or keep for each middleware; `--skip-middleware` bypasses all middleware work. Compose supports PostgreSQL/MySQL/Redis/RustFS/MinIO/Qdrant/pgvector/Chroma/OpenLDAP/Mailpit. Optional cloud provisioning supports Neon/Upstash/R2/Resend/Aliyun SMS and requires network access.
71
+ --env/--env-dir select configuration. --build builds selected application images before packaging. --services selects Compose services; --artifact-dir selects existing artifacts. --bundle-only creates a tar and platform scripts without SSH. --runtime selects the local build/export engine; --output overrides the archive path, resolved from the command's working directory, and adds the application version suffix. --yes uses valid settings without interaction and reports missing required values.
37
72
 
38
- Optional `container.s3Engine` defaults to rustfs and chooses RustFS/MinIO only when creating a Compose S3 service. Existing custom S3 services are unaffected. Use `--skip-middleware` to bypass middleware setup; the SDK field is `skipMiddleware`.
73
+ #### When the machines can connect: automatic deployment
39
74
 
40
- A single private tar contains Compose, runtime env, app/web images, optional Web proxy, checksums, README and `start-<mode>.sh`. SSH uploads this tar, extracts and starts it remotely. No source upload or remote build. With app/web images, Web exposes the public port and proxies the internal API on the same origin; no API secrets enter Web. Online success requires both health checks. Vercel uploads existing `.vercel/output` , sets runtime variables and never builds locally.
75
+ ```sh
76
+ pnpm run deploy --env prod --build
77
+ pnpm run deploy --env prod --artifact-dir .hai/build/docker/<buildId>
78
+ pnpm run deploy --env prod --build --services web
79
+ ```
80
+
81
+ Partial updates require a successful full server installation and matching ports/layout. Merge selected services into the server's successful baseline; preserve unselected services, settings and volumes. The deployment script first removes only the selected old containers by project and service labels, retaining their volumes. It then runs `compose up -d --no-deps --no-build --pull never --no-recreate web` to create replacements while other containers keep running, without project-wide down. storage-init is a one-time S3 bucket initialization task, executed only when storage initialization is selected.
41
82
 
42
- ## Offline / manual transfer
83
+ Here `-d` starts in the background; `--no-deps` leaves dependencies untouched; `--no-build` prevents server builds; `--pull never` forbids registry pulls; `--no-recreate` preserves containers that still exist; the selected old containers were already removed by the script, so their replacements are created. `web` is a Compose service name, not an image tag; separate multiple services with spaces.
43
84
 
44
- Prepare supported Node/pnpm and installed project CLI/SDK dependencies on Windows, plus the complete prebuilt image directory for the Linux server architecture. Deploy requires tar locally; automatic mode also needs ssh/scp, trusted host keys and reachable SSH/application ports. Bundle-only works with removable media and no network between machines.
85
+ `storage-init` uses the application's S3 SDK to wait for storage and create a missing bucket without deleting data. Start storage first, then run `compose up --no-deps --no-build --pull never --force-recreate --exit-code-from storage-init storage-init`. Start selected application services only after initialization exits with zero. For partial updates, the script first removes the old storage-init container and uses `--no-recreate` instead of `--force-recreate` here, preserving running application containers. Updating only `storage` still requires an artifact containing the `app` image for initialization. If the most recent build contains only Web, select the original complete artifact with `--artifact-dir`, or run `pnpm build --target docker --images app` first. This image is used for initialization without updating the running `app` service.
45
86
 
46
- Linux needs Docker/Podman, compose, sh, tar, sha256sum, writable deployment/data directories and container permissions. Middleware images must already be loaded with the exact names/tags printed in the bundle README; app/web archives are included. Missing images stop startup without downloading. Custom connections require reachable running services, accounts, databases/buckets and credentials.
87
+ #### When the machines cannot connect: copy a bundle
47
88
 
48
89
  ```sh
49
- mkdir -p release && chmod 700 release
50
- tar -xf release-prod-1.2.3.tar -C release
51
- cd release
52
- HAI_DEPLOY_PROVIDER_REMOTE_RUNTIME=docker sh start-prod.sh
90
+ pnpm run deploy --env prod --build --bundle-only
53
91
  ```
54
92
 
55
- The tar contains secrets: restrict permissions and never commit it. `packaged` means no server has been started or health-checked. After manual startup, use `docker compose -f docker-compose-1.2.3.yml --env-file .env.runtime ps` (or logs), then verify Web, /health, real login/refresh, restart and persistence. Production sessions need HTTPS, trusted certificates, DNS and correct CORS; TLS is managed separately.
93
+ Deployment caches, archives and adjacent -deploy/ directories default to `.hai/deploy/<environment>/` at the same project root as `.hai/build/`. Archive names include the project, deployment ID and application version, such as `bundle-demo-<deploymentId>-1.2.3.tar`. An explicit `--output release-prod.tar` instead produces `release-prod-1.2.3.tar` and its adjacent operation directory relative to the command's working directory. 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.
94
+
95
+ On isolated Linux servers, extract into a separate package directory and run `sh apply.sh`, optionally passing the deployment root. Every failed step exits nonzero. Image loading, service startup and HTTP checks are distinct steps. result-<deploymentId>.json records the result; current changes only after successful checks. Reapplying the same deployment ID stops clearly; a newly generated bundle for the same application version is allowed. Failed updates attempt to restore selected containers and configuration while preserving data volumes and diagnostics. Data already written by the application is not rolled back.
96
+
97
+ The server holds a nonblocking kernel lock with util-linux `flock` on `.deploy.lock` in the deployment root, throughout deployment and recovery. Normal foreground deployment and synchronous failure recovery explicitly unlock after finalization and terminal-result publication, so background services do not block later deployments. Keep this file permanently: never delete, replace or steal it based on elapsed time, and use a filesystem that supports `flock`. On HUP/INT/TERM or a killed parent shell, active child commands retain the inherited lock until every holder exits or the server restarts. The old `.deploy-lock` directory is ignored and left untouched; stop old deployment processes before upgrading and avoid mixing old bundles. Forced termination or power loss skips recovery traps. Without a result file, execution is unknown: inspect containers, images and the successful `current` baseline before recovering with a new bundle. An unlocked file does not prove success or rolled-back effects.
56
98
 
57
- Prebuilt deployment needs no local container engine, Linux Node base image, compiler, CUDA or SQLite download. Fully offline **building** separately needs Linux base images, pnpm/Corepack, complete Linux dependency caches and SQLite prebuilds matching driver/ABI/architecture/libc. Windows node_modules are insufficient. Use `pnpm build --target docker --sqlite-prebuild-mirror http://trusted-host/better-sqlite3` when appropriate. No AI runtime dependency means no AI/CUDA installation. Cloud services are unsuitable offline. Prove offline behavior by actually disconnecting; online tests do not establish it.
99
+ #### Before going fully offline
58
100
 
59
- ## SDK / development
101
+ 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.
102
+
103
+ ### SDK
104
+
105
+ ```ts
106
+ import { deploy } from '@h-ai/deploy'
107
+
108
+ const initialized = await deploy.init({ provider: { type: 'docker-ssh', expose: { hostPort: 18080 } } })
109
+ if (!initialized.success)
110
+ throw new Error(initialized.error.message)
111
+ try {
112
+ const result = await deploy.deployApp('./packages/demo-serv', {
113
+ environment: 'prod',
114
+ envDir: '.',
115
+ bundleOnly: true,
116
+ artifactDir: './.hai/build/docker/<buildId>',
117
+ runtime: 'auto',
118
+ })
119
+ if (!result.success)
120
+ throw new Error(result.error.message)
121
+ // result.data.bundlePath / instructions; packaged does not mean server ready.
122
+ }
123
+ finally {
124
+ await deploy.close()
125
+ }
126
+ ```
60
127
 
61
- Call `deploy.init(config)`, check success, then `deploy.deployApp(appDir, { environment: 'prod', envDir: '.', artifactDir, bundleOnly: true })`, check success and finally `deploy.close()`. `deploy.scan` / credentials do not require init. Results return bundlePath/instructions for packaged mode, URL and health status for automatic deployment.
128
+ `selectedServices: ['web']` selects a partial update. `onProgress` receives actual packaging/server stages. `deploy.scan` and `deploy.credentials.*` are available before init. Check HaiResult.success before using data. Vercel uploads existing .vercel/output through the prebuilt API and requires internet; it does not provide offline or Compose partial deployment.
129
+
130
+ Command execution redacts correctly decoded UTF-8 logical streams, including known secrets split across stdout/stderr chunks. Successful captures, errors and output callbacks use the same boundary. Internal command callers must enumerate sensitive literals in `secrets`, including separately encoded or transformed forms. Each stream captures only its last 1 Mi characters by default; `maxCaptureChars` accepts 1 through 16 Mi characters. Check `stdoutTruncated` / `stderrTruncated` before parsing structured output. Async `onOutput` callbacks receive all safe stdout in order with pipe backpressure; deployment progress parses only the first 512 characters of each line. Total secret length is limited to 1 Mi UTF-16 units; invalid redaction fails closed. A timeout reports failure; remote process termination still requires confirmation.
131
+
132
+ Command deadlines include helper startup and output handling. Timeouts, input/output errors and callback failures terminate managed processes. POSIX uses a separate process group. Windows uses an embedded PowerShell/.NET Job Object: create suspended, assign successfully, then resume, with no breakaway. Helper, compilation or assignment failure never falls back to an unmanaged process. System PowerShell and Add-Type are required on Windows; execution is hidden without user profiles, preserving arguments, environment and UTF-8 pipes. POSIX commands must keep descendants in the inherited group; detached system daemons and remote services are outside local termination confirmation.
133
+
134
+ `terminationTimeoutMs` separately bounds failure cleanup verification, default 10000 and maximum 60000 milliseconds. Sending kill is not confirmation. `localTermination` is `confirmed` only after the managed Job/group has no active members, `unknown` if verification fails or expires, and `not-started` before launch. In the `if (!result.success)` branch, call public `getDeployCommandState(result.error)` for the reason and state, without raw exceptions or command arguments. An output callback already entered cannot be undone; failures stop further output delivery.
135
+
136
+ SSH interruptions initially report `remoteExecution: 'unknown'`. The docker-ssh SDK reconnects read-only to inspect `result-<deploymentId>.json`. Only a complete, untruncated terminal record with the matching ID confirms `finished`, with the actual stage and exit code. Finished scripts do not imply stopped containers. Even exit code 0 preserves the original SSH/output failure. CLI shows local and remote states separately with the result path. Missing, stale, damaged or unreadable records remain unknown; deployment and rollback are never retried automatically. Manual upload scripts conservatively report unknown on SSH failure with the inspection directory; find the deployment ID in the bundle manifest. Inspect steps, `current`, actual services and data before recovery.
137
+
138
+ ## Development and testing
62
139
 
63
140
  ```sh
64
141
  pnpm --filter @h-ai/deploy typecheck
65
142
  pnpm --filter @h-ai/deploy lint
66
143
  pnpm --filter @h-ai/deploy build
67
144
  pnpm --filter @h-ai/deploy test
68
- pnpm --filter @h-ai/cli test
145
+ pnpm --filter @h-ai/deploy test:e2e
69
146
  pnpm --filter @h-ai/cli test:scaffold-gates
70
147
  pnpm --filter @h-ai/cli test:deploy-gates
71
148
  ```
72
149
 
73
- Deploy gates generate fullstack from current archives, build API/Web once, exercise SSH and manual bundle startup and run real browser flows. Tests clean temporary projects, images, containers, screenshots/reports and helper processes in finally/teardown even on failure. Native installer acceptance requires each OS. See [configuration and middleware](../cli/templates/skills/hai-deploy/middleware.md) and [complete examples](README.md).
150
+ Real deployment selects API, SSR, static mobile and fullstack representatives. Admin covers the SSR Dockerfile and production deployment branch shared by website/h5; all application types retain their own installation, compilation and HTTP/browser acceptance in the eight scaffold scenarios. Measured resource contention keeps scaffold and generated-route runtime in sequential batches; three smaller CLI gates can share the runtime batch with at most two file workers. Generated scenarios reuse the complete E2E build while preserving production build isolation and actual output checks. CLI deployment gates preserve authentication/transport, incremental updates, damaged artifacts and rollback, and run the production Nginx version against a public deployment bundle with `nginx -t`. Fixtures enable init and verify that adopted orphan PIDs actually disappear.
151
+
152
+ Run actual generated projects and SSH/manual deployment, including an isolated registry environment, incremental updates, damaged archives, same-version releases and failed health checks. Clean only test-owned projects, images, containers, logs and processes in finally/teardown.
153
+
154
+ `test:e2e` builds the current package and enables both Linux lock and process gates in a child process, running the files serially. Root `pnpm e2e` includes this entry. The gates require reachable Podman (preferred) or Docker to run the public API's generated `apply.sh`: concurrent execution, child-held locks after killing the parent, full termination and restart recovery. Compose/HTTP use deterministic fixtures; this does not replace real service deployment acceptance.
155
+
156
+ Process gates run with `pnpm --filter @h-ai/deploy exec vitest run tests/deploy-command-process.test.ts tests/deploy-secret-masker.test.ts`. With the same `HAI_DEPLOY_E2E=1`, build deploy first and run `tests/deploy-command-runtime.e2e.test.ts` for real Linux/OpenSSH, published dist, remote continuation/completion and local process groups. The fixture needs network access to install sshd; Compose/HTTP are deterministic fixtures. It scales deployment deadlines to 2500 milliseconds and pauses output consumption to inject lost acknowledgments.
74
157
 
75
- Deploy gates do not forward host proxies by default. To download build dependencies through a proxy, set test-only `HAI_DEPLOY_E2E_CONTAINER_PROXY` (unset by default), for example `$env:HAI_DEPLOY_E2E_CONTAINER_PROXY='http://host.containers.internal:10808'` in PowerShell for Windows Podman. The address must be reachable from build containers; it is not written to application configuration or release images.
158
+ Deployment fixtures inspect pinned public base images and pull only confirmed missing images; HAI_DEPLOY_E2E_MIRROR remains available. Public image caches are never cleanup targets. A successful create records its container ID before asynchronous APT/pip/sshd preparation inside a private PID namespace. Preparation errors, deadlines and cooperative cancellation wait for the local client to close, then remove and verify that exact owned ID; only the nested Podman fixture is privileged. HAI_DEPLOY_E2E_APT_MIRROR accepts a mirror hostname and keeps HTTPS. Ownership tests use run-specific private tags of pinned public images while preserving foreign same-content tags, retag protection, dynamic ports and external sentinels. A lost create acknowledgment without a trusted ID, or a forcibly terminated test process, remains unknown and never authorizes adoption by name or label.
76
159
 
77
- Test-only `HAI_DEPLOY_E2E_CONTAINER_NETWORK` is unset by default and forwards its value to build's `--network`. For example, rootless Podman can use `$env:HAI_DEPLOY_E2E_CONTAINER_NETWORK='pasta'`. Build and run networks may differ; verify the proxy address on the build network too.
160
+ ## License
78
161
 
79
- On Windows, set test-only HAI_CLI_NATIVE_BUILD=1 (unset by default), then run `pnpm --filter @h-ai/cli test:scaffold-gates -t "fullstack scaffold"`. With Rust/MSVC/Windows SDK installed, it additionally builds the generated Tauri installer and checks that root version 2.4.6 appears in the exe filename. The temporary project and native output are cleaned automatically.
162
+ Apache-2.0
package/README.ja.md CHANGED
@@ -2,78 +2,161 @@
2
2
 
3
3
  [简体中文](README.md) | [English](README.en.md) | [日本語](README.ja.md)
4
4
 
5
- deploy は既存の成果物だけを配布します。ソースのコンパイルやイメージのビルドは行いません。同じイメージを複数環境へ配布できます。
5
+ ## 概要
6
6
 
7
- 作成、開発、ビルド、デプロイの全体は[使用ガイド](../../docs/usage/README.ja.md)を参照してください。本ページではデプロイの準備、SDK、モジュール開発を説明します。
7
+ 既存イメージまたは Vercel prebuilt 成果物を配布します。完全オフライン、サービス選択、SSH 自動化、OS 別の手動配布スクリプトに対応します。SDK は成果物を消費し、CLI --build は構築から配布を明示的に実行します。
8
8
 
9
- ## ビルド
9
+ ## 主な機能
10
10
 
11
- Node `^22.22.2 || ^24.15.0 || >=26.0.0` と pnpm 12.11.2 を使用します。Windows では `pnpm.cmd` を実行してください。Node 20 / pnpm 9.5.0 は対象外です。
11
+ - CLI でビルド、梱包、SSH 転送、起動、アクセス確認を実行。
12
+ - アプリと自前ミドルウェアのイメージを同梱し、選択したサービスだけの更新にも対応。
13
+ - オフライン用 tar と Windows/Linux/macOS 操作スクリプトを生成し、手順の結果と失敗時の復元を扱う。
14
+
15
+ ## 使い始める
16
+
17
+ ### 4. ソースをコンパイルし、配布物を作る
18
+
19
+ デプロイツールは作成時に既定で含まれます。不要な場合は `hai create my-app --no-deploy` を指定します。SDK は開発依存に配置し、実行イメージには含めません。
12
20
 
13
21
  ```sh
14
- pnpm build # ソースだけをコンパイル。環境は選択しない
15
- pnpm build --target docker # 利用可能な Podman、次に Docker
16
- pnpm build --target docker --runtime docker
22
+ pnpm build
23
+ pnpm build --target docker
24
+ pnpm build --target docker --images web
17
25
  pnpm build --target desktop --platform windows --arch x64
18
26
  ```
19
27
 
20
- `hai.build.json` で Dockerfile のステージと Tauri ディレクトリーを指定します。イメージと SHA-256 付きマニフェストは `.hai/build/docker/<buildId>` に出力されます。API/Web は同じビルド ID を使い、すべて成功してから latest を更新します。Tauri は対象の Windows/Linux/macOS 上で実行し、対応する Rust target、SDK、パッケージツールが必要です。インストーラーは `src-tauri/target/<target>/release/bundle` に出力されます。ビルドでは dev/test/prod を選ばず、デプロイの認証情報も取り込みません。
28
+ #### build のオプション
21
29
 
22
- 版はアプリルートの package.json.version を使います。例 1.2.3 では app-1.2.3.tar、web-1.2.3.tar、docker-compose-1.2.3.yml を生成します。マニフェスト形式の版は version: 2、アプリ版は appVersion です。--output release-prod.tar は release-prod-1.2.3.tar になり、Tauri も同じ版を使います。既定値と例は[完全ガイド](../../docs/usage/README.ja.md)を参照してください。
30
+ `--target` は compile(既定)、docker、desktop を選択します。`--images app|web|app,web` は対象イメージを、`--runtime auto|podman|docker` はローカルエンジンを選択します。auto は接続可能な Podman を優先します。`--network` は構築ネットワーク、`--no-http-proxy` は Podman のプロキシ継承無効、`--sqlite-prebuild-mirror` は信頼できる HTTP(S) バイナリ配布元です。ネイティブ配布物には対象 OS の SDK と Rust ツールチェーンが必要です。構築時にデプロイ環境や秘密情報を読み込みません。
23
31
 
24
- ## デプロイ
32
+ #### hai.build.json でパッケージの構成を指定する
25
33
 
26
- ```sh
27
- pnpm run deploy --env test
28
- pnpm run deploy --env prod --artifact-dir .hai/build/docker/<buildId> --skip-middleware
29
- pnpm run deploy --env prod --bundle-only --output release-prod.tar
30
- # fullstack で同じ処理を直接呼ぶ場合
31
- pnpm exec hai deploy packages/my-app-serv --env prod --env-dir .
34
+ ```json
35
+ { "images": [{ "name": "app", "context": ".", "dockerfile": "images/app.Dockerfile", "containerPort": 3000 }, { "name": "web", "context": ".", "dockerfile": "images/web.Dockerfile", "containerPort": 8080 }] }
32
36
  ```
33
37
 
34
- 対応する版の `@h-ai/cli` / `@h-ai/deploy`、`_deploy.yml`、lockfile、`.env.<mode>` が必要です。環境ファイルがなければ処理を停止します。公開設定の `.env`、`.env.dev/test/prod` と説明付き `.env.example` は Git に登録し、私有の `.env.local` は除外します。優先順位はプロセス変数 > local > 環境別 > 基本設定です。SSH の接続情報やトークンは私有の `HAI_DEPLOY_PROVIDER` JSON に保存できます。bundle-only では SSH 設定やローカルのコンテナーエンジンは不要です。
38
+ 各イメージに独立した Dockerfile を用意します。Web 用設定は images/web/ に置きます。Dockerfile 内の構築・実行段階は維持しますが、設定から段階を選びません。不要なイメージ項目は削除し、desktop ディレクトリは対象プロジェクトのみ設定します。
39
+
40
+ 生成する `web.conf` は API location に `client_max_body_size 2129920`(2 MiB + 32 KiB)を設定し、`proxy_request_buffering` / `proxy_buffering` を無効にします。transport の平文 1 MiB を暗号化した JSON を通過させ、アプリ側では鍵交換 16 KiB、公開鍵 4 KiB、平文 1 MiB の制限を逐次検証します。独自プロキシでも暗号文の上限を許可し、キャンセルを伝播してください。プロキシ上限の変更だけでは serv/kit の有界読み取りを代替できません。大容量アップロードは専用パスと容量ポリシーを用意します。
41
+
42
+ 本文なし認証封装には X-Hai-Transport を使います。生成設定は large_client_header_buffers 4 32k と proxy_buffer_size 32k を指定します。独自プロキシもこのヘッダーを保持し、通過させてください。
43
+
44
+ 構築器はパッケージ情報、ローカルアーカイブとパッチを images/dependencies/ に準備し、pnpm store と依存レイヤーをキャッシュします。通常のソース変更で全依存を再ダウンロードしない構成です。キャッシュが空でもオンライン構築できます。Windows の node_modules は Linux のネイティブ依存を代替できません。完全オフライン構築には基底イメージ、ツールと一致する ABI・アーキテクチャ・libc のバイナリも準備します。
45
+
46
+ アプリの版はルート package.json.version で管理します。`.hai/build/docker/<buildId>/` に形式 3 の manifest.json、選択イメージの tar と SHA-256 を出力します。partial は部分構築、hasWeb は構成を記録します。appContainerPort と webContainerPort は明示した app/web の待受ポートを保持し、部分構築で選ばなかったイメージのポートも失いません。未指定のポートにはデプロイ時の既定値を使います。同じアプリ版でも再構築可能で、構築 ID とイメージ参照で内容を区別します。全出力に成功してからローカルの構築参照を更新します。基底・ミドルウェア・ツールは版を固定し、latest を使いません。
47
+
48
+ ### 5. 成果物を対象環境へデプロイする
49
+
50
+ #### 環境と接続先を用意する
51
+
52
+ `.env.<環境>` とサービスの config/_deploy.yml を用意します。fullstack の deploy は packages/<プロジェクト>-serv、API workspace は apps/<プロジェクト>-service を指定します。これは設定と実行依存の走査入口で、成果物は構築設定のルートから読み込みます。
53
+
54
+ ```yaml
55
+ provider:
56
+ type: docker-ssh
57
+ expose:
58
+ hostPort: 18080
59
+ container:
60
+ s3Engine: rustfs
61
+ ```
62
+
63
+ 直接デプロイでは、サーバー、SSH ユーザー、任意の鍵・指紋ファイル、公開ポートの不足項目を説明付きで質問し、完全な設定は再利用します。接続情報は .env.local、秘密鍵はパスのみ保存します。`--bundle-only` では SSH 接続情報を質問せず、後でアップロードする前に `deploy-target.json` に設定します。
64
+
65
+ #### 本当に必要なミドルウェアだけを設定する
66
+
67
+ 実行依存と設定に基づき、既定、自分の接続、設定維持を選びます。--skip-middleware は設定と開通を省略します。SQLite、メモリーキャッシュ、ローカル保存には外部イメージがありません。完全配布物には自前ミドルウェアのイメージも自動で含めます。外部サービスは接続先への到達性が必要で、クラウド開通はオフライン処理ではありません。
68
+
69
+ #### deploy のオプション
35
70
 
36
- ウィザードは lockfile の実行時依存だけをたどり、dev/peer を除外します。ミドルウェアごとに既定構成、独自構成、既存設定の保持を選べます。`--skip-middleware` はミドルウェア処理全体を省略します。Compose は PostgreSQL/MySQL/Redis/RustFS/MinIO/Qdrant/pgvector/Chroma/OpenLDAP/Mailpit に対応します。任意のクラウド作成は Neon/Upstash/R2/Resend/Aliyun SMS に対応し、ネットワーク接続が必要です。
71
+ --env/--env-dir は環境、--build は先行する選択イメージ構築、--services は更新対象、--artifact-dir は既存成果物を指定します。--bundle-only は SSH 接続なしで tar と OS 別スクリプトを生成します。--runtime はローカル構築・イメージ出力エンジンです。--output はコマンドの作業ディレクトリを基準とする出力先を指定し、アプリ版を末尾に付けます。--yes は有効な設定を非対話で使い、不足値はエラーで示します。一体化構築でも --network、--no-http-proxy、--sqlite-prebuild-mirror を指定できます。
37
72
 
38
- `container.s3Engine` は任意で、既定値は rustfs です。Compose で S3 サービスを自動作成するときだけ RustFS/MinIO を選び、独自の既存 S3 には影響しません。ミドルウェア処理の省略は CLI の `--skip-middleware`、SDK の `skipMiddleware` で指定します。
73
+ #### マシン同士が接続できる場合:自動デプロイ
39
74
 
40
- 一つの私有 tar に Compose、実行時の環境変数、app/web イメージ、必要な Web プロキシ、チェックサム、README、`start-<mode>.sh` をまとめます。SSH でこの tar を転送し、リモートで展開・起動します。ソースの転送やリモートビルドは行いません。app/web 構成では Web の公開ポートから同一オリジンで内部 API に接続し、API の秘密情報は Web に渡しません。自動デプロイの成功には両方のヘルスチェック通過が必要です。Vercel は既存の `.vercel/output` を転送して実行時変数を設定し、ローカルビルドは行いません。
75
+ ```sh
76
+ pnpm run deploy --env prod --build
77
+ pnpm run deploy --env prod --artifact-dir .hai/build/docker/<buildId>
78
+ pnpm run deploy --env prod --build --services web
79
+ ```
80
+
81
+ 部分更新には成功済みの完全インストールと一致するポート・構成が必要です。Compose 標準の設定合成で未選択サービス、設定、ボリュームを保持します。スクリプトはプロジェクト名とサービス名で選択した旧コンテナーだけを削除し、ボリュームを保持します。その後 `compose up -d --no-deps --no-build --pull never --no-recreate web` で新しいコンテナーを作成します。他のコンテナーは稼働したままで、全体の down は実行しません。storage-init は S3 バケットの一時初期化処理で、ストレージ初期化を伴う場合に限り実行します。
41
82
 
42
- ## オフラインと手動転送
83
+ `-d` はバックグラウンド起動、`--no-deps` は依存サービスを更新しない指定、`--no-build` はサーバーでの構築禁止、`--pull never` は取得禁止、`--no-recreate` は残っているコンテナーを保持します。選択した旧コンテナーは事前に削除されているため、新しいコンテナーが作成されます。末尾の `web` は Compose サービス名で、複数指定は空白で区切ります。
43
84
 
44
- Windows 側に対応する Node/pnpm、インストール済みの CLI/SDK 依存関係、Linux サーバーのアーキテクチャーに合う構築済みイメージのディレクトリー全体を準備します。ローカルには tar が必要です。自動転送では ssh/scp、信頼済みホスト鍵、SSH とアプリのポートへの接続も必要です。bundle-only なら、二台の間にネットワークがなくても外部メディアで運べます。
85
+ `storage-init` はアプリの S3 SDK でストレージの準備を待ち、不足するバケットを作成します。既存データは削除しません。storage 起動後に `compose up --no-deps --no-build --pull never --force-recreate --exit-code-from storage-init storage-init` を実行し、終了コード 0 を確認してアプリを起動します。 部分更新では旧 storage-init コンテナーを先に削除し、このコマンドの `--force-recreate` を `--no-recreate` に替えて、稼働中のアプリを保持します。`storage` だけを更新する場合も、初期化のために `app` イメージを含む成果物が必要です。直近のビルドが Web のみなら、`--artifact-dir` で元の完全な成果物を選ぶか、先に `pnpm build --target docker --images app` を実行します。このイメージは初期化に使い、稼働中の `app` サービスは更新しません。
45
86
 
46
- Linux 側には Docker/Podman、compose、sh、tar、sha256sum、書き込み可能な配布・データディレクトリー、コンテナー操作権限が必要です。ミドルウェアイメージは tar 内の README に記載された名前とタグで読み込んでください。app/web のアーカイブは同梱されます。イメージが不足すると、ダウンロードせずに起動を停止します。独自接続では利用可能なサービス、アカウント、DB/バケット、認証情報を準備します。
87
+ #### マシン同士が接続できない場合:パッケージをコピー
47
88
 
48
89
  ```sh
49
- mkdir -p release && chmod 700 release
50
- tar -xf release-prod-1.2.3.tar -C release
51
- cd release
52
- HAI_DEPLOY_PROVIDER_REMOTE_RUNTIME=docker sh start-prod.sh
90
+ pnpm run deploy --env prod --build --bundle-only
53
91
  ```
54
92
 
55
- tar には秘密情報が含まれるため、アクセス権を制限し、Git に登録しないでください。`packaged` はサーバー起動やヘルスチェックをまだ行っていない状態です。手動起動後は `docker compose -f docker-compose-1.2.3.yml --env-file .env.runtime ps`(または logs)、Web、/health、実際のログインと再読み込み、再起動とデータ保持を確認します。本番のセッションには HTTPS、信頼できる証明書、DNS、正しい CORS が必要で、TLS は別途設定します。
93
+ 既定では `.hai/build/` と同じプロジェクトルートの `.hai/deploy/<環境>/` にデプロイキャッシュ、tar と隣接する -deploy/ 操作ディレクトリを生成します。アーカイブ名はプロジェクト名、配置 ID、アプリ版を含み、例は `bundle-demo-<配置ID>-1.2.3.tar` です。`--output release-prod.tar` を明示すると、コマンドの作業ディレクトリを基準に release-prod-1.2.3.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 に移す場合、これらのパスを移動先の実ファイルに合わせます。
94
+
95
+ 隔離された Linux では独立ディレクトリに展開し、`sh apply.sh` を実行します。引数で配置先を上書きできます。各段階の失敗は非ゼロ終了し、イメージ導入・起動・HTTP 検査を別々に報告します。result-<配置ID>.json に結果を記録し、成功時だけ current を更新します。同じ配置 ID の再適用は停止しますが、同じアプリ版から生成した新しい配布物は適用できます。更新失敗時は対象コンテナーと設定を以前の状態に戻すことを試み、データボリュームと診断情報を保持します。すでに書き込まれた業務データは元に戻しません。
96
+
97
+ サーバーは util-linux の `flock` で配置ルートの `.deploy.lock` に非ブロッキングのカーネルロックを取得し、復元処理の終了まで保持します。通常の前景配置と同期の失敗復元は、後処理と終端結果の公開後に明示解放し、背景サービスの稼働は次の配置を妨げません。このファイルは残し、削除・置換・経過時間による横取りをしないでください。対応するファイルシステムが必要です。HUP/INT/TERM または親 shell の強制終了時は、記述子を継承した実行中の子コマンドが全 holder の終了かサーバー再起動までロックを保持します。旧 `.deploy-lock` ディレクトリは判定に使わず削除もしません。更新前に旧配置プロセスを終了し、旧パッケージを併用しないでください。強制終了・停電では復元 trap が動きません。結果ファイルがなければ実行状態は不明です。コンテナー、イメージ、成功した `current` を確認して新しいパッケージで復旧してください。ロック解放は成功や副作用の取消を意味しません。
56
98
 
57
- 構築済み成果物の配布には、ローカルのコンテナーエンジン、Linux Node ベースイメージ、コンパイラー、CUDA、SQLite のダウンロードは不要です。完全オフラインでの**ビルド**には、別途 Linux ベースイメージ、pnpm/Corepack、Linux 用依存キャッシュ一式、driver/ABI/アーキテクチャー/libc が一致する SQLite バイナリーが必要です。Windows の node_modules だけでは足りません。必要に応じて `pnpm build --target docker --sqlite-prebuild-mirror http://trusted-host/better-sqlite3` を使えます。AI の実行時依存がなければ AI/CUDA は不要です。クラウドサービスはオフラインでは使えません。完全オフラインの動作は実際に接続を切って確認してください。
99
+ #### 完全オフラインの前に確認する
58
100
 
59
- ## SDK とモジュール開発
101
+ 完全 tar は自前ミドルウェアのアーカイブと一致するアーキテクチャを含み、起動時にレジストリーへ接続しません。Linux に Docker/Podman、Docker Compose v2 または podman-compose 1.6.0 以降、sh、tar、sha256sum、awk、curl、util-linux の flock、ディレクトリ・コンテナー権限が必要です。秘密設定を安全に転送し、版間でボリューム識別を保持します。外部ネットワークを切って起動、ログイン、再読込、再起動と永続化を検証します。HTTPS、証明書、DNS、外部サービスは別途用意します。
102
+
103
+ ### SDK
104
+
105
+ ```ts
106
+ import { deploy } from '@h-ai/deploy'
107
+
108
+ const initialized = await deploy.init({ provider: { type: 'docker-ssh', expose: { hostPort: 18080 } } })
109
+ if (!initialized.success)
110
+ throw new Error(initialized.error.message)
111
+ try {
112
+ const result = await deploy.deployApp('./packages/demo-serv', {
113
+ environment: 'prod',
114
+ envDir: '.',
115
+ bundleOnly: true,
116
+ artifactDir: './.hai/build/docker/<buildId>',
117
+ runtime: 'auto',
118
+ })
119
+ if (!result.success)
120
+ throw new Error(result.error.message)
121
+ // result.data.bundlePath / instructions; packaged does not mean server ready.
122
+ }
123
+ finally {
124
+ await deploy.close()
125
+ }
126
+ ```
60
127
 
61
- `deploy.init(config)` の成功を確認してから `deploy.deployApp(appDir, { environment: 'prod', envDir: '.', artifactDir, bundleOnly: true })` を呼び、結果を確認し、最後に `deploy.close()` を実行します。`deploy.scan` と credentials は初期化不要です。packaged の結果には bundlePath/instructions、自動デプロイの結果には URL とヘルス状態が入ります。
128
+ `selectedServices: ['web']` は部分更新を選択し、`onProgress` はパッケージ作成とサーバー実行の段階を通知します。`deploy.scan` と `deploy.credentials.*` は初期化前も使用できます。HaiResult.success を確認してからデータを読み取ります。Vercel は既存 .vercel/output を prebuilt API でアップロードするためネット接続が必要で、オフラインや Compose の部分公開には対応しません。
129
+
130
+ コマンド出力は正しく UTF-8 デコードした論理ストリーム単位で秘匿し、stdout/stderr のチャンク境界をまたぐ既知の秘密も保護します。成功結果、エラー、出力コールバックは同じ境界を使います。内部コマンドの `secrets` に機密リテラルを指定し、変換・エンコードした値も別途指定してください。各ストリームは既定で末尾 1 Mi 文字を保持し、`maxCaptureChars` は 1~16 Mi 文字です。構造化出力の解析前に `stdoutTruncated` / `stderrTruncated` を確認します。非同期 `onOutput` を順に待ち pipe の背圧を保ち、安全な stdout 全体を渡します。進捗解析は各行の先頭 512 文字のみです。秘密の合計上限は UTF-16 で 1 Mi 単位、秘匿失敗は処理失敗とします。タイムアウトだけでリモートプロセスの終了を断定せず、終了を確認してください。
131
+
132
+ コマンド期限は helper 起動と出力処理を含みます。タイムアウト、入出力・コールバック失敗時は管理対象プロセスを終了します。POSIX は独立したプロセスグループ、Windows は内嵌 PowerShell/.NET Job Object を使い、停止状態で作成して割当成功後だけ再開します。breakaway は許可せず、helper・コンパイル・割当失敗時に裸のプロセスへ切り替えません。Windows はシステム PowerShell と Add-Type が必要です。非表示で profile を読み込まず、引数・環境・UTF-8 pipe を保持します。POSIX の子孫は同じグループを継承してください。独立したシステム daemon と遠隔サービスはローカル終了確認の対象外です。
133
+
134
+ 失敗後の確認待ちは `terminationTimeoutMs`(既定 10000、最大 60000 ミリ秒)です。kill 送信だけでは確認とせず、管理対象 Job/グループの活動メンバーがなくなった場合だけ `localTermination: 'confirmed'`、確認失敗・期限切れは `unknown`、起動前は `not-started` を記録します。`if (!result.success)` 内で公開 `getDeployCommandState(result.error)` を使い、原始例外やコマンド引数を含まない状態を読みます。実行中の非同期出力 callback は取り消せませんが、失敗後に新しい出力を渡しません。
135
+
136
+ SSH 中断は最初に `remoteExecution: 'unknown'` とし、docker-ssh SDK は別接続で `result-<deploymentId>.json` を読みます。完全で未切断、ID が一致する終端結果だけ `finished` と実際の段階・終了値を確認できます。script 終了はコンテナー停止を意味しません。終了値が 0 でも元の SSH/出力失敗は失敗として残します。CLI はローカルと遠隔の状態と結果パスを別々に表示します。欠落・旧 ID・破損・再接続失敗は不明のまま、配置や rollback を自動再実行しません。手動アップロード script は SSH 失敗を不明と表示し、確認先を示します。配置 ID はパッケージの manifest で確認します。手順、`current`、実サービスとデータを確認して復旧してください。
137
+
138
+ ## 開発とテスト
62
139
 
63
140
  ```sh
64
141
  pnpm --filter @h-ai/deploy typecheck
65
142
  pnpm --filter @h-ai/deploy lint
66
143
  pnpm --filter @h-ai/deploy build
67
144
  pnpm --filter @h-ai/deploy test
68
- pnpm --filter @h-ai/cli test
145
+ pnpm --filter @h-ai/deploy test:e2e
69
146
  pnpm --filter @h-ai/cli test:scaffold-gates
70
147
  pnpm --filter @h-ai/cli test:deploy-gates
71
148
  ```
72
149
 
73
- デプロイのゲートは現在のソースをパッケージ化して fullstack を生成し、API/Web を一度構築してから、SSH と手動 tar の起動、実際のブラウザー操作を検証します。失敗時も finally/teardown で一時プロジェクト、イメージ、コンテナー、スクリーンショット・レポート、補助プロセスを削除します。ネイティブインストーラーは各 OS での確認が必要です。[設定とミドルウェア](../cli/templates/skills/hai-deploy/middleware.md)、[詳細な例](README.md)も参照してください。
150
+ 実配置は API、SSR、静的モバイル、fullstack を代表として選びます。admin は website/h5 と共通の SSR Dockerfile と本番配置分岐を検証し、全アプリ種別の個別インストール、コンパイル、HTTP/ブラウザー検証は八つの scaffold シナリオで維持します。実測の資源競合に基づき scaffold と生成ルート runtime は逐次バッチとし、三つの軽い CLI ゲートは runtime と最大二つの worker で並列実行できます。生成シナリオは E2E の完全構築を再利用し、本番構築分離と実成果物の検証を維持します。CLI 配置ゲートは認証/暗号化、増分更新、破損成果物と復旧を維持し、本番と同じ Nginx で公開 bundle に `nginx -t` を実行します。fixture は init を有効化し、引き取った孤児 PID の実消失を検証します。
151
+
152
+ 実際の生成プロジェクト、SSH と手動公開を検証します。レジストリー接続禁止、部分更新、破損アーカイブ、同一版での再公開、ヘルスチェック失敗を含めます。finally/teardown ではテスト自身が作成したプロジェクト、イメージ、コンテナー、ログ、プロセスのみを削除します。
153
+
154
+ `test:e2e` は現在のパッケージをビルドし、子プロセスで Linux のロックとプロセスの両ゲートを有効にしてファイルを順番に実行します。ルートの `pnpm e2e` もこの入口を含みます。接続可能な Podman(優先)または Docker を使い、公開 API が生成した `apply.sh` を実行します。同時実行、親の強制終了後の子によるロック保持、全終了と再起動からの復旧を確認します。Compose/HTTP は決定的なテスト用実装で、実サービス公開の検証を代替しません。
155
+
156
+ プロセス専用ゲートは `pnpm --filter @h-ai/deploy exec vitest run tests/deploy-command-process.test.ts tests/deploy-secret-masker.test.ts` です。同じ `HAI_DEPLOY_E2E=1` を設定し、deploy をビルドしてから `tests/deploy-command-runtime.e2e.test.ts` を実行すると、実 Linux/OpenSSH、公開 dist、遠隔の継続・完了、ローカルグループを検証します。sshd 導入にネットワークが必要で、Compose/HTTP はテスト用実装です。配置期限を 2500 ミリ秒に短縮し、出力消費を停止して応答喪失を再現します。
74
157
 
75
- デプロイのゲートは既定でホストのプロキシを転送しません。依存のダウンロードに必要な場合、テスト専用 `HAI_DEPLOY_E2E_CONTAINER_PROXY`(既定は未設定)を設定します。Windows Podman の PowerShell の例は `$env:HAI_DEPLOY_E2E_CONTAINER_PROXY='http://host.containers.internal:10808'` です。ビルドコンテナーから到達できるアドレスを使い、アプリ設定や配布イメージには保存しません。
158
+ デプロイ用 fixture は固定版の公開基盤イメージを確認し、不在を確認した場合だけ取得します。HAI_DEPLOY_E2E_MIRROR を利用でき、公開キャッシュは回収対象にしません。create 成功時のコンテナー ID を先に記録し、専用 PID namespace 内で APT/pip/sshd を非同期準備します。準備失敗、期限超過、協調的取消ではローカルクライアントの終了を待ち、記録した ID だけを削除して消失を確認します。特権を使うのはネストした Podman fixture のみです。HAI_DEPLOY_E2E_APT_MIRROR はホスト名のみを受け付け、HTTPS を維持します。所有権テストは固定公開イメージに実行専用 tag を付け、同じ内容の外部 tag、tag の付け替え、動的ポート、外部 sentinel の保護を維持します。create の応答喪失で信頼できる ID がない場合や、テストが強制終了した場合は不明状態を残し、名前や label を根拠に回収しません。
76
159
 
77
- テスト専用 `HAI_DEPLOY_E2E_CONTAINER_NETWORK` は既定では未設定で、設定値を build の `--network` に渡します。rootless Podman の例は `$env:HAI_DEPLOY_E2E_CONTAINER_NETWORK='pasta'` です。build と run ではネットワークが異なる場合があるため、ビルド側でプロキシの到達性も確認してください。
160
+ ## ライセンス
78
161
 
79
- Windows ではテスト専用 HAI_CLI_NATIVE_BUILD=1(既定は未設定)を指定し、`pnpm --filter @h-ai/cli test:scaffold-gates -t "fullstack scaffold"` を実行できます。Rust/MSVC/Windows SDK が必要で、生成 Tauri インストーラーの exe 名にルート版 2.4.6 が反映されることを確認します。一時プロジェクトとネイティブ出力も自動削除します。
162
+ Apache-2.0