com.worxbend.codeberg4s.pulls
Members list
Packages
Type members
Classlikes
One file a pull request touches, as GET /repos/{owner}/{repo}/pulls/{index}/files reports it.
One file a pull request touches, as GET /repos/{owner}/{repo}/pulls/{index}/files reports it.
Forgejo's ChangedFile, which is '''not''' the CommitAffectedFiles that com.worxbend.codeberg4s.repositories.CommitFile models: that one has two keys and no counts, this one carries the line arithmetic and three URLs. The two are kept apart rather than merged, because merging them would produce a model whose fields are populated depending on which endpoint answered.
status '''is''' shared, though — it is the same vocabulary Forgejo derives from Git's status letters, so this model reuses the repository wave's com.worxbend.codeberg4s.repositories.CommitFileStatus per docs/LEDGER.md rather than declaring a second enum with the same seven cases. golden/pull/files-list.json shows "changed".
No diff text reaches this model. The patch is a separate document — GET /repos/{owner}/{repo}/pulls/{index}.diff — and it is not JSON, so it is not this endpoint's to return.
Value parameters
- additions
-
lines added;
0when the instance did not report a count - changes
-
Forgejo's own total. Usually
additions + deletions, and read from the payload rather than recomputed, because a client that recomputes a server-side number quietly disagrees with the web UI - contentsUrl
-
the API URL of the file's contents at the pull request's head commit
- deletions
-
lines removed
- filename
-
the file's path relative to the repository root, as Git records it
- previousFilename
-
where the file was before, populated only for a rename
- rawUrl
-
the browser URL of the raw file at that same commit
- status
-
what the pull request does to the file, absent when the instance sent a value this library does not recognise; see com.worxbend.codeberg4s.repositories.CommitFileStatus.parse
Attributes
- Supertypes
-
trait Serializabletrait Producttrait Equalsclass Objecttrait Matchableclass AnyShow all
Attributes
- Companion
- class
- Supertypes
-
trait Producttrait Mirrorclass Objecttrait Matchableclass Any
- Self type
-
CreatePullRequest.type
Everything POST /repos/{owner}/{repo}/pulls may be told, as one value.
Everything POST /repos/{owner}/{repo}/pulls may be told, as one value.
A command type rather than an eight-parameter method: the parameters are almost all optional and almost all Option[String] or Option[Long], and a call site passing five Nones in a fixed order is a defect waiting to happen. Built by naming what should be set:
for command <- CreatePullRequest.of("fix the hook quoting", head, base)
yield command.withBody("backport of #13679").labelled(Vector(bug))
'''Only what is set is sent.''' An unset field contributes no JSON key, so the instance applies its own default rather than this library's idea of one.
Value parameters
- assignees
-
the logins to assign, empty for none. Forgejo silently ignores a login the caller may not assign
- base
-
the branch to merge into. A com.worxbend.codeberg4s.repositories.BranchName and not a PullRequestHead, because a base is always a branch of the repository being posted to — Forgejo has no cross-repository base
- dueDate
-
a deadline for the pull request
- head
-
the branch to merge from, in the one spelling Forgejo accepts; see PullRequestHead
- labels
-
the labels to attach, by com.worxbend.codeberg4s.issues.LabelId —
CreatePullRequestOption.labelsis a list of ids, not of names - title
-
the pull request title; validated by CreatePullRequest.of
Attributes
- Companion
- object
- Supertypes
-
trait Serializabletrait Producttrait Equalsclass Objecttrait Matchableclass AnyShow all
Attributes
- Companion
- class
- Supertypes
-
trait Producttrait Mirrorclass Objecttrait Matchableclass Any
- Self type
-
CreateReview.type
Everything POST /repos/{owner}/{repo}/pulls/{index}/reviews may be told, as one value.
Everything POST /repos/{owner}/{repo}/pulls/{index}/reviews may be told, as one value.
Forgejo's CreatePullReviewOptions. One call posts a summary, an intent, and any number of inline remarks at once, which is what the web UI's "submit review" button does; posting the remarks one at a time through com.worxbend.codeberg4s.pulls.PullRequestApi.createReviewComment produces a different thing — comments attached to a pending review — and is the reason both endpoints exist.
==The event decides whether a review is submitted or left pending==
event is Forgejo's ReviewStateType, and this library reuses ReviewState for it rather than declaring a near-duplicate enum. Only four of the five cases are meaningful as an '''event''':
- ReviewState.Approved, ReviewState.RequestChanges and ReviewState.Comment submit the review immediately;
- ReviewState.Pending — and an absent event, which Forgejo treats the same way — leaves it as the reviewer's own unsent draft, to be finished later with com.worxbend.codeberg4s.pulls.PullRequestApi.submitReview;
- ReviewState.RequestReview is not an event at all. Forgejo rejects it with a
422, because asking someone else to review is com.worxbend.codeberg4s.pulls.PullRequestApi.requestReviews and a different endpoint.
'''Only what is set is sent''', so an unset field lets the instance apply its own default rather than this library's idea of one.
Value parameters
- body
-
the review's summary text. Forgejo requires one for ReviewState.Comment and for ReviewState.RequestChanges, and answers
422without it - comments
-
the inline remarks to post with the review, in order; empty for a summary-only review
- commit
-
the head commit the review is made against, absent to let Forgejo pin the review to whatever the head is now. Naming it explicitly is what keeps a review from silently attaching to commits the reviewer never read
- event
-
what the review says; see the note above
Attributes
- Companion
- object
- Supertypes
-
trait Serializabletrait Producttrait Equalsclass Objecttrait Matchableclass AnyShow all
Which non-JSON representation of a pull request to fetch — the {diffType} of /repos/{owner}/{repo}/pulls/{index}.{diffType}.
Which non-JSON representation of a pull request to fetch — the {diffType} of /repos/{owner}/{repo}/pulls/{index}.{diffType}.
The two are not interchangeable, and the difference is not cosmetic:
- Diff is a plain unified diff of the whole pull request, with no commit metadata. It is what
git diffproduces and whatgit applyconsumes; - Patch is a mailbox of one
git format-patchmessage per commit, each with its own author, date and message. It is whatgit amconsumes, and it preserves authorship that Diff discards.
A caller that means to replay someone's commits wants Patch; a caller that means to look at the net change wants Diff. Choosing wrongly produces a document that applies with the wrong tool and no error until it does.
This is a path segment, not a query parameter, and it is the reason the endpoint's path has a dot in it.
Attributes
- Supertypes
-
trait Enumtrait Serializabletrait Producttrait Equalsclass Objecttrait Matchableclass AnyShow all
Attributes
- Companion
- class
- Supertypes
-
trait Producttrait Mirrorclass Objecttrait Matchableclass Any
- Self type
-
DiffRequest.type
What to ask GET /repos/{owner}/{repo}/pulls/{index}.{diffType} for.
What to ask GET /repos/{owner}/{repo}/pulls/{index}.{diffType} for.
Two decisions travel together — which representation, and whether binary changes are included — so they are one value rather than two parameters whose order a call site has to remember. The flag is a named builder for the reason MergePullRequest gives: download(pull, format, true) makes a reader reconstruct what the true was.
client.pulls.download(owner, name, number, DiffRequest.of(DiffFormat.Diff).includingBinary)
Value parameters
- format
-
which document to fetch; see DiffFormat
- includeBinary
-
whether Forgejo should embed binary file changes.
falseunless includingBinary was called, because the embedded form multiplies the response size — a pull request that touches one image can turn a two-kilobyte diff into a megabyte one, and the library will not choose that on a caller's behalf. Set it when the result has to be applicable withgit apply, which is the only thing it is for
Attributes
- Companion
- object
- Supertypes
-
trait Serializabletrait Producttrait Equalsclass Objecttrait Matchableclass AnyShow all
Attributes
- Companion
- class
- Supertypes
-
trait Producttrait Mirrorclass Objecttrait Matchableclass Any
- Self type
-
DismissReview.type
Everything POST /repos/{owner}/{repo}/pulls/{index}/reviews/{id}/dismissals may be told, as one value.
Everything POST /repos/{owner}/{repo}/pulls/{index}/reviews/{id}/dismissals may be told, as one value.
Forgejo's DismissPullReviewOptions. Dismissing does '''not''' delete a review: it stays on the listing with Review.isDismissed set and stops counting towards the base branch's required-approval rule. Deleting one is com.worxbend.codeberg4s.pulls.PullRequestApi.deleteReview and is irreversible; com.worxbend.codeberg4s.pulls.PullRequestApi.undismissReview undoes this.
Value parameters
- message
-
the reason recorded against the dismissal, absent to record none. Worth setting — it is the only explanation the reviewer ever sees
- priors
-
whether to dismiss the reviewer's '''earlier''' reviews of the same pull request as well.
falseunless includingPriors was called: dismissing more than the review that was named is not a default this library picks
Attributes
- Companion
- object
- Supertypes
-
trait Serializabletrait Producttrait Equalsclass Objecttrait Matchableclass AnyShow all
Everything PATCH /repos/{owner}/{repo}/pulls/{index} may be told, as one value.
Everything PATCH /repos/{owner}/{repo}/pulls/{index} may be told, as one value.
Built by starting from EditPullRequest.Empty and naming only what should change:
EditPullRequest.Empty.withTitle("fix the hook quoting").allowingMaintainerEdit
'''Only what is set is sent, and that is the whole contract of a PATCH.''' An unset field contributes no JSON key, so the instance leaves that property alone. Three consequences are worth spelling out because they are easy to get wrong:
- assignees and labels '''replace''' rather than add, so an empty vector clears them. That is why both are
Option[Vector[…]]: absent leaves the list alone, present-and-empty empties it. - clearing a deadline is withoutDueDate, which sends
unset_due_date: true, and not dueBy with some sentinel instant. Forgejo needs the separate flag becausedue_date: nullis indistinguishable from an absent key on its side. - withBase '''retargets the pull request''', which makes Forgejo recompute the diff against a different branch. It is the one field here that can change what the pull request means rather than how it is labelled.
An EditPullRequest.Empty sent as-is is a well-formed request that changes nothing.
Value parameters
- allowMaintainerEdit
-
whether the base repository's maintainers may push to the head branch; absent leaves the setting alone
- state
-
the lifecycle transition to apply. com.worxbend.codeberg4s.issues.IssueStateChange and not a type of this group's own: Forgejo's
EditPullRequestOption.statetakes the same twoopen/closedspellings asEditIssueOption.state, anddocs/LEDGER.mdforbids forking a model that already exists. There is deliberately no transition that merges — merging is MergePullRequest and a different endpoint
Attributes
- Companion
- object
- Supertypes
-
trait Serializabletrait Producttrait Equalsclass Objecttrait Matchableclass AnyShow all
Attributes
- Companion
- class
- Supertypes
-
trait Producttrait Mirrorclass Objecttrait Matchableclass Any
- Self type
-
EditPullRequest.type
Attributes
- Companion
- class
- Supertypes
-
trait Producttrait Mirrorclass Objecttrait Matchableclass Any
- Self type
-
MergePullRequest.type
Everything POST /repos/{owner}/{repo}/pulls/{index}/merge may be told, as one value.
Everything POST /repos/{owner}/{repo}/pulls/{index}/merge may be told, as one value.
This is the request behind the most destructive operation in this library, and the type is shaped accordingly.
'''The style is mandatory and is not a String.''' MergeStyle is the only argument MergePullRequest.using takes, because MergePullRequestOption.Do is the only property Forgejo declares as required, and the difference between two of its six values is the difference between rewriting a branch's history and not.
'''Every flag is a named method, not a Boolean parameter.''' merge(pull, force = true, delete = true) makes a reader reconstruct which true was which, and one of them deletes a branch. SCALA_CODE_STYLE.md bans that shape outright; here it would be a footgun as well as a style violation.
==Making a retry safe==
expecting is the one thing that makes repeating this call safe, and it is worth using deliberately. It sends head_commit_id, which Forgejo compares against the branch's actual head and refuses the merge if it has moved — so a merge sent twice after a timeout cannot merge a commit the caller never saw. Without it, a repeat merges whatever the head has since become. com.worxbend.codeberg4s.pulls.PullRequestApi.merge never retries by itself for exactly this reason.
Value parameters
- deleteBranchAfterMerge
-
whether to delete the head branch once the merge lands.
falseunless deletingSourceBranch was called — deleting someone's branch is not a default this library picks - forceMerge
-
whether to merge past failing status checks and unsatisfied review requirements. Requires the credentials to be allowed to do so, and is refused with a
405otherwise - headCommit
-
the head the caller believes it is merging; see the note above
- mergeWhenChecksSucceed
-
whether to schedule the merge instead of performing it. Forgejo answers such a request with a success and merges later, so a
200from this variant does '''not''' mean the pull request is merged - mergedCommit
-
the commit that already holds the merge, for MergeStyle.ManuallyMerged only. Forgejo's
MergeCommitID - message
-
the merge commit's body, same caveat
- style
-
how to integrate the commits; see MergeStyle
- title
-
the merge commit's subject, absent to let Forgejo compose one. Ignored by MergeStyle.FastForwardOnly, which creates no commit
Attributes
- Companion
- object
- Supertypes
-
trait Serializabletrait Producttrait Equalsclass Objecttrait Matchableclass AnyShow all
How Forgejo should integrate a pull request's commits when it is merged.
How Forgejo should integrate a pull request's commits when it is merged.
The wire value is MergePullRequestOption.Do, and it is the '''only''' required property of that request body. Modelling it as an enum rather than as a String is not decoration: the six spellings below are the complete set Forgejo accepts, a seventh comes back as a 405, and the difference between two of them is the difference between rewriting a branch's history and not. A typo in a string literal would be discovered by a production merge.
A repository can forbid any of these — allow_merge_commits, allow_rebase, allow_rebase_explicit, allow_squash_merge and allow_fast_forward_only_merge are all fields of com.worxbend.codeberg4s.repositories.wire.RepositoryDto, and golden/pull/single-open.json shows one repository with allow_fast_forward_only_merge: false and its fork with true. Asking for a style the repository forbids is a 405, not a validation error this library can catch in advance.
Attributes
- Supertypes
-
trait Enumtrait Serializabletrait Producttrait Equalsclass Objecttrait Matchableclass AnyShow all
One inline remark to write, as CreatePullReviewComment expects it.
One inline remark to write, as CreatePullReviewComment expects it.
Used twice: on its own as the body of POST /repos/{owner}/{repo}/pulls/{index}/reviews/{id}/comments, and as an element of CreateReview.comments when a whole review is posted in one call. The pinned spec expresses that reuse literally — CreatePullReviewCommentOptions is a $ref to CreatePullReviewComment and nothing else — so this library models it once.
==Which line, and which side of the diff==
Forgejo carries two line numbers and uses 0 for "not this side": new_position addresses the line as it appears '''after''' the change, old_position addresses it as it appeared '''before'''. Getting them the wrong way round anchors the remark to an unrelated line rather than failing, which is why there is no constructor taking both. Pick the one that says what is meant:
for remark <- NewReviewComment.onNewLine("modules/git/hook.go", 42L, "this quoting is still wrong")
yield remark.spanning(3L)
NewReviewComment.onFile is the third possibility — a remark about the file as a whole, with neither position set — which Forgejo accepts and renders at the top of the file's diff.
Value parameters
- body
-
the remark, as Markdown source; trimmed and required by every constructor
- extraLinesCount
-
how many further lines the remark covers, absent for a single-line remark. Forgejo reads an absent value and a
0identically, so this library sends neither unless spanning was called - newPosition
-
the line on the new side of the diff, absent for a remark on the old side or on the file as a whole
- oldPosition
-
the line on the old side of the diff, absent for a remark on the new side or on the file as a whole
- path
-
the file the remark is about, relative to the repository root, exactly as com.worxbend.codeberg4s.pulls.ChangedFile.filename reports it
Attributes
- Companion
- object
- Supertypes
-
trait Serializabletrait Producttrait Equalsclass Objecttrait Matchableclass AnyShow all
Attributes
- Companion
- class
- Supertypes
-
trait Producttrait Mirrorclass Objecttrait Matchableclass Any
- Self type
-
NewReviewComment.type
A pull request on a Codeberg or Forgejo instance.
A pull request on a Codeberg or Forgejo instance.
Curated, not generated (ADR-0001), and owned by this group per docs/LEDGER.md. Label, Milestone and com.worxbend.codeberg4s.users.User are the issue and user waves' models, embedded unchanged: Forgejo returns the identical objects inside a PullRequest as inside an Issue, so forking them would be a review-blocking defect.
==The lifecycle is a state, not five fields==
state, closed_at, merged, merged_at, merge_commit_sha and merged_by collapse into state. That is the single most important thing about this model, and PullRequestState explains why — including the trap that a merged pull request reports state: "closed" on the wire.
==Keys deliberately not modelled==
Four of Forgejo's thirty-eight PullRequest keys are kept on com.worxbend.codeberg4s.pulls.wire.PullRequestDto and nowhere else:
assigneeduplicates the first element ofassignees, exactly as it does on an issue;requested_reviewers_teamsis an array of Forgejo'sTeammodel, whichdocs/LEDGER.mdassigns to the organisation wave. It is[]on every pull request in the fixtures, and inventing a shape from an empty array would be a guess;pin_orderdescribes a repository's pinned-pull-request ordering rather than the pull request;flowis Forgejo's AGit indicator,0on all five captured pull requests, and means nothing to a caller who did not push with AGit.
Value parameters
- allowsMaintainerEdit
-
whether the base repository's maintainers may push to the head branch
- assignees
-
everyone assigned, empty when unassigned — Forgejo sends
null, not[], in that case - author
-
the account that opened it, absent for content imported from another forge
- base
-
the branch the pull request merges '''into'''
- changedFileCount
-
how many files the pull request touches; the com.worxbend.codeberg4s.pulls.ChangedFile listing is the detail
- commentCount
-
ordinary issue-style comments, as the instance counts them;
0when it did not say - diffUrl
-
the browser URL of the unified diff — a
.diffdocument, not JSON, and not fetched by this library - dueDate
-
the deadline set on the pull request, absent when it has none
- head
-
the branch the pull request merges '''from'''; its repository differs from the base's for a fork pull request
- id
-
the instance-wide row identifier. Almost never what a caller wants: no endpoint accepts it, and every URL uses number
- isDraft
-
whether the pull request is marked as not ready for review. Independent of state: a draft is an open pull request that Forgejo refuses to merge, not a fourth lifecycle state
- isMergeable
-
the instance's own verdict, absent when it did not report one. Advisory: it is computed in the background, so it can be stale, and a merge can still be refused by a branch protection rule that this flag knows nothing about
- mergeBase
-
the common ancestor the diff is computed against
- number
-
the per-repository index every endpoint and every human uses; see PullRequestNumber
- patchUrl
-
the browser URL of the mailbox-format patch series
- requestedReviewers
-
the accounts whose review was asked for. Not the accounts that reviewed: those are on the reviews endpoint, and a reviewer who has already submitted may still appear here
- reviewCommentCount
-
comments made on the diff during a review, which Forgejo counts separately from commentCount
- state
-
open, closed, or merged together with the evidence of the merge; see PullRequestState
Attributes
- Supertypes
-
trait Serializabletrait Producttrait Equalsclass Objecttrait Matchableclass AnyShow all
One end of a pull request: the branch it merges into, or the branch it merges from.
One end of a pull request: the branch it merges into, or the branch it merges from.
Forgejo's PRBranchInfo, carried twice on every pull request as base and head. repository is a complete com.worxbend.codeberg4s.repositories.Repository object, not a reduced one — on golden/pull/single-open.json the head's repository is trim21/forgejo, a fork whose own parent is the full forgejo/forgejo — which is why this model reuses the repository wave's type per docs/LEDGER.md rather than inventing a smaller one.
Value parameters
- label
-
Forgejo's display label for the branch: the bare branch name for a same-repository pull request, and the fork's branch name for a cross-repository one
- ref
-
the Git reference this end points at. '''Not always a branch that exists''':
golden/pull/list-closed.jsonshows pull request 13726 whose headrefisrefs/pull/13726/head, because the fork branch it was opened from was deleted when it merged. Reading it back withGET /repos/{owner}/{repo}/branches/{branch}would answer404, so treat it as provenance rather than as something to fetch. A value com.worxbend.codeberg4s.repositories.BranchName refuses — a traversal segment, say — costs the caller this field and not the whole pull request - repository
-
the repository this end lives in, when the endpoint supplied it
- repositoryId
-
the numeric id of the repository this end lives in. Worth reading even when repository is present: comparing
base.repositoryIdwithhead.repositoryIdis how a caller tells a fork pull request from an internal one - sha
-
the commit at this end when the pull request was last synchronised
Attributes
- Supertypes
-
trait Serializabletrait Producttrait Equalsclass Objecttrait Matchableclass AnyShow all
Attributes
- Supertypes
-
class Objecttrait Matchableclass Any
- Self type
-
PullRequestHead.type
Attributes
- Supertypes
-
class Objecttrait Matchableclass Any
- Self type
-
PullRequestNumber.type
Attributes
- Companion
- class
- Supertypes
-
trait Producttrait Mirrorclass Objecttrait Matchableclass Any
- Self type
-
PullRequestQuery.type
The filters GET /repos/{owner}/{repo}/pulls accepts, as one value rather than as seven parameters.
The filters GET /repos/{owner}/{repo}/pulls accepts, as one value rather than as seven parameters.
Built by starting from PullRequestQuery.Empty and naming what should change:
PullRequestQuery.Empty
.withState(StateFilter.All)
.sortedBy(PullRequestSort.RecentUpdate)
.withBase(mainBranch)
'''Only what is set is sent.''' Every field here is absent by default and an absent field contributes no query parameter at all, which matters because Forgejo's defaults are not this library's to guess: omitting state means open pull requests only, and sending state= empty is not the same request. See com.worxbend.codeberg4s.issues.StateFilter, which this group reuses rather than forking — the endpoint takes the same open/closed/all vocabulary as the issue listing.
The builder methods exist because .scalafix.conf bans default arguments, and a seven-argument copy at every call site would be worse than either. Each returns a new query; the type is immutable and safe to share.
Value parameters
- base
-
restrict to pull requests merging into this branch
- head
-
restrict to pull requests merging from this branch; see PullRequestHead for the
owner:branchform - labels
-
restrict to pull requests carrying '''all''' of these labels, by id. Sent as a repeated
labelsparameter rather than as one comma-joined value — the spec declarescollectionFormat: multihere, where the issue listing declares a comma-joined string - milestone
-
restrict to one milestone, by id. An id and not a title, unlike the issue listing's
milestonesparameter, which is Forgejo's inconsistency and not this library's - poster
-
restrict to pull requests opened by this login
- sort
-
the ordering to ask for; absent means the instance's default
- state
-
which lifecycle states to include; absent means Forgejo's own default of open only. Note that
closedhere includes '''merged''' pull requests, because Forgejo'sstatedoes — see PullRequestState
Attributes
- Companion
- object
- Supertypes
-
trait Serializabletrait Producttrait Equalsclass Objecttrait Matchableclass AnyShow all
The orderings GET /repos/{owner}/{repo}/pulls accepts in its sort parameter.
The orderings GET /repos/{owner}/{repo}/pulls accepts in its sort parameter.
Forgejo's own seven spellings, none of which is a plain field name and two of which are run together without a separator (recentupdate, leastupdate). An enum rather than a String for the reason MergeStyle gives: a misspelling is not rejected, it is ignored, and the caller silently gets the instance's default ordering instead of the one they asked for.
There is no case for the default. Leaving PullRequestQuery.sort unset is what asks for it, and that is a different request from asking for any of these — see PullRequestQuery.
Attributes
- Supertypes
-
trait Enumtrait Serializabletrait Producttrait Equalsclass Objecttrait Matchableclass AnyShow all
Where a PullRequest is in its lifecycle, with the evidence of a merge attached to the one state that has any.
Where a PullRequest is in its lifecycle, with the evidence of a merge attached to the one state that has any.
A pull request is open, closed without being merged, or merged. Forgejo spreads that across '''five''' independent fields — state, closed_at, merged, merged_at, merge_commit_sha and merged_by — which is exactly the shape SCALA_CODE_STYLE.md forbids a domain model to keep: as six optional fields a caller can build a pull request that is open and merged, or merged with no merge commit and closed at a time it was never closed, and every reader has to remember which combinations the server actually produces.
==state alone cannot tell you==
'''A merged pull request reports state: "closed".''' golden/pull/single-merged.json is pull request 13726 with "state": "closed", "merged": true, a merged_at, a merge_commit_sha and a merged_by, and golden/pull/list-closed.json contains that same pull request beside 13730 and 13711, which are "closed" and '''not''' merged. Anything that branches on state and stops there reports every merge as a rejection. That is why from looks at the merge evidence before it looks at state.
==Why the merged fields are still optional==
They are measured, not assumed. In golden/pull/list-closed.json pull request 13726 arrives with merged: true, merged_at and merge_commit_sha all populated and "merged_by": null — while golden/pull/single-merged.json, the '''same''' pull request read through GET /pulls/{index}, carries a full merged_by user. The listing endpoint simply does not resolve the merging account. Making mergedBy mandatory would therefore fail every merged pull request on every listing, so Merged keeps each piece of evidence optional and only guarantees that an Open or a Closed pull request has none of it.
Attributes
- Companion
- object
- Supertypes
-
trait Enumtrait Serializabletrait Producttrait Equalsclass Objecttrait Matchableclass AnyShow all
Attributes
- Companion
- enum
- Supertypes
-
trait Sumtrait Mirrorclass Objecttrait Matchableclass Any
- Self type
-
PullRequestState.type
One review of a pull request, as GET /repos/{owner}/{repo}/pulls/{index}/reviews reports it.
One review of a pull request, as GET /repos/{owner}/{repo}/pulls/{index}/reviews reports it.
Owned by this group per docs/LEDGER.md. A "review" here is any row on that endpoint, which includes the review '''requests''' Forgejo records when someone is asked to look at a pull request: on golden/pull/reviews-list.json two of the three rows are ReviewState.RequestReview with an empty body and no commit, and only the third is an approval. state is what separates them.
Forgejo's PullReview also carries a team — a review requested from a whole team rather than an account. That field is null on all three fixture rows and its payload is the organisation wave's Team model, so it is kept on com.worxbend.codeberg4s.pulls.wire.ReviewDto and not modelled here.
Value parameters
- author
-
the account that reviewed, or whose review was requested
- body
-
the review's summary text, absent when the reviewer left none. Empty on every row of the fixture, which com.worxbend.codeberg4s.codec.JsonFields.text reads as absence
- commentCount
-
how many inline diff comments the review carries;
0for a review request and for a summary-only review - commit
-
the head commit the review was made against, absent for a review request — nothing has been reviewed yet, so there is nothing to pin it to
- htmlUrl
-
the browser URL of the review, absent for a review request —
""on the fixture's two request rows and a real anchor on the approval - id
-
the instance-wide identifier; see ReviewId
- isDismissed
-
whether a maintainer dismissed the review, which removes it from the approval count without deleting it
- isOfficial
-
whether the review counts towards the base branch's required-approval rule. A review from someone without write access is recorded but not official
- isStale
-
whether the pull request has moved on since commit, which makes the verdict advisory rather than current
- state
-
what the review said, absent when the instance sent a value this library does not recognise — including the
""it sends for a stateless row. See ReviewState.parse
Attributes
- Supertypes
-
trait Serializabletrait Producttrait Equalsclass Objecttrait Matchableclass AnyShow all
One inline remark attached to a diff line, as GET /repos/{owner}/{repo}/pulls/{index}/reviews/{id}/comments reports it.
One inline remark attached to a diff line, as GET /repos/{owner}/{repo}/pulls/{index}/reviews/{id}/comments reports it.
Forgejo's PullReviewComment. This is '''not''' com.worxbend.codeberg4s.issues.Comment: a pull request's ordinary conversation lives on the issue endpoints and carries no path, no diff hunk and no line numbers, whereas every value here is anchored to a position in a file. The two are deliberately separate models, because merging them would produce one whose half-populated fields depend on which endpoint answered.
==Derived from the pinned spec, not from a capture==
golden/MANIFEST.md records no review-comment fixture — the anonymous harvest could reach /pulls/{n}/reviews but every review of the harvested pull requests carried comments_count: 0, so there was nothing to capture. The fifteen fields below are the fifteen properties of the pinned spec's PullReviewComment definition, and docs/HAZARDS.md §1 is why every one of them is treated as absent-able. Should a capture ever contradict this model, the capture wins.
==The two positions, and what 0 means==
Forgejo types position and original_position as uint64 and uses 0 as "not this side of the diff": a comment on an added line has a position and 0 for originalPosition, and a comment on a removed line has it the other way round. That sentinel is preserved rather than folded into an Option, because 0 is also what an absent key decodes to and the two are genuinely indistinguishable on the wire. Read them together with path: a comment with neither position set is a remark about the file rather than about a line.
Value parameters
- author
-
the account that wrote the remark
- body
-
the remark itself, as Markdown source
- commit
-
the commit the comment currently applies to
- diffHunk
-
the excerpt of the diff the remark is anchored to, as Forgejo rendered it at the time
- extraLinesCount
-
how many further lines after position the remark covers;
0is a single-line comment, which is Forgejo's own reading of the field - id
-
the instance-wide identifier, and the only way to address the comment; see ReviewCommentId
- originalCommit
-
the commit the comment was written against, which differs from commit once the branch has moved
- originalPosition
-
the line in the '''old''' side of the diff,
0when the comment is not on the old side - path
-
the file the remark is about, relative to the repository root
- position
-
the line in the '''new''' side of the diff,
0when the comment is not on the new side - resolver
-
the account that marked the conversation resolved, absent while it is still open
- reviewId
-
the review the comment was written as part of, absent when the instance sent nothing or sent Forgejo's
0placeholder for a comment not yet attached to a submitted review
Attributes
- Supertypes
-
trait Serializabletrait Producttrait Equalsclass Objecttrait Matchableclass AnyShow all
Attributes
- Supertypes
-
class Objecttrait Matchableclass Any
- Self type
-
ReviewCommentId.type
Attributes
- Supertypes
-
class Objecttrait Matchableclass Any
- Self type
-
ReviewId.type
Attributes
- Companion
- class
- Supertypes
-
trait Producttrait Mirrorclass Objecttrait Matchableclass Any
- Self type
-
ReviewRequest.type
Who to ask for a review, or whose request to withdraw — Forgejo's PullReviewRequestOptions.
Who to ask for a review, or whose request to withdraw — Forgejo's PullReviewRequestOptions.
One type for two operations, because Forgejo sends the same body to both: com.worxbend.codeberg4s.pulls.PullRequestApi.requestReviews adds the named reviewers and com.worxbend.codeberg4s.pulls.PullRequestApi.removeReviewRequests removes them. Nothing about the value says which; the endpoint does.
==Accounts and teams are different keys, not one list==
reviewers holds account handles and team_reviewers holds team '''names''', and Forgejo will not look a value up in the other list. So the two are separate here as well, and each is built from an already-validated type:
- an account is a com.worxbend.codeberg4s.users.Username, which has already rejected a blank handle and a handle containing a slash;
- a team is a com.worxbend.codeberg4s.organizations.Team — the wave-5 model, consumed rather than re-described. Forgejo identifies a team by name and a name is easy to mistype, so this library takes the team value a caller read from
client.organizationsinstead of a string it cannot check.
'''An empty list contributes no key.''' Asking for nobody is not the same request as asking for the default, and a PullReviewRequestOptions with both lists empty is a 422 rather than a no-op.
Value parameters
- reviewers
-
the accounts to ask, in order
- teams
-
the team names to ask, in order
Attributes
- Companion
- object
- Supertypes
-
trait Serializabletrait Producttrait Equalsclass Objecttrait Matchableclass AnyShow all
What a Review said.
What a Review said.
Forgejo's ReviewStateType, and the one enum in this group whose wire values are '''upper''' case with underscores — "APPROVED", "REQUEST_REVIEW" — rather than the lowercase spellings the rest of the API uses. golden/pull/reviews-list.json shows two of them on one pull request; the others are read from Forgejo's own ReviewStateType constants rather than measured, which is exactly why parse answers None on an unrecognised value instead of failing.
Note that a review request is itself a review here: asking someone to review produces a RequestReview row on the reviews endpoint, so a caller counting approvals must filter rather than count.
Attributes
- Companion
- object
- Supertypes
-
trait Enumtrait Serializabletrait Producttrait Equalsclass Objecttrait Matchableclass AnyShow all
Attributes
- Companion
- enum
- Supertypes
-
trait Sumtrait Mirrorclass Objecttrait Matchableclass Any
- Self type
-
ReviewState.type
Attributes
- Companion
- class
- Supertypes
-
trait Producttrait Mirrorclass Objecttrait Matchableclass Any
- Self type
-
SubmitReview.type
Everything POST /repos/{owner}/{repo}/pulls/{index}/reviews/{id} may be told, as one value.
Everything POST /repos/{owner}/{repo}/pulls/{index}/reviews/{id} may be told, as one value.
Forgejo's SubmitPullReviewOptions: it finishes a review that already exists as the reviewer's pending draft — created by CreateReview with no event, and filled in with com.worxbend.codeberg4s.pulls.PullRequestApi.createReviewComment — and turns it into a submitted verdict that everyone can see.
'''The event is required here''', unlike on CreateReview, because submitting without saying what the review says has no meaning: Forgejo answers 422. ReviewState.Pending is equally meaningless — it is what the review already is — and ReviewState.RequestReview belongs to a different endpoint entirely; both come back as a 422 rather than as anything this library can catch in advance.
Value parameters
- body
-
the summary text, absent to keep whatever the pending review already carried. Forgejo requires one for ReviewState.Comment and ReviewState.RequestChanges when the draft has none
- event
-
what the review says: ReviewState.Approved, ReviewState.RequestChanges or ReviewState.Comment
Attributes
- Companion
- object
- Supertypes
-
trait Serializabletrait Producttrait Equalsclass Objecttrait Matchableclass AnyShow all
How POST /repos/{owner}/{repo}/pulls/{index}/update should bring a pull request's branch up to date with its base.
How POST /repos/{owner}/{repo}/pulls/{index}/update should bring a pull request's branch up to date with its base.
This operation writes to the '''head''' branch, and the two cases differ in whether that write is destructive:
- Merge records a merge commit of the base into the head. Every existing commit keeps its sha, so anyone who has the branch checked out can fast-forward;
- Rebase replays the head's commits onto the base and '''force-pushes''' the result. Every commit gets a new sha, and every existing checkout of the branch — and every review pinned to one of the old commits — is left pointing at history that no longer exists.
Forgejo has no third option and no "leave it to the repository's preference": its handler reads the style query parameter and treats anything other than the literal rebase as a merge. Naming one of these is therefore exactly as expressive as omitting the parameter, and considerably harder to get wrong by accident, which is why com.worxbend.codeberg4s.pulls.PullRequestApi.updateBranch requires it.
Attributes
- Supertypes
-
trait Enumtrait Serializabletrait Producttrait Equalsclass Objecttrait Matchableclass AnyShow all
Types
The branch a pull request is opened '''from''', in the spelling CreatePullRequestOption.head expects.
The branch a pull request is opened '''from''', in the spelling CreatePullRequestOption.head expects.
Forgejo overloads one string with two meanings: a bare branch names a branch of the same repository, and owner:branch names a branch of a fork. golden/pull/single-open.json is the second kind — head fix-pep691 in trim21/forgejo against base forgejo in forgejo/forgejo.
There is no from(value: String) here, and that is the point. The two spellings are produced by the two constructors below out of values that are '''already''' validated — an com.worxbend.codeberg4s.repositories.Owner cannot contain a / or a control character, and a com.worxbend.codeberg4s.repositories.BranchName cannot contain a traversal segment — so this type never has to parse a colon back out of a string and never has to decide what a:b:c meant. Both constructors are total, which is why neither returns an Either.
Attributes
The number a repository gives a pull request — the {index} of /repos/{owner}/{repo}/pulls/{index}.
The number a repository gives a pull request — the {index} of /repos/{owner}/{repo}/pulls/{index}.
This is '''not''' PullRequest.id. Forgejo returns both: id is the instance-wide row identifier, which no endpoint in this group accepts, and number is the per-repository index every URL and every human uses. They are both int64 and both plausible values for each other, so keeping them in different types is the only thing that stops a 404 — or, worse, a successful read of an unrelated pull request.
==Why this is not IssueNumber==
Forgejo numbers issues and pull requests from one shared per-repository sequence, so pull request 13731 and issue 13731 are the same underlying row and GET /issues/13731 really does answer with the pull request. The two types are still kept apart, because the '''endpoints''' are not interchangeable: GET /pulls/{index} on an issue number that belongs to a plain issue answers 404, and GET /issues/{index} on a pull request answers with the issue-shaped projection rather than with a PullRequest. A single type would make both mistakes silent, and neither is worth the saving of one opaque type. There is deliberately no conversion between them for the same reason.
Attributes
The instance-wide identifier of a ReviewComment — the {comment} of /repos/{owner}/{repo}/pulls/{index}/reviews/{id}/comments/{comment}.
The instance-wide identifier of a ReviewComment — the {comment} of /repos/{owner}/{repo}/pulls/{index}/reviews/{id}/comments/{comment}.
Kept apart from ReviewId even though both are int64 and both appear in the same path, one segment from each other. /reviews/{id}/comments/{comment} with the two swapped is a request Forgejo answers 404 to, and a 404 on a review comment reads like "the maintainer deleted it" rather than like a caller bug. The types are what make that mistake fail to compile instead.
==No fixture proves the shape of the values==
golden/MANIFEST.md holds no capture of a review-comment payload, so the only thing asserted here is Forgejo's declared type — a positive int64, as every other row identifier in the API is. See ReviewComment for what that means for the model as a whole.
Attributes
The instance-wide identifier of a Review — the {id} of /repos/{owner}/{repo}/pulls/{index}/reviews/{id}.
The instance-wide identifier of a Review — the {id} of /repos/{owner}/{repo}/pulls/{index}/reviews/{id}.
Reviews are addressed by this id and never by a per-pull-request index: the ids on golden/pull/reviews-list.json are 1654064, 1654067 and 1654076 for three reviews of the '''same''' pull request, which is what an instance-wide sequence looks like.