@volter/twin-github 0.1.2 → 2.0.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +88 -36
- package/client/github-mirror.css +277 -319
- package/client/github-mirror.d.ts +418 -0
- package/client/github-mirror.js +485 -0
- package/client/github-mirror.tsx +153 -357
- package/client/pulls-rest.ts +159 -0
- package/client/pulls-workspace.tsx +841 -0
- package/dist/client/github-mirror.bundle.js +239 -0
- package/dist/client/github-mirror.css +916 -0
- package/dist/client/github-mirror.d.ts +418 -0
- package/dist/client/github-mirror.js +485 -0
- package/dist/client/github-mirror.tsx +1315 -0
- package/dist/client/pulls-rest.d.ts +42 -0
- package/dist/client/pulls-rest.js +140 -0
- package/dist/client/pulls-rest.ts +159 -0
- package/dist/client/pulls-workspace.bundle.js +22 -0
- package/dist/client/pulls-workspace.d.ts +114 -0
- package/dist/client/pulls-workspace.js +418 -0
- package/dist/client/pulls-workspace.tsx +841 -0
- package/dist/src/cli.d.ts +2 -0
- package/dist/src/cli.js +40 -0
- package/dist/src/generated/graphql-sdl.gen.json +1 -0
- package/dist/src/generated/graphql.gen.json +1 -0
- package/dist/src/generated/surface.gen.json +1 -0
- package/dist/src/generated/ui.gen.json +1 -0
- package/dist/src/github-budget.d.ts +69 -0
- package/dist/src/github-budget.js +172 -0
- package/dist/src/github-capabilities.d.ts +5 -0
- package/dist/src/github-capabilities.js +4468 -0
- package/dist/src/github-conformance.d.ts +43 -0
- package/dist/src/github-conformance.js +76 -0
- package/dist/src/github-connector.d.ts +307 -0
- package/dist/src/github-connector.js +1398 -0
- package/dist/src/github-events.d.ts +41 -0
- package/dist/src/github-events.js +232 -0
- package/dist/src/github-git-http.d.ts +49 -0
- package/dist/src/github-git-http.js +185 -0
- package/dist/src/github-git-plane.d.ts +114 -0
- package/dist/src/github-git-plane.js +407 -0
- package/dist/src/github-mirror-state.d.ts +2 -0
- package/dist/src/github-mirror-state.js +335 -0
- package/dist/src/github-mirror-ui.d.ts +20 -0
- package/dist/src/github-mirror-ui.js +101 -0
- package/dist/src/github-server.d.ts +14 -0
- package/dist/src/github-server.js +240 -0
- package/dist/src/github-shared.d.ts +12 -0
- package/dist/src/github-shared.js +21 -0
- package/dist/src/github-twin.d.ts +1411 -0
- package/dist/src/github-twin.js +4084 -0
- package/dist/src/github-ui-conformance.d.ts +4 -0
- package/dist/src/github-ui-conformance.js +105 -0
- package/dist/src/github-ui-structure.d.ts +18 -0
- package/dist/src/github-ui-structure.js +251 -0
- package/dist/src/graphql-wire.d.ts +22 -0
- package/dist/src/graphql-wire.js +89 -0
- package/dist/src/index.d.ts +17 -0
- package/dist/src/index.js +104 -0
- package/dist/src/manifest.d.ts +8 -0
- package/dist/src/manifest.js +597 -0
- package/dist/src/npm-registry.d.ts +7 -0
- package/dist/src/npm-registry.js +47 -0
- package/dist/src/screens/app-installation.d.ts +3 -0
- package/dist/src/screens/app-installation.js +166 -0
- package/dist/src/screens/app-manifest.d.ts +3 -0
- package/dist/src/screens/app-manifest.js +81 -0
- package/dist/src/screens/oauth.d.ts +15 -0
- package/dist/src/screens/oauth.js +257 -0
- package/dist/src/screens/session.d.ts +8 -0
- package/dist/src/screens/session.js +170 -0
- package/dist/src/semantics/actions.d.ts +2 -0
- package/dist/src/semantics/actions.js +413 -0
- package/dist/src/semantics/activity.d.ts +4 -0
- package/dist/src/semantics/activity.js +161 -0
- package/dist/src/semantics/apps.d.ts +2 -0
- package/dist/src/semantics/apps.js +144 -0
- package/dist/src/semantics/branches.d.ts +2 -0
- package/dist/src/semantics/branches.js +136 -0
- package/dist/src/semantics/checks.d.ts +2 -0
- package/dist/src/semantics/checks.js +176 -0
- package/dist/src/semantics/code-scanning-upload.d.ts +2 -0
- package/dist/src/semantics/code-scanning-upload.js +97 -0
- package/dist/src/semantics/codespaces.d.ts +2 -0
- package/dist/src/semantics/codespaces.js +58 -0
- package/dist/src/semantics/commits.d.ts +2 -0
- package/dist/src/semantics/commits.js +109 -0
- package/dist/src/semantics/contents.d.ts +2 -0
- package/dist/src/semantics/contents.js +131 -0
- package/dist/src/semantics/deployments.d.ts +2 -0
- package/dist/src/semantics/deployments.js +127 -0
- package/dist/src/semantics/gists.d.ts +2 -0
- package/dist/src/semantics/gists.js +86 -0
- package/dist/src/semantics/git.d.ts +2 -0
- package/dist/src/semantics/git.js +235 -0
- package/dist/src/semantics/graphql.d.ts +7 -0
- package/dist/src/semantics/graphql.js +512 -0
- package/dist/src/semantics/index.d.ts +5 -0
- package/dist/src/semantics/index.js +62 -0
- package/dist/src/semantics/issues.d.ts +2 -0
- package/dist/src/semantics/issues.js +456 -0
- package/dist/src/semantics/keys.d.ts +2 -0
- package/dist/src/semantics/keys.js +66 -0
- package/dist/src/semantics/labels.d.ts +2 -0
- package/dist/src/semantics/labels.js +100 -0
- package/dist/src/semantics/meta.d.ts +12 -0
- package/dist/src/semantics/meta.js +144 -0
- package/dist/src/semantics/notifications.d.ts +4 -0
- package/dist/src/semantics/notifications.js +62 -0
- package/dist/src/semantics/orgs.d.ts +2 -0
- package/dist/src/semantics/orgs.js +420 -0
- package/dist/src/semantics/packages.d.ts +2 -0
- package/dist/src/semantics/packages.js +55 -0
- package/dist/src/semantics/pages.d.ts +2 -0
- package/dist/src/semantics/pages.js +176 -0
- package/dist/src/semantics/projects.d.ts +2 -0
- package/dist/src/semantics/projects.js +239 -0
- package/dist/src/semantics/pulls.d.ts +2 -0
- package/dist/src/semantics/pulls.js +462 -0
- package/dist/src/semantics/push-reactions.d.ts +101 -0
- package/dist/src/semantics/push-reactions.js +513 -0
- package/dist/src/semantics/releases.d.ts +19 -0
- package/dist/src/semantics/releases.js +231 -0
- package/dist/src/semantics/repo-invitations.d.ts +2 -0
- package/dist/src/semantics/repo-invitations.js +98 -0
- package/dist/src/semantics/repos.d.ts +17 -0
- package/dist/src/semantics/repos.js +390 -0
- package/dist/src/semantics/rulesets.d.ts +2 -0
- package/dist/src/semantics/rulesets.js +111 -0
- package/dist/src/semantics/search.d.ts +2 -0
- package/dist/src/semantics/search.js +84 -0
- package/dist/src/semantics/security.d.ts +2 -0
- package/dist/src/semantics/security.js +177 -0
- package/dist/src/semantics/shared.d.ts +61 -0
- package/dist/src/semantics/shared.js +151 -0
- package/dist/src/semantics/users.d.ts +2 -0
- package/dist/src/semantics/users.js +255 -0
- package/dist/src/semantics/webhooks.d.ts +2 -0
- package/dist/src/semantics/webhooks.js +107 -0
- package/dist/test-fixtures/github-a11y-reference.pr-list.SOURCE.md +56 -0
- package/dist/test-fixtures/github-a11y-reference.pr-list.json +1447 -0
- package/dist/test-fixtures/github-comment-schema.SOURCE.md +11 -0
- package/dist/test-fixtures/github-comment-schema.json +702 -0
- package/dist/test-fixtures/github-known-deviations.json +94 -0
- package/dist/test-fixtures/github-openapi-operations.SOURCE.md +76 -0
- package/dist/test-fixtures/github-openapi-operations.json +362 -0
- package/dist/test-fixtures/github-pull-schema.SOURCE.md +37 -0
- package/dist/test-fixtures/github-pull-schema.json +3601 -0
- package/dist/test-fixtures/github-review-schema.SOURCE.md +12 -0
- package/dist/test-fixtures/github-review-schema.json +236 -0
- package/package.json +20 -11
- package/src/cli.ts +7 -6
- package/src/generated/graphql-sdl.gen.json +1 -0
- package/src/generated/graphql.gen.json +1 -0
- package/src/generated/surface.gen.json +1 -0
- package/src/generated/ui.gen.json +1 -0
- package/src/github-a11y-snapshot.uitest.ts +5 -5
- package/src/github-budget.ts +4 -4
- package/src/github-capabilities.ts +1993 -556
- package/src/github-conformance.ts +12 -7
- package/src/github-connector.ts +108 -96
- package/src/github-events.ts +225 -95
- package/src/github-git-http.ts +48 -84
- package/src/github-git-plane.ts +247 -385
- package/src/github-journey.uitest.ts +28 -44
- package/src/github-mirror-state.ts +23 -61
- package/src/github-mirror-ui.ts +16 -10
- package/src/github-server.ts +158 -60
- package/src/github-shared.ts +1 -1
- package/src/github-twin.ts +1525 -4494
- package/src/github-ui-conformance.ts +7 -8
- package/src/github-ui-structure.ts +19 -18
- package/src/graphql-wire.ts +115 -0
- package/src/index.ts +50 -7
- package/src/manifest.ts +605 -0
- package/src/npm-registry.ts +43 -0
- package/src/screens/app-installation.tsx +217 -0
- package/src/screens/app-manifest.tsx +97 -0
- package/src/screens/oauth.tsx +258 -0
- package/src/screens/session.tsx +193 -0
- package/src/semantics/actions.ts +395 -0
- package/src/semantics/activity.ts +171 -0
- package/src/semantics/apps.ts +133 -0
- package/src/semantics/branches.ts +133 -0
- package/src/semantics/checks.ts +163 -0
- package/src/semantics/code-scanning-upload.ts +92 -0
- package/src/semantics/codespaces.ts +58 -0
- package/src/semantics/commits.ts +109 -0
- package/src/semantics/contents.ts +112 -0
- package/src/semantics/deployments.ts +116 -0
- package/src/semantics/gists.ts +85 -0
- package/src/semantics/git.ts +226 -0
- package/src/semantics/graphql.ts +505 -0
- package/src/semantics/index.ts +68 -0
- package/src/semantics/issues.ts +434 -0
- package/src/semantics/keys.ts +66 -0
- package/src/semantics/labels.ts +91 -0
- package/src/semantics/meta.ts +139 -0
- package/src/semantics/notifications.ts +58 -0
- package/src/semantics/orgs.ts +383 -0
- package/src/semantics/packages.ts +59 -0
- package/src/semantics/pages.ts +154 -0
- package/src/semantics/projects.ts +246 -0
- package/src/semantics/pulls.ts +421 -0
- package/src/semantics/push-reactions.ts +471 -0
- package/src/semantics/releases.ts +213 -0
- package/src/semantics/repo-invitations.ts +112 -0
- package/src/semantics/repos.ts +373 -0
- package/src/semantics/rulesets.ts +107 -0
- package/src/semantics/search.ts +83 -0
- package/src/semantics/security.ts +153 -0
- package/src/semantics/shared.ts +181 -0
- package/src/semantics/users.ts +252 -0
- package/src/semantics/webhooks.ts +101 -0
- package/test-fixtures/github-known-deviations.json +7 -8
- package/test-fixtures/github-openapi-operations.json +46 -227
- package/src/github-graphql.ts +0 -398
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
import type { DerivedManifest } from '@volter/world-core';
|
|
2
|
+
/** Path parameters whose values GitHub lets hold slashes, which its OpenAPI description does not say:
|
|
3
|
+
* a git ref (`heads/feature/x`, https://docs.github.com/rest/git/refs#get-a-reference), a file path
|
|
4
|
+
* (https://docs.github.com/rest/repos/contents#get-repository-content), a release tag, a branch name
|
|
5
|
+
* (https://docs.github.com/rest/branches/branches#get-a-branch), a label name, and a compare range
|
|
6
|
+
* (`base...head` where either is a branch). The surface's `spanning` list (github-server.ts). */
|
|
7
|
+
export declare const spanning: string[];
|
|
8
|
+
export declare const manifest: DerivedManifest;
|
|
@@ -0,0 +1,597 @@
|
|
|
1
|
+
import { callerLogin, GITHUB_WORLD_USER } from "./github-twin.js";
|
|
2
|
+
/** Path parameters whose values GitHub lets hold slashes, which its OpenAPI description does not say:
|
|
3
|
+
* a git ref (`heads/feature/x`, https://docs.github.com/rest/git/refs#get-a-reference), a file path
|
|
4
|
+
* (https://docs.github.com/rest/repos/contents#get-repository-content), a release tag, a branch name
|
|
5
|
+
* (https://docs.github.com/rest/branches/branches#get-a-branch), a label name, and a compare range
|
|
6
|
+
* (`base...head` where either is a branch). The surface's `spanning` list (github-server.ts). */
|
|
7
|
+
export const spanning = ['ref', 'path', 'tag', 'branch', 'name', 'basehead'];
|
|
8
|
+
/** A resource that lives in a repository: named by `{owner}/{repo}` and stored with that value in its
|
|
9
|
+
* `repository` field. Its `key`, where one is declared, is the subject id the twin mints for it from the
|
|
10
|
+
* path (locally created subjects; an observed one keeps the id it was observed under). The core serves
|
|
11
|
+
* none of these operations: the repository itself is stored under a sequence id (`repo:<n>`), so the
|
|
12
|
+
* core's parent check, which looks the parent up by subject id, can never find `{owner}/{repo}`; and
|
|
13
|
+
* every stored shape is the twin's (githubState folds and renames), not the answer. Handlers serve them. */
|
|
14
|
+
// a repository is stored as repo:<n> with its owner and name, and addressed by both
|
|
15
|
+
const inRepository = { params: ['owner', 'repo'], value: '{owner}/{repo}', field: 'repository', resource: 'full-repository', where: { owner: '{owner}', name: '{repo}' } };
|
|
16
|
+
export const manifest = {
|
|
17
|
+
vendor: 'github',
|
|
18
|
+
service: 'github',
|
|
19
|
+
// GitHub reads a body as JSON whatever its content type says (curl's default is a form type)
|
|
20
|
+
body: { json: 'always' },
|
|
21
|
+
ids: { template: '{n}' },
|
|
22
|
+
time: 'iso',
|
|
23
|
+
error: { message: '{message}', documentation_url: 'https://docs.github.com/rest', status: '{statusText}' },
|
|
24
|
+
readOnly: { status: 403, message: 'twin is read-only (mirror mode); start in simulator/fork to write' },
|
|
25
|
+
notFound: { status: 404, message: 'Not Found' },
|
|
26
|
+
list: {
|
|
27
|
+
style: 'envelope',
|
|
28
|
+
envelope: '{data}',
|
|
29
|
+
limit: { param: 'per_page', default: 30, max: 100 },
|
|
30
|
+
page: { param: 'page', link: true },
|
|
31
|
+
},
|
|
32
|
+
deleted: null,
|
|
33
|
+
// a token minted at the twin's user door names its user; the World's shared token names no one
|
|
34
|
+
identity: (authorization, root) => callerLogin((authorization ?? '').replace(/^(?:bearer|token)\s+/i, '').trim() || undefined, root) ?? GITHUB_WORLD_USER,
|
|
35
|
+
// Operations on a declared resource the core must not claim: GitHub's stored subjects are the twin's
|
|
36
|
+
// own shape (a sequence id such as `sshkey:3`, fields folded by githubState), not the vendor's, so
|
|
37
|
+
// the core reproduces none of them; each is a handler, or unserved (the vendor's Not Found).
|
|
38
|
+
unmodeled: [
|
|
39
|
+
'actions/delete-environment-variable',
|
|
40
|
+
'actions/delete-workflow-run',
|
|
41
|
+
'actions/disable-workflow',
|
|
42
|
+
'actions/enable-workflow',
|
|
43
|
+
'actions/get-environment-variable',
|
|
44
|
+
'actions/get-workflow-run-attempt',
|
|
45
|
+
'actions/list-environment-variables',
|
|
46
|
+
'actions/list-jobs-for-workflow-run-attempt',
|
|
47
|
+
'actions/list-repo-organization-secrets',
|
|
48
|
+
'actions/list-repo-organization-variables',
|
|
49
|
+
'actions/list-workflow-run-artifacts',
|
|
50
|
+
'activity/mark-thread-as-done',
|
|
51
|
+
'agents/delete-org-secret',
|
|
52
|
+
'agents/delete-org-variable',
|
|
53
|
+
'agents/delete-repo-secret',
|
|
54
|
+
'agents/delete-repo-variable',
|
|
55
|
+
'agents/get-org-secret',
|
|
56
|
+
'agents/get-org-variable',
|
|
57
|
+
'agents/get-repo-secret',
|
|
58
|
+
'agents/get-repo-variable',
|
|
59
|
+
'agents/list-org-secrets',
|
|
60
|
+
'agents/list-org-variables',
|
|
61
|
+
'agents/list-repo-organization-secrets',
|
|
62
|
+
'agents/list-repo-organization-variables',
|
|
63
|
+
'agents/list-repo-secrets',
|
|
64
|
+
'agents/list-repo-variables',
|
|
65
|
+
'apps/delete-installation',
|
|
66
|
+
'apps/get-org-installation',
|
|
67
|
+
'apps/get-repo-installation',
|
|
68
|
+
'apps/get-user-installation',
|
|
69
|
+
'apps/list-installations-for-authenticated-user',
|
|
70
|
+
'codespaces/create-with-repo-for-authenticated-user',
|
|
71
|
+
'codespaces/get-codespaces-for-user-in-org',
|
|
72
|
+
'codespaces/list-in-organization',
|
|
73
|
+
'codespaces/list-in-repository-for-authenticated-user',
|
|
74
|
+
'codespaces/update-for-authenticated-user',
|
|
75
|
+
'gists/list-for-user',
|
|
76
|
+
'gists/list-forks',
|
|
77
|
+
'gists/list-public',
|
|
78
|
+
'gists/list-starred',
|
|
79
|
+
'git/list-matching-refs',
|
|
80
|
+
'issues/add-blocked-by-dependency',
|
|
81
|
+
'issues/delete-milestone',
|
|
82
|
+
'issues/get-parent',
|
|
83
|
+
'issues/list',
|
|
84
|
+
'issues/list-comments-for-repo',
|
|
85
|
+
'issues/list-dependencies-blocked-by',
|
|
86
|
+
'issues/list-dependencies-blocking',
|
|
87
|
+
'issues/list-for-authenticated-user',
|
|
88
|
+
'issues/list-for-org',
|
|
89
|
+
'issues/list-labels-for-milestone',
|
|
90
|
+
'issues/remove-dependency-blocked-by',
|
|
91
|
+
'orgs/delete',
|
|
92
|
+
'orgs/get-membership-for-authenticated-user',
|
|
93
|
+
'orgs/list-app-installations',
|
|
94
|
+
'orgs/list-invitation-teams',
|
|
95
|
+
'orgs/list-memberships-for-authenticated-user',
|
|
96
|
+
'orgs/update-membership-for-authenticated-user',
|
|
97
|
+
'packages/delete-package-for-org',
|
|
98
|
+
'packages/delete-package-for-user',
|
|
99
|
+
'packages/delete-package-version-for-org',
|
|
100
|
+
'packages/delete-package-version-for-user',
|
|
101
|
+
'packages/get-all-package-versions-for-package-owned-by-org',
|
|
102
|
+
'packages/get-all-package-versions-for-package-owned-by-user',
|
|
103
|
+
'packages/get-package-for-organization',
|
|
104
|
+
'packages/get-package-for-user',
|
|
105
|
+
'packages/get-package-version-for-organization',
|
|
106
|
+
'packages/get-package-version-for-user',
|
|
107
|
+
'packages/list-docker-migration-conflicting-packages-for-authenticated-user',
|
|
108
|
+
'packages/list-docker-migration-conflicting-packages-for-organization',
|
|
109
|
+
'packages/list-docker-migration-conflicting-packages-for-user',
|
|
110
|
+
'packages/list-packages-for-organization',
|
|
111
|
+
'packages/list-packages-for-user',
|
|
112
|
+
'projects/add-field-for-org',
|
|
113
|
+
'projects/add-field-for-user',
|
|
114
|
+
'projects/delete-item-for-org',
|
|
115
|
+
'projects/delete-item-for-user',
|
|
116
|
+
'projects/get-field-for-org',
|
|
117
|
+
'projects/get-field-for-user',
|
|
118
|
+
'projects/get-for-user',
|
|
119
|
+
'projects/get-org-item',
|
|
120
|
+
'projects/get-user-item',
|
|
121
|
+
'projects/list-fields-for-org',
|
|
122
|
+
'projects/list-fields-for-user',
|
|
123
|
+
'projects/list-for-user',
|
|
124
|
+
'projects/list-items-for-org',
|
|
125
|
+
'projects/list-items-for-user',
|
|
126
|
+
'projects/list-view-items-for-org',
|
|
127
|
+
'projects/list-view-items-for-user',
|
|
128
|
+
'projects/update-item-for-org',
|
|
129
|
+
'projects/update-item-for-user',
|
|
130
|
+
'pulls/delete-pending-review',
|
|
131
|
+
'pulls/list-review-comments-for-repo',
|
|
132
|
+
'reactions/create-for-commit-comment',
|
|
133
|
+
'reactions/create-for-release',
|
|
134
|
+
'reactions/list-for-commit-comment',
|
|
135
|
+
'reactions/list-for-release',
|
|
136
|
+
'repos/add-team-access-restrictions',
|
|
137
|
+
'repos/create-org-ruleset',
|
|
138
|
+
'repos/delete-deployment',
|
|
139
|
+
'repos/delete-org-ruleset',
|
|
140
|
+
'repos/delete-release-asset',
|
|
141
|
+
'repos/get-access-restrictions',
|
|
142
|
+
'repos/get-org-rule-suite',
|
|
143
|
+
'repos/get-org-ruleset',
|
|
144
|
+
'repos/get-org-rulesets',
|
|
145
|
+
'repos/get-teams-with-access-to-protected-branch',
|
|
146
|
+
'repos/list-issue-types',
|
|
147
|
+
'repos/list-teams',
|
|
148
|
+
'repos/update-org-ruleset',
|
|
149
|
+
'repos/update-release-asset',
|
|
150
|
+
'teams/check-permissions-for-repo-legacy',
|
|
151
|
+
'teams/delete-legacy',
|
|
152
|
+
'teams/get-legacy',
|
|
153
|
+
'teams/list-child-in-org',
|
|
154
|
+
'teams/list-child-legacy',
|
|
155
|
+
'teams/list-for-authenticated-user',
|
|
156
|
+
'teams/remove-repo-legacy',
|
|
157
|
+
'teams/update-legacy',
|
|
158
|
+
'users/list-gpg-keys-for-user',
|
|
159
|
+
],
|
|
160
|
+
// Every declared resource's served operations are handlers (semantics/); the declarations name the
|
|
161
|
+
// stored type and rule on the spec's state candidates.
|
|
162
|
+
// The screens applications and people reach (docs/contributing/architecture.md, "Screens"). Demand is the
|
|
163
|
+
// ladder's 85 applications: the code that sends a user to the page.
|
|
164
|
+
screens: [
|
|
165
|
+
{
|
|
166
|
+
id: 'sign-in', kind: 'flow', host: 'github.com', path: '/login', status: 'done',
|
|
167
|
+
demand: 'every github.com page a person reaches: each asks who is signed in', controls: ['Username or email address', 'Password', 'Sign in'],
|
|
168
|
+
source: 'https://docs.github.com/authentication/keeping-your-account-and-data-secure/about-authentication-to-github',
|
|
169
|
+
},
|
|
170
|
+
{
|
|
171
|
+
id: 'two-factor', kind: 'flow', host: 'github.com', path: '/sessions/two-factor/app', status: 'done',
|
|
172
|
+
demand: 'every person with two-factor authentication signing in, as GitHub requires of contributors', controls: ['Authentication code', 'Verify'],
|
|
173
|
+
source: 'https://docs.github.com/authentication/securing-your-account-with-two-factor-authentication-2fa/accessing-github-using-two-factor-authentication',
|
|
174
|
+
},
|
|
175
|
+
{
|
|
176
|
+
id: 'oauth-consent', kind: 'flow', host: 'github.com', path: '/login/oauth/authorize', status: 'done',
|
|
177
|
+
demand: '35 of 85 applications sign users in with GitHub', controls: ['Authorize {login}', 'Cancel'],
|
|
178
|
+
source: 'https://docs.github.com/apps/oauth-apps/building-oauth-apps/authorizing-oauth-apps',
|
|
179
|
+
},
|
|
180
|
+
{
|
|
181
|
+
id: 'app-installation', kind: 'flow', host: 'github.com', path: '/apps/{slug}/installations/new', status: 'done',
|
|
182
|
+
demand: '10 of 85 applications send an owner to install their GitHub App', controls: ['Install', 'Install & Authorize', 'Cancel', 'All repositories', 'Only select repositories', 'Switch account'],
|
|
183
|
+
source: 'https://docs.github.com/apps/using-github-apps/installing-a-github-app-from-a-third-party',
|
|
184
|
+
},
|
|
185
|
+
{
|
|
186
|
+
id: 'pull-requests', kind: 'workspace', host: 'github.com', path: '/{owner}/{repo}/pulls', status: 'done',
|
|
187
|
+
demand: 'testers and agents review pull requests', source: 'https://docs.github.com/pull-requests',
|
|
188
|
+
},
|
|
189
|
+
],
|
|
190
|
+
resources: {
|
|
191
|
+
// users and keys (semantics/users.ts)
|
|
192
|
+
email: { storedAs: 'user_email', idPrefix: 'useremail:' },
|
|
193
|
+
key: { storedAs: 'user_ssh_key', idPrefix: 'sshkey:' },
|
|
194
|
+
'gpg-key': { storedAs: 'user_gpg_key', idPrefix: 'gpgkey:' },
|
|
195
|
+
// gists (semantics/gists.ts): one stored gist answers both the full and the listed shape
|
|
196
|
+
'gist-simple': { storedAs: 'gist', idPrefix: 'gist:' },
|
|
197
|
+
'base-gist': { storedAs: 'gist', idPrefix: 'gist:' },
|
|
198
|
+
// notification threads (semantics/activity.ts)
|
|
199
|
+
thread: { storedAs: 'notification', idPrefix: 'notification:' },
|
|
200
|
+
// organizations and teams (semantics/orgs.ts)
|
|
201
|
+
// is_verified: GitHub verifies an organization's domain; no API moves it
|
|
202
|
+
'organization-full': { storedAs: 'organization', idPrefix: 'org:', notState: ['is_verified'] },
|
|
203
|
+
'org-membership': {
|
|
204
|
+
storedAs: 'org_membership',
|
|
205
|
+
idPrefix: 'orgmember:',
|
|
206
|
+
notState: ['role'],
|
|
207
|
+
state: {
|
|
208
|
+
// the twin confirms a membership as it sets it (no invitation to accept offline); GitHub starts
|
|
209
|
+
// one pending until the member accepts
|
|
210
|
+
state: { initial: 'active', vendorInitial: 'pending', transitions: [{ operation: 'orgs/update-membership-for-authenticated-user', from: ['pending'], to: 'active', source: 'https://docs.github.com/rest/orgs/members#update-an-organization-membership-for-the-authenticated-user' }] },
|
|
211
|
+
},
|
|
212
|
+
},
|
|
213
|
+
// active: a setting an edit names
|
|
214
|
+
'org-hook': { storedAs: 'org_webhook', idPrefix: 'orghook:', notState: ['active'] },
|
|
215
|
+
'issue-type': { storedAs: 'issue_type', idPrefix: 'issuetype:', notState: ['color', 'is_enabled'] },
|
|
216
|
+
'team-full': { storedAs: 'team', idPrefix: 'team:', notState: ['notification_setting', 'privacy', 'type'] },
|
|
217
|
+
team: { storedAs: 'team', idPrefix: 'team:', notState: ['access_source', 'type'] },
|
|
218
|
+
// archived, disabled, is_template: the repository's own, ruled on full-repository
|
|
219
|
+
'team-repository': { storedAs: 'team_repo', idPrefix: 'teamrepo:', notState: ['archived', 'disabled', 'is_template'], key: 'teamrepo:{org}#{team_slug}#{owner}/{repo}' },
|
|
220
|
+
// Projects v2 (semantics/projects.ts): GitHub moves a project's state by GraphQL's
|
|
221
|
+
// updateProjectV2 (closed), no REST operation: another wire's move (`external`); the twin stores
|
|
222
|
+
// it as `closed`. is_template: a setting (markProjectV2AsTemplate).
|
|
223
|
+
'projects-v2': {
|
|
224
|
+
storedAs: 'project',
|
|
225
|
+
idPrefix: 'project:',
|
|
226
|
+
notState: ['is_template'],
|
|
227
|
+
state: {
|
|
228
|
+
state: {
|
|
229
|
+
initial: 'open',
|
|
230
|
+
transitions: [
|
|
231
|
+
{ actor: 'external', from: ['open'], to: 'closed', source: 'https://docs.github.com/graphql/reference/mutations#updateprojectv2' },
|
|
232
|
+
{ actor: 'external', from: ['closed'], to: 'open', source: 'https://docs.github.com/graphql/reference/mutations#updateprojectv2' },
|
|
233
|
+
],
|
|
234
|
+
},
|
|
235
|
+
},
|
|
236
|
+
},
|
|
237
|
+
'projects-v2-field': { storedAs: 'project_field', idPrefix: 'projectfield:', notState: ['data_type'] },
|
|
238
|
+
'projects-v2-item-with-content': { storedAs: 'project_item', idPrefix: 'projectitem:', notState: ['content_type'] },
|
|
239
|
+
// security alerts (semantics/security.ts): the twin accepts any requested state on an update, as
|
|
240
|
+
// it always has; GitHub's documented moves are the machines
|
|
241
|
+
'code-scanning-alert-items': {
|
|
242
|
+
storedAs: 'code_scanning_alert',
|
|
243
|
+
idPrefix: 'csalert:',
|
|
244
|
+
parent: inRepository,
|
|
245
|
+
key: 'csalert:{owner}/{repo}#{alert_number}',
|
|
246
|
+
notState: ['dismissed_reason'],
|
|
247
|
+
state: {
|
|
248
|
+
state: {
|
|
249
|
+
initial: 'open',
|
|
250
|
+
transitions: [
|
|
251
|
+
{ operation: 'code-scanning/update-alert', from: '*', to: 'dismissed', source: 'https://docs.github.com/rest/code-scanning/code-scanning#update-a-code-scanning-alert' },
|
|
252
|
+
{ operation: 'code-scanning/update-alert', from: '*', to: 'open', source: 'https://docs.github.com/rest/code-scanning/code-scanning#update-a-code-scanning-alert' },
|
|
253
|
+
// an analysis that no longer finds it fixes it (semantics/code-scanning-upload.ts)
|
|
254
|
+
{ actor: 'vendor', from: ['open'], to: 'fixed', source: 'https://docs.github.com/code-security/code-scanning/managing-code-scanning-alerts/about-code-scanning-alerts#about-alert-details' },
|
|
255
|
+
],
|
|
256
|
+
},
|
|
257
|
+
},
|
|
258
|
+
},
|
|
259
|
+
'code-scanning-analysis': { storedAs: 'code_scanning_analysis', idPrefix: 'csanalysis:', parent: inRepository, key: 'csanalysis:{analysis_id}' },
|
|
260
|
+
'dependabot-alert': {
|
|
261
|
+
storedAs: 'dependabot_alert',
|
|
262
|
+
idPrefix: 'dependabot:',
|
|
263
|
+
parent: inRepository,
|
|
264
|
+
key: 'dependabot:{owner}/{repo}#{alert_number}',
|
|
265
|
+
notState: ['dismissed_reason'],
|
|
266
|
+
state: {
|
|
267
|
+
state: {
|
|
268
|
+
initial: 'open',
|
|
269
|
+
transitions: [
|
|
270
|
+
{ operation: 'dependabot/update-alert', from: '*', to: 'dismissed', source: 'https://docs.github.com/rest/dependabot/alerts#update-a-dependabot-alert' },
|
|
271
|
+
{ operation: 'dependabot/update-alert', from: '*', to: 'open', source: 'https://docs.github.com/rest/dependabot/alerts#update-a-dependabot-alert' },
|
|
272
|
+
// a push whose manifest no longer asks for a vulnerable version fixes it (semantics/push-reactions.ts)
|
|
273
|
+
{ actor: 'vendor', from: ['open'], to: 'fixed', source: 'https://docs.github.com/code-security/dependabot/dependabot-alerts/about-dependabot-alerts' },
|
|
274
|
+
],
|
|
275
|
+
},
|
|
276
|
+
},
|
|
277
|
+
},
|
|
278
|
+
'secret-scanning-alert': {
|
|
279
|
+
storedAs: 'secret_scanning_alert',
|
|
280
|
+
idPrefix: 'secretscan:',
|
|
281
|
+
parent: inRepository,
|
|
282
|
+
key: 'secretscan:{owner}/{repo}#{alert_number}',
|
|
283
|
+
notState: ['resolution', 'validity'],
|
|
284
|
+
state: {
|
|
285
|
+
state: {
|
|
286
|
+
initial: 'open',
|
|
287
|
+
transitions: [
|
|
288
|
+
{ operation: 'secret-scanning/update-alert', from: '*', to: 'resolved', source: 'https://docs.github.com/rest/secret-scanning/secret-scanning#update-a-secret-scanning-alert' },
|
|
289
|
+
{ operation: 'secret-scanning/update-alert', from: '*', to: 'open', source: 'https://docs.github.com/rest/secret-scanning/secret-scanning#update-a-secret-scanning-alert' },
|
|
290
|
+
],
|
|
291
|
+
},
|
|
292
|
+
},
|
|
293
|
+
},
|
|
294
|
+
// Pages builds (semantics/pages.ts): GitHub queues a requested build and builds it (queued → building →
|
|
295
|
+
// built or errored, docs.github.com/rest/pages/pages#request-a-github-pages-build); the twin records it built
|
|
296
|
+
// as it is requested (nothing builds offline), so it makes none of those moves
|
|
297
|
+
'page-build': {
|
|
298
|
+
storedAs: 'pages_build',
|
|
299
|
+
idPrefix: 'pagesbuild:',
|
|
300
|
+
parent: inRepository,
|
|
301
|
+
key: 'pagesbuild:{build_id}',
|
|
302
|
+
state: { status: { initial: 'built', vendorInitial: 'queued', transitions: [] } },
|
|
303
|
+
},
|
|
304
|
+
// packages (semantics/packages.ts)
|
|
305
|
+
package: { storedAs: 'package', idPrefix: 'package:', notState: ['package_type', 'visibility'] },
|
|
306
|
+
'package-version': { storedAs: 'package_version', idPrefix: 'packageversion:' },
|
|
307
|
+
// app installations (semantics/apps.ts)
|
|
308
|
+
installation: { storedAs: 'app_installation', idPrefix: 'installation:', notState: ['repository_selection'] },
|
|
309
|
+
// Actions (semantics/actions.ts): no runner executes anything; runs move only by rerun, cancel
|
|
310
|
+
// and the twin's runner door, from any state, as the twin always has
|
|
311
|
+
workflow: {
|
|
312
|
+
storedAs: 'workflow',
|
|
313
|
+
idPrefix: 'workflow:',
|
|
314
|
+
parent: inRepository,
|
|
315
|
+
state: {
|
|
316
|
+
state: {
|
|
317
|
+
initial: 'active',
|
|
318
|
+
transitions: [
|
|
319
|
+
{ operation: 'actions/disable-workflow', from: ['active'], to: 'disabled_manually', source: 'https://docs.github.com/rest/actions/workflows#disable-a-workflow' },
|
|
320
|
+
{ operation: 'actions/enable-workflow', from: ['disabled_manually', 'disabled_inactivity', 'disabled_fork'], to: 'active', source: 'https://docs.github.com/rest/actions/workflows#enable-a-workflow' },
|
|
321
|
+
],
|
|
322
|
+
},
|
|
323
|
+
},
|
|
324
|
+
},
|
|
325
|
+
'workflow-run': {
|
|
326
|
+
storedAs: 'workflow_run',
|
|
327
|
+
idPrefix: 'run:',
|
|
328
|
+
parent: inRepository,
|
|
329
|
+
key: 'run:{run_id}',
|
|
330
|
+
// the result a completed run records, not a state of its own
|
|
331
|
+
notState: ['conclusion'],
|
|
332
|
+
state: {
|
|
333
|
+
// a runner finishing it is the vendor's move (the twin's runner door, /_twin/.../complete)
|
|
334
|
+
status: {
|
|
335
|
+
initial: 'queued',
|
|
336
|
+
transitions: [
|
|
337
|
+
{ operation: 'actions/re-run-workflow', from: '*', to: 'queued', source: 'https://docs.github.com/rest/actions/workflow-runs#re-run-a-workflow' },
|
|
338
|
+
{ operation: 'actions/cancel-workflow-run', from: '*', to: 'completed', source: 'https://docs.github.com/rest/actions/workflow-runs#cancel-a-workflow-run' },
|
|
339
|
+
// a first-time contributor's run from a fork waits, completed as action_required, until a maintainer approves it
|
|
340
|
+
{ operation: 'actions/approve-workflow-run', from: ['completed'], to: 'queued', source: 'https://docs.github.com/rest/actions/workflow-runs#approve-a-workflow-run-for-a-fork-pull-request' },
|
|
341
|
+
// a runner picking it up (the twin's runner door, /_twin/.../start)
|
|
342
|
+
{ actor: 'vendor', from: ['queued'], to: 'in_progress', refusal: { status: 409, message: 'The run has already started' }, source: 'https://docs.github.com/actions/about-github-actions/understanding-github-actions#runners' },
|
|
343
|
+
{ actor: 'vendor', from: ['queued', 'in_progress'], to: 'completed', refusal: { status: 409, message: 'The run has already completed' }, source: 'https://docs.github.com/actions/managing-workflow-runs-and-deployments/managing-workflow-runs/re-running-workflows-and-jobs' },
|
|
344
|
+
],
|
|
345
|
+
},
|
|
346
|
+
},
|
|
347
|
+
},
|
|
348
|
+
job: {
|
|
349
|
+
storedAs: 'workflow_job',
|
|
350
|
+
idPrefix: 'job:',
|
|
351
|
+
parent: inRepository,
|
|
352
|
+
key: 'job:{job_id}',
|
|
353
|
+
// the result a completed job records, not a state of its own
|
|
354
|
+
notState: ['conclusion'],
|
|
355
|
+
state: {
|
|
356
|
+
// a job moves with its run: by the run's rerun and cancel, and when the runner finishes the run
|
|
357
|
+
status: {
|
|
358
|
+
initial: 'queued',
|
|
359
|
+
transitions: [
|
|
360
|
+
{ operation: 'actions/re-run-workflow', from: '*', to: 'queued', source: 'https://docs.github.com/rest/actions/workflow-runs#re-run-a-workflow' },
|
|
361
|
+
{ operation: 'actions/cancel-workflow-run', from: '*', to: 'completed', source: 'https://docs.github.com/rest/actions/workflow-runs#cancel-a-workflow-run' },
|
|
362
|
+
{ actor: 'vendor', from: ['queued'], to: 'in_progress', source: 'https://docs.github.com/rest/actions/workflow-jobs#get-a-job-for-a-workflow-run' },
|
|
363
|
+
{ actor: 'vendor', from: ['queued', 'in_progress'], to: 'completed', source: 'https://docs.github.com/rest/actions/workflow-jobs#get-a-job-for-a-workflow-run' },
|
|
364
|
+
],
|
|
365
|
+
},
|
|
366
|
+
},
|
|
367
|
+
},
|
|
368
|
+
artifact: { storedAs: 'actions_artifact', idPrefix: 'artifact:', parent: inRepository, key: 'artifact:{artifact_id}' },
|
|
369
|
+
// a secret or variable is stored under its `container` (a repository, `owner/repo:env` for an
|
|
370
|
+
// environment's): one resource spans both, so no parent field names the repository alone
|
|
371
|
+
'actions-secret': { storedAs: 'actions_secret', idPrefix: 'secret:repo:' },
|
|
372
|
+
'actions-variable': { storedAs: 'actions_variable', idPrefix: 'variable:repo:' },
|
|
373
|
+
'organization-actions-secret': { storedAs: 'actions_secret', idPrefix: 'secret:org:', notState: ['visibility'] },
|
|
374
|
+
'organization-actions-variable': { storedAs: 'actions_variable', idPrefix: 'variable:org:', notState: ['visibility'] },
|
|
375
|
+
// deploy keys and autolinks (semantics/keys.ts)
|
|
376
|
+
'deploy-key': { storedAs: 'deploy_key', idPrefix: 'deploykey:', parent: inRepository, key: 'deploykey:{key_id}' },
|
|
377
|
+
// is_alphanumeric: how the prefix matches, set at creation
|
|
378
|
+
autolink: { storedAs: 'autolink', idPrefix: 'autolink:', parent: inRepository, key: 'autolink:{autolink_id}', notState: ['is_alphanumeric'] },
|
|
379
|
+
// rulesets and rule suites (semantics/rulesets.ts): enforcement is a setting an update names, any
|
|
380
|
+
// value from any value; a suite's results are the outcome it recorded
|
|
381
|
+
'repository-ruleset': { storedAs: 'ruleset', idPrefix: 'ruleset:', parent: inRepository, key: 'ruleset:{ruleset_id}', notState: ['current_user_can_bypass', 'enforcement', 'source_type', 'target'] },
|
|
382
|
+
'rule-suite': { storedAs: 'rule_suite', idPrefix: 'rulesuite:', parent: inRepository, key: 'rulesuite:{rule_suite_id}', notState: ['evaluation_result', 'result'] },
|
|
383
|
+
// deployments and environments (semantics/deployments.ts): a status is created with its state and
|
|
384
|
+
// never moves (the deployment's state is its latest status)
|
|
385
|
+
deployment: { storedAs: 'deployment', idPrefix: 'deployment:', parent: inRepository, key: 'deployment:{deployment_id}' },
|
|
386
|
+
'deployment-status': { storedAs: 'deployment_status', idPrefix: 'depstatus:', parent: inRepository, key: 'depstatus:{status_id}', notState: ['state'] },
|
|
387
|
+
environment: { storedAs: 'environment', idPrefix: 'env:', parent: inRepository, key: 'env:{owner}/{repo}#{environment_name}' },
|
|
388
|
+
// releases (semantics/releases.ts); tags are derived from published releases, never stored
|
|
389
|
+
// a release is created a draft or published; an edit publishes a draft (`draft: false`) or unpublishes
|
|
390
|
+
// it (`draft: true`), from either value as the twin always took it
|
|
391
|
+
release: {
|
|
392
|
+
storedAs: 'release',
|
|
393
|
+
idPrefix: 'release:',
|
|
394
|
+
parent: inRepository,
|
|
395
|
+
key: 'release:{release_id}',
|
|
396
|
+
state: {
|
|
397
|
+
draft: {
|
|
398
|
+
initial: false,
|
|
399
|
+
transitions: [
|
|
400
|
+
{ operation: 'repos/update-release', from: '*', to: 'false', source: 'https://docs.github.com/rest/releases/releases#update-a-release' },
|
|
401
|
+
{ operation: 'repos/update-release', from: '*', to: 'true', source: 'https://docs.github.com/rest/releases/releases#update-a-release' },
|
|
402
|
+
],
|
|
403
|
+
},
|
|
404
|
+
},
|
|
405
|
+
},
|
|
406
|
+
'release-asset': {
|
|
407
|
+
storedAs: 'release_asset',
|
|
408
|
+
idPrefix: 'asset:',
|
|
409
|
+
parent: inRepository,
|
|
410
|
+
key: 'asset:{asset_id}',
|
|
411
|
+
state: {
|
|
412
|
+
// the upload completing moves it open → uploaded on GitHub (docs.github.com/rest/releases/assets#upload-a-release-asset);
|
|
413
|
+
// the twin records an asset already uploaded, so it makes no move
|
|
414
|
+
state: { initial: 'uploaded', vendorInitial: 'open', transitions: [] },
|
|
415
|
+
},
|
|
416
|
+
},
|
|
417
|
+
// repository webhooks (semantics/webhooks.ts)
|
|
418
|
+
// active: a setting an edit names
|
|
419
|
+
hook: { storedAs: 'webhook', idPrefix: 'webhook:', parent: inRepository, key: 'webhook:{hook_id}', notState: ['active'] },
|
|
420
|
+
// labels and milestones (semantics/labels.ts): a milestone's state is set by an edit, any value
|
|
421
|
+
// from any value, as the twin always took it
|
|
422
|
+
label: { storedAs: 'label', idPrefix: 'label:', parent: inRepository },
|
|
423
|
+
milestone: {
|
|
424
|
+
storedAs: 'milestone',
|
|
425
|
+
idPrefix: 'milestone:',
|
|
426
|
+
parent: inRepository,
|
|
427
|
+
key: '{owner}/{repo}#milestone:{milestone_number}', number: { field: 'number' },
|
|
428
|
+
state: {
|
|
429
|
+
state: {
|
|
430
|
+
initial: 'open',
|
|
431
|
+
transitions: [
|
|
432
|
+
{ operation: 'issues/update-milestone', from: '*', to: 'closed', source: 'https://docs.github.com/rest/issues/milestones#update-a-milestone' },
|
|
433
|
+
{ operation: 'issues/update-milestone', from: '*', to: 'open', source: 'https://docs.github.com/rest/issues/milestones#update-a-milestone' },
|
|
434
|
+
],
|
|
435
|
+
},
|
|
436
|
+
},
|
|
437
|
+
},
|
|
438
|
+
// commit comments (semantics/commits.ts); commits are the git plane's, never stored
|
|
439
|
+
'commit-comment': { storedAs: 'commit_comment', idPrefix: 'commitcomment:', parent: inRepository, key: 'commitcomment:{comment_id}', notState: ['author_association'] },
|
|
440
|
+
// statuses and check runs (semantics/checks.ts): a caller moves a run to whatever status it posts,
|
|
441
|
+
// and a conclusion completes it; suites are derived from runs, never stored
|
|
442
|
+
// a status is created with its state and never moves (a commit's state is its latest per context)
|
|
443
|
+
status: { storedAs: 'commit_status', idPrefix: 'status:', parent: inRepository, notState: ['state'] },
|
|
444
|
+
'check-run': {
|
|
445
|
+
storedAs: 'check_run',
|
|
446
|
+
idPrefix: 'check:',
|
|
447
|
+
parent: inRepository,
|
|
448
|
+
key: 'check:{check_run_id}',
|
|
449
|
+
notState: ['conclusion'],
|
|
450
|
+
state: {
|
|
451
|
+
status: {
|
|
452
|
+
initial: 'queued',
|
|
453
|
+
transitions: [
|
|
454
|
+
{ operation: 'checks/update', from: '*', to: 'in_progress', source: 'https://docs.github.com/rest/checks/runs#update-a-check-run' },
|
|
455
|
+
{ operation: 'checks/update', from: '*', to: 'completed', source: 'https://docs.github.com/rest/checks/runs#update-a-check-run' },
|
|
456
|
+
],
|
|
457
|
+
},
|
|
458
|
+
},
|
|
459
|
+
},
|
|
460
|
+
// Git Data (semantics/git.ts): refs are rows; blobs, trees, commits and tags are objects in the git
|
|
461
|
+
// plane the surface names no resource for
|
|
462
|
+
'git-ref': { storedAs: 'git_ref', idPrefix: 'gitref:', parent: inRepository, key: 'gitref:{owner}/{repo}#refs/{ref}' },
|
|
463
|
+
// repositories, branches and collaborators (semantics/repos.ts, semantics/branches.ts): a
|
|
464
|
+
// repository's merge and squash settings are settings an edit names, not states. An edit archives
|
|
465
|
+
// a repository and unarchives it; GitHub disables one on its own (no API moves `disabled`, and the
|
|
466
|
+
// twin never does); is_template is a setting.
|
|
467
|
+
'full-repository': {
|
|
468
|
+
storedAs: 'repository',
|
|
469
|
+
idPrefix: 'repo:',
|
|
470
|
+
notState: ['disabled', 'is_template', 'merge_commit_message', 'merge_commit_title', 'pull_request_creation_policy', 'squash_merge_commit_message', 'squash_merge_commit_title'],
|
|
471
|
+
state: {
|
|
472
|
+
archived: {
|
|
473
|
+
initial: false,
|
|
474
|
+
transitions: [
|
|
475
|
+
{ operation: 'repos/update', from: '*', to: 'true', source: 'https://docs.github.com/rest/repos/repos#update-a-repository' },
|
|
476
|
+
{ operation: 'repos/update', from: '*', to: 'false', source: 'https://docs.github.com/rest/repos/repos#update-a-repository' },
|
|
477
|
+
],
|
|
478
|
+
},
|
|
479
|
+
},
|
|
480
|
+
},
|
|
481
|
+
'short-branch': { storedAs: 'branch', idPrefix: 'branch:', parent: inRepository, key: 'branch:{owner}/{repo}#{branch}' },
|
|
482
|
+
collaborator: { storedAs: 'collaborator', idPrefix: 'collab:', parent: inRepository, key: 'collab:{owner}/{repo}#{username}' },
|
|
483
|
+
// issues, their comments and reactions (semantics/issues.ts). An issue is keyed by its repository
|
|
484
|
+
// and number; its number is counted with the repository's pull requests (one sequence for both), so
|
|
485
|
+
// `number` cannot declare it. Its state moves by an edit from any value (closing defaults
|
|
486
|
+
// state_reason to completed, reopening to reopened).
|
|
487
|
+
issue: {
|
|
488
|
+
storedAs: 'issue',
|
|
489
|
+
idPrefix: 'issue:',
|
|
490
|
+
parent: inRepository,
|
|
491
|
+
key: '{owner}/{repo}#issue:{issue_number}',
|
|
492
|
+
// draft: a pull request's, which an issue answer carries for a pull request's number
|
|
493
|
+
notState: ['author_association', 'draft', 'state_reason'],
|
|
494
|
+
state: {
|
|
495
|
+
state: {
|
|
496
|
+
initial: 'open',
|
|
497
|
+
transitions: [
|
|
498
|
+
{ operation: 'issues/update', from: '*', to: 'closed', source: 'https://docs.github.com/rest/issues/issues#update-an-issue' },
|
|
499
|
+
{ operation: 'issues/update', from: '*', to: 'open', source: 'https://docs.github.com/rest/issues/issues#update-an-issue' },
|
|
500
|
+
// a pull request merged into the default branch closes the issues it links with a closing keyword, and so
|
|
501
|
+
// does a commit pushed there that names them (semantics/pulls.ts, semantics/push-reactions.ts)
|
|
502
|
+
{ operation: 'pulls/merge', from: ['open'], to: 'closed', source: 'https://docs.github.com/issues/tracking-your-work-with-issues/using-issues/linking-a-pull-request-to-an-issue' },
|
|
503
|
+
{ actor: 'external', from: ['open'], to: 'closed', source: 'https://docs.github.com/issues/tracking-your-work-with-issues/using-issues/linking-a-pull-request-to-an-issue' },
|
|
504
|
+
],
|
|
505
|
+
},
|
|
506
|
+
// locking a locked conversation (or unlocking an unlocked one) is answered 204 as any other
|
|
507
|
+
locked: {
|
|
508
|
+
initial: false,
|
|
509
|
+
transitions: [
|
|
510
|
+
{ operation: 'issues/lock', from: '*', to: 'true', source: 'https://docs.github.com/rest/issues/issues#lock-an-issue' },
|
|
511
|
+
{ operation: 'issues/unlock', from: '*', to: 'false', source: 'https://docs.github.com/rest/issues/issues#unlock-an-issue' },
|
|
512
|
+
],
|
|
513
|
+
},
|
|
514
|
+
},
|
|
515
|
+
},
|
|
516
|
+
'issue-comment': { storedAs: 'issue_comment', idPrefix: 'comment:', parent: inRepository, key: 'comment:{comment_id}', notState: ['author_association'] },
|
|
517
|
+
reaction: { storedAs: 'reaction', idPrefix: 'reaction:', parent: inRepository, key: 'reaction:{reaction_id}', notState: ['content'] },
|
|
518
|
+
'pull-request-review-comment': { storedAs: 'pull_request_review_comment', idPrefix: 'comment:', parent: inRepository, key: 'comment:{comment_id}', notState: ['author_association', 'side', 'start_side', 'subject_type'] },
|
|
519
|
+
// pull requests and reviews (semantics/pulls.ts): one machine per state field. A merge needs an open,
|
|
520
|
+
// unmerged, non-draft pull request (the handler asks ctx.legal of all three); an edit moves state
|
|
521
|
+
// from any value. Deleting the head branch closes it (git/delete-ref, on the pull request's machine).
|
|
522
|
+
// GitHub's auto-merge (GraphQL's enablePullRequestAutoMerge) lands one when its checks pass; the twin does
|
|
523
|
+
// not have it, so makes no such move. Draft moves by GraphQL alone
|
|
524
|
+
// (markPullRequestReadyForReview, convertPullRequestToDraft: another wire, `external`), which also
|
|
525
|
+
// needs it open (a merged one is closed). The conversation locks by the issue operations on its number.
|
|
526
|
+
'pull-request': {
|
|
527
|
+
storedAs: 'pull_request',
|
|
528
|
+
idPrefix: 'pr:',
|
|
529
|
+
parent: inRepository,
|
|
530
|
+
key: '{owner}/{repo}#{pull_number}',
|
|
531
|
+
notState: ['author_association'],
|
|
532
|
+
state: {
|
|
533
|
+
state: {
|
|
534
|
+
initial: 'open',
|
|
535
|
+
transitions: [
|
|
536
|
+
{ operation: 'pulls/update', from: '*', to: 'closed', source: 'https://docs.github.com/rest/pulls/pulls#update-a-pull-request' },
|
|
537
|
+
{ operation: 'pulls/update', from: '*', to: 'open', source: 'https://docs.github.com/rest/pulls/pulls#update-a-pull-request' },
|
|
538
|
+
{ operation: 'pulls/merge', from: ['open'], to: 'closed', refusal: { status: 405, message: 'Pull Request is not mergeable' }, source: 'https://docs.github.com/rest/pulls/pulls#merge-a-pull-request' },
|
|
539
|
+
{ operation: 'git/delete-ref', from: ['open'], to: 'closed', source: 'https://docs.github.com/pull-requests/collaborating-with-pull-requests/proposing-changes-to-your-work-with-pull-requests/creating-and-deleting-branches-within-your-repository#deleting-a-branch-used-for-a-pull-request' },
|
|
540
|
+
{ actor: 'external', from: ['open'], refusal: { status: 422, message: 'Pull request must be open' }, source: 'https://docs.github.com/graphql/reference/mutations#markpullrequestreadyforreview' },
|
|
541
|
+
// deleting the head branch by a git push closes it too, the git wire's (github-git-http.ts); after the
|
|
542
|
+
// guard, so an ask that names no state finds the guard
|
|
543
|
+
{ actor: 'external', from: ['open'], to: 'closed', source: 'https://docs.github.com/pull-requests/collaborating-with-pull-requests/proposing-changes-to-your-work-with-pull-requests/creating-and-deleting-branches-within-your-repository#deleting-a-branch-used-for-a-pull-request' },
|
|
544
|
+
],
|
|
545
|
+
},
|
|
546
|
+
merged: {
|
|
547
|
+
initial: false,
|
|
548
|
+
transitions: [
|
|
549
|
+
{ operation: 'pulls/merge', from: ['false'], to: 'true', refusal: { status: 405, message: 'Pull Request is not mergeable' }, source: 'https://docs.github.com/rest/pulls/pulls#merge-a-pull-request' },
|
|
550
|
+
],
|
|
551
|
+
},
|
|
552
|
+
// a guard: a draft is never merged
|
|
553
|
+
draft: {
|
|
554
|
+
initial: false,
|
|
555
|
+
transitions: [
|
|
556
|
+
{ operation: 'pulls/merge', from: ['false'], refusal: { status: 405, message: 'Draft pull requests cannot be merged.' }, source: 'https://docs.github.com/rest/pulls/pulls#merge-a-pull-request' },
|
|
557
|
+
{ actor: 'external', from: ['true'], to: 'false', refusal: { status: 422, message: 'Pull request is already ready for review' }, source: 'https://docs.github.com/graphql/reference/mutations#markpullrequestreadyforreview' },
|
|
558
|
+
{ actor: 'external', from: ['false'], to: 'true', refusal: { status: 422, message: 'Pull request is already a draft' }, source: 'https://docs.github.com/graphql/reference/mutations#convertpullrequesttodraft' },
|
|
559
|
+
],
|
|
560
|
+
},
|
|
561
|
+
locked: {
|
|
562
|
+
initial: false,
|
|
563
|
+
transitions: [
|
|
564
|
+
{ operation: 'issues/lock', from: '*', to: 'true', source: 'https://docs.github.com/rest/issues/issues#lock-an-issue' },
|
|
565
|
+
{ operation: 'issues/unlock', from: '*', to: 'false', source: 'https://docs.github.com/rest/issues/issues#unlock-an-issue' },
|
|
566
|
+
],
|
|
567
|
+
},
|
|
568
|
+
},
|
|
569
|
+
},
|
|
570
|
+
'pull-request-review': {
|
|
571
|
+
storedAs: 'pull_request_review',
|
|
572
|
+
idPrefix: 'review:',
|
|
573
|
+
parent: inRepository,
|
|
574
|
+
key: 'review:{review_id}',
|
|
575
|
+
notState: ['author_association'],
|
|
576
|
+
state: {
|
|
577
|
+
// set by the submitting event (APPROVE → APPROVED …); a dismissal overlays DISMISSED
|
|
578
|
+
state: { initial: 'COMMENTED', transitions: [{ operation: 'pulls/dismiss-review', from: '*', to: 'DISMISSED', source: 'https://docs.github.com/rest/pulls/reviews#dismiss-a-review-for-a-pull-request' }] },
|
|
579
|
+
},
|
|
580
|
+
},
|
|
581
|
+
// codespaces (semantics/codespaces.ts): start and stop move from any state, as the twin always has
|
|
582
|
+
codespace: {
|
|
583
|
+
storedAs: 'codespace',
|
|
584
|
+
idPrefix: 'codespace:',
|
|
585
|
+
notState: ['location'],
|
|
586
|
+
state: {
|
|
587
|
+
state: {
|
|
588
|
+
initial: 'Available',
|
|
589
|
+
transitions: [
|
|
590
|
+
{ operation: 'codespaces/start-for-authenticated-user', from: '*', to: 'Available', source: 'https://docs.github.com/rest/codespaces/codespaces#start-a-codespace-for-the-authenticated-user' },
|
|
591
|
+
{ operation: 'codespaces/stop-for-authenticated-user', from: '*', to: 'Shutdown', source: 'https://docs.github.com/rest/codespaces/codespaces#stop-a-codespace-for-the-authenticated-user' },
|
|
592
|
+
],
|
|
593
|
+
},
|
|
594
|
+
},
|
|
595
|
+
},
|
|
596
|
+
},
|
|
597
|
+
};
|