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,304 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Shell check runner for shell filters and conditions (Spec §6, §20.3, §20.6).
|
|
3
|
+
*
|
|
4
|
+
* - Command as argument list (no shell), unless `shell: true` is configured
|
|
5
|
+
* explicitly (then `/bin/sh -c <command> sh <args...>`).
|
|
6
|
+
* - Minimal environment (PATH, HOME, LANG, TZ, USER, LOGNAME, TMPDIR) plus
|
|
7
|
+
* explicit `env` plus `ADISPATCH_CHECK_CONTEXT_FILE` pointing to a JSON file with
|
|
8
|
+
* the check context (written with mode 0600, removed afterwards).
|
|
9
|
+
* - Exit 0 = `true`, exit 1 = `false`; exit ≥ 2, signal, timeout, spawn error
|
|
10
|
+
* or abort = `unknown` with error detail.
|
|
11
|
+
* - Output (stdout/stderr) is captured up to a limit, the rest is discarded.
|
|
12
|
+
* - The process runs in its own process group; on timeout/abort the whole
|
|
13
|
+
* group gets SIGTERM, then SIGKILL after a grace period.
|
|
14
|
+
* - Optional TTL cache (Clock based) for workflow conditions; item checks run
|
|
15
|
+
* uncached by default.
|
|
16
|
+
*/
|
|
17
|
+
import { spawn } from 'node:child_process';
|
|
18
|
+
import { mkdtemp, rm, writeFile } from 'node:fs/promises';
|
|
19
|
+
import { tmpdir } from 'node:os';
|
|
20
|
+
import { join } from 'node:path';
|
|
21
|
+
import { errorMessage, noopLogger, systemClock, systemTimers, } from '../core/index.js';
|
|
22
|
+
/** Environment variable holding the path of the check context JSON file. */
|
|
23
|
+
export const CHECK_CONTEXT_ENV = 'ADISPATCH_CHECK_CONTEXT_FILE';
|
|
24
|
+
/** Variables copied from the controller environment into every check process. */
|
|
25
|
+
export const MINIMAL_ENV_KEYS = ['PATH', 'HOME', 'LANG', 'TZ', 'USER', 'LOGNAME', 'TMPDIR'];
|
|
26
|
+
/** Default per-stream output limit in bytes. */
|
|
27
|
+
export const DEFAULT_MAX_CHECK_OUTPUT_BYTES = 16 * 1024;
|
|
28
|
+
/** Default grace period between SIGTERM and SIGKILL. */
|
|
29
|
+
export const DEFAULT_CHECK_KILL_GRACE_MS = 2000;
|
|
30
|
+
/** Build a {@link ShellCheckContext}. `sourceType` is the adapter type (e.g. `github`). */
|
|
31
|
+
export function buildCheckContext(kind, workflowId, item, sourceType) {
|
|
32
|
+
const ctx = { schema_version: 1, kind, workflow: { id: workflowId } };
|
|
33
|
+
if (item) {
|
|
34
|
+
ctx.source = {
|
|
35
|
+
id: item.sourceId,
|
|
36
|
+
type: sourceType ?? '',
|
|
37
|
+
item_id: item.itemId,
|
|
38
|
+
item_key: item.key,
|
|
39
|
+
url: item.url,
|
|
40
|
+
item_type: item.type,
|
|
41
|
+
...(item.createdAt !== undefined ? { created_at: item.createdAt } : {}),
|
|
42
|
+
attributes: { ...item.fields },
|
|
43
|
+
};
|
|
44
|
+
}
|
|
45
|
+
return ctx;
|
|
46
|
+
}
|
|
47
|
+
class OutputBuffer {
|
|
48
|
+
limit;
|
|
49
|
+
chunks = [];
|
|
50
|
+
size = 0;
|
|
51
|
+
truncated = false;
|
|
52
|
+
constructor(limit) {
|
|
53
|
+
this.limit = limit;
|
|
54
|
+
}
|
|
55
|
+
push(chunk) {
|
|
56
|
+
const room = this.limit - this.size;
|
|
57
|
+
if (room <= 0) {
|
|
58
|
+
if (chunk.length > 0)
|
|
59
|
+
this.truncated = true;
|
|
60
|
+
return;
|
|
61
|
+
}
|
|
62
|
+
const part = chunk.length > room ? chunk.subarray(0, room) : chunk;
|
|
63
|
+
if (part.length < chunk.length)
|
|
64
|
+
this.truncated = true;
|
|
65
|
+
this.chunks.push(part);
|
|
66
|
+
this.size += part.length;
|
|
67
|
+
}
|
|
68
|
+
text() {
|
|
69
|
+
return Buffer.concat(this.chunks).toString('utf8');
|
|
70
|
+
}
|
|
71
|
+
}
|
|
72
|
+
/** Runs shell checks; one instance per orchestrator (holds the workflow-condition cache). */
|
|
73
|
+
export class ShellCheckRunner {
|
|
74
|
+
clock;
|
|
75
|
+
timers;
|
|
76
|
+
logger;
|
|
77
|
+
hostEnv;
|
|
78
|
+
tempDir;
|
|
79
|
+
maxOutputBytes;
|
|
80
|
+
killGraceMs;
|
|
81
|
+
cache = new Map();
|
|
82
|
+
inflight = new Map();
|
|
83
|
+
constructor(options = {}) {
|
|
84
|
+
this.clock = options.clock ?? systemClock;
|
|
85
|
+
this.timers = options.timers ?? systemTimers;
|
|
86
|
+
this.logger = options.logger ?? noopLogger;
|
|
87
|
+
this.hostEnv = options.hostEnv ?? process.env;
|
|
88
|
+
this.tempDir = options.tempDir ?? tmpdir();
|
|
89
|
+
this.maxOutputBytes = options.maxOutputBytes ?? DEFAULT_MAX_CHECK_OUTPUT_BYTES;
|
|
90
|
+
this.killGraceMs = options.killGraceMs ?? DEFAULT_CHECK_KILL_GRACE_MS;
|
|
91
|
+
}
|
|
92
|
+
/** Environment for a check process (minimal env + explicit env + context file). */
|
|
93
|
+
buildEnv(spec, contextFile) {
|
|
94
|
+
const env = {};
|
|
95
|
+
for (const key of MINIMAL_ENV_KEYS) {
|
|
96
|
+
const v = this.hostEnv[key];
|
|
97
|
+
if (v !== undefined)
|
|
98
|
+
env[key] = v;
|
|
99
|
+
}
|
|
100
|
+
Object.assign(env, spec.env ?? {});
|
|
101
|
+
env[CHECK_CONTEXT_ENV] = contextFile;
|
|
102
|
+
return env;
|
|
103
|
+
}
|
|
104
|
+
/** Run a check without caching. Never throws. */
|
|
105
|
+
async run(spec, context, options = {}) {
|
|
106
|
+
const startedAt = this.clock.now();
|
|
107
|
+
const t = spec.timeoutMs;
|
|
108
|
+
if (typeof t !== 'number' || !Number.isFinite(t) || t <= 0) {
|
|
109
|
+
return this.failure(startedAt, `invalid timeout: ${String(t)}`);
|
|
110
|
+
}
|
|
111
|
+
let dir;
|
|
112
|
+
try {
|
|
113
|
+
dir = await mkdtemp(join(this.tempDir, 'orch-check-'));
|
|
114
|
+
const contextFile = join(dir, 'context.json');
|
|
115
|
+
await writeFile(contextFile, JSON.stringify(context ?? null), { mode: 0o600 });
|
|
116
|
+
return await this.spawnCheck(spec, this.buildEnv(spec, contextFile), spec.cwd ?? dir, startedAt, options.signal);
|
|
117
|
+
}
|
|
118
|
+
catch (err) {
|
|
119
|
+
return this.failure(startedAt, `check preparation failed: ${errorMessage(err)}`);
|
|
120
|
+
}
|
|
121
|
+
finally {
|
|
122
|
+
if (dir)
|
|
123
|
+
await rm(dir, { recursive: true, force: true }).catch(() => undefined);
|
|
124
|
+
}
|
|
125
|
+
}
|
|
126
|
+
/**
|
|
127
|
+
* Run a check with a TTL cache under `cacheKey` (e.g. `<workflowId>:condition:<index>`).
|
|
128
|
+
* Only definitive results (`true`/`false`) are cached; concurrent calls for
|
|
129
|
+
* the same key share one execution. `ttlMs <= 0` disables caching.
|
|
130
|
+
*/
|
|
131
|
+
async runCached(cacheKey, ttlMs, spec, context, options = {}) {
|
|
132
|
+
if (ttlMs <= 0)
|
|
133
|
+
return this.run(spec, context, options);
|
|
134
|
+
const now = this.clock.now().getTime();
|
|
135
|
+
const entry = this.cache.get(cacheKey);
|
|
136
|
+
if (entry && now - entry.storedAt < entry.ttlMs)
|
|
137
|
+
return { ...entry.result, cached: true };
|
|
138
|
+
if (entry)
|
|
139
|
+
this.cache.delete(cacheKey);
|
|
140
|
+
const running = this.inflight.get(cacheKey);
|
|
141
|
+
if (running)
|
|
142
|
+
return { ...(await running), cached: true };
|
|
143
|
+
const p = this.run(spec, context, options).then((result) => {
|
|
144
|
+
if (result.value !== 'unknown')
|
|
145
|
+
this.cache.set(cacheKey, { storedAt: this.clock.now().getTime(), ttlMs, result });
|
|
146
|
+
return result;
|
|
147
|
+
});
|
|
148
|
+
this.inflight.set(cacheKey, p);
|
|
149
|
+
try {
|
|
150
|
+
return await p;
|
|
151
|
+
}
|
|
152
|
+
finally {
|
|
153
|
+
this.inflight.delete(cacheKey);
|
|
154
|
+
}
|
|
155
|
+
}
|
|
156
|
+
/** Drop one cache entry, or all (e.g. after a config reload). */
|
|
157
|
+
invalidate(cacheKey) {
|
|
158
|
+
if (cacheKey === undefined)
|
|
159
|
+
this.cache.clear();
|
|
160
|
+
else
|
|
161
|
+
this.cache.delete(cacheKey);
|
|
162
|
+
}
|
|
163
|
+
failure(startedAt, error) {
|
|
164
|
+
return {
|
|
165
|
+
value: 'unknown',
|
|
166
|
+
exitCode: null,
|
|
167
|
+
signal: null,
|
|
168
|
+
timedOut: false,
|
|
169
|
+
error,
|
|
170
|
+
stdout: '',
|
|
171
|
+
stderr: '',
|
|
172
|
+
outputTruncated: false,
|
|
173
|
+
startedAt: startedAt.toISOString(),
|
|
174
|
+
durationMs: Math.max(0, this.clock.now().getTime() - startedAt.getTime()),
|
|
175
|
+
cached: false,
|
|
176
|
+
};
|
|
177
|
+
}
|
|
178
|
+
spawnCheck(spec, env, cwd, startedAt, signal) {
|
|
179
|
+
const [file, args] = spec.shell
|
|
180
|
+
? ['/bin/sh', ['-c', spec.command, 'sh', ...(spec.args ?? [])]]
|
|
181
|
+
: [spec.command, [...(spec.args ?? [])]];
|
|
182
|
+
const stdout = new OutputBuffer(this.maxOutputBytes);
|
|
183
|
+
const stderr = new OutputBuffer(this.maxOutputBytes);
|
|
184
|
+
return new Promise((resolve) => {
|
|
185
|
+
let settled = false;
|
|
186
|
+
let timedOut = false;
|
|
187
|
+
let aborted = false;
|
|
188
|
+
let spawnError;
|
|
189
|
+
const handles = [];
|
|
190
|
+
const child = spawn(file, args, { cwd, env, stdio: ['ignore', 'pipe', 'pipe'], detached: true });
|
|
191
|
+
child.stdout.on('data', (c) => stdout.push(c));
|
|
192
|
+
child.stderr.on('data', (c) => stderr.push(c));
|
|
193
|
+
const killGroup = (sig) => {
|
|
194
|
+
if (child.pid === undefined)
|
|
195
|
+
return;
|
|
196
|
+
try {
|
|
197
|
+
process.kill(-child.pid, sig);
|
|
198
|
+
}
|
|
199
|
+
catch {
|
|
200
|
+
try {
|
|
201
|
+
child.kill(sig);
|
|
202
|
+
}
|
|
203
|
+
catch {
|
|
204
|
+
/* already gone */
|
|
205
|
+
}
|
|
206
|
+
}
|
|
207
|
+
};
|
|
208
|
+
const finish = (exitCode, sig) => {
|
|
209
|
+
if (settled)
|
|
210
|
+
return;
|
|
211
|
+
settled = true;
|
|
212
|
+
for (const h of handles)
|
|
213
|
+
this.timers.clearTimeout(h);
|
|
214
|
+
signal?.removeEventListener('abort', onAbort);
|
|
215
|
+
// Make sure no stray process of the group survives (e.g. background children).
|
|
216
|
+
if (child.pid !== undefined) {
|
|
217
|
+
try {
|
|
218
|
+
process.kill(-child.pid, 'SIGKILL');
|
|
219
|
+
}
|
|
220
|
+
catch {
|
|
221
|
+
/* group already gone */
|
|
222
|
+
}
|
|
223
|
+
}
|
|
224
|
+
let value = 'unknown';
|
|
225
|
+
let error;
|
|
226
|
+
if (spawnError !== undefined)
|
|
227
|
+
error = `spawn failed: ${spawnError}`;
|
|
228
|
+
else if (timedOut)
|
|
229
|
+
error = `timed out after ${spec.timeoutMs}ms`;
|
|
230
|
+
else if (aborted)
|
|
231
|
+
error = 'aborted';
|
|
232
|
+
else if (sig !== null)
|
|
233
|
+
error = `terminated by signal ${sig}`;
|
|
234
|
+
else if (exitCode === 0)
|
|
235
|
+
value = true;
|
|
236
|
+
else if (exitCode === 1)
|
|
237
|
+
value = false;
|
|
238
|
+
else
|
|
239
|
+
error = `check error: exit code ${String(exitCode)}`;
|
|
240
|
+
if (error !== undefined)
|
|
241
|
+
this.logger.warn('shell check failed', { command: spec.command, error });
|
|
242
|
+
resolve({
|
|
243
|
+
value,
|
|
244
|
+
exitCode,
|
|
245
|
+
signal: sig,
|
|
246
|
+
timedOut,
|
|
247
|
+
...(error !== undefined ? { error } : {}),
|
|
248
|
+
stdout: stdout.text(),
|
|
249
|
+
stderr: stderr.text(),
|
|
250
|
+
outputTruncated: stdout.truncated || stderr.truncated,
|
|
251
|
+
startedAt: startedAt.toISOString(),
|
|
252
|
+
durationMs: Math.max(0, this.clock.now().getTime() - startedAt.getTime()),
|
|
253
|
+
cached: false,
|
|
254
|
+
});
|
|
255
|
+
};
|
|
256
|
+
const terminate = () => {
|
|
257
|
+
killGroup('SIGTERM');
|
|
258
|
+
handles.push(this.timers.setTimeout(() => {
|
|
259
|
+
killGroup('SIGKILL');
|
|
260
|
+
// Last resort if pipes are held open by an escaped process.
|
|
261
|
+
handles.push(this.timers.setTimeout(() => {
|
|
262
|
+
child.stdout.destroy();
|
|
263
|
+
child.stderr.destroy();
|
|
264
|
+
finish(child.exitCode, child.signalCode);
|
|
265
|
+
}, this.killGraceMs));
|
|
266
|
+
}, this.killGraceMs));
|
|
267
|
+
};
|
|
268
|
+
const onAbort = () => {
|
|
269
|
+
if (settled || timedOut)
|
|
270
|
+
return;
|
|
271
|
+
aborted = true;
|
|
272
|
+
terminate();
|
|
273
|
+
};
|
|
274
|
+
child.on('error', (err) => {
|
|
275
|
+
spawnError = err.message;
|
|
276
|
+
// 'close' may not follow a failed spawn.
|
|
277
|
+
if (child.pid === undefined)
|
|
278
|
+
finish(null, null);
|
|
279
|
+
});
|
|
280
|
+
child.on('close', (code, sig) => finish(code, sig));
|
|
281
|
+
child.on('exit', (code, sig) => {
|
|
282
|
+
// Pipes may be held open by background children; do not wait for them forever.
|
|
283
|
+
handles.push(this.timers.setTimeout(() => {
|
|
284
|
+
child.stdout.destroy();
|
|
285
|
+
child.stderr.destroy();
|
|
286
|
+
finish(code, sig);
|
|
287
|
+
}, this.killGraceMs));
|
|
288
|
+
});
|
|
289
|
+
handles.push(this.timers.setTimeout(() => {
|
|
290
|
+
if (settled || aborted)
|
|
291
|
+
return;
|
|
292
|
+
timedOut = true;
|
|
293
|
+
terminate();
|
|
294
|
+
}, spec.timeoutMs));
|
|
295
|
+
if (signal) {
|
|
296
|
+
if (signal.aborted)
|
|
297
|
+
onAbort();
|
|
298
|
+
else
|
|
299
|
+
signal.addEventListener('abort', onAbort, { once: true });
|
|
300
|
+
}
|
|
301
|
+
});
|
|
302
|
+
}
|
|
303
|
+
}
|
|
304
|
+
//# sourceMappingURL=shell-check.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"shell-check.js","sourceRoot":"","sources":["../../src/filters/shell-check.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
import { type AccessToken, type Clock, type CredentialProvider, type FetchLike, type IdentityDescription, type IdentityRef, type Logger, type SecretRedactor, type Timers } from '../core/index.js';
|
|
2
|
+
import { GitHubHttpClient } from '../sources/index.js';
|
|
3
|
+
/** Identity entry of type `github_app` (normalised, camelCase). */
|
|
4
|
+
export interface GitHubAppIdentityConfig {
|
|
5
|
+
appId: string | number;
|
|
6
|
+
installationId: string | number;
|
|
7
|
+
/** Name of the environment variable holding the PEM private key. */
|
|
8
|
+
privateKeyEnv: string;
|
|
9
|
+
}
|
|
10
|
+
/** Dependencies of {@link GitHubAppCredentialProvider}. */
|
|
11
|
+
export interface GitHubAppCredentialProviderDeps {
|
|
12
|
+
clock: Clock;
|
|
13
|
+
fetch?: FetchLike;
|
|
14
|
+
timers?: Timers;
|
|
15
|
+
logger?: Logger;
|
|
16
|
+
/** Environment to read private keys from. Default `process.env`. */
|
|
17
|
+
env?: Readonly<Record<string, string | undefined>>;
|
|
18
|
+
/** Registry that receives private keys and issued tokens for redaction. */
|
|
19
|
+
redactor?: SecretRedactor;
|
|
20
|
+
/** API base URL (default `https://api.github.com`). */
|
|
21
|
+
apiBaseUrl?: string;
|
|
22
|
+
/** Pre-built HTTP client (overrides fetch/timers/apiBaseUrl). */
|
|
23
|
+
http?: GitHubHttpClient;
|
|
24
|
+
/** Refresh a cached token this long before it expires. Default 5 min. */
|
|
25
|
+
refreshMarginMs?: number;
|
|
26
|
+
}
|
|
27
|
+
/** {@link CredentialProvider} for identities of type `github_app`. */
|
|
28
|
+
export declare class GitHubAppCredentialProvider implements CredentialProvider {
|
|
29
|
+
private readonly identities;
|
|
30
|
+
private readonly clock;
|
|
31
|
+
private readonly logger;
|
|
32
|
+
private readonly env;
|
|
33
|
+
private readonly redactor;
|
|
34
|
+
private readonly http;
|
|
35
|
+
private readonly refreshMarginMs;
|
|
36
|
+
private readonly keys;
|
|
37
|
+
private readonly cache;
|
|
38
|
+
private readonly inflight;
|
|
39
|
+
/** Bumped on invalidate so that an in-flight exchange started earlier does not repopulate the cache. */
|
|
40
|
+
private readonly generation;
|
|
41
|
+
/** Issued tokens still registered with the redactor (removed once expired). */
|
|
42
|
+
private issued;
|
|
43
|
+
constructor(identities: Readonly<Record<string, GitHubAppIdentityConfig>>, deps: GitHubAppCredentialProviderDeps);
|
|
44
|
+
/** IDs of the configured identities. */
|
|
45
|
+
identityIds(): string[];
|
|
46
|
+
getToken(identity: IdentityRef, options?: {
|
|
47
|
+
signal?: AbortSignal;
|
|
48
|
+
}): Promise<AccessToken>;
|
|
49
|
+
describe(identity: IdentityRef): IdentityDescription | undefined;
|
|
50
|
+
invalidate(identity: IdentityRef): void;
|
|
51
|
+
private privateKey;
|
|
52
|
+
private exchange;
|
|
53
|
+
/** Register a new token for redaction and forget tokens that have expired (bounded registry). */
|
|
54
|
+
private trackForRedaction;
|
|
55
|
+
}
|
|
@@ -0,0 +1,160 @@
|
|
|
1
|
+
import { SourceError, noopLogger, } from '../core/index.js';
|
|
2
|
+
import { GitHubHttpClient } from '../sources/index.js';
|
|
3
|
+
import { createAppJwt, normalizePrivateKeyPem, parsePrivateKey } from './jwt.js';
|
|
4
|
+
/** {@link CredentialProvider} for identities of type `github_app`. */
|
|
5
|
+
export class GitHubAppCredentialProvider {
|
|
6
|
+
identities;
|
|
7
|
+
clock;
|
|
8
|
+
logger;
|
|
9
|
+
env;
|
|
10
|
+
redactor;
|
|
11
|
+
http;
|
|
12
|
+
refreshMarginMs;
|
|
13
|
+
keys = new Map();
|
|
14
|
+
cache = new Map();
|
|
15
|
+
inflight = new Map();
|
|
16
|
+
/** Bumped on invalidate so that an in-flight exchange started earlier does not repopulate the cache. */
|
|
17
|
+
generation = new Map();
|
|
18
|
+
/** Issued tokens still registered with the redactor (removed once expired). */
|
|
19
|
+
issued = [];
|
|
20
|
+
constructor(identities, deps) {
|
|
21
|
+
this.identities = new Map(Object.entries(identities));
|
|
22
|
+
this.clock = deps.clock;
|
|
23
|
+
this.logger = (deps.logger ?? noopLogger).child({ component: 'identities' });
|
|
24
|
+
this.env = deps.env ?? process.env;
|
|
25
|
+
this.redactor = deps.redactor;
|
|
26
|
+
this.refreshMarginMs = deps.refreshMarginMs ?? 5 * 60_000;
|
|
27
|
+
this.http =
|
|
28
|
+
deps.http ??
|
|
29
|
+
new GitHubHttpClient({
|
|
30
|
+
clock: deps.clock,
|
|
31
|
+
logger: this.logger,
|
|
32
|
+
...(deps.fetch ? { fetch: deps.fetch } : {}),
|
|
33
|
+
...(deps.timers ? { timers: deps.timers } : {}),
|
|
34
|
+
...(deps.apiBaseUrl ? { baseUrl: deps.apiBaseUrl } : {}),
|
|
35
|
+
});
|
|
36
|
+
}
|
|
37
|
+
/** IDs of the configured identities. */
|
|
38
|
+
identityIds() {
|
|
39
|
+
return [...this.identities.keys()];
|
|
40
|
+
}
|
|
41
|
+
async getToken(identity, options = {}) {
|
|
42
|
+
const cached = this.cache.get(identity);
|
|
43
|
+
if (cached && cached.expiresAt.getTime() - this.refreshMarginMs > this.clock.now().getTime())
|
|
44
|
+
return cached;
|
|
45
|
+
let shared = this.inflight.get(identity);
|
|
46
|
+
if (!shared) {
|
|
47
|
+
const generation = this.generation.get(identity) ?? 0;
|
|
48
|
+
// The shared exchange is independent of any caller's signal: one caller
|
|
49
|
+
// aborting must not fail the exchange for the others.
|
|
50
|
+
const promise = this.exchange(identity, undefined)
|
|
51
|
+
.then((token) => {
|
|
52
|
+
if ((this.generation.get(identity) ?? 0) === generation)
|
|
53
|
+
this.cache.set(identity, token);
|
|
54
|
+
return token;
|
|
55
|
+
})
|
|
56
|
+
.finally(() => {
|
|
57
|
+
if (this.inflight.get(identity) === promise)
|
|
58
|
+
this.inflight.delete(identity);
|
|
59
|
+
});
|
|
60
|
+
this.inflight.set(identity, promise);
|
|
61
|
+
shared = promise;
|
|
62
|
+
}
|
|
63
|
+
return raceWithSignal(shared, options.signal);
|
|
64
|
+
}
|
|
65
|
+
describe(identity) {
|
|
66
|
+
const config = this.identities.get(identity);
|
|
67
|
+
return config ? { appId: String(config.appId) } : undefined;
|
|
68
|
+
}
|
|
69
|
+
invalidate(identity) {
|
|
70
|
+
this.cache.delete(identity);
|
|
71
|
+
this.inflight.delete(identity);
|
|
72
|
+
this.generation.set(identity, (this.generation.get(identity) ?? 0) + 1);
|
|
73
|
+
}
|
|
74
|
+
privateKey(identity, config) {
|
|
75
|
+
const cached = this.keys.get(identity);
|
|
76
|
+
if (cached)
|
|
77
|
+
return cached;
|
|
78
|
+
const raw = this.env[config.privateKeyEnv];
|
|
79
|
+
if (!raw || raw.trim() === '') {
|
|
80
|
+
throw new SourceError('auth', `Private key for identity "${identity}" missing: environment variable ${config.privateKeyEnv} is not set`, { retryable: false });
|
|
81
|
+
}
|
|
82
|
+
// Register every form the key may show up in (raw env value, `\n`-escaped and normalised PEM).
|
|
83
|
+
const normalized = normalizePrivateKeyPem(raw);
|
|
84
|
+
for (const form of [raw, raw.trim(), normalized, normalized.trim()])
|
|
85
|
+
this.redactor?.add(form);
|
|
86
|
+
const key = parsePrivateKey(raw, `identity "${identity}"`);
|
|
87
|
+
this.keys.set(identity, key);
|
|
88
|
+
return key;
|
|
89
|
+
}
|
|
90
|
+
async exchange(identity, signal) {
|
|
91
|
+
const config = this.identities.get(identity);
|
|
92
|
+
if (!config)
|
|
93
|
+
throw new SourceError('auth', `Unknown identity "${identity}"`, { retryable: false });
|
|
94
|
+
const jwt = createAppJwt(config.appId, this.privateKey(identity, config), this.clock.now());
|
|
95
|
+
this.redactor?.add(jwt);
|
|
96
|
+
let data;
|
|
97
|
+
try {
|
|
98
|
+
const res = await this.http.request('POST', `/app/installations/${encodeURIComponent(String(config.installationId))}/access_tokens`,
|
|
99
|
+
// Token creation has no side effects worth reconciling: safe to retry.
|
|
100
|
+
{ token: jwt, idempotent: true, ...(signal ? { signal } : {}) });
|
|
101
|
+
data = res.data ?? {};
|
|
102
|
+
}
|
|
103
|
+
catch (err) {
|
|
104
|
+
if (err instanceof SourceError) {
|
|
105
|
+
// Client errors (bad JWT, unknown installation, revoked app) are auth failures;
|
|
106
|
+
// transient/rate-limit errors keep their kind so callers can retry.
|
|
107
|
+
if (err.kind === 'transient' || err.kind === 'rate_limited')
|
|
108
|
+
throw err;
|
|
109
|
+
throw new SourceError('auth', `Could not obtain installation token for identity "${identity}": ${err.message}`, {
|
|
110
|
+
retryable: false,
|
|
111
|
+
...(err.status !== undefined ? { status: err.status } : {}),
|
|
112
|
+
});
|
|
113
|
+
}
|
|
114
|
+
throw err;
|
|
115
|
+
}
|
|
116
|
+
finally {
|
|
117
|
+
this.redactor?.remove(jwt);
|
|
118
|
+
}
|
|
119
|
+
if (typeof data.token !== 'string' || typeof data.expires_at !== 'string' || Number.isNaN(Date.parse(data.expires_at))) {
|
|
120
|
+
throw new SourceError('auth', `Invalid installation token response for identity "${identity}"`, { retryable: false });
|
|
121
|
+
}
|
|
122
|
+
const token = { token: data.token, expiresAt: new Date(data.expires_at) };
|
|
123
|
+
this.trackForRedaction(token);
|
|
124
|
+
this.logger.info('Obtained GitHub installation token', { identity, expiresAt: token.expiresAt.toISOString() });
|
|
125
|
+
return token;
|
|
126
|
+
}
|
|
127
|
+
/** Register a new token for redaction and forget tokens that have expired (bounded registry). */
|
|
128
|
+
trackForRedaction(token) {
|
|
129
|
+
if (!this.redactor)
|
|
130
|
+
return;
|
|
131
|
+
const now = this.clock.now().getTime();
|
|
132
|
+
this.issued = this.issued.filter((t) => {
|
|
133
|
+
if (t.expiresAt.getTime() > now)
|
|
134
|
+
return true;
|
|
135
|
+
this.redactor?.remove(t.token);
|
|
136
|
+
return false;
|
|
137
|
+
});
|
|
138
|
+
this.redactor.add(token.token);
|
|
139
|
+
this.issued.push(token);
|
|
140
|
+
}
|
|
141
|
+
}
|
|
142
|
+
/** Resolve/reject with `promise`, but reject early with the signal's reason when `signal` aborts. */
|
|
143
|
+
function raceWithSignal(promise, signal) {
|
|
144
|
+
if (!signal)
|
|
145
|
+
return promise;
|
|
146
|
+
if (signal.aborted)
|
|
147
|
+
return Promise.reject(signal.reason ?? new DOMException('aborted', 'AbortError'));
|
|
148
|
+
return new Promise((resolve, reject) => {
|
|
149
|
+
const onAbort = () => reject(signal.reason ?? new DOMException('aborted', 'AbortError'));
|
|
150
|
+
signal.addEventListener('abort', onAbort, { once: true });
|
|
151
|
+
promise.then((value) => {
|
|
152
|
+
signal.removeEventListener('abort', onAbort);
|
|
153
|
+
resolve(value);
|
|
154
|
+
}, (err) => {
|
|
155
|
+
signal.removeEventListener('abort', onAbort);
|
|
156
|
+
reject(err);
|
|
157
|
+
});
|
|
158
|
+
});
|
|
159
|
+
}
|
|
160
|
+
//# sourceMappingURL=github-app.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"github-app.js","sourceRoot":"","sources":["../../src/identities/github-app.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/identities/index.ts"],"names":[],"mappings":"AAAA;;;GAGG;AACH,cAAc,iBAAiB,CAAC;AAChC,cAAc,UAAU,CAAC"}
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* GitHub App JWT (RS256) creation with `node:crypto` (Spec §5.3).
|
|
3
|
+
*/
|
|
4
|
+
import { type KeyObject } from 'node:crypto';
|
|
5
|
+
/** Seconds subtracted from `iat` to tolerate clock drift (GitHub recommendation). */
|
|
6
|
+
export declare const JWT_IAT_SKEW_SECONDS = 60;
|
|
7
|
+
/** JWT lifetime counted from the real "now"; GitHub allows at most 10 minutes. */
|
|
8
|
+
export declare const JWT_LIFETIME_SECONDS: number;
|
|
9
|
+
/**
|
|
10
|
+
* Normalise a PEM private key from an environment variable: accepts real
|
|
11
|
+
* newlines, literal `\n` escapes (common in `.env` files / systemd units),
|
|
12
|
+
* CRLF and surrounding quotes/whitespace.
|
|
13
|
+
*/
|
|
14
|
+
export declare function normalizePrivateKeyPem(raw: string): string;
|
|
15
|
+
/**
|
|
16
|
+
* Parse a PEM private key. Throws `SourceError('auth')` with a message that
|
|
17
|
+
* never contains key material.
|
|
18
|
+
*/
|
|
19
|
+
export declare function parsePrivateKey(raw: string, label: string): KeyObject;
|
|
20
|
+
/**
|
|
21
|
+
* Create a GitHub App JWT: header `{alg: RS256, typ: JWT}`, payload
|
|
22
|
+
* `{iat: now-60s, exp: now+9min, iss: appId}`.
|
|
23
|
+
*/
|
|
24
|
+
export declare function createAppJwt(appId: string | number, privateKey: KeyObject, now: Date): string;
|
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* GitHub App JWT (RS256) creation with `node:crypto` (Spec §5.3).
|
|
3
|
+
*/
|
|
4
|
+
import { createPrivateKey, sign } from 'node:crypto';
|
|
5
|
+
import { SourceError } from '../core/index.js';
|
|
6
|
+
/** Seconds subtracted from `iat` to tolerate clock drift (GitHub recommendation). */
|
|
7
|
+
export const JWT_IAT_SKEW_SECONDS = 60;
|
|
8
|
+
/** JWT lifetime counted from the real "now"; GitHub allows at most 10 minutes. */
|
|
9
|
+
export const JWT_LIFETIME_SECONDS = 9 * 60;
|
|
10
|
+
/**
|
|
11
|
+
* Normalise a PEM private key from an environment variable: accepts real
|
|
12
|
+
* newlines, literal `\n` escapes (common in `.env` files / systemd units),
|
|
13
|
+
* CRLF and surrounding quotes/whitespace.
|
|
14
|
+
*/
|
|
15
|
+
export function normalizePrivateKeyPem(raw) {
|
|
16
|
+
let pem = raw.trim();
|
|
17
|
+
if ((pem.startsWith('"') && pem.endsWith('"')) || (pem.startsWith("'") && pem.endsWith("'"))) {
|
|
18
|
+
pem = pem.slice(1, -1).trim();
|
|
19
|
+
}
|
|
20
|
+
return `${pem.replace(/\\r\\n|\\n/g, '\n').replace(/\r\n/g, '\n').trim()}\n`;
|
|
21
|
+
}
|
|
22
|
+
/**
|
|
23
|
+
* Parse a PEM private key. Throws `SourceError('auth')` with a message that
|
|
24
|
+
* never contains key material.
|
|
25
|
+
*/
|
|
26
|
+
export function parsePrivateKey(raw, label) {
|
|
27
|
+
try {
|
|
28
|
+
const key = createPrivateKey({ key: normalizePrivateKeyPem(raw), format: 'pem' });
|
|
29
|
+
if (key.asymmetricKeyType !== 'rsa')
|
|
30
|
+
throw new Error('not an RSA key');
|
|
31
|
+
return key;
|
|
32
|
+
}
|
|
33
|
+
catch {
|
|
34
|
+
throw new SourceError('auth', `Private key for ${label} is not a valid RSA PEM key`, { retryable: false });
|
|
35
|
+
}
|
|
36
|
+
}
|
|
37
|
+
function base64url(input) {
|
|
38
|
+
return Buffer.from(input).toString('base64url');
|
|
39
|
+
}
|
|
40
|
+
/**
|
|
41
|
+
* Create a GitHub App JWT: header `{alg: RS256, typ: JWT}`, payload
|
|
42
|
+
* `{iat: now-60s, exp: now+9min, iss: appId}`.
|
|
43
|
+
*/
|
|
44
|
+
export function createAppJwt(appId, privateKey, now) {
|
|
45
|
+
const nowSeconds = Math.floor(now.getTime() / 1000);
|
|
46
|
+
const header = { alg: 'RS256', typ: 'JWT' };
|
|
47
|
+
const payload = {
|
|
48
|
+
iat: nowSeconds - JWT_IAT_SKEW_SECONDS,
|
|
49
|
+
exp: nowSeconds + JWT_LIFETIME_SECONDS,
|
|
50
|
+
iss: String(appId),
|
|
51
|
+
};
|
|
52
|
+
const signingInput = `${base64url(JSON.stringify(header))}.${base64url(JSON.stringify(payload))}`;
|
|
53
|
+
const signature = sign('RSA-SHA256', Buffer.from(signingInput), privateKey);
|
|
54
|
+
return `${signingInput}.${base64url(signature)}`;
|
|
55
|
+
}
|
|
56
|
+
//# sourceMappingURL=jwt.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"jwt.js","sourceRoot":"","sources":["../../src/identities/jwt.ts"],"names":[],"mappings":"AAAA;;GAEG;AACH,OAAO,EAAE,gBAAgB,EAAE,IAAI,EAAkB,MAAM,aAAa,CAAC;AACrE,OAAO,EAAE,WAAW,EAAE,MAAM,kBAAkB,CAAC;AAE/C,qFAAqF;AACrF,MAAM,CAAC,MAAM,oBAAoB,GAAG,EAAE,CAAC;AAEvC,kFAAkF;AAClF,MAAM,CAAC,MAAM,oBAAoB,GAAG,CAAC,GAAG,EAAE,CAAC;AAE3C;;;;GAIG;AACH,MAAM,UAAU,sBAAsB,CAAC,GAAW;IAChD,IAAI,GAAG,GAAG,GAAG,CAAC,IAAI,EAAE,CAAC;IACrB,IAAI,CAAC,GAAG,CAAC,UAAU,CAAC,GAAG,CAAC,IAAI,GAAG,CAAC,QAAQ,CAAC,GAAG,CAAC,CAAC,IAAI,CAAC,GAAG,CAAC,UAAU,CAAC,GAAG,CAAC,IAAI,GAAG,CAAC,QAAQ,CAAC,GAAG,CAAC,CAAC,EAAE,CAAC;QAC7F,GAAG,GAAG,GAAG,CAAC,KAAK,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC,IAAI,EAAE,CAAC;IAChC,CAAC;IACD,OAAO,GAAG,GAAG,CAAC,OAAO,CAAC,aAAa,EAAE,IAAI,CAAC,CAAC,OAAO,CAAC,OAAO,EAAE,IAAI,CAAC,CAAC,IAAI,EAAE,IAAI,CAAC;AAC/E,CAAC;AAED;;;GAGG;AACH,MAAM,UAAU,eAAe,CAAC,GAAW,EAAE,KAAa;IACxD,IAAI,CAAC;QACH,MAAM,GAAG,GAAG,gBAAgB,CAAC,EAAE,GAAG,EAAE,sBAAsB,CAAC,GAAG,CAAC,EAAE,MAAM,EAAE,KAAK,EAAE,CAAC,CAAC;QAClF,IAAI,GAAG,CAAC,iBAAiB,KAAK,KAAK;YAAE,MAAM,IAAI,KAAK,CAAC,gBAAgB,CAAC,CAAC;QACvE,OAAO,GAAG,CAAC;IACb,CAAC;IAAC,MAAM,CAAC;QACP,MAAM,IAAI,WAAW,CAAC,MAAM,EAAE,mBAAmB,KAAK,6BAA6B,EAAE,EAAE,SAAS,EAAE,KAAK,EAAE,CAAC,CAAC;IAC7G,CAAC;AACH,CAAC;AAED,SAAS,SAAS,CAAC,KAAsB;IACvC,OAAO,MAAM,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,QAAQ,CAAC,WAAW,CAAC,CAAC;AAClD,CAAC;AAED;;;GAGG;AACH,MAAM,UAAU,YAAY,CAAC,KAAsB,EAAE,UAAqB,EAAE,GAAS;IACnF,MAAM,UAAU,GAAG,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,OAAO,EAAE,GAAG,IAAI,CAAC,CAAC;IACpD,MAAM,MAAM,GAAG,EAAE,GAAG,EAAE,OAAO,EAAE,GAAG,EAAE,KAAK,EAAE,CAAC;IAC5C,MAAM,OAAO,GAAG;QACd,GAAG,EAAE,UAAU,GAAG,oBAAoB;QACtC,GAAG,EAAE,UAAU,GAAG,oBAAoB;QACtC,GAAG,EAAE,MAAM,CAAC,KAAK,CAAC;KACnB,CAAC;IACF,MAAM,YAAY,GAAG,GAAG,SAAS,CAAC,IAAI,CAAC,SAAS,CAAC,MAAM,CAAC,CAAC,IAAI,SAAS,CAAC,IAAI,CAAC,SAAS,CAAC,OAAO,CAAC,CAAC,EAAE,CAAC;IAClG,MAAM,SAAS,GAAG,IAAI,CAAC,YAAY,EAAE,MAAM,CAAC,IAAI,CAAC,YAAY,CAAC,EAAE,UAAU,CAAC,CAAC;IAC5E,OAAO,GAAG,YAAY,IAAI,SAAS,CAAC,SAAS,CAAC,EAAE,CAAC;AACnD,CAAC"}
|