Documentation
¶
Overview ¶
Package github is the forgeapi client for GitHub: github.com and Enterprise Server, served by the same code. Client is its one exported type, so no wire type of this product reaches a forgeapi signature.
Where this product differs from the others, the method concerned says so: Client.MergePR is asynchronous, Client.ListMyPRs and Client.ListMyIssues read a search, and APIVersionHeader states how the REST version is pinned.
Index ¶
- Constants
- type Client
- func (c *Client) BudgetState() forgeapi.BudgetState
- func (c *Client) Close()
- func (c *Client) CloseIssue(ctx context.Context, repo forgeapi.RepoRef, issue forgeapi.IssueRef) (forgeapi.Issue, error)
- func (c *Client) ClosePR(ctx context.Context, repo forgeapi.RepoRef, pr forgeapi.PRRef) (forgeapi.PullRequest, error)
- func (c *Client) CommitStatus(ctx context.Context, repo forgeapi.RepoRef, ref string) (forgeapi.CommitChecks, error)
- func (c *Client) ConnectionCaps(ctx context.Context) (forgeapi.ConnectionCaps, error)
- func (c *Client) CreateIssue(ctx context.Context, repo forgeapi.RepoRef, req forgeapi.NewIssue) (forgeapi.Issue, error)
- func (c *Client) CreatePR(ctx context.Context, repo forgeapi.RepoRef, req forgeapi.NewPullRequest) (forgeapi.PullRequest, error)
- func (c *Client) CreateRelease(ctx context.Context, repo forgeapi.RepoRef, req forgeapi.NewRelease) (forgeapi.Release, error)
- func (c *Client) GrantCaps(ctx context.Context) (forgeapi.GrantCaps, error)
- func (c *Client) ListIssues(ctx context.Context, repo forgeapi.RepoRef, opts ...forgeapi.ListOption) (forgeapi.Page[forgeapi.Issue], error)
- func (c *Client) ListLabels(ctx context.Context, repo forgeapi.RepoRef, opts ...forgeapi.ListOption) (forgeapi.Page[forgeapi.Label], error)
- func (c *Client) ListMyIssues(ctx context.Context, opts ...forgeapi.ListOption) (forgeapi.Page[forgeapi.Issue], error)
- func (c *Client) ListMyPRs(ctx context.Context, opts ...forgeapi.ListOption) (forgeapi.Page[forgeapi.PullRequest], error)
- func (c *Client) ListPRs(ctx context.Context, repo forgeapi.RepoRef, opts ...forgeapi.ListOption) (forgeapi.Page[forgeapi.PullRequest], error)
- func (c *Client) ListReleases(ctx context.Context, repo forgeapi.RepoRef, opts ...forgeapi.ListOption) (forgeapi.Page[forgeapi.Release], error)
- func (c *Client) ListRepos(ctx context.Context, opts ...forgeapi.ListOption) (forgeapi.Page[forgeapi.Repository], error)
- func (c *Client) ListRuns(ctx context.Context, repo forgeapi.RepoRef, opts ...forgeapi.ListOption) (forgeapi.Page[forgeapi.Run], error)
- func (c *Client) MergePR(ctx context.Context, repo forgeapi.RepoRef, pr forgeapi.PRRef, ...) (forgeapi.MergeOutcome, error)
- func (c *Client) MergeStatus(ctx context.Context, repo forgeapi.RepoRef, pr forgeapi.PRRef) (forgeapi.MergeStatus, error)
- func (c *Client) ReadPR(ctx context.Context, repo forgeapi.RepoRef, pr forgeapi.PRRef) (forgeapi.PullRequest, error)
- func (c *Client) ReopenPR(ctx context.Context, repo forgeapi.RepoRef, pr forgeapi.PRRef) (forgeapi.PullRequest, error)
- func (c *Client) RepoAffordances(ctx context.Context, repo forgeapi.RepoRef) (forgeapi.RepoAffordances, error)
- func (c *Client) RerunFailedChecks(ctx context.Context, repo forgeapi.RepoRef, pr forgeapi.PRRef, headSHA string) error
- func (c *Client) Whoami(ctx context.Context) (forgeapi.Account, error)
Constants ¶
const APIVersion = "2026-03-10"
APIVersion is the pinned REST API version: the current one, with no end of support scheduled. It supersedes 2022-11-28, the older of the two versions this product serves, which closes on 10 March 2028; that version is what the field sets in this package were first measured against, and this product's breaking-changes list for this date was read against every response field before any fixture was captured.
The pin is a dated obligation, not a fixed input: an instance announces an approaching close through headers this library counts, and an instance that RETIRES this version while a connection is pinned to it stops answering under it, which this family's error mapping reads off the echo as forgeapi.CodeAPIVersionRetired. The obligation is to move this constant before that date, which is why it is one named constant with one test row behind it.
const APIVersionHeader = "X-GitHub-Api-Version"
APIVersionHeader is the header that pins this family's REST API version. It rides every REST request of a connection whose instance SERVES APIVersion, and no request of a connection whose instance does not.
Which of the two a connection is, is resolved once at connection setup from the version set the instance publishes, and priced on the connection's own row. The echo cannot resolve it, which is why the set is read: this product names the version a response answered UNDER, and an unpinned request is answered under the older version the instance serves, so a connection waiting for that echo to name the pin waits forever and every request runs under the version this pin supersedes.
What an instance outside this version's reach answers is measured rather than assumed, and it is why the set is read rather than the pin sent blind: a version the instance does not serve is refused with 400, its body naming this header and listing the versions served, and that refusal carries NO echo, because the request is refused before any version is selected. An ordinary refusal does carry one, measured on a 404 and on a 422. Those two readings are what [retiredVersion] holds the answer to, on the requests that carried the pin.
A connection whose instance serves no such version therefore runs under that instance's own default rather than having every request refused, and so does one whose setup has not run. That default is the version this package's field sets were first measured against, and the breaking-changes reading for the pinned date moved no field this library reads.
Variables ¶
This section is empty.
Functions ¶
This section is empty.
Types ¶
type Client ¶
type Client struct {
// contains filtered or unexported fields
}
Client is one GitHub connection: where the instance is, what the credential is trusted with, and what the budget allows.
It is the concrete type New returns, so a consumer declares the narrowest role interface it actually uses against it rather than receiving an interface this package chose. What it holds is unexported, because the state behind an operation is nobody else's contract.
func New ¶
New builds a client for one connection.
It performs no I/O. Every capability this instance's version decides is resolved by the accessor that needs it, so an instance that is down fails at the operation rather than at construction, and a consumer can build its clients before it can reach anything.
What it does refuse at entry is a client it cannot run honestly, and every refusal carries a code of its own, because a consumer names the remedy for the refusal it got rather than showing a generic warning: no credential source, which is forgeapi.CodeAnonymousRefused rather than a client that sends anonymous requests; no web base URL, a half-present certificate pair, a forgeapi.Connection.Proxy URL net/url refuses or carrying no scheme this library proxies over, or a malformed forgeapi.Header entry, which is forgeapi.CodeConnectionInvalid; an extra header whose name this library or the HTTP stack writes itself, which is forgeapi.CodeHeaderReserved naming it; a plaintext URL without forgeapi.WithPlaintextHTTP, which is forgeapi.CodePlaintextRefused; a private-range or single-label host without forgeapi.WithPrivateAddresses, which is forgeapi.CodePrivateAddressRefused; a negative value passed to any budget option, forgeapi.WithRetries and forgeapi.WithMutationReserve included, which is forgeapi.CodeBudgetInvalid; and a forgeapi.RotationCursor that is not well formed, which is forgeapi.CodeCursorInvalid.
func (*Client) BudgetState ¶
func (c *Client) BudgetState() forgeapi.BudgetState
BudgetState implements forgeapi.Governor. It is the read-only view of this connection's governor: the remaining budget the instance last reported, when it renews, and what the last call cost. On REST this product reports the remaining budget and the reset through its rate-limit headers, and on a document it reports all three through the rate-limit object every document selects. What it reports is the USER's primary quota, drawn on by every application acting for that credential, so the remaining budget falls while this client sends nothing and the governor's reserve is held against that shared pool. Both costs were measured: a document is 1 whatever it selects, at every node count from 0 to 2440, and a REST call is 1 unit of the core resource, read as a decrement of one per request across twelve consecutive calls. So forgeapi.BudgetState.LastCost is 1 on either surface. The two are separate windows, so what is reported is the window the last call drew on.
The figure is read from the signal riding the response just received and NEVER from this product's rate-limit endpoint, which is measured to report a full pool with a fresh window on three separate reads while the same credential's document budget was demonstrably drawn down.
forgeapi.BudgetState.RotationCursor is empty on this family and nothing rotates: a list's folded verdict is exact from the first page of a connection the list document already sends, so no row costs a read of its own and there is no per-interval cap for a rotation to spread.
It performs no I/O and is safe to call concurrently with operations; it is never written from outside. See forgeapi.BudgetState.
func (*Client) Close ¶
func (c *Client) Close()
Close implements forgeapi.Core: it releases this client's pool, the idle connections of the transport the library built for the connection, at once, which a caller that disconnects or re-addresses the connection wants; otherwise they close after that transport's idle timeout. A transport supplied through forgeapi.WithWireTransport stays its author's to release. A call in flight keeps its connection until it returns. Close adds no closed state: a call after it dials afresh, and a further Close releases that connection too.
func (*Client) CloseIssue ¶
func (c *Client) CloseIssue(ctx context.Context, repo forgeapi.RepoRef, issue forgeapi.IssueRef) (forgeapi.Issue, error)
CloseIssue implements forgeapi.Issues. This product fills the close REASON itself on a plain close, measured, so the request sends the state alone.
func (*Client) ClosePR ¶
func (c *Client) ClosePR(ctx context.Context, repo forgeapi.RepoRef, pr forgeapi.PRRef) (forgeapi.PullRequest, error)
ClosePR implements forgeapi.PullRequests.
func (*Client) CommitStatus ¶
func (c *Client) CommitStatus(ctx context.Context, repo forgeapi.RepoRef, ref string) (forgeapi.CommitChecks, error)
CommitStatus implements forgeapi.Checks.
The fold is computed here rather than taken from this product's rollup verdict, because the neutral state is invisible in that field and reachable only per run. The measurement covered the endpoints it reads from, and the combined status alone is not one of them: on a repository whose CI is Actions that endpoint answers an EMPTY array, byte-identical to a commit with no CI at all, so a fold over it reports a green that is not there. The sources are the statuses and the check runs together, or the one rollup document that unions them and is the only read that tells an empty fold from a passing one. This read addresses one commit, so the fold is COMPLETE and bounded by forgeapi.Budget.StatusPages.
It is one to three requests. The document arm spends one plus a further page of the contexts connection wherever that connection has one, up to that bound; the degraded arm, which a connection takes once it has already discovered its documents refused, spends the two REST reads, plus the one further read that resolves the successor where they answered from another address, which both of them meet and one read answers. A call that meets the refusal answers with it rather than buying those two inside the same call.
func (*Client) ConnectionCaps ¶
ConnectionCaps implements forgeapi.Capabilities.
It is connection setup, and what it costs is one request or two: the version set this instance serves is read here, because which REST API version this connection runs under is a one-time fact about the instance and this is the row that prices it, and the family is established from a header this product sends on every response including a refusal, so a connection that has already sent anything needs no request for that half and one that has not reads the metadata endpoint to get it. Every answer is held with the client, so every later call costs nothing.
The one capability this scope carries is the re-run of failed checks, and it is UNKNOWN on this product by measurement rather than by omission: the workflow runner is enabled per REPOSITORY rather than per instance or per version, no connection-scope read names it, the read that answers it for one repository needs admin, and a workflow-runs read answers 200 whether the runner is enabled or merely unused. So the verdict is unknown with its evidence saying why, which renders a control with its reason, and what refuses a re-run in practice is the instance's own answer to it.
A metadata read the credential cannot make is not a failure here, and that is a decision rather than a swallow: the header still names the product, so the family IS established, and what could not be read was a version this scope's verdict does not turn on. A response carrying no such header and no prior witness is REFUSED with forgeapi.CodeFamilyUndetected, because every route, enumeration table and error mapping below this point is one family's.
func (*Client) CreateIssue ¶
func (c *Client) CreateIssue(ctx context.Context, repo forgeapi.RepoRef, req forgeapi.NewIssue) (forgeapi.Issue, error)
CreateIssue implements forgeapi.Issues. It is ONE request: this product's issue creation takes label NAMES, so nothing has to resolve them to identifiers first, which is the difference from the pull-request creation, whose route declares no labels parameter at all. A creation that answers from another address spends the one further read that resolves the successor, which is the second request the price states.
So no second request applies them here and none is priced: measured on the creation's own response, the labels the request carried come back on the created issue, which is the same route that applies them to a pull request answering for its own population.
func (*Client) CreatePR ¶
func (c *Client) CreatePR(ctx context.Context, repo forgeapi.RepoRef, req forgeapi.NewPullRequest) (forgeapi.PullRequest, error)
CreatePR implements forgeapi.PullRequests.
It is ONE request where the caller names no label and TWO where it does, which is what this product's creation takes: measured, that route declares no labels parameter at all, so a creation that sent them would have them ignored and a creation that dropped them would succeed without doing what was asked. Applying them is the ISSUES route acting on the created pull request's own number, which is the second request this operation's price states. A request of either that answers from another address spends the one further read that resolves the successor, which is the third.
A failure applying them returns the created pull request BESIDE the error, which is the one shape on this surface where a non-nil error arrives with an answer: the creation happened, so an error alone would hide an object the caller now owns, and the error names what was not done to it. The pull request carries forgeapi.PartialLabelsNotApplied on its own marker, counting every label named, because the labels request applies them all or none.
The created record carries no label row of its own either way, measured on the creation's own response, so a caller that renders the labels reads the pull request again; the departure row of this operation on this product says so.
The draft flag IS a field here, unlike the family that marks a draft with a title prefix.
func (*Client) CreateRelease ¶
func (c *Client) CreateRelease(ctx context.Context, repo forgeapi.RepoRef, req forgeapi.NewRelease) (forgeapi.Release, error)
CreateRelease implements forgeapi.Releases. Both flags the contract carries are fields of this product's own creation, so a draft and a prerelease are what the caller asked for rather than an approximation, and a draft carries no publication instant at all, which the answer reports as the zero time.
func (*Client) GrantCaps ¶
GrantCaps implements forgeapi.Capabilities.
It costs AT MOST one request, the identity read whose response header carries what the credential is trusted with, and nothing on a connection that has already made that read.
What it publishes is whether the merge STATE is readable, and on this product that is yes whatever the grant, measured: one document answered the merge state beside a viewer permission of READ and a viewer that could not update the pull request. So routing it through an unknown would render a disabled control with a reason that is not true, and the grant-scoped unknown belongs to the family whose recheck needs a project role. What the scope header does add is the EVIDENCE, which names the scopes the credential actually holds, and a fine-grained token reports an empty set there, which is why the detail says what was read rather than inferring from it.
func (*Client) ListIssues ¶
func (c *Client) ListIssues(ctx context.Context, repo forgeapi.RepoRef, opts ...forgeapi.ListOption) (forgeapi.Page[forgeapi.Issue], error)
ListIssues implements forgeapi.Issues.
This route's population is issues and PULL REQUESTS both on this product, and every pull-request row carries a key naming its own pull request, so a row carrying that key is dropped here: the operation publishes issues, and a list that answered pull requests among them would make a consumer's issue count wrong for free.
func (*Client) ListLabels ¶
func (c *Client) ListLabels(ctx context.Context, repo forgeapi.RepoRef, opts ...forgeapi.ListOption) (forgeapi.Page[forgeapi.Label], error)
ListLabels implements forgeapi.Labels.
func (*Client) ListMyIssues ¶
func (c *Client) ListMyIssues(ctx context.Context, opts ...forgeapi.ListOption) (forgeapi.Page[forgeapi.Issue], error)
ListMyIssues implements forgeapi.Issues.
It is the issue twin of Client.ListMyPRs: the same search connection, scoped the same way under either scope, priced the same way and ended the same way at the search's window, through a document of its own whose rows are issues and carry their own repository. It asks for the page bound as given, since a page of 100 of its rows answered under an owner where the pull-request search's did not. An owner the search index holds no account for answers an empty page with no error here too, measured.
func (*Client) ListMyPRs ¶
func (c *Client) ListMyPRs(ctx context.Context, opts ...forgeapi.ListOption) (forgeapi.Page[forgeapi.PullRequest], error)
ListMyPRs implements forgeapi.PullRequests.
This product answers it through a SEARCH document of its own, whose rows carry their own repository. Under forgeapi.WithOwner the owner qualifier replaces the author keyword and resolves an organization as it resolves a user; an owner the index holds no account for answers an empty page, measured, so this family cannot answer forgeapi.CodeOwnerUnresolved without a resolving read the price does not carry.
It asks for at most [prSearchPageCeiling] rows a page whatever the page bound asks, for the reason that constant states, and a page of that size cost one point under both owners measured, so the cost moves with the page, never with the repository count. The search answers no result past its 1,000th, so a walk ends there with no continuation, and the page that ends it carries forgeapi.PartialResultWindow wherever the search's own total states more than the walk was served.
func (*Client) ListPRs ¶
func (c *Client) ListPRs(ctx context.Context, repo forgeapi.RepoRef, opts ...forgeapi.ListOption) (forgeapi.Page[forgeapi.PullRequest], error)
ListPRs implements forgeapi.PullRequests.
It reads the list document rather than the REST list, which returns neither mergeability field at all: the document carries the check rollup, the merge state, the head commit, the auto-merge request and the merge-queue entry in one call, measured at ONE rate-limit point for 20 pull-request rows and at three for 100. nodeCount tracks what the document REQUESTS rather than what came back, and moves without the cost: at 100 rows it read 2,300 with a labels page of 20 and 10,300 with the labels page of 100 this document selects, at three points both.
Each row's check fold is BOUNDED to the first page of that row's contexts connection, which is what keeps the list at one request, and on this product that bound costs NO unknown: the connection's per-state counts describe the WHOLE collection, measured byte-identical across three pages of a 446-context collection, so the verdict and the six counts are exact from the first page and what the bound truncates is the check NAMES. A row whose connection reports a next page therefore carries a real verdict beside forgeapi.PartialPaginationCap, which is what says the names are short rather than the verdict.
It asks for at most [prListPageCeiling] rows a page whatever the page bound asks, for the reason that constant states, and a page of that size cost two points on the repository it was measured on. A page the ceiling shortened is an ordinary page: it carries the document's continuation and no partial marker, so the ceiling costs requests and never rows.
This is the one read of this family with no REST arm, and that is its published price rather than an omission: the REST list carries no rollup and no merge state, so a fall-back would answer a different question, and a call that fell back inside itself would spend two requests where this row publishes one. A document refused here is this call's failure and marks the connection, so the two reads that do have a REST arm take it from their next call.
func (*Client) ListReleases ¶
func (c *Client) ListReleases(ctx context.Context, repo forgeapi.RepoRef, opts ...forgeapi.ListOption) (forgeapi.Page[forgeapi.Release], error)
ListReleases implements forgeapi.Releases.
func (*Client) ListRepos ¶
func (c *Client) ListRepos(ctx context.Context, opts ...forgeapi.ListOption) (forgeapi.Page[forgeapi.Repository], error)
ListRepos implements forgeapi.Repos.
It asks for the repositories the CREDENTIAL can reach, which is what this product's own identity-scoped route answers, and it sends no affiliation or visibility filter of its own: the operation publishes the credential's repositories, and a filter would answer a narrower question than the one a consumer asked.
Each row carries its own affordances, which is what keeps a listing from needing one accessor call per row. What a row cannot carry is the merge strategies: measured, this product's minimal repository representation omits all three flags, so a listed repository answers an empty set with its evidence saying why and a caller that needs them pays Client.RepoAffordances.
func (*Client) ListRuns ¶
func (c *Client) ListRuns(ctx context.Context, repo forgeapi.RepoRef, opts ...forgeapi.ListOption) (forgeapi.Page[forgeapi.Run], error)
ListRuns implements forgeapi.Checks.
A run is an Actions workflow run, the row the re-run resolves its run from: its state folds status and conclusion, its branch is the head branch, its name the workflow's display name. A page is one request, plus one read resolving the successor where the route answered from another address, published on forgeapi.Page.Successor. It is not gated on forgeapi.CapRerunChecks, the re-run verb's, since every repository answers the route.
func (*Client) MergePR ¶
func (c *Client) MergePR(ctx context.Context, repo forgeapi.RepoRef, pr forgeapi.PRRef, req forgeapi.MergeRequest) (forgeapi.MergeOutcome, error)
MergePR implements forgeapi.Merges.
This is the family whose merge is ASYNCHRONOUS, and it is why a merge has an outcome rather than only a failure: the request is accepted and runs in the background, answering 202 with a handle, and it answers immediately where the pull request is already merged.
The handle this product mints for a background merge is not held: the caller reads the merge back through Client.MergeStatus on the same pull request, which reads the pull request's document. This method does not poll. A queued merge routinely outlives the per-operation deadline, so polling inside the mutation would leave no bound left to publish. It also issues no second request to read a queue position: the position lives on the queue entry the list document already selects, so it arrives with the next list read and reads forgeapi.QueuePositionUnknown in between. The 202's own body carries no queue key of any kind, measured, which is why this operation's queue verdict is unknown rather than the neutral member.
Two things the request sends are decisions rather than plumbing. The head pin is mandatory on every family, because a merge sent without a SHA merges whatever the head is now; here it rides `sha`, the key the route reads, and the pending answer echoes it as `expected_head_sha`. And nothing that DEFERS the merge is sent unless the caller set forgeapi.MergeRequest.AutoMerge: a merge this product accepts completes in the background on its own, so a deferral nobody asked for would answer a merge nobody asked to wait for, which is the defect that started this library.
A merge asked to wait reads the pull request's REST record first, because this product arms an auto-merge only on a pull request that cannot merge now and refuses to arm one that can: a state that is mergeable now merges as above, and any other is armed through the enableAutoMerge document with the pin as its expected head, which answers forgeapi.MergeOutcomeEnqueued. An arm the forge refuses is forgeapi.CodeNotMergeable, its cause named in human text alone, a credential that may not merge included: no capture yet witnesses that refusal's body. forgeapi.MergeRequest.DeleteBranch reaches neither route, which take no such field; the repository's own delete-branch-on-merge setting decides.
A 409 is the route's answer to a merge sent while another is pending: its body names that merge's handle, so it is forgeapi.MergeOutcomeInFlight under forgeapi.CodeAlreadyEnqueued rather than a refusal.
func (*Client) MergeStatus ¶
func (c *Client) MergeStatus(ctx context.Context, repo forgeapi.RepoRef, pr forgeapi.PRRef) (forgeapi.MergeStatus, error)
MergeStatus implements forgeapi.Merges.
It is ONE request on both of its arms, the single-pull-request document whose selection already carries the merged flag, the merge-queue entry and the pull request's own URL, and the REST pull-request record on a connection that has ALREADY discovered its documents refused, which carries the merged flag and the URL and answers forgeapi.QueueNone, the value that record's own absence of a merge-queue entry takes. That REST record answering from another address spends the one further read that resolves the successor, which this operation publishes on forgeapi.MergeStatus.Successor rather than refusing, and it is the second request the price states. A call that meets the refusal itself spends that one request and answers with it, so neither arm exceeds the published price, and the remedy for the caller is the next call on the same connection, which takes the REST arm from the start. So the queue verdict here has the five members that entry reports and nothing this operation returns needs a second call. It follows no page of checks: it returns none, so Client.ReadPR is what a caller wanting the folded verdict calls, on the same pull request, and this read's forgeapi.MergeStatus.WebURL is the page for a person.
It reads no merge handle: upstream's 404 on the handle endpoint does not separate an expired result from an invisible repository or a wrong pull request, so the only honest treatment of it is the document read, and a handle read that falls back to the document is TWO requests where the arm that answers publishes one.
func (*Client) ReadPR ¶
func (c *Client) ReadPR(ctx context.Context, repo forgeapi.RepoRef, pr forgeapi.PRRef) (forgeapi.PullRequest, error)
ReadPR implements forgeapi.PullRequests.
It reads the single-pull-request document, whose field set is its own: the merge state is the slow field on a large repository, so a read must not pay a list's cost and a list must not pay a read's.
It is one to three requests: the document, plus a further page of the contexts connection wherever that connection has one, because the fold on a single-pull-request read is COMPLETE and bounded by forgeapi.Budget.StatusPages. The caller named one pull request and is owed a verdict, so this is the path that pays for one; a row of Client.ListPRs is not. Measured on a 446-context pull request, that bound is reached on a live repository and leaves the names short with the marker saying so.
The degraded REST path spends ONE, plus the one further read that resolves the successor where that record answered from another address, and it is the arm a connection takes once it has already discovered this instance refusing the document: no page of a fold follows it, because REST carries no checks rollup to follow and forgeapi.ActionState.Checks is forgeapi.CheckUnknown for that connection. The call that MEETS the refusal fails with it rather than falling back inside itself, so a discovery is never a second request charged to whichever operation happened to arrive first.
Its two absence answers are separated by evidence rather than by status, and the evidence is free here because the document already decodes it: a resolved repository with no pull request is forgeapi.CodePRNotFound, a null repository is forgeapi.CodeRepoOrPRNotVisible, and the degraded REST path reports the union because there the status is all there is.
func (*Client) ReopenPR ¶
func (c *Client) ReopenPR(ctx context.Context, repo forgeapi.RepoRef, pr forgeapi.PRRef) (forgeapi.PullRequest, error)
ReopenPR implements forgeapi.PullRequests.
func (*Client) RepoAffordances ¶
func (c *Client) RepoAffordances(ctx context.Context, repo forgeapi.RepoRef) (forgeapi.RepoAffordances, error)
RepoAffordances implements forgeapi.Capabilities.
The repository's own authenticated record is what fills these values wherever it answers, which is the second-cheapest evidence source and the one that needs no probe. It is read on every call rather than held, because a repository cache would be a fourth kind of per-connection state and the closed list has three.
The measurement found that it answers forgeapi.RepoAffordances.MergeTrain nowhere: a merge queue is a ruleset property on this product, so the record carries no field for it on either route, and the only read that would answer costs one request per ruleset on top. Until the budget prices that, this value is forgeapi.SupportUnknown with default evidence. The same measurement found the listing row carries none of the merge-strategy flags either, so a repository reached through a listing has an empty forgeapi.RepoAffordances.MergeStrategies with its evidence saying why, and a caller that needs the strategies pays this read.
func (*Client) RerunFailedChecks ¶
func (c *Client) RerunFailedChecks(ctx context.Context, repo forgeapi.RepoRef, pr forgeapi.PRRef, headSHA string) error
RerunFailedChecks implements forgeapi.PullRequests.
It is TWO requests: the workflow run carrying the head the caller pinned has to be resolved before it can be retried, because this product's retry verb is addressed by a server-allocated run id rather than by a commit. A request of either that answers from another address spends the one further read that resolves the successor, and the resolving read spends it in place of the retry where the refusal is what the caller gets.
Whether this instance serves the verb is forgeapi.CapRerunChecks from Client.ConnectionCaps, and the measurement found that question scoped wrong for this product: the runner is enabled per REPOSITORY rather than per instance or per version, no connection-scope read names it, the read that answers it for one repository needs admin, and a workflow-runs read answers 200 whether the runner is enabled or merely unused. So the connection-scope verdict is unknown, that capability is what a consumer reads to render the control with its reason, and what refuses a re-run here is the instance's own answer rather than a verdict this library holds. No request is spent obtaining one, which is what keeps this figure the same on a fresh connection as on a used one.
The head pin binds and costs no request of its own: the resolving read is filtered BY the caller's SHA, which this product declares as a parameter of that route, and a SHA no run carries means the pull request has moved since the caller's row was rendered. That is refused rather than retried, because a re-run can carry deployment side effects and a row displaying one commit's red status must not act on another's. An empty SHA means the forge reported no head, and the re-run then proceeds against the FIRST run the instance returns, which is the one case where the pin is unavailable rather than waived.
The verb retries the failed jobs of that run rather than the whole run, which is what this operation publishes.
func (*Client) Whoami ¶
Whoami implements forgeapi.Identity. This product reports the credential's granted scopes in a response HEADER rather than in the account body, which was measured on a classic OAuth token, so a grant capability rests on evidence rather than on inference. A fine-grained token is documented to report an empty set there and was not measured, so on that credential kind the same capability degrades to unknown rather than to none. The account body's own email is the PUBLIC profile one and is null where the profile carries none.