Skip to content

steps/pull-requests ​

Low-level GitHub operations for factory-owned steps. Call their durable #jigs/steps wrappers from workflow code.

Watch changes with watchPullRequest from #jigs/routines, and post updates with postPullRequestNote. callGitHub reaches any other REST endpoint from a factory's own "use step" function. See Waiting and external events.

Errors ​

GitHubApiError ​

GitHub answered a REST call with an error status. Check status to handle one answer, such as 422 when GitHub refuses a request it understood.

Extends ​

Constructors ​

Constructor ​
ts
new GitHubApiError(
   status, 
   apiPath, 
   body, 
   message?): GitHubApiError;
Parameters ​
ParameterType
statusnumber
apiPathstring
bodystring
message?string
Returns ​

GitHubApiError

Overrides ​

ProviderApiError.constructor

Properties ​

PropertyTypeDefault valueDescription
bodystringundefinedThe response body as GitHub sent it.
code?stringundefined-
githubMessagestringundefinedGitHub's message, or the whole response body when it has none.
hint?stringundefinedWhat the reader can do about it. Quote each command to run in backticks, as in stop the service first: `pnpm exec jigs service stop` : the CLI prints it on its own line.
providerProviderundefined-
rateLimitedbooleanfalseGitHub refused for its rate limit, and the waits for it ran out.
statusnumberundefinedThe HTTP status, such as 404 or 422.

Read ​

fetchPullRequestState ​

ts
const fetchPullRequestState: FetchPrState;

Read the pull request’s checks, reviews, open review threads and approval.

Open/update ​

OpenedPullRequest ​

ts
type OpenedPullRequest = PullRequestRef & object;

A newly opened or adopted pull request and its browser URL.

Type Declaration ​

NameTypeDescription
urlstringThe pull request's browser URL.

createPullRequest() ​

ts
function createPullRequest(request): Promise<OpenedPullRequest>;

Create a pull request from the worktree's branch into its repository's default branch.

The lookup comes first because this is one step: a create that succeeded before the assignment failed, or whose response was lost, leaves a pull request GitHub will refuse to open twice. The retry adopts that pull request and re-attempts only what did not finish.

Parameters ​

ParameterType
request{ body: string; draft?: boolean; title: string; worktree: Worktree; }
request.bodystring
request.draft?boolean
request.titlestring
request.worktreeWorktree

Returns ​

Promise<OpenedPullRequest>


markPullRequestReady() ​

ts
function markPullRequestReady(pr): Promise<PullRequestSnapshot>;

Mark a draft pull request ready and return its freshly read state.

Parameters ​

ParameterType
prPullRequestRef

Returns ​

Promise<PullRequestSnapshot>

Discuss/review ​

commentOnPullRequest() ​

ts
function commentOnPullRequest(pr, body): Promise<{
  id: number;
}>;

Post a comment on the pull request conversation and return its id.

Parameters ​

ParameterType
prPullRequestRef
bodystring

Returns ​

Promise<{ id: number; }>


replyToPullRequestReviewThread() ​

ts
function replyToPullRequestReviewThread(
   pr, 
   rootId, 
   body): Promise<{
  id: number;
}>;

Reply to a review thread and return the posted comment id.

Parameters ​

ParameterType
prPullRequestRef
rootIdnumber
bodystring

Returns ​

Promise<{ id: number; }>


reviewPullRequest() ​

ts
function reviewPullRequest(pr, review): Promise<{
  id: number;
}>;

Post a pull request review and return its id. GitHub refuses an approval from the pull request's own author with 422 Unprocessable Entity; Jigs lets GitHub's GitHubApiError surface unchanged.

Parameters ​

ParameterType
prPullRequestRef
reviewPullRequestReviewRequest

Returns ​

Promise<{ id: number; }>

Merge ​

MergeOutcome ​

ts
type MergeOutcome = 
  | {
  mergeCommitSha: string | null;
  merged: true;
}
  | object & MergeRefusal;

What GitHub did, why it declined, and whether asking again could change the answer, which is what decides between standing the commit down and leaving it merge-ready.

Type Declaration ​

ts
{
  mergeCommitSha: string | null;
  merged: true;
}
NameTypeDescription
mergeCommitShastring | nullThe merge commit, or null when GitHub has not reported it yet.
mergedtrueConfirms that GitHub reports the pull request merged.

object & MergeRefusal


mergePullRequest() ​

ts
function mergePullRequest(
   pr, 
   expectedHeadSha, 
options): Promise<MergeOutcome>;

Merge the pull request, pinned to the head the caller judged ready.

The method is the first one the repository allows of squash, merge commit and rebase, read from GitHub at each merge.

The title is re-read here rather than carried in from describePullRequest: a reviewer who corrects it, usually to satisfy a conventional-commit check on the target repo, does so between the pull request opening and this merge, and a title captured at open time would ship the one they corrected away. After any ambiguous answer the pull request is read again, and this reports merged only if GitHub says so.

Parameters ​

ParameterType
prPullRequestRef
expectedHeadShastring
optionsMergeOptions

Returns ​

Promise<MergeOutcome>

Any REST endpoint ​

callGitHub() ​

ts
function callGitHub<T>(
   method, 
   path, 
options): Promise<T>;

Call any GitHub REST endpoint as the factory's GitHub App, and return GitHub's parsed JSON response. Wrap it in your own "use step" function.

Type Parameters ​

Type ParameterDefault type
Tunknown

Parameters ​

ParameterType
method"GET" | "POST" | "PUT" | "PATCH" | "DELETE"
pathstring
options{ body?: JsonValue; installationName: string; }
options.body?JsonValue
options.installationNamestring

Returns ​

Promise<T>

Remarks ​

path starts with / and is the endpoint's path with its query string, such as /repos/acme/app/commits?author=dev@acme.com. installationName names the App installation, as named on the hub, to call through. body is sent as JSON. An answer with no content, such as 204, returns undefined.

When GitHub answers with an error status, it throws a GitHubApiError with the status and GitHub's message. Rate-limited calls are retried. A step can run more than once, so a call that is not safe to repeat has to accept what a repeat gets back. The App needs whatever permission the endpoint asks for.

Example ​

ts
// workflows/review/steps.ts
import { callGitHub } from "@jigs-ai/jigs/steps/pull-requests";

export async function closeIssue(repo: string, issue: number) {
  "use step";
  await callGitHub("PATCH", `/repos/${repo}/issues/${issue}`, {
    installationName: "github-acme",
    body: { state: "closed" },
  });
}