@foss.global/interfaces 0.13.0 → 1.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/changelog.md +28 -0
- package/dist_ts/00_commitinfo_data.js +2 -2
- package/dist_ts/data/forgesourceinventory.d.ts +336 -0
- package/dist_ts/data/forgesourceinventory.js +2 -0
- package/dist_ts/data/gitmanager.d.ts +84 -10
- package/dist_ts/data/index.d.ts +1 -0
- package/dist_ts/data/index.js +2 -1
- package/dist_ts/data/runner.d.ts +1 -1
- package/package.json +6 -6
- package/readme.md +99 -1
- package/ts/00_commitinfo_data.ts +1 -1
- package/ts/data/forgesourceinventory.ts +335 -0
- package/ts/data/gitmanager.ts +86 -10
- package/ts/data/index.ts +1 -0
package/changelog.md
CHANGED
|
@@ -1,5 +1,33 @@
|
|
|
1
1
|
# Changelog
|
|
2
2
|
|
|
3
|
+
## 2026-10-13 - 1.1.0
|
|
4
|
+
|
|
5
|
+
### Features
|
|
6
|
+
|
|
7
|
+
- add forge source inventory contracts (data)
|
|
8
|
+
- `IForgeSourceInventoryReport`: an authenticated, read-only, deterministic measurement of a source forge before its migration, with `complete`, `partial` and `notMeasured` measures as decimal strings, organization and user owner inventories with owner totals, and per-repository Git, LFS, collaboration, release (drafts, asset counts and bytes), access and Actions counts.
|
|
9
|
+
- Run units (`TForgeSourceInventoryUnit`, `TForgeSourceInventoryUnitResult`, `IForgeSourceInventoryDiscovery`) for resumable measurement, and `TForgeSourceCollisionCheck` for the native name collision check.
|
|
10
|
+
- A report never carries secret values; secrets and variables are counted, never named.
|
|
11
|
+
|
|
12
|
+
### Maintenance
|
|
13
|
+
|
|
14
|
+
- release tooling: `@git.zone/tsbuild` ^6.0.2 (TypeScript 7; the tsconfig needs no change), `@git.zone/tstest` ^7.2.1, `@git.zone/tsrun` ^3.0.3, `@git.zone/tsdoc` ^3.0.2 (its CLI moved to smartconsole; `buildDocs` is unchanged), `@types/node` ^26.6.4 and pnpm 12.10.0 (26.6.5 and pnpm 12.11.x are younger than seven days)
|
|
15
|
+
|
|
16
|
+
## 2026-09-25 - 1.0.0
|
|
17
|
+
|
|
18
|
+
### Breaking Changes
|
|
19
|
+
|
|
20
|
+
- replace the GitManager ref listing contract with a complete paginated ref inventory (gitmanager)
|
|
21
|
+
- `IGitManagerRefRequest` gains `prefixes`, `cursor`, and `limit`; without prefixes every ref under `refs/` is selected, overlapping prefixes select their de-duplicated union, an empty array is invalid, and a complete ref name as the only prefix is an exact lookup.
|
|
22
|
+
- `IGitManagerRef` now carries `name`, `objectId`, `objectType`, `peeledObjectId`, `peeledObjectType`, and `symbolicTarget`; `objectId` and `objectType` are null only for a symbolic ref whose target does not resolve. The per-ref `org`, `repo`, `shortName`, `refType`, `updatedAt`, and `subject` fields and `TGitManagerRefType` are removed.
|
|
23
|
+
- Add `TGitManagerRefInventoryResult`: an `IGitManagerRefInventoryPage` with HEAD, total count, inventory digest, and cursor pagination, or `IGitManagerRefInventoryStale` when the selected refs or HEAD changed between pages.
|
|
24
|
+
|
|
25
|
+
### Maintenance
|
|
26
|
+
|
|
27
|
+
- Update release tooling to pnpm 12.4.2, `@git.zone/tsbuild` 5.0.0, `@git.zone/tsrun` 3.0.0, `@git.zone/tstest` 6.2.0, `@git.zone/tsdoc` 2.2.2 and `@types/node` 26.6.1 (tooling)
|
|
28
|
+
- pnpm 12.5.x and `@types/node` 26.6.2 are inside the seven-day release-age window, so pnpm stays on 12.4.2 and `@types/node` on 26.6.1.
|
|
29
|
+
- No source migration is needed: no `ts*` folder carries its own `tsconfig.json` (tsbuild 5), no script reads `process.argv` (tsrun 3), and both test files end in `tap.start()` without `TapNodeTools` (tstest 5 and 6).
|
|
30
|
+
|
|
3
31
|
## 2026-09-05 - 0.13.0
|
|
4
32
|
|
|
5
33
|
### Features
|
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
*/
|
|
4
4
|
export const commitinfo = {
|
|
5
5
|
name: '@foss.global/interfaces',
|
|
6
|
-
version: '
|
|
6
|
+
version: '1.1.0',
|
|
7
7
|
description: 'Shared TypeScript interfaces and TypedRequest contracts for the foss.global Git platform ecosystem.'
|
|
8
8
|
};
|
|
9
|
-
//# sourceMappingURL=data:application/json;base64,
|
|
9
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiMDBfY29tbWl0aW5mb19kYXRhLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vdHMvMDBfY29tbWl0aW5mb19kYXRhLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQUFBOztHQUVHO0FBQ0gsTUFBTSxDQUFDLE1BQU0sVUFBVSxHQUFHO0lBQ3hCLElBQUksRUFBRSx5QkFBeUI7SUFDL0IsT0FBTyxFQUFFLE9BQU87SUFDaEIsV0FBVyxFQUFFLHFHQUFxRztDQUNuSCxDQUFBIn0=
|
|
@@ -0,0 +1,336 @@
|
|
|
1
|
+
import type { TForgeInventoryVisibility } from './forgeinventory.js';
|
|
2
|
+
/**
|
|
3
|
+
* Authenticated, read-only measurement of a source forge before its one-time
|
|
4
|
+
* migration. Unlike the caller-visible inventory in `forgeinventory.ts`, it is
|
|
5
|
+
* read with a site administrator's token and counts per owner and repository.
|
|
6
|
+
*
|
|
7
|
+
* A report never contains secret values: no credentials, tokens, private keys,
|
|
8
|
+
* Actions secret or variable values, webhook secrets, or mirror remote URLs.
|
|
9
|
+
* Secrets and variables are counted, never named in the report. Reasons are
|
|
10
|
+
* sanitized diagnostics, never raw response bodies or URLs.
|
|
11
|
+
*/
|
|
12
|
+
/** Source forges the inventory can read. */
|
|
13
|
+
export type TForgeSourceKind = 'gitea';
|
|
14
|
+
/**
|
|
15
|
+
* Values are canonical nonnegative decimal integers, retaining JSON precision.
|
|
16
|
+
* `partial` was attempted and did not finish (a resumed run retries it);
|
|
17
|
+
* `notMeasured` was not attempted, for example because no read exists yet.
|
|
18
|
+
*/
|
|
19
|
+
export type TForgeSourceMeasure = {
|
|
20
|
+
status: 'complete';
|
|
21
|
+
value: string;
|
|
22
|
+
} | {
|
|
23
|
+
status: 'partial';
|
|
24
|
+
observedValue: string;
|
|
25
|
+
reason: string;
|
|
26
|
+
} | {
|
|
27
|
+
status: 'notMeasured';
|
|
28
|
+
reason: string;
|
|
29
|
+
};
|
|
30
|
+
export interface IForgeSourceIdentity {
|
|
31
|
+
/** Operator-assigned identity retained when the instance URL changes. */
|
|
32
|
+
instanceId: string;
|
|
33
|
+
kind: TForgeSourceKind;
|
|
34
|
+
/** Origin and path prefix only; never carries credentials. */
|
|
35
|
+
baseUrl: string;
|
|
36
|
+
version: string;
|
|
37
|
+
}
|
|
38
|
+
/** The account whose token read the source; an inventory requires a site administrator. */
|
|
39
|
+
export interface IForgeSourceReader {
|
|
40
|
+
login: string;
|
|
41
|
+
siteAdmin: boolean;
|
|
42
|
+
}
|
|
43
|
+
export interface IForgeSourceUserCounts {
|
|
44
|
+
total: TForgeSourceMeasure;
|
|
45
|
+
active: TForgeSourceMeasure;
|
|
46
|
+
admins: TForgeSourceMeasure;
|
|
47
|
+
restricted: TForgeSourceMeasure;
|
|
48
|
+
prohibitLogin: TForgeSourceMeasure;
|
|
49
|
+
/** Users authenticated through an external source such as LDAP or OAuth2. */
|
|
50
|
+
externalAuth: TForgeSourceMeasure;
|
|
51
|
+
twoFactor: TForgeSourceMeasure;
|
|
52
|
+
}
|
|
53
|
+
export interface IForgeSourceInstanceInventory {
|
|
54
|
+
users: IForgeSourceUserCounts;
|
|
55
|
+
organizations: TForgeSourceMeasure;
|
|
56
|
+
/** System and default webhooks. */
|
|
57
|
+
systemWebhooks: TForgeSourceMeasure;
|
|
58
|
+
/** Instance-scoped Actions runners; their registrations are reissued. */
|
|
59
|
+
runners: TForgeSourceMeasure;
|
|
60
|
+
/** Repositories on disk that the forge database does not know. */
|
|
61
|
+
unadoptedRepositories: TForgeSourceMeasure;
|
|
62
|
+
}
|
|
63
|
+
export interface IForgeSourcePackageTypeCounts {
|
|
64
|
+
/** Provider package type, such as `npm`, `generic` or `container`. */
|
|
65
|
+
type: string;
|
|
66
|
+
packages: TForgeSourceMeasure;
|
|
67
|
+
versions: TForgeSourceMeasure;
|
|
68
|
+
files: TForgeSourceMeasure;
|
|
69
|
+
bytes: TForgeSourceMeasure;
|
|
70
|
+
}
|
|
71
|
+
export interface IForgeSourceUserAccount {
|
|
72
|
+
admin: boolean;
|
|
73
|
+
active: boolean;
|
|
74
|
+
restricted: boolean;
|
|
75
|
+
prohibitLogin: boolean;
|
|
76
|
+
externalAuth: boolean;
|
|
77
|
+
}
|
|
78
|
+
export interface IForgeSourceOwnerInventoryBase {
|
|
79
|
+
name: string;
|
|
80
|
+
/** Provider row id as a decimal string. */
|
|
81
|
+
id: string;
|
|
82
|
+
visibility: TForgeInventoryVisibility;
|
|
83
|
+
repositories: TForgeSourceMeasure;
|
|
84
|
+
webhooks: TForgeSourceMeasure;
|
|
85
|
+
actionsVariables: TForgeSourceMeasure;
|
|
86
|
+
runners: TForgeSourceMeasure;
|
|
87
|
+
/** Sorted by type. */
|
|
88
|
+
packages: IForgeSourcePackageTypeCounts[];
|
|
89
|
+
}
|
|
90
|
+
export interface IForgeSourceOrganizationInventory extends IForgeSourceOwnerInventoryBase {
|
|
91
|
+
kind: 'organization';
|
|
92
|
+
members: TForgeSourceMeasure;
|
|
93
|
+
teams: TForgeSourceMeasure;
|
|
94
|
+
teamMemberships: TForgeSourceMeasure;
|
|
95
|
+
teamRepositoryGrants: TForgeSourceMeasure;
|
|
96
|
+
labels: TForgeSourceMeasure;
|
|
97
|
+
actionsSecrets: TForgeSourceMeasure;
|
|
98
|
+
}
|
|
99
|
+
/** User-scoped Actions secrets have no list read; see `IForgeSourceInventory.limitations`. */
|
|
100
|
+
export interface IForgeSourceUserInventory extends IForgeSourceOwnerInventoryBase {
|
|
101
|
+
kind: 'user';
|
|
102
|
+
account: IForgeSourceUserAccount;
|
|
103
|
+
sshKeys: TForgeSourceMeasure;
|
|
104
|
+
gpgKeys: TForgeSourceMeasure;
|
|
105
|
+
}
|
|
106
|
+
export type TForgeSourceOwnerInventory = IForgeSourceOrganizationInventory | IForgeSourceUserInventory;
|
|
107
|
+
/** Owner-level settings summed over every owner; repository settings are summed separately. */
|
|
108
|
+
export interface IForgeSourceOwnerTotals {
|
|
109
|
+
webhooks: TForgeSourceMeasure;
|
|
110
|
+
actionsSecrets: TForgeSourceMeasure;
|
|
111
|
+
actionsVariables: TForgeSourceMeasure;
|
|
112
|
+
runners: TForgeSourceMeasure;
|
|
113
|
+
members: TForgeSourceMeasure;
|
|
114
|
+
teams: TForgeSourceMeasure;
|
|
115
|
+
teamMemberships: TForgeSourceMeasure;
|
|
116
|
+
teamRepositoryGrants: TForgeSourceMeasure;
|
|
117
|
+
labels: TForgeSourceMeasure;
|
|
118
|
+
sshKeys: TForgeSourceMeasure;
|
|
119
|
+
gpgKeys: TForgeSourceMeasure;
|
|
120
|
+
}
|
|
121
|
+
export interface IForgeSourceGitCounts {
|
|
122
|
+
/** As reported by the forge, in KiB; not a transfer size. */
|
|
123
|
+
reportedSizeKiB: TForgeSourceMeasure;
|
|
124
|
+
branches: TForgeSourceMeasure;
|
|
125
|
+
tags: TForgeSourceMeasure;
|
|
126
|
+
/** Hidden refs that preserve pull request heads. */
|
|
127
|
+
pullRequestRefs: TForgeSourceMeasure;
|
|
128
|
+
otherRefs: TForgeSourceMeasure;
|
|
129
|
+
}
|
|
130
|
+
export interface IForgeSourceLfsCounts {
|
|
131
|
+
objects: TForgeSourceMeasure;
|
|
132
|
+
bytes: TForgeSourceMeasure;
|
|
133
|
+
}
|
|
134
|
+
export interface IForgeSourceCollaborationCounts {
|
|
135
|
+
issues: TForgeSourceMeasure;
|
|
136
|
+
pullRequests: TForgeSourceMeasure;
|
|
137
|
+
/** Conversation comments on issues and pull requests. */
|
|
138
|
+
comments: TForgeSourceMeasure;
|
|
139
|
+
reviews: TForgeSourceMeasure;
|
|
140
|
+
reviewComments: TForgeSourceMeasure;
|
|
141
|
+
labels: TForgeSourceMeasure;
|
|
142
|
+
milestones: TForgeSourceMeasure;
|
|
143
|
+
/** Reactions on issues, pull requests and their comments. */
|
|
144
|
+
reactions: TForgeSourceMeasure;
|
|
145
|
+
/** Files attached to issues, pull requests and their comments. */
|
|
146
|
+
attachments: TForgeSourceMeasure;
|
|
147
|
+
attachmentBytes: TForgeSourceMeasure;
|
|
148
|
+
}
|
|
149
|
+
export interface IForgeSourceReleaseCounts {
|
|
150
|
+
/** Includes drafts and prereleases. */
|
|
151
|
+
releases: TForgeSourceMeasure;
|
|
152
|
+
drafts: TForgeSourceMeasure;
|
|
153
|
+
assets: TForgeSourceMeasure;
|
|
154
|
+
assetBytes: TForgeSourceMeasure;
|
|
155
|
+
}
|
|
156
|
+
export interface IForgeSourceAccessCounts {
|
|
157
|
+
collaborators: TForgeSourceMeasure;
|
|
158
|
+
teams: TForgeSourceMeasure;
|
|
159
|
+
deployKeys: TForgeSourceMeasure;
|
|
160
|
+
webhooks: TForgeSourceMeasure;
|
|
161
|
+
branchProtections: TForgeSourceMeasure;
|
|
162
|
+
tagProtections: TForgeSourceMeasure;
|
|
163
|
+
/** Push mirror configurations; their remote credentials are reissued. */
|
|
164
|
+
pushMirrors: TForgeSourceMeasure;
|
|
165
|
+
}
|
|
166
|
+
export interface IForgeSourceActionsCounts {
|
|
167
|
+
/** Workflow files on the default branch. */
|
|
168
|
+
workflows: TForgeSourceMeasure;
|
|
169
|
+
secrets: TForgeSourceMeasure;
|
|
170
|
+
variables: TForgeSourceMeasure;
|
|
171
|
+
runners: TForgeSourceMeasure;
|
|
172
|
+
/** Run history and artifacts are archived, not migrated; counted to size the archive. */
|
|
173
|
+
runs: TForgeSourceMeasure;
|
|
174
|
+
artifacts: TForgeSourceMeasure;
|
|
175
|
+
artifactBytes: TForgeSourceMeasure;
|
|
176
|
+
}
|
|
177
|
+
/** Repository units the forge enables. */
|
|
178
|
+
export interface IForgeSourceRepositoryFeatures {
|
|
179
|
+
issues: boolean;
|
|
180
|
+
pullRequests: boolean;
|
|
181
|
+
wiki: boolean;
|
|
182
|
+
releases: boolean;
|
|
183
|
+
packages: boolean;
|
|
184
|
+
actions: boolean;
|
|
185
|
+
projects: boolean;
|
|
186
|
+
}
|
|
187
|
+
export interface IForgeSourceRepositoryInventory {
|
|
188
|
+
owner: string;
|
|
189
|
+
name: string;
|
|
190
|
+
id: string;
|
|
191
|
+
visibility: TForgeInventoryVisibility;
|
|
192
|
+
fork: boolean;
|
|
193
|
+
/** `owner/name` of the fork parent, or null. */
|
|
194
|
+
parent: string | null;
|
|
195
|
+
mirror: boolean;
|
|
196
|
+
template: boolean;
|
|
197
|
+
archived: boolean;
|
|
198
|
+
empty: boolean;
|
|
199
|
+
/** Git object format such as `sha1` or `sha256`. */
|
|
200
|
+
objectFormat: string;
|
|
201
|
+
defaultBranch: string;
|
|
202
|
+
features: IForgeSourceRepositoryFeatures;
|
|
203
|
+
git: IForgeSourceGitCounts;
|
|
204
|
+
lfs: IForgeSourceLfsCounts;
|
|
205
|
+
collaboration: IForgeSourceCollaborationCounts;
|
|
206
|
+
releases: IForgeSourceReleaseCounts;
|
|
207
|
+
wikiPages: TForgeSourceMeasure;
|
|
208
|
+
access: IForgeSourceAccessCounts;
|
|
209
|
+
actions: IForgeSourceActionsCounts;
|
|
210
|
+
}
|
|
211
|
+
export interface IForgeSourceRepositoryTotals {
|
|
212
|
+
total: TForgeSourceMeasure;
|
|
213
|
+
private: TForgeSourceMeasure;
|
|
214
|
+
internal: TForgeSourceMeasure;
|
|
215
|
+
forks: TForgeSourceMeasure;
|
|
216
|
+
mirrors: TForgeSourceMeasure;
|
|
217
|
+
templates: TForgeSourceMeasure;
|
|
218
|
+
archived: TForgeSourceMeasure;
|
|
219
|
+
empty: TForgeSourceMeasure;
|
|
220
|
+
withWiki: TForgeSourceMeasure;
|
|
221
|
+
}
|
|
222
|
+
/**
|
|
223
|
+
* Sums over every owner and repository; a sum is complete only when every
|
|
224
|
+
* addend is. Repository-shaped groups sum repositories only.
|
|
225
|
+
*/
|
|
226
|
+
export interface IForgeSourceInventoryTotals {
|
|
227
|
+
organizations: TForgeSourceMeasure;
|
|
228
|
+
users: TForgeSourceMeasure;
|
|
229
|
+
repositories: IForgeSourceRepositoryTotals;
|
|
230
|
+
git: IForgeSourceGitCounts;
|
|
231
|
+
lfs: IForgeSourceLfsCounts;
|
|
232
|
+
collaboration: IForgeSourceCollaborationCounts;
|
|
233
|
+
releases: IForgeSourceReleaseCounts;
|
|
234
|
+
wikiPages: TForgeSourceMeasure;
|
|
235
|
+
access: IForgeSourceAccessCounts;
|
|
236
|
+
actions: IForgeSourceActionsCounts;
|
|
237
|
+
owners: IForgeSourceOwnerTotals;
|
|
238
|
+
/** Sorted by type. */
|
|
239
|
+
packages: IForgeSourcePackageTypeCounts[];
|
|
240
|
+
}
|
|
241
|
+
export interface IForgeSourceInventoryGenerator {
|
|
242
|
+
package: string;
|
|
243
|
+
version: string;
|
|
244
|
+
}
|
|
245
|
+
/**
|
|
246
|
+
* The deterministic measurement of one source: the same source state yields
|
|
247
|
+
* the same document. It carries no timestamps; run times belong to the run.
|
|
248
|
+
* Owners sort by kind then name, repositories by owner then name, and reason
|
|
249
|
+
* lists by code-unit order.
|
|
250
|
+
*/
|
|
251
|
+
export interface IForgeSourceInventory {
|
|
252
|
+
generators: IForgeSourceInventoryGenerator[];
|
|
253
|
+
source: IForgeSourceIdentity;
|
|
254
|
+
reader: IForgeSourceReader;
|
|
255
|
+
/** True only when discovery finished and no measure is partial or not measured. */
|
|
256
|
+
inventoryComplete: boolean;
|
|
257
|
+
incompleteReasons: string[];
|
|
258
|
+
/**
|
|
259
|
+
* Source data that the migration reissues rather than copies and that the
|
|
260
|
+
* provider exposes to no administrator read, such as user-scoped Actions
|
|
261
|
+
* secrets on Gitea. Nothing that is migrated may be listed here instead of
|
|
262
|
+
* being measured.
|
|
263
|
+
*/
|
|
264
|
+
limitations: string[];
|
|
265
|
+
instance: IForgeSourceInstanceInventory;
|
|
266
|
+
owners: TForgeSourceOwnerInventory[];
|
|
267
|
+
repositories: IForgeSourceRepositoryInventory[];
|
|
268
|
+
totals: IForgeSourceInventoryTotals;
|
|
269
|
+
}
|
|
270
|
+
/** A source name that already exists natively and would block an import under that name. */
|
|
271
|
+
export interface IForgeSourceCollision {
|
|
272
|
+
subject: 'owner' | 'repository';
|
|
273
|
+
/** `owner` or `owner/name` at the source. */
|
|
274
|
+
source: string;
|
|
275
|
+
/** The existing native name. */
|
|
276
|
+
native: string;
|
|
277
|
+
nativeKind: 'namespace' | 'repository' | 'user';
|
|
278
|
+
match: 'exact' | 'caseInsensitive';
|
|
279
|
+
}
|
|
280
|
+
export type TForgeSourceCollisionCheck = {
|
|
281
|
+
status: 'checked';
|
|
282
|
+
collisions: IForgeSourceCollision[];
|
|
283
|
+
} | {
|
|
284
|
+
status: 'notChecked';
|
|
285
|
+
reason: string;
|
|
286
|
+
};
|
|
287
|
+
/**
|
|
288
|
+
* A report is a complete basis for migration planning only when
|
|
289
|
+
* `inventoryComplete` is true and the collision check ran. Collisions sort by
|
|
290
|
+
* subject, then source, then native name.
|
|
291
|
+
*/
|
|
292
|
+
export interface IForgeSourceInventoryReport extends IForgeSourceInventory {
|
|
293
|
+
collisionCheck: TForgeSourceCollisionCheck;
|
|
294
|
+
}
|
|
295
|
+
/** The complete list of what a run measures, read before any unit. */
|
|
296
|
+
export interface IForgeSourceInventoryDiscovery {
|
|
297
|
+
source: IForgeSourceIdentity;
|
|
298
|
+
reader: IForgeSourceReader;
|
|
299
|
+
owners: Array<{
|
|
300
|
+
kind: 'organization' | 'user';
|
|
301
|
+
name: string;
|
|
302
|
+
}>;
|
|
303
|
+
repositories: Array<{
|
|
304
|
+
owner: string;
|
|
305
|
+
name: string;
|
|
306
|
+
}>;
|
|
307
|
+
/** Non-empty when discovery could not finish; such a run can never be complete. */
|
|
308
|
+
incompleteReasons: string[];
|
|
309
|
+
}
|
|
310
|
+
/** One independently measured and resumable part of a run. */
|
|
311
|
+
export type TForgeSourceInventoryUnit = {
|
|
312
|
+
kind: 'instance';
|
|
313
|
+
} | {
|
|
314
|
+
kind: 'owner';
|
|
315
|
+
ownerKind: 'organization' | 'user';
|
|
316
|
+
name: string;
|
|
317
|
+
} | {
|
|
318
|
+
kind: 'repository';
|
|
319
|
+
owner: string;
|
|
320
|
+
name: string;
|
|
321
|
+
};
|
|
322
|
+
/** A failed unit, or one holding a partial measure, is measured again when a run resumes. */
|
|
323
|
+
export type TForgeSourceInventoryUnitResult = {
|
|
324
|
+
kind: 'instance';
|
|
325
|
+
instance: IForgeSourceInstanceInventory;
|
|
326
|
+
} | {
|
|
327
|
+
kind: 'owner';
|
|
328
|
+
owner: TForgeSourceOwnerInventory;
|
|
329
|
+
} | {
|
|
330
|
+
kind: 'repository';
|
|
331
|
+
repository: IForgeSourceRepositoryInventory;
|
|
332
|
+
} | {
|
|
333
|
+
kind: 'failed';
|
|
334
|
+
unit: TForgeSourceInventoryUnit;
|
|
335
|
+
reason: string;
|
|
336
|
+
};
|
|
@@ -1,4 +1,3 @@
|
|
|
1
|
-
export type TGitManagerRefType = 'branch' | 'tag' | 'other';
|
|
2
1
|
export type TGitManagerObjectType = 'blob' | 'tree' | 'commit' | 'tag' | 'other';
|
|
3
2
|
export type TGitManagerTreeEntryType = 'file' | 'dir' | 'symlink' | 'submodule' | 'other';
|
|
4
3
|
export type TGitManagerDiffFileStatus = 'added' | 'modified' | 'deleted' | 'renamed' | 'copied' | 'typechange' | 'unmerged' | 'unknown';
|
|
@@ -18,17 +17,92 @@ export interface IGitManagerInitBareRepositoryRequest extends IGitManagerReposit
|
|
|
18
17
|
export interface IGitManagerImportMirrorRequest extends IGitManagerRepositorySelector {
|
|
19
18
|
remoteUrl: string;
|
|
20
19
|
}
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
20
|
+
/**
|
|
21
|
+
* One page request of a repository's complete ref inventory.
|
|
22
|
+
*
|
|
23
|
+
* Without `prefixes`, every ref under `refs/` is listed: branches, tags, and
|
|
24
|
+
* all other namespaces such as `refs/notes/*`, `refs/pull/*`,
|
|
25
|
+
* `refs/keep-around/*`, and provider-internal refs. A prefix selects refs on
|
|
26
|
+
* full path components: `refs/heads/` selects every branch, and a complete
|
|
27
|
+
* ref name such as `refs/heads/main` selects exactly that ref.
|
|
28
|
+
*/
|
|
30
29
|
export interface IGitManagerRefRequest extends IGitManagerRepositorySelector {
|
|
30
|
+
/**
|
|
31
|
+
* `refs/`-rooted prefixes; omit to list every ref. An empty array is
|
|
32
|
+
* rejected as invalid. Overlapping prefixes select the de-duplicated union,
|
|
33
|
+
* so each ref appears once.
|
|
34
|
+
*/
|
|
35
|
+
prefixes?: string[];
|
|
36
|
+
/** Opaque cursor from the preceding page; omit to start a new inventory. */
|
|
37
|
+
cursor?: string;
|
|
38
|
+
/** Maximum refs in this page. The engine owns the default and maximum. */
|
|
39
|
+
limit?: number;
|
|
31
40
|
}
|
|
41
|
+
export interface IGitManagerRef {
|
|
42
|
+
/** Full ref name, for example `refs/heads/main`. */
|
|
43
|
+
name: string;
|
|
44
|
+
/**
|
|
45
|
+
* Object the ref points at; for a symbolic ref, the object its target
|
|
46
|
+
* resolves to. Null only for a symbolic ref whose target does not resolve,
|
|
47
|
+
* such as `refs/remotes/origin/HEAD` pointing at a deleted branch; such refs
|
|
48
|
+
* are listed, never dropped.
|
|
49
|
+
*/
|
|
50
|
+
objectId: string | null;
|
|
51
|
+
/** Type of `objectId`; null exactly when `objectId` is null. */
|
|
52
|
+
objectType: TGitManagerObjectType | null;
|
|
53
|
+
/** Fully peeled object for annotated tags, including nested tags; otherwise null. */
|
|
54
|
+
peeledObjectId: string | null;
|
|
55
|
+
peeledObjectType: TGitManagerObjectType | null;
|
|
56
|
+
/** Target ref name when this ref is symbolic; otherwise null. */
|
|
57
|
+
symbolicTarget: string | null;
|
|
58
|
+
}
|
|
59
|
+
/** Repository HEAD, which is reported separately and never listed in `refs`. */
|
|
60
|
+
export interface IGitManagerRefHead {
|
|
61
|
+
/** Target ref name when HEAD is symbolic; null when detached. */
|
|
62
|
+
symbolicTarget: string | null;
|
|
63
|
+
/** Resolved object; null when HEAD points at an unborn branch. */
|
|
64
|
+
objectId: string | null;
|
|
65
|
+
}
|
|
66
|
+
export type TGitManagerRefInventoryPagination = {
|
|
67
|
+
status: 'more';
|
|
68
|
+
cursor: string;
|
|
69
|
+
} | {
|
|
70
|
+
status: 'exhausted';
|
|
71
|
+
};
|
|
72
|
+
/**
|
|
73
|
+
* A coherent page of the selected ref inventory, sorted by ref name in byte
|
|
74
|
+
* order. Every page carries the digest of the complete selection it was cut
|
|
75
|
+
* from; a cursor is honoured only while that digest is unchanged, so pages of
|
|
76
|
+
* one inventory never mix two ref states.
|
|
77
|
+
*
|
|
78
|
+
* `inventoryDigest` is the lowercase hex SHA-256 over the UTF-8 bytes of
|
|
79
|
+
* `HEAD\0<head.symbolicTarget or empty>\0<head.objectId or empty>\n` followed
|
|
80
|
+
* by `<name>\0<objectId or empty>\0<symbolicTarget or empty>\n` for each
|
|
81
|
+
* selected ref in ref-name byte order over the complete selection. Peeled
|
|
82
|
+
* values and object types follow from the object IDs and are not part of the
|
|
83
|
+
* digest.
|
|
84
|
+
*/
|
|
85
|
+
export interface IGitManagerRefInventoryPage extends IGitManagerRepositorySelector {
|
|
86
|
+
status: 'page';
|
|
87
|
+
inventoryDigest: string;
|
|
88
|
+
/** Number of refs in the complete selection, not in this page. */
|
|
89
|
+
refCount: number;
|
|
90
|
+
head: IGitManagerRefHead;
|
|
91
|
+
refs: IGitManagerRef[];
|
|
92
|
+
pagination: TGitManagerRefInventoryPagination;
|
|
93
|
+
}
|
|
94
|
+
/**
|
|
95
|
+
* The selected refs or HEAD changed since the cursor was issued. The caller
|
|
96
|
+
* restarts the inventory without a cursor; no partial page is returned.
|
|
97
|
+
*/
|
|
98
|
+
export interface IGitManagerRefInventoryStale extends IGitManagerRepositorySelector {
|
|
99
|
+
status: 'stale';
|
|
100
|
+
/** Digest bound to the rejected cursor. */
|
|
101
|
+
expectedInventoryDigest: string;
|
|
102
|
+
/** Digest of the current selection. */
|
|
103
|
+
inventoryDigest: string;
|
|
104
|
+
}
|
|
105
|
+
export type TGitManagerRefInventoryResult = IGitManagerRefInventoryPage | IGitManagerRefInventoryStale;
|
|
32
106
|
export type TGitManagerMergeMethod = 'merge' | 'squash' | 'rebase';
|
|
33
107
|
export type TGitManagerMergeStatus = 'merged' | 'already_merged' | 'conflicting' | 'stale';
|
|
34
108
|
export interface IGitManagerMergeRequest extends IGitManagerRepositorySelector {
|
package/dist_ts/data/index.d.ts
CHANGED
package/dist_ts/data/index.js
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
export * from './codefeed.js';
|
|
2
2
|
export * from './forgeinventory.js';
|
|
3
|
+
export * from './forgesourceinventory.js';
|
|
3
4
|
export * from './gitmanager.js';
|
|
4
5
|
export * from './public.js';
|
|
5
6
|
export * from './runner.js';
|
|
6
|
-
//# sourceMappingURL=data:application/json;base64,
|
|
7
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiaW5kZXguanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi90cy9kYXRhL2luZGV4LnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQUFBLGNBQWMsZUFBZSxDQUFDO0FBQzlCLGNBQWMscUJBQXFCLENBQUM7QUFDcEMsY0FBYywyQkFBMkIsQ0FBQztBQUMxQyxjQUFjLGlCQUFpQixDQUFDO0FBQ2hDLGNBQWMsYUFBYSxDQUFDO0FBQzVCLGNBQWMsYUFBYSxDQUFDIn0=
|
package/dist_ts/data/runner.d.ts
CHANGED
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@foss.global/interfaces",
|
|
3
|
-
"version": "
|
|
3
|
+
"version": "1.1.0",
|
|
4
4
|
"private": false,
|
|
5
5
|
"description": "Shared TypeScript interfaces and TypedRequest contracts for the foss.global Git platform ecosystem.",
|
|
6
6
|
"exports": {
|
|
@@ -13,11 +13,11 @@
|
|
|
13
13
|
"@api.global/typedrequest-interfaces": "^7.1.0"
|
|
14
14
|
},
|
|
15
15
|
"devDependencies": {
|
|
16
|
-
"@git.zone/tsbuild": "^
|
|
17
|
-
"@git.zone/tsdoc": "^
|
|
18
|
-
"@git.zone/tsrun": "^
|
|
19
|
-
"@git.zone/tstest": "^
|
|
20
|
-
"@types/node": "^26.4
|
|
16
|
+
"@git.zone/tsbuild": "^6.0.2",
|
|
17
|
+
"@git.zone/tsdoc": "^3.0.2",
|
|
18
|
+
"@git.zone/tsrun": "^3.0.3",
|
|
19
|
+
"@git.zone/tstest": "^7.2.1",
|
|
20
|
+
"@types/node": "^26.6.4"
|
|
21
21
|
},
|
|
22
22
|
"files": [
|
|
23
23
|
"ts/**/*",
|
package/readme.md
CHANGED
|
@@ -95,6 +95,64 @@ The runner lifecycle contracts cover registration, sessions, runner and job hear
|
|
|
95
95
|
|
|
96
96
|
Protocol v1 describes OCI execution with Docker or Podman and `tar.gz` source archives. Artifacts, caches, and service containers are explicitly unsupported in the v1 capability shape. Supported job network modes are `none` and `bridge`; the execution service remains responsible for enforcing the advertised capability.
|
|
97
97
|
|
|
98
|
+
### GitManager ref inventory contracts
|
|
99
|
+
|
|
100
|
+
`IGitManagerRefRequest`, `IGitManagerRef`, and `TGitManagerRefInventoryResult`
|
|
101
|
+
describe a complete, paginated ref inventory. Without `prefixes`, every ref
|
|
102
|
+
under `refs/` is listed, including notes, pull, keep-around, and
|
|
103
|
+
provider-internal namespaces. HEAD is reported separately in `head`. Annotated
|
|
104
|
+
tags carry their fully peeled object. Symbolic refs carry their target ref
|
|
105
|
+
name; a symbolic ref whose target does not resolve is still listed, with a null
|
|
106
|
+
`objectId` and `objectType`.
|
|
107
|
+
|
|
108
|
+
```ts
|
|
109
|
+
import type {
|
|
110
|
+
IGitManagerRef,
|
|
111
|
+
IGitManagerRefRequest,
|
|
112
|
+
TGitManagerRefInventoryResult,
|
|
113
|
+
} from '@foss.global/interfaces';
|
|
114
|
+
|
|
115
|
+
declare function listRefs(
|
|
116
|
+
request: IGitManagerRefRequest,
|
|
117
|
+
): Promise<TGitManagerRefInventoryResult>;
|
|
118
|
+
|
|
119
|
+
const collectRefs = async (): Promise<IGitManagerRef[]> => {
|
|
120
|
+
const refs: IGitManagerRef[] = [];
|
|
121
|
+
let cursor: string | undefined;
|
|
122
|
+
while (true) {
|
|
123
|
+
const result = await listRefs({ org: 'foss.global', repo: 'interfaces', cursor });
|
|
124
|
+
if (result.status === 'stale') {
|
|
125
|
+
refs.length = 0;
|
|
126
|
+
cursor = undefined;
|
|
127
|
+
continue;
|
|
128
|
+
}
|
|
129
|
+
refs.push(...result.refs);
|
|
130
|
+
if (result.pagination.status === 'exhausted') {
|
|
131
|
+
return refs;
|
|
132
|
+
}
|
|
133
|
+
cursor = result.pagination.cursor;
|
|
134
|
+
}
|
|
135
|
+
};
|
|
136
|
+
|
|
137
|
+
// A complete ref name as the only prefix is an exact lookup.
|
|
138
|
+
const main = await listRefs({
|
|
139
|
+
org: 'foss.global',
|
|
140
|
+
repo: 'interfaces',
|
|
141
|
+
prefixes: ['refs/heads/main'],
|
|
142
|
+
});
|
|
143
|
+
```
|
|
144
|
+
|
|
145
|
+
Prefixes match whole path components, so `refs/heads/ma` does not select
|
|
146
|
+
`refs/heads/main`. Overlapping prefixes select their de-duplicated union, and
|
|
147
|
+
an empty `prefixes` array is rejected as invalid. Pages are sorted by ref name
|
|
148
|
+
in byte order and each carries `inventoryDigest`, the SHA-256 of the complete
|
|
149
|
+
selection defined on `IGitManagerRefInventoryPage`. A cursor is opaque and
|
|
150
|
+
bound to the repository, the prefix set, and that digest. When the selected
|
|
151
|
+
refs or HEAD change between pages, the next call returns `status: 'stale'`
|
|
152
|
+
instead of a page that would mix two states; the caller restarts without a
|
|
153
|
+
cursor. A cursor is a transport continuation, not a durable replication
|
|
154
|
+
checkpoint.
|
|
155
|
+
|
|
98
156
|
### Forge inventory contracts
|
|
99
157
|
|
|
100
158
|
`IForgeInventoryReport`, `IForgeInventoryPage<TItem>`, `IForgeInventoryNamespace`,
|
|
@@ -131,9 +189,49 @@ scope consistency, capability/result agreement, cursor binding, diagnostics, and
|
|
|
131
189
|
authorization. These DTOs do not establish replication authority, historical
|
|
132
190
|
import fidelity, checksummed manifests, or durable recovery checkpoints.
|
|
133
191
|
|
|
192
|
+
### Forge source inventory contracts
|
|
193
|
+
|
|
194
|
+
`IForgeSourceInventoryReport` is the authenticated, read-only measurement of a
|
|
195
|
+
source forge before its one-time migration, read with a site administrator's
|
|
196
|
+
token. It counts users, organizations, teams, memberships, keys, packages by
|
|
197
|
+
type, and per repository the Git refs, LFS objects, issues, pull requests,
|
|
198
|
+
comments, reviews, reactions, attachments, releases (drafts included) with
|
|
199
|
+
asset bytes, wiki pages, access settings, webhooks, push mirrors, Actions
|
|
200
|
+
settings, and the Actions runs and artifacts that are archived rather than
|
|
201
|
+
migrated.
|
|
202
|
+
|
|
203
|
+
Every count is a `TForgeSourceMeasure`: `complete` with a decimal-string value,
|
|
204
|
+
`partial` with the value observed before a retryable failure, or `notMeasured`
|
|
205
|
+
when no read was attempted. `inventoryComplete` is true only when discovery
|
|
206
|
+
finished and no measure is partial or not measured; `incompleteReasons` lists
|
|
207
|
+
why not. `limitations` names source data the provider exposes to no
|
|
208
|
+
administrator read and that is reissued rather than migrated, such as Gitea's
|
|
209
|
+
user-scoped Actions secrets; everything readable is a measure instead.
|
|
210
|
+
Reasons are sanitized text, never raw response bodies or URLs.
|
|
211
|
+
|
|
212
|
+
Owners are a `TForgeSourceOwnerInventory` union: an organization carries its
|
|
213
|
+
members, teams, team memberships and repository grants, labels and Actions
|
|
214
|
+
secret count; a user carries its account flags and SSH and GPG key counts.
|
|
215
|
+
Both carry repositories, webhooks, Actions variables, runners and packages by
|
|
216
|
+
type. `totals.owners` sums the owner-level counts; the repository-shaped totals
|
|
217
|
+
sum repositories only.
|
|
218
|
+
|
|
219
|
+
A run first reads `IForgeSourceInventoryDiscovery`, then measures independent
|
|
220
|
+
`TForgeSourceInventoryUnit`s (the instance, each owner and each repository). A
|
|
221
|
+
failed unit, or one holding a partial measure, is measured again on resume.
|
|
222
|
+
`IForgeSourceInventory` is deterministic: it carries no timestamps, owners sort
|
|
223
|
+
by kind and name, repositories by owner and name. The report adds
|
|
224
|
+
`collisionCheck`, the source owner and repository names that already exist
|
|
225
|
+
natively, exactly or case-insensitively, sorted by subject, source and native
|
|
226
|
+
name. A report is a complete planning basis only when `inventoryComplete` is
|
|
227
|
+
true and the collision check ran.
|
|
228
|
+
|
|
229
|
+
A report never contains secret values, credentials, tokens, private keys,
|
|
230
|
+
Actions secret or variable values, webhook secrets, or mirror remote URLs.
|
|
231
|
+
|
|
134
232
|
## Exports
|
|
135
233
|
|
|
136
|
-
- `data`: public DTOs for users, organizations, repositories, contents, commits, diffs, releases, issues, activity, news, stats, codefeed commit results, GitManager repository/read API results, and runner/CI contracts.
|
|
234
|
+
- `data`: public DTOs for users, organizations, repositories, contents, commits, diffs, releases, issues, activity, news, stats, codefeed commit results, GitManager repository/read API results, forge and forge source inventories, and runner/CI contracts.
|
|
137
235
|
- `requests`: TypedRequest contracts for `codefeed`, `publicOverview`, `publicOrg`, `publicRepo`, `publicFile`, and `publicCommits`.
|
|
138
236
|
- Barrel exports: all public data and request interfaces are also exported from the package root.
|
|
139
237
|
|
package/ts/00_commitinfo_data.ts
CHANGED
|
@@ -0,0 +1,335 @@
|
|
|
1
|
+
import type { TForgeInventoryVisibility } from './forgeinventory.js';
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* Authenticated, read-only measurement of a source forge before its one-time
|
|
5
|
+
* migration. Unlike the caller-visible inventory in `forgeinventory.ts`, it is
|
|
6
|
+
* read with a site administrator's token and counts per owner and repository.
|
|
7
|
+
*
|
|
8
|
+
* A report never contains secret values: no credentials, tokens, private keys,
|
|
9
|
+
* Actions secret or variable values, webhook secrets, or mirror remote URLs.
|
|
10
|
+
* Secrets and variables are counted, never named in the report. Reasons are
|
|
11
|
+
* sanitized diagnostics, never raw response bodies or URLs.
|
|
12
|
+
*/
|
|
13
|
+
|
|
14
|
+
/** Source forges the inventory can read. */
|
|
15
|
+
export type TForgeSourceKind = 'gitea';
|
|
16
|
+
|
|
17
|
+
/**
|
|
18
|
+
* Values are canonical nonnegative decimal integers, retaining JSON precision.
|
|
19
|
+
* `partial` was attempted and did not finish (a resumed run retries it);
|
|
20
|
+
* `notMeasured` was not attempted, for example because no read exists yet.
|
|
21
|
+
*/
|
|
22
|
+
export type TForgeSourceMeasure =
|
|
23
|
+
| { status: 'complete'; value: string }
|
|
24
|
+
| { status: 'partial'; observedValue: string; reason: string }
|
|
25
|
+
| { status: 'notMeasured'; reason: string };
|
|
26
|
+
|
|
27
|
+
export interface IForgeSourceIdentity {
|
|
28
|
+
/** Operator-assigned identity retained when the instance URL changes. */
|
|
29
|
+
instanceId: string;
|
|
30
|
+
kind: TForgeSourceKind;
|
|
31
|
+
/** Origin and path prefix only; never carries credentials. */
|
|
32
|
+
baseUrl: string;
|
|
33
|
+
version: string;
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
/** The account whose token read the source; an inventory requires a site administrator. */
|
|
37
|
+
export interface IForgeSourceReader {
|
|
38
|
+
login: string;
|
|
39
|
+
siteAdmin: boolean;
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
export interface IForgeSourceUserCounts {
|
|
43
|
+
total: TForgeSourceMeasure;
|
|
44
|
+
active: TForgeSourceMeasure;
|
|
45
|
+
admins: TForgeSourceMeasure;
|
|
46
|
+
restricted: TForgeSourceMeasure;
|
|
47
|
+
prohibitLogin: TForgeSourceMeasure;
|
|
48
|
+
/** Users authenticated through an external source such as LDAP or OAuth2. */
|
|
49
|
+
externalAuth: TForgeSourceMeasure;
|
|
50
|
+
twoFactor: TForgeSourceMeasure;
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
export interface IForgeSourceInstanceInventory {
|
|
54
|
+
users: IForgeSourceUserCounts;
|
|
55
|
+
organizations: TForgeSourceMeasure;
|
|
56
|
+
/** System and default webhooks. */
|
|
57
|
+
systemWebhooks: TForgeSourceMeasure;
|
|
58
|
+
/** Instance-scoped Actions runners; their registrations are reissued. */
|
|
59
|
+
runners: TForgeSourceMeasure;
|
|
60
|
+
/** Repositories on disk that the forge database does not know. */
|
|
61
|
+
unadoptedRepositories: TForgeSourceMeasure;
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
export interface IForgeSourcePackageTypeCounts {
|
|
65
|
+
/** Provider package type, such as `npm`, `generic` or `container`. */
|
|
66
|
+
type: string;
|
|
67
|
+
packages: TForgeSourceMeasure;
|
|
68
|
+
versions: TForgeSourceMeasure;
|
|
69
|
+
files: TForgeSourceMeasure;
|
|
70
|
+
bytes: TForgeSourceMeasure;
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
export interface IForgeSourceUserAccount {
|
|
74
|
+
admin: boolean;
|
|
75
|
+
active: boolean;
|
|
76
|
+
restricted: boolean;
|
|
77
|
+
prohibitLogin: boolean;
|
|
78
|
+
externalAuth: boolean;
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
export interface IForgeSourceOwnerInventoryBase {
|
|
82
|
+
name: string;
|
|
83
|
+
/** Provider row id as a decimal string. */
|
|
84
|
+
id: string;
|
|
85
|
+
visibility: TForgeInventoryVisibility;
|
|
86
|
+
repositories: TForgeSourceMeasure;
|
|
87
|
+
webhooks: TForgeSourceMeasure;
|
|
88
|
+
actionsVariables: TForgeSourceMeasure;
|
|
89
|
+
runners: TForgeSourceMeasure;
|
|
90
|
+
/** Sorted by type. */
|
|
91
|
+
packages: IForgeSourcePackageTypeCounts[];
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
export interface IForgeSourceOrganizationInventory extends IForgeSourceOwnerInventoryBase {
|
|
95
|
+
kind: 'organization';
|
|
96
|
+
members: TForgeSourceMeasure;
|
|
97
|
+
teams: TForgeSourceMeasure;
|
|
98
|
+
teamMemberships: TForgeSourceMeasure;
|
|
99
|
+
teamRepositoryGrants: TForgeSourceMeasure;
|
|
100
|
+
labels: TForgeSourceMeasure;
|
|
101
|
+
actionsSecrets: TForgeSourceMeasure;
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
/** User-scoped Actions secrets have no list read; see `IForgeSourceInventory.limitations`. */
|
|
105
|
+
export interface IForgeSourceUserInventory extends IForgeSourceOwnerInventoryBase {
|
|
106
|
+
kind: 'user';
|
|
107
|
+
account: IForgeSourceUserAccount;
|
|
108
|
+
sshKeys: TForgeSourceMeasure;
|
|
109
|
+
gpgKeys: TForgeSourceMeasure;
|
|
110
|
+
}
|
|
111
|
+
|
|
112
|
+
export type TForgeSourceOwnerInventory = IForgeSourceOrganizationInventory | IForgeSourceUserInventory;
|
|
113
|
+
|
|
114
|
+
/** Owner-level settings summed over every owner; repository settings are summed separately. */
|
|
115
|
+
export interface IForgeSourceOwnerTotals {
|
|
116
|
+
webhooks: TForgeSourceMeasure;
|
|
117
|
+
actionsSecrets: TForgeSourceMeasure;
|
|
118
|
+
actionsVariables: TForgeSourceMeasure;
|
|
119
|
+
runners: TForgeSourceMeasure;
|
|
120
|
+
members: TForgeSourceMeasure;
|
|
121
|
+
teams: TForgeSourceMeasure;
|
|
122
|
+
teamMemberships: TForgeSourceMeasure;
|
|
123
|
+
teamRepositoryGrants: TForgeSourceMeasure;
|
|
124
|
+
labels: TForgeSourceMeasure;
|
|
125
|
+
sshKeys: TForgeSourceMeasure;
|
|
126
|
+
gpgKeys: TForgeSourceMeasure;
|
|
127
|
+
}
|
|
128
|
+
|
|
129
|
+
export interface IForgeSourceGitCounts {
|
|
130
|
+
/** As reported by the forge, in KiB; not a transfer size. */
|
|
131
|
+
reportedSizeKiB: TForgeSourceMeasure;
|
|
132
|
+
branches: TForgeSourceMeasure;
|
|
133
|
+
tags: TForgeSourceMeasure;
|
|
134
|
+
/** Hidden refs that preserve pull request heads. */
|
|
135
|
+
pullRequestRefs: TForgeSourceMeasure;
|
|
136
|
+
otherRefs: TForgeSourceMeasure;
|
|
137
|
+
}
|
|
138
|
+
|
|
139
|
+
export interface IForgeSourceLfsCounts {
|
|
140
|
+
objects: TForgeSourceMeasure;
|
|
141
|
+
bytes: TForgeSourceMeasure;
|
|
142
|
+
}
|
|
143
|
+
|
|
144
|
+
export interface IForgeSourceCollaborationCounts {
|
|
145
|
+
issues: TForgeSourceMeasure;
|
|
146
|
+
pullRequests: TForgeSourceMeasure;
|
|
147
|
+
/** Conversation comments on issues and pull requests. */
|
|
148
|
+
comments: TForgeSourceMeasure;
|
|
149
|
+
reviews: TForgeSourceMeasure;
|
|
150
|
+
reviewComments: TForgeSourceMeasure;
|
|
151
|
+
labels: TForgeSourceMeasure;
|
|
152
|
+
milestones: TForgeSourceMeasure;
|
|
153
|
+
/** Reactions on issues, pull requests and their comments. */
|
|
154
|
+
reactions: TForgeSourceMeasure;
|
|
155
|
+
/** Files attached to issues, pull requests and their comments. */
|
|
156
|
+
attachments: TForgeSourceMeasure;
|
|
157
|
+
attachmentBytes: TForgeSourceMeasure;
|
|
158
|
+
}
|
|
159
|
+
|
|
160
|
+
export interface IForgeSourceReleaseCounts {
|
|
161
|
+
/** Includes drafts and prereleases. */
|
|
162
|
+
releases: TForgeSourceMeasure;
|
|
163
|
+
drafts: TForgeSourceMeasure;
|
|
164
|
+
assets: TForgeSourceMeasure;
|
|
165
|
+
assetBytes: TForgeSourceMeasure;
|
|
166
|
+
}
|
|
167
|
+
|
|
168
|
+
export interface IForgeSourceAccessCounts {
|
|
169
|
+
collaborators: TForgeSourceMeasure;
|
|
170
|
+
teams: TForgeSourceMeasure;
|
|
171
|
+
deployKeys: TForgeSourceMeasure;
|
|
172
|
+
webhooks: TForgeSourceMeasure;
|
|
173
|
+
branchProtections: TForgeSourceMeasure;
|
|
174
|
+
tagProtections: TForgeSourceMeasure;
|
|
175
|
+
/** Push mirror configurations; their remote credentials are reissued. */
|
|
176
|
+
pushMirrors: TForgeSourceMeasure;
|
|
177
|
+
}
|
|
178
|
+
|
|
179
|
+
export interface IForgeSourceActionsCounts {
|
|
180
|
+
/** Workflow files on the default branch. */
|
|
181
|
+
workflows: TForgeSourceMeasure;
|
|
182
|
+
secrets: TForgeSourceMeasure;
|
|
183
|
+
variables: TForgeSourceMeasure;
|
|
184
|
+
runners: TForgeSourceMeasure;
|
|
185
|
+
/** Run history and artifacts are archived, not migrated; counted to size the archive. */
|
|
186
|
+
runs: TForgeSourceMeasure;
|
|
187
|
+
artifacts: TForgeSourceMeasure;
|
|
188
|
+
artifactBytes: TForgeSourceMeasure;
|
|
189
|
+
}
|
|
190
|
+
|
|
191
|
+
/** Repository units the forge enables. */
|
|
192
|
+
export interface IForgeSourceRepositoryFeatures {
|
|
193
|
+
issues: boolean;
|
|
194
|
+
pullRequests: boolean;
|
|
195
|
+
wiki: boolean;
|
|
196
|
+
releases: boolean;
|
|
197
|
+
packages: boolean;
|
|
198
|
+
actions: boolean;
|
|
199
|
+
projects: boolean;
|
|
200
|
+
}
|
|
201
|
+
|
|
202
|
+
export interface IForgeSourceRepositoryInventory {
|
|
203
|
+
owner: string;
|
|
204
|
+
name: string;
|
|
205
|
+
id: string;
|
|
206
|
+
visibility: TForgeInventoryVisibility;
|
|
207
|
+
fork: boolean;
|
|
208
|
+
/** `owner/name` of the fork parent, or null. */
|
|
209
|
+
parent: string | null;
|
|
210
|
+
mirror: boolean;
|
|
211
|
+
template: boolean;
|
|
212
|
+
archived: boolean;
|
|
213
|
+
empty: boolean;
|
|
214
|
+
/** Git object format such as `sha1` or `sha256`. */
|
|
215
|
+
objectFormat: string;
|
|
216
|
+
defaultBranch: string;
|
|
217
|
+
features: IForgeSourceRepositoryFeatures;
|
|
218
|
+
git: IForgeSourceGitCounts;
|
|
219
|
+
lfs: IForgeSourceLfsCounts;
|
|
220
|
+
collaboration: IForgeSourceCollaborationCounts;
|
|
221
|
+
releases: IForgeSourceReleaseCounts;
|
|
222
|
+
wikiPages: TForgeSourceMeasure;
|
|
223
|
+
access: IForgeSourceAccessCounts;
|
|
224
|
+
actions: IForgeSourceActionsCounts;
|
|
225
|
+
}
|
|
226
|
+
|
|
227
|
+
export interface IForgeSourceRepositoryTotals {
|
|
228
|
+
total: TForgeSourceMeasure;
|
|
229
|
+
private: TForgeSourceMeasure;
|
|
230
|
+
internal: TForgeSourceMeasure;
|
|
231
|
+
forks: TForgeSourceMeasure;
|
|
232
|
+
mirrors: TForgeSourceMeasure;
|
|
233
|
+
templates: TForgeSourceMeasure;
|
|
234
|
+
archived: TForgeSourceMeasure;
|
|
235
|
+
empty: TForgeSourceMeasure;
|
|
236
|
+
withWiki: TForgeSourceMeasure;
|
|
237
|
+
}
|
|
238
|
+
|
|
239
|
+
/**
|
|
240
|
+
* Sums over every owner and repository; a sum is complete only when every
|
|
241
|
+
* addend is. Repository-shaped groups sum repositories only.
|
|
242
|
+
*/
|
|
243
|
+
export interface IForgeSourceInventoryTotals {
|
|
244
|
+
organizations: TForgeSourceMeasure;
|
|
245
|
+
users: TForgeSourceMeasure;
|
|
246
|
+
repositories: IForgeSourceRepositoryTotals;
|
|
247
|
+
git: IForgeSourceGitCounts;
|
|
248
|
+
lfs: IForgeSourceLfsCounts;
|
|
249
|
+
collaboration: IForgeSourceCollaborationCounts;
|
|
250
|
+
releases: IForgeSourceReleaseCounts;
|
|
251
|
+
wikiPages: TForgeSourceMeasure;
|
|
252
|
+
access: IForgeSourceAccessCounts;
|
|
253
|
+
actions: IForgeSourceActionsCounts;
|
|
254
|
+
owners: IForgeSourceOwnerTotals;
|
|
255
|
+
/** Sorted by type. */
|
|
256
|
+
packages: IForgeSourcePackageTypeCounts[];
|
|
257
|
+
}
|
|
258
|
+
|
|
259
|
+
export interface IForgeSourceInventoryGenerator {
|
|
260
|
+
package: string;
|
|
261
|
+
version: string;
|
|
262
|
+
}
|
|
263
|
+
|
|
264
|
+
/**
|
|
265
|
+
* The deterministic measurement of one source: the same source state yields
|
|
266
|
+
* the same document. It carries no timestamps; run times belong to the run.
|
|
267
|
+
* Owners sort by kind then name, repositories by owner then name, and reason
|
|
268
|
+
* lists by code-unit order.
|
|
269
|
+
*/
|
|
270
|
+
export interface IForgeSourceInventory {
|
|
271
|
+
generators: IForgeSourceInventoryGenerator[];
|
|
272
|
+
source: IForgeSourceIdentity;
|
|
273
|
+
reader: IForgeSourceReader;
|
|
274
|
+
/** True only when discovery finished and no measure is partial or not measured. */
|
|
275
|
+
inventoryComplete: boolean;
|
|
276
|
+
incompleteReasons: string[];
|
|
277
|
+
/**
|
|
278
|
+
* Source data that the migration reissues rather than copies and that the
|
|
279
|
+
* provider exposes to no administrator read, such as user-scoped Actions
|
|
280
|
+
* secrets on Gitea. Nothing that is migrated may be listed here instead of
|
|
281
|
+
* being measured.
|
|
282
|
+
*/
|
|
283
|
+
limitations: string[];
|
|
284
|
+
instance: IForgeSourceInstanceInventory;
|
|
285
|
+
owners: TForgeSourceOwnerInventory[];
|
|
286
|
+
repositories: IForgeSourceRepositoryInventory[];
|
|
287
|
+
totals: IForgeSourceInventoryTotals;
|
|
288
|
+
}
|
|
289
|
+
|
|
290
|
+
/** A source name that already exists natively and would block an import under that name. */
|
|
291
|
+
export interface IForgeSourceCollision {
|
|
292
|
+
subject: 'owner' | 'repository';
|
|
293
|
+
/** `owner` or `owner/name` at the source. */
|
|
294
|
+
source: string;
|
|
295
|
+
/** The existing native name. */
|
|
296
|
+
native: string;
|
|
297
|
+
nativeKind: 'namespace' | 'repository' | 'user';
|
|
298
|
+
match: 'exact' | 'caseInsensitive';
|
|
299
|
+
}
|
|
300
|
+
|
|
301
|
+
export type TForgeSourceCollisionCheck =
|
|
302
|
+
| { status: 'checked'; collisions: IForgeSourceCollision[] }
|
|
303
|
+
| { status: 'notChecked'; reason: string };
|
|
304
|
+
|
|
305
|
+
/**
|
|
306
|
+
* A report is a complete basis for migration planning only when
|
|
307
|
+
* `inventoryComplete` is true and the collision check ran. Collisions sort by
|
|
308
|
+
* subject, then source, then native name.
|
|
309
|
+
*/
|
|
310
|
+
export interface IForgeSourceInventoryReport extends IForgeSourceInventory {
|
|
311
|
+
collisionCheck: TForgeSourceCollisionCheck;
|
|
312
|
+
}
|
|
313
|
+
|
|
314
|
+
/** The complete list of what a run measures, read before any unit. */
|
|
315
|
+
export interface IForgeSourceInventoryDiscovery {
|
|
316
|
+
source: IForgeSourceIdentity;
|
|
317
|
+
reader: IForgeSourceReader;
|
|
318
|
+
owners: Array<{ kind: 'organization' | 'user'; name: string }>;
|
|
319
|
+
repositories: Array<{ owner: string; name: string }>;
|
|
320
|
+
/** Non-empty when discovery could not finish; such a run can never be complete. */
|
|
321
|
+
incompleteReasons: string[];
|
|
322
|
+
}
|
|
323
|
+
|
|
324
|
+
/** One independently measured and resumable part of a run. */
|
|
325
|
+
export type TForgeSourceInventoryUnit =
|
|
326
|
+
| { kind: 'instance' }
|
|
327
|
+
| { kind: 'owner'; ownerKind: 'organization' | 'user'; name: string }
|
|
328
|
+
| { kind: 'repository'; owner: string; name: string };
|
|
329
|
+
|
|
330
|
+
/** A failed unit, or one holding a partial measure, is measured again when a run resumes. */
|
|
331
|
+
export type TForgeSourceInventoryUnitResult =
|
|
332
|
+
| { kind: 'instance'; instance: IForgeSourceInstanceInventory }
|
|
333
|
+
| { kind: 'owner'; owner: TForgeSourceOwnerInventory }
|
|
334
|
+
| { kind: 'repository'; repository: IForgeSourceRepositoryInventory }
|
|
335
|
+
| { kind: 'failed'; unit: TForgeSourceInventoryUnit; reason: string };
|
package/ts/data/gitmanager.ts
CHANGED
|
@@ -1,5 +1,3 @@
|
|
|
1
|
-
export type TGitManagerRefType = 'branch' | 'tag' | 'other';
|
|
2
|
-
|
|
3
1
|
export type TGitManagerObjectType = 'blob' | 'tree' | 'commit' | 'tag' | 'other';
|
|
4
2
|
|
|
5
3
|
export type TGitManagerTreeEntryType = 'file' | 'dir' | 'symlink' | 'submodule' | 'other';
|
|
@@ -35,17 +33,95 @@ export interface IGitManagerImportMirrorRequest extends IGitManagerRepositorySel
|
|
|
35
33
|
remoteUrl: string;
|
|
36
34
|
}
|
|
37
35
|
|
|
38
|
-
|
|
36
|
+
/**
|
|
37
|
+
* One page request of a repository's complete ref inventory.
|
|
38
|
+
*
|
|
39
|
+
* Without `prefixes`, every ref under `refs/` is listed: branches, tags, and
|
|
40
|
+
* all other namespaces such as `refs/notes/*`, `refs/pull/*`,
|
|
41
|
+
* `refs/keep-around/*`, and provider-internal refs. A prefix selects refs on
|
|
42
|
+
* full path components: `refs/heads/` selects every branch, and a complete
|
|
43
|
+
* ref name such as `refs/heads/main` selects exactly that ref.
|
|
44
|
+
*/
|
|
45
|
+
export interface IGitManagerRefRequest extends IGitManagerRepositorySelector {
|
|
46
|
+
/**
|
|
47
|
+
* `refs/`-rooted prefixes; omit to list every ref. An empty array is
|
|
48
|
+
* rejected as invalid. Overlapping prefixes select the de-duplicated union,
|
|
49
|
+
* so each ref appears once.
|
|
50
|
+
*/
|
|
51
|
+
prefixes?: string[];
|
|
52
|
+
/** Opaque cursor from the preceding page; omit to start a new inventory. */
|
|
53
|
+
cursor?: string;
|
|
54
|
+
/** Maximum refs in this page. The engine owns the default and maximum. */
|
|
55
|
+
limit?: number;
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
export interface IGitManagerRef {
|
|
59
|
+
/** Full ref name, for example `refs/heads/main`. */
|
|
39
60
|
name: string;
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
61
|
+
/**
|
|
62
|
+
* Object the ref points at; for a symbolic ref, the object its target
|
|
63
|
+
* resolves to. Null only for a symbolic ref whose target does not resolve,
|
|
64
|
+
* such as `refs/remotes/origin/HEAD` pointing at a deleted branch; such refs
|
|
65
|
+
* are listed, never dropped.
|
|
66
|
+
*/
|
|
67
|
+
objectId: string | null;
|
|
68
|
+
/** Type of `objectId`; null exactly when `objectId` is null. */
|
|
69
|
+
objectType: TGitManagerObjectType | null;
|
|
70
|
+
/** Fully peeled object for annotated tags, including nested tags; otherwise null. */
|
|
71
|
+
peeledObjectId: string | null;
|
|
72
|
+
peeledObjectType: TGitManagerObjectType | null;
|
|
73
|
+
/** Target ref name when this ref is symbolic; otherwise null. */
|
|
74
|
+
symbolicTarget: string | null;
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
/** Repository HEAD, which is reported separately and never listed in `refs`. */
|
|
78
|
+
export interface IGitManagerRefHead {
|
|
79
|
+
/** Target ref name when HEAD is symbolic; null when detached. */
|
|
80
|
+
symbolicTarget: string | null;
|
|
81
|
+
/** Resolved object; null when HEAD points at an unborn branch. */
|
|
82
|
+
objectId: string | null;
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
export type TGitManagerRefInventoryPagination =
|
|
86
|
+
| { status: 'more'; cursor: string }
|
|
87
|
+
| { status: 'exhausted' };
|
|
88
|
+
|
|
89
|
+
/**
|
|
90
|
+
* A coherent page of the selected ref inventory, sorted by ref name in byte
|
|
91
|
+
* order. Every page carries the digest of the complete selection it was cut
|
|
92
|
+
* from; a cursor is honoured only while that digest is unchanged, so pages of
|
|
93
|
+
* one inventory never mix two ref states.
|
|
94
|
+
*
|
|
95
|
+
* `inventoryDigest` is the lowercase hex SHA-256 over the UTF-8 bytes of
|
|
96
|
+
* `HEAD\0<head.symbolicTarget or empty>\0<head.objectId or empty>\n` followed
|
|
97
|
+
* by `<name>\0<objectId or empty>\0<symbolicTarget or empty>\n` for each
|
|
98
|
+
* selected ref in ref-name byte order over the complete selection. Peeled
|
|
99
|
+
* values and object types follow from the object IDs and are not part of the
|
|
100
|
+
* digest.
|
|
101
|
+
*/
|
|
102
|
+
export interface IGitManagerRefInventoryPage extends IGitManagerRepositorySelector {
|
|
103
|
+
status: 'page';
|
|
104
|
+
inventoryDigest: string;
|
|
105
|
+
/** Number of refs in the complete selection, not in this page. */
|
|
106
|
+
refCount: number;
|
|
107
|
+
head: IGitManagerRefHead;
|
|
108
|
+
refs: IGitManagerRef[];
|
|
109
|
+
pagination: TGitManagerRefInventoryPagination;
|
|
110
|
+
}
|
|
111
|
+
|
|
112
|
+
/**
|
|
113
|
+
* The selected refs or HEAD changed since the cursor was issued. The caller
|
|
114
|
+
* restarts the inventory without a cursor; no partial page is returned.
|
|
115
|
+
*/
|
|
116
|
+
export interface IGitManagerRefInventoryStale extends IGitManagerRepositorySelector {
|
|
117
|
+
status: 'stale';
|
|
118
|
+
/** Digest bound to the rejected cursor. */
|
|
119
|
+
expectedInventoryDigest: string;
|
|
120
|
+
/** Digest of the current selection. */
|
|
121
|
+
inventoryDigest: string;
|
|
46
122
|
}
|
|
47
123
|
|
|
48
|
-
export
|
|
124
|
+
export type TGitManagerRefInventoryResult = IGitManagerRefInventoryPage | IGitManagerRefInventoryStale;
|
|
49
125
|
|
|
50
126
|
export type TGitManagerMergeMethod = 'merge' | 'squash' | 'rebase';
|
|
51
127
|
|