@alienplatform/testing 0.1.0
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.md +320 -0
- package/package.json +74 -0
package/README.md
ADDED
|
@@ -0,0 +1,320 @@
|
|
|
1
|
+
# @alienplatform/testing
|
|
2
|
+
|
|
3
|
+
Testing framework for Alien applications. Deploy, test, and tear down Alien apps in real environments.
|
|
4
|
+
|
|
5
|
+
## Installation
|
|
6
|
+
|
|
7
|
+
```bash
|
|
8
|
+
npm install @alienplatform/testing
|
|
9
|
+
```
|
|
10
|
+
|
|
11
|
+
## Quick Start
|
|
12
|
+
|
|
13
|
+
```typescript
|
|
14
|
+
import { deploy } from "@alienplatform/testing"
|
|
15
|
+
|
|
16
|
+
const deployment = await deploy({
|
|
17
|
+
app: "./my-app",
|
|
18
|
+
platform: "aws",
|
|
19
|
+
workspace: "my-workspace",
|
|
20
|
+
project: "my-project",
|
|
21
|
+
})
|
|
22
|
+
|
|
23
|
+
// Test your deployment
|
|
24
|
+
const response = await fetch(`${deployment.url}/api/test`)
|
|
25
|
+
expect(response.status).toBe(200)
|
|
26
|
+
|
|
27
|
+
// Cleanup
|
|
28
|
+
await deployment.destroy()
|
|
29
|
+
```
|
|
30
|
+
|
|
31
|
+
## Authentication
|
|
32
|
+
|
|
33
|
+
### API Key
|
|
34
|
+
|
|
35
|
+
Set your Alien API key:
|
|
36
|
+
|
|
37
|
+
```bash
|
|
38
|
+
export ALIEN_API_KEY="your-key"
|
|
39
|
+
# or
|
|
40
|
+
alien login
|
|
41
|
+
```
|
|
42
|
+
|
|
43
|
+
### Platform Credentials
|
|
44
|
+
|
|
45
|
+
Credentials are **optional**. When not provided, deployers use standard environment variables.
|
|
46
|
+
|
|
47
|
+
#### AWS
|
|
48
|
+
```bash
|
|
49
|
+
export AWS_ACCESS_KEY_ID="..."
|
|
50
|
+
export AWS_SECRET_ACCESS_KEY="..."
|
|
51
|
+
export AWS_REGION="us-east-1"
|
|
52
|
+
```
|
|
53
|
+
|
|
54
|
+
Or pass explicitly:
|
|
55
|
+
```typescript
|
|
56
|
+
credentials: {
|
|
57
|
+
platform: "aws",
|
|
58
|
+
accessKeyId: "...",
|
|
59
|
+
secretAccessKey: "...",
|
|
60
|
+
region: "us-east-1",
|
|
61
|
+
}
|
|
62
|
+
```
|
|
63
|
+
|
|
64
|
+
#### GCP
|
|
65
|
+
```bash
|
|
66
|
+
export GOOGLE_APPLICATION_CREDENTIALS="/path/to/key.json"
|
|
67
|
+
export GCP_PROJECT_ID="my-project"
|
|
68
|
+
```
|
|
69
|
+
|
|
70
|
+
Or pass explicitly:
|
|
71
|
+
```typescript
|
|
72
|
+
credentials: {
|
|
73
|
+
platform: "gcp",
|
|
74
|
+
projectId: "my-project",
|
|
75
|
+
serviceAccountKeyPath: "/path/to/key.json",
|
|
76
|
+
// or
|
|
77
|
+
serviceAccountKeyJson: "{ ... }",
|
|
78
|
+
}
|
|
79
|
+
```
|
|
80
|
+
|
|
81
|
+
#### Azure
|
|
82
|
+
```bash
|
|
83
|
+
export AZURE_SUBSCRIPTION_ID="..."
|
|
84
|
+
export AZURE_TENANT_ID="..."
|
|
85
|
+
export AZURE_CLIENT_ID="..."
|
|
86
|
+
export AZURE_CLIENT_SECRET="..."
|
|
87
|
+
```
|
|
88
|
+
|
|
89
|
+
Or pass explicitly:
|
|
90
|
+
```typescript
|
|
91
|
+
credentials: {
|
|
92
|
+
platform: "azure",
|
|
93
|
+
subscriptionId: "...",
|
|
94
|
+
tenantId: "...",
|
|
95
|
+
clientId: "...",
|
|
96
|
+
clientSecret: "...",
|
|
97
|
+
}
|
|
98
|
+
```
|
|
99
|
+
|
|
100
|
+
#### Kubernetes
|
|
101
|
+
```bash
|
|
102
|
+
export KUBECONFIG="~/.kube/config"
|
|
103
|
+
```
|
|
104
|
+
|
|
105
|
+
Or pass explicitly:
|
|
106
|
+
```typescript
|
|
107
|
+
credentials: {
|
|
108
|
+
platform: "kubernetes",
|
|
109
|
+
kubeconfigPath: "~/.kube/config",
|
|
110
|
+
}
|
|
111
|
+
```
|
|
112
|
+
|
|
113
|
+
## Deployment Methods
|
|
114
|
+
|
|
115
|
+
### API (Default)
|
|
116
|
+
|
|
117
|
+
Fastest method. Agent Manager deploys directly:
|
|
118
|
+
|
|
119
|
+
```typescript
|
|
120
|
+
const deployment = await deploy({
|
|
121
|
+
app: "./my-app",
|
|
122
|
+
platform: "aws",
|
|
123
|
+
workspace: "my-workspace",
|
|
124
|
+
project: "my-project",
|
|
125
|
+
method: "api", // default
|
|
126
|
+
})
|
|
127
|
+
```
|
|
128
|
+
|
|
129
|
+
### CLI
|
|
130
|
+
|
|
131
|
+
Tests the actual CLI deployment flow:
|
|
132
|
+
|
|
133
|
+
```typescript
|
|
134
|
+
const deployment = await deploy({
|
|
135
|
+
app: "./my-app",
|
|
136
|
+
platform: "aws",
|
|
137
|
+
workspace: "my-workspace",
|
|
138
|
+
project: "my-project",
|
|
139
|
+
method: "cli",
|
|
140
|
+
})
|
|
141
|
+
```
|
|
142
|
+
|
|
143
|
+
### Terraform
|
|
144
|
+
|
|
145
|
+
Tests Terraform provider:
|
|
146
|
+
|
|
147
|
+
```typescript
|
|
148
|
+
const deployment = await deploy({
|
|
149
|
+
app: "./my-app",
|
|
150
|
+
platform: "aws",
|
|
151
|
+
workspace: "my-workspace",
|
|
152
|
+
project: "my-project",
|
|
153
|
+
method: "terraform",
|
|
154
|
+
})
|
|
155
|
+
```
|
|
156
|
+
|
|
157
|
+
### CloudFormation
|
|
158
|
+
|
|
159
|
+
Tests CloudFormation deployment (AWS only):
|
|
160
|
+
|
|
161
|
+
```typescript
|
|
162
|
+
const deployment = await deploy({
|
|
163
|
+
app: "./my-app",
|
|
164
|
+
platform: "aws",
|
|
165
|
+
workspace: "my-workspace",
|
|
166
|
+
project: "my-project",
|
|
167
|
+
method: "cloudformation",
|
|
168
|
+
})
|
|
169
|
+
```
|
|
170
|
+
|
|
171
|
+
### Helm
|
|
172
|
+
|
|
173
|
+
Tests Helm chart deployment (Kubernetes only):
|
|
174
|
+
|
|
175
|
+
```typescript
|
|
176
|
+
const deployment = await deploy({
|
|
177
|
+
app: "./my-app",
|
|
178
|
+
platform: "kubernetes",
|
|
179
|
+
workspace: "my-workspace",
|
|
180
|
+
project: "my-project",
|
|
181
|
+
method: "helm",
|
|
182
|
+
valuesYaml: "./values.yaml",
|
|
183
|
+
namespace: "default",
|
|
184
|
+
})
|
|
185
|
+
```
|
|
186
|
+
|
|
187
|
+
### Operator Image
|
|
188
|
+
|
|
189
|
+
Tests pull-mode deployment via Docker operator:
|
|
190
|
+
|
|
191
|
+
```typescript
|
|
192
|
+
const deployment = await deploy({
|
|
193
|
+
app: "./my-app",
|
|
194
|
+
platform: "aws",
|
|
195
|
+
workspace: "my-workspace",
|
|
196
|
+
project: "my-project",
|
|
197
|
+
method: "operator-image",
|
|
198
|
+
})
|
|
199
|
+
```
|
|
200
|
+
|
|
201
|
+
## Query Logs
|
|
202
|
+
|
|
203
|
+
Query deployment logs using DeepStore:
|
|
204
|
+
|
|
205
|
+
```typescript
|
|
206
|
+
const deployment = await deploy({
|
|
207
|
+
app: "./my-app",
|
|
208
|
+
platform: "test",
|
|
209
|
+
workspace: "my-workspace",
|
|
210
|
+
project: "my-project",
|
|
211
|
+
})
|
|
212
|
+
|
|
213
|
+
// Configure log querying
|
|
214
|
+
const logsConfig = {
|
|
215
|
+
managerUrl: "http://localhost:3000",
|
|
216
|
+
deepstoreServerUrl: "http://localhost:8080",
|
|
217
|
+
databaseId: "db_123",
|
|
218
|
+
agentToken: "token_123",
|
|
219
|
+
}
|
|
220
|
+
|
|
221
|
+
const logs = await deployment.queryLogs({
|
|
222
|
+
query: "level:ERROR",
|
|
223
|
+
startTime: new Date(Date.now() - 3600_000), // 1 hour ago
|
|
224
|
+
endTime: new Date(),
|
|
225
|
+
maxHits: 100,
|
|
226
|
+
})
|
|
227
|
+
|
|
228
|
+
console.log(`Found ${logs.num_hits} logs`)
|
|
229
|
+
```
|
|
230
|
+
|
|
231
|
+
## Environment Variables
|
|
232
|
+
|
|
233
|
+
Pass environment variables to your deployment:
|
|
234
|
+
|
|
235
|
+
```typescript
|
|
236
|
+
const deployment = await deploy({
|
|
237
|
+
app: "./my-app",
|
|
238
|
+
platform: "aws",
|
|
239
|
+
workspace: "my-workspace",
|
|
240
|
+
project: "my-project",
|
|
241
|
+
environmentVariables: [
|
|
242
|
+
{ name: "DATABASE_URL", value: "postgres://...", type: "plaintext" },
|
|
243
|
+
{ name: "API_KEY", value: "secret", type: "secret" },
|
|
244
|
+
],
|
|
245
|
+
})
|
|
246
|
+
```
|
|
247
|
+
|
|
248
|
+
## Stack Settings
|
|
249
|
+
|
|
250
|
+
Customize deployment behavior:
|
|
251
|
+
|
|
252
|
+
```typescript
|
|
253
|
+
const deployment = await deploy({
|
|
254
|
+
app: "./my-app",
|
|
255
|
+
platform: "aws",
|
|
256
|
+
workspace: "my-workspace",
|
|
257
|
+
project: "my-project",
|
|
258
|
+
stackSettings: {
|
|
259
|
+
deploymentModel: "push",
|
|
260
|
+
heartbeats: "on",
|
|
261
|
+
telemetry: "auto",
|
|
262
|
+
updates: "auto",
|
|
263
|
+
},
|
|
264
|
+
})
|
|
265
|
+
```
|
|
266
|
+
|
|
267
|
+
## Example Test
|
|
268
|
+
|
|
269
|
+
```typescript
|
|
270
|
+
import { describe, it, expect } from "vitest"
|
|
271
|
+
import { deploy } from "@alienplatform/testing"
|
|
272
|
+
|
|
273
|
+
describe("my app", () => {
|
|
274
|
+
it("should deploy and respond", async () => {
|
|
275
|
+
const deployment = await deploy({
|
|
276
|
+
app: "./fixtures/my-app",
|
|
277
|
+
platform: "test",
|
|
278
|
+
workspace: "test-workspace",
|
|
279
|
+
project: "test-project",
|
|
280
|
+
})
|
|
281
|
+
|
|
282
|
+
try {
|
|
283
|
+
const response = await fetch(`${deployment.url}/api/hello`)
|
|
284
|
+
const data = await response.json()
|
|
285
|
+
|
|
286
|
+
expect(response.status).toBe(200)
|
|
287
|
+
expect(data.message).toBe("Hello, World!")
|
|
288
|
+
} finally {
|
|
289
|
+
await deployment.destroy()
|
|
290
|
+
}
|
|
291
|
+
}, 180_000) // 3 min timeout
|
|
292
|
+
})
|
|
293
|
+
```
|
|
294
|
+
|
|
295
|
+
## API Reference
|
|
296
|
+
|
|
297
|
+
### `deploy(options: DeployOptions): Promise<Deployment>`
|
|
298
|
+
|
|
299
|
+
Deploy an Alien application for testing.
|
|
300
|
+
|
|
301
|
+
### `Deployment`
|
|
302
|
+
|
|
303
|
+
Handle to a deployed application.
|
|
304
|
+
|
|
305
|
+
**Properties:**
|
|
306
|
+
- `id: string` - Agent ID
|
|
307
|
+
- `name: string` - Agent name
|
|
308
|
+
- `url: string` - Deployment URL
|
|
309
|
+
- `platform: Platform` - Target platform
|
|
310
|
+
- `status: AgentStatus` - Current status
|
|
311
|
+
|
|
312
|
+
**Methods:**
|
|
313
|
+
- `refresh(): Promise<void>` - Refresh deployment info from API
|
|
314
|
+
- `waitForStatus(status: AgentStatus, options?: WaitOptions): Promise<void>` - Wait for specific status
|
|
315
|
+
- `queryLogs(query: LogQuery): Promise<LogQueryResult>` - Query deployment logs
|
|
316
|
+
- `destroy(): Promise<void>` - Tear down the deployment
|
|
317
|
+
|
|
318
|
+
## License
|
|
319
|
+
|
|
320
|
+
ISC
|
package/package.json
ADDED
|
@@ -0,0 +1,74 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@alienplatform/testing",
|
|
3
|
+
"version": "0.1.0",
|
|
4
|
+
"description": "Testing framework for Alien applications",
|
|
5
|
+
"type": "module",
|
|
6
|
+
"main": "./dist/index.js",
|
|
7
|
+
"types": "./dist/index.d.ts",
|
|
8
|
+
"exports": {
|
|
9
|
+
".": {
|
|
10
|
+
"types": "./dist/index.d.ts",
|
|
11
|
+
"import": "./dist/index.js"
|
|
12
|
+
}
|
|
13
|
+
},
|
|
14
|
+
"files": [
|
|
15
|
+
"dist"
|
|
16
|
+
],
|
|
17
|
+
"publishConfig": {
|
|
18
|
+
"access": "public"
|
|
19
|
+
},
|
|
20
|
+
"dependencies": {
|
|
21
|
+
"get-port": "^7.1.0",
|
|
22
|
+
"zod": "4.3.2",
|
|
23
|
+
"@alienplatform/commands-client": "1.0.0",
|
|
24
|
+
"@alienplatform/core": "1.0.1"
|
|
25
|
+
},
|
|
26
|
+
"peerDependencies": {
|
|
27
|
+
"@aws-sdk/client-cloudformation": "^3.0.0",
|
|
28
|
+
"@aws-sdk/client-ssm": "^3.0.0",
|
|
29
|
+
"@azure/identity": "^4.0.0",
|
|
30
|
+
"@azure/keyvault-secrets": "^4.0.0",
|
|
31
|
+
"@google-cloud/secret-manager": "^5.0.0",
|
|
32
|
+
"@kubernetes/client-node": "^0.21.0"
|
|
33
|
+
},
|
|
34
|
+
"peerDependenciesMeta": {
|
|
35
|
+
"@aws-sdk/client-cloudformation": {
|
|
36
|
+
"optional": true
|
|
37
|
+
},
|
|
38
|
+
"@aws-sdk/client-ssm": {
|
|
39
|
+
"optional": true
|
|
40
|
+
},
|
|
41
|
+
"@google-cloud/secret-manager": {
|
|
42
|
+
"optional": true
|
|
43
|
+
},
|
|
44
|
+
"@azure/keyvault-secrets": {
|
|
45
|
+
"optional": true
|
|
46
|
+
},
|
|
47
|
+
"@azure/identity": {
|
|
48
|
+
"optional": true
|
|
49
|
+
},
|
|
50
|
+
"@kubernetes/client-node": {
|
|
51
|
+
"optional": true
|
|
52
|
+
}
|
|
53
|
+
},
|
|
54
|
+
"devDependencies": {
|
|
55
|
+
"@aws-sdk/client-cloudformation": "^3.0.0",
|
|
56
|
+
"@aws-sdk/client-ssm": "^3.0.0",
|
|
57
|
+
"@azure/identity": "^4.0.0",
|
|
58
|
+
"@azure/keyvault-secrets": "^4.0.0",
|
|
59
|
+
"@google-cloud/secret-manager": "^5.0.0",
|
|
60
|
+
"@kubernetes/client-node": "^0.21.0",
|
|
61
|
+
"@types/node": "^24.0.15",
|
|
62
|
+
"tsdown": "^0.13.0",
|
|
63
|
+
"typescript": "^5.8.3",
|
|
64
|
+
"vitest": "^3.1.4",
|
|
65
|
+
"@alienplatform/typescript-config": "^1.0.0"
|
|
66
|
+
},
|
|
67
|
+
"scripts": {
|
|
68
|
+
"build": "tsdown",
|
|
69
|
+
"dev": "tsdown --watch --no-clean",
|
|
70
|
+
"test": "vitest run",
|
|
71
|
+
"test:watch": "vitest",
|
|
72
|
+
"test:ts": "tsc --noEmit"
|
|
73
|
+
}
|
|
74
|
+
}
|