adispatchd 0.0.0-stage → 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/LICENSE +21 -0
- package/README.md +195 -2
- package/dist/api/errors.d.ts +27 -0
- package/dist/api/errors.js +80 -0
- package/dist/api/errors.js.map +1 -0
- package/dist/api/index.d.ts +10 -0
- package/dist/api/index.js +11 -0
- package/dist/api/index.js.map +1 -0
- package/dist/api/logs.d.ts +30 -0
- package/dist/api/logs.js +88 -0
- package/dist/api/logs.js.map +1 -0
- package/dist/api/serialize.d.ts +65 -0
- package/dist/api/serialize.js +135 -0
- package/dist/api/serialize.js.map +1 -0
- package/dist/api/server.d.ts +89 -0
- package/dist/api/server.js +751 -0
- package/dist/api/server.js.map +1 -0
- package/dist/api/sse.d.ts +90 -0
- package/dist/api/sse.js +225 -0
- package/dist/api/sse.js.map +1 -0
- package/dist/app.d.ts +173 -0
- package/dist/app.js +488 -0
- package/dist/app.js.map +1 -0
- package/dist/cli/config-validate.d.ts +6 -0
- package/dist/cli/config-validate.js +39 -0
- package/dist/cli/config-validate.js.map +1 -0
- package/dist/cli/control.d.ts +31 -0
- package/dist/cli/control.js +186 -0
- package/dist/cli/control.js.map +1 -0
- package/dist/cli/http-client.d.ts +57 -0
- package/dist/cli/http-client.js +174 -0
- package/dist/cli/http-client.js.map +1 -0
- package/dist/cli/index.d.ts +14 -0
- package/dist/cli/index.js +14 -0
- package/dist/cli/index.js.map +1 -0
- package/dist/cli/init-templates.d.ts +20 -0
- package/dist/cli/init-templates.js +275 -0
- package/dist/cli/init-templates.js.map +1 -0
- package/dist/cli/init.d.ts +16 -0
- package/dist/cli/init.js +107 -0
- package/dist/cli/init.js.map +1 -0
- package/dist/cli/main.d.ts +2 -0
- package/dist/cli/main.js +25 -0
- package/dist/cli/main.js.map +1 -0
- package/dist/cli/program.d.ts +102 -0
- package/dist/cli/program.js +133 -0
- package/dist/cli/program.js.map +1 -0
- package/dist/cli/service.d.ts +27 -0
- package/dist/cli/service.js +252 -0
- package/dist/cli/service.js.map +1 -0
- package/dist/cli/start.d.ts +22 -0
- package/dist/cli/start.js +133 -0
- package/dist/cli/start.js.map +1 -0
- package/dist/cli/workflow-dry-run.d.ts +13 -0
- package/dist/cli/workflow-dry-run.js +144 -0
- package/dist/cli/workflow-dry-run.js.map +1 -0
- package/dist/config/field-catalog.d.ts +33 -0
- package/dist/config/field-catalog.js +172 -0
- package/dist/config/field-catalog.js.map +1 -0
- package/dist/config/filter-schema.d.ts +15 -0
- package/dist/config/filter-schema.js +110 -0
- package/dist/config/filter-schema.js.map +1 -0
- package/dist/config/index.d.ts +15 -0
- package/dist/config/index.js +16 -0
- package/dist/config/index.js.map +1 -0
- package/dist/config/issues.d.ts +27 -0
- package/dist/config/issues.js +37 -0
- package/dist/config/issues.js.map +1 -0
- package/dist/config/loader.d.ts +32 -0
- package/dist/config/loader.js +250 -0
- package/dist/config/loader.js.map +1 -0
- package/dist/config/manager.d.ts +153 -0
- package/dist/config/manager.js +276 -0
- package/dist/config/manager.js.map +1 -0
- package/dist/config/model.d.ts +334 -0
- package/dist/config/model.js +2 -0
- package/dist/config/model.js.map +1 -0
- package/dist/config/normalize.d.ts +20 -0
- package/dist/config/normalize.js +200 -0
- package/dist/config/normalize.js.map +1 -0
- package/dist/config/parameters.d.ts +37 -0
- package/dist/config/parameters.js +71 -0
- package/dist/config/parameters.js.map +1 -0
- package/dist/config/public.d.ts +6 -0
- package/dist/config/public.js +18 -0
- package/dist/config/public.js.map +1 -0
- package/dist/config/schemas.d.ts +538 -0
- package/dist/config/schemas.js +321 -0
- package/dist/config/schemas.js.map +1 -0
- package/dist/config/snapshot.d.ts +38 -0
- package/dist/config/snapshot.js +57 -0
- package/dist/config/snapshot.js.map +1 -0
- package/dist/config/validate.d.ts +33 -0
- package/dist/config/validate.js +346 -0
- package/dist/config/validate.js.map +1 -0
- package/dist/core/clock.d.ts +59 -0
- package/dist/core/clock.js +133 -0
- package/dist/core/clock.js.map +1 -0
- package/dist/core/duration.d.ts +19 -0
- package/dist/core/duration.js +93 -0
- package/dist/core/duration.js.map +1 -0
- package/dist/core/errors.d.ts +62 -0
- package/dist/core/errors.js +72 -0
- package/dist/core/errors.js.map +1 -0
- package/dist/core/ids.d.ts +57 -0
- package/dist/core/ids.js +88 -0
- package/dist/core/ids.js.map +1 -0
- package/dist/core/index.d.ts +13 -0
- package/dist/core/index.js +14 -0
- package/dist/core/index.js.map +1 -0
- package/dist/core/logger.d.ts +100 -0
- package/dist/core/logger.js +207 -0
- package/dist/core/logger.js.map +1 -0
- package/dist/core/paths.d.ts +84 -0
- package/dist/core/paths.js +138 -0
- package/dist/core/paths.js.map +1 -0
- package/dist/core/template.d.ts +136 -0
- package/dist/core/template.js +261 -0
- package/dist/core/template.js.map +1 -0
- package/dist/core/types.d.ts +544 -0
- package/dist/core/types.js +172 -0
- package/dist/core/types.js.map +1 -0
- package/dist/core/worker-protocol.d.ts +102 -0
- package/dist/core/worker-protocol.js +75 -0
- package/dist/core/worker-protocol.js.map +1 -0
- package/dist/executors/classify.d.ts +25 -0
- package/dist/executors/classify.js +54 -0
- package/dist/executors/classify.js.map +1 -0
- package/dist/executors/dispatcher.d.ts +35 -0
- package/dist/executors/dispatcher.js +68 -0
- package/dist/executors/dispatcher.js.map +1 -0
- package/dist/executors/env.d.ts +43 -0
- package/dist/executors/env.js +66 -0
- package/dist/executors/env.js.map +1 -0
- package/dist/executors/event-parser.d.ts +41 -0
- package/dist/executors/event-parser.js +106 -0
- package/dist/executors/event-parser.js.map +1 -0
- package/dist/executors/index.d.ts +12 -0
- package/dist/executors/index.js +13 -0
- package/dist/executors/index.js.map +1 -0
- package/dist/executors/log-capture.d.ts +57 -0
- package/dist/executors/log-capture.js +155 -0
- package/dist/executors/log-capture.js.map +1 -0
- package/dist/executors/process-identity.d.ts +124 -0
- package/dist/executors/process-identity.js +283 -0
- package/dist/executors/process-identity.js.map +1 -0
- package/dist/executors/shell-executor.d.ts +35 -0
- package/dist/executors/shell-executor.js +478 -0
- package/dist/executors/shell-executor.js.map +1 -0
- package/dist/executors/stream-redactor.d.ts +40 -0
- package/dist/executors/stream-redactor.js +89 -0
- package/dist/executors/stream-redactor.js.map +1 -0
- package/dist/executors/workspace.d.ts +10 -0
- package/dist/executors/workspace.js +47 -0
- package/dist/executors/workspace.js.map +1 -0
- package/dist/filters/evaluate.d.ts +77 -0
- package/dist/filters/evaluate.js +187 -0
- package/dist/filters/evaluate.js.map +1 -0
- package/dist/filters/fields.d.ts +35 -0
- package/dist/filters/fields.js +75 -0
- package/dist/filters/fields.js.map +1 -0
- package/dist/filters/index.d.ts +11 -0
- package/dist/filters/index.js +12 -0
- package/dist/filters/index.js.map +1 -0
- package/dist/filters/iso-date.d.ts +10 -0
- package/dist/filters/iso-date.js +42 -0
- package/dist/filters/iso-date.js.map +1 -0
- package/dist/filters/predicate.d.ts +24 -0
- package/dist/filters/predicate.js +178 -0
- package/dist/filters/predicate.js.map +1 -0
- package/dist/filters/priority.d.ts +51 -0
- package/dist/filters/priority.js +91 -0
- package/dist/filters/priority.js.map +1 -0
- package/dist/filters/pushdown.d.ts +12 -0
- package/dist/filters/pushdown.js +52 -0
- package/dist/filters/pushdown.js.map +1 -0
- package/dist/filters/shell-check.d.ts +110 -0
- package/dist/filters/shell-check.js +304 -0
- package/dist/filters/shell-check.js.map +1 -0
- package/dist/identities/github-app.d.ts +55 -0
- package/dist/identities/github-app.js +160 -0
- package/dist/identities/github-app.js.map +1 -0
- package/dist/identities/index.d.ts +6 -0
- package/dist/identities/index.js +7 -0
- package/dist/identities/index.js.map +1 -0
- package/dist/identities/jwt.d.ts +24 -0
- package/dist/identities/jwt.js +56 -0
- package/dist/identities/jwt.js.map +1 -0
- package/dist/lifecycle/context.d.ts +106 -0
- package/dist/lifecycle/context.js +170 -0
- package/dist/lifecycle/context.js.map +1 -0
- package/dist/lifecycle/engine.d.ts +185 -0
- package/dist/lifecycle/engine.js +551 -0
- package/dist/lifecycle/engine.js.map +1 -0
- package/dist/lifecycle/errors.d.ts +48 -0
- package/dist/lifecycle/errors.js +71 -0
- package/dist/lifecycle/errors.js.map +1 -0
- package/dist/lifecycle/index.d.ts +9 -0
- package/dist/lifecycle/index.js +9 -0
- package/dist/lifecycle/index.js.map +1 -0
- package/dist/lifecycle/performers.d.ts +66 -0
- package/dist/lifecycle/performers.js +179 -0
- package/dist/lifecycle/performers.js.map +1 -0
- package/dist/notifications/index.d.ts +6 -0
- package/dist/notifications/index.js +7 -0
- package/dist/notifications/index.js.map +1 -0
- package/dist/notifications/service.d.ts +115 -0
- package/dist/notifications/service.js +364 -0
- package/dist/notifications/service.js.map +1 -0
- package/dist/persistence/actions.d.ts +101 -0
- package/dist/persistence/actions.js +196 -0
- package/dist/persistence/actions.js.map +1 -0
- package/dist/persistence/blocks.d.ts +85 -0
- package/dist/persistence/blocks.js +140 -0
- package/dist/persistence/blocks.js.map +1 -0
- package/dist/persistence/cron-firings.d.ts +55 -0
- package/dist/persistence/cron-firings.js +70 -0
- package/dist/persistence/cron-firings.js.map +1 -0
- package/dist/persistence/database.d.ts +60 -0
- package/dist/persistence/database.js +124 -0
- package/dist/persistence/database.js.map +1 -0
- package/dist/persistence/errors.d.ts +39 -0
- package/dist/persistence/errors.js +67 -0
- package/dist/persistence/errors.js.map +1 -0
- package/dist/persistence/events.d.ts +72 -0
- package/dist/persistence/events.js +83 -0
- package/dist/persistence/events.js.map +1 -0
- package/dist/persistence/index.d.ts +18 -0
- package/dist/persistence/index.js +19 -0
- package/dist/persistence/index.js.map +1 -0
- package/dist/persistence/instance-lock.d.ts +26 -0
- package/dist/persistence/instance-lock.js +117 -0
- package/dist/persistence/instance-lock.js.map +1 -0
- package/dist/persistence/lock-keys.d.ts +16 -0
- package/dist/persistence/lock-keys.js +41 -0
- package/dist/persistence/lock-keys.js.map +1 -0
- package/dist/persistence/notifications.d.ts +113 -0
- package/dist/persistence/notifications.js +213 -0
- package/dist/persistence/notifications.js.map +1 -0
- package/dist/persistence/persistence.d.ts +46 -0
- package/dist/persistence/persistence.js +42 -0
- package/dist/persistence/persistence.js.map +1 -0
- package/dist/persistence/retention.d.ts +46 -0
- package/dist/persistence/retention.js +68 -0
- package/dist/persistence/retention.js.map +1 -0
- package/dist/persistence/runs.d.ts +215 -0
- package/dist/persistence/runs.js +417 -0
- package/dist/persistence/runs.js.map +1 -0
- package/dist/persistence/schema.d.ts +16 -0
- package/dist/persistence/schema.js +183 -0
- package/dist/persistence/schema.js.map +1 -0
- package/dist/persistence/sqlite.d.ts +49 -0
- package/dist/persistence/sqlite.js +131 -0
- package/dist/persistence/sqlite.js.map +1 -0
- package/dist/runs/controller.d.ts +307 -0
- package/dist/runs/controller.js +1078 -0
- package/dist/runs/controller.js.map +1 -0
- package/dist/runs/errors.d.ts +20 -0
- package/dist/runs/errors.js +26 -0
- package/dist/runs/errors.js.map +1 -0
- package/dist/runs/event-bus.d.ts +106 -0
- package/dist/runs/event-bus.js +105 -0
- package/dist/runs/event-bus.js.map +1 -0
- package/dist/runs/execution.d.ts +39 -0
- package/dist/runs/execution.js +146 -0
- package/dist/runs/execution.js.map +1 -0
- package/dist/runs/index.d.ts +12 -0
- package/dist/runs/index.js +13 -0
- package/dist/runs/index.js.map +1 -0
- package/dist/runs/retention.d.ts +64 -0
- package/dist/runs/retention.js +232 -0
- package/dist/runs/retention.js.map +1 -0
- package/dist/runs/workspace.d.ts +20 -0
- package/dist/runs/workspace.js +51 -0
- package/dist/runs/workspace.js.map +1 -0
- package/dist/scheduler/checks.d.ts +41 -0
- package/dist/scheduler/checks.js +111 -0
- package/dist/scheduler/checks.js.map +1 -0
- package/dist/scheduler/cron.d.ts +32 -0
- package/dist/scheduler/cron.js +83 -0
- package/dist/scheduler/cron.js.map +1 -0
- package/dist/scheduler/dry-run.d.ts +42 -0
- package/dist/scheduler/dry-run.js +167 -0
- package/dist/scheduler/dry-run.js.map +1 -0
- package/dist/scheduler/errors.d.ts +22 -0
- package/dist/scheduler/errors.js +22 -0
- package/dist/scheduler/errors.js.map +1 -0
- package/dist/scheduler/format.d.ts +3 -0
- package/dist/scheduler/format.js +73 -0
- package/dist/scheduler/format.js.map +1 -0
- package/dist/scheduler/index.d.ts +13 -0
- package/dist/scheduler/index.js +14 -0
- package/dist/scheduler/index.js.map +1 -0
- package/dist/scheduler/planner.d.ts +88 -0
- package/dist/scheduler/planner.js +255 -0
- package/dist/scheduler/planner.js.map +1 -0
- package/dist/scheduler/scheduler.d.ts +160 -0
- package/dist/scheduler/scheduler.js +680 -0
- package/dist/scheduler/scheduler.js.map +1 -0
- package/dist/scheduler/state.d.ts +26 -0
- package/dist/scheduler/state.js +25 -0
- package/dist/scheduler/state.js.map +1 -0
- package/dist/scheduler/types.d.ts +197 -0
- package/dist/scheduler/types.js +3 -0
- package/dist/scheduler/types.js.map +1 -0
- package/dist/service/index.d.ts +6 -0
- package/dist/service/index.js +7 -0
- package/dist/service/index.js.map +1 -0
- package/dist/service/install.d.ts +93 -0
- package/dist/service/install.js +250 -0
- package/dist/service/install.js.map +1 -0
- package/dist/service/unit.d.ts +50 -0
- package/dist/service/unit.js +171 -0
- package/dist/service/unit.js.map +1 -0
- package/dist/sources/github/adapter.d.ts +99 -0
- package/dist/sources/github/adapter.js +336 -0
- package/dist/sources/github/adapter.js.map +1 -0
- package/dist/sources/github/fields.d.ts +8 -0
- package/dist/sources/github/fields.js +72 -0
- package/dist/sources/github/fields.js.map +1 -0
- package/dist/sources/github/http.d.ts +100 -0
- package/dist/sources/github/http.js +288 -0
- package/dist/sources/github/http.js.map +1 -0
- package/dist/sources/github/index.d.ts +6 -0
- package/dist/sources/github/index.js +7 -0
- package/dist/sources/github/index.js.map +1 -0
- package/dist/sources/github/pushdown.d.ts +14 -0
- package/dist/sources/github/pushdown.js +47 -0
- package/dist/sources/github/pushdown.js.map +1 -0
- package/dist/sources/github/refs.d.ts +17 -0
- package/dist/sources/github/refs.js +61 -0
- package/dist/sources/github/refs.js.map +1 -0
- package/dist/sources/index.d.ts +6 -0
- package/dist/sources/index.js +7 -0
- package/dist/sources/index.js.map +1 -0
- package/dist/ui/index.d.ts +12 -0
- package/dist/ui/index.js +28 -0
- package/dist/ui/index.js.map +1 -0
- package/dist/ui/public/app.css +239 -0
- package/dist/ui/public/favicon.svg +1 -0
- package/dist/ui/public/index.html +27 -0
- package/dist/ui/public/js/client/api.js +68 -0
- package/dist/ui/public/js/client/app.js +146 -0
- package/dist/ui/public/js/client/dom.js +34 -0
- package/dist/ui/public/js/client/page.js +9 -0
- package/dist/ui/public/js/client/pages/actions.js +35 -0
- package/dist/ui/public/js/client/pages/blocked.js +58 -0
- package/dist/ui/public/js/client/pages/config.js +126 -0
- package/dist/ui/public/js/client/pages/dashboard.js +175 -0
- package/dist/ui/public/js/client/pages/run.js +367 -0
- package/dist/ui/public/js/client/pages/runs.js +72 -0
- package/dist/ui/public/js/client/pages/views.js +80 -0
- package/dist/ui/public/js/client/pages/workflows.js +291 -0
- package/dist/ui/public/js/client/types.js +1 -0
- package/dist/ui/public/js/client/ui.js +152 -0
- package/dist/ui/public/js/shared/dom.js +77 -0
- package/dist/ui/public/js/shared/events.js +88 -0
- package/dist/ui/public/js/shared/format.js +213 -0
- package/dist/ui/public/js/shared/logs.js +136 -0
- package/dist/ui/public/js/shared/params.js +90 -0
- package/dist/ui/public/js/shared/route.js +36 -0
- package/dist/ui/public/js/shared/sort.js +70 -0
- package/dist/ui/public/js/shared/sse.js +193 -0
- package/dist/ui/public/js/shared/throttle.js +65 -0
- package/dist/views/index.d.ts +6 -0
- package/dist/views/index.js +7 -0
- package/dist/views/index.js.map +1 -0
- package/dist/views/service.d.ts +131 -0
- package/dist/views/service.js +264 -0
- package/dist/views/service.js.map +1 -0
- package/docs/api.md +239 -0
- package/docs/configuration-reference.md +1785 -0
- package/docs/cron-semantics.md +96 -0
- package/docs/manual-tests/github-fixture/config.yaml +30 -0
- package/docs/manual-tests/github-fixture/helpers.sh +93 -0
- package/docs/manual-tests/github-fixture/identities.yaml +18 -0
- package/docs/manual-tests/github-fixture/scripts/test-worker.sh +100 -0
- package/docs/manual-tests/github-fixture/sources.yaml +13 -0
- package/docs/manual-tests/github-fixture/views/dependencies.yaml +17 -0
- package/docs/manual-tests/github-fixture/views/needs-maintainer.yaml +17 -0
- package/docs/manual-tests/github-fixture/workflows/coder-test.yaml +76 -0
- package/docs/manual-tests/github-fixture/workflows/commenter-test.yaml +63 -0
- package/docs/manual-tests/github-fixture/workflows/reviewer-test.yaml +60 -0
- package/docs/manual-tests/github.md +1308 -0
- package/docs/manual-tests/process-supervision.md +64 -0
- package/docs/manual-tests/systemd.md +68 -0
- package/docs/operations.md +271 -0
- package/docs/worker-protocol.md +145 -0
- package/examples/config/config.yaml +35 -0
- package/examples/config/identities.yaml +18 -0
- package/examples/config/sources.yaml +13 -0
- package/examples/config/views/needs-maintainer.yaml +15 -0
- package/examples/config/workflows/coder-project-a.yaml +86 -0
- package/examples/config/workflows/deploy.yaml +15 -0
- package/examples/config/workflows/nightly-maintenance.yaml +13 -0
- package/package.json +75 -4
|
@@ -0,0 +1,178 @@
|
|
|
1
|
+
import { parseIsoDate } from './iso-date.js';
|
|
2
|
+
const TRUE = { value: true };
|
|
3
|
+
const FALSE = { value: false };
|
|
4
|
+
function unknown(reason) {
|
|
5
|
+
return { value: 'unknown', reason };
|
|
6
|
+
}
|
|
7
|
+
function isScalar(v) {
|
|
8
|
+
return typeof v === 'string' || typeof v === 'number' || typeof v === 'boolean';
|
|
9
|
+
}
|
|
10
|
+
function typeName(v) {
|
|
11
|
+
if (v === null)
|
|
12
|
+
return 'null';
|
|
13
|
+
if (Array.isArray(v))
|
|
14
|
+
return 'array';
|
|
15
|
+
return typeof v;
|
|
16
|
+
}
|
|
17
|
+
/** Strict ISO-8601 (no offset = UTC); anything else is not a date. */
|
|
18
|
+
const parseDate = parseIsoDate;
|
|
19
|
+
/**
|
|
20
|
+
* Equality of two scalars. Dates (field type `date`) compare as instants.
|
|
21
|
+
* Returns `unknown` for different JS types.
|
|
22
|
+
*/
|
|
23
|
+
function scalarEquals(actual, expected, fieldType) {
|
|
24
|
+
if (fieldType === 'date') {
|
|
25
|
+
const a = parseDate(actual);
|
|
26
|
+
const b = parseDate(expected);
|
|
27
|
+
if (a === undefined || b === undefined)
|
|
28
|
+
return unknown('date value is not ISO-8601');
|
|
29
|
+
return a === b ? TRUE : FALSE;
|
|
30
|
+
}
|
|
31
|
+
if (typeof actual !== typeof expected) {
|
|
32
|
+
return unknown(`incompatible types: ${typeName(actual)} vs ${typeName(expected)}`);
|
|
33
|
+
}
|
|
34
|
+
if (typeof actual === 'number' && (Number.isNaN(actual) || Number.isNaN(expected))) {
|
|
35
|
+
return unknown('NaN is not comparable');
|
|
36
|
+
}
|
|
37
|
+
return actual === expected ? TRUE : FALSE;
|
|
38
|
+
}
|
|
39
|
+
function equals(actual, expected, fieldType) {
|
|
40
|
+
// `null` is a known absent value (e.g. no milestone): it equals only `null`.
|
|
41
|
+
if (actual === null || expected === null)
|
|
42
|
+
return actual === expected ? TRUE : FALSE;
|
|
43
|
+
const actualIsArray = Array.isArray(actual);
|
|
44
|
+
const expectedIsArray = Array.isArray(expected);
|
|
45
|
+
if (actualIsArray !== expectedIsArray) {
|
|
46
|
+
return unknown(`incompatible types: ${typeName(actual)} vs ${typeName(expected)}`);
|
|
47
|
+
}
|
|
48
|
+
if (actualIsArray) {
|
|
49
|
+
// Arrays (e.g. labels) compare as sets: order and duplicates do not matter.
|
|
50
|
+
const a = actual;
|
|
51
|
+
const b = expected;
|
|
52
|
+
if (!a.every(isScalar) || !b.every(isScalar))
|
|
53
|
+
return unknown('array contains non-scalar values');
|
|
54
|
+
const sa = new Set(a);
|
|
55
|
+
const sb = new Set(b);
|
|
56
|
+
if (sa.size !== sb.size)
|
|
57
|
+
return FALSE;
|
|
58
|
+
for (const x of sa)
|
|
59
|
+
if (!sb.has(x))
|
|
60
|
+
return FALSE;
|
|
61
|
+
return TRUE;
|
|
62
|
+
}
|
|
63
|
+
return scalarEquals(actual, expected, fieldType);
|
|
64
|
+
}
|
|
65
|
+
function compareOrder(actual, expected, fieldType) {
|
|
66
|
+
if (actual === null || expected === null)
|
|
67
|
+
return unknown('null is not comparable');
|
|
68
|
+
if (fieldType === 'date') {
|
|
69
|
+
const a = parseDate(actual);
|
|
70
|
+
const b = parseDate(expected);
|
|
71
|
+
if (a === undefined || b === undefined)
|
|
72
|
+
return unknown('date value is not ISO-8601');
|
|
73
|
+
return { cmp: Math.sign(a - b) };
|
|
74
|
+
}
|
|
75
|
+
if (typeof actual === 'number' && typeof expected === 'number') {
|
|
76
|
+
if (Number.isNaN(actual) || Number.isNaN(expected))
|
|
77
|
+
return unknown('NaN is not comparable');
|
|
78
|
+
return { cmp: Math.sign(actual - expected) };
|
|
79
|
+
}
|
|
80
|
+
if (typeof actual === 'string' && typeof expected === 'string') {
|
|
81
|
+
// Plain code-unit order: deterministic, locale-independent (ISO dates sort correctly).
|
|
82
|
+
return { cmp: actual < expected ? -1 : actual > expected ? 1 : 0 };
|
|
83
|
+
}
|
|
84
|
+
return unknown(`not comparable: ${typeName(actual)} vs ${typeName(expected)}`);
|
|
85
|
+
}
|
|
86
|
+
function contains(actual, expected) {
|
|
87
|
+
if (expected === null || Array.isArray(expected)) {
|
|
88
|
+
return unknown(`contains expects a scalar operand, got ${typeName(expected)}`);
|
|
89
|
+
}
|
|
90
|
+
if (actual === null)
|
|
91
|
+
return FALSE;
|
|
92
|
+
if (Array.isArray(actual)) {
|
|
93
|
+
const arr = actual;
|
|
94
|
+
if (arr.length === 0)
|
|
95
|
+
return FALSE;
|
|
96
|
+
if (!arr.some((x) => typeof x === typeof expected)) {
|
|
97
|
+
return unknown(`incompatible types: array of ${typeName(arr[0])} vs ${typeName(expected)}`);
|
|
98
|
+
}
|
|
99
|
+
return arr.includes(expected) ? TRUE : FALSE;
|
|
100
|
+
}
|
|
101
|
+
if (typeof actual === 'string' && typeof expected === 'string') {
|
|
102
|
+
return actual.includes(expected) ? TRUE : FALSE;
|
|
103
|
+
}
|
|
104
|
+
return unknown(`contains not applicable: ${typeName(actual)} vs ${typeName(expected)}`);
|
|
105
|
+
}
|
|
106
|
+
function inList(actual, expected, fieldType) {
|
|
107
|
+
if (!Array.isArray(expected))
|
|
108
|
+
return unknown(`in expects an array operand, got ${typeName(expected)}`);
|
|
109
|
+
const list = expected;
|
|
110
|
+
if (actual === null)
|
|
111
|
+
return FALSE;
|
|
112
|
+
if (Array.isArray(actual)) {
|
|
113
|
+
// Array field: true if any element is in the list (non-empty intersection).
|
|
114
|
+
const arr = actual;
|
|
115
|
+
if (arr.length === 0 || list.length === 0)
|
|
116
|
+
return FALSE;
|
|
117
|
+
if (!arr.some((x) => list.some((y) => typeof y === typeof x))) {
|
|
118
|
+
return unknown('incompatible types between field array and list');
|
|
119
|
+
}
|
|
120
|
+
return arr.some((x) => list.includes(x)) ? TRUE : FALSE;
|
|
121
|
+
}
|
|
122
|
+
if (list.length === 0)
|
|
123
|
+
return FALSE;
|
|
124
|
+
let sawUnknown = false;
|
|
125
|
+
let sawComparable = false;
|
|
126
|
+
for (const candidate of list) {
|
|
127
|
+
const r = scalarEquals(actual, candidate, fieldType);
|
|
128
|
+
if (r.value === true)
|
|
129
|
+
return TRUE;
|
|
130
|
+
if (r.value === 'unknown')
|
|
131
|
+
sawUnknown = true;
|
|
132
|
+
else
|
|
133
|
+
sawComparable = true;
|
|
134
|
+
}
|
|
135
|
+
if (sawComparable)
|
|
136
|
+
return FALSE;
|
|
137
|
+
return sawUnknown ? unknown(`incompatible types: ${typeName(actual)} vs list`) : FALSE;
|
|
138
|
+
}
|
|
139
|
+
function lower(value) {
|
|
140
|
+
if (typeof value === 'string')
|
|
141
|
+
return value.toLowerCase();
|
|
142
|
+
if (Array.isArray(value))
|
|
143
|
+
return value.map((v) => (typeof v === 'string' ? v.toLowerCase() : v));
|
|
144
|
+
return value;
|
|
145
|
+
}
|
|
146
|
+
/**
|
|
147
|
+
* Apply `operator` to a known field value and the literal `expected`.
|
|
148
|
+
* `fieldType` (from the adapter's field definition) enables date semantics;
|
|
149
|
+
* `options.caseInsensitive` folds the case of all string values first.
|
|
150
|
+
*/
|
|
151
|
+
export function applyOperator(operator, actualValue, expectedValue, fieldType, options = {}) {
|
|
152
|
+
const actual = options.caseInsensitive ? lower(actualValue) : actualValue;
|
|
153
|
+
const expected = options.caseInsensitive ? lower(expectedValue) : expectedValue;
|
|
154
|
+
switch (operator) {
|
|
155
|
+
case 'equals':
|
|
156
|
+
return equals(actual, expected, fieldType);
|
|
157
|
+
case 'not_equals': {
|
|
158
|
+
const r = equals(actual, expected, fieldType);
|
|
159
|
+
return r.value === 'unknown' ? r : r.value ? FALSE : TRUE;
|
|
160
|
+
}
|
|
161
|
+
case 'contains':
|
|
162
|
+
return contains(actual, expected);
|
|
163
|
+
case 'in':
|
|
164
|
+
return inList(actual, expected, fieldType);
|
|
165
|
+
case 'greater_than':
|
|
166
|
+
case 'less_than': {
|
|
167
|
+
if (Array.isArray(actual) || Array.isArray(expected))
|
|
168
|
+
return unknown('arrays are not comparable');
|
|
169
|
+
const r = compareOrder(actual, expected, fieldType);
|
|
170
|
+
if (!('cmp' in r))
|
|
171
|
+
return r;
|
|
172
|
+
return (operator === 'greater_than' ? r.cmp > 0 : r.cmp < 0) ? TRUE : FALSE;
|
|
173
|
+
}
|
|
174
|
+
default:
|
|
175
|
+
return unknown(`unsupported operator: ${String(operator)}`);
|
|
176
|
+
}
|
|
177
|
+
}
|
|
178
|
+
//# sourceMappingURL=predicate.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"predicate.js","sourceRoot":"","sources":["../../src/filters/predicate.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Item priority (`item_priority.rules`) and deterministic candidate ordering (Spec §7).
|
|
3
|
+
*/
|
|
4
|
+
import type { FilterNode } from '../core/index.js';
|
|
5
|
+
import { type FieldSource, type FilterTrace } from './evaluate.js';
|
|
6
|
+
/** One `item_priority` rule: first rule whose `when` is true wins. */
|
|
7
|
+
export interface ItemPriorityRule {
|
|
8
|
+
when: FilterNode;
|
|
9
|
+
value: number;
|
|
10
|
+
}
|
|
11
|
+
/** `item_priority` block of a workflow. */
|
|
12
|
+
export interface ItemPriorityConfig {
|
|
13
|
+
rules: readonly ItemPriorityRule[];
|
|
14
|
+
default: number;
|
|
15
|
+
}
|
|
16
|
+
/** Result of {@link resolveItemPriority}. */
|
|
17
|
+
export interface ItemPriorityResult {
|
|
18
|
+
priority: number;
|
|
19
|
+
/** Index of the matching rule, or `null` if the default applied. */
|
|
20
|
+
matchedRule: number | null;
|
|
21
|
+
/** One trace per rule; rules after the match are `not_evaluated`. */
|
|
22
|
+
traces: FilterTrace[];
|
|
23
|
+
}
|
|
24
|
+
/**
|
|
25
|
+
* Determine an item's priority: the first rule evaluating to `true` wins;
|
|
26
|
+
* `false` and `unknown` do not match; otherwise `default` (0 if no config).
|
|
27
|
+
*/
|
|
28
|
+
export declare function resolveItemPriority(config: ItemPriorityConfig | undefined | null, source: FieldSource): Promise<ItemPriorityResult>;
|
|
29
|
+
/** Minimal shape needed for ordering scheduling candidates. */
|
|
30
|
+
export interface PrioritizedCandidate {
|
|
31
|
+
workflowId: string;
|
|
32
|
+
workflowPriority: number;
|
|
33
|
+
itemPriority: number;
|
|
34
|
+
/** Item creation time (ISO-8601); missing values sort after present ones. */
|
|
35
|
+
createdAt?: string | undefined;
|
|
36
|
+
/** `sourceItemKey(...)`; absent for item-less (cron/manual) candidates. */
|
|
37
|
+
itemKey?: string | undefined;
|
|
38
|
+
}
|
|
39
|
+
/**
|
|
40
|
+
* Locale-independent natural compare: digit runs compare numerically
|
|
41
|
+
* (`repo:9` < `repo:10`), everything else by code unit; final fallback is a
|
|
42
|
+
* plain code-unit compare so distinct strings never compare equal.
|
|
43
|
+
*/
|
|
44
|
+
export declare function naturalCompare(a: string, b: string): number;
|
|
45
|
+
/**
|
|
46
|
+
* Total order for candidates (Spec §7): workflow priority desc → item priority
|
|
47
|
+
* desc → creation time asc (missing/non-ISO last) → item key asc (natural) → workflow ID asc.
|
|
48
|
+
*/
|
|
49
|
+
export declare function compareCandidates(a: PrioritizedCandidate, b: PrioritizedCandidate): number;
|
|
50
|
+
/** Return a new array sorted by {@link compareCandidates}; input order does not matter. */
|
|
51
|
+
export declare function sortCandidates<T extends PrioritizedCandidate>(candidates: readonly T[]): T[];
|
|
@@ -0,0 +1,91 @@
|
|
|
1
|
+
import { parseIsoDate } from './iso-date.js';
|
|
2
|
+
import { evaluateFilter, notEvaluatedTrace } from './evaluate.js';
|
|
3
|
+
/**
|
|
4
|
+
* Determine an item's priority: the first rule evaluating to `true` wins;
|
|
5
|
+
* `false` and `unknown` do not match; otherwise `default` (0 if no config).
|
|
6
|
+
*/
|
|
7
|
+
export async function resolveItemPriority(config, source) {
|
|
8
|
+
if (!config)
|
|
9
|
+
return { priority: 0, matchedRule: null, traces: [] };
|
|
10
|
+
const traces = [];
|
|
11
|
+
let matched = null;
|
|
12
|
+
for (const [i, rule] of config.rules.entries()) {
|
|
13
|
+
if (matched !== null) {
|
|
14
|
+
traces.push(notEvaluatedTrace(rule.when));
|
|
15
|
+
continue;
|
|
16
|
+
}
|
|
17
|
+
const r = await evaluateFilter(rule.when, source);
|
|
18
|
+
traces.push(r.trace);
|
|
19
|
+
if (r.value === true)
|
|
20
|
+
matched = i;
|
|
21
|
+
}
|
|
22
|
+
return {
|
|
23
|
+
priority: matched === null ? config.default : config.rules[matched].value,
|
|
24
|
+
matchedRule: matched,
|
|
25
|
+
traces,
|
|
26
|
+
};
|
|
27
|
+
}
|
|
28
|
+
function codeUnitCompare(a, b) {
|
|
29
|
+
return a < b ? -1 : a > b ? 1 : 0;
|
|
30
|
+
}
|
|
31
|
+
/**
|
|
32
|
+
* Locale-independent natural compare: digit runs compare numerically
|
|
33
|
+
* (`repo:9` < `repo:10`), everything else by code unit; final fallback is a
|
|
34
|
+
* plain code-unit compare so distinct strings never compare equal.
|
|
35
|
+
*/
|
|
36
|
+
export function naturalCompare(a, b) {
|
|
37
|
+
const re = /(\d+)|(\D+)/g;
|
|
38
|
+
const ta = a.match(re) ?? [];
|
|
39
|
+
const tb = b.match(re) ?? [];
|
|
40
|
+
for (let i = 0; i < Math.min(ta.length, tb.length); i++) {
|
|
41
|
+
const x = ta[i];
|
|
42
|
+
const y = tb[i];
|
|
43
|
+
const xd = /^\d/.test(x);
|
|
44
|
+
const yd = /^\d/.test(y);
|
|
45
|
+
let c;
|
|
46
|
+
if (xd && yd) {
|
|
47
|
+
const xs = x.replace(/^0+(?=\d)/, '');
|
|
48
|
+
const ys = y.replace(/^0+(?=\d)/, '');
|
|
49
|
+
c = xs.length - ys.length || codeUnitCompare(xs, ys);
|
|
50
|
+
}
|
|
51
|
+
else {
|
|
52
|
+
c = codeUnitCompare(x, y);
|
|
53
|
+
}
|
|
54
|
+
if (c !== 0)
|
|
55
|
+
return Math.sign(c);
|
|
56
|
+
}
|
|
57
|
+
return Math.sign(ta.length - tb.length) || codeUnitCompare(a, b);
|
|
58
|
+
}
|
|
59
|
+
/** Strict ISO-8601 (no offset = UTC); missing or invalid values sort last. */
|
|
60
|
+
function createdAtMs(v) {
|
|
61
|
+
return parseIsoDate(v);
|
|
62
|
+
}
|
|
63
|
+
/**
|
|
64
|
+
* Total order for candidates (Spec §7): workflow priority desc → item priority
|
|
65
|
+
* desc → creation time asc (missing/non-ISO last) → item key asc (natural) → workflow ID asc.
|
|
66
|
+
*/
|
|
67
|
+
export function compareCandidates(a, b) {
|
|
68
|
+
if (a.workflowPriority !== b.workflowPriority)
|
|
69
|
+
return b.workflowPriority > a.workflowPriority ? 1 : -1;
|
|
70
|
+
if (a.itemPriority !== b.itemPriority)
|
|
71
|
+
return b.itemPriority > a.itemPriority ? 1 : -1;
|
|
72
|
+
const ca = createdAtMs(a.createdAt);
|
|
73
|
+
const cb = createdAtMs(b.createdAt);
|
|
74
|
+
if (ca !== cb) {
|
|
75
|
+
if (ca === undefined)
|
|
76
|
+
return 1;
|
|
77
|
+
if (cb === undefined)
|
|
78
|
+
return -1;
|
|
79
|
+
return ca < cb ? -1 : 1;
|
|
80
|
+
}
|
|
81
|
+
const ka = a.itemKey ?? '';
|
|
82
|
+
const kb = b.itemKey ?? '';
|
|
83
|
+
if (ka !== kb)
|
|
84
|
+
return naturalCompare(ka, kb);
|
|
85
|
+
return codeUnitCompare(a.workflowId, b.workflowId);
|
|
86
|
+
}
|
|
87
|
+
/** Return a new array sorted by {@link compareCandidates}; input order does not matter. */
|
|
88
|
+
export function sortCandidates(candidates) {
|
|
89
|
+
return [...candidates].sort(compareCandidates);
|
|
90
|
+
}
|
|
91
|
+
//# sourceMappingURL=priority.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"priority.js","sourceRoot":"","sources":["../../src/filters/priority.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import { type FieldDefinition, type FilterNode, type FilterPredicate } from '../core/index.js';
|
|
2
|
+
/** Result of {@link splitForPushdown}. `null` = nothing in that part. */
|
|
3
|
+
export interface PushdownSplit {
|
|
4
|
+
/** Conjunction the adapter may push into its query (pass as `listCandidates({ filter })`). */
|
|
5
|
+
pushdown: FilterNode | null;
|
|
6
|
+
/** Remaining conjunction that must be evaluated locally. */
|
|
7
|
+
local: FilterNode | null;
|
|
8
|
+
}
|
|
9
|
+
/** True if the adapter declares pushdown support for this predicate. */
|
|
10
|
+
export declare function canPushDown(predicate: FilterPredicate, definitions: readonly FieldDefinition[]): boolean;
|
|
11
|
+
/** Split `filter` into a pushable and a local conjunction. */
|
|
12
|
+
export declare function splitForPushdown(filter: FilterNode | undefined | null, definitions: readonly FieldDefinition[]): PushdownSplit;
|
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Conservative pushdown split (Spec §6): which part of a filter the adapter may
|
|
3
|
+
* evaluate in its external query, and which part stays local.
|
|
4
|
+
*
|
|
5
|
+
* Only predicates of a top-level conjunction (`all`, nested `all`s are
|
|
6
|
+
* flattened) are pushed, and only if the field is declared, cheap, and lists
|
|
7
|
+
* the operator in `FieldDefinition.pushdown`. `any`/`not` are never pushed.
|
|
8
|
+
* Since `pushdown AND local ≡ filter`, callers may evaluate just `local` on the
|
|
9
|
+
* adapter's result — but because adapters may ignore pushed parts, the safe
|
|
10
|
+
* default (and the `SourceAdapter` contract) is to re-evaluate the full filter.
|
|
11
|
+
*/
|
|
12
|
+
import { isValidNode } from './evaluate.js';
|
|
13
|
+
import { isFilterAll, isFilterPredicate } from '../core/index.js';
|
|
14
|
+
function flattenConjunction(node, out) {
|
|
15
|
+
// Malformed nodes stay local (where they evaluate to unknown).
|
|
16
|
+
if (isValidNode(node) && isFilterAll(node))
|
|
17
|
+
for (const c of node.all)
|
|
18
|
+
flattenConjunction(c, out);
|
|
19
|
+
else
|
|
20
|
+
out.push(node);
|
|
21
|
+
}
|
|
22
|
+
function conjunction(parts) {
|
|
23
|
+
if (parts.length === 0)
|
|
24
|
+
return null;
|
|
25
|
+
if (parts.length === 1)
|
|
26
|
+
return parts[0];
|
|
27
|
+
return { all: parts };
|
|
28
|
+
}
|
|
29
|
+
/** True if the adapter declares pushdown support for this predicate. */
|
|
30
|
+
export function canPushDown(predicate, definitions) {
|
|
31
|
+
const def = definitions.find((d) => d.name === predicate.field);
|
|
32
|
+
if (!def || def.expensive)
|
|
33
|
+
return false;
|
|
34
|
+
return (def.pushdown ?? []).includes(predicate.operator) && def.operators.includes(predicate.operator);
|
|
35
|
+
}
|
|
36
|
+
/** Split `filter` into a pushable and a local conjunction. */
|
|
37
|
+
export function splitForPushdown(filter, definitions) {
|
|
38
|
+
if (!filter)
|
|
39
|
+
return { pushdown: null, local: null };
|
|
40
|
+
const parts = [];
|
|
41
|
+
flattenConjunction(filter, parts);
|
|
42
|
+
const pushed = [];
|
|
43
|
+
const local = [];
|
|
44
|
+
for (const part of parts) {
|
|
45
|
+
if (isValidNode(part) && isFilterPredicate(part) && canPushDown(part, definitions))
|
|
46
|
+
pushed.push(part);
|
|
47
|
+
else
|
|
48
|
+
local.push(part);
|
|
49
|
+
}
|
|
50
|
+
return { pushdown: conjunction(pushed), local: conjunction(local) };
|
|
51
|
+
}
|
|
52
|
+
//# sourceMappingURL=pushdown.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"pushdown.js","sourceRoot":"","sources":["../../src/filters/pushdown.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG;AACH,OAAO,EAAE,WAAW,EAAE,MAAM,eAAe,CAAC;AAC5C,OAAO,EAAE,WAAW,EAAE,iBAAiB,EAA+D,MAAM,kBAAkB,CAAC;AAU/H,SAAS,kBAAkB,CAAC,IAAgB,EAAE,GAAiB;IAC7D,+DAA+D;IAC/D,IAAI,WAAW,CAAC,IAAI,CAAC,IAAI,WAAW,CAAC,IAAI,CAAC;QAAE,KAAK,MAAM,CAAC,IAAI,IAAI,CAAC,GAAG;YAAE,kBAAkB,CAAC,CAAC,EAAE,GAAG,CAAC,CAAC;;QAC5F,GAAG,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;AACtB,CAAC;AAED,SAAS,WAAW,CAAC,KAAmB;IACtC,IAAI,KAAK,CAAC,MAAM,KAAK,CAAC;QAAE,OAAO,IAAI,CAAC;IACpC,IAAI,KAAK,CAAC,MAAM,KAAK,CAAC;QAAE,OAAO,KAAK,CAAC,CAAC,CAAe,CAAC;IACtD,OAAO,EAAE,GAAG,EAAE,KAAK,EAAE,CAAC;AACxB,CAAC;AAED,wEAAwE;AACxE,MAAM,UAAU,WAAW,CAAC,SAA0B,EAAE,WAAuC;IAC7F,MAAM,GAAG,GAAG,WAAW,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,KAAK,SAAS,CAAC,KAAK,CAAC,CAAC;IAChE,IAAI,CAAC,GAAG,IAAI,GAAG,CAAC,SAAS;QAAE,OAAO,KAAK,CAAC;IACxC,OAAO,CAAC,GAAG,CAAC,QAAQ,IAAI,EAAE,CAAC,CAAC,QAAQ,CAAC,SAAS,CAAC,QAAQ,CAAC,IAAI,GAAG,CAAC,SAAS,CAAC,QAAQ,CAAC,SAAS,CAAC,QAAQ,CAAC,CAAC;AACzG,CAAC;AAED,8DAA8D;AAC9D,MAAM,UAAU,gBAAgB,CAC9B,MAAqC,EACrC,WAAuC;IAEvC,IAAI,CAAC,MAAM;QAAE,OAAO,EAAE,QAAQ,EAAE,IAAI,EAAE,KAAK,EAAE,IAAI,EAAE,CAAC;IACpD,MAAM,KAAK,GAAiB,EAAE,CAAC;IAC/B,kBAAkB,CAAC,MAAM,EAAE,KAAK,CAAC,CAAC;IAClC,MAAM,MAAM,GAAiB,EAAE,CAAC;IAChC,MAAM,KAAK,GAAiB,EAAE,CAAC;IAC/B,KAAK,MAAM,IAAI,IAAI,KAAK,EAAE,CAAC;QACzB,IAAI,WAAW,CAAC,IAAI,CAAC,IAAI,iBAAiB,CAAC,IAAI,CAAC,IAAI,WAAW,CAAC,IAAI,EAAE,WAAW,CAAC;YAAE,MAAM,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;;YACjG,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;IACxB,CAAC;IACD,OAAO,EAAE,QAAQ,EAAE,WAAW,CAAC,MAAM,CAAC,EAAE,KAAK,EAAE,WAAW,CAAC,KAAK,CAAC,EAAE,CAAC;AACtE,CAAC"}
|
|
@@ -0,0 +1,110 @@
|
|
|
1
|
+
import { type Clock, type Logger, type SourceItem, type Timers, type TriValue } from '../core/index.js';
|
|
2
|
+
/** Environment variable holding the path of the check context JSON file. */
|
|
3
|
+
export declare const CHECK_CONTEXT_ENV = "ADISPATCH_CHECK_CONTEXT_FILE";
|
|
4
|
+
/** Variables copied from the controller environment into every check process. */
|
|
5
|
+
export declare const MINIMAL_ENV_KEYS: readonly ['PATH', 'HOME', 'LANG', 'TZ', 'USER', 'LOGNAME', 'TMPDIR'];
|
|
6
|
+
/** Default per-stream output limit in bytes. */
|
|
7
|
+
export declare const DEFAULT_MAX_CHECK_OUTPUT_BYTES: number;
|
|
8
|
+
/** Default grace period between SIGTERM and SIGKILL. */
|
|
9
|
+
export declare const DEFAULT_CHECK_KILL_GRACE_MS = 2000;
|
|
10
|
+
/** One configured shell check (shell filter or condition). */
|
|
11
|
+
export interface ShellCheckSpec {
|
|
12
|
+
/** Executable (or, with `shell: true`, a shell command string). */
|
|
13
|
+
command: string;
|
|
14
|
+
args?: readonly string[];
|
|
15
|
+
/** Run `command` through `/bin/sh -c`. Only if explicitly configured. */
|
|
16
|
+
shell?: boolean;
|
|
17
|
+
/** Timeout in milliseconds. */
|
|
18
|
+
timeoutMs: number;
|
|
19
|
+
/** Explicit additional environment variables. */
|
|
20
|
+
env?: Readonly<Record<string, string>>;
|
|
21
|
+
/** Working directory (default: the runner's temp directory for this check). */
|
|
22
|
+
cwd?: string;
|
|
23
|
+
}
|
|
24
|
+
/** Kind of check, part of the context file. */
|
|
25
|
+
export type ShellCheckKind = 'shell_filter' | 'workflow_condition' | 'item_condition';
|
|
26
|
+
/** Content of the file at `ADISPATCH_CHECK_CONTEXT_FILE`. Never contains secrets. */
|
|
27
|
+
export interface ShellCheckContext {
|
|
28
|
+
schema_version: 1;
|
|
29
|
+
kind: ShellCheckKind;
|
|
30
|
+
workflow: {
|
|
31
|
+
id: string;
|
|
32
|
+
};
|
|
33
|
+
/** Present for item-bound checks (shell filter, item conditions). */
|
|
34
|
+
source?: {
|
|
35
|
+
id: string;
|
|
36
|
+
type: string;
|
|
37
|
+
item_id: string;
|
|
38
|
+
item_key: string;
|
|
39
|
+
url: string;
|
|
40
|
+
item_type: string;
|
|
41
|
+
created_at?: string;
|
|
42
|
+
/** Cheap item fields (as in `SourceItem.fields`). */
|
|
43
|
+
attributes: Record<string, unknown>;
|
|
44
|
+
};
|
|
45
|
+
}
|
|
46
|
+
/** Build a {@link ShellCheckContext}. `sourceType` is the adapter type (e.g. `github`). */
|
|
47
|
+
export declare function buildCheckContext(kind: ShellCheckKind, workflowId: string, item?: SourceItem, sourceType?: string): ShellCheckContext;
|
|
48
|
+
/** Result of one shell check. */
|
|
49
|
+
export interface ShellCheckResult {
|
|
50
|
+
value: TriValue;
|
|
51
|
+
exitCode: number | null;
|
|
52
|
+
signal: string | null;
|
|
53
|
+
timedOut: boolean;
|
|
54
|
+
/** Error detail when `value` is `unknown`. */
|
|
55
|
+
error?: string;
|
|
56
|
+
stdout: string;
|
|
57
|
+
stderr: string;
|
|
58
|
+
/** True if stdout or stderr exceeded the limit and was cut. */
|
|
59
|
+
outputTruncated: boolean;
|
|
60
|
+
/** ISO-8601 start time (from the injected clock). */
|
|
61
|
+
startedAt: string;
|
|
62
|
+
durationMs: number;
|
|
63
|
+
/** True if served from the cache ({@link ShellCheckRunner.runCached}). */
|
|
64
|
+
cached: boolean;
|
|
65
|
+
}
|
|
66
|
+
/** Dependencies/options of {@link ShellCheckRunner}. */
|
|
67
|
+
export interface ShellCheckRunnerOptions {
|
|
68
|
+
clock?: Clock;
|
|
69
|
+
timers?: Timers;
|
|
70
|
+
logger?: Logger;
|
|
71
|
+
/** Source of the minimal environment (default: `process.env`). */
|
|
72
|
+
hostEnv?: Readonly<Record<string, string | undefined>>;
|
|
73
|
+
/** Directory for temporary context files (default: OS temp dir). */
|
|
74
|
+
tempDir?: string;
|
|
75
|
+
/** Per-stream output limit in bytes. */
|
|
76
|
+
maxOutputBytes?: number;
|
|
77
|
+
/** Grace period between SIGTERM and SIGKILL. */
|
|
78
|
+
killGraceMs?: number;
|
|
79
|
+
}
|
|
80
|
+
/** Runs shell checks; one instance per orchestrator (holds the workflow-condition cache). */
|
|
81
|
+
export declare class ShellCheckRunner {
|
|
82
|
+
private readonly clock;
|
|
83
|
+
private readonly timers;
|
|
84
|
+
private readonly logger;
|
|
85
|
+
private readonly hostEnv;
|
|
86
|
+
private readonly tempDir;
|
|
87
|
+
private readonly maxOutputBytes;
|
|
88
|
+
private readonly killGraceMs;
|
|
89
|
+
private readonly cache;
|
|
90
|
+
private readonly inflight;
|
|
91
|
+
constructor(options?: ShellCheckRunnerOptions);
|
|
92
|
+
/** Environment for a check process (minimal env + explicit env + context file). */
|
|
93
|
+
buildEnv(spec: ShellCheckSpec, contextFile: string): Record<string, string>;
|
|
94
|
+
/** Run a check without caching. Never throws. */
|
|
95
|
+
run(spec: ShellCheckSpec, context: unknown, options?: {
|
|
96
|
+
signal?: AbortSignal;
|
|
97
|
+
}): Promise<ShellCheckResult>;
|
|
98
|
+
/**
|
|
99
|
+
* Run a check with a TTL cache under `cacheKey` (e.g. `<workflowId>:condition:<index>`).
|
|
100
|
+
* Only definitive results (`true`/`false`) are cached; concurrent calls for
|
|
101
|
+
* the same key share one execution. `ttlMs <= 0` disables caching.
|
|
102
|
+
*/
|
|
103
|
+
runCached(cacheKey: string, ttlMs: number, spec: ShellCheckSpec, context: unknown, options?: {
|
|
104
|
+
signal?: AbortSignal;
|
|
105
|
+
}): Promise<ShellCheckResult>;
|
|
106
|
+
/** Drop one cache entry, or all (e.g. after a config reload). */
|
|
107
|
+
invalidate(cacheKey?: string): void;
|
|
108
|
+
private failure;
|
|
109
|
+
private spawnCheck;
|
|
110
|
+
}
|