@h-ai/deploy 0.1.0-alpha.63 → 0.1.0-alpha.65
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 +134 -175
- package/README.ja.md +134 -175
- package/README.md +133 -175
- package/dist/index.d.ts +173 -6
- package/dist/index.js +631 -255
- package/dist/index.js.map +1 -1
- package/package.json +2 -2
package/README.en.md
CHANGED
|
@@ -2,242 +2,201 @@
|
|
|
2
2
|
|
|
3
3
|
[简体中文](./README.md) | [English](./README.en.md) | [日本語](./README.ja.md)
|
|
4
4
|
|
|
5
|
-
[Framework home](../../README.en.md) ·
|
|
5
|
+
[Framework home](../../README.en.md) · [CLI](../cli/README.en.md) · [Environment and middleware](../cli/templates/skills/hai-deploy/middleware.md)
|
|
6
6
|
|
|
7
|
-
|
|
7
|
+
Deployment SDK used by the `hai deploy` command in `@h-ai/cli`. It also runs independently in Node.js scripts.
|
|
8
8
|
|
|
9
|
-
##
|
|
9
|
+
## Features and scope
|
|
10
10
|
|
|
11
|
-
|
|
|
12
|
-
| ------------ |
|
|
13
|
-
| `
|
|
14
|
-
| `
|
|
11
|
+
| Target | Application | Operation |
|
|
12
|
+
| ------------ | --------------------------------------------------- | ----------------------------------------------------------------------------------- |
|
|
13
|
+
| `docker-ssh` | Native Node services or SvelteKit with adapter-node | Build locally, upload over SSH, run Compose on Linux and check HTTP health |
|
|
14
|
+
| `vercel` | SvelteKit with adapter-vercel | Build, upload, set environment variables and wait for deployment; requires internet |
|
|
15
15
|
|
|
16
|
-
|
|
16
|
+
- Follow runtime dependencies and workspace links from the target importer in `pnpm-lock.yaml`, excluding development dependencies and peers. Application configuration selects middleware backends. Optional AI peers do not enable AI/CUDA.
|
|
17
|
+
- Select an environment and require `.env.<mode>` before choosing defaults, custom connections or keep unchanged per middleware. Complete environments can skip all middleware processing.
|
|
18
|
+
- Compose supports PostgreSQL, MySQL, Redis, RustFS/MinIO, Qdrant, pgvector, Chroma, OpenLDAP and Mailpit. SQLite, memory, local and LanceDB use their respective local storage. Mailpit captures test mail only.
|
|
19
|
+
- Cloud provisioning supports Neon, Upstash, Cloudflare R2, Resend and Alibaba Cloud SMS. R2 needs existing S3 credentials, Resend a verified sender domain, and SMS approved signatures/templates. Use custom connections for other backends.
|
|
17
20
|
|
|
18
|
-
|
|
19
|
-
| ------------ | ------------- | ------------------------------- |
|
|
20
|
-
| Database | Neon | PostgreSQL Serverless |
|
|
21
|
-
| Cache | Upstash | Redis TCP + TLS |
|
|
22
|
-
| Storage | Cloudflare R2 | S3-compatible object storage |
|
|
23
|
-
| Email | Resend | SMTP (existing verified domain) |
|
|
24
|
-
| SMS | Alibaba Cloud | Alibaba Cloud SMS |
|
|
21
|
+
**Fullstack API and Web are separate deployments.** `hai deploy packages/my-app-serv` deploys the API only. The root template Dockerfile has `runtime` and `web` targets for API and static Web images. Upload and run Web separately, setting `PUBLIC_API_BASE` and API CORS. There is no command to publish both together, nor automatic domain, TLS or reverse proxy configuration.
|
|
25
22
|
|
|
26
|
-
##
|
|
23
|
+
## Command-line deployment
|
|
27
24
|
|
|
28
|
-
|
|
29
|
-
import { deploy } from '@h-ai/deploy'
|
|
25
|
+
### 1. Install and prepare
|
|
30
26
|
|
|
31
|
-
|
|
32
|
-
deploy.credentials.load()
|
|
27
|
+
Node must satisfy `^22.22.2 || ^24.15.0 || >=26.0.0`; generated projects pin `pnpm@12.11.2`. Node 20 / pnpm 9.5.0 are unsupported. Use `pnpm.cmd` in Windows PowerShell.
|
|
33
28
|
|
|
34
|
-
|
|
35
|
-
await deploy.init({
|
|
36
|
-
provider: { type: 'vercel', token: 'vel_xxx' },
|
|
37
|
-
services: {
|
|
38
|
-
db: { provisioner: 'neon', apiKey: 'neon_xxx' },
|
|
39
|
-
cache: { provisioner: 'upstash', email: 'a@b.com', apiKey: 'up_xxx' },
|
|
40
|
-
},
|
|
41
|
-
})
|
|
29
|
+
In the generated workspace root, install CLI/SDK versions matching the application's framework and retain the lockfile. Installation needs a package source or complete offline dependencies:
|
|
42
30
|
|
|
43
|
-
|
|
44
|
-
|
|
31
|
+
```powershell
|
|
32
|
+
pnpm.cmd add -Dw @h-ai/cli @h-ai/deploy
|
|
33
|
+
pnpm.cmd exec hai --help
|
|
34
|
+
```
|
|
45
35
|
|
|
46
|
-
|
|
47
|
-
const provisions = await deploy.provisionAll('my-app')
|
|
36
|
+
Creation with `--features deploy` already adds the local SDK, but does not install a global `hai`. With a global CLI, run `hai deploy` directly. The template's `pnpm run deploy` packages artifacts; it does not invoke this deployment command.
|
|
48
37
|
|
|
49
|
-
|
|
50
|
-
const result = await deploy.deployApp('./apps/my-app')
|
|
38
|
+
For docker-ssh, prepare:
|
|
51
39
|
|
|
52
|
-
|
|
53
|
-
|
|
40
|
+
- A running local Docker/Podman engine capable of building Linux images for the server architecture. Windows needs the corresponding virtualization/WSL2/VM environment; a client alone is insufficient. `auto` prefers Podman; Docker can be selected explicitly.
|
|
41
|
+
- Local `ssh` and `scp`, noninteractive key/agent authentication and the server host fingerprint.
|
|
42
|
+
- Remote Docker/Podman with its `compose` command. The SSH user must run containers and write the deployment directory. Windows must reach SSH and the exposed application port.
|
|
43
|
+
- `config/_deploy.yml` in the target package and `.env.prod` or `.env.test` in the environment directory. Missing environment files stop deployment.
|
|
54
44
|
|
|
55
|
-
|
|
45
|
+
### 2. Configure target and environment
|
|
56
46
|
|
|
57
|
-
|
|
47
|
+
Minimal `config/_deploy.yml` for Docker; supply machine-specific target details through the whole-object `HAI_DEPLOY_PROVIDER` override in `.env.local`:
|
|
58
48
|
|
|
59
49
|
```yaml
|
|
60
|
-
# config/_deploy.yml
|
|
61
50
|
provider:
|
|
62
|
-
type:
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
provisioner: neon
|
|
68
|
-
apiKey: ${HAI_DEPLOY_NEON_API_KEY}
|
|
69
|
-
cache:
|
|
70
|
-
provisioner: upstash
|
|
71
|
-
email: ${HAI_DEPLOY_UPSTASH_EMAIL}
|
|
72
|
-
apiKey: ${HAI_DEPLOY_UPSTASH_API_KEY}
|
|
51
|
+
type: docker-ssh
|
|
52
|
+
container:
|
|
53
|
+
runtime: docker
|
|
54
|
+
s3Engine: rustfs
|
|
55
|
+
services: {}
|
|
73
56
|
```
|
|
74
57
|
|
|
75
|
-
|
|
76
|
-
such as `HAI_DEPLOY_PROVIDER_TOKEN` are also set, the convention-based variables take precedence.
|
|
77
|
-
|
|
78
|
-
Use `deploy.credentials.*` to manage credential files explicitly in scripts or the CLI:
|
|
58
|
+
Replace the host, user, ports and key path for your environment. Never commit `.env.local`:
|
|
79
59
|
|
|
80
|
-
```
|
|
81
|
-
|
|
82
|
-
deploy.credentials.save('HAI_DEPLOY_VERCEL_TOKEN', 'vel_xxx')
|
|
83
|
-
deploy.credentials.saveAll({
|
|
84
|
-
HAI_DEPLOY_NEON_API_KEY: 'neon_xxx',
|
|
85
|
-
})
|
|
60
|
+
```dotenv
|
|
61
|
+
HAI_DEPLOY_PROVIDER='{"type":"docker-ssh","ssh":{"host":"10.0.0.20","port":22,"username":"deploy","identityFile":"C:/Users/me/.ssh/hai_deploy"},"remote":{"baseDir":"/opt/hai/apps","runtime":"docker"},"expose":{"type":"port","containerPort":3000,"hostPort":18080}}'
|
|
86
62
|
```
|
|
87
63
|
|
|
88
|
-
|
|
64
|
+
Alternatively, the wizard asks for missing target details, saves them in `.env.local` and reuses them. Store private key paths only. Edit `HAI_DEPLOY_PROVIDER` to switch a complete target.
|
|
89
65
|
|
|
90
|
-
|
|
66
|
+
Precedence: `.env` → `.env.<mode>` → `.env.local` → process environment. Parent JSON such as `HAI_DB` overrides child variables. `.env.example` documents all fields and enums. Commit `.env` and `.env.dev/test/prod`; keep real credentials in `.env.local`. Fullstack's first start also needs a private `HAI_ADMIN_DEFAULT_PASSWORD` satisfying the IAM password policy.
|
|
91
67
|
|
|
92
|
-
|
|
68
|
+
Fullstack production also requires an explicit Web Origin in `.env.prod`, such as `HAI_SERV_CORS_ORIGIN=https://app.hai.internal`; the default `*` prevents production startup. Production refresh cookies use Secure, so Web/API need trusted HTTPS endpoints. Exposing HTTP ports alone does not validate complete login/session refresh.
|
|
93
69
|
|
|
94
|
-
###
|
|
70
|
+
### 3. Deploy
|
|
95
71
|
|
|
96
|
-
|
|
97
|
-
- **Remote host**: SSH access, docker/podman and compose installed, and a login user permitted to run containers.
|
|
98
|
-
- **Application**: SvelteKit must use `@sveltejs/adapter-node` (covered by the supplied `Dockerfile`); otherwise `ADAPTER_MISSING` is returned.
|
|
72
|
+
From the fullstack root, replace the service directory:
|
|
99
73
|
|
|
100
|
-
|
|
74
|
+
```powershell
|
|
75
|
+
pnpm.cmd exec hai deploy packages/my-app-serv --env prod --env-dir .
|
|
76
|
+
```
|
|
101
77
|
|
|
102
|
-
|
|
78
|
+
The wizard shows the effective backend and purpose. Defaults generate Compose services/volumes; custom connections omit that middleware container. Keep unchanged is offered only when the target environment file explicitly declares complete configuration. Public values go to the selected environment file, credentials to `.env.local`, with redacted output.
|
|
103
79
|
|
|
104
|
-
|
|
105
|
-
|
|
80
|
+
When all database, cache and storage connections are already configured:
|
|
81
|
+
|
|
82
|
+
```powershell
|
|
83
|
+
pnpm.cmd exec hai deploy packages/my-app-serv --env prod --env-dir . --yes --skip-middleware
|
|
106
84
|
```
|
|
107
85
|
|
|
108
|
-
|
|
86
|
+
`--skip-middleware` (alias `--skip-provision`) skips middleware prompts, configuration updates and resource creation; application build/deployment still run. It does not start external middleware. `--yes` alone keeps complete settings and otherwise uses the current backend defaults.
|
|
109
87
|
|
|
110
|
-
|
|
111
|
-
provider:
|
|
112
|
-
type: docker-ssh
|
|
113
|
-
ssh:
|
|
114
|
-
host: 10.0.0.20 # 主机 IP 或 ~/.ssh/config 别名
|
|
115
|
-
port: 22
|
|
116
|
-
username: deploy
|
|
117
|
-
identityFile: ${HAI_DEPLOY_SSH_KEY} # 私钥文件路径,省略则用 ssh-agent
|
|
118
|
-
remote:
|
|
119
|
-
baseDir: /opt/hai/apps # 远程部署根目录
|
|
120
|
-
runtime: auto # 远程运行时;auto 优先 podman,其次 docker
|
|
121
|
-
expose:
|
|
122
|
-
type: port
|
|
123
|
-
containerPort: 3000 # 容器内端口(adapter-node 默认 3000)
|
|
124
|
-
hostPort: 18080 # 宿主机端口 → 访问地址 http://10.0.0.20:18080
|
|
88
|
+
`--project-name <name>` sets the name; an explicit environment adds a suffix. **`--skip-build` currently skips only Vercel application builds. docker-ssh always builds an image and has no option to deploy a specified existing image directly.** Failures return a nonzero exit code.
|
|
125
89
|
|
|
126
|
-
|
|
127
|
-
runtime: auto # 本地构建运行时(可选)
|
|
90
|
+
## docker-ssh execution and files
|
|
128
91
|
|
|
129
|
-
|
|
130
|
-
|
|
92
|
+
1. Use the target package's Dockerfile, or generate a fallback with the workspace root as context. Fullstack service packages use the fallback by default, not the root Web target.
|
|
93
|
+
2. Build the image locally and export a tar with `docker/podman save`.
|
|
94
|
+
3. Check the remote engine and Compose over SSH, upload the tar with SCP, then run `load` remotely.
|
|
95
|
+
4. Generate `compose.yml`, `.env.runtime` and `start-<mode>.sh` locally and upload each to `<baseDir>/<projectName>-<mode>/`. These are separate from the image archive; no single Compose bundle is uploaded and no source build runs on Linux.
|
|
96
|
+
5. The remote script sets `HAI_DEPLOY_ENVIRONMENT`/`HAI_CORE_ENV` and runs `compose --env-file .env.runtime ... up -d`. The SDK checks native `/health` or SvelteKit `/` from the local machine before succeeding.
|
|
131
97
|
|
|
132
|
-
|
|
98
|
+
Local artifacts live in the target package's Git-ignored `.hai/deploy/<mode>/`. Remote `.env.runtime` uses mode `600`. Retain local artifacts for repeat deployment: keep unchanged preserves services/volumes from the previous local Compose, not arbitrary server-side Compose definitions. Exclude private environment files and deployment archives from image contexts.
|
|
133
99
|
|
|
134
|
-
|
|
135
|
-
hai deploy # 读取 config/_deploy.yml,输出访问地址
|
|
136
|
-
```
|
|
100
|
+
## Fully offline deployment
|
|
137
101
|
|
|
138
|
-
|
|
139
|
-
import { deploy } from '@h-ai/deploy'
|
|
102
|
+
Offline means no internet; Windows and Linux must still communicate over an internal SSH/HTTP network. Vercel and cloud provisioning are unavailable.
|
|
140
103
|
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
104
|
+
### Materials to bring in advance
|
|
105
|
+
|
|
106
|
+
| Location | Requirements |
|
|
107
|
+
| ------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
|
|
108
|
+
| Windows tools | Compatible Node (for example a supported Node 24), pnpm 12.11.2, installed CLI/SDK and transitive dependencies, OpenSSH, initialized and runnable Linux container engine |
|
|
109
|
+
| Project | Complete source, pinned lockfile, environment files and private credentials; `pnpm.cmd exec hai --help` must work offline. Avoid on-demand `npx` / `pnpm dlx` downloads |
|
|
110
|
+
| Linux | Docker CLI/Engine, Compose plugin (`docker compose version` works), authorized SSH key, container permissions, writable deployment directory, ports and disk space. Host Node/pnpm are unnecessary for running images |
|
|
111
|
+
| Images | API, Web and middleware images matching Linux CPU architecture and exact Compose names/tags; import with `docker load -i <archive.tar>` |
|
|
112
|
+
| Application | PostgreSQL database/account, Redis connection/password, RustFS keys/bucket and initial administrator password. Existing services must already run and be reachable from the app container; `localhost` means that container |
|
|
113
|
+
|
|
114
|
+
Defaults use `postgres:16-alpine`, `redis:7-alpine` and `ghcr.io/rustfs/rustfs:1.0.1`. Other tags do not match automatically: import the exact images, correctly retag verified compatible images, or use custom connections. The SDK does not transfer middleware images. Other pinned images are in the [Compose implementation](src/container/deploy-container-compose.ts).
|
|
115
|
+
|
|
116
|
+
**The default source build is not ready for offline use without preparation.** Dockerfiles prepare pnpm and download packages and SQLite prebuilds; the fullstack root also runs `pnpm fetch` and uses an external Dockerfile frontend. Windows `node_modules`/pnpm store cannot replace Linux build dependencies. For offline source builds, bring Node base images, the build frontend, Corepack/pnpm, Linux dependencies and native binary caches into the local engine/build environment, adapt the Dockerfile, and rehearse with internet disconnected. `pnpm install --offline --frozen-lockfile` only addresses package-store access, not additional downloads by install scripts.
|
|
117
|
+
|
|
118
|
+
SQLite prebuilds must match better-sqlite3 version, Node ABI, CPU architecture and libc. Installation may still need them when runtime uses PostgreSQL. Preload prebuild-install's Linux cache or use an internal `container.sqlitePrebuildMirror`; otherwise bring the binary or a finished image. Default fullstack needs no CUDA.
|
|
150
119
|
|
|
151
|
-
###
|
|
120
|
+
### Reuse prebuilt images through the SDK offline
|
|
152
121
|
|
|
153
|
-
For
|
|
122
|
+
Prepare finished images before delivery. For a project named `my-app` with a Web frontend, build on the server's architecture in an environment with dependencies available:
|
|
154
123
|
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
8. **Health check**: poll `http://<host>:<hostPort>/`; only HTTP 200 yields `ready`.
|
|
124
|
+
```powershell
|
|
125
|
+
docker build --target runtime -t my-app-api:offline .
|
|
126
|
+
docker build --target web -t my-app-web:offline .
|
|
127
|
+
docker save -o my-app-images.tar my-app-api:offline my-app-web:offline
|
|
128
|
+
```
|
|
129
|
+
|
|
130
|
+
Import the archive into the offline Windows Linux engine with `docker load -i my-app-images.tar`. Create `packages/my-app-serv/Dockerfile` containing only:
|
|
163
131
|
|
|
164
|
-
|
|
132
|
+
```dockerfile
|
|
133
|
+
FROM my-app-api:offline
|
|
134
|
+
```
|
|
165
135
|
|
|
166
|
-
|
|
136
|
+
Add a service-package `.dockerignore` containing `*`. This makes the SDK's mandatory build reuse the finished API without package installation. Rebuild the finished image after source changes. Configure the target, then run the deployment command above. To create middleware containers, select `HAI_DB_TYPE=postgresql`, `HAI_CACHE_TYPE=redis`, `HAI_STORAGE_TYPE=s3` in `.env.prod` and choose defaults in the wizard. For existing services, enter custom connections; once complete, `--skip-middleware` is available. The SDK uploads the API image. Rehearse with internet disconnected to confirm the builder needs no network.
|
|
167
137
|
|
|
168
|
-
|
|
138
|
+
Transfer the Web image separately. This example assumes separately prepared internal TLS endpoints `https://app.hai.internal` and `https://api.hai.internal`, proxying Web port 18081 and API port 18080. Bring proxy configuration/images and certificates, configure internal DNS/hosts and client certificate trust, then run over SSH:
|
|
139
|
+
|
|
140
|
+
```sh
|
|
141
|
+
docker load -i /path/to/my-app-images.tar
|
|
142
|
+
docker run -d --name my-app-web-prod --restart unless-stopped -p 18081:8080 -e PUBLIC_API_BASE=https://api.hai.internal my-app-web:offline
|
|
143
|
+
```
|
|
169
144
|
|
|
170
|
-
|
|
171
|
-
| ---------------- | ---------------- | ------------------------------- | ------------------ |
|
|
172
|
-
| `db` | `postgresql` | `postgres:16-alpine` | `HAI_DB` |
|
|
173
|
-
| `db` | `mysql` | `mysql:8.4` | `HAI_DB` |
|
|
174
|
-
| `db` | `sqlite` | None (mount `/app/data` volume) | — |
|
|
175
|
-
| `cache` | `redis` | `redis:7-alpine` | `HAI_CACHE` |
|
|
176
|
-
| `storage` | `s3` | `minio` + bucket initialization | `HAI_STORAGE` |
|
|
177
|
-
| `vecdb` | `qdrant` | `qdrant/qdrant` | `HAI_VECDB` |
|
|
178
|
-
| `vecdb` | `pgvector` | `pgvector/pgvector` | `HAI_VECDB` |
|
|
179
|
-
| `vecdb` | `chroma` | `chromadb/chroma` | `HAI_VECDB` |
|
|
180
|
-
| `vecdb` | `lancedb` | None (mount `/app/data` volume) | — |
|
|
145
|
+
Use a browser-reachable API URL and set API `HAI_SERV_CORS_ORIGIN=https://app.hai.internal`. Verify API `/health`, Web login/business requests, hash-route reload, session refresh, restarts and persistence. These are preparation/adaptation instructions; online deployment tests do not prove offline acceptance.
|
|
181
146
|
|
|
182
|
-
|
|
183
|
-
- Existing cloud provisioners take precedence (for example Neon providing `HAI_DB`); no duplicate sidecar is created.
|
|
184
|
-
- Sidecar secrets such as passwords go only in remote `.env.runtime` (`600`), never `compose.yml`.
|
|
147
|
+
Official references: Docker [save](https://docs.docker.com/reference/cli/docker/image/save/) / [load](https://docs.docker.com/reference/cli/docker/image/load/), [pnpm install](https://pnpm.io/cli/install), [Compose plugin installation](https://docs.docker.com/compose/install/linux/).
|
|
185
148
|
|
|
186
|
-
|
|
187
|
-
> uses accept-new: trust first use and reject changed keys. You may connect once manually with `ssh` for an unknown host.
|
|
149
|
+
## SDK and failures
|
|
188
150
|
|
|
189
|
-
|
|
151
|
+
Scripts do not need the CLI. Supply parsed configuration; use public `loadDeploymentEnvironment` / `loadDeploymentConfig` for the same environment resolution:
|
|
190
152
|
|
|
191
153
|
```typescript
|
|
192
|
-
import {
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
154
|
+
import type { DeployConfigInput } from '@h-ai/deploy'
|
|
155
|
+
import { deploy } from '@h-ai/deploy'
|
|
156
|
+
|
|
157
|
+
/**
|
|
158
|
+
* 使用现有中间件发布生产 API,并释放部署模块。
|
|
159
|
+
* @param config - 从部署环境解析得到的配置
|
|
160
|
+
* @returns 初始化或部署的 HaiResult,由调用者检查 success
|
|
161
|
+
* @example `const result = await publish(config)`
|
|
162
|
+
*/
|
|
163
|
+
export async function publish(config: DeployConfigInput) {
|
|
164
|
+
const initialized = await deploy.init(config)
|
|
165
|
+
if (!initialized.success)
|
|
166
|
+
return initialized
|
|
167
|
+
try {
|
|
168
|
+
return await deploy.deployApp('./packages/my-app-serv', {
|
|
169
|
+
environment: 'prod',
|
|
170
|
+
envDir: '.',
|
|
171
|
+
skipProvision: true,
|
|
172
|
+
})
|
|
173
|
+
}
|
|
174
|
+
finally {
|
|
175
|
+
await deploy.close()
|
|
203
176
|
}
|
|
204
177
|
}
|
|
205
178
|
```
|
|
206
179
|
|
|
207
|
-
|
|
180
|
+
Check `result.success` before reading `error.code/message` or `data.url/healthCheck`. `deploy.scan()` and `deploy.credentials.*()` require no initialization. `deployApp()` includes provisioning, so do not also call `provisionAll()` beforehand. Check results for manual provisioning too. SDK `skipProvision` has the CLI's skip-middleware semantics.
|
|
208
181
|
|
|
209
|
-
|
|
210
|
-
| --------------------------------- | ---------------- | ------------------------------------- |
|
|
211
|
-
| `HaiDeployError.DEPLOY_FAILED` | `hai:deploy:001` | Deployment failed |
|
|
212
|
-
| `HaiDeployError.BUILD_FAILED` | `hai:deploy:003` | Build failed |
|
|
213
|
-
| `HaiDeployError.AUTH_FAILED` | `hai:deploy:006` | Authentication failed |
|
|
214
|
-
| `HaiDeployError.PROVISION_FAILED` | `hai:deploy:007` | Provisioning failed |
|
|
215
|
-
| `HaiDeployError.NOT_INITIALIZED` | `hai:deploy:010` | Not initialized |
|
|
216
|
-
| `HaiDeployError.ENV_VAR_FAILED` | `hai:deploy:011` | Environment variable operation failed |
|
|
182
|
+
Cloud provisioners return whole-object `HAI_DB`, `HAI_CACHE`, `HAI_STORAGE` or `HAI_REACH_PROVIDERS`; applications must load their YAML and initialize the modules. `getDeployRecovery(result.error)` returns stage/resource IDs; verify `unknown` outcomes in the platform before retrying. Same-name retries reuse resources without automatic deletion. Types, configuration and error codes are available through the [public entry](src/index.ts).
|
|
217
183
|
|
|
218
|
-
|
|
184
|
+
## Testing and development
|
|
219
185
|
|
|
220
|
-
|
|
221
|
-
| -------------------------------------------- | ---------------- | --------------------------- |
|
|
222
|
-
| `HaiDeployError.CONTAINER_RUNTIME_NOT_FOUND` | `hai:deploy:015` | Container runtime not found |
|
|
223
|
-
| `HaiDeployError.CONTAINER_BUILD_FAILED` | `hai:deploy:016` | Image build failed |
|
|
224
|
-
| `HaiDeployError.REMOTE_CONNECT_FAILED` | `hai:deploy:017` | Remote connection failed |
|
|
225
|
-
| `HaiDeployError.REMOTE_COMMAND_FAILED` | `hai:deploy:018` | Remote command failed |
|
|
226
|
-
| `HaiDeployError.IMAGE_TRANSFER_FAILED` | `hai:deploy:019` | Image transfer failed |
|
|
227
|
-
| `HaiDeployError.HEALTH_CHECK_FAILED` | `hai:deploy:020` | Health check failed |
|
|
186
|
+
After installing dependencies, run from the framework root (Windows: `pnpm.cmd`):
|
|
228
187
|
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
pnpm --filter @h-ai/deploy
|
|
188
|
+
```powershell
|
|
189
|
+
pnpm.cmd --filter @h-ai/deploy typecheck
|
|
190
|
+
pnpm.cmd --filter @h-ai/deploy lint
|
|
191
|
+
pnpm.cmd --filter @h-ai/deploy build
|
|
192
|
+
pnpm.cmd --filter @h-ai/deploy test
|
|
193
|
+
pnpm.cmd check:skills
|
|
233
194
|
```
|
|
234
195
|
|
|
235
|
-
|
|
196
|
+
`src/deploy-scanner.ts` handles lockfile traversal, `deploy-middleware.ts` connection fields, `container/` engines/SSH/Compose, `providers/` deployment targets and `provisioners/` cloud resources. CLI prompts live in `../cli/src/commands/cli-deploy*.ts`. Changes to backends/configuration must update consumers, environment examples, tests and the [deployment skill](../cli/templates/skills/hai-deploy/SKILL.md).
|
|
236
197
|
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
Provisioned configuration: Neon emits HAI_DB (PostgreSQL JSON), Upstash HAI_CACHE (Redis rediss URL JSON), and R2 HAI_STORAGE (flat S3 JSON). Email/SMS emit HAI_REACH_PROVIDERS; deployApp merges both channels while preserving YAML message templates, replacing the original providers array. Core supports whole-object/array overrides, with parents preceding leaves and schema validation retained. Build subprocesses and target runtimes share provisioned values. R2 needs existing S3 accessKeyId/secretAccessKey, Resend a verified-domain from address, and Alibaba Cloud approved signName/templates. Applications need matching `_db.yml` / `_cache.yml` / `_storage.yml` / `_reach.yml` loaded at startup; network clients require Node.
|
|
198
|
+
For deployment changes, also run CLI typecheck/lint/build/test and `pnpm.cmd --filter @h-ai/cli test:deploy-gates`: current package archives → generated fullstack → Podman/SSH → health, environment, login and repeat deployment. This needs a local engine and OpenSSH; first fixture setup downloads images and OS/Node dependencies, so it is not an offline acceptance test. Template changes also require `pnpm.cmd --filter @h-ai/cli test:scaffold-gates`. Unit tests do not prove cloud resource creation; validate paid cloud operations separately. Keep logs/screenshots/reports in Git-ignored `tmp/` or `test-results/`.
|
|
240
199
|
|
|
241
|
-
|
|
200
|
+
## License
|
|
242
201
|
|
|
243
|
-
|
|
202
|
+
Apache-2.0
|