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,336 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Source adapter `github` (Spec §5.2, §6, §10): issues and pull requests of
|
|
3
|
+
* one repository, native "blocked by" dependencies, labels and comments.
|
|
4
|
+
*/
|
|
5
|
+
import { SourceError, noopLogger, sourceItemKey, systemTimers, } from '../../core/index.js';
|
|
6
|
+
import { DEPENDENCY_FIELDS, GITHUB_FIELD_DEFINITIONS } from './fields.js';
|
|
7
|
+
import { GitHubHttpClient } from './http.js';
|
|
8
|
+
import { pushdownQuery } from './pushdown.js';
|
|
9
|
+
import { ITEM_ID_PATTERN, parseGitHubItemRef } from './refs.js';
|
|
10
|
+
/** Adapter type name. */
|
|
11
|
+
export const GITHUB_SOURCE_TYPE = 'github';
|
|
12
|
+
/** Marker pattern accepted by {@link GitHubSourceAdapter.postComment} (see `commentMarker`). */
|
|
13
|
+
const MARKER_PATTERN = /^[A-Za-z0-9_.:-]+$/;
|
|
14
|
+
/** {@link SourceAdapter} for one GitHub repository. */
|
|
15
|
+
export class GitHubSourceAdapter {
|
|
16
|
+
type = GITHUB_SOURCE_TYPE;
|
|
17
|
+
sourceId;
|
|
18
|
+
repository;
|
|
19
|
+
config;
|
|
20
|
+
http;
|
|
21
|
+
credentials;
|
|
22
|
+
logger;
|
|
23
|
+
repoPath;
|
|
24
|
+
constructor(sourceId, config, deps, options = {}) {
|
|
25
|
+
if (!config.owner || !config.repository)
|
|
26
|
+
throw new SourceError('invalid', `Source "${sourceId}": owner and repository are required`);
|
|
27
|
+
this.sourceId = sourceId;
|
|
28
|
+
this.config = config;
|
|
29
|
+
this.repository = `${config.owner}/${config.repository}`;
|
|
30
|
+
this.repoPath = `/repos/${encodeURIComponent(config.owner)}/${encodeURIComponent(config.repository)}`;
|
|
31
|
+
this.credentials = deps.credentials;
|
|
32
|
+
this.logger = (deps.logger ?? noopLogger).child({ component: 'source', sourceId });
|
|
33
|
+
this.http =
|
|
34
|
+
options.http ??
|
|
35
|
+
new GitHubHttpClient({
|
|
36
|
+
...options.httpOptions,
|
|
37
|
+
clock: deps.clock,
|
|
38
|
+
timers: options.timers ?? systemTimers,
|
|
39
|
+
logger: this.logger,
|
|
40
|
+
...(deps.fetch ? { fetch: deps.fetch } : {}),
|
|
41
|
+
...(config.apiBaseUrl ? { baseUrl: config.apiBaseUrl } : {}),
|
|
42
|
+
});
|
|
43
|
+
}
|
|
44
|
+
fieldDefinitions() {
|
|
45
|
+
return GITHUB_FIELD_DEFINITIONS;
|
|
46
|
+
}
|
|
47
|
+
async listCandidates(options = {}) {
|
|
48
|
+
const query = pushdownQuery(options.filter);
|
|
49
|
+
const issues = await this.withToken(this.config.identity, options.signal, (token) => this.http.paginate(`${this.repoPath}/issues`, {
|
|
50
|
+
token,
|
|
51
|
+
query: {
|
|
52
|
+
state: query.state,
|
|
53
|
+
...(query.labels.length > 0 ? { labels: query.labels.join(',') } : {}),
|
|
54
|
+
sort: 'created',
|
|
55
|
+
direction: 'asc',
|
|
56
|
+
},
|
|
57
|
+
...(options.signal ? { signal: options.signal } : {}),
|
|
58
|
+
}));
|
|
59
|
+
return issues.map((issue) => this.toItem(issue));
|
|
60
|
+
}
|
|
61
|
+
async getItem(itemId, options = {}) {
|
|
62
|
+
const issue = await this.fetchIssue(itemId, this.config.identity, options.signal);
|
|
63
|
+
return issue ? this.toItem(issue) : null;
|
|
64
|
+
}
|
|
65
|
+
parseItemRef(ref) {
|
|
66
|
+
return parseGitHubItemRef(ref, this.config.owner, this.config.repository, this.config.webBaseUrl);
|
|
67
|
+
}
|
|
68
|
+
async resolveFields(item, fields, options = {}) {
|
|
69
|
+
const out = {};
|
|
70
|
+
const wantsDependencies = fields.some((f) => DEPENDENCY_FIELDS.includes(f));
|
|
71
|
+
const dependencies = wantsDependencies ? await this.resolveDependencies(item, options.signal) : undefined;
|
|
72
|
+
for (const name of fields) {
|
|
73
|
+
if (dependencies && name in dependencies) {
|
|
74
|
+
out[name] = dependencies[name];
|
|
75
|
+
}
|
|
76
|
+
else if (Object.hasOwn(item.fields, name)) {
|
|
77
|
+
out[name] = { known: true, value: item.fields[name] };
|
|
78
|
+
}
|
|
79
|
+
else {
|
|
80
|
+
out[name] = { known: false, reason: `unknown field "${name}" for source type github` };
|
|
81
|
+
}
|
|
82
|
+
}
|
|
83
|
+
return out;
|
|
84
|
+
}
|
|
85
|
+
async applyUpdate(item, update, identity) {
|
|
86
|
+
this.assertOwnItem(item);
|
|
87
|
+
const add = uniqueCaseInsensitive(update.labels?.add ?? []);
|
|
88
|
+
const addLower = new Set(add.map((l) => l.toLowerCase()));
|
|
89
|
+
// A label listed in both add and remove is added (remove ignored).
|
|
90
|
+
const remove = uniqueCaseInsensitive(update.labels?.remove ?? []).filter((l) => !addLower.has(l.toLowerCase()));
|
|
91
|
+
if (add.length === 0 && remove.length === 0)
|
|
92
|
+
return { changed: false };
|
|
93
|
+
// Re-read the item first so manual changes since the snapshot are respected (Spec §10).
|
|
94
|
+
const fresh = await this.fetchIssue(item.itemId, identity);
|
|
95
|
+
if (!fresh)
|
|
96
|
+
throw new SourceError('not_found', `Item ${this.repository}#${item.itemId} not found`, { retryable: false });
|
|
97
|
+
const current = labelNames(fresh);
|
|
98
|
+
const currentByLower = new Map(current.map((l) => [l.toLowerCase(), l]));
|
|
99
|
+
const toAdd = add.filter((l) => !currentByLower.has(l.toLowerCase()));
|
|
100
|
+
const toRemove = remove.map((l) => currentByLower.get(l.toLowerCase())).filter((l) => l !== undefined);
|
|
101
|
+
const issuePath = `${this.repoPath}/issues/${item.itemId}`;
|
|
102
|
+
if (toAdd.length > 0) {
|
|
103
|
+
await this.withToken(identity, undefined, (token) =>
|
|
104
|
+
// Adding labels is idempotent on GitHub's side: repeating is safe.
|
|
105
|
+
this.http.request('POST', `${issuePath}/labels`, { token, body: { labels: toAdd }, idempotent: true }));
|
|
106
|
+
}
|
|
107
|
+
const removed = [];
|
|
108
|
+
for (const label of toRemove) {
|
|
109
|
+
try {
|
|
110
|
+
await this.withToken(identity, undefined, (token) => this.http.request('DELETE', `${issuePath}/labels/${encodeURIComponent(label)}`, { token, idempotent: true }));
|
|
111
|
+
removed.push(label);
|
|
112
|
+
}
|
|
113
|
+
catch (err) {
|
|
114
|
+
// Already removed concurrently: desired state reached.
|
|
115
|
+
if (err instanceof SourceError && err.kind === 'not_found')
|
|
116
|
+
continue;
|
|
117
|
+
throw err;
|
|
118
|
+
}
|
|
119
|
+
}
|
|
120
|
+
const changed = toAdd.length > 0 || removed.length > 0;
|
|
121
|
+
this.logger.info('Applied label update', { item: item.key, labelsAdded: toAdd, labelsRemoved: removed });
|
|
122
|
+
return {
|
|
123
|
+
changed,
|
|
124
|
+
...(changed ? { applied: { labelsAdded: toAdd, labelsRemoved: removed } } : {}),
|
|
125
|
+
};
|
|
126
|
+
}
|
|
127
|
+
async postComment(item, body, marker, identity) {
|
|
128
|
+
this.assertOwnItem(item);
|
|
129
|
+
const markerLine = renderMarker(marker);
|
|
130
|
+
const fullBody = `${body.replace(/\s+$/, '')}\n\n${markerLine}`;
|
|
131
|
+
const res = await this.withToken(identity, undefined, (token) => this.http.request('POST', `${this.repoPath}/issues/${item.itemId}/comments`, {
|
|
132
|
+
token,
|
|
133
|
+
body: { body: fullBody },
|
|
134
|
+
}));
|
|
135
|
+
const id = res.data?.id;
|
|
136
|
+
if ((typeof id !== 'number' && typeof id !== 'string') || String(id) === '') {
|
|
137
|
+
// The comment may exist although the response is unusable: reconcile via marker.
|
|
138
|
+
throw new SourceError('transient', `Comment on ${item.key} returned no comment id; outcome unknown`, {
|
|
139
|
+
status: res.status,
|
|
140
|
+
outcomeUnknown: true,
|
|
141
|
+
});
|
|
142
|
+
}
|
|
143
|
+
return toCommentRef(res.data);
|
|
144
|
+
}
|
|
145
|
+
async findCommentByMarker(item, marker, identity) {
|
|
146
|
+
this.assertOwnItem(item);
|
|
147
|
+
const pattern = markerPattern(marker);
|
|
148
|
+
const comments = await this.withToken(identity, undefined, (token) => this.http.paginate(`${this.repoPath}/issues/${item.itemId}/comments`, { token }));
|
|
149
|
+
const isOwn = this.authorPredicate(identity);
|
|
150
|
+
const found = comments.find((c) => typeof c.body === 'string' && pattern.test(c.body) && isOwn(c));
|
|
151
|
+
return found ? toCommentRef(found) : null;
|
|
152
|
+
}
|
|
153
|
+
/**
|
|
154
|
+
* Only comments written by the identity's own app count as carrying a
|
|
155
|
+
* marker; otherwise anybody could suppress an orchestrator comment by
|
|
156
|
+
* posting the marker. With a known app ID (CredentialProvider.describe) the
|
|
157
|
+
* comment must have `performed_via_github_app.id === appId`; without one,
|
|
158
|
+
* at least a bot author (`user.type === 'Bot'`) is required.
|
|
159
|
+
*/
|
|
160
|
+
authorPredicate(identity) {
|
|
161
|
+
const appId = this.credentials.describe?.(identity)?.appId;
|
|
162
|
+
if (appId !== undefined) {
|
|
163
|
+
return (c) => c.performed_via_github_app?.id !== undefined && String(c.performed_via_github_app.id) === appId;
|
|
164
|
+
}
|
|
165
|
+
return (c) => c.user?.type === 'Bot';
|
|
166
|
+
}
|
|
167
|
+
// -------------------------------------------------------------------------
|
|
168
|
+
async resolveDependencies(item, signal) {
|
|
169
|
+
this.assertOwnItem(item);
|
|
170
|
+
let issue;
|
|
171
|
+
let blockers;
|
|
172
|
+
try {
|
|
173
|
+
// Fresh issue (for the authoritative blocker count) and the visible blocker list.
|
|
174
|
+
[issue, blockers] = await Promise.all([
|
|
175
|
+
this.fetchIssue(item.itemId, this.config.identity, signal),
|
|
176
|
+
this.withToken(this.config.identity, signal, (token) => this.http.paginate(`${this.repoPath}/issues/${item.itemId}/dependencies/blocked_by`, {
|
|
177
|
+
token,
|
|
178
|
+
...(signal ? { signal } : {}),
|
|
179
|
+
})),
|
|
180
|
+
]);
|
|
181
|
+
}
|
|
182
|
+
catch (err) {
|
|
183
|
+
if (signal?.aborted)
|
|
184
|
+
throw err;
|
|
185
|
+
const reason = err instanceof SourceError ? `dependencies unavailable (${err.kind}): ${err.message}` : 'dependencies unavailable (unexpected error)';
|
|
186
|
+
this.logger.warn('Could not resolve dependencies', { item: item.key, reason });
|
|
187
|
+
return unknownDependencies(reason);
|
|
188
|
+
}
|
|
189
|
+
if (!issue)
|
|
190
|
+
return unknownDependencies(`item ${item.key} not found while resolving dependencies`);
|
|
191
|
+
const summaryTotal = issue.issue_dependencies_summary?.total_blocked_by;
|
|
192
|
+
if (typeof summaryTotal !== 'number' || !Number.isInteger(summaryTotal) || summaryTotal < 0) {
|
|
193
|
+
return unknownDependencies('issue_dependencies_summary missing; completeness of blockers cannot be verified');
|
|
194
|
+
}
|
|
195
|
+
let open = 0;
|
|
196
|
+
for (const blocker of blockers) {
|
|
197
|
+
if (blocker.state === 'open')
|
|
198
|
+
open += 1;
|
|
199
|
+
else if (blocker.state !== 'closed')
|
|
200
|
+
return unknownDependencies(`blocker with unexpected state "${String(blocker.state)}"`);
|
|
201
|
+
}
|
|
202
|
+
const total = blockers.length;
|
|
203
|
+
if (summaryTotal > total) {
|
|
204
|
+
// GitHub knows more blockers than this identity can see (e.g. cross-repo without access): fail closed.
|
|
205
|
+
return unknownDependencies(`${summaryTotal - total} of ${summaryTotal} blockers not visible to identity (missing access?)`);
|
|
206
|
+
}
|
|
207
|
+
return {
|
|
208
|
+
'dependencies.blocked_by_total': { known: true, value: total },
|
|
209
|
+
'dependencies.blocked_by_open': { known: true, value: open },
|
|
210
|
+
'dependencies.blocked': { known: true, value: open > 0 },
|
|
211
|
+
'dependencies.status': { known: true, value: 'ok' },
|
|
212
|
+
};
|
|
213
|
+
}
|
|
214
|
+
async fetchIssue(itemId, identity, signal) {
|
|
215
|
+
if (!ITEM_ID_PATTERN.test(itemId))
|
|
216
|
+
return null;
|
|
217
|
+
try {
|
|
218
|
+
const res = await this.withToken(identity, signal, (token) => this.http.request('GET', `${this.repoPath}/issues/${itemId}`, { token, ...(signal ? { signal } : {}) }));
|
|
219
|
+
// Transferred issues redirect to another repository: not an item of this source.
|
|
220
|
+
if (res.data.repository_url && !sameRepoUrl(res.data.repository_url, this.config.owner, this.config.repository))
|
|
221
|
+
return null;
|
|
222
|
+
return res.data;
|
|
223
|
+
}
|
|
224
|
+
catch (err) {
|
|
225
|
+
if (err instanceof SourceError && err.kind === 'not_found')
|
|
226
|
+
return null;
|
|
227
|
+
throw err;
|
|
228
|
+
}
|
|
229
|
+
}
|
|
230
|
+
/** Run `fn` with a token; on 401 invalidate the cached token and retry once. */
|
|
231
|
+
async withToken(identity, signal, fn) {
|
|
232
|
+
const first = await this.credentials.getToken(identity, signal ? { signal } : {});
|
|
233
|
+
try {
|
|
234
|
+
return await fn(first.token);
|
|
235
|
+
}
|
|
236
|
+
catch (err) {
|
|
237
|
+
if (!(err instanceof SourceError) || err.kind !== 'auth' || !this.credentials.invalidate)
|
|
238
|
+
throw err;
|
|
239
|
+
this.credentials.invalidate(identity);
|
|
240
|
+
const second = await this.credentials.getToken(identity, signal ? { signal } : {});
|
|
241
|
+
return fn(second.token);
|
|
242
|
+
}
|
|
243
|
+
}
|
|
244
|
+
toItem(issue) {
|
|
245
|
+
if (!Number.isInteger(issue.number) || issue.number <= 0) {
|
|
246
|
+
throw new SourceError('invalid', `GitHub returned an item without a valid number in ${this.repository}`);
|
|
247
|
+
}
|
|
248
|
+
const itemId = String(issue.number);
|
|
249
|
+
const isPr = issue.pull_request !== undefined && issue.pull_request !== null;
|
|
250
|
+
const url = issue.html_url ?? `${(this.config.webBaseUrl ?? 'https://github.com').replace(/\/+$/, '')}/${this.repository}/${isPr ? 'pull' : 'issues'}/${itemId}`;
|
|
251
|
+
return {
|
|
252
|
+
sourceId: this.sourceId,
|
|
253
|
+
itemId,
|
|
254
|
+
key: sourceItemKey(this.sourceId, itemId),
|
|
255
|
+
url,
|
|
256
|
+
type: isPr ? 'pull_request' : 'issue',
|
|
257
|
+
...(issue.created_at ? { createdAt: issue.created_at } : {}),
|
|
258
|
+
fields: {
|
|
259
|
+
number: issue.number,
|
|
260
|
+
title: issue.title ?? '',
|
|
261
|
+
state: issue.state ?? null,
|
|
262
|
+
labels: labelNames(issue),
|
|
263
|
+
assignees: (issue.assignees ?? []).map((a) => a.login).filter((l) => typeof l === 'string'),
|
|
264
|
+
author: issue.user?.login ?? null,
|
|
265
|
+
is_pull_request: isPr,
|
|
266
|
+
created_at: issue.created_at ?? null,
|
|
267
|
+
updated_at: issue.updated_at ?? null,
|
|
268
|
+
url,
|
|
269
|
+
repository: this.repository,
|
|
270
|
+
},
|
|
271
|
+
};
|
|
272
|
+
}
|
|
273
|
+
assertOwnItem(item) {
|
|
274
|
+
if (item.sourceId !== this.sourceId || !ITEM_ID_PATTERN.test(item.itemId)) {
|
|
275
|
+
throw new SourceError('invalid', `Item ${item.key} does not belong to source "${this.sourceId}"`, { retryable: false });
|
|
276
|
+
}
|
|
277
|
+
}
|
|
278
|
+
}
|
|
279
|
+
/** Factory registered under type `github`. */
|
|
280
|
+
export function createGitHubSourceFactory(options = {}) {
|
|
281
|
+
return {
|
|
282
|
+
type: GITHUB_SOURCE_TYPE,
|
|
283
|
+
create: (sourceId, config, deps) => new GitHubSourceAdapter(sourceId, config, deps, options),
|
|
284
|
+
};
|
|
285
|
+
}
|
|
286
|
+
/** Default factory (real timers). */
|
|
287
|
+
export const githubSourceFactory = createGitHubSourceFactory();
|
|
288
|
+
/** Render the HTML comment that carries an idempotency marker. */
|
|
289
|
+
export function renderMarker(marker) {
|
|
290
|
+
if (!MARKER_PATTERN.test(marker))
|
|
291
|
+
throw new SourceError('invalid', 'Comment marker contains unsupported characters', { retryable: false });
|
|
292
|
+
return `<!-- ${marker} -->`;
|
|
293
|
+
}
|
|
294
|
+
/**
|
|
295
|
+
* Regex matching the marker as the LAST line of the body, i.e. the marker that
|
|
296
|
+
* `postComment` appends itself. A marker text inside the body (e.g. copied from
|
|
297
|
+
* untrusted worker output into the message) is followed by the real marker and
|
|
298
|
+
* therefore never matches — it cannot forge the idempotency check (WI-07 review).
|
|
299
|
+
*/
|
|
300
|
+
function markerPattern(marker) {
|
|
301
|
+
const line = renderMarker(marker).replace(/[.*+?^${}()|[\]\\]/g, '\\$&');
|
|
302
|
+
return new RegExp(`(^|\\n)[ \\t]*${line}\\s*$`);
|
|
303
|
+
}
|
|
304
|
+
function unknownDependencies(reason) {
|
|
305
|
+
return {
|
|
306
|
+
'dependencies.blocked_by_total': { known: false, reason },
|
|
307
|
+
'dependencies.blocked_by_open': { known: false, reason },
|
|
308
|
+
'dependencies.blocked': { known: false, reason },
|
|
309
|
+
// The status itself is always known: it says that the others are not.
|
|
310
|
+
'dependencies.status': { known: true, value: 'unknown' },
|
|
311
|
+
};
|
|
312
|
+
}
|
|
313
|
+
function labelNames(issue) {
|
|
314
|
+
return (issue.labels ?? [])
|
|
315
|
+
.map((l) => (typeof l === 'string' ? l : l.name))
|
|
316
|
+
.filter((l) => typeof l === 'string' && l !== '');
|
|
317
|
+
}
|
|
318
|
+
function uniqueCaseInsensitive(values) {
|
|
319
|
+
const seen = new Set();
|
|
320
|
+
const out = [];
|
|
321
|
+
for (const v of values) {
|
|
322
|
+
const k = v.toLowerCase();
|
|
323
|
+
if (v === '' || seen.has(k))
|
|
324
|
+
continue;
|
|
325
|
+
seen.add(k);
|
|
326
|
+
out.push(v);
|
|
327
|
+
}
|
|
328
|
+
return out;
|
|
329
|
+
}
|
|
330
|
+
function sameRepoUrl(repositoryUrl, owner, repo) {
|
|
331
|
+
return repositoryUrl.toLowerCase().endsWith(`/repos/${owner}/${repo}`.toLowerCase());
|
|
332
|
+
}
|
|
333
|
+
function toCommentRef(comment) {
|
|
334
|
+
return { id: String(comment.id), ...(comment.html_url ? { url: comment.html_url } : {}) };
|
|
335
|
+
}
|
|
336
|
+
//# sourceMappingURL=adapter.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"adapter.js","sourceRoot":"","sources":["../../../src/sources/github/adapter.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Field catalogue of the GitHub source adapter (Spec §6, §17).
|
|
3
|
+
*/
|
|
4
|
+
import { type FieldDefinition } from '../../core/index.js';
|
|
5
|
+
/** Names of the expensive dependency fields (resolved lazily via one API round trip). */
|
|
6
|
+
export declare const DEPENDENCY_FIELDS: readonly ['dependencies.blocked_by_total', 'dependencies.blocked_by_open', 'dependencies.blocked', 'dependencies.status'];
|
|
7
|
+
/** All fields provided by the GitHub adapter. */
|
|
8
|
+
export declare const GITHUB_FIELD_DEFINITIONS: readonly FieldDefinition[];
|
|
@@ -0,0 +1,72 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Field catalogue of the GitHub source adapter (Spec §6, §17).
|
|
3
|
+
*/
|
|
4
|
+
import { OPERATORS_BY_TYPE } from '../../core/index.js';
|
|
5
|
+
const STRING_OPS = OPERATORS_BY_TYPE.string;
|
|
6
|
+
const NUMBER_OPS = OPERATORS_BY_TYPE.number;
|
|
7
|
+
const BOOLEAN_OPS = OPERATORS_BY_TYPE.boolean;
|
|
8
|
+
const DATE_OPS = OPERATORS_BY_TYPE.date;
|
|
9
|
+
const LIST_OPS = OPERATORS_BY_TYPE['string[]'];
|
|
10
|
+
/** Names of the expensive dependency fields (resolved lazily via one API round trip). */
|
|
11
|
+
export const DEPENDENCY_FIELDS = [
|
|
12
|
+
'dependencies.blocked_by_total',
|
|
13
|
+
'dependencies.blocked_by_open',
|
|
14
|
+
'dependencies.blocked',
|
|
15
|
+
'dependencies.status',
|
|
16
|
+
];
|
|
17
|
+
/** All fields provided by the GitHub adapter. */
|
|
18
|
+
export const GITHUB_FIELD_DEFINITIONS = Object.freeze([
|
|
19
|
+
{ name: 'number', type: 'number', description: 'Issue/PR number', link: 'url', operators: NUMBER_OPS },
|
|
20
|
+
{ name: 'title', type: 'string', description: 'Title', link: 'url', operators: STRING_OPS },
|
|
21
|
+
{
|
|
22
|
+
name: 'state',
|
|
23
|
+
type: 'string',
|
|
24
|
+
description: 'open | closed',
|
|
25
|
+
operators: STRING_OPS,
|
|
26
|
+
pushdown: ['equals', 'in'],
|
|
27
|
+
},
|
|
28
|
+
{
|
|
29
|
+
name: 'labels',
|
|
30
|
+
type: 'string[]',
|
|
31
|
+
description: 'Label names (compared case-insensitively, like GitHub)',
|
|
32
|
+
operators: LIST_OPS,
|
|
33
|
+
pushdown: ['contains'],
|
|
34
|
+
caseInsensitive: true,
|
|
35
|
+
},
|
|
36
|
+
{ name: 'assignees', type: 'string[]', description: 'Assignee logins', operators: LIST_OPS },
|
|
37
|
+
{ name: 'author', type: 'string', description: 'Login of the author', operators: STRING_OPS },
|
|
38
|
+
{ name: 'is_pull_request', type: 'boolean', description: 'True for pull requests', operators: BOOLEAN_OPS },
|
|
39
|
+
{ name: 'created_at', type: 'date', description: 'Creation time', operators: DATE_OPS },
|
|
40
|
+
{ name: 'updated_at', type: 'date', description: 'Last update time', operators: DATE_OPS },
|
|
41
|
+
{ name: 'url', type: 'string', description: 'Web URL', operators: STRING_OPS },
|
|
42
|
+
{ name: 'repository', type: 'string', description: 'owner/name', operators: STRING_OPS },
|
|
43
|
+
{
|
|
44
|
+
name: 'dependencies.blocked_by_total',
|
|
45
|
+
type: 'number',
|
|
46
|
+
description: 'Number of issues blocking this one (native "blocked by", incl. cross-repo)',
|
|
47
|
+
operators: NUMBER_OPS,
|
|
48
|
+
expensive: true,
|
|
49
|
+
},
|
|
50
|
+
{
|
|
51
|
+
name: 'dependencies.blocked_by_open',
|
|
52
|
+
type: 'number',
|
|
53
|
+
description: 'Number of OPEN issues blocking this one; unknown without access',
|
|
54
|
+
operators: NUMBER_OPS,
|
|
55
|
+
expensive: true,
|
|
56
|
+
},
|
|
57
|
+
{
|
|
58
|
+
name: 'dependencies.blocked',
|
|
59
|
+
type: 'boolean',
|
|
60
|
+
description: 'True if at least one blocker is open; unknown without access',
|
|
61
|
+
operators: BOOLEAN_OPS,
|
|
62
|
+
expensive: true,
|
|
63
|
+
},
|
|
64
|
+
{
|
|
65
|
+
name: 'dependencies.status',
|
|
66
|
+
type: 'string',
|
|
67
|
+
description: '"ok" if dependencies were fully resolved, otherwise "unknown"',
|
|
68
|
+
operators: STRING_OPS,
|
|
69
|
+
expensive: true,
|
|
70
|
+
},
|
|
71
|
+
]);
|
|
72
|
+
//# sourceMappingURL=fields.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"fields.js","sourceRoot":"","sources":["../../../src/sources/github/fields.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,100 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Minimal GitHub REST client on top of an injectable `fetch` (no Octokit).
|
|
3
|
+
*
|
|
4
|
+
* - Pins the REST API version ({@link GITHUB_API_VERSION}) and the
|
|
5
|
+
* `application/vnd.github+json` media type.
|
|
6
|
+
* - Maps HTTP failures to {@link SourceError} kinds (auth, forbidden,
|
|
7
|
+
* not_found, rate_limited, transient, invalid). Messages never contain the
|
|
8
|
+
* token or request headers (Spec §20.4).
|
|
9
|
+
* - Retries idempotent requests on transient errors and rate limits using the
|
|
10
|
+
* injected {@link Timers}; mutating requests are never retried blindly and are
|
|
11
|
+
* flagged `outcomeUnknown` when the request may have taken effect.
|
|
12
|
+
* - Follows `Link: <…>; rel="next"` pagination, but only within the API origin
|
|
13
|
+
* so the token is never sent to a foreign host.
|
|
14
|
+
*/
|
|
15
|
+
import { type Clock, type FetchLike, type Logger, type Timers } from '../../core/index.js';
|
|
16
|
+
/** Pinned GitHub REST API version (sent as `X-GitHub-Api-Version`). */
|
|
17
|
+
export declare const GITHUB_API_VERSION = "2026-03-10";
|
|
18
|
+
/** Default REST API base URL. */
|
|
19
|
+
export declare const GITHUB_API_BASE_URL = "https://api.github.com";
|
|
20
|
+
/** Media type requested from the API. */
|
|
21
|
+
export declare const GITHUB_ACCEPT = "application/vnd.github+json";
|
|
22
|
+
/** HTTP methods used by the orchestrator. */
|
|
23
|
+
export type HttpMethod = 'GET' | 'POST' | 'PATCH' | 'PUT' | 'DELETE';
|
|
24
|
+
/** Options of {@link GitHubHttpClient}. */
|
|
25
|
+
export interface GitHubHttpClientOptions {
|
|
26
|
+
/** HTTP implementation; defaults to the global `fetch`. */
|
|
27
|
+
fetch?: FetchLike;
|
|
28
|
+
clock: Clock;
|
|
29
|
+
/** Timers used for retry delays (inject a `FakeClock` in tests). */
|
|
30
|
+
timers?: Timers;
|
|
31
|
+
logger?: Logger;
|
|
32
|
+
/** API base URL, default {@link GITHUB_API_BASE_URL} (GHES: `https://host/api/v3`). */
|
|
33
|
+
baseUrl?: string;
|
|
34
|
+
/** Retries for idempotent requests (transient errors / rate limits). Default 2. */
|
|
35
|
+
maxRetries?: number;
|
|
36
|
+
/** Longest wait the client sleeps for a rate limit before giving up and throwing. Default 60 s. */
|
|
37
|
+
maxRetryWaitMs?: number;
|
|
38
|
+
/** Base delay for transient retries (exponential). Default 1 s. */
|
|
39
|
+
retryBaseDelayMs?: number;
|
|
40
|
+
/** Per-request timeout. Default 30 s. `0` disables it. */
|
|
41
|
+
requestTimeoutMs?: number;
|
|
42
|
+
/** Max pages followed by {@link GitHubHttpClient.paginate}. Default 50. */
|
|
43
|
+
maxPages?: number;
|
|
44
|
+
userAgent?: string;
|
|
45
|
+
}
|
|
46
|
+
/** Per-request options. */
|
|
47
|
+
export interface GitHubRequestOptions {
|
|
48
|
+
/** Bearer token (installation token or app JWT). Never logged. */
|
|
49
|
+
token?: string;
|
|
50
|
+
query?: Record<string, string | number | boolean | undefined>;
|
|
51
|
+
/** JSON body. */
|
|
52
|
+
body?: unknown;
|
|
53
|
+
signal?: AbortSignal;
|
|
54
|
+
/**
|
|
55
|
+
* Whether the request may be repeated safely. Default: true for GET,
|
|
56
|
+
* false otherwise. Rate-limit responses are retried regardless because
|
|
57
|
+
* the request was rejected before taking effect.
|
|
58
|
+
*/
|
|
59
|
+
idempotent?: boolean;
|
|
60
|
+
}
|
|
61
|
+
/** Successful response. */
|
|
62
|
+
export interface GitHubResponse<T> {
|
|
63
|
+
status: number;
|
|
64
|
+
data: T;
|
|
65
|
+
headers: Headers;
|
|
66
|
+
}
|
|
67
|
+
/** Default per-page size used for list endpoints. */
|
|
68
|
+
export declare const DEFAULT_PER_PAGE = 100;
|
|
69
|
+
/** GitHub REST client. One instance can be shared by adapters and credential providers. */
|
|
70
|
+
export declare class GitHubHttpClient {
|
|
71
|
+
readonly baseUrl: string;
|
|
72
|
+
private readonly fetchImpl;
|
|
73
|
+
private readonly clock;
|
|
74
|
+
private readonly timers;
|
|
75
|
+
private readonly logger;
|
|
76
|
+
private readonly maxRetries;
|
|
77
|
+
private readonly maxRetryWaitMs;
|
|
78
|
+
private readonly retryBaseDelayMs;
|
|
79
|
+
private readonly requestTimeoutMs;
|
|
80
|
+
private readonly maxPages;
|
|
81
|
+
private readonly userAgent;
|
|
82
|
+
private readonly origin;
|
|
83
|
+
constructor(options: GitHubHttpClientOptions);
|
|
84
|
+
/** Perform one request (with retries for idempotent calls) and parse the JSON body. */
|
|
85
|
+
request<T = unknown>(method: HttpMethod, path: string, options?: GitHubRequestOptions): Promise<GitHubResponse<T>>;
|
|
86
|
+
/**
|
|
87
|
+
* GET all pages of a list endpoint by following `Link: rel="next"`.
|
|
88
|
+
* `per_page` defaults to {@link DEFAULT_PER_PAGE}.
|
|
89
|
+
*/
|
|
90
|
+
paginate<T = unknown>(path: string, options?: Omit<GitHubRequestOptions, 'body' | 'idempotent'>): Promise<T[]>;
|
|
91
|
+
private buildUrl;
|
|
92
|
+
private nextPageUrl;
|
|
93
|
+
private requestUrl;
|
|
94
|
+
private once;
|
|
95
|
+
private toError;
|
|
96
|
+
/** Wait time from `Retry-After` (seconds) or `X-RateLimit-Reset` (epoch seconds). */
|
|
97
|
+
private retryAfter;
|
|
98
|
+
}
|
|
99
|
+
/** Parse an RFC 8288 `Link` header into `{ rel: url }`. */
|
|
100
|
+
export declare function parseLinkHeader(header: string | null | undefined): Record<string, string>;
|