@cloud-cli/on 1.9.0 → 1.10.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 +66 -35
- package/dist/config.d.ts.map +1 -1
- package/dist/index.d.ts +1 -3
- package/dist/index.d.ts.map +1 -1
- package/dist/on.js +7503 -7115
- package/dist/plugins/github-status.plugin.d.ts +13 -3
- package/dist/plugins/github-status.plugin.d.ts.map +1 -1
- package/dist/plugins/manager.d.ts +3 -2
- package/dist/plugins/manager.d.ts.map +1 -1
- package/dist/queue.d.ts +1 -1
- package/dist/queue.d.ts.map +1 -1
- package/dist/run-view.d.ts +16 -0
- package/dist/run-view.d.ts.map +1 -0
- package/dist/safe-eval.d.ts +6 -0
- package/dist/safe-eval.d.ts.map +1 -1
- package/dist/scheduler.d.ts +17 -0
- package/dist/scheduler.d.ts.map +1 -0
- package/dist/secret-repository.d.ts +10 -0
- package/dist/secret-repository.d.ts.map +1 -0
- package/dist/secrets.d.ts +3 -5
- package/dist/secrets.d.ts.map +1 -1
- package/dist/server.d.ts +15 -1
- package/dist/server.d.ts.map +1 -1
- package/dist/types.d.ts +31 -33
- package/dist/types.d.ts.map +1 -1
- package/dist/worker.d.ts.map +1 -1
- package/dist/workflows.d.ts +22 -0
- package/dist/workflows.d.ts.map +1 -0
- package/package.json +1 -1
- package/dist/reporters/html.reporter.d.ts +0 -11
- package/dist/reporters/html.reporter.d.ts.map +0 -1
- package/dist/reporters/json-file.reporter.d.ts +0 -10
- package/dist/reporters/json-file.reporter.d.ts.map +0 -1
- package/dist/reporters/slack.reporter.d.ts +0 -16
- package/dist/reporters/slack.reporter.d.ts.map +0 -1
package/README.md
CHANGED
|
@@ -15,7 +15,9 @@ Designed with a strict **security-first boundary**, native **JavaScript AST eval
|
|
|
15
15
|
- **Deterministic Field Evaluation:** No silent fallbacks or ambiguous type conversions. Plain strings remain literal strings; conditions in `if:` fields run as strict JS boolean expressions.
|
|
16
16
|
- **Built-in Dark Mode Web UI (`/runs`):** Monitor job statuses live, inspect workspace inputs, and view ANSI-colored terminal log streams rendered in real-time.
|
|
17
17
|
- **System & Container Execution Drivers:** Run steps directly as detached host process groups or inside isolated Docker/Systemd transient units.
|
|
18
|
-
- **
|
|
18
|
+
- **DB-authored workflows:** Draft, validate, and publish portable YAML workflows through the authenticated API.
|
|
19
|
+
- **Scheduled execution:** Published workflows can run from cron expressions or local sunrise/sunset events.
|
|
20
|
+
- **Encrypted secret storage:** Secret ciphertext is stored in the database; the master key remains on the HTTP server.
|
|
19
21
|
|
|
20
22
|
---
|
|
21
23
|
|
|
@@ -23,10 +25,6 @@ Designed with a strict **security-first boundary**, native **JavaScript AST eval
|
|
|
23
25
|
|
|
24
26
|
```text
|
|
25
27
|
my-project/
|
|
26
|
-
├── on/ # Workflow definitions directory
|
|
27
|
-
│ ├── release.yml
|
|
28
|
-
│ └── test.yml
|
|
29
|
-
├── .env # Local secrets (git-ignored)
|
|
30
28
|
├── runner.config.mjs # (Optional) Engine configuration
|
|
31
29
|
└── package.json
|
|
32
30
|
|
|
@@ -41,24 +39,14 @@ my-project/
|
|
|
41
39
|
Run the engine directly via `npx` or `pnpm dlx`:
|
|
42
40
|
|
|
43
41
|
```bash
|
|
44
|
-
# Start
|
|
45
|
-
npx @cloud-cli/on start
|
|
42
|
+
# Start each role (normally managed by the supplied systemd units)
|
|
43
|
+
npx @cloud-cli/on start-server
|
|
44
|
+
npx @cloud-cli/on start-scheduler
|
|
45
|
+
npx @cloud-cli/on start-workers
|
|
46
46
|
|
|
47
47
|
```
|
|
48
48
|
|
|
49
|
-
### 2.
|
|
50
|
-
|
|
51
|
-
Secrets are automatically loaded from `.env` at the root of your project. Prefix secrets with `SECRET_`:
|
|
52
|
-
|
|
53
|
-
```env
|
|
54
|
-
SECRET_NPM_TOKEN="npm_1234567890abcdef"
|
|
55
|
-
SECRET_GITHUB_TOKEN="ghp_1234567890abcdef"
|
|
56
|
-
SECRET_GITHUB_WEBHOOK_SECRET="my-webhook-secret"
|
|
57
|
-
```
|
|
58
|
-
|
|
59
|
-
`SECRET_GITHUB_WEBHOOK_SECRET` is required to validate incoming webhooks from GitHub
|
|
60
|
-
|
|
61
|
-
### 3. Define a Workflow (`on/release.yml`)
|
|
49
|
+
### 2. Define a Workflow
|
|
62
50
|
|
|
63
51
|
```yaml
|
|
64
52
|
name: Build and Publish Release
|
|
@@ -110,6 +98,32 @@ steps:
|
|
|
110
98
|
npx --yes semantic-release@24 -b main --no-ci
|
|
111
99
|
```
|
|
112
100
|
|
|
101
|
+
Store the YAML as a draft and publish it through the authenticated API. Only published revisions can receive webhooks or scheduled runs:
|
|
102
|
+
|
|
103
|
+
```bash
|
|
104
|
+
curl -u admin:"$RUNNER_ADMIN_SECRET" -X POST http://localhost:11235/api/workflows/validate \
|
|
105
|
+
-H 'Content-Type: application/json' --data '{"sourceYaml":"..."}'
|
|
106
|
+
curl -u admin:"$RUNNER_ADMIN_SECRET" -X PUT http://localhost:11235/api/workflows/build-and-publish-release \
|
|
107
|
+
-H 'Content-Type: application/json' --data '{"sourceYaml":"..."}'
|
|
108
|
+
curl -u admin:"$RUNNER_ADMIN_SECRET" -X POST http://localhost:11235/api/workflows/build-and-publish-release/publish
|
|
109
|
+
```
|
|
110
|
+
|
|
111
|
+
Time triggers are defined beside a webhook trigger:
|
|
112
|
+
|
|
113
|
+
```yaml
|
|
114
|
+
on:
|
|
115
|
+
schedule:
|
|
116
|
+
- id: nightly
|
|
117
|
+
cron: "0 2 * * *"
|
|
118
|
+
timezone: Europe/Berlin
|
|
119
|
+
solar:
|
|
120
|
+
- id: morning
|
|
121
|
+
event: sunrise
|
|
122
|
+
latitude: 52.52
|
|
123
|
+
longitude: 13.405
|
|
124
|
+
offset: +15m
|
|
125
|
+
```
|
|
126
|
+
|
|
113
127
|
GitHub triggers support these preprocessor filters:
|
|
114
128
|
|
|
115
129
|
| Field | Match behavior |
|
|
@@ -150,8 +164,8 @@ npx @cloud-cli/on [command] [options]
|
|
|
150
164
|
| Command | Description |
|
|
151
165
|
| ------------------- | ---------------------------------------------------------------------------------------- |
|
|
152
166
|
| **`start-server`** | Runs Webhook Ingress Gateway (the HTTP server receiving webhooks). |
|
|
167
|
+
| **`start-scheduler`** | Dispatches published cron and solar workflow triggers. |
|
|
153
168
|
| **`start-workers`** | Runs the event-driven worker scheduler (Scalable Workers). |
|
|
154
|
-
| **`validate`** | Parses and validates all YAML workflows in your workflows folder without executing jobs. |
|
|
155
169
|
|
|
156
170
|
### CLI and Environment Options
|
|
157
171
|
|
|
@@ -160,17 +174,18 @@ npx @cloud-cli/on [command] [options]
|
|
|
160
174
|
| `-h` | `--help` | — | - | Prints CLI help message and exits. |
|
|
161
175
|
| `-c` | `--config` | `./runner.config.mjs` | `RUNNER_CONFIG_FILE` | Path to JavaScript configuration file. |
|
|
162
176
|
| `-d` | `--database` | - | `RUNNER_DATABASE_URL` | SQLite database file path or HTTP URL. |
|
|
163
|
-
| `-w` | `--workflows` | `on/` | `RUNNER_WORKFLOWS` | Directory where workflow YAML files live. |
|
|
164
177
|
| `-p` | `--port` | `11235` | `PORT` | Port for the Ingress HTTP server. |
|
|
165
178
|
| `-k` | `--workers` | `5` | `RUNNER_WORKERS` | Maximum concurrent jobs on this node. |
|
|
166
179
|
| | | | `RUNNER_ADMIN_SECRET` | Admin token to refresh secrets via API |
|
|
167
180
|
| | | | `RUNNER_SERVER_URL` | Webhook server URL used by workers. |
|
|
168
181
|
| | | | `RUNNER_TAGS` | Comma-separated worker capability tags. |
|
|
169
182
|
|
|
170
|
-
Set the same non-empty `RUNNER_ADMIN_SECRET` on the server and workers to publish live job-status refresh events
|
|
183
|
+
Set the same non-empty `RUNNER_ADMIN_SECRET` on the server and workers to publish live job-status refresh events and let workers retrieve job-scoped secrets. The dashboard workflow APIs accept either Bearer authentication or HTTP Basic authentication with username `admin` and this secret.
|
|
171
184
|
|
|
172
185
|
### Secrets
|
|
173
186
|
|
|
187
|
+
Secrets are written through `PUT /api/secrets/:NAME` and are AES-256-GCM encrypted in the database. Set `RUNNER_MASTER_KEY` only on the HTTP server, or provide an `on-master-key` systemd credential. Workers receive decrypted values only after claiming a running job; values are not written to job payloads or reports.
|
|
188
|
+
|
|
174
189
|
---
|
|
175
190
|
|
|
176
191
|
## ⚙️ Configuration Reference
|
|
@@ -179,14 +194,13 @@ You can customize engine behavior using `runner.config.mjs` in your project root
|
|
|
179
194
|
|
|
180
195
|
```javascript
|
|
181
196
|
// runner.config.mjs
|
|
182
|
-
import {
|
|
197
|
+
import { GitHubStatusPlugin } from '@cloud-cli/on';
|
|
183
198
|
|
|
184
199
|
export default {
|
|
185
200
|
port: 3000,
|
|
186
201
|
workers: 5,
|
|
187
202
|
serverUrl: 'https://runner.example.com/',
|
|
188
203
|
tags: ['linux', 'docker'],
|
|
189
|
-
workflows: '/home/workflows/',
|
|
190
204
|
storagePath: '/tmp/workspaces',
|
|
191
205
|
database: 'https://remote.db.com/',
|
|
192
206
|
|
|
@@ -195,18 +209,19 @@ export default {
|
|
|
195
209
|
NODE_ENV: 'production',
|
|
196
210
|
},
|
|
197
211
|
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
new SlackReporter({
|
|
203
|
-
webhookUrl: process.env.SLACK_WEBHOOK_URL,
|
|
204
|
-
channel: '#ci-deployments',
|
|
212
|
+
plugins: [
|
|
213
|
+
new GitHubStatusPlugin({
|
|
214
|
+
token: process.env.SECRET_GITHUB_TOKEN,
|
|
215
|
+
context: 'on',
|
|
205
216
|
}),
|
|
206
217
|
],
|
|
207
218
|
};
|
|
208
219
|
```
|
|
209
220
|
|
|
221
|
+
The GitHub status plugin publishes commit states when a workflow starts and finishes. Its token needs permission to write commit statuses for the target repository.
|
|
222
|
+
|
|
223
|
+
Run details are available as HTML at `/runs/:id` and as sanitized JSON at `/api/runs/:id`. The HTML view refreshes reactively through job-specific SSE events while a run is active. Both representations omit raw webhook bodies, sensitive input fields, execution environment values, and internal rerun state.
|
|
224
|
+
|
|
210
225
|
---
|
|
211
226
|
|
|
212
227
|
## 📐 Deterministic Evaluation Rules
|
|
@@ -243,7 +258,7 @@ Within `${...}`, `if:`, and `eval:` contexts, the following object scopes are ex
|
|
|
243
258
|
|
|
244
259
|
- **`inputs`**: Payload key-values received from incoming webhooks.
|
|
245
260
|
- **`env`**: Merged environment variables from global config and workflow definitions.
|
|
246
|
-
- **`secrets`**: Unmasked
|
|
261
|
+
- **`secrets`**: Unmasked job-scoped values from encrypted central secret storage.
|
|
247
262
|
- **`steps`**: Execution statuses and outputs from previous steps in the workflow (`steps.<id>.status`, `steps.<id>.outputs`).
|
|
248
263
|
- **`BUILTIN_HELPERS`**: JS utilities including `String`, `Number`, `Boolean`, and `JSON.parse` / `JSON.stringify`.
|
|
249
264
|
|
|
@@ -278,8 +293,24 @@ The Ingress Gateway listens for incoming HTTP requests and serves the live web U
|
|
|
278
293
|
AST evaluation explicitly blocks access to dangerous JS properties (`constructor`, `__proto__`, `prototype`).
|
|
279
294
|
3. **Payload Size Guard:**
|
|
280
295
|
The Ingress server enforces a strict 5MB payload limit to prevent Out-Of-Memory (OOM) denial-of-service attacks.
|
|
281
|
-
4. **
|
|
282
|
-
|
|
296
|
+
4. **Single-operator API authentication:**
|
|
297
|
+
Workflow validation, publishing, secret management, and job details require `RUNNER_ADMIN_SECRET` over HTTPS.
|
|
298
|
+
|
|
299
|
+
## systemd Deployment
|
|
300
|
+
|
|
301
|
+
Install the unit files from `systemd/`, create a non-login `on` user, and create a root-owned `/etc/on/runner.env` with `RUNNER_DATABASE_URL`, `RUNNER_SERVER_URL`, `RUNNER_ADMIN_SECRET`, `RUNNER_TAGS`, and `RUNNER_TMP`. Use `systemctl edit` for per-machine overrides.
|
|
302
|
+
|
|
303
|
+
Place the server master key in `/etc/on/credentials/on-master-key` with permissions readable only by the `on` user. `runner-server.service` exposes it privately through systemd's credentials directory. Start the primary control plane with `systemctl enable --now runner.target`; enable `runner-worker.service` separately on worker machines. Use `systemctl edit runner-worker.service` for machine-specific labels and paths.
|
|
304
|
+
|
|
305
|
+
## Database Migration
|
|
306
|
+
|
|
307
|
+
Before deploying the revision-reference queue code to an existing database, run `migrations/20260904_job_workflow_revisions.sql` once through the SQLite HTTPS query service. It adds `jobs.workflow_revision` and `jobs.required_tags`, backfills routing tags, links jobs to the currently published workflow revision, and cancels only pending/running legacy jobs that cannot be linked. New installations receive both columns from `QueueManager.createTables()`.
|
|
308
|
+
|
|
309
|
+
Workers now resolve the immutable revision when they claim a job. A workflow can safely use a checkout step followed by `if: files.exists('Dockerfile')`; `files` is constrained to the job's `workingDir`, so it cannot inspect files outside that workspace.
|
|
310
|
+
|
|
311
|
+
## Future Security Work
|
|
312
|
+
|
|
313
|
+
This MVP intentionally supports one trusted operator. Before sharing the UI or exposing it beyond a private deployment, add individual accounts and roles, secure browser sessions and CSRF protection, audit logs, worker enrollment credentials, secret key rotation, encrypted systemd credentials, rate limiting, and database high availability.
|
|
283
314
|
|
|
284
315
|
## Development
|
|
285
316
|
|
package/dist/config.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"config.d.ts","sourceRoot":"","sources":["../src/config.ts"],"names":[],"mappings":"AAGA,OAAO,EAAE,YAAY,EAAE,gBAAgB,EAAE,MAAM,YAAY,CAAC;AAG5D,wBAAsB,UAAU,CAAC,MAAM,KAAA,GAAG,OAAO,CAAC,YAAY,GAAG,IAAI,CAAC,
|
|
1
|
+
{"version":3,"file":"config.d.ts","sourceRoot":"","sources":["../src/config.ts"],"names":[],"mappings":"AAGA,OAAO,EAAE,YAAY,EAAE,gBAAgB,EAAE,MAAM,YAAY,CAAC;AAG5D,wBAAsB,UAAU,CAAC,MAAM,KAAA,GAAG,OAAO,CAAC,YAAY,GAAG,IAAI,CAAC,CAmBrE;AAED,wBAAgB,aAAa,CAAC,cAAc,EAAE,gBAAgB,EAAE,aAAa,EAAE,gBAAgB,GAAG,YAAY,CAe7G;AAED,wBAAgB,SAAS,SAsBxB;AAED,wBAAsB,YAAY,IAAI,OAAO,CAAC;IAAE,MAAM,EAAE,YAAY,GAAG,IAAI,CAAC;IAAC,OAAO,EAAE,MAAM,CAAA;CAAE,CAAC,CAuB9F"}
|
package/dist/index.d.ts
CHANGED
|
@@ -1,5 +1,3 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
|
-
export {
|
|
3
|
-
export { JsonFileReporter } from './reporters/json-file.reporter.js';
|
|
4
|
-
export { SlackReporter } from './reporters/slack.reporter.js';
|
|
2
|
+
export { GitHubStatusPlugin } from './plugins/github-status.plugin.js';
|
|
5
3
|
//# sourceMappingURL=index.d.ts.map
|
package/dist/index.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":";
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":";AAUA,OAAO,EAAE,kBAAkB,EAAE,MAAM,mCAAmC,CAAC"}
|