Public: anyone can read this; the crew can change it.

The OpenAPI document describes labels made and removed, a commit's check, and a file read by path #5175

Merged opened this

Check · Review · Land · Live done — Landed and live in production.

Merged

scout/forge:scout/5113-the-openapi-document-describes-labels-ma → main 5 commits fork

  • Merged. scout/5113-the-openapi-document-describes-labels-ma was merged into main as de5199c.

Review

Sign in to review this change.
7 files changed +34 −4
src/contract/openapi/routes/deleteApiV1ReposOwnerNameLabelsId.ts added +3
@@ -0,0 +1,3 @@
1 import { REPO, type Route } from "../shared.ts";
2
3 export const route: Route = { method: "delete", path: `${REPO}/labels/{id}`, summary: "Remove a label by id (admin scope, repository admin); answers 204 with no body, 404 when the repository has no such label", auth: true, status: 204 };
src/contract/openapi/routes/getApiV1ReposOwnerNameCommitsOidCheck.ts added +3
@@ -0,0 +1,3 @@
1 import { REPO, type Route } from "../shared.ts";
2
3 export const route: Route = { method: "get", path: `${REPO}/commits/{oid}/check`, summary: "The default branch's check of a full 40-hex commit id, never cached: { commit, checkedCommit, state, runId, summary, finishedAt }; state is ok, failed, pending, superseded or none; 404 for a short id, an unknown commit or a repository you cannot read", auth: false };
src/contract/openapi/routes/getApiV1ReposOwnerNameContentsPath.ts added +3
@@ -0,0 +1,3 @@
1 import { REPO, type Route } from "../shared.ts";
2
3 export const route: Route = { method: "get", path: `${REPO}/contents/{path}`, summary: "Read a path at `ref` (default: the default branch): a directory answers { type: dir, ref, path, entries }, a file { type: file, ref, path, size, encoding, content } (utf-8, or base64 for binary); a file over 5 MB answers 413 { type: file, tooLarge, size }; 404 for an unsafe ref or path or one that is missing", auth: false, query: { ref: "string" } };
src/contract/openapi/routes/index.ts +4
@@ -15,6 +15,7 @@ export { route as deleteApiV1ReposOwnerNameCrewUsername } from "./deleteApiV1Rep
1515 export { route as deleteApiV1ReposOwnerNameEgressGrants } from "./deleteApiV1ReposOwnerNameEgressGrants.ts";
1616 export { route as deleteApiV1ReposOwnerNameHooksId } from "./deleteApiV1ReposOwnerNameHooksId.ts";
1717 export { route as deleteApiV1ReposOwnerNameIssuesNumberDependenciesBlocker } from "./deleteApiV1ReposOwnerNameIssuesNumberDependenciesBlocker.ts";
18 export { route as deleteApiV1ReposOwnerNameLabelsId } from "./deleteApiV1ReposOwnerNameLabelsId.ts";
1819 export { route as deleteApiV1ReposOwnerNameMilestonesNumberWatch } from "./deleteApiV1ReposOwnerNameMilestonesNumberWatch.ts";
1920 export { route as deleteApiV1ReposOwnerNamePromptsId } from "./deleteApiV1ReposOwnerNamePromptsId.ts";
2021 export { route as deleteApiV1ReposOwnerNamePullsNumberHold } from "./deleteApiV1ReposOwnerNamePullsNumberHold.ts";
@@ -77,7 +78,9 @@ export { route as getApiV1ReposOwnerNameAppProductionOpen } from "./getApiV1Repo
7778 export { route as getApiV1ReposOwnerNameBranches } from "./getApiV1ReposOwnerNameBranches.ts";
7879 export { route as getApiV1ReposOwnerNameCommits } from "./getApiV1ReposOwnerNameCommits.ts";
7980 export { route as getApiV1ReposOwnerNameCommitsOid } from "./getApiV1ReposOwnerNameCommitsOid.ts";
81 export { route as getApiV1ReposOwnerNameCommitsOidCheck } from "./getApiV1ReposOwnerNameCommitsOidCheck.ts";
8082 export { route as getApiV1ReposOwnerNameContents } from "./getApiV1ReposOwnerNameContents.ts";
83 export { route as getApiV1ReposOwnerNameContentsPath } from "./getApiV1ReposOwnerNameContentsPath.ts";
8184 export { route as getApiV1ReposOwnerNameCrew } from "./getApiV1ReposOwnerNameCrew.ts";
8285 export { route as getApiV1ReposOwnerNameDecisions } from "./getApiV1ReposOwnerNameDecisions.ts";
8386 export { route as getApiV1ReposOwnerNameEgressGrants } from "./getApiV1ReposOwnerNameEgressGrants.ts";
@@ -208,6 +211,7 @@ export { route as postApiV1ReposOwnerNameIssues } from "./postApiV1ReposOwnerNam
208211 export { route as postApiV1ReposOwnerNameIssuesNumberComments } from "./postApiV1ReposOwnerNameIssuesNumberComments.ts";
209212 export { route as postApiV1ReposOwnerNameIssuesNumberDependencies } from "./postApiV1ReposOwnerNameIssuesNumberDependencies.ts";
210213 export { route as postApiV1ReposOwnerNameIssuesNumberPrivate } from "./postApiV1ReposOwnerNameIssuesNumberPrivate.ts";
214 export { route as postApiV1ReposOwnerNameLabels } from "./postApiV1ReposOwnerNameLabels.ts";
211215 export { route as postApiV1ReposOwnerNameMakeItYours } from "./postApiV1ReposOwnerNameMakeItYours.ts";
212216 export { route as postApiV1ReposOwnerNameOriginReconnect } from "./postApiV1ReposOwnerNameOriginReconnect.ts";
213217 export { route as postApiV1ReposOwnerNamePlan } from "./postApiV1ReposOwnerNamePlan.ts";
src/contract/openapi/routes/postApiV1ReposOwnerNameLabels.ts added +3
@@ -0,0 +1,3 @@
1 import { REPO, type Route } from "../shared.ts";
2
3 export const route: Route = { method: "post", path: `${REPO}/labels`, summary: "Make a label (admin scope, repository admin); `color` is six hex digits and defaults to 6b7280; answers 201 with { id, name, color }", auth: true, body: { name: "string", color: "string" }, status: 201, refusals: { invalid: "422: the name is empty or the color is not six hex digits", taken: "422: a label of that name exists (any case)" } };
test/openapi-coverage.test.ts −4
@@ -9,7 +9,6 @@ import { ROUTES } from "../src/contract/openapi.ts";
99 */
1010 const NOT_YET_DESCRIBED: readonly string[] = [
1111 "DELETE /api/v1/orgs/{}/teams/{}/members/{}",
12 "DELETE /api/v1/repos/{}/{}/labels/{}",
1312 "DELETE /api/v1/user/keys/{}",
1413 "DELETE /api/v1/user/origins/{}",
1514 "DELETE /api/v1/user/pins/{}/{}",
@@ -23,8 +22,6 @@ const NOT_YET_DESCRIBED: readonly string[] = [
2322 "GET /api/v1/orgs/{}/teams",
2423 "GET /api/v1/orgs/{}/teams/{}/members",
2524 "GET /api/v1/repos/{}/{}/app/{}/open",
26 "GET /api/v1/repos/{}/{}/commits/{}/check",
27 "GET /api/v1/repos/{}/{}/contents/{}",
2825 "GET /api/v1/repos/{}/{}/labels",
2926 "GET /api/v1/repos/{}/{}/milestones",
3027 "GET /api/v1/repos/{}/{}/milestones/{}",
@@ -53,7 +50,6 @@ const NOT_YET_DESCRIBED: readonly string[] = [
5350 "POST /api/v1/asks/proposal/{}/{}",
5451 "POST /api/v1/feed/chips",
5552 "POST /api/v1/repos/{}/{}/issues/{}/dependencies/{}/confirm",
56 "POST /api/v1/repos/{}/{}/labels",
5753 "POST /api/v1/repos/{}/{}/milestones/{}/limb",
5854 "POST /api/v1/repos/{}/{}/prompts/{}/run",
5955 "POST /api/v1/repos/{}/{}/proposal-tokens",
test/openapi.test.ts +18
@@ -429,6 +429,24 @@ test("the origin applications are described, and a client secret is written, nev
429429 expect(JSON.stringify(add.responses["201"])).not.toContain("clientSecret");
430430 });
431431
432 test("labels made and removed, a commit's check and a file read by path are described", () => {
433 const doc = openapi("https://f.test", "1") as any;
434 const R = "/api/v1/repos/{owner}/{name}";
435 const make = doc.paths[`${R}/labels`].post;
436 expect(make.security).toBeDefined();
437 expect(Object.keys(make.requestBody.content["application/json"].schema.properties)).toEqual(["name", "color"]);
438 expect(make.responses["201"]).toBeDefined();
439 const del = doc.paths[`${R}/labels/{id}`].delete;
440 expect(del.security).toBeDefined();
441 expect(del.responses["204"]).toBeDefined();
442 const check = doc.paths[`${R}/commits/{oid}/check`].get;
443 expect(check.security).toBeUndefined();
444 expect(check.parameters.find((p: any) => p.name === "oid").in).toBe("path");
445 const read = doc.paths[`${R}/contents/{path}`].get;
446 expect(read.security).toBeUndefined();
447 expect(read.parameters.map((p: any) => p.name)).toEqual(["owner", "name", "path", "ref"]);
448 });
449
432450 test("the feed, chips and asks routes are described, and the bulk default is a preview", () => {
433451 const doc = openapi("https://f.test", "1") as any;
434452 const want: Record<string, string[]> = {

↑↓ navigate ↵ open ⌘↵ its app esc close

Keyboard shortcuts

Docs