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

The OpenAPI document describes a pull comment, a pull variant, a steered run and a prompt run #5136

Merged opened this

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

Merged

scout/forge:scout/5114-the-openapi-document-describes-a-pull-co → main 3 commits fork 1 thread · 1 unresolved

  • Merged. scout/5114-the-openapi-document-describes-a-pull-co was merged into main as 58352ea.

Review

Sign in to review this change.
6 files changed +73 −0
src/contract/openapi/routes/index.ts +4
@@ -168,14 +168,18 @@ export { route as postApiV1ReposOwnerNameMakeItYours } from "./postApiV1ReposOwn
168168 export { route as postApiV1ReposOwnerNameOriginReconnect } from "./postApiV1ReposOwnerNameOriginReconnect.ts";
169169 export { route as postApiV1ReposOwnerNamePlan } from "./postApiV1ReposOwnerNamePlan.ts";
170170 export { route as postApiV1ReposOwnerNamePrompts } from "./postApiV1ReposOwnerNamePrompts.ts";
171 export { route as postApiV1ReposOwnerNamePromptsIdRun } from "./postApiV1ReposOwnerNamePromptsIdRun.ts";
171172 export { route as postApiV1ReposOwnerNamePulls } from "./postApiV1ReposOwnerNamePulls.ts";
172173 export { route as postApiV1ReposOwnerNamePullsNumberApproveHere } from "./postApiV1ReposOwnerNamePullsNumberApproveHere.ts";
173174 export { route as postApiV1ReposOwnerNamePullsNumberChecks } from "./postApiV1ReposOwnerNamePullsNumberChecks.ts";
175 export { route as postApiV1ReposOwnerNamePullsNumberComments } from "./postApiV1ReposOwnerNamePullsNumberComments.ts";
174176 export { route as postApiV1ReposOwnerNamePullsNumberMerge } from "./postApiV1ReposOwnerNamePullsNumberMerge.ts";
175177 export { route as postApiV1ReposOwnerNamePullsNumberReviews } from "./postApiV1ReposOwnerNamePullsNumberReviews.ts";
176178 export { route as postApiV1ReposOwnerNamePullsNumberThreadsAnchorResolve } from "./postApiV1ReposOwnerNamePullsNumberThreadsAnchorResolve.ts";
179 export { route as postApiV1ReposOwnerNamePullsNumberVariant } from "./postApiV1ReposOwnerNamePullsNumberVariant.ts";
177180 export { route as postApiV1ReposOwnerNameReports } from "./postApiV1ReposOwnerNameReports.ts";
178181 export { route as postApiV1ReposOwnerNameRunsIdCancel } from "./postApiV1ReposOwnerNameRunsIdCancel.ts";
182 export { route as postApiV1ReposOwnerNameRunsIdSteer } from "./postApiV1ReposOwnerNameRunsIdSteer.ts";
179183 export { route as postApiV1ReposOwnerNameSpend } from "./postApiV1ReposOwnerNameSpend.ts";
180184 export { route as postApiV1ReposOwnerNameSync } from "./postApiV1ReposOwnerNameSync.ts";
181185 export { route as postApiV1ReposOwnerNameUpstreamCheck } from "./postApiV1ReposOwnerNameUpstreamCheck.ts";
src/contract/openapi/routes/postApiV1ReposOwnerNamePromptsIdRun.ts added +12
@@ -0,0 +1,12 @@
1 import { REPO, type Route } from "../shared.ts";
2
3 export const route: Route = {
4 method: "post",
5 path: `${REPO}/prompts/{id}/run`,
6 summary: "Look at a prompt source now, whatever the hour (admin scope); answers the source as the run left it",
7 auth: true,
8 refusals: {
9 no_such_source: "the repository has no such prompt source (422)",
10 not_running: "the prompt routine is not running on this forge (422)",
11 },
12 };
src/contract/openapi/routes/postApiV1ReposOwnerNamePullsNumberComments.ts added +14
@@ -0,0 +1,14 @@
1 import { REPO, type Route } from "../shared.ts";
2
3 export const route: Route = {
4 method: "post",
5 path: `${REPO}/pulls/{number}/comments`,
6 summary: "Comment on a pull (rw scope; anyone who may take part in the repository); answers 201 with the comment",
7 auth: true,
8 status: 201,
9 body: { body: "string" },
10 refusals: {
11 empty_body: "`body` is empty (422)",
12 mirrored: "the repository mirrors an origin; comment there (409)",
13 },
14 };
src/contract/openapi/routes/postApiV1ReposOwnerNamePullsNumberVariant.ts added +16
@@ -0,0 +1,16 @@
1 import { REPO, type Route } from "../shared.ts";
2
3 export const route: Route = {
4 method: "post",
5 path: `${REPO}/pulls/{number}/variant`,
6 summary: "Like or dislike a pull among its variant siblings (rw scope and write access); a dislike closes the pull with a one-line reason; answers 201 with { answer, closed }",
7 auth: true,
8 status: 201,
9 body: { answer: "string", reason: "string" },
10 refusals: {
11 invalid_answer: "`answer` is not like or dislike (422)",
12 not_variant: "the pull is not one of a set of variants (422)",
13 not_open: "the pull is closed or merged (422)",
14 failed: "the vote could not be recorded (422)",
15 },
16 };
src/contract/openapi/routes/postApiV1ReposOwnerNameRunsIdSteer.ts added +15
@@ -0,0 +1,15 @@
1 import { REPO, type Route } from "../shared.ts";
2
3 export const route: Route = {
4 method: "post",
5 path: `${REPO}/runs/{id}/steer`,
6 summary: "Say something to an agent's run (rw scope; a verified person with write access, not an agent); a running agent hears it as its next turn, otherwise it lands as a comment on the issue or pull; answers { outcome: sent | commented }",
7 auth: true,
8 body: { text: "string" },
9 refusals: {
10 empty: "`text` is empty (422)",
11 not_agent: "the run is not an agent's (422)",
12 unverified: "verify your email first (403)",
13 forbidden: "the caller is an agent (403)",
14 },
15 };
test/openapi.test.ts +12
@@ -269,6 +269,18 @@ test("the admin's writes are described: a capacity setting, a limit and a team",
269269 expect(doc.paths["/api/v1/admin/limits/{key}"].put.summary).toContain("api.anonymous_per_source");
270270 });
271271
272 test("a pull comment, a pull variant, a steered run and a prompt run are described", () => {
273 const doc = openapi("https://f.test", "1") as any;
274 const R = "/api/v1/repos/{owner}/{name}";
275 for (const path of ["pulls/{number}/comments", "pulls/{number}/variant", "runs/{id}/steer", "prompts/{id}/run"]) {
276 expect(doc.paths[`${R}/${path}`]?.post?.security, path).toBeDefined();
277 }
278 expect(doc.paths[`${R}/pulls/{number}/comments`].post.responses["201"]).toBeDefined();
279 expect(doc.paths[`${R}/pulls/{number}/variant`].post.responses["201"]).toBeDefined();
280 const steer = doc.paths[`${R}/runs/{id}/steer`].post;
281 expect(Object.keys(steer.requestBody.content["application/json"].schema.properties)).toEqual(["text"]);
282 });
283
272284 test("a person's sign-ins and ending one are described, with no session secret", () => {
273285 const doc = openapi("https://f.test", "1") as any;
274286 const list = doc.paths["/api/v1/users/{username}/signins"]?.get;

↑↓ navigate ↵ open ⌘↵ its app esc close

Keyboard shortcuts

Docs