diff --git a/openapi/SPEC_COMMIT b/openapi/SPEC_COMMIT index 737f3b5..1d71608 100644 --- a/openapi/SPEC_COMMIT +++ b/openapi/SPEC_COMMIT @@ -1 +1 @@ -f04802661e353fbf4eaf082679e4df2d04939033 +6c838d3b418b461463c10e59ecba1e2706dec0f5 diff --git a/openapi/openapi.yaml b/openapi/openapi.yaml index c2d6ec5..cfcf06d 100644 --- a/openapi/openapi.yaml +++ b/openapi/openapi.yaml @@ -1207,6 +1207,84 @@ paths: schema: $ref: "#/components/schemas/ActionError" + /api/pull-requests/rerun-checks: + post: + operationId: rerunPullRequestChecks + summary: Rerun only the failed jobs of one pull request's checks, on the signed-in user's behalf + description: | + Asks the forge to rerun the failed jobs of the GitHub Actions + workflow runs on the pull request's head commit, and nothing that + passed. It answers once the forge has queued them, not when they + finish, so a client shows a queued state and lets the next refresh + carry the result. + + GitHub only (#698). A pull request offers it as a `rerun_checks` + entry in `allowedActions`, when its CI is failing. Forgejo's commit + statuses don't say which workflow run they came from, so a Forgejo + pull request never lists it. A failed check that isn't an Actions job + (a third-party check, a legacy status) can't be rerun here. + + Refusals are an `ActionError` (see Merge). `not_mergeable` with a 409 + means the pull request has no failed check to rerun. Anything the + forge refuses (the token may not write to Actions, the run is too + old or already running) arrives with its own plain-words `message`. + tags: [pull-requests] + security: [{ bearerAuth: [] }] + requestBody: + required: true + content: + application/json: + schema: + $ref: "#/components/schemas/PullRequestActionRequest" + responses: + "204": + description: The failed jobs were queued to rerun. + "400": + description: | + The request body wasn't valid JSON, `fullName` wasn't + "owner/repo", no credentials are saved for that forge, or that + forge's client doesn't support rerunning checks. + content: + application/json: + schema: + $ref: "#/components/schemas/Error" + "401": + description: No valid session cookie was presented. + content: + application/json: + schema: + $ref: "#/components/schemas/Error" + "403": + description: The forge rejected the request as unauthorized. The saved token can't write to Actions on that repo. `code` is `permission`. + content: + application/json: + schema: + $ref: "#/components/schemas/ActionError" + "404": + description: The forge reported the repo or pull request doesn't exist (or isn't visible to this token). `code` is `unknown`. + content: + application/json: + schema: + $ref: "#/components/schemas/ActionError" + "409": + description: There is no failed Actions job to rerun, or the pull request was already merged or closed. + content: + application/json: + schema: + $ref: "#/components/schemas/ActionError" + "429": + description: The forge rate-limited the request. `code` is `rate_limited`; `resetsAt` carries when the budget comes back, when the forge said. + content: + application/json: + schema: + $ref: "#/components/schemas/ActionError" + "502": + description: The forge was unreachable, or answered with something this app couldn't classify more specifically. + content: + application/json: + schema: + $ref: "#/components/schemas/ActionError" + /api/pull-requests/update-branch: post: operationId: updatePullRequestBranch @@ -3505,6 +3583,7 @@ components: - dependabot_rebase - dependabot_recreate - renovate_rebase + - rerun_checks blocked: type: object required: [code, message] diff --git a/src/forge_dashboard/_generated/api/pull_requests/rerun_pull_request_checks.py b/src/forge_dashboard/_generated/api/pull_requests/rerun_pull_request_checks.py new file mode 100644 index 0000000..c2b6465 --- /dev/null +++ b/src/forge_dashboard/_generated/api/pull_requests/rerun_pull_request_checks.py @@ -0,0 +1,293 @@ +from http import HTTPStatus +from typing import Any, cast +from urllib.parse import quote + +import httpx + +from ...client import AuthenticatedClient, Client +from ...types import Response, UNSET +from ... import errors + +from ...models.action_error import ActionError +from ...models.error import Error +from ...models.pull_request_action_request import PullRequestActionRequest +from typing import cast + + + +def _get_kwargs( + *, + body: PullRequestActionRequest, + +) -> dict[str, Any]: + headers: dict[str, Any] = {} + + + + + + + _kwargs: dict[str, Any] = { + "method": "post", + "url": "/api/pull-requests/rerun-checks", + } + + _kwargs["json"] = body.to_dict() + + headers["Content-Type"] = "application/json" + + _kwargs["headers"] = headers + return _kwargs + + + +def _parse_response(*, client: AuthenticatedClient | Client, response: httpx.Response) -> ActionError | Any | Error | None: + if response.status_code == 204: + response_204 = cast(Any, None) + return response_204 + + if response.status_code == 400: + response_400 = Error.from_dict(response.json()) + + + + return response_400 + + if response.status_code == 401: + response_401 = Error.from_dict(response.json()) + + + + return response_401 + + if response.status_code == 403: + response_403 = ActionError.from_dict(response.json()) + + + + return response_403 + + if response.status_code == 404: + response_404 = ActionError.from_dict(response.json()) + + + + return response_404 + + if response.status_code == 409: + response_409 = ActionError.from_dict(response.json()) + + + + return response_409 + + if response.status_code == 429: + response_429 = ActionError.from_dict(response.json()) + + + + return response_429 + + if response.status_code == 502: + response_502 = ActionError.from_dict(response.json()) + + + + return response_502 + + if client.raise_on_unexpected_status: + raise errors.UnexpectedStatus(response.status_code, response.content) + else: + return None + + +def _build_response(*, client: AuthenticatedClient | Client, response: httpx.Response) -> Response[ActionError | Any | Error]: + return Response( + status_code=HTTPStatus(response.status_code), + content=response.content, + headers=response.headers, + parsed=_parse_response(client=client, response=response), + ) + + +def sync_detailed( + *, + client: AuthenticatedClient, + body: PullRequestActionRequest, + +) -> Response[ActionError | Any | Error]: + """ Rerun only the failed jobs of one pull request's checks, on the signed-in user's behalf + + Asks the forge to rerun the failed jobs of the GitHub Actions + workflow runs on the pull request's head commit, and nothing that + passed. It answers once the forge has queued them, not when they + finish, so a client shows a queued state and lets the next refresh + carry the result. + + GitHub only (#698). A pull request offers it as a `rerun_checks` + entry in `allowedActions`, when its CI is failing. Forgejo's commit + statuses don't say which workflow run they came from, so a Forgejo + pull request never lists it. A failed check that isn't an Actions job + (a third-party check, a legacy status) can't be rerun here. + + Refusals are an `ActionError` (see Merge). `not_mergeable` with a 409 + means the pull request has no failed check to rerun. Anything the + forge refuses (the token may not write to Actions, the run is too + old or already running) arrives with its own plain-words `message`. + + Args: + body (PullRequestActionRequest): Which pull request to act on. + + Raises: + errors.UnexpectedStatus: If the server returns an undocumented status code and Client.raise_on_unexpected_status is True. + httpx.TimeoutException: If the request takes longer than Client.timeout. + + Returns: + Response[ActionError | Any | Error] + """ + + + kwargs = _get_kwargs( + body=body, + + ) + + response = client.get_httpx_client().request( + **kwargs, + ) + + return _build_response(client=client, response=response) + +def sync( + *, + client: AuthenticatedClient, + body: PullRequestActionRequest, + +) -> ActionError | Any | Error | None: + """ Rerun only the failed jobs of one pull request's checks, on the signed-in user's behalf + + Asks the forge to rerun the failed jobs of the GitHub Actions + workflow runs on the pull request's head commit, and nothing that + passed. It answers once the forge has queued them, not when they + finish, so a client shows a queued state and lets the next refresh + carry the result. + + GitHub only (#698). A pull request offers it as a `rerun_checks` + entry in `allowedActions`, when its CI is failing. Forgejo's commit + statuses don't say which workflow run they came from, so a Forgejo + pull request never lists it. A failed check that isn't an Actions job + (a third-party check, a legacy status) can't be rerun here. + + Refusals are an `ActionError` (see Merge). `not_mergeable` with a 409 + means the pull request has no failed check to rerun. Anything the + forge refuses (the token may not write to Actions, the run is too + old or already running) arrives with its own plain-words `message`. + + Args: + body (PullRequestActionRequest): Which pull request to act on. + + Raises: + errors.UnexpectedStatus: If the server returns an undocumented status code and Client.raise_on_unexpected_status is True. + httpx.TimeoutException: If the request takes longer than Client.timeout. + + Returns: + ActionError | Any | Error + """ + + + return sync_detailed( + client=client, +body=body, + + ).parsed + +async def asyncio_detailed( + *, + client: AuthenticatedClient, + body: PullRequestActionRequest, + +) -> Response[ActionError | Any | Error]: + """ Rerun only the failed jobs of one pull request's checks, on the signed-in user's behalf + + Asks the forge to rerun the failed jobs of the GitHub Actions + workflow runs on the pull request's head commit, and nothing that + passed. It answers once the forge has queued them, not when they + finish, so a client shows a queued state and lets the next refresh + carry the result. + + GitHub only (#698). A pull request offers it as a `rerun_checks` + entry in `allowedActions`, when its CI is failing. Forgejo's commit + statuses don't say which workflow run they came from, so a Forgejo + pull request never lists it. A failed check that isn't an Actions job + (a third-party check, a legacy status) can't be rerun here. + + Refusals are an `ActionError` (see Merge). `not_mergeable` with a 409 + means the pull request has no failed check to rerun. Anything the + forge refuses (the token may not write to Actions, the run is too + old or already running) arrives with its own plain-words `message`. + + Args: + body (PullRequestActionRequest): Which pull request to act on. + + Raises: + errors.UnexpectedStatus: If the server returns an undocumented status code and Client.raise_on_unexpected_status is True. + httpx.TimeoutException: If the request takes longer than Client.timeout. + + Returns: + Response[ActionError | Any | Error] + """ + + + kwargs = _get_kwargs( + body=body, + + ) + + response = await client.get_async_httpx_client().request( + **kwargs + ) + + return _build_response(client=client, response=response) + +async def asyncio( + *, + client: AuthenticatedClient, + body: PullRequestActionRequest, + +) -> ActionError | Any | Error | None: + """ Rerun only the failed jobs of one pull request's checks, on the signed-in user's behalf + + Asks the forge to rerun the failed jobs of the GitHub Actions + workflow runs on the pull request's head commit, and nothing that + passed. It answers once the forge has queued them, not when they + finish, so a client shows a queued state and lets the next refresh + carry the result. + + GitHub only (#698). A pull request offers it as a `rerun_checks` + entry in `allowedActions`, when its CI is failing. Forgejo's commit + statuses don't say which workflow run they came from, so a Forgejo + pull request never lists it. A failed check that isn't an Actions job + (a third-party check, a legacy status) can't be rerun here. + + Refusals are an `ActionError` (see Merge). `not_mergeable` with a 409 + means the pull request has no failed check to rerun. Anything the + forge refuses (the token may not write to Actions, the run is too + old or already running) arrives with its own plain-words `message`. + + Args: + body (PullRequestActionRequest): Which pull request to act on. + + Raises: + errors.UnexpectedStatus: If the server returns an undocumented status code and Client.raise_on_unexpected_status is True. + httpx.TimeoutException: If the request takes longer than Client.timeout. + + Returns: + ActionError | Any | Error + """ + + + return (await asyncio_detailed( + client=client, +body=body, + + )).parsed diff --git a/src/forge_dashboard/_generated/models/allowed_action_action.py b/src/forge_dashboard/_generated/models/allowed_action_action.py index bf9a972..38639ad 100644 --- a/src/forge_dashboard/_generated/models/allowed_action_action.py +++ b/src/forge_dashboard/_generated/models/allowed_action_action.py @@ -7,6 +7,7 @@ class AllowedActionAction(StrEnum): DEPENDABOT_RECREATE = "dependabot_recreate" MERGE = "merge" RENOVATE_REBASE = "renovate_rebase" + RERUN_CHECKS = "rerun_checks" UPDATE_BRANCH = "update_branch" def __str__(self) -> str: