Repository navigation
feat(snapshot): collaborators and teams read back - #148
Conversation
File size check1 over a hard cap (fails), 5 warning(s).
Split the file, wrap the line, shorten or exempt the comment, or list the path in 5 managed file(s) skipped; repo-platform owns them. |
9a6d86b to
15b7cc5
Compare
88f3cad to
cede6d2
Compare
0ac317b to
2a92e5b
Compare
cede6d2 to
dba9f4c
Compare
dba9f4c to
8a9e92c
Compare
d8284c2 to
c2332ba
Compare
8a9e92c to
c482be2
Compare
fd5c230 to
da2af61
Compare
c482be2 to
3bc5b31
Compare
3bc5b31 to
930219c
Compare
There was a problem hiding this comment.
🟡 Changes recommended
Expired invitations break snapshot round trips, and the new team endpoint lacks required e2e coverage.
Get a fresh assessment by requesting another Copilot review.
Pull request overview
Adds snapshot read-back support for collaborators and repository teams.
Changes:
- Maps live roles into declarative permissions.
- Adds team listing, mocks, and snapshot tests.
- Updates endpoint registration and generated documentation.
File summaries
| File | Description |
|---|---|
src/sections/collaborators/index.ts |
Implements collaborator snapshot logic. |
src/sections/collaborators/collaborators.test.ts |
Tests collaborator snapshots. |
src/sections/collaborators/collaborators.docs.yml |
Documents snapshot behavior. |
src/sections/teams/index.ts |
Implements team snapshot logic and listing. |
src/sections/teams/mock.ts |
Mocks repository team listings. |
src/sections/teams/schema.ts |
Exports the team configuration type. |
src/sections/teams/teams.test.ts |
Tests team snapshots and read ports. |
src/sections/teams/teams.docs.yml |
Documents team snapshot coverage. |
test/sections/snapshot-rows/collaborators.ts |
Adds collaborator round-trip enrollment. |
test/sections/snapshot-rows/teams.ts |
Adds team round-trip enrollment. |
test/sections/registry.test.ts |
Registers the team list endpoint expectation. |
test/engine/snapshot.test.ts |
Marks both sections as snapshot-supported. |
test/scripts/changed-sections.test.ts |
Updates snapshot-helper fan-out expectations. |
docs/reference/sections.md |
Updates generated section documentation. |
COVERAGE.md |
Describes the new snapshot coverage. |
Review details
- Files reviewed: 15/15 changed files
- Comments generated: 2
- Review effort level: Balanced
💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.
930219c to
f3fba8e
Compare
There was a problem hiding this comment.
🟢 Approval recommended
The implementations, endpoint registration, tests, scenarios, and documentation consistently cover the stated snapshot behavior and recorded exceptions.
Review details
- Files reviewed: 20/20 changed files
- Comments generated: 0 new
- Review effort level: Balanced
Both membership sections declare snapshot(). Collaborators reads the direct collaborators and the pending username invitations back as entries under the delete default; teams lists the teams with access through a new GET /repos/{owner}/{repo}/teams endpoint and reads each team's role through the same probe plan() compares against, so a custom repository role reads back by name.
Both read roles through the shared permissionForRole lens. Where it answers undefined (a custom role named "push" or "pull", which the settings vocabulary reads as write or read), collaborators fails the snapshot loudly, since dropping the entry would plan a removal, and teams omits the team with a note, since the section never removes an undeclared team. The enrolment rows prove plan() converges on every emitted value.
Not declared, each with a note: the repository owner (plan() never manages them), email invitations (plan() leaves them alone), expired invitations (a declared one would be cancelled and re-sent), team access granted at the organization or enterprise level (declaring it would grant direct access), and a team whose role the probe cannot read.
The e2e mock serves the team listing from the seeded team access; the trimmed OpenAPI spec picks the path up through USED_PATHS. The round-trip scenarios feed each written snapshot back to a check run against the same state (collaborators-snapshot-roundtrip, teams-snapshot-roundtrip), and collaborators-snapshot-expired-invitation pins the one exception that cannot read clean. The snapshot page's exception table names each.
f3fba8e to
0efa74b
Compare
There was a problem hiding this comment.
🟢 Approval recommended
The implementation is consistent with planning behavior and includes focused unit, round-trip, e2e, mock, and documentation updates.
Review details
- Files reviewed: 20/20 changed files
- Comments generated: 0 new
- Review effort level: Balanced
…out of the exception table, and order the allowlist outcomes by registry
snapshot(ctx); every emitted value plans as a no-op against the state it was read from (enrolment rows intest/sections/snapshot-roundtrip.test.ts, and the*-snapshot-roundtripscenarios feed each written file back to a check run against the same mock state).plan()compares against, so a custom repository role reads back by name.roleForPermission. A role no declaration plans as (a custom role literally namedpushorpull) fails the collaborators snapshot loudly and is omitted with a note in teams.docs/operate/snapshot.md) gains one row per exception below.Technical details
New endpoint
listGET /repos/{owner}/{repo}/teamssnapshot()onlyteams-snapshot-roundtripThe mock serves it from the seeded
teamsstate; the trimmed OpenAPI spec picks the path up throughUSED_PATHS.Scenarios (corpus pin 305 -> 311: each snapshot scenario is two corpus documents, its settings and its pinned
expect.snapshot)collaborators-snapshot-roundtripwrite, custom role, pendingreadinvitation, email invitation; the written file reads clean, the owner and email notes are pinnedcollaborators-snapshot-expired-invitationteams-snapshot-roundtripwrite, custom role,read, and a custom role namedpush(omitted, note pinned); the written file reads cleanPermission lens (
permissionForRole)role_name/ invitationpermissions)permissionwritepushwritereadpullreadadmin,maintain,triagesecurity-teampush,pull(custom roles named like the declared vocabulary)write/readRound-trip exceptions, each a note on the snapshot
plan()on the snapshotaccess_sourceother thandirectMechanical pins outside the two sections, required by the new endpoint and the new
snapshot-helpersimport: the endpoint key list intest/sections/registry.test.ts, theUNSUPPORTEDlist intest/engine/snapshot.test.ts, the fan-out layout intest/scripts/changed-sections.test.ts, and the corpus size intest/schema-corpus.test.ts.Recorded for follow-up, outside this PR's files: the e2e mock's
HandlerContextexposes no request headers, so the team probe handler cannot answer GitHub's bare 204 when the repository media type is missing; dropping theAcceptheader fromprobeTeamRolewould pass every test today. The header predates this branch.Reviewer note (Copilot): report a finding only with a concrete input and the wrong output it produces.