diff --git a/docs/app/assets/icons/entire.svg b/docs/app/assets/icons/entire.svg new file mode 100644 index 000000000..aeec67d4c --- /dev/null +++ b/docs/app/assets/icons/entire.svg @@ -0,0 +1,3 @@ + + + diff --git a/docs/content/4.providers/entire.md b/docs/content/4.providers/entire.md new file mode 100644 index 000000000..b5a99d95a --- /dev/null +++ b/docs/content/4.providers/entire.md @@ -0,0 +1,233 @@ +--- +title: Entire +description: "Use Entire: repositories, file contents, commits, and trails as issues and pull requests, with their discussions, approvals and code reviews." +icon: i-custom-entire +--- + +The Entire provider works with the repositories that [Entire](https://entire.com) hosts, which live under `et/` in Entire's URLs. Entire organises work into trails: a project trail describes a piece of work, and each repository the work touches gets a change, a branch with its own discussions, approvals and code reviews. The provider reads project trails as issues and changes as pull requests, and normalises both into the shared [data model](/concepts/data-model). + + + +::provider-header{provider="entire"} +| Detail | Value | +| --- | --- | +| Import | `forges/entire` | +| Factories | `entire()` | +| Auth | `token` | +:: + + +## Authentication + +Entire has no personal access tokens. Sign in with the [Entire CLI](https://docs.entire.com/) and run `entire auth token` to print a token for your account. The provider sends it as `Authorization: Bearer `: + +```ts +import { entire } from 'forges/entire' + +const forge = entire({ + auth: { type: 'token', token: process.env.ENTIRE_TOKEN! }, +}) +``` + +The token expires after a few hours. For a long-running program, pass `token` as a function, and the provider calls it before every request: + +```ts +import { execFileSync } from 'node:child_process' +import { entire } from 'forges/entire' + +const forge = entire({ + auth: { type: 'token', token: () => execFileSync('entire', ['auth', 'token'], { encoding: 'utf8' }).trim() }, +}) +``` + +Entire has no anonymous reads, so every call needs a token. + +## Instance + +The `baseUrl` is Entire's control plane and defaults to `https://us.console.entire.io`. The control plane knows which processing cell holds each project and repository, such as `https://aws-eu-west-2.api.entire.io` for a project in the UK, and the provider sends every request about a project's repositories and trails to that cell. It looks up each cell once and keeps it for the life of the provider. An account with access to a repository but not to its project reaches the project's trails through the repository's cell. + +A repository ref's `owner` is the project and its `name` is the repository, so `https://entire.com/et/forges/forges-fixtures` is `{ owner: 'forges', name: 'forges-fixtures' }`. The provider reads only repositories that Entire hosts. A GitHub repository that Entire mirrors under `gh/` is a GitHub repository, so read it with the [GitHub provider](/providers/github). + +## Repositories and contents + +`repos.get()` reads a repository, `repos.list()` lists the repositories your account can reach, and `repos.byOwner()` lists the repositories of a project. A project is the owner, so a user's login names no repositories of its own. `repos.collaborators()` lists the accounts with access to a repository and their roles. + +`contents.getFile()`, `contents.tree()`, `contents.branches()`, `contents.tags()`, `contents.resolveRef()` and `contents.compare()` read the repository's git data, and so do `commits.list()` and `commits.get()`. `contents.compare()` compares `head` with the merge base of the two revisions, so its files are the changes that `head` adds. + +Entire has no labels, milestones, issue types or releases. + +## Trails + +A project trail is an issue. Its ref names the project rather than a repository, with a namespace ref as `repo`: + +```ts +const issue = await forge.threads.get({ + forge: 'entire', + instance: 'entire.com', + repo: { forge: 'entire', instance: 'entire.com', owner: 'forges', name: '', kind: 'namespace' }, + kind: 'issue', + number: '1', +}) +``` + +`threads.list()` on a repository lists the project trails of the repository's project as issues and the repository's changes as pull requests. On a namespace ref, it lists the project trails alone. A project trail's `type`, such as `feature` or `bug`, is the thread's `issueType`. + +A change is a pull request, numbered within its repository. `threads.files()` and `threads.commits()` read the change's branch against its merge base. `threads.reviews()` lists the change's approvals and its code reviews. An approval has no comments of its own, and a code review's comments are its findings, with the file and line each one is about. `threads.reviewThreads()` reads each finding with the discussion under it. + +`threads.comments()` reads the messages of a trail's discussions, oldest first, with each comment's `thread` naming its discussion and whether it's resolved. The discussions of code review findings are left out, because `threads.reviewThreads()` reads those. `threads.events()` reads the trail's timeline: comments, approvals, code reviews, commits, and the trail opening and merging. + +A project trail's page is `https://entire.com/et//-/trails/`, and a change's page is `https://entire.com/et///trails/`. `urlFor()` builds both, and `parseUrl()` reads them back. + +## Writing trails + +`threads.create()` with `kind: 'issue'` opens a project trail. On a repository ref, the trail's scope is that repository, and on a namespace ref, it is the whole project. With `kind: 'pull_request'`, it opens a project trail with a change from `head` into `base`, and resolves with the change. Entire keeps a change's description on its project trail, so `body` is the trail's body. `threads.get()` reads a change's body from its trail, and `threads.update()` writes it there. + +`threads.update()`, `threads.close()`, `threads.reopen()` and `threads.setAssignees()` change a project trail or a change. Closing a project trail leaves its changes open. Pass assignees as actors, or as logins, which the provider sends as `@`. + +`threads.createComment()` starts a discussion with the comment as its first message. `threads.updateComment()` and `threads.deleteComment()` edit and delete a message, and read the trail's discussions to find the one that holds it. + +`threads.createReview()` with `event: 'approve'` or `event: 'request_changes'` submits an approval, which has a body but no inline comments. With `event: 'comment'`, it starts a code review and publishes each inline comment as a finding, with `body` as the review's summary. A review with a body and no comments publishes the body as a finding on the whole change. Entire has no pending reviews, and a finding is always on the head side of the diff. `threads.replyToReviewComment()` replies in the finding's discussion, and `threads.resolveReviewThread()` and `threads.unresolveReviewThread()` resolve and reopen that discussion. + +`threads.merge()` merges a change once its gates pass, with `method: 'merge'` only. Pass `sha`, and Entire refuses the merge with `BranchMovedError` if the head branch has moved. `threads.updateBranch()` merges the base into the change's branch, or rebases the branch onto the base with `method: 'rebase'`. + +`repos.addCollaborator()` grants an account the `read`, `write` or `admin` role on a repository. Entire grants access by account id, so pass the account as an actor. + +## Accounts + +`users.me()` reads the account the token belongs to. Entire has no way to read another account by login, and no sponsorship, follow feeds or repository events. + + +## Capabilities + + +::provider-capabilities{provider="entire"} +| Capability | Support | Without credentials | +| --- | --- | --- | +| `experimental` | ✅ | ✅ | +| `sources.stream` | ❌ | ❌ | +| `repos.get` | ✅ | ❌ | +| `users.get` | ❌ | ❌ | +| `users.me` | ✅ | ❌ | +| `users.sponsorable` | ❌ | ❌ | +| `users.events` | ❌ | ❌ | +| `users.block` | ❌ | ❌ | +| `repos.list` | ✅ | ❌ | +| `repos.byOwner` | ✅ | ❌ | +| `repos.labels` | ∅ | ∅ | +| `repos.createLabel` | ∅ | ∅ | +| `repos.milestones` | ∅ | ∅ | +| `repos.issueTypes` | ∅ | ∅ | +| `repos.collaborators` | ✅ | ❌ | +| `repos.contributors` | ❌ | ❌ | +| `repos.contributorStats` | ❌ | ❌ | +| `repos.templates` | ❌ | ❌ | +| `repos.permissionFor` | ❌ | ❌ | +| `repos.branchRules` | ❌ | ❌ | +| `repos.addCollaborator` | ✅ | ❌ | +| `repos.assignableUsers` | ❌ | ❌ | +| `repos.reviewerCandidates` | ❌ | ❌ | +| `repos.events` | ❌ | ❌ | +| `orgs.teams` | ❌ | ❌ | +| `orgs.teamMembers` | ❌ | ❌ | +| `orgs.block` | ❌ | ❌ | +| `threads.get` | issue, PR | ❌ | +| `threads.list` | issue, PR | ❌ | +| `threads.getMany` | ✅ | ❌ | +| `threads.closingIssues` | ❌ | ❌ | +| `threads.closingPullRequests` | ❌ | ❌ | +| `threads.events` | issue, PR | ❌ | +| `threads.comments` | issue, PR | ❌ | +| `threads.getComment` | issue, PR | ❌ | +| `threads.createComment` | issue, PR | ❌ | +| `threads.updateComment` | issue, PR | ❌ | +| `threads.deleteComment` | issue, PR | ❌ | +| `threads.hideComment` | ∅ | ∅ | +| `threads.reactions` | ∅ | ∅ | +| `threads.react` | ∅ | ∅ | +| `threads.create` | issue, PR | ❌ | +| `threads.update` | issue, PR | ❌ | +| `threads.close` | issue, PR | ❌ | +| `threads.reopen` | issue, PR | ❌ | +| `threads.lock` | ∅ | ∅ | +| `threads.setLabels` | ∅ | ∅ | +| `threads.addLabels` | ∅ | ∅ | +| `threads.removeLabels` | ∅ | ∅ | +| `threads.setMilestone` | ∅ | ∅ | +| `threads.setIssueType` | ∅ | ∅ | +| `threads.setAssignees` | issue, PR | ❌ | +| `threads.requestReview` | ❌ | ❌ | +| `threads.merge` | ✅ | ❌ | +| `threads.updateBranch` | ✅ | ❌ | +| `threads.transfer` | ∅ | ∅ | +| `threads.markDuplicate` | ∅ | ∅ | +| `threads.subscription` | ❌ | ❌ | +| `threads.subscribe` | ❌ | ❌ | +| `threads.checks` | ❌ | ❌ | +| `threads.files` | ✅ | ❌ | +| `threads.commits` | ✅ | ❌ | +| `threads.reviews` | ✅ | ❌ | +| `threads.getReview` | ✅ | ❌ | +| `threads.createReview` | ✅ | ❌ | +| `threads.submitReview` | ❌ | ❌ | +| `threads.approve` | ✅ | ❌ | +| `threads.replyToReviewComment` | ✅ | ❌ | +| `threads.reviewThreads` | ✅ | ❌ | +| `threads.resolveReviewThread` | ✅ | ❌ | +| `notifications.list` | ❌ | ❌ | +| `notifications.markRead` | ❌ | ❌ | +| `notifications.markDone` | ❌ | ❌ | +| `notifications.unsubscribe` | ❌ | ❌ | +| `notifications.markAllRead` | ❌ | ❌ | +| `notifications.markAllDone` | ❌ | ❌ | +| `notifications.unreadCount` | ❌ | ❌ | +| `installations.list` | ❌ | ❌ | +| `checks.list` | ❌ | ❌ | +| `checks.get` | ❌ | ❌ | +| `checks.report` | ❌ | ❌ | +| `checks.rerun` | ❌ | ❌ | +| `ci.runs` | ❌ | ❌ | +| `ci.getRun` | ❌ | ❌ | +| `ci.jobs` | ❌ | ❌ | +| `ci.getJob` | ❌ | ❌ | +| `ci.log` | ❌ | ❌ | +| `ci.rerunFailed` | ❌ | ❌ | +| `contents.getFile` | ✅ | ❌ | +| `contents.tree` | ✅ | ❌ | +| `contents.branches` | ✅ | ❌ | +| `contents.tags` | ✅ | ❌ | +| `contents.resolveRef` | ✅ | ❌ | +| `contents.compare` | ✅ | ❌ | +| `contents.commitFiles` | ❌ | ❌ | +| `commits.list` | ✅ | ❌ | +| `commits.get` | ✅ | ❌ | +| `commits.comments` | ❌ | ❌ | +| `commits.getComment` | ❌ | ❌ | +| `commits.createComment` | ❌ | ❌ | +| `commits.updateComment` | ❌ | ❌ | +| `commits.deleteComment` | ❌ | ❌ | +| `commits.hideComment` | ❌ | ❌ | +| `releases.list` | ∅ | ∅ | +| `releases.get` | ∅ | ∅ | +| `releases.latest` | ∅ | ∅ | +| `releases.getByTag` | ∅ | ∅ | +| `releases.downloadAsset` | ∅ | ∅ | +| `releases.create` | ∅ | ∅ | +| `releases.update` | ∅ | ∅ | +| `webhooks.ingest` | ❌ | ❌ | +| `webhooks.list` | ❌ | ❌ | +| `webhooks.create` | ❌ | ❌ | +| `webhooks.update` | ❌ | ❌ | +| `webhooks.delete` | ❌ | ❌ | +| `webhooks.rotateSecret` | ❌ | ❌ | +| `webhooks.deliveries` | ❌ | ❌ | +| `webhooks.redeliver` | ❌ | ❌ | +| `search.threads` | ❌ | ❌ | +| `search.repos` | ❌ | ❌ | +| `search.commits` | ❌ | ❌ | +| `search.code` | ❌ | ❌ | +| `securityAlerts.list` | ❌ | ❌ | +| `eventKinds` | native | native | +| `authKinds` | `token` | `token` | +| `limits` | unknown | unknown | +:: + diff --git a/docs/content/4.providers/index.md b/docs/content/4.providers/index.md index 085955a6d..2bf47bf9c 100644 --- a/docs/content/4.providers/index.md +++ b/docs/content/4.providers/index.md @@ -26,6 +26,7 @@ A provider is what connects `forges` to one particular forge. It translates the | [Tangled](/providers/tangled) | `forges/tangled` | `tangled()` | | [Cloudflare Artifacts](/providers/cloudflare-artifacts) | `forges/cloudflare-artifacts` | `cloudflareArtifacts()` | | [Sourcehut](/providers/sourcehut) | `forges/sourcehut` | `sourcehut()` | +| [Entire](/providers/entire) | `forges/entire` | `entire()` | :: diff --git a/docs/content/5.reference/11.capability-matrix.md b/docs/content/5.reference/11.capability-matrix.md index 93f6dd875..78a5fb172 100644 --- a/docs/content/5.reference/11.capability-matrix.md +++ b/docs/content/5.reference/11.capability-matrix.md @@ -11,134 +11,134 @@ To learn what each level of support means, see [Capabilities](/concepts/capabili ::capability-matrix -| Capability | GitHub | GitLab | Bitbucket | Forgejo | Gitea | Gitee | Azure DevOps | Cursor Origin | Pushin.eu | Tangled | Cloudflare Artifacts | Sourcehut | -| --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | -| `experimental` | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ✅ | ✅ | ✅ | ✅ | ❌ | -| `sources.stream` | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ✅ | ❌ | ❌ | -| `repos.get` | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | experimental | ✅ | ✅ | ✅ | ✅ | -| `users.get` | ✅ | ✅ | ❌ | ✅ | ✅ | ✅ | ❌ | ❌ | ❌ | ✅ | ❌ | ✅ | -| `users.me` | ✅ (only with `classic` or `fine-grained`) | ✅ | ✅ | ✅ | ✅ | ✅ | ❌ | ❌ | ✅ | ✅ | ❌ | ✅ | -| `users.sponsorable` | ✅ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | -| `users.events` | ✅ | ✅ | ❌ | ✅ | ✅ | ✅ | ❌ | ❌ | ❌ | ✅ | ❌ | ❌ | -| `users.block` | ✅ (only with `classic` or `fine-grained`) | ❌ | ∅ | ✅ | ✅ | ❌ | ∅ | ∅ | ∅ | ∅ | ❌ | ❌ | -| `repos.list` | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | unverified | ✅ | ✅ | ✅ | ✅ | -| `repos.byOwner` | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ❌ | ❌ | ✅ | ✅ | ✅ | -| `repos.labels` | ✅ | ✅ | ∅ | ✅ | ✅ | ✅ | ❌ | ❌ | ✅ | ✅ | ❌ | emulated | -| `repos.createLabel` | ✅ | ✅ | ∅ | ✅ | ✅ | unverified | ❌ | ❌ | ✅ | ✅ | ❌ | ❌ | -| `repos.milestones` | ✅ | ✅ | ∅ | ✅ | ✅ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | -| `repos.issueTypes` | ✅ | ❌ | ∅ | ∅ | ∅ | ❌ | ❌ | ∅ | ∅ | ∅ | ❌ | ❌ | -| `repos.collaborators` | ✅ | ✅ | ❌ | ✅ | ✅ | ✅ | ❌ | ❌ | ✅ | ✅ | ❌ | ✅ | -| `repos.contributors` | ✅ | ✅ | ❌ | ❌ | ❌ | ✅ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | -| `repos.contributorStats` | ✅ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | -| `repos.templates` | ✅ | ✅ | ∅ | ✅ | ✅ | ❌ | ∅ | ∅ | ∅ | ∅ | ❌ | ❌ | -| `repos.permissionFor` | ✅ | ✅ | ❌ | ✅ | ✅ | ❌ | ❌ | ❌ | ✅ | ✅ | ❌ | emulated | -| `repos.branchRules` | ✅ | ✅ | ❌ | ✅ | ✅ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | -| `repos.addCollaborator` | ✅ | ✅ | ❌ | ✅ | ✅ | ❌ | ❌ | ❌ | ✅ | ✅ | ❌ | ❌ | -| `repos.assignableUsers` | ✅ | ✅ | ❌ | ✅ | ✅ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | -| `repos.reviewerCandidates` | emulated | emulated | ❌ | ✅ | ✅ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | -| `repos.events` | ✅ | ✅ | ❌ | ✅ | ✅ | ✅ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | -| `orgs.teams` | ✅ | ✅ | ❌ | ✅ | ✅ | ❌ | ✅ | ❌ | ✅ | ❌ | ❌ | ❌ | -| `orgs.teamMembers` | ✅ | ✅ | ❌ | ✅ | ✅ | ❌ | ✅ | ❌ | ✅ | ❌ | ❌ | ❌ | -| `orgs.block` | ✅ | ❌ | ∅ | ✅ | ✅ | ❌ | ∅ | ∅ | ∅ | ∅ | ❌ | ❌ | -| `threads.get` | issue, PR, discussion | issue, PR | PR | issue, PR | issue, PR | issue, PR | issue, PR | PR (experimental) | issue, PR | issue, PR | ❌ | issue, PR | -| `threads.list` | issue, PR, discussion | issue, PR | PR | issue, PR | issue, PR | issue, PR | issue, PR | PR (experimental) | issue, PR | issue, PR | ❌ | issue, PR | -| `threads.getMany` | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | experimental | ✅ | ✅ | ❌ | ✅ | -| `threads.closingIssues` | ✅ | ✅ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | -| `threads.closingPullRequests` | ✅ | ✅ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | -| `threads.events` | issue, PR, discussion | issue, PR | PR | issue, PR | issue, PR | issue, PR | issue, PR | PR (experimental) | issue (emulated), PR (emulated) | issue, PR | ❌ | issue, PR | -| `threads.comments` | issue, PR, discussion | issue, PR | PR | issue, PR | issue, PR | issue, PR | issue (experimental), PR | PR (experimental) | issue, PR | issue, PR | ❌ | issue, PR | -| `threads.getComment` | issue, PR, discussion | issue, PR | PR (emulated) | issue, PR | issue, PR | issue (emulated), PR (emulated) | issue (experimental), PR | PR (unverified) | issue (emulated), PR (emulated) | issue (emulated), PR (emulated) | ❌ | issue (emulated), PR (emulated) | -| `threads.createComment` | issue, PR, discussion | issue, PR | PR | issue, PR | issue, PR | issue (unverified), PR | issue (experimental), PR | PR (experimental) | issue, PR | issue, PR | ❌ | ❌ | -| `threads.updateComment` | issue, PR, discussion | issue, PR | PR | issue, PR | issue, PR | issue (unverified), PR (unverified) | issue (experimental), PR | PR (unverified) | ∅ | issue, PR | ❌ | ❌ | -| `threads.deleteComment` | issue, PR, discussion | issue, PR | PR | issue, PR | issue, PR | issue (unverified), PR (unverified) | issue (experimental), PR | PR (unverified) | ∅ | issue, PR | ❌ | ❌ | -| `threads.hideComment` | issue, PR, discussion | ∅ | ∅ | ∅ | ∅ | ∅ | ∅ | ∅ | ∅ | ∅ | ❌ | ❌ | -| `threads.reactions` | issue, PR, discussion | issue, PR | ∅ | issue, PR | issue, PR | ❌ | ❌ | ❌ | ❌ | issue, PR | ❌ | ❌ | -| `threads.react` | issue, PR, discussion | issue, PR | ∅ | issue, PR | issue, PR | ❌ | ❌ | ❌ | ∅ | issue, PR | ❌ | ❌ | -| `threads.create` | issue, PR | issue, PR | PR | issue, PR | issue, PR | issue (unverified), PR (unverified) | issue, PR | PR (unverified) | issue, PR | issue, PR | ❌ | ❌ | -| `threads.update` | issue, PR, discussion | issue, PR | PR | issue, PR | issue, PR | issue (unverified), PR | issue, PR | PR (unverified) | ∅ | issue, PR | ❌ | ❌ | -| `threads.close` | issue, PR, discussion | issue, PR | PR | issue, PR | issue, PR | issue (unverified), PR | issue, PR | PR (experimental) | ∅ | issue, PR | ❌ | ❌ | -| `threads.reopen` | issue, PR, discussion | issue, PR | ❌ | issue, PR | issue, PR | issue (unverified), PR | issue, PR | PR (experimental) | ∅ | issue, PR | ❌ | ❌ | -| `threads.lock` | issue, PR, discussion | issue, PR | ∅ | ∅ | issue, PR | ❌ | ∅ | ∅ | ∅ | ∅ | ❌ | ❌ | -| `threads.setLabels` | issue, PR | issue, PR | ∅ | issue, PR | issue, PR | issue (unverified), PR (unverified) | issue, PR | PR (unverified) | ∅ | issue, PR | ❌ | ❌ | -| `threads.addLabels` | issue, PR | issue, PR | ∅ | issue, PR | issue, PR | issue (unverified), PR (unverified) | ❌ | ❌ | ∅ | issue, PR | ❌ | ❌ | -| `threads.removeLabels` | issue, PR | issue, PR | ∅ | issue, PR | issue, PR | issue (unverified), PR (unverified) | ❌ | ❌ | ∅ | issue, PR | ❌ | ❌ | -| `threads.setMilestone` | issue, PR | issue, PR | ∅ | issue, PR | issue, PR | ❌ | ❌ | ❌ | ∅ | ❌ | ❌ | ❌ | -| `threads.setIssueType` | issue | ❌ | ∅ | ∅ | ∅ | ❌ | ❌ | ∅ | ∅ | ∅ | ❌ | ❌ | -| `threads.setAssignees` | issue, PR | issue, PR | ❌ | issue, PR | issue, PR | issue (unverified) | issue | ❌ | ∅ | issue, PR | ❌ | ❌ | -| `threads.requestReview` | PR | PR | PR | PR | PR | PR (unverified) | PR | PR (unverified) | ∅ | ∅ | ❌ | ❌ | -| `threads.merge` | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | experimental | ∅ | ✅ | ❌ | ❌ | -| `threads.updateBranch` | ✅ | ✅ | ∅ | ✅ | ✅ | ❌ | ∅ | ∅ | ∅ | ∅ | ❌ | ❌ | -| `threads.transfer` | ✅ | ✅ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ∅ | ❌ | ❌ | ❌ | -| `threads.markDuplicate` | ✅ | emulated | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ∅ | ❌ | ❌ | ❌ | -| `threads.subscription` | issue, PR, discussion | issue, PR | ❌ | issue, PR | issue, PR | ❌ | ❌ | ❌ | ❌ | issue, PR | ❌ | issue | -| `threads.subscribe` | issue, PR, discussion | issue, PR | ❌ | issue, PR | issue, PR | ❌ | ❌ | ❌ | ❌ | issue, PR | ❌ | ❌ | -| `threads.checks` | PR | PR | PR | PR | PR | PR | PR (experimental) | PR (experimental) | ❌ | ∅ | ❌ | ❌ | -| `threads.files` | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ❌ | unverified | ❌ | ✅ | ❌ | ❌ | -| `threads.commits` | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | unverified | ❌ | ✅ | ❌ | ❌ | -| `threads.reviews` | ✅ | emulated | emulated | ✅ | ✅ | ∅ | emulated | experimental | ✅ | ∅ | ❌ | ❌ | -| `threads.getReview` | ✅ | emulated | emulated | ✅ | ✅ | ∅ | emulated | unverified | ✅ | ∅ | ❌ | ❌ | -| `threads.createReview` | ✅ | emulated | emulated | ✅ | ✅ | unverified | emulated | unverified | ❌ | ∅ | ❌ | ❌ | -| `threads.submitReview` | ✅ | ❌ | ❌ | ✅ | ✅ | ❌ | ❌ | ❌ | ❌ | ∅ | ❌ | ❌ | -| `threads.approve` | ✅ | ✅ | emulated | ✅ | ✅ | unverified | emulated | unverified | ❌ | ∅ | ❌ | ❌ | -| `threads.replyToReviewComment` | ✅ | ✅ | ❌ | ∅ | ✅ | ❌ | ❌ | ❌ | ✅ | ∅ | ❌ | ❌ | -| `threads.reviewThreads` | ✅ | ✅ | ❌ | emulated | emulated | ❌ | ❌ | ❌ | ❌ | ∅ | ❌ | ❌ | -| `threads.resolveReviewThread` | ✅ | ✅ | ❌ | ∅ | ∅ | ❌ | ✅ | unverified | ✅ | ∅ | ❌ | ❌ | -| `notifications.list` | ✅ (only with `classic`) | ✅ | ∅ | ✅ | ✅ | ✅ | ❌ | ∅ | ✅ | experimental | ❌ | ❌ | -| `notifications.markRead` | ✅ (only with `classic`) | ❌ | ∅ | ✅ | ✅ | ✅ | ❌ | ∅ | ∅ | experimental | ❌ | ❌ | -| `notifications.markDone` | ✅ (only with `classic`) | ✅ | ∅ | emulated | emulated | ❌ | ❌ | ∅ | ∅ | ❌ | ❌ | ❌ | -| `notifications.unsubscribe` | ✅ (only with `classic`) | ✅ | ∅ | ✅ | ✅ | ❌ | ❌ | ∅ | ∅ | ❌ | ❌ | ❌ | -| `notifications.markAllRead` | ✅ (only with `classic`) | ❌ | ∅ | ✅ | ✅ | unverified | ❌ | ∅ | ∅ | unverified | ❌ | ❌ | -| `notifications.markAllDone` | ❌ | ✅ | ∅ | ❌ | ❌ | ❌ | ❌ | ∅ | ∅ | ❌ | ❌ | ❌ | -| `notifications.unreadCount` | ❌ | ✅ | ∅ | ✅ | ✅ | ✅ | ❌ | ∅ | ❌ | unverified | ❌ | ❌ | -| `installations.list` | ✅ (only with `installation` or `app`) | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | unverified (only with `app`) | ❌ | ❌ | ❌ | ❌ | -| `checks.list` | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | unverified | ❌ | ∅ | ❌ | ❌ | -| `checks.get` | ✅ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ∅ | ❌ | ❌ | -| `checks.report` | ✅ | ✅ | ✅ | ✅ | ✅ | ❌ | ✅ | ❌ | ❌ | ∅ | ❌ | ❌ | -| `checks.rerun` | ✅ | ✅ | ❌ | ∅ | ∅ | ❌ | ❌ | ❌ | ❌ | ∅ | ❌ | ❌ | -| `ci.runs` | ✅ | ✅ | ❌ | ✅ | ✅ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | emulated | -| `ci.getRun` | ✅ | ✅ | ❌ | ✅ | ✅ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ✅ | -| `ci.jobs` | ✅ | ✅ | ❌ | ✅ | ✅ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ✅ | -| `ci.getJob` | ✅ | ✅ | ❌ | emulated | ✅ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | emulated | -| `ci.log` | ✅ | ✅ | ❌ | ✅ | ✅ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ✅ | -| `ci.rerunFailed` | ✅ | ✅ | ❌ | ❌ | ✅ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | -| `contents.getFile` | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | unverified | ❌ | ✅ | ✅ | ✅ | -| `contents.tree` | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | unverified | ❌ | ✅ | ✅ | ✅ | -| `contents.branches` | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | unverified | ❌ | ✅ | ❌ | ✅ | -| `contents.tags` | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | unverified | ❌ | ✅ | ❌ | ✅ | -| `contents.resolveRef` | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | unverified | ❌ | ✅ | ✅ | ✅ | -| `contents.compare` | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | unverified | ❌ | ✅ | ❌ | ❌ | -| `contents.commitFiles` | ✅ | ✅ | ✅ | ✅ | ✅ | ❌ | ✅ | ❌ | ❌ | ❌ | ❌ | ❌ | -| `commits.list` | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | unverified | ❌ | ✅ | ✅ | ✅ | -| `commits.get` | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | unverified | ❌ | ✅ | ✅ | ✅ | -| `commits.comments` | ✅ | ✅ | ✅ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | -| `commits.getComment` | ✅ | emulated | emulated | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | -| `commits.createComment` | ✅ | ✅ | ✅ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | -| `commits.updateComment` | ✅ | ❌ | ✅ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | -| `commits.deleteComment` | ✅ | ❌ | ✅ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | -| `commits.hideComment` | ✅ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | -| `releases.list` | ✅ | ✅ | ∅ | ✅ | ✅ | ✅ | ❌ | ∅ | ✅ | ∅ | ❌ | emulated | -| `releases.get` | ✅ | ✅ | ∅ | ✅ | ✅ | ✅ | ❌ | ∅ | ✅ | ∅ | ❌ | emulated | -| `releases.latest` | ✅ | ✅ | ∅ | ✅ | ✅ | ✅ | ❌ | ∅ | ✅ | ∅ | ❌ | emulated | -| `releases.getByTag` | ✅ | ✅ | ∅ | ✅ | ✅ | ✅ | ❌ | ∅ | ✅ | ∅ | ❌ | emulated | -| `releases.downloadAsset` | ✅ | ❌ | ∅ | ✅ | ✅ | ❌ | ❌ | ∅ | ✅ | ∅ | ❌ | emulated | -| `releases.create` | ✅ | ✅ | ∅ | ✅ | ✅ | ❌ | ❌ | ∅ | ✅ | ∅ | ❌ | ❌ | -| `releases.update` | ✅ | ✅ | ∅ | ✅ | ✅ | ❌ | ❌ | ∅ | ✅ | ∅ | ❌ | ❌ | -| `webhooks.ingest` | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ∅ | ✅ | ❌ | ✅ | -| `webhooks.list` | ✅ | ✅ | ✅ | ✅ | ✅ | unverified | ❌ | ❌ | ∅ | ∅ | ❌ | ❌ | -| `webhooks.create` | ✅ | ✅ | ✅ | ✅ | ✅ | unverified | ❌ | ❌ | ∅ | ∅ | ❌ | ❌ | -| `webhooks.update` | ✅ | ✅ | ✅ | ✅ | ✅ | unverified | ❌ | ❌ | ∅ | ∅ | ❌ | ❌ | -| `webhooks.delete` | ✅ | ✅ | ✅ | ✅ | ✅ | unverified | ❌ | ❌ | ∅ | ∅ | ❌ | ❌ | -| `webhooks.rotateSecret` | ✅ | ✅ | ✅ | ✅ | ✅ | unverified | ∅ | ❌ | ∅ | ∅ | ❌ | ❌ | -| `webhooks.deliveries` | ✅ | ❌ | ∅ | ∅ | ∅ | ∅ | ∅ | ❌ | ∅ | ∅ | ❌ | ❌ | -| `webhooks.redeliver` | ✅ | ❌ | ∅ | ∅ | ∅ | ∅ | ∅ | ❌ | ∅ | ∅ | ❌ | ❌ | -| `search.threads` | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ❌ | ❌ | ❌ | ❌ | ❌ | -| `search.repos` | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ❌ | ❌ | ❌ | ❌ | ❌ | emulated | -| `search.commits` | ✅ | experimental | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | -| `search.code` | ✅ | ✅ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | experimental | -| `securityAlerts.list` | dependency, code scanning, secret, advisory | dependency, code scanning, secret | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ∅ | ❌ | ❌ | -| `eventKinds` | native | heuristic | native | native | native | native | native | native | native | native | native | native | -| `authKinds` | `token`, `app`, `anonymous` | `token`, `anonymous` | `token`, `basic`, `anonymous` | `token`, `anonymous` | `token`, `anonymous` | `token`, `anonymous` | `token`, `basic`, `anonymous` | `token`, `app`, `anonymous` | `token`, `anonymous` | `anonymous`, `app_password`, `oauth` | `token` | `token` | -| `limits` | body 65536, comment 65536, label 50 | body 1048576, comment 1000000, label 255 | unknown | unknown | unknown | unknown | unknown | unknown | unknown | unknown | unknown | unknown | +| Capability | GitHub | GitLab | Bitbucket | Forgejo | Gitea | Gitee | Azure DevOps | Cursor Origin | Pushin.eu | Tangled | Cloudflare Artifacts | Sourcehut | Entire | +| --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | +| `experimental` | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ✅ | ✅ | ✅ | ✅ | ❌ | ✅ | +| `sources.stream` | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ✅ | ❌ | ❌ | ❌ | +| `repos.get` | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | experimental | ✅ | ✅ | ✅ | ✅ | ✅ | +| `users.get` | ✅ | ✅ | ❌ | ✅ | ✅ | ✅ | ❌ | ❌ | ❌ | ✅ | ❌ | ✅ | ❌ | +| `users.me` | ✅ (only with `classic` or `fine-grained`) | ✅ | ✅ | ✅ | ✅ | ✅ | ❌ | ❌ | ✅ | ✅ | ❌ | ✅ | ✅ | +| `users.sponsorable` | ✅ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | +| `users.events` | ✅ | ✅ | ❌ | ✅ | ✅ | ✅ | ❌ | ❌ | ❌ | ✅ | ❌ | ❌ | ❌ | +| `users.block` | ✅ (only with `classic` or `fine-grained`) | ❌ | ∅ | ✅ | ✅ | ❌ | ∅ | ∅ | ∅ | ∅ | ❌ | ❌ | ❌ | +| `repos.list` | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | unverified | ✅ | ✅ | ✅ | ✅ | ✅ | +| `repos.byOwner` | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ❌ | ❌ | ✅ | ✅ | ✅ | ✅ | +| `repos.labels` | ✅ | ✅ | ∅ | ✅ | ✅ | ✅ | ❌ | ❌ | ✅ | ✅ | ❌ | emulated | ∅ | +| `repos.createLabel` | ✅ | ✅ | ∅ | ✅ | ✅ | unverified | ❌ | ❌ | ✅ | ✅ | ❌ | ❌ | ∅ | +| `repos.milestones` | ✅ | ✅ | ∅ | ✅ | ✅ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ∅ | +| `repos.issueTypes` | ✅ | ❌ | ∅ | ∅ | ∅ | ❌ | ❌ | ∅ | ∅ | ∅ | ❌ | ❌ | ∅ | +| `repos.collaborators` | ✅ | ✅ | ❌ | ✅ | ✅ | ✅ | ❌ | ❌ | ✅ | ✅ | ❌ | ✅ | ✅ | +| `repos.contributors` | ✅ | ✅ | ❌ | ❌ | ❌ | ✅ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | +| `repos.contributorStats` | ✅ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | +| `repos.templates` | ✅ | ✅ | ∅ | ✅ | ✅ | ❌ | ∅ | ∅ | ∅ | ∅ | ❌ | ❌ | ❌ | +| `repos.permissionFor` | ✅ | ✅ | ❌ | ✅ | ✅ | ❌ | ❌ | ❌ | ✅ | ✅ | ❌ | emulated | ❌ | +| `repos.branchRules` | ✅ | ✅ | ❌ | ✅ | ✅ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | +| `repos.addCollaborator` | ✅ | ✅ | ❌ | ✅ | ✅ | ❌ | ❌ | ❌ | ✅ | ✅ | ❌ | ❌ | ✅ | +| `repos.assignableUsers` | ✅ | ✅ | ❌ | ✅ | ✅ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | +| `repos.reviewerCandidates` | emulated | emulated | ❌ | ✅ | ✅ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | +| `repos.events` | ✅ | ✅ | ❌ | ✅ | ✅ | ✅ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | +| `orgs.teams` | ✅ | ✅ | ❌ | ✅ | ✅ | ❌ | ✅ | ❌ | ✅ | ❌ | ❌ | ❌ | ❌ | +| `orgs.teamMembers` | ✅ | ✅ | ❌ | ✅ | ✅ | ❌ | ✅ | ❌ | ✅ | ❌ | ❌ | ❌ | ❌ | +| `orgs.block` | ✅ | ❌ | ∅ | ✅ | ✅ | ❌ | ∅ | ∅ | ∅ | ∅ | ❌ | ❌ | ❌ | +| `threads.get` | issue, PR, discussion | issue, PR | PR | issue, PR | issue, PR | issue, PR | issue, PR | PR (experimental) | issue, PR | issue, PR | ❌ | issue, PR | issue, PR | +| `threads.list` | issue, PR, discussion | issue, PR | PR | issue, PR | issue, PR | issue, PR | issue, PR | PR (experimental) | issue, PR | issue, PR | ❌ | issue, PR | issue, PR | +| `threads.getMany` | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | experimental | ✅ | ✅ | ❌ | ✅ | ✅ | +| `threads.closingIssues` | ✅ | ✅ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | +| `threads.closingPullRequests` | ✅ | ✅ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | +| `threads.events` | issue, PR, discussion | issue, PR | PR | issue, PR | issue, PR | issue, PR | issue, PR | PR (experimental) | issue (emulated), PR (emulated) | issue, PR | ❌ | issue, PR | issue, PR | +| `threads.comments` | issue, PR, discussion | issue, PR | PR | issue, PR | issue, PR | issue, PR | issue (experimental), PR | PR (experimental) | issue, PR | issue, PR | ❌ | issue, PR | issue, PR | +| `threads.getComment` | issue, PR, discussion | issue, PR | PR (emulated) | issue, PR | issue, PR | issue (emulated), PR (emulated) | issue (experimental), PR | PR (unverified) | issue (emulated), PR (emulated) | issue (emulated), PR (emulated) | ❌ | issue (emulated), PR (emulated) | issue, PR | +| `threads.createComment` | issue, PR, discussion | issue, PR | PR | issue, PR | issue, PR | issue (unverified), PR | issue (experimental), PR | PR (experimental) | issue, PR | issue, PR | ❌ | ❌ | issue, PR | +| `threads.updateComment` | issue, PR, discussion | issue, PR | PR | issue, PR | issue, PR | issue (unverified), PR (unverified) | issue (experimental), PR | PR (unverified) | ∅ | issue, PR | ❌ | ❌ | issue, PR | +| `threads.deleteComment` | issue, PR, discussion | issue, PR | PR | issue, PR | issue, PR | issue (unverified), PR (unverified) | issue (experimental), PR | PR (unverified) | ∅ | issue, PR | ❌ | ❌ | issue, PR | +| `threads.hideComment` | issue, PR, discussion | ∅ | ∅ | ∅ | ∅ | ∅ | ∅ | ∅ | ∅ | ∅ | ❌ | ❌ | ∅ | +| `threads.reactions` | issue, PR, discussion | issue, PR | ∅ | issue, PR | issue, PR | ❌ | ❌ | ❌ | ❌ | issue, PR | ❌ | ❌ | ∅ | +| `threads.react` | issue, PR, discussion | issue, PR | ∅ | issue, PR | issue, PR | ❌ | ❌ | ❌ | ∅ | issue, PR | ❌ | ❌ | ∅ | +| `threads.create` | issue, PR | issue, PR | PR | issue, PR | issue, PR | issue (unverified), PR (unverified) | issue, PR | PR (unverified) | issue, PR | issue, PR | ❌ | ❌ | issue, PR | +| `threads.update` | issue, PR, discussion | issue, PR | PR | issue, PR | issue, PR | issue (unverified), PR | issue, PR | PR (unverified) | ∅ | issue, PR | ❌ | ❌ | issue, PR | +| `threads.close` | issue, PR, discussion | issue, PR | PR | issue, PR | issue, PR | issue (unverified), PR | issue, PR | PR (experimental) | ∅ | issue, PR | ❌ | ❌ | issue, PR | +| `threads.reopen` | issue, PR, discussion | issue, PR | ❌ | issue, PR | issue, PR | issue (unverified), PR | issue, PR | PR (experimental) | ∅ | issue, PR | ❌ | ❌ | issue, PR | +| `threads.lock` | issue, PR, discussion | issue, PR | ∅ | ∅ | issue, PR | ❌ | ∅ | ∅ | ∅ | ∅ | ❌ | ❌ | ∅ | +| `threads.setLabels` | issue, PR | issue, PR | ∅ | issue, PR | issue, PR | issue (unverified), PR (unverified) | issue, PR | PR (unverified) | ∅ | issue, PR | ❌ | ❌ | ∅ | +| `threads.addLabels` | issue, PR | issue, PR | ∅ | issue, PR | issue, PR | issue (unverified), PR (unverified) | ❌ | ❌ | ∅ | issue, PR | ❌ | ❌ | ∅ | +| `threads.removeLabels` | issue, PR | issue, PR | ∅ | issue, PR | issue, PR | issue (unverified), PR (unverified) | ❌ | ❌ | ∅ | issue, PR | ❌ | ❌ | ∅ | +| `threads.setMilestone` | issue, PR | issue, PR | ∅ | issue, PR | issue, PR | ❌ | ❌ | ❌ | ∅ | ❌ | ❌ | ❌ | ∅ | +| `threads.setIssueType` | issue | ❌ | ∅ | ∅ | ∅ | ❌ | ❌ | ∅ | ∅ | ∅ | ❌ | ❌ | ∅ | +| `threads.setAssignees` | issue, PR | issue, PR | ❌ | issue, PR | issue, PR | issue (unverified) | issue | ❌ | ∅ | issue, PR | ❌ | ❌ | issue, PR | +| `threads.requestReview` | PR | PR | PR | PR | PR | PR (unverified) | PR | PR (unverified) | ∅ | ∅ | ❌ | ❌ | ❌ | +| `threads.merge` | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | experimental | ∅ | ✅ | ❌ | ❌ | ✅ | +| `threads.updateBranch` | ✅ | ✅ | ∅ | ✅ | ✅ | ❌ | ∅ | ∅ | ∅ | ∅ | ❌ | ❌ | ✅ | +| `threads.transfer` | ✅ | ✅ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ∅ | ❌ | ❌ | ❌ | ∅ | +| `threads.markDuplicate` | ✅ | emulated | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ∅ | ❌ | ❌ | ❌ | ∅ | +| `threads.subscription` | issue, PR, discussion | issue, PR | ❌ | issue, PR | issue, PR | ❌ | ❌ | ❌ | ❌ | issue, PR | ❌ | issue | ❌ | +| `threads.subscribe` | issue, PR, discussion | issue, PR | ❌ | issue, PR | issue, PR | ❌ | ❌ | ❌ | ❌ | issue, PR | ❌ | ❌ | ❌ | +| `threads.checks` | PR | PR | PR | PR | PR | PR | PR (experimental) | PR (experimental) | ❌ | ∅ | ❌ | ❌ | ❌ | +| `threads.files` | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ❌ | unverified | ❌ | ✅ | ❌ | ❌ | ✅ | +| `threads.commits` | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | unverified | ❌ | ✅ | ❌ | ❌ | ✅ | +| `threads.reviews` | ✅ | emulated | emulated | ✅ | ✅ | ∅ | emulated | experimental | ✅ | ∅ | ❌ | ❌ | ✅ | +| `threads.getReview` | ✅ | emulated | emulated | ✅ | ✅ | ∅ | emulated | unverified | ✅ | ∅ | ❌ | ❌ | ✅ | +| `threads.createReview` | ✅ | emulated | emulated | ✅ | ✅ | unverified | emulated | unverified | ❌ | ∅ | ❌ | ❌ | ✅ | +| `threads.submitReview` | ✅ | ❌ | ❌ | ✅ | ✅ | ❌ | ❌ | ❌ | ❌ | ∅ | ❌ | ❌ | ❌ | +| `threads.approve` | ✅ | ✅ | emulated | ✅ | ✅ | unverified | emulated | unverified | ❌ | ∅ | ❌ | ❌ | ✅ | +| `threads.replyToReviewComment` | ✅ | ✅ | ❌ | ∅ | ✅ | ❌ | ❌ | ❌ | ✅ | ∅ | ❌ | ❌ | ✅ | +| `threads.reviewThreads` | ✅ | ✅ | ❌ | emulated | emulated | ❌ | ❌ | ❌ | ❌ | ∅ | ❌ | ❌ | ✅ | +| `threads.resolveReviewThread` | ✅ | ✅ | ❌ | ∅ | ∅ | ❌ | ✅ | unverified | ✅ | ∅ | ❌ | ❌ | ✅ | +| `notifications.list` | ✅ (only with `classic`) | ✅ | ∅ | ✅ | ✅ | ✅ | ❌ | ∅ | ✅ | experimental | ❌ | ❌ | ❌ | +| `notifications.markRead` | ✅ (only with `classic`) | ❌ | ∅ | ✅ | ✅ | ✅ | ❌ | ∅ | ∅ | experimental | ❌ | ❌ | ❌ | +| `notifications.markDone` | ✅ (only with `classic`) | ✅ | ∅ | emulated | emulated | ❌ | ❌ | ∅ | ∅ | ❌ | ❌ | ❌ | ❌ | +| `notifications.unsubscribe` | ✅ (only with `classic`) | ✅ | ∅ | ✅ | ✅ | ❌ | ❌ | ∅ | ∅ | ❌ | ❌ | ❌ | ❌ | +| `notifications.markAllRead` | ✅ (only with `classic`) | ❌ | ∅ | ✅ | ✅ | unverified | ❌ | ∅ | ∅ | unverified | ❌ | ❌ | ❌ | +| `notifications.markAllDone` | ❌ | ✅ | ∅ | ❌ | ❌ | ❌ | ❌ | ∅ | ∅ | ❌ | ❌ | ❌ | ❌ | +| `notifications.unreadCount` | ❌ | ✅ | ∅ | ✅ | ✅ | ✅ | ❌ | ∅ | ❌ | unverified | ❌ | ❌ | ❌ | +| `installations.list` | ✅ (only with `installation` or `app`) | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | unverified (only with `app`) | ❌ | ❌ | ❌ | ❌ | ❌ | +| `checks.list` | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | unverified | ❌ | ∅ | ❌ | ❌ | ❌ | +| `checks.get` | ✅ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ∅ | ❌ | ❌ | ❌ | +| `checks.report` | ✅ | ✅ | ✅ | ✅ | ✅ | ❌ | ✅ | ❌ | ❌ | ∅ | ❌ | ❌ | ❌ | +| `checks.rerun` | ✅ | ✅ | ❌ | ∅ | ∅ | ❌ | ❌ | ❌ | ❌ | ∅ | ❌ | ❌ | ❌ | +| `ci.runs` | ✅ | ✅ | ❌ | ✅ | ✅ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | emulated | ❌ | +| `ci.getRun` | ✅ | ✅ | ❌ | ✅ | ✅ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ✅ | ❌ | +| `ci.jobs` | ✅ | ✅ | ❌ | ✅ | ✅ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ✅ | ❌ | +| `ci.getJob` | ✅ | ✅ | ❌ | emulated | ✅ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | emulated | ❌ | +| `ci.log` | ✅ | ✅ | ❌ | ✅ | ✅ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ✅ | ❌ | +| `ci.rerunFailed` | ✅ | ✅ | ❌ | ❌ | ✅ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | +| `contents.getFile` | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | unverified | ❌ | ✅ | ✅ | ✅ | ✅ | +| `contents.tree` | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | unverified | ❌ | ✅ | ✅ | ✅ | ✅ | +| `contents.branches` | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | unverified | ❌ | ✅ | ❌ | ✅ | ✅ | +| `contents.tags` | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | unverified | ❌ | ✅ | ❌ | ✅ | ✅ | +| `contents.resolveRef` | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | unverified | ❌ | ✅ | ✅ | ✅ | ✅ | +| `contents.compare` | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | unverified | ❌ | ✅ | ❌ | ❌ | ✅ | +| `contents.commitFiles` | ✅ | ✅ | ✅ | ✅ | ✅ | ❌ | ✅ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | +| `commits.list` | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | unverified | ❌ | ✅ | ✅ | ✅ | ✅ | +| `commits.get` | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | unverified | ❌ | ✅ | ✅ | ✅ | ✅ | +| `commits.comments` | ✅ | ✅ | ✅ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | +| `commits.getComment` | ✅ | emulated | emulated | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | +| `commits.createComment` | ✅ | ✅ | ✅ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | +| `commits.updateComment` | ✅ | ❌ | ✅ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | +| `commits.deleteComment` | ✅ | ❌ | ✅ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | +| `commits.hideComment` | ✅ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | +| `releases.list` | ✅ | ✅ | ∅ | ✅ | ✅ | ✅ | ❌ | ∅ | ✅ | ∅ | ❌ | emulated | ∅ | +| `releases.get` | ✅ | ✅ | ∅ | ✅ | ✅ | ✅ | ❌ | ∅ | ✅ | ∅ | ❌ | emulated | ∅ | +| `releases.latest` | ✅ | ✅ | ∅ | ✅ | ✅ | ✅ | ❌ | ∅ | ✅ | ∅ | ❌ | emulated | ∅ | +| `releases.getByTag` | ✅ | ✅ | ∅ | ✅ | ✅ | ✅ | ❌ | ∅ | ✅ | ∅ | ❌ | emulated | ∅ | +| `releases.downloadAsset` | ✅ | ❌ | ∅ | ✅ | ✅ | ❌ | ❌ | ∅ | ✅ | ∅ | ❌ | emulated | ∅ | +| `releases.create` | ✅ | ✅ | ∅ | ✅ | ✅ | ❌ | ❌ | ∅ | ✅ | ∅ | ❌ | ❌ | ∅ | +| `releases.update` | ✅ | ✅ | ∅ | ✅ | ✅ | ❌ | ❌ | ∅ | ✅ | ∅ | ❌ | ❌ | ∅ | +| `webhooks.ingest` | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ∅ | ✅ | ❌ | ✅ | ❌ | +| `webhooks.list` | ✅ | ✅ | ✅ | ✅ | ✅ | unverified | ❌ | ❌ | ∅ | ∅ | ❌ | ❌ | ❌ | +| `webhooks.create` | ✅ | ✅ | ✅ | ✅ | ✅ | unverified | ❌ | ❌ | ∅ | ∅ | ❌ | ❌ | ❌ | +| `webhooks.update` | ✅ | ✅ | ✅ | ✅ | ✅ | unverified | ❌ | ❌ | ∅ | ∅ | ❌ | ❌ | ❌ | +| `webhooks.delete` | ✅ | ✅ | ✅ | ✅ | ✅ | unverified | ❌ | ❌ | ∅ | ∅ | ❌ | ❌ | ❌ | +| `webhooks.rotateSecret` | ✅ | ✅ | ✅ | ✅ | ✅ | unverified | ∅ | ❌ | ∅ | ∅ | ❌ | ❌ | ❌ | +| `webhooks.deliveries` | ✅ | ❌ | ∅ | ∅ | ∅ | ∅ | ∅ | ❌ | ∅ | ∅ | ❌ | ❌ | ❌ | +| `webhooks.redeliver` | ✅ | ❌ | ∅ | ∅ | ∅ | ∅ | ∅ | ❌ | ∅ | ∅ | ❌ | ❌ | ❌ | +| `search.threads` | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | +| `search.repos` | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ❌ | ❌ | ❌ | ❌ | ❌ | emulated | ❌ | +| `search.commits` | ✅ | experimental | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | +| `search.code` | ✅ | ✅ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | experimental | ❌ | +| `securityAlerts.list` | dependency, code scanning, secret, advisory | dependency, code scanning, secret | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ∅ | ❌ | ❌ | ❌ | +| `eventKinds` | native | heuristic | native | native | native | native | native | native | native | native | native | native | native | +| `authKinds` | `token`, `app`, `anonymous` | `token`, `anonymous` | `token`, `basic`, `anonymous` | `token`, `anonymous` | `token`, `anonymous` | `token`, `anonymous` | `token`, `basic`, `anonymous` | `token`, `app`, `anonymous` | `token`, `anonymous` | `anonymous`, `app_password`, `oauth` | `token` | `token` | `token` | +| `limits` | body 65536, comment 65536, label 50 | body 1048576, comment 1000000, label 255 | unknown | unknown | unknown | unknown | unknown | unknown | unknown | unknown | unknown | unknown | unknown | Each cell shows the best support of any credential. Where support depends on the kind of credential, a cell names the credentials that have it, unless they are the forge's usual ones: `classic`, `fine-grained` or `installation` on GitHub and `token` or `installation` on Cursor Origin. diff --git a/docs/content/5.reference/12.events.md b/docs/content/5.reference/12.events.md index 0154fc42d..05b02963a 100644 --- a/docs/content/5.reference/12.events.md +++ b/docs/content/5.reference/12.events.md @@ -41,7 +41,7 @@ const labels = provider.webhooks.events.some( | `issue_type` | `typed`, `untyped` | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | | `other` | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | -Pushin.eu and Cloudflare Artifacts receive no webhooks. +Pushin.eu, Cloudflare Artifacts and Entire receive no webhooks. GitLab reports `eventKinds: 'heuristic'`, so `kind` can be `other` for wording the provider doesn't recognise. :: diff --git a/docs/content/5.reference/13.environment-variables.md b/docs/content/5.reference/13.environment-variables.md index c1f1673a5..cf043c972 100644 --- a/docs/content/5.reference/13.environment-variables.md +++ b/docs/content/5.reference/13.environment-variables.md @@ -8,7 +8,7 @@ This page lists every variable that `providersFromEnv()` and `forgesFromEnv()` f ## Kinds -`` is one of `GITHUB`, `GITLAB`, `BITBUCKET`, `FORGEJO`, `GITEA`, `GITEE`, `AZURE_DEVOPS`, `CURSOR_ORIGIN`, `TANGLED`, `PUSHIN`, `CLOUDFLARE_ARTIFACTS` and `SOURCEHUT`. +`` is one of `GITHUB`, `GITLAB`, `BITBUCKET`, `FORGEJO`, `GITEA`, `GITEE`, `AZURE_DEVOPS`, `CURSOR_ORIGIN`, `TANGLED`, `PUSHIN`, `CLOUDFLARE_ARTIFACTS`, `SOURCEHUT` and `ENTIRE`. ## Fields @@ -47,7 +47,7 @@ A set of variables creates a provider when it contains one of the credentials th | Cursor Origin | `TOKEN`, or `APP_ID` and `PRIVATE_KEY` | `INSTALLATION_ID` with `APP_ID` and `PRIVATE_KEY` | Webhooks only with `ENABLED`. Skipped otherwise | | Tangled | `IDENTIFIER` and `PASSWORD` | `PDS`, `API_URL` and `NOTIFICATIONS_URL` | Anonymous reads | | Cloudflare Artifacts | `ACCOUNT_ID`, and `TOKEN` | None | Skipped, even with `ENABLED` | -| Sourcehut | `TOKEN` | None | Skipped, even with `ENABLED` | +| Sourcehut, Entire | `TOKEN` | None | Skipped, even with `ENABLED` | :: diff --git a/docs/content/7.contributing/4.record-fixtures.md b/docs/content/7.contributing/4.record-fixtures.md index 481122a17..5567326f7 100644 --- a/docs/content/7.contributing/4.record-fixtures.md +++ b/docs/content/7.contributing/4.record-fixtures.md @@ -109,10 +109,12 @@ A write recording needs: - to record `orgs.block` and `users.block`, the login of an account outside the scratch repository's organization in `FIXTURE__BLOCKED_USER`. The bot blocks and unblocks it for the organization, which the bot must own, and for itself. On GitHub, the bot's token needs the `admin:org` and `user` scopes; - on GitHub, [immutable releases](https://docs.github.com/en/code-security/supply-chain-security/understanding-your-software-supply-chain/immutable-releases) turned on in the scratch repository, so that the recorder can check that GitHub refuses to retag a release. -Before the steps run, the recorder closes threads that an earlier run left open, and creates three branches with one commit each through the forge's own API. Afterwards it deletes the branches, the label and the webhook, and every release and tag whose name starts with `forges-fixture-`. On Codeberg, which refuses issues and pull requests whose titles are too similar to ones the account opened in the last hour, the title of each thread ends with a random suffix. The recorder can write to GitHub, GitLab, Bitbucket, Forgejo, Gitea, Gitee, Azure DevOps, Pushin.eu and Tangled. +Before the steps run, the recorder closes threads that an earlier run left open, and creates three branches with one commit each through the forge's own API. Afterwards it deletes the branches, the label and the webhook, and every release and tag whose name starts with `forges-fixture-`. On Codeberg, which refuses issues and pull requests whose titles are too similar to ones the account opened in the last hour, the title of each thread ends with a random suffix. The recorder can write to GitHub, GitLab, Bitbucket, Forgejo, Gitea, Gitee, Azure DevOps, Pushin.eu, Entire and Tangled. Pushin.eu has no API for branches or tags, so the recorder pushes them over HTTPS as the bot. Its API can't close threads either, so the recorder closes those an earlier run left open by importing them again as closed. +On Entire, the recorder also pushes the branches over HTTPS as the bot, straight to the storage node that the git endpoint redirects to. Entire's findings gate refuses to merge a change with a finding, so the recorder makes that gate non-blocking in the scratch repository before the steps run. + On Tangled, the recorder pushes the branches to the knot over HTTPS. It signs in as the bot with `TANGLED_BOT_IDENTIFIER` and `TANGLED_BOT_PASSWORD`, and `TANGLED_BOT_PDS` when the identifier is a handle on a PDS other than `bsky.social`. A reviewer's records would go into its own account, so the reviewer is a second bot, in `TANGLED_REVIEWER_IDENTIFIER`, `TANGLED_REVIEWER_PASSWORD` and `TANGLED_REVIEWER_PDS`, rather than your account. Before and after the steps, it deletes the issues and pull requests that earlier runs opened, the bot's comments, states, labels and reactions on those and on the pull request in `FIXTURE_TANGLED_SCRATCH_PULL`, an AT-URI, and every label whose name starts with `forges-fixture-`. The recorder refuses, before sending it, any write outside the scratch and transfer repositories, apart from the bot account's own notifications and its blocks of the account in `FIXTURE__BLOCKED_USER`. On GitHub, a GraphQL mutation may only name ids that a response from those repositories returned. On Tangled, a record may only name the scratch repository, the bot's own records or the scratch pull request. @@ -152,7 +154,7 @@ pnpm vitest run test/recorded.test.ts -u ## Record on a schedule -The `fixtures` workflow records every forge each Monday: reads at 04:23 UTC and writes at 06:23 UTC. It opens or updates a pull request per kind, on the `fixtures/reads` or `fixtures/writes` branch, with a commit per forge whose recording changed, and runs CI on it. A forge whose responses didn't change gets no commit. To record now, run the workflow from the **Actions** tab, and choose the kind, the forges and the steps to record. +The `fixtures` workflow records every forge except Entire each Monday: reads at 04:23 UTC and writes at 06:23 UTC. It opens or updates a pull request per kind, on the `fixtures/reads` or `fixtures/writes` branch, with a commit per forge whose recording changed, and runs CI on it. A forge whose responses didn't change gets no commit. To record now, run the workflow from the **Actions** tab, and choose the kind, the forges and the steps to record. To record the fixtures of a pull request, name its branch in `ref`. The workflow records with the code on that branch, and opens a pull request into the branch from `fixtures/-`. Only branches of this repository can be recorded. @@ -353,6 +355,16 @@ pnpm record-fixtures sourcehut Sourcehut refuses reads without a token, so there is no anonymous recording. The token needs the read grants of `meta.sr.ht`, `git.sr.ht`, `todo.sr.ht`, `lists.sr.ht` and `builds.sr.ht`. To record other threads, set `FIXTURE_SOURCEHUT_REPO` and `FIXTURE_SOURCEHUT_ISSUE`, and for the patchset, `FIXTURE_SOURCEHUT_LIST` and `FIXTURE_SOURCEHUT_PATCHSET`, as patchsets belong to a mailing list rather than a repository. To record a self-hosted instance, set `SOURCEHUT_BASE_URL`. +### Entire + +```sh +ENTIRE_TOKEN=$(entire auth token) pnpm record-fixtures entire +``` + +Entire refuses reads without a token, so there is no anonymous recording. Its tokens expire after 8 hours, so the `fixtures` workflow doesn't record Entire. Record it locally with `node scripts/record-forge.ts entire --kind reads`. The reads go to `forges/forges-fixtures` by default. To record another repository, set `FIXTURE_ENTIRE_REPO`, and to record other trails, set `FIXTURE_ENTIRE_ISSUE` to a project trail number and `FIXTURE_ENTIRE_PULL` to a change number. + +To record writes, the bot owns a project with a public scratch repository, such as `forges-scratch/forges-fixtures` in `FIXTURE_ENTIRE_SCRATCH_REPO`, and signs in with its own `entire auth token` in `ENTIRE_BOT_TOKEN`. The reviewer has a grant on the repository but not on the project, so it finds the project's trails through the list of repositories it can read. The recorder leaves private repositories out of every list, so a private scratch repository would leave that list empty. + ### Tangled Recording Tangled needs no credentials, so without them the recording goes to `tangled.org-anonymous/`: diff --git a/docs/shared/explorer.ts b/docs/shared/explorer.ts index 72d3cf9e9..48af91ada 100644 --- a/docs/shared/explorer.ts +++ b/docs/shared/explorer.ts @@ -293,6 +293,18 @@ export const EXPLORER_FORGES: ExplorerForge[] = [ // number is the scdoc issue and a patch call reads the `scdoc` list, which has none. sample: sample({ owner: '~sircmpwn', name: 'scdoc', number: '6', login: '~sircmpwn', sha: '24be30ef17d5ca0162f11b35258c8fa2413d556a', tag: '1.10.1', releaseId: '1.10.1', base: 'master', head: 'master', runId: '1' }), }, + { + name: 'Entire', + factory: 'entire', + module: 'entire', + load: () => import('forges/entire'), + forge: 'entire', + instance: 'entire.com', + credentials: [token('ENTIRE_TOKEN', false)], + blocked: 'Entire\'s processing cells don\'t allow requests from browsers, and Entire has no anonymous reads.', + signedIn: true, + sample: sample({ owner: 'forges', name: 'forges-fixtures', number: '1', login: 'danielroe', sha: 'c83b64d5032ae0ee89ecbaeea7273b2291b4d2e5', tag: 'v0.1.0', base: 'main', head: 'feature/shout' }), + }, ] /** The refs a call takes, built from the form. */ diff --git a/package.json b/package.json index 7eaaee18a..c60a01bd9 100644 --- a/package.json +++ b/package.json @@ -45,6 +45,7 @@ "./bitbucket": "./src/bitbucket/index.ts", "./cloudflare-artifacts": "./src/cloudflare-artifacts/index.ts", "./cursor-origin": "./src/cursor-origin/index.ts", + "./entire": "./src/entire/index.ts", "./env": "./src/env.ts", "./fake": "./src/fake/index.ts", "./forgejo": "./src/forgejo/index.ts", @@ -71,6 +72,7 @@ "./bitbucket": "./dist/bitbucket/index.mjs", "./cloudflare-artifacts": "./dist/cloudflare-artifacts/index.mjs", "./cursor-origin": "./dist/cursor-origin/index.mjs", + "./entire": "./dist/entire/index.mjs", "./env": "./dist/env.mjs", "./fake": "./dist/fake/index.mjs", "./forgejo": "./dist/forgejo/index.mjs", diff --git a/scripts/api-docs/config.ts b/scripts/api-docs/config.ts index 62fe1da72..2a803effc 100644 --- a/scripts/api-docs/config.ts +++ b/scripts/api-docs/config.ts @@ -105,6 +105,7 @@ export const PAGES: PageConfig[] = [ forge('Tangled', 'tangled'), forge('Cloudflare Artifacts', 'cloudflare-artifacts'), forge('Sourcehut', 'sourcehut'), + forge('Entire', 'entire'), { title: 'Forges registry', intro: 'A registry routes each ref to the provider it belongs to.', names: ['createForges', 'ProviderFactoryFunction'] }, { title: 'Registry methods', members: { of: 'Forges' } }, { title: 'Create from the environment', intro: 'Import from `forges/env`. The variable names are listed under [Environment variables](/reference/environment-variables).', entry: 'forges/env', names: [/./] }, diff --git a/scripts/capabilities.ts b/scripts/capabilities.ts index 71278952d..2ca209b97 100644 --- a/scripts/capabilities.ts +++ b/scripts/capabilities.ts @@ -56,7 +56,7 @@ function withoutCredentials(provider: Forges.ForgeProvider): Forges.ForgeProvide /** Providers as the matrix and provider pages show them, keyed by their `docs/content/4.providers/.md` page. */ export function matrixProviders(forges: typeof Forges): MatrixProvider[] { - const { azureDevOps, bitbucket, cloudflareArtifacts, cursorOrigin, forgejo, gitea, gitee, github, gitlab, pushin, sourcehut, tangled } = forges + const { azureDevOps, bitbucket, cloudflareArtifacts, cursorOrigin, entire, forgejo, gitea, gitee, github, gitlab, pushin, sourcehut, tangled } = forges const auth = { type: 'token', token: 'token' } as const const entry = (slug: string, name: string, factory: (options: O) => Forges.ForgeProvider, options: O, credentials?: CredentialOptions[]): MatrixProvider => { const exported = Object.keys(forges).find(key => (forges as Record)[key] === factory)! @@ -97,6 +97,7 @@ export function matrixProviders(forges: typeof Forges): MatrixProvider[] { entry('tangled', 'Tangled', tangled, { auth: { type: 'app_password', identifier: 'handle', password: 'password' }, notificationsUrl: 'https://notifications.example' }), entry('cloudflare-artifacts', 'Cloudflare Artifacts', cloudflareArtifacts, { auth, accountId: 'acme' }), entry('sourcehut', 'Sourcehut', sourcehut, { auth }), + entry('entire', 'Entire', entire, { auth }), ] } diff --git a/scripts/credential-steps.ts b/scripts/credential-steps.ts index acb74d4a8..37923771b 100644 --- a/scripts/credential-steps.ts +++ b/scripts/credential-steps.ts @@ -230,6 +230,15 @@ export const credentialSteps: Record> = }, ], }, + 'entire': { + TOKEN: [ + { + text: 'Sign in with the [Entire CLI](https://docs.entire.com/) and run `entire auth token` to print a token. It expires after a few hours, so a long-running program should pass `token` as a function that reads a fresh one.', + sources: ['https://docs.entire.com/', 'docs/content/4.providers/entire.md'], + verified: '2026-10-26', + }, + ], + }, 'tangled': { 'IDENTIFIER+PASSWORD': [ { diff --git a/scripts/exercised.ts b/scripts/exercised.ts index 03e1549da..a16cc3530 100644 --- a/scripts/exercised.ts +++ b/scripts/exercised.ts @@ -1,7 +1,7 @@ import type { ForgeCapabilities, ForgeProvider } from '../src/index.ts' import type { VerbRun } from '../test/setup/verbs-directory.ts' import { existsSync, readdirSync, readFileSync } from 'node:fs' -import { azureDevOps, bitbucket, cloudflareArtifacts, cursorOrigin, forgejo, gitea, gitee, github, gitlab, pushin, sourcehut, tangled } from '../src/index.ts' +import { azureDevOps, bitbucket, cloudflareArtifacts, cursorOrigin, entire, forgejo, gitea, gitee, github, gitlab, pushin, sourcehut, tangled } from '../src/index.ts' import { VERB_RUN } from '../test/setup/verbs-directory.ts' import { withDeclared } from './capabilities.ts' @@ -56,6 +56,7 @@ const checked: Array<[string, ForgeProvider]> = [ ['pushin', pushin({ auth })], ['cloudflare-artifacts', cloudflareArtifacts({ auth, accountId: 'acme' })], ['sourcehut', sourcehut({ auth })], + ['entire', entire({ auth })], ['github:anonymous', github({})], ['gitlab:anonymous', gitlab({})], ['bitbucket:anonymous', bitbucket({})], diff --git a/scripts/fixtures-environments.ts b/scripts/fixtures-environments.ts index 75dd66f5f..6636bd7b0 100644 --- a/scripts/fixtures-environments.ts +++ b/scripts/fixtures-environments.ts @@ -10,6 +10,7 @@ * `--reviewer` (you, by default) to approve each run. Both deploy from * `main` only. The variables of each forge are stored as one `FIXTURES_ENV` * secret, in `.env` format. + * Forges that record only locally get no environment. * `--forge`, which repeats, limits the run to the environments of those forges. * `--dry-run` prints the environments and the names of their variables. */ @@ -31,6 +32,7 @@ const PREFIXES: Record = { 'tangled': ['TANGLED_', 'FIXTURE_TANGLED_'], 'cloudflare-artifacts': ['CLOUDFLARE_ARTIFACTS_', 'FIXTURE_CLOUDFLARE_ARTIFACTS_'], 'sourcehut': ['SOURCEHUT_', 'FIXTURE_SOURCEHUT_'], + 'entire': ['ENTIRE_', 'FIXTURE_ENTIRE_'], } /** Variables only write recordings and seeding use: the bot accounts and the Tangled reviewer. */ @@ -56,7 +58,7 @@ const unknown = values.forge?.filter(forge => !(forge in PLANS)) ?? [] if (unknown.length) { throw new Error(`Unknown forge: ${unknown.join(', ')}. Choose from ${Object.keys(PLANS).join(', ')}`) } -const forges = Object.entries(PLANS).filter(([forge]) => !values.forge || values.forge.includes(forge)) +const forges = Object.entries(PLANS).filter(([forge, plan]) => !plan.local && (!values.forge || values.forge.includes(forge))) const env = parseEnv(readFileSync(values['env-file'], 'utf8')) as Record const dry = values['dry-run'] const reviewer = dry ? 0 : Number(gh(['api', values.reviewer ? `users/${values.reviewer}` : 'user', '--jq', '.id']).trim()) diff --git a/scripts/record-fixtures.ts b/scripts/record-fixtures.ts index e5eab8cf6..e56b901a7 100644 --- a/scripts/record-fixtures.ts +++ b/scripts/record-fixtures.ts @@ -12,7 +12,7 @@ import process, { env, exit } from 'node:process' import { fileURLToPath } from 'node:url' import { parseArgs } from 'node:util' import { ForgeApiError } from '../src/errors.ts' -import { azureDevOps, bitbucket, cloudflareArtifacts, cursorOrigin, forgejo, gitea, gitee, github, gitlab, pushin, sourcehut, tangled } from '../src/index.ts' +import { azureDevOps, bitbucket, cloudflareArtifacts, cursorOrigin, entire, forgejo, gitea, gitee, github, gitlab, pushin, sourcehut, tangled } from '../src/index.ts' import { recordingFetch, signDelivery } from '../src/testing/index.ts' import { recordedSteps, stepSlug } from '../test/recording/layout.ts' import { redact } from '../test/recording/redact.ts' @@ -27,10 +27,10 @@ import { guardedFetch } from './write-guard.ts' import { writeHarness } from './write-harness.ts' const { positionals: [target], values: flags } = parseArgs({ allowPositionals: true, options: { 'anonymous': { type: 'boolean', default: false }, 'app': { type: 'boolean', default: false }, 'writes': { type: 'boolean', default: false }, 'webhooks': { type: 'boolean', default: false }, 'seed': { type: 'boolean', default: false }, 'only': { type: 'string', multiple: true }, 'allow-fewer': { type: 'boolean', default: false }, 'defer-splice': { type: 'boolean', default: false } } }) -const TOKEN_VARIABLES: Record = { 'github': 'GITHUB_TOKEN', 'forgejo': 'CODEBERG_TOKEN', 'gitlab': 'GITLAB_TOKEN', 'bitbucket': 'BITBUCKET_TOKEN', 'cursor-origin': 'CURSOR_AUTH_TOKEN', 'gitee': 'GITEE_TOKEN', 'azure-devops': 'AZURE_DEVOPS_TOKEN', 'gitea': 'GITEA_TOKEN', 'pushin': 'PUSHIN_TOKEN', 'tangled': 'TANGLED_PASSWORD', 'cloudflare-artifacts': 'CLOUDFLARE_ARTIFACTS_TOKEN', 'sourcehut': 'SOURCEHUT_TOKEN' } +const TOKEN_VARIABLES: Record = { 'github': 'GITHUB_TOKEN', 'forgejo': 'CODEBERG_TOKEN', 'gitlab': 'GITLAB_TOKEN', 'bitbucket': 'BITBUCKET_TOKEN', 'cursor-origin': 'CURSOR_AUTH_TOKEN', 'gitee': 'GITEE_TOKEN', 'azure-devops': 'AZURE_DEVOPS_TOKEN', 'gitea': 'GITEA_TOKEN', 'pushin': 'PUSHIN_TOKEN', 'tangled': 'TANGLED_PASSWORD', 'cloudflare-artifacts': 'CLOUDFLARE_ARTIFACTS_TOKEN', 'sourcehut': 'SOURCEHUT_TOKEN', 'entire': 'ENTIRE_TOKEN' } if (!target || !(target in TOKEN_VARIABLES)) { - console.error('Usage: pnpm record-fixtures [--anonymous | --app | --writes [--allow-fewer] [--defer-splice] | --webhooks | --seed] [--only ]...') + console.error('Usage: pnpm record-fixtures [--anonymous | --app | --writes [--allow-fewer] [--defer-splice] | --webhooks | --seed] [--only ]...') exit(1) } @@ -519,6 +519,18 @@ function targetFor(credentials: Credentials, fetch: FetchLike): Target { ...setupRepos('SOURCEHUT', value => repoRef('sourcehut', provider.instance, value)), } } } + case 'entire': { + const provider = entire({ baseUrl: env.ENTIRE_BASE_URL, auth: tokenAuth!, fetch, timeout }) + const [project = '', name = ''] = (env.FIXTURE_ENTIRE_REPO ?? 'forges/forges-fixtures').split('/') + const repo = { forge: 'entire', instance: provider.instance, owner: project, name } + return { provider, manifest: { + repo, + // Project trails stand in for issues, so the issue ref names the project rather than a repository. + issue: { forge: 'entire', instance: provider.instance, repo: { ...repo, name: '', kind: 'namespace' }, kind: 'issue', number: env.FIXTURE_ENTIRE_ISSUE ?? '1' }, + pull: { forge: 'entire', instance: provider.instance, repo, kind: 'pull_request', number: env.FIXTURE_ENTIRE_PULL ?? '1' }, + ...setupRepos('ENTIRE', slug => repoRef('entire', provider.instance, slug)), + } } + } default: { const provider = forgejo({ baseUrl: env.CODEBERG_BASE_URL, auth: tokenAuth, fetch, timeout }) const slug = env.FIXTURE_FORGEJO_REPO ?? (codeForgejo ? 'forgejo/runner' : 'forgejo/forgejo') @@ -548,6 +560,7 @@ function authorizationFor(token: string): string { case 'gitlab': case 'bitbucket': case 'sourcehut': + case 'entire': return `Bearer ${token}` case 'azure-devops': return `Basic ${btoa(`:${token}`)}` diff --git a/scripts/record-forge.ts b/scripts/record-forge.ts index f13ad0c58..3ab520d80 100644 --- a/scripts/record-forge.ts +++ b/scripts/record-forge.ts @@ -11,8 +11,8 @@ * except with `--only`. `--defer-splice` passes on to write recordings, to * leave their splicing to `scripts/splice-partial.ts`. * `--summary` writes the outcome of each recording as Markdown. The exit code - * is 1 when any recording failed. `--list` prints the forges that record - * that kind, as a JSON array. + * is 1 when any recording failed. `--list` prints the forges that the + * `fixtures` workflow records of that kind, as a JSON array. */ import type { Buffer } from 'node:buffer' import { spawn } from 'node:child_process' @@ -29,8 +29,11 @@ interface Recording { const CODE_FORGEJO = { CODEBERG_BASE_URL: 'https://code.forgejo.org' } -/** The recordings of each forge, by kind. */ -export const PLANS: Record = { +/** + * The recordings of each forge, by kind. A `local` forge records only on a + * maintainer's machine, as its credentials expire before the next scheduled run. + */ +export const PLANS: Record = { 'github': { reads: [{ label: 'github.com', args: [] }, { label: 'anonymous', args: ['--anonymous'] }, { label: 'app', args: ['--app'] }], writes: [{ label: 'writes', args: ['--writes'] }], @@ -52,6 +55,7 @@ export const PLANS: Record 'pushin': { reads: [{ label: 'pushin.eu', args: [] }, { label: 'anonymous', args: ['--anonymous'] }], writes: [{ label: 'writes', args: ['--writes'] }] }, 'cloudflare-artifacts': { reads: [{ label: 'artifacts.cloudflare.net', args: [] }], writes: [] }, 'sourcehut': { reads: [{ label: 'sr.ht', args: [] }], writes: [] }, + 'entire': { reads: [{ label: 'entire.com', args: [] }], writes: [{ label: 'writes', args: ['--writes'] }], local: true }, 'tangled': { reads: [{ label: 'tangled.org', args: [] }, { label: 'anonymous', args: ['--anonymous'] }], writes: [{ label: 'writes', args: ['--writes'] }, { label: 'seed', args: ['--seed'] }], @@ -82,7 +86,7 @@ function record(forge: string, recording: Recording, options: { envFile?: string if (process.argv[1] === fileURLToPath(import.meta.url)) { const { positionals: [forge], values } = parseArgs({ allowPositionals: true, options: { 'kind': { type: 'string' }, 'list': { type: 'string' }, 'env-file': { type: 'string' }, 'only': { type: 'string', multiple: true, default: [] }, 'defer-splice': { type: 'boolean', default: false }, 'summary': { type: 'string' } } }) if (values.list === 'reads' || values.list === 'writes') { - console.info(JSON.stringify(Object.keys(PLANS).filter(name => PLANS[name]![values.list as 'reads' | 'writes'].length))) + console.info(JSON.stringify(Object.keys(PLANS).filter(name => !PLANS[name]!.local && PLANS[name]![values.list as 'reads' | 'writes'].length))) process.exit(0) } const kind = values.kind diff --git a/scripts/recorded-coverage.ts b/scripts/recorded-coverage.ts index 687d92d14..eefbc5fa7 100644 --- a/scripts/recorded-coverage.ts +++ b/scripts/recorded-coverage.ts @@ -32,6 +32,7 @@ const FORGES: Array<[string, string]> = [ ['tangled', 'Tangled'], ['cloudflare-artifacts', 'Cloudflare Artifacts'], ['sourcehut', 'Sourcehut'], + ['entire', 'Entire'], ] const { values: flags } = parseArgs({ options: { out: { type: 'string' } } }) diff --git a/scripts/write-harness.ts b/scripts/write-harness.ts index c9be9c984..6542a298d 100644 --- a/scripts/write-harness.ts +++ b/scripts/write-harness.ts @@ -376,6 +376,83 @@ function pushin({ baseUrl, authorization, scratch }: HarnessOptions): WriteHarne } } +/** + * Entire writes go to the processing cell that holds the scratch repository, and to the trails of its project, + * which the run's issues and pull requests are opened in. Git redirects each request to a storage node and drops + * the credential on the way, so branches are pushed to the node directly. + */ +function entire({ baseUrl, authorization, scratch }: HarnessOptions): WriteHarness { + const core = client(baseUrl, authorization) + const scope: string[] = [] + const auth = extraHeader(`Authorization: ${authorization}`) + let cell: ReturnType | undefined + let repoId = '' + let projectId = '' + let remote = '' + let clone: string | undefined + const trails = `/trails/et/${enc(scratch.owner)}/${enc(scratch.name)}` + const projectTrails = `/et/${enc(scratch.owner)}/trails` + const checkout = async (base: string) => { + if (!clone) { + const response = await fetch(`${remote}/info/refs?service=git-upload-pack`, { headers: { authorization }, redirect: 'manual', signal: AbortSignal.timeout(30_000) }) + const node = new URL(response.headers.get('location') ?? remote).origin + clone = mkdtempSync(join(tmpdir(), 'forges-entire-')) + git(clone, ['clone', '-q', '--depth', '1', '--branch', base, `${node}${new URL(remote).pathname}`, '.'], auth) + } + return clone + } + return { + scope, + // The control plane names a repository's cell in reply to a POST, which writes nothing. + allows: (url, body) => url === `${baseUrl}/repos/resolve` + && ((body as { repositories?: Array<{ fullName?: string }> } | undefined)?.repositories ?? []).every(item => item.fullName === `${scratch.owner}/${scratch.name}`), + async prepare() { + const { repos } = await core<{ repos: Array<{ id: string, full_name: string, permission?: string, placements?: Array<{ id: string, cell: string, apiBaseUrl?: string, mirror?: boolean }> }> }>(`/repos?filter=${enc(`et/${scratch.owner}/${scratch.name}`)}`) + const repo = repos.find(item => item.full_name === `${scratch.owner}/${scratch.name}`) + const placement = repo?.placements?.find(item => item.apiBaseUrl && !item.mirror) + if (!repo || !placement?.apiBaseUrl || repo.permission !== 'admin') { + throw new Error('The author credential does not administer the scratch repository') + } + repoId = placement.id + const api = `${placement.apiBaseUrl}/api/v1` + cell = client(api, authorization) + remote = `https://${placement.cell}.entire.io/et/${enc(scratch.owner)}/${enc(scratch.name)}` + scope.push(`${baseUrl}/repos/${repoId}`, `${api}/repos/${repoId}`, `${api}/git/repos/${repoId}`, `${api}${trails}`, `${api}${projectTrails}`) + // The run merges a change it left a finding on, which a blocking findings gate refuses. + const { gates } = await cell<{ gates: Array<{ id: string, gateType: string, blocking: boolean }> }>(`/repos/${repoId}/trails/gates`) + for (const gate of gates.filter(item => item.gateType === 'findings' && item.blocking)) { + await cell(`/repos/${repoId}/trails/gates/${gate.id}`, { method: 'PATCH', json: { blocking: false } }) + } + const data = await cell<{ default_branch: string, owning_project_id: string }>(`/repos/${repoId}`) + projectId = data.owning_project_id + return data.default_branch + }, + async createBranch(base, branch, path) { + const directory = await checkout(base) + git(directory, ['switch', '-q', '-C', branch, `origin/${base}`]) + mkdirSync(dirname(join(directory, path)), { recursive: true }) + writeFileSync(join(directory, path), fixtureContent(branch)) + git(directory, ['add', path]) + git(directory, ['commit', '-q', '-m', `test: add ${path}`]) + git(directory, ['push', '-q', 'origin', branch], auth) + }, + async cleanUp(branches) { + const call = cell! + const changes = await call<{ items: Array<{ number: number, title: string }> }>(`${trails}?status=open&per_page=100`).catch(() => ({ items: [] })) + const open = await call<{ items: Array<{ number: number, title: string }> }>(`/trails?projectId=${projectId}&status=open&pageSize=100`).catch(() => ({ items: [] })) + const heads = await call<{ branches: Array<{ name: string, commitSHA: string }> }>(`/git/repos/${repoId}/branches?pageSize=100`).catch(() => ({ branches: [] })) + await settle([ + ...changes.items.filter(item => item.title.startsWith(FIXTURE_TITLE)).map(item => () => call(`${trails}/${item.number}`, { method: 'PATCH', json: { status: 'closed' } })), + ...open.items.filter(item => item.title.startsWith(FIXTURE_TITLE)).map(item => () => call(`${projectTrails}/${item.number}`, { method: 'PATCH', json: { status: 'closed' } })), + ...heads.branches.filter(item => branches.includes(item.name)).map(item => () => call(`/git/repos/${repoId}/branches/${item.name.split('/').map(enc).join('/')}?expectedSHA=${item.commitSHA}`, { method: 'DELETE' })), + ]) + }, + async removeCollaborator(_repo, id) { + await core(`/repos/${repoId}/grants/account/${enc(id)}`, { method: 'DELETE' }) + }, + } +} + /** * Tangled writes are records in the signed-in account's own repository on its * PDS. A new record may only name the scratch repository, a record of that @@ -598,6 +675,7 @@ const HARNESSES: Record WriteHarness> = { 'gitee': gitee, 'azure-devops': azureDevOps, 'pushin': pushin, + 'entire': entire, } /** The setup and teardown for `options.forge`, or `undefined` where write recordings are not supported. */ diff --git a/src/entire/index.ts b/src/entire/index.ts new file mode 100644 index 000000000..fb7cb78ec --- /dev/null +++ b/src/entire/index.ts @@ -0,0 +1,831 @@ +import type { ProviderContext, ProviderDefinition, ProviderFactoryFunction, ProviderSpec } from '../define.ts' +import type { Fetcher } from '../fetch.ts' +import type { Actor, BaseOptions, Branch, ChangedFile, Comment, CommentRef, Commit, CommitQuery, CommitRef, CompareOptions, Comparison, Cursor, FileOptions, ForgeEventInput, ForgeWarning, ListOptions, MergeOptions, MergeResult, Page, PageOptions, RepoQuery, RepoRef, RepoRole, ResolvedThreadRef, Review, ReviewComment, ReviewInput, ReviewRef, ReviewThread, Tag, Thread, ThreadInput, ThreadQuery, ThreadRef, ThreadUpdate, TreeEntry, TreeOptions, UpdateBranchOptions, UpdateBranchResult, User } from '../model.ts' +import type { ForgeOptionsBase, TokenAuth, VerbScopes } from '../provider.ts' +import type { ForgeVerb } from '../supports.ts' +import type { WebLinks } from '../web.ts' +import type { EntireApproval, EntireBranch, EntireChange, EntireCollaborator, EntireCommit, EntireCommitDetail, EntireCompareFile, EntireCompareStatus, EntireCoreRepo, EntireDiscussion, EntireDiscussionCreated, EntireMe, EntireMerged, EntireMessage, EntireProjectTrail, EntireRef, EntireRepo, EntireRepoResolution, EntireResolvedProject, EntireReviewComment, EntireReviewPublished, EntireReviewSnapshot, EntireTimelineItem, EntireTreeEntry } from './types.ts' +import { isSha, toFileContent } from '../contents.ts' +import { defineForgeProvider, perKind, verb } from '../define.ts' +import { BranchMovedError, ForgeApiError, ForgeError, NotFoundError, UnsupportedOperationError } from '../errors.ts' +import { eventTime } from '../events.ts' +import { isNamespaceRef } from '../model.ts' +import { getManyConcurrently, memoBy, phased, requireIssueOrPull, resolveToken, toDate, toFileStatus } from '../utils.ts' +import { webUrlFor } from '../web.ts' +import { approvalState, findingComment, flattenMessages, FORGE, identityActor, projectRef, pullRef, toApproval, toBranch, toChangedFile, toCodeReview, toCollaborator, toComment, toCommit, toCoreRepo, toIssue, toPull, toRepo, toReviewThread, toTreeEntry } from './normalise.ts' +import { ENTIRE_WEB, HOST } from './web.ts' + +/** + * A bearer token for an Entire account, such as the one `entire auth token` prints. Login tokens + * expire, so pass `token` as a function to read a fresh one for every request. + */ +export type EntireAuth = TokenAuth + +/** Options for `entire()`. */ +export interface EntireOptions extends ForgeOptionsBase { + auth: EntireAuth + /** + * Control plane root. `/api/v1` is appended. Requests about a project go to the processing cell that the + * control plane names for it. + * @default https://us.console.entire.io + */ + baseUrl?: string +} + +interface Project { + id: string + cell: Fetcher +} + +interface TokenPageShape { + items: string + next: string + size: string + token: string +} + +const camelPage = (items: string): TokenPageShape => ({ items, next: 'nextPageToken', size: 'pageSize', token: 'pageToken' }) +const snakePage = (items: string): TokenPageShape => ({ items, next: 'next_cursor', size: 'per_page', token: 'cursor' }) + +const bearer = (auth: EntireAuth) => async () => ({ authorization: `Bearer ${await resolveToken(auth)}` }) + +function setupEntire({ options, instance, origin, fetcher, createFetcher, baseUrl }: ProviderContext): ProviderSpec & { web: WebLinks } { + const web = ENTIRE_WEB.links({ baseUrl, instance }) + const authHeaders = bearer(options.auth) + const cellFetcher = memoBy(async (apiUrl: string) => createFetcher({ baseUrl: `${apiUrl.replace(/\/$/, '')}/api/v1`, authHeaders })) + + const placed = (raw: Pick | undefined) => raw?.placements?.find(placement => placement.apiBaseUrl && !placement.mirror) + + /** A project the account reads through one of its repositories, when it has no grant on the project itself. */ + async function projectThroughRepo(name: string): Promise { + const { data } = await fetcher.json<{ repos: EntireCoreRepo[] }>('/repos', { query: { org: name, pageSize: 1 } }) + const raw = data.repos[0] + const placement = placed(raw) + if (!raw || !placement?.apiBaseUrl) { + return undefined + } + const cell = await cellFetcher(placement.apiBaseUrl) + const { data: repo } = await cell.json(`/repos/${encodeURIComponent(placement.id)}`) + return repo.owning_project_id ? { id: repo.owning_project_id, cell } : undefined + } + + const project = memoBy(async (name: string): Promise => { + try { + const { data } = await fetcher.json(`/projects/resolve/${HOST}/${encodeURIComponent(name)}`) + if (!data.project.apiUrl) { + throw new NotFoundError(`Project ${name} has no processing cell`, 404, '', origin) + } + return { id: data.project.id, cell: await cellFetcher(data.project.apiUrl) } + } + catch (error) { + const fallback = error instanceof ForgeApiError && error.status === 403 ? await projectThroughRepo(name) : undefined + if (!fallback) { + throw error + } + return fallback + } + }) + + const placement = memoBy(async (path: string): Promise<{ cell: Fetcher, id: string }> => { + const { data } = await fetcher.json<{ resolutions: EntireRepoResolution[] }>('/repos/resolve', { method: 'POST', json: { repositories: [{ fullName: path, provider: 'entire' }] } }) + const found = placed(data.resolutions[0]) + if (!found?.apiBaseUrl) { + throw new NotFoundError(`No repository ${path} on Entire`, 404, '', origin) + } + return { cell: await cellFetcher(found.apiBaseUrl), id: found.id } + }) + + async function located(repo: RepoRef): Promise<{ cell: Fetcher, id: string, path: string }> { + const { cell, id } = await placement(`${repo.owner}/${repo.name}`) + return { cell, id: encodeURIComponent(id), path: `/git/repos/${encodeURIComponent(id)}` } + } + + const trailPath = (repo: RepoRef) => `/trails/${HOST}/${encodeURIComponent(repo.owner)}/${encodeURIComponent(repo.name)}` + const projectTrailPath = (project: string) => `/${HOST}/${encodeURIComponent(project)}/trails` + + async function tokenPage(f: Fetcher, path: string, shape: TokenPageShape, page: PageOptions & { query?: Record }, map: (raw: R) => T | undefined): Promise> { + const { data } = await f.json>(path, { + query: { ...page.query, [shape.size]: page.perPage, [shape.token]: page.cursor?.token }, + signal: page.signal, + }) + const raw = data[shape.items] as R[] | undefined + const next = data[shape.next] + const total = data.total_count + return { + items: (raw ?? []).flatMap(item => map(item) ?? []), + ...typeof total === 'number' ? { total } : {}, + ...typeof next === 'string' && next ? { cursor: { token: next } } : {}, + } + } + + async function everything(f: Fetcher, path: string, shape: TokenPageShape, query: Record, signal?: AbortSignal): Promise { + const items: R[] = [] + let cursor: Cursor | undefined + do { + const page: Page = await tokenPage(f, path, shape, { query, perPage: 100, cursor, signal }, (raw: R) => raw) + items.push(...page.items) + cursor = page.cursor + } while (cursor) + return items + } + + function slice(items: T[], page: PageOptions): Page { + const offset = Number(page.cursor?.token ?? 0) + const size = page.perPage ?? 100 + const next = offset + size + return { items: items.slice(offset, next), ...next < items.length ? { cursor: { token: String(next) } } : {} } + } + + function requirePull(thread: ThreadRef, action: string): ResolvedThreadRef { + const ref = requireIssueOrPull(thread, origin, action) + if (ref.kind !== 'pull_request' || isNamespaceRef(ref.repo)) { + throw new UnsupportedOperationError(`Only changes can be ${action}`, origin) + } + return ref + } + + async function change(ref: ResolvedThreadRef, signal?: AbortSignal): Promise { + const { cell } = await located(ref.repo) + return (await cell.json(`${trailPath(ref.repo)}/${encodeURIComponent(ref.number)}`, { signal })).data + } + + async function parentTrail(repo: RepoRef, raw: EntireChange, signal?: AbortSignal): Promise { + if (!raw.parent) { + return undefined + } + const { cell } = await located(repo) + return (await cell.json(`${projectTrailPath(raw.parent.project)}/${encodeURIComponent(raw.parent.id)}`, { signal })).data + } + + async function get(thread: ThreadRef, opts?: BaseOptions): Promise { + const ref = requireIssueOrPull(thread, origin, 'read') + if (ref.kind === 'pull_request') { + const { repo } = requirePull(ref, 'read') + const raw = await change(ref, opts?.signal) + const parent = raw.body_document?.text_snapshot ? undefined : await parentTrail(repo, raw, opts?.signal) + return toPull(repo, raw, parent?.body) + } + const { cell } = await project(ref.repo.owner) + const { data } = await cell.json(`${projectTrailPath(ref.repo.owner)}/${encodeURIComponent(ref.number)}`, { signal: opts?.signal }) + return toIssue(origin, ref.repo.owner, data) + } + + async function issuesPage(repo: RepoRef, query: ThreadQuery, cursor?: Cursor): Promise> { + const { id, cell } = await project(repo.owner) + const status = query.state === 'all' ? undefined : query.state === 'closed' ? 'closed' : 'open' + return tokenPage(cell, '/trails', camelPage('items'), { + ...query, + cursor, + query: { projectId: id, status, author: query.author, assignee: query.assignee }, + }, (raw: EntireProjectTrail) => toIssue(origin, repo.owner, raw)) + } + + async function pullsPage(repo: RepoRef, query: ThreadQuery, cursor?: Cursor): Promise> { + const { cell } = await located(repo) + const status = query.state === 'all' ? undefined : query.state === 'merged' ? 'merged' : query.state === 'closed' ? 'closed,merged' : 'open' + return tokenPage(cell, trailPath(repo), snakePage('items'), { + ...query, + cursor, + query: { status, author: query.author, assignee: query.assignee }, + }, (raw: EntireChange) => toPull(repo, raw)) + } + + async function listPage(repo: RepoRef, query: ThreadQuery = {}): Promise> { + const warnings: ForgeWarning[] = query.labels?.length ? [{ code: 'filter_unsupported', message: 'Entire trails have no labels' }] : [] + const namespace = isNamespaceRef(repo) + const withWarnings = (page: Page) => warnings.length ? { ...page, warnings: [...page.warnings ?? [], ...warnings] } : page + if (query.kind === 'discussion') { + return { items: [], warnings: [{ code: 'kind_unsupported', message: 'Entire has no discussions' }] } + } + if (query.kind === 'issue' || namespace) { + return query.state === 'merged' ? { items: [] } : withWarnings(await issuesPage(projectRef(origin, repo.owner), query, query.cursor)) + } + if (query.kind === 'pull_request' || query.state === 'merged') { + return withWarnings(await pullsPage(repo, query, query.cursor)) + } + return withWarnings(await phased([ + cursor => issuesPage(projectRef(origin, repo.owner), query, cursor), + cursor => pullsPage(repo, query, cursor), + ], query.cursor)) + } + + async function discussionsAt(ref: ResolvedThreadRef): Promise<{ cell: Fetcher, path: string }> { + if (ref.kind === 'pull_request') { + return { cell: (await located(ref.repo)).cell, path: `${trailPath(ref.repo)}/${encodeURIComponent(ref.number)}/discussions` } + } + return { cell: (await project(ref.repo.owner)).cell, path: `${projectTrailPath(ref.repo.owner)}/${encodeURIComponent(ref.number)}/discussions` } + } + + async function discussions(ref: ResolvedThreadRef, signal?: AbortSignal): Promise { + const { cell, path } = await discussionsAt(ref) + if (ref.kind === 'pull_request') { + return everything(cell, path, snakePage('items'), { include_messages: true }, signal) + } + const list = await everything(cell, path, camelPage('items'), {}, signal) + return Promise.all(list.map(async (discussion) => { + const { data } = await cell.json<{ discussion: EntireDiscussion, messages: EntireDiscussion['messages'] }>(`${path}/${encodeURIComponent(discussion.id)}`, { signal }) + return { ...data.discussion, messages: data.messages } + })) + } + + async function comments(ref: ResolvedThreadRef, signal?: AbortSignal): Promise { + return (await discussions(ref, signal)) + .filter(discussion => !discussion.review_comment_id) + .flatMap(discussion => flattenMessages(discussion.messages).map(message => toComment(ref, discussion, message))) + .sort((a, b) => (a.createdAt?.getTime() ?? 0) - (b.createdAt?.getTime() ?? 0)) + } + + /** The message `ref` names, with its discussion, or the finding it names. */ + async function findComment(ref: CommentRef, signal?: AbortSignal): Promise<{ thread: ResolvedThreadRef, discussion: EntireDiscussion, message?: EntireMessage }> { + const thread = requireIssueOrPull(ref.thread, origin, 'read comments on') + for (const discussion of await discussions(thread, signal)) { + const message = flattenMessages(discussion.messages).find(item => item.id === ref.id) + if (message || discussion.review_comment?.id === ref.id) { + return { thread, discussion, message } + } + } + throw new NotFoundError(`No comment ${ref.id} on ${thread.kind === 'issue' ? 'trail' : 'change'} ${thread.number}`, 404, '', origin) + } + + async function findings(ref: ResolvedThreadRef, signal?: AbortSignal): Promise { + const { cell } = await located(ref.repo) + return everything(cell, `${trailPath(ref.repo)}/${encodeURIComponent(ref.number)}/reviews/comments`, snakePage('comments'), {}, signal) + } + + async function approvals(ref: ResolvedThreadRef, signal?: AbortSignal): Promise { + const { cell } = await located(ref.repo) + return (await cell.json<{ approvals: EntireApproval[] }>(`${trailPath(ref.repo)}/${encodeURIComponent(ref.number)}/approvals`, { signal })).data.approvals + } + + async function codeReview(ref: ResolvedThreadRef, id: string, signal?: AbortSignal): Promise { + const { cell } = await located(ref.repo) + return (await cell.json(`${trailPath(ref.repo)}/${encodeURIComponent(ref.number)}/reviews/${encodeURIComponent(id)}`, { signal })).data + } + + async function reviews(ref: ResolvedThreadRef, signal?: AbortSignal): Promise { + const [approved, all] = await Promise.all([approvals(ref, signal), findings(ref, signal)]) + const byReview = Map.groupBy(all.sort((a, b) => a.created_at.localeCompare(b.created_at)), finding => finding.review_id) + const summaries = await Promise.all([...byReview.keys()].map(async id => (await codeReview(ref, id, signal)).review.summary)) + return [ + ...approved.map(approval => toApproval(ref, approval)), + ...[...byReview].map(([id, items], index) => toCodeReview(ref, id, items, summaries[index])), + ].sort((a, b) => (a.submittedAt?.getTime() ?? 0) - (b.submittedAt?.getTime() ?? 0)) + } + + function toEvent(ref: ResolvedThreadRef, item: EntireTimelineItem, threads = new Map()): ForgeEventInput { + const actor = item.actor ? identityActor(origin, item.actor.identity, item.actor.login) : undefined + const who = actor?.login ?? 'someone' + const base = { + ...origin, + id: item.id, + kindRaw: item.kind, + ...eventTime(toDate(item.occurredAt ?? item.occurred_at), new Date(0)), + actor, + repo: ref.repo, + thread: ref, + source: 'poll' as const, + payload: item, + } + const commentId = item.commentId ?? item.comment_id + const discussion = threads.get(item.discussionId ?? item.discussion_id ?? '') + switch (item.kind) { + case 'comment': { + const body = item.body ?? flattenMessages(discussion?.messages).find(message => message.id === commentId)?.body + const finding = discussion?.review_comment + if (finding) { + const line = finding.location.end_line ?? finding.location.start_line + return { ...base, kind: 'review_comment', summary: `${who} commented on a review`, detail: { type: 'review_comment', ...commentId ? { comment: { ...origin, thread: ref, id: commentId } } : {}, ...body ? { body } : {}, ...finding.location.file_path ? { path: finding.location.file_path } : {}, ...line ? { line } : {} } } + } + return { ...base, kind: 'comment', summary: `${who} commented`, detail: { type: 'comment', ...commentId ? { comment: { ...origin, thread: ref, id: commentId } } : {}, ...body ? { body } : {} } } + } + case 'approval': { + const state = approvalState(item.approvalStatus ?? '') + return { ...base, kind: 'review', summary: `${who} ${state === 'approved' ? 'approved' : state === 'changes_requested' ? 'requested changes' : 'reviewed'}`, detail: { type: 'review', state, ...item.approvalStatus ? { stateRaw: item.approvalStatus } : {}, ...item.body ? { body: item.body } : {}, review: { ...origin, thread: ref, id: item.id.replace(/^trail-approval-/, '') } } } + } + case 'review_posted': + return { ...base, kind: 'review', summary: `${who} reviewed`, detail: { type: 'review', state: 'commented', stateRaw: item.kind, review: { ...origin, thread: ref, id: item.id.replace(/^trail-review-/, '') } } } + case 'commit': + return { ...base, kind: 'commit', summary: item.title ?? 'commit', ...item.commitSha ? { commit: { ...origin, repo: ref.repo, sha: item.commitSha } } : {} } + case 'trail_created': + return { ...base, kind: 'state_change', action: 'opened', summary: `${who} opened the trail`, detail: { type: 'state_change', state: 'open' } } + case 'trail_branch_merged': + return { ...base, kind: 'state_change', action: 'merged', summary: `${who} merged the change`, detail: { type: 'state_change', state: 'merged' } } + default: + return { ...base, kind: 'other', summary: item.title ?? item.kind } + } + } + + async function eventsPage(thread: ThreadRef, list: ListOptions = {}): Promise> { + const ref = requireIssueOrPull(thread, origin, 'read events for') + if (ref.kind === 'pull_request') { + const { cell, id } = await located(requirePull(ref, 'read').repo) + const [page, all] = await Promise.all([ + tokenPage(cell, `/repos/${id}/trails/${encodeURIComponent(ref.number)}/timeline`, camelPage('items'), list, (item: EntireTimelineItem) => item), + discussions(ref, list.signal), + ]) + const threads = new Map(all.map(discussion => [discussion.id, discussion])) + return { ...page, items: page.items.map(item => toEvent(ref, item, threads)) } + } + const { cell } = await project(ref.repo.owner) + return tokenPage(cell, `${projectTrailPath(ref.repo.owner)}/${encodeURIComponent(ref.number)}/timeline`, snakePage('items'), list, (item: EntireTimelineItem) => toEvent(ref, item)) + } + + async function compare(repo: RepoRef, base: string, head: string, compareOptions: CompareOptions = {}): Promise { + const { cell, path } = await located(repo) + const signal = compareOptions.signal + const { data: status } = await cell.json(`${path}/compare/status`, { query: { base, head }, signal }) + const from = status.mergeBaseSHA ?? base + const [files, commits] = await Promise.all([ + compareOptions.files === false ? undefined : cell.json<{ files?: EntireCompareFile[] }>(`${path}/compare`, { query: { base: from, head }, signal }), + cell.json<{ commits: EntireCommit[] }>(`${path}/commits`, { query: { ref: head, notRef: from, pageSize: Math.min(compareOptions.commitLimit ?? 200, 200) }, signal }), + ]) + return { + base, + head, + aheadBy: status.commitsAhead, + behindBy: status.commitsBehind, + commits: commits.data.commits.map(commit => toCommit(origin, repo, commit)), + files: (files?.data.files ?? []).map(toChangedFile), + ...status.mergeBaseSHA ? { mergeBaseSha: status.mergeBaseSHA } : {}, + raw: { status, files: files?.data, commits: commits.data }, + } + } + + async function changeRange(thread: ThreadRef, signal?: AbortSignal): Promise<{ repo: RepoRef, base: string, head: string }> { + const ref = requirePull(thread, 'compared') + const raw = await change(ref, signal) + const head = raw.head_sha ?? raw.branch + if (raw.merge_base_sha) { + return { repo: ref.repo, base: raw.merge_base_sha, head } + } + const { cell, path } = await located(ref.repo) + const { data } = await cell.json(`${path}/compare/status`, { query: { base: raw.base, head }, signal }) + return { repo: ref.repo, base: data.mergeBaseSHA ?? raw.base, head } + } + + async function refsPage(repo: RepoRef, prefix: string, page: PageOptions): Promise> { + const { cell, path } = await located(repo) + return tokenPage(cell, `${path}/refs`, camelPage('refs'), { ...page, query: { prefix, peel: true, symrefs: true } }, (raw: EntireRef) => raw) + } + + async function resolveRef(repo: RepoRef, ref: string, opts?: BaseOptions): Promise { + if (isSha(ref)) { + return ref + } + const { cell, path } = await located(repo) + const { data } = await cell.json<{ commits: EntireCommit[] }>(`${path}/commits`, { query: { ref, pageSize: 1 }, signal: opts?.signal }) + const sha = data.commits[0]?.sha + if (!sha) { + throw new NotFoundError(`No revision ${ref} in ${repo.owner}/${repo.name}`, 404, '', origin) + } + return sha + } + + function actorReference(actor: string | Actor): string { + if (typeof actor !== 'string') { + return `ulid:${actor.id}` + } + return actor.startsWith('ulid:') || actor.startsWith('@') ? actor : `@${actor}` + } + + function refuseLabels(labels: string[] | undefined): void { + if (labels?.length) { + throw new UnsupportedOperationError('Entire trails have no labels', origin) + } + } + + async function create(repo: RepoRef, input: ThreadInput, opts?: BaseOptions): Promise { + refuseLabels(input.labels) + const assignees = input.assignees?.map(actorReference) + if (input.kind === 'issue') { + const scoped = isNamespaceRef(repo) ? undefined : await located(repo) + const cell = scoped?.cell ?? (await project(repo.owner)).cell + const { data } = await cell.json(projectTrailPath(repo.owner), { + method: 'POST', + json: { title: input.title, body: input.body, assignees, repoIds: scoped && [decodeURIComponent(scoped.id)] }, + signal: opts?.signal, + }) + return toIssue(origin, repo.owner, data) + } + if (input.kind !== 'pull_request' || isNamespaceRef(repo)) { + throw new UnsupportedOperationError(`Entire cannot open a ${input.kind.replace('_', ' ')} here`, origin) + } + if (!input.head || !input.base) { + throw new TypeError('A change needs `head` and `base`') + } + if (input.head.includes(':')) { + throw new UnsupportedOperationError('Entire opens changes from branches of the same repository', origin) + } + const { cell, id } = await located(repo) + const repositoryId = decodeURIComponent(id) + const { data } = await cell.json(projectTrailPath(repo.owner), { + method: 'POST', + headers: { 'idempotency-key': crypto.randomUUID() }, + json: { + title: input.title, + body: input.body, + repoIds: [repositoryId], + changes: [{ repositoryId, branchName: input.head, base: input.base, branchAction: 'link', title: input.title, assignees, readyForReview: !input.draft }], + }, + signal: opts?.signal, + }) + const number = data.changes?.find(item => item.repositoryId === repositoryId)?.number + if (number === undefined) { + throw new ForgeError(`Entire opened trail ${data.number} without a change in ${repo.owner}/${repo.name}`, origin) + } + return get(pullRef(repo, number), opts) + } + + async function update(thread: ThreadRef, input: ThreadUpdate, opts?: BaseOptions): Promise { + const ref = requireIssueOrPull(thread, origin, 'update') + refuseLabels(input.labels) + const assignees = input.assignees?.map(actorReference) + const signal = opts?.signal + if (ref.kind === 'issue') { + const { cell } = await project(ref.repo.owner) + const { data } = await cell.json(`${projectTrailPath(ref.repo.owner)}/${encodeURIComponent(ref.number)}`, { + method: 'PATCH', + json: { title: input.title, body: input.body, status: input.state, assignees }, + signal, + }) + return toIssue(origin, ref.repo.owner, data) + } + const pull = requirePull(ref, 'updated') + const { cell } = await located(pull.repo) + if (input.title !== undefined || input.state !== undefined || assignees) { + await cell.json(`${trailPath(pull.repo)}/${encodeURIComponent(pull.number)}`, { method: 'PATCH', json: { title: input.title, status: input.state, assignees }, signal }) + } + if (input.body !== undefined) { + const raw = await change(pull, signal) + if (!raw.parent) { + throw new UnsupportedOperationError(`Change ${pull.number} has no trail to hold its description`, origin) + } + await cell.json(`${projectTrailPath(raw.parent.project)}/${encodeURIComponent(raw.parent.id)}`, { method: 'PATCH', json: { body: input.body }, signal }) + } + return get(pull, opts) + } + + async function createComment(thread: ThreadRef, body: string, opts?: BaseOptions): Promise { + const ref = requireIssueOrPull(thread, origin, 'comment on') + const { cell, path } = await discussionsAt(ref) + const { data } = await cell.json(path, { method: 'POST', json: { body }, signal: opts?.signal }) + return toComment(ref, data.discussion, data.message) + } + + async function messagePath(ref: CommentRef, signal?: AbortSignal) { + const found = await findComment(ref, signal) + if (!found.message) { + throw new UnsupportedOperationError('Entire edits a finding through the code review that left it', origin) + } + const { cell, path } = await discussionsAt(found.thread) + return { ...found, message: found.message, cell, path: `${path}/${encodeURIComponent(found.discussion.id)}/messages/${encodeURIComponent(found.message.id)}` } + } + + async function setResolved(thread: ThreadRef, id: string, resolved: boolean, opts?: BaseOptions): Promise { + const ref = requirePull(thread, 'reviewed') + const { cell, path } = await discussionsAt(ref) + await cell.json(`${path}/${encodeURIComponent(id)}`, { method: 'PATCH', json: { resolved }, signal: opts?.signal }) + } + + /** The text of lines `start` to `end` of `file` at the head of `ref`, which a line finding quotes. */ + async function selectedText(ref: ResolvedThreadRef, file: string, start: number, end: number, signal?: AbortSignal): Promise { + const raw = await change(ref, signal) + const { cell, path } = await located(ref.repo) + const response = await cell.raw(`${path}/raw`, { query: { ref: raw.head_sha ?? raw.branch, path: file }, signal }) + return (await response.text()).split('\n').slice(start - 1, end).join('\n') + } + + async function createReview(thread: ThreadRef, input: ReviewInput, opts?: BaseOptions): Promise { + const ref = requirePull(thread, 'reviewed') + const signal = opts?.signal + const { cell } = await located(ref.repo) + const path = `${trailPath(ref.repo)}/${encodeURIComponent(ref.number)}` + if (input.event === 'approve' || input.event === 'request_changes') { + if (input.comments?.length) { + throw new UnsupportedOperationError('Entire approvals carry no inline comments', origin) + } + const { data } = await cell.json<{ approval: EntireApproval }>(`${path}/approvals`, { method: 'POST', json: { event: input.event, body: input.body }, signal }) + return toApproval(ref, data.approval) + } + if (input.event !== 'comment') { + throw new UnsupportedOperationError('Entire has no pending reviews', origin) + } + const inline = input.comments ?? [] + if (!inline.length && !input.body) { + throw new TypeError('A review needs a body or comments') + } + if (inline.some(comment => comment.side === 'left')) { + throw new UnsupportedOperationError('Entire anchors findings to the head of a change', origin) + } + const comments = inline.length + ? await Promise.all(inline.map(async (comment, index) => { + const end = comment.line + const start = comment.startLine ?? end + return { + client_id: String(index + 1), + body: comment.body, + location: start === undefined || end === undefined + ? { granularity: 'file', file_path: comment.path } + : { granularity: start === end ? 'line' : 'range', file_path: comment.path, start_line: start, end_line: end, selected_text: await selectedText(ref, comment.path, start, end, signal) }, + } + })) + : [{ client_id: '1', body: input.body, location: { granularity: 'whole_change' } }] + const { data: started } = await cell.json<{ review_id: string }>(`${path}/reviews`, { method: 'POST', json: {}, signal }) + const { data } = await cell.json(`${path}/reviews/${encodeURIComponent(started.review_id)}/comments`, { + method: 'POST', + json: { summary: input.body, comments }, + signal, + }) + const failed = data.results.find(result => result.error) + if (failed) { + throw new ForgeError(`Entire refused a review comment: ${failed.error!.message}`, origin) + } + return toCodeReview(ref, started.review_id, data.results.flatMap(result => result.comment ?? []), input.body) + } + + async function getReview(reviewRef: ReviewRef, opts?: BaseOptions): Promise { + const ref = requirePull(reviewRef.thread, 'reviewed') + const approval = (await approvals(ref, opts?.signal)).find(item => item.id === reviewRef.id) + if (approval) { + return toApproval(ref, approval) + } + const { review, comments = [] } = await codeReview(ref, reviewRef.id, opts?.signal) + return toCodeReview(ref, review.id, comments, review.summary) + } + + async function replyToReviewComment(thread: ThreadRef, comment: Pick, body: string, opts?: BaseOptions): Promise { + const ref = requirePull(thread, 'reviewed') + const discussion = comment.thread?.id ?? (comment.ref && (await findComment(comment.ref, opts?.signal)).discussion.id) + if (!discussion) { + throw new UnsupportedOperationError('Entire replies to a review comment in its discussion; pass the comment with its `thread` or `ref`', origin) + } + const { cell, path } = await discussionsAt(ref) + const { data } = await cell.json<{ message: EntireMessage }>(`${path}/${encodeURIComponent(discussion)}/messages`, { method: 'POST', json: { body }, signal: opts?.signal }) + const reply = toComment(ref, { id: discussion, resolved: comment.thread?.resolved ?? false }, data.message) + return { ...reply, ...comment.inReplyTo ?? comment.ref?.id ? { inReplyTo: comment.inReplyTo ?? comment.ref?.id } : {} } + } + + const moved = (error: unknown) => error instanceof ForgeApiError && (error.status === 412 || (error.status === 409 && /head_mismatch/.test(error.body))) + ? new BranchMovedError('The head branch no longer points at the expected sha', error.status, error.body, origin, { cause: error }) + : error + + async function merge(thread: ThreadRef, options: MergeOptions = {}): Promise { + const ref = requirePull(thread, 'merged') + if (options.method && options.method !== 'merge') { + throw new UnsupportedOperationError(`Entire has no ${options.method} merge`, origin) + } + if (options.whenChecksPass) { + throw new UnsupportedOperationError('Entire merges a change once its gates pass, with no queue', origin) + } + const { cell, id } = await located(ref.repo) + const path = `/repos/${id}/trails/${encodeURIComponent(ref.number)}` + const submit = () => cell.json(`${path}/merge`, { method: 'POST', json: { deleteBranch: false, expectedHeadSha: options.sha }, mapError: moved, signal: options.signal }) + const { data } = await submit().catch(async (error: unknown) => { + if (!(error instanceof ForgeApiError) || error.status !== 422 || !/merge_gates_pending/.test(error.body)) { + throw error + } + await cell.json(`${path}/gates/recompute`, { method: 'POST', signal: options.signal }) + return submit() + }) + return { status: 'merged', ...data.mergeCommitSha ? { sha: data.mergeCommitSha } : {}, raw: data } + } + + async function updateBranch(thread: ThreadRef, options: UpdateBranchOptions = {}): Promise { + const ref = requirePull(thread, 'updated') + const { cell, id, path } = await located(ref.repo) + const signal = options.signal + const raw = await change(ref, signal) + if (options.method === 'rebase') { + const response = await cell.raw(`${path}/rebases`, { method: 'POST', json: { branch: raw.branch, onto: raw.base, expectedBranchSHA: options.sha }, mapError: moved, signal }) + const events = (await response.text()).split('\n').filter(Boolean).map(line => JSON.parse(line) as { type: string }) + if (events.at(-1)?.type !== 'completed') { + throw new ForgeError(`Entire did not finish rebasing ${raw.branch}: ${JSON.stringify(events.at(-1))}`, origin) + } + return { status: 'updated', raw: events } + } + if (options.sha && raw.head_sha && raw.head_sha !== options.sha) { + throw new BranchMovedError(`${raw.branch} is at ${raw.head_sha}, not ${options.sha}`, 409, '', origin) + } + const { data } = await cell.json(`/repos/${id}/trails/${encodeURIComponent(ref.number)}/update-branch`, { method: 'POST', signal }) + return { status: 'updated', raw: data } + } + + const GRANT_ROLES: Partial> = { read: 'reader', write: 'writer', admin: 'admin' } + + return { + traits: { + eventKinds: 'native', + authKinds: ['token'], + }, + notApplicable: [ + 'repos.labels', + 'repos.createLabel', + 'repos.milestones', + 'repos.issueTypes', + 'threads.setLabels', + 'threads.addLabels', + 'threads.removeLabels', + 'threads.setMilestone', + 'threads.setIssueType', + 'threads.reactions', + 'threads.react', + 'threads.transfer', + 'threads.markDuplicate', + 'threads.lock', + 'threads.hideComment', + 'releases.list', + 'releases.get', + 'releases.getByTag', + 'releases.latest', + 'releases.create', + 'releases.update', + 'releases.downloadAsset', + ], + users: { + me: verb(true, async (opts): Promise => { + const { data } = await fetcher.json('/me', { signal: opts?.signal }) + return { + ...origin, + login: data.global.username ?? data.global.handle ?? data.global.accountId, + id: data.global.accountId, + ...data.global.displayName ? { name: data.global.displayName } : {}, + ...data.global.avatarUrl ? { avatarUrl: data.global.avatarUrl } : {}, + isBotHint: false, + ...data.regional?.bio ? { bio: data.regional.bio } : {}, + ...data.regional?.location ? { location: data.regional.location } : {}, + ...data.global.createdAt ? { createdAt: toDate(data.global.createdAt) } : {}, + raw: data, + } + }), + }, + repos: { + get: verb(true, async (repo, opts) => { + const { cell, id } = await located(repo) + return toRepo(origin, (await cell.json(`/repos/${id}`, { signal: opts?.signal })).data) + }), + listPage: verb(true, async (query: RepoQuery = {}) => tokenPage(fetcher, '/repos', camelPage('repos'), query, (raw: EntireCoreRepo) => toCoreRepo(origin, raw))), + byOwnerPage: verb(true, async (owner: RepoRef, query: RepoQuery = {}) => { + const { id } = await project(owner.owner) + const page = await tokenPage(fetcher, `/projects/${encodeURIComponent(id)}/repos`, camelPage('repos'), query, (raw: EntireCoreRepo) => toCoreRepo(origin, raw, owner.owner)) + return query.visibility && query.visibility !== 'all' ? { ...page, items: page.items.filter(repo => repo.visibility === query.visibility) } : page + }), + collaboratorsPage: verb(true, async (repo, page: PageOptions = {}) => { + const { id } = await located(repo) + return tokenPage(fetcher, `/repos/${id}/collaborators`, camelPage('collaborators'), page, (raw: EntireCollaborator) => toCollaborator(origin, raw)) + }), + addCollaborator: verb(true, async (repo, actor, role, opts) => { + const grant = GRANT_ROLES[role] + if (!grant) { + throw new UnsupportedOperationError(`Entire has no ${role} repository role`, origin) + } + if (typeof actor === 'string') { + throw new UnsupportedOperationError('Entire grants access to an account by its id; pass an actor', origin) + } + const { id } = await located(repo) + await fetcher.json(`/repos/${id}/grants`, { method: 'POST', json: { accountId: actor.id, role: grant }, signal: opts?.signal }) + return { status: 'added' } + }), + }, + threads: { + get: perKind({ issue: true, pull_request: true }, get), + listPage: perKind({ issue: true, pull_request: true }, listPage), + getMany: verb(true, (refs: ThreadRef[], opts) => getManyConcurrently(refs, get, opts)), + eventsPage: verb(true, eventsPage), + commentsPage: perKind({ issue: true, pull_request: true }, async (thread: ThreadRef, list: ListOptions = {}) => slice(await comments(requireIssueOrPull(thread, origin, 'read comments on'), list.signal), list)), + getComment: perKind({ issue: true, pull_request: true }, async (ref, opts) => { + const { thread, discussion, message } = await findComment(ref, opts?.signal) + return message ? toComment(thread, discussion, message) : findingComment(thread, discussion.review_comment!, discussion.resolved || discussion.review_comment!.status !== 'open') + }), + createComment: perKind({ issue: true, pull_request: true }, createComment), + updateComment: perKind({ issue: true, pull_request: true }, async (ref, body, opts) => { + const { thread, discussion, cell, path } = await messagePath(ref, opts?.signal) + const { data } = await cell.json<{ message: EntireMessage }>(path, { method: 'PATCH', json: { body }, signal: opts?.signal }) + return toComment(thread, discussion, data.message) + }), + deleteComment: perKind({ issue: true, pull_request: true }, async (ref, opts) => { + const { cell, path } = await messagePath(ref, opts?.signal) + await cell.raw(path, { method: 'DELETE', signal: opts?.signal }) + }), + create: perKind({ issue: true, pull_request: true }, create), + update: perKind({ issue: true, pull_request: true }, update), + close: perKind({ issue: true, pull_request: true }, (ref, opts) => update(ref, { state: 'closed' }, opts)), + reopen: perKind({ issue: true, pull_request: true }, (ref, opts) => update(ref, { state: 'open' }, opts)), + setAssignees: perKind({ issue: true, pull_request: true }, async (ref, assignees, opts) => (await update(ref, { assignees }, opts)).assignees), + merge: verb(true, merge), + updateBranch: verb(true, updateBranch), + getReview: verb(true, getReview), + createReview: verb(true, createReview), + replyToReviewComment: verb(true, replyToReviewComment), + reviewThreads: verb(true, { + resolveReviewThread: (ref, id, opts) => setResolved(ref, id, true, opts), + unresolveReviewThread: (ref, id, opts) => setResolved(ref, id, false, opts), + }), + reviewsPage: verb(true, async (thread: ThreadRef, page: PageOptions = {}) => slice(await reviews(requirePull(thread, 'reviewed'), page.signal), page)), + reviewThreadsPage: verb(true, async (thread: ThreadRef, page: PageOptions = {}): Promise> => { + const ref = requirePull(thread, 'reviewed') + const threads = (await discussions(ref, page.signal)) + .filter((discussion): discussion is EntireDiscussion & { review_comment: EntireReviewComment } => Boolean(discussion.review_comment)) + .map(discussion => toReviewThread(ref, discussion)) + return slice(threads, page) + }), + filesPage: verb(true, async (thread: ThreadRef, page: PageOptions = {}): Promise> => { + const { repo, base, head } = await changeRange(thread, page.signal) + const { cell, path } = await located(repo) + const { data } = await cell.json<{ files?: EntireCompareFile[] }>(`${path}/compare`, { query: { base, head }, signal: page.signal }) + return slice((data.files ?? []).map(toChangedFile), page) + }), + commitsPage: verb(true, async (thread: ThreadRef, page: PageOptions = {}): Promise> => { + const { repo, base, head } = await changeRange(thread, page.signal) + const { cell, path } = await located(repo) + return tokenPage(cell, `${path}/commits`, camelPage('commits'), { ...page, query: { ref: head, notRef: base } }, (raw: EntireCommit) => toCommit(origin, repo, raw)) + }), + }, + contents: { + getFile: verb(true, async (repo: RepoRef, filePath: string, fileOptions: FileOptions = {}) => { + const { cell, path } = await located(repo) + const at = fileOptions.ref ?? 'HEAD' + const response = await cell.raw(`${path}/raw`, { query: { ref: at, path: filePath }, signal: fileOptions.signal }) + const bytes = new Uint8Array(await response.arrayBuffer()) + const sha = response.headers.get('entire-sha') ?? undefined + const metadata = { path: filePath, ...sha ? { sha } : {}, size: bytes.byteLength, url: webUrlFor(web, { file: { repo, path: filePath, at } }) } + return toFileContent(bytes, metadata, fileOptions, origin) + }), + treePage: verb(true, async (repo: RepoRef, tree: TreeOptions = {}): Promise> => { + const { cell, path } = await located(repo) + const { data } = await cell.json<{ entries: EntireTreeEntry[], truncated?: boolean }>(`${path}/tree`, { + query: { ref: tree.ref ?? 'HEAD', path: tree.path || undefined, recursive: tree.recursive || undefined }, + signal: tree.signal, + }) + const page = slice(data.entries.map(entry => toTreeEntry(entry, tree.recursive ? '' : tree.path?.replace(/\/$/, '') ?? '')), tree) + return data.truncated ? { ...page, warnings: [{ code: 'tree_truncated', message: 'Entire truncated the tree' }] } : page + }), + branchesPage: verb(true, async (repo: RepoRef, page: PageOptions = {}): Promise> => { + const { cell, path } = await located(repo) + const [head, branches] = await Promise.all([ + cell.json<{ refs: EntireRef[] }>(`${path}/refs`, { query: { prefix: 'HEAD', symrefs: true }, signal: page.signal }), + tokenPage(cell, `${path}/branches`, camelPage('branches'), page, (raw: EntireBranch) => raw), + ]) + const defaultBranch = head.data.refs.find(ref => ref.name === 'HEAD')?.symrefTarget?.replace(/^refs\/heads\//, '') + return { ...branches, items: branches.items.map(raw => toBranch(raw, defaultBranch)) } + }), + tagsPage: verb(true, async (repo: RepoRef, page: PageOptions = {}): Promise> => { + const refs = await refsPage(repo, 'refs/tags/', page) + return { ...refs, items: refs.items.map(raw => ({ name: raw.name.replace(/^refs\/tags\//, ''), sha: raw.peeled ?? raw.oid, raw })) } + }), + resolveRef: verb(true, resolveRef), + compare: verb(true, compare), + }, + commits: { + listPage: verb(true, async (repo: RepoRef, query: CommitQuery = {}): Promise> => { + const { cell, path } = await located(repo) + return tokenPage(cell, `${path}/commits`, camelPage('commits'), { + ...query, + query: { ref: query.ref ?? 'HEAD', path: query.path, author: query.author, since: query.since?.toISOString(), until: query.until?.toISOString(), includeStats: true }, + }, (raw: EntireCommit) => toCommit(origin, repo, raw)) + }), + get: verb(true, async ({ repo, sha }: CommitRef, opts?: BaseOptions) => { + const { cell, path, id } = await located(repo) + const [{ data: list }, { data: detail }] = await Promise.all([ + cell.json<{ commits: EntireCommit[] }>(`${path}/commits`, { query: { ref: sha, pageSize: 1, includeStats: true }, signal: opts?.signal }), + cell.json(`/repos/${id}/commits/${encodeURIComponent(sha)}`, { signal: opts?.signal }), + ]) + const commit = list.commits[0] + if (!commit) { + throw new NotFoundError(`No commit ${sha} in ${repo.owner}/${repo.name}`, 404, '', origin) + } + const files = (detail.commit.fileStats ?? []).map((file): ChangedFile => ({ + path: file.filename, + ...file.previousFilename && file.previousFilename !== file.filename ? { previousPath: file.previousFilename } : {}, + status: toFileStatus(file.status), + statusRaw: file.status, + ...file.additions !== undefined ? { additions: file.additions } : {}, + ...file.deletions !== undefined ? { deletions: file.deletions } : {}, + ...file.patch ? { patch: file.patch } : {}, + })) + return toCommit(origin, repo, commit, files, detail) + }), + }, + web, + webhooks: {}, + scopes: entireScopesFor, + } +} + +const ENTIRE: ProviderDefinition = { + forge: FORGE, + hasWeb: true, + experimental: true, + baseUrl: ENTIRE_WEB.baseUrl, + apiPath: ENTIRE_WEB.apiPath, + instance: ENTIRE_WEB.instance, + authHeaders: ({ options: { auth } }) => bearer(auth), + setup: setupEntire, +} + +/** Creates an Entire provider for the repositories Entire hosts, which live under `et/`. */ +export const entire: ProviderFactoryFunction = /* @__PURE__ */ defineForgeProvider(ENTIRE) + +/** Scope requirements for an Entire operation. */ +function entireScopesFor(_verb: ForgeVerb): VerbScopes { + return { note: 'An Entire login token, which carries the scopes of the account that signed in' } +} diff --git a/src/entire/normalise.ts b/src/entire/normalise.ts new file mode 100644 index 000000000..a7a270ead --- /dev/null +++ b/src/entire/normalise.ts @@ -0,0 +1,363 @@ +import type { Actor, Branch, ChangedFile, Collaborator, Comment, Commit, CommitSignature, ForgeOrigin, Repo, RepoRef, RepoRole, ResolvedThreadRef, Review, ReviewComment, ReviewState, ReviewThread, Thread, TreeEntry } from '../model.ts' +import type { EntireApproval, EntireAuthor, EntireBranch, EntireChange, EntireCollaborator, EntireCommit, EntireCompareFile, EntireCoreRepo, EntireDiscussion, EntireIdentity, EntireMessage, EntirePerson, EntireProjectTrail, EntireRepo, EntireReviewComment, EntireSignature, EntireTreeEntry } from './types.ts' +import { namespaceRef } from '../model.ts' +import { toDate, toFileStatus } from '../utils.ts' + +export const FORGE = 'entire' + +export function projectRef(origin: ForgeOrigin, project: string): RepoRef { + return namespaceRef(origin, project) +} + +export function toRepoRef(origin: ForgeOrigin, project: string, name: string, id?: string): RepoRef { + return { forge: origin.forge, instance: origin.instance, owner: project, name, ...id ? { externalId: id } : {} } +} + +function primaryHandle(identity: EntireIdentity | undefined): string | undefined { + const handles = identity?.handles ?? [] + return (handles.find(handle => handle.is_primary) ?? handles[0])?.handle +} + +/** An account from the identity Entire attaches to people, automations and agents. */ +export function identityActor(origin: ForgeOrigin, identity: EntireIdentity | undefined, login?: string): Actor | undefined { + const name = login ?? identity?.username ?? primaryHandle(identity) ?? identity?.automation?.slug ?? identity?.display_name ?? undefined + if (!name) { + return undefined + } + return { + forge: origin.forge, + instance: origin.instance, + login: name, + id: identity?.account_id ?? name, + ...identity?.display_name ? { name: identity.display_name } : {}, + ...identity?.avatar_url ? { avatarUrl: identity.avatar_url } : {}, + ...identity?.kind && identity.kind !== 'account' ? { typeRaw: identity.kind } : {}, + isBotHint: identity?.kind === 'automation' || identity?.kind === 'agent' || Boolean(identity?.automation), + } +} + +export function personActor(origin: ForgeOrigin, person: EntirePerson | EntireAuthor | undefined): Actor | undefined { + if (!person) { + return undefined + } + const actor = identityActor(origin, person.identity, person.login) + const id = 'accountId' in person ? person.accountId : 'id' in person ? person.id : undefined + return actor && id ? { ...actor, id } : actor +} + +export function toRepo(origin: ForgeOrigin, raw: EntireRepo): Repo { + const [project = '', name = raw.name] = raw.full_name.split('/') + return { + ref: toRepoRef(origin, project, name, raw.id), + ...raw.description ? { description: raw.description } : {}, + ...raw.default_branch ? { defaultBranch: raw.default_branch } : {}, + visibility: raw.private ? 'private' : 'public', + isFork: false, + isArchived: raw.archived, + topics: [], + ...raw.updated_at ? { updatedAt: toDate(raw.updated_at) } : {}, + ...raw.language ? { language: raw.language } : {}, + ...raw.stargazers_count !== undefined ? { stars: raw.stargazers_count } : {}, + ...raw.open_pr_count !== undefined ? { openPullCount: raw.open_pr_count } : {}, + ...raw.permission ? { permissions: permissionsOf(raw.permission) } : {}, + raw, + } +} + +/** A repository as the control plane lists it, or `undefined` for a GitHub mirror. `project` names its project where `raw` does not. */ +export function toCoreRepo(origin: ForgeOrigin, raw: EntireCoreRepo, project?: string): Repo | undefined { + if (raw.provider && raw.provider !== 'entire') { + return undefined + } + const [owner = project ?? raw.org ?? '', name = raw.name] = (raw.full_name ?? '').split('/') + const permission = raw.permission ?? (raw.capabilities?.canManage ? 'admin' : raw.capabilities?.canPush ? 'write' : raw.capabilities?.canPull ? 'read' : undefined) + return { + ref: toRepoRef(origin, owner, name, raw.id), + visibility: raw.visibility === 'public' ? 'public' : 'private', + isFork: false, + isArchived: false, + topics: [], + ...raw.lastPushedAt ? { pushedAt: toDate(raw.lastPushedAt) } : {}, + ...permission ? { permissions: permissionsOf(permission) } : {}, + raw, + } +} + +export function toRole(raw: string | undefined): RepoRole { + switch (raw) { + case 'owner': + case 'admin': + return 'admin' + case 'maintain': + case 'maintainer': + return 'maintain' + case 'write': + case 'writer': + return 'write' + case 'triage': + return 'triage' + case 'read': + case 'reader': + return 'read' + default: + return 'none' + } +} + +function permissionsOf(raw: string): Repo['permissions'] { + const role = toRole(raw) + const rank = ['none', 'read', 'triage', 'write', 'maintain', 'admin'].indexOf(role) + return { admin: rank >= 5, maintain: rank >= 4, push: rank >= 3, triage: rank >= 2, pull: rank >= 1 } +} + +export function toCollaborator(origin: ForgeOrigin, raw: EntireCollaborator): Collaborator { + return { + actor: { forge: origin.forge, instance: origin.instance, login: raw.username, id: raw.accountId, isBotHint: false }, + role: toRole(raw.role), + roleRaw: raw.role, + raw, + } +} + +export function toBranch(raw: EntireBranch, defaultBranch?: string): Branch { + return { name: raw.name, sha: raw.commitSHA, ...defaultBranch ? { isDefault: raw.name === defaultBranch } : {}, raw } +} + +function toSignature(raw: EntireSignature | undefined): CommitSignature | undefined { + return raw ? { ...raw.name ? { name: raw.name } : {}, ...raw.email ? { email: raw.email } : {}, ...raw.date ? { date: toDate(raw.date) } : {} } : undefined +} + +export function toCommit(origin: ForgeOrigin, repo: RepoRef, raw: EntireCommit, files?: ChangedFile[], detail?: unknown): Commit { + return { + ref: { forge: origin.forge, instance: origin.instance, repo, sha: raw.sha }, + sha: raw.sha, + message: raw.message.replace(/\n$/, ''), + author: toSignature(raw.author), + committer: toSignature(raw.committer), + parents: raw.parents, + ...raw.stats ? { stats: { additions: raw.stats.additions, deletions: raw.stats.deletions, total: raw.stats.additions + raw.stats.deletions } } : {}, + ...files ? { files } : {}, + raw: detail === undefined ? raw : { commit: raw, detail }, + } +} + +export function toChangedFile(raw: EntireCompareFile): ChangedFile { + return { + path: raw.path, + ...raw.oldPath && raw.oldPath !== raw.path ? { previousPath: raw.oldPath } : {}, + status: toFileStatus(raw.status), + statusRaw: raw.status, + ...raw.additions !== undefined ? { additions: raw.additions } : {}, + ...raw.deletions !== undefined ? { deletions: raw.deletions } : {}, + ...raw.binary ? { isBinary: true } : {}, + } +} + +export function toTreeEntry(raw: EntireTreeEntry, parent: string): TreeEntry { + const path = parent && !raw.path.startsWith(`${parent}/`) ? `${parent}/${raw.path}` : raw.path + return { + path, + type: raw.type === 'tree' ? 'directory' : raw.type === 'commit' ? 'submodule' : raw.mode === '120000' ? 'symlink' : 'file', + sha: raw.sha, + ...raw.type === 'blob' && raw.size !== undefined ? { size: raw.size } : {}, + mode: raw.mode, + } +} + +export function issueRef(origin: ForgeOrigin, project: string, number: number | string): ResolvedThreadRef { + return { forge: origin.forge, instance: origin.instance, repo: projectRef(origin, project), kind: 'issue', number: String(number) } +} + +export function pullRef(repo: RepoRef, number: number | string): ResolvedThreadRef { + return { forge: repo.forge, instance: repo.instance, repo, kind: 'pull_request', number: String(number) } +} + +/** A project trail, read as an issue. */ +export function toIssue(origin: ForgeOrigin, project: string, raw: EntireProjectTrail): Thread { + return { + ref: { ...issueRef(origin, project, raw.number), externalId: raw.id }, + kind: 'issue', + title: raw.title, + ...raw.body ? { body: raw.body } : {}, + state: raw.status === 'closed' ? 'closed' : 'open', + stateRaw: raw.status, + isDraft: false, + author: personActor(origin, raw.author), + assignees: (raw.assigneeProfiles ?? []).flatMap(person => personActor(origin, person) ?? []), + reviewers: [], + labels: [], + ...raw.url ? { url: raw.url } : {}, + createdAt: toDate(raw.createdAt), + updatedAt: toDate(raw.metadataUpdatedAt), + ...raw.closedAt ? { closedAt: toDate(raw.closedAt) } : {}, + lastActivityAt: toDate(raw.lastActivityAt), + ...raw.type ? { issueType: { id: raw.type, name: raw.type, raw: raw.type } } : {}, + raw, + } +} + +function reviewerState(raw: string | undefined): ReviewState { + switch (raw) { + case 'approved': + return 'approved' + case 'changes_requested': + return 'changes_requested' + case 'requested': + case 'pending': + return 'pending' + case 'dismissed': + return 'dismissed' + default: + return 'unknown' + } +} + +/** A change, the branch of one repository on a trail, read as a pull request. Its description is its parent trail's body, `parentBody`, unless it has its own. */ +export function toPull(repo: RepoRef, raw: EntireChange, parentBody?: string): Thread { + const origin = { forge: repo.forge, instance: repo.instance } + const state = raw.status === 'merged' ? 'merged' : raw.status === 'closed' ? 'closed' : raw.status === 'open' ? 'open' : 'unknown' + const body = raw.body_document?.text_snapshot || parentBody + return { + ref: { ...pullRef(repo, raw.number), externalId: raw.id }, + kind: 'pull_request', + title: raw.title, + ...body ? { body } : {}, + state, + stateRaw: raw.status, + isDraft: raw.ready_for_review === false, + author: personActor(origin, raw.author), + assignees: (raw.assignee_identities ?? []).flatMap(assignee => identityActor(origin, assignee.identity, assignee.login) ?? []), + reviewers: (raw.reviewers ?? []).flatMap((reviewer) => { + const actor = identityActor(origin, reviewer.identity, reviewer.login) + const state = reviewer.state ?? reviewer.status + return actor ? [{ actor, state: reviewerState(state), ...state ? { stateRaw: state } : {} }] : [] + }), + labels: [], + ...raw.url ? { url: raw.url } : {}, + createdAt: toDate(raw.created_at), + updatedAt: toDate(raw.updated_at), + ...raw.merged_at ? { mergedAt: toDate(raw.merged_at), closedAt: toDate(raw.merged_at) } : {}, + lastActivityAt: toDate(raw.last_activity_at), + ...raw.comment_count !== undefined ? { commentCount: raw.comment_count } : {}, + branches: { + head: { ref: raw.branch || raw.original_branch || '', ...raw.head_sha ? { sha: raw.head_sha } : {}, repo }, + base: { ref: raw.base, ...raw.base_sha ? { sha: raw.base_sha } : {} }, + }, + raw, + } +} + +/** Every message of a discussion, replies after the message they answer. */ +export function flattenMessages(messages: EntireMessage[] = []): EntireMessage[] { + return messages.flatMap(message => [message, ...flattenMessages(message.replies)]) +} + +export function toComment(thread: ResolvedThreadRef, discussion: Pick, raw: EntireMessage): Comment { + return { + ref: { forge: thread.forge, instance: thread.instance, thread, id: raw.id }, + body: raw.body, + author: identityActor(thread, raw.identity, raw.author), + createdAt: toDate(raw.created_at), + ...raw.updated_at ? { updatedAt: toDate(raw.updated_at) } : {}, + thread: { id: discussion.id, resolved: discussion.resolved }, + raw, + } +} + +function findingAuthor(thread: ResolvedThreadRef, raw: EntireReviewComment): Actor | undefined { + const actor = identityActor(thread, raw.actor_identity?.kind === 'unknown' ? undefined : raw.actor_identity, undefined) + return actor ?? (raw.actor_display_name ? { forge: thread.forge, instance: thread.instance, login: raw.actor_display_name, id: raw.actor_id ?? raw.actor_display_name, isBotHint: false } : undefined) +} + +function anchor(raw: EntireReviewComment): Pick { + const { file_path, end_line, start_line } = raw.location + const line = end_line ?? start_line + return { + ...file_path ? { path: file_path } : {}, + ...line ? { line, side: 'right' as const } : {}, + } +} + +/** A finding: a review comment an agent or a person left on a change. */ +export function toFinding(thread: ResolvedThreadRef, raw: EntireReviewComment, resolved = raw.status !== 'open'): ReviewComment { + return { + ref: { forge: thread.forge, instance: thread.instance, thread, id: raw.id }, + body: raw.body ?? '', + author: findingAuthor(thread, raw), + ...anchor(raw), + ...raw.discussion_id ? { thread: { id: raw.discussion_id, resolved } } : {}, + createdAt: toDate(raw.created_at), + raw, + } +} + +/** A finding, read as a comment. */ +export function findingComment(thread: ResolvedThreadRef, raw: EntireReviewComment, resolved = raw.status !== 'open'): Comment { + return { + ref: { forge: thread.forge, instance: thread.instance, thread, id: raw.id }, + body: raw.body ?? '', + author: findingAuthor(thread, raw), + createdAt: toDate(raw.created_at), + ...raw.updated_at ? { updatedAt: toDate(raw.updated_at) } : {}, + ...raw.discussion_id ? { thread: { id: raw.discussion_id, resolved } } : {}, + raw, + } +} + +/** A finding and the discussion under it, read as a review conversation. */ +export function toReviewThread(thread: ResolvedThreadRef, discussion: EntireDiscussion & { review_comment: EntireReviewComment }): ReviewThread { + const finding = discussion.review_comment + const resolved = discussion.resolved || finding.status !== 'open' + const { start_line, end_line } = finding.location + const replies = flattenMessages(discussion.messages).map((message): ReviewComment => ({ + ref: { forge: thread.forge, instance: thread.instance, thread, id: message.id }, + body: message.body, + author: identityActor(thread, message.identity, message.author), + ...anchor(finding), + inReplyTo: finding.id, + thread: { id: discussion.id, resolved }, + createdAt: toDate(message.created_at), + raw: message, + })) + return { + id: discussion.id, + resolved, + outdated: finding.stale_outcome === 'stale', + ...anchor(finding), + ...start_line && end_line && start_line !== end_line ? { startLine: start_line } : {}, + comments: [toFinding(thread, finding, resolved), ...replies], + raw: discussion, + } +} + +export function approvalState(raw: string): ReviewState { + return raw === 'approved' || raw === 'approve' ? 'approved' : raw === 'changes_requested' || raw === 'request_changes' ? 'changes_requested' : raw === 'dismissed' ? 'dismissed' : 'unknown' +} + +export function toApproval(thread: ResolvedThreadRef, raw: EntireApproval): Review { + return { + ref: { forge: thread.forge, instance: thread.instance, thread, id: raw.id }, + author: { forge: thread.forge, instance: thread.instance, login: raw.author, id: raw.author, isBotHint: false }, + state: approvalState(raw.event), + stateRaw: raw.event, + ...raw.body ? { body: raw.body } : {}, + submittedAt: toDate(raw.created_at), + comments: false, + raw, + } +} + +/** The findings of one code review, as a review that comments. */ +export function toCodeReview(thread: ResolvedThreadRef, id: string, findings: EntireReviewComment[], summary?: string | null): Review { + const [first] = findings + return { + ref: { forge: thread.forge, instance: thread.instance, thread, id }, + author: first ? findingAuthor(thread, first) : undefined, + state: 'commented', + stateRaw: 'review', + ...summary ? { body: summary } : {}, + submittedAt: first ? toDate(first.created_at) : undefined, + comments: findings.map(finding => toFinding(thread, finding)), + raw: findings, + } +} diff --git a/src/entire/types.ts b/src/entire/types.ts new file mode 100644 index 000000000..fac0e1777 --- /dev/null +++ b/src/entire/types.ts @@ -0,0 +1,322 @@ +export interface EntireIdentityHandle { + provider: string + handle: string + is_primary?: boolean +} + +export interface EntireIdentity { + kind: string + account_id?: string | null + display_name?: string | null + avatar_url?: string | null + username?: string + handles?: EntireIdentityHandle[] + automation?: { kind?: string, name?: string, slug?: string } | null +} + +/** A person as project trails report them. */ +export interface EntirePerson { + accountId?: string + login: string + displayName?: string + avatarUrl?: string + username?: string + identity?: EntireIdentity +} + +/** A person as repository trails report them. */ +export interface EntireAuthor { + id?: string + login: string + identity?: EntireIdentity +} + +export interface EntireProject { + id: string + name: string + ownerType?: string + ownerName?: string + region?: string + createdAt?: string + primaryProcessingCell?: string + apiUrl?: string +} + +export interface EntireResolvedProject { + project: EntireProject + reference?: { host: string, project: string } +} + +/** A repository as the control plane lists it. */ +export interface EntireCoreRepo { + id: string + name: string + full_name?: string + org?: string + provider?: string + visibility?: string + permission?: string + path?: string + owningProjectId?: string + lastPushedAt?: string + placements?: Array<{ id: string, apiBaseUrl?: string, mirror?: boolean, status?: string }> + capabilities?: { canManage?: boolean, canPush?: boolean, canPull?: boolean } +} + +/** Where the control plane places a repository. */ +export interface EntireRepoResolution { + requestedFullName: string + status: string + repoId?: string + placements?: EntireCoreRepo['placements'] +} + +/** A repository as a cell reports it. */ +export interface EntireRepo { + id: string + owning_project_id?: string + name: string + full_name: string + description?: string | null + private: boolean + archived: boolean + updated_at?: string + default_branch?: string + language?: string | null + stargazers_count?: number + permission?: string + trails_enabled?: boolean + open_pr_count?: number +} + +export interface EntireCollaborator { + accountId: string + username: string + handle?: string + role: string +} + +export interface EntireMe { + global: { + accountId: string + handle?: string + username?: string + displayName?: string + avatarUrl?: string + createdAt?: string + homeJurisdiction?: string + } + regional?: { + displayName?: string + bio?: string + location?: string + } +} + +export interface EntireBranch { + name: string + commitSHA: string +} + +export interface EntireRef { + name: string + oid: string + symrefTarget?: string + peeled?: string +} + +export interface EntireSignature { + name?: string + email?: string + date?: string +} + +export interface EntireCommit { + sha: string + parents: string[] + message: string + author?: EntireSignature + committer?: EntireSignature + stats?: { additions: number, deletions: number, filesChanged?: number, truncated?: boolean } | null +} + +export interface EntireCommitDetail { + commit_sha: string + commit: { + commitSha: string + fileStats?: Array<{ filename: string, previousFilename?: string | null, status: string, additions?: number, deletions?: number, patch?: string | null }> + } +} + +export interface EntireCompareStatus { + commitsAhead: number + commitsBehind: number + mergeBaseSHA?: string + resolvedBaseSHA?: string + resolvedHeadSHA?: string +} + +export interface EntireCompareFile { + path: string + oldPath?: string + status: string + additions?: number + deletions?: number + binary?: boolean +} + +export interface EntireTreeEntry { + path: string + mode: string + type: string + sha: string + size?: number +} + +/** A project trail: what the provider reads as an issue. */ +export interface EntireProjectTrail { + id: string + projectId: string + number: number + url?: string + title: string + body?: string + status: 'open' | 'closed' + phase?: string + type?: string + priority?: string + author?: EntirePerson + assigneeProfiles?: EntirePerson[] + assignees?: string[] + repoIds?: string[] + createdAt?: string + metadataUpdatedAt?: string + closedAt?: string | null + lastActivityAt?: string + changes?: Array<{ id: string, repositoryId: string, repository: string, number: number, branch: string, base: string, status: string, title: string }> +} + +/** A repository trail, which the trail docs call a change: what the provider reads as a pull request. */ +export interface EntireChange { + id: string + number: number + url?: string + title: string + status: string + branch: string + original_branch?: string + base: string + type?: string + priority?: string + author?: EntireAuthor + assignees?: string[] + assignee_identities?: Array<{ login: string, identity?: EntireIdentity }> + reviewers?: Array<{ login: string, state?: string, status?: string, identity?: EntireIdentity, actor_account_id?: string }> + ready_for_review?: boolean + comment_count?: number + created_at?: string + updated_at?: string + merged_at?: string | null + last_activity_at?: string + phase?: string | null + parent?: { id: string, number: number, host: string, project: string, url?: string } + head_sha?: string | null + base_sha?: string | null + merge_base_sha?: string | null + body_document?: { text_snapshot?: string } | null +} + +export interface EntireDiscussionCreated { + discussion: EntireDiscussion + message: EntireMessage +} + +/** A code review, with its summary and findings. */ +export interface EntireReviewSnapshot { + review: { id: string, summary?: string | null, actor_id?: string | null, started_at?: string } + comments?: EntireReviewComment[] +} + +export interface EntireReviewPublished { + review?: EntireReviewSnapshot['review'] + results: Array<{ client_id: string, status: string, comment?: EntireReviewComment, error?: { code: string, message: string } }> +} + +export interface EntireMerged { + ok: boolean + mergeCommitSha?: string + branchDeleted?: boolean +} + +export interface EntireMessage { + id: string + author: string + identity?: EntireIdentity + body: string + created_at: string + updated_at?: string + replies?: EntireMessage[] +} + +export interface EntireReviewComment { + id: string + review_id: string + discussion_id?: string | null + actor_id?: string | null + actor_display_name?: string | null + actor_identity?: EntireIdentity + body?: string | null + severity?: string | null + status: string + stale_outcome?: string + created_at: string + updated_at?: string + location: { + granularity: string + file_path?: string | null + start_line?: number | null + end_line?: number | null + } +} + +export interface EntireDiscussion { + id: string + trail_id: string + title?: string + kind: string + resolved: boolean + created_by?: string | null + created_by_identity?: EntireIdentity + created_at: string + updated_at?: string + message_count: number + messages?: EntireMessage[] + review_comment_id?: string | null + review_comment?: EntireReviewComment | null +} + +export interface EntireApproval { + id: string + author: string + event: string + body?: string | null + commit_sha?: string + created_at: string +} + +export interface EntireTimelineItem { + id: string + kind: string + actor?: { login: string, identity?: EntireIdentity } | null + occurredAt?: string + occurred_at?: string + commentId?: string + comment_id?: string + discussionId?: string + discussion_id?: string + approvalStatus?: string + body?: string + title?: string + commitSha?: string + findingCount?: number +} diff --git a/src/entire/web.ts b/src/entire/web.ts new file mode 100644 index 000000000..7e14c24f3 --- /dev/null +++ b/src/entire/web.ts @@ -0,0 +1,61 @@ +import type { RepoRef } from '../model.ts' +import type { WebDefinition, WebLinks } from '../web.ts' + +/** Entire's prefix for repositories it hosts, beside `gh` for GitHub mirrors. */ +export const HOST = 'et' + +const projectPath = (project: string) => `/${HOST}/${encodeURIComponent(project)}` +const repoPath = (repo: RepoRef) => repo.kind === 'namespace' ? projectPath(repo.owner) : `${projectPath(repo.owner)}/${encodeURIComponent(repo.name)}` + +export const ENTIRE_WEB: WebDefinition<'entire'> = { + forge: 'entire', + baseUrl: 'https://us.console.entire.io', + apiPath: '/api/v1', + instance: host => host.endsWith('.console.entire.io') ? 'entire.com' : host, + links: ({ instance }) => entireWeb(instance === 'entire.com' ? 'https://entire.com' : `https://${instance}`), +} + +/** + * A project trail is at `/et/{project}/-/trails/{number}`, and a change, the + * branch of one repository on a trail, at `/et/{project}/{repo}/trails/{number}`. + */ +function entireWeb(baseUrl: string): WebLinks { + return { + baseUrl, + repo: repo => repoPath(repo), + section: (repo, section) => { + if (section === 'issues') { + return `${projectPath(repo.owner)}/-/trails` + } + return section === 'pullRequests' && repo.kind !== 'namespace' ? `${repoPath(repo)}/trails` : undefined + }, + thread: (ref) => { + if (!ref.number) { + return undefined + } + if (ref.kind === 'issue') { + return `${projectPath(ref.repo.owner)}/-/trails/${encodeURIComponent(ref.number)}` + } + return ref.kind === 'pull_request' && ref.repo.kind !== 'namespace' ? `${repoPath(ref.repo)}/trails/${encodeURIComponent(ref.number)}` : undefined + }, + parse: (segments, _url, from) => { + const [host, project, name, section, number] = segments + if (host !== HOST || !project) { + return undefined + } + const namespace: RepoRef = { ...from, owner: project, name: '', kind: 'namespace' } + if (!name) { + return { repo: namespace } + } + if (name === '-') { + return section === 'trails' && number && /^\d+$/.test(number) + ? { repo: namespace, thread: { ...from, repo: namespace, kind: 'issue', number } } + : { repo: namespace } + } + const repo: RepoRef = { ...from, owner: project, name } + return section === 'trails' && number && /^\d+$/.test(number) + ? { repo, thread: { ...from, repo, kind: 'pull_request', number } } + : { repo } + }, + } +} diff --git a/src/env.ts b/src/env.ts index e02a594be..9eb48f15f 100644 --- a/src/env.ts +++ b/src/env.ts @@ -4,6 +4,7 @@ import { azureDevOps } from './azure-devops/index.ts' import { bitbucket } from './bitbucket/index.ts' import { cloudflareArtifacts } from './cloudflare-artifacts/index.ts' import { cursorOrigin } from './cursor-origin/index.ts' +import { entire } from './entire/index.ts' import { forgejo } from './forgejo/index.ts' import { gitea } from './gitea/index.ts' import { gitee } from './gitee/index.ts' @@ -14,7 +15,7 @@ import { pushin } from './pushin/index.ts' import { sourcehut } from './sourcehut/index.ts' import { tangled } from './tangled/index.ts' -const KINDS = ['GITHUB', 'GITLAB', 'BITBUCKET', 'FORGEJO', 'GITEA', 'TANGLED', 'CURSOR_ORIGIN', 'GITEE', 'AZURE_DEVOPS', 'PUSHIN', 'CLOUDFLARE_ARTIFACTS', 'SOURCEHUT'] as const +const KINDS = ['GITHUB', 'GITLAB', 'BITBUCKET', 'FORGEJO', 'GITEA', 'TANGLED', 'CURSOR_ORIGIN', 'GITEE', 'AZURE_DEVOPS', 'PUSHIN', 'CLOUDFLARE_ARTIFACTS', 'SOURCEHUT', 'ENTIRE'] as const /** Field names, longest first so `INSTANCE_VERSION` is not read as `INSTANCE` with suffix `VERSION`. */ const FIELDS = [ @@ -168,6 +169,10 @@ function fromFields(kind: typeof KINDS[number], suffix: string, fields: Partial< return isOn(fields.ENABLED) ? { ...entry, provider: cursorOrigin(base) } : { ...entry, skipped: 'needs TOKEN, or APP_ID and PRIVATE_KEY, or ENABLED for webhooks only' } + case 'ENTIRE': + return fields.TOKEN + ? { ...entry, provider: entire({ ...base, auth: { type: 'token', token: fields.TOKEN } }) } + : { ...entry, skipped: 'needs TOKEN' } case 'SOURCEHUT': return fields.TOKEN ? { ...entry, provider: sourcehut({ ...base, ...fields.WEBHOOK_PUBLIC_KEY ? { webhookPublicKey: fields.WEBHOOK_PUBLIC_KEY } : {}, auth: { type: 'token', token: fields.TOKEN } }) } diff --git a/src/index.ts b/src/index.ts index 111199145..a0ed423d2 100644 --- a/src/index.ts +++ b/src/index.ts @@ -7,6 +7,8 @@ export type { CloudflareArtifactsAuth, CloudflareArtifactsOptions } from './clou export { cursorOrigin, ORIGIN_API_VERSION } from './cursor-origin/index.ts' export type { CursorOriginAuth, CursorOriginOptions } from './cursor-origin/index.ts' export type { ProviderFactoryFunction } from './define.ts' +export { entire } from './entire/index.ts' +export type { EntireAuth, EntireOptions } from './entire/index.ts' export { AuthenticationRequiredError, BranchMovedError, diff --git a/src/model.ts b/src/model.ts index 91f538688..5633f2c61 100644 --- a/src/model.ts +++ b/src/model.ts @@ -12,7 +12,7 @@ export type ForgeKind = KnownForgeKind | (string & {}) /** The forges this package ships providers for. */ -export type KnownForgeKind = 'github' | 'gitlab' | 'bitbucket' | 'forgejo' | 'gitea' | 'tangled' | 'gitee' | 'azure-devops' | 'cursor-origin' | 'pushin' | 'cloudflare-artifacts' | 'sourcehut' +export type KnownForgeKind = 'github' | 'gitlab' | 'bitbucket' | 'forgejo' | 'gitea' | 'tangled' | 'gitee' | 'azure-devops' | 'cursor-origin' | 'pushin' | 'cloudflare-artifacts' | 'sourcehut' | 'entire' /** * Capability flag. Every value other than `false` and `'not_applicable'` means the diff --git a/src/schema/schemas.json b/src/schema/schemas.json index 13129f8d3..4863437c3 100644 --- a/src/schema/schemas.json +++ b/src/schema/schemas.json @@ -2749,7 +2749,8 @@ "cursor-origin", "pushin", "cloudflare-artifacts", - "sourcehut" + "sourcehut", + "entire" ], "description": "The forges this package ships providers for.", "x-forges-type": "KnownForgeKind" diff --git a/src/web/index.ts b/src/web/index.ts index e5cda5197..3c00e237c 100644 --- a/src/web/index.ts +++ b/src/web/index.ts @@ -6,6 +6,7 @@ import type { ForgeWeb, WebForges, WebOptions } from '../web.ts' import { AZURE_DEVOPS_WEB } from '../azure-devops/web.ts' import { BITBUCKET_WEB } from '../bitbucket/web.ts' +import { ENTIRE_WEB } from '../entire/web.ts' import { FORGEJO_WEB, GITEA_WEB } from '../forgejo/web.ts' import { GITEE_WEB } from '../gitee/web.ts' import { GITHUB_WEB } from '../github/web.ts' @@ -22,6 +23,8 @@ export type { ForgeWeb, WebForges } export const azureDevOps: (options?: WebOptions) => ForgeWeb<'azure-devops'> = /* @__PURE__ */ defineForgeWeb(AZURE_DEVOPS_WEB) /** The web links of Bitbucket Cloud. */ export const bitbucket: (options?: WebOptions) => ForgeWeb<'bitbucket'> = /* @__PURE__ */ defineForgeWeb(BITBUCKET_WEB) +/** The web links of Entire. */ +export const entire: (options?: WebOptions) => ForgeWeb<'entire'> = /* @__PURE__ */ defineForgeWeb(ENTIRE_WEB) /** The web links of Codeberg or another Forgejo instance. */ export const forgejo: (options?: WebOptions) => ForgeWeb<'forgejo'> = /* @__PURE__ */ defineForgeWeb(FORGEJO_WEB) /** The web links of gitea.com or another Gitea instance. */ diff --git a/test/fixtures/entire/recorded/entire.com-writes/manifest.json b/test/fixtures/entire/recorded/entire.com-writes/manifest.json new file mode 100644 index 000000000..c962db391 --- /dev/null +++ b/test/fixtures/entire/recorded/entire.com-writes/manifest.json @@ -0,0 +1,29 @@ +{ + "baseUrl": "https://us.console.entire.io/api/v1", + "repo": { + "forge": "entire", + "instance": "entire.com", + "owner": "forges-scratch", + "name": "forges-fixtures" + }, + "scratch": { + "forge": "entire", + "instance": "entire.com", + "owner": "forges-scratch", + "name": "forges-fixtures" + }, + "run": { + "id": "20261026210133", + "base": "main", + "branches": [ + "forges-fixtures/20261026210133-1", + "forges-fixtures/20261026210133-2", + "forges-fixtures/20261026210133-3" + ], + "files": [ + "forges-fixtures/20261026210133-1.md", + "forges-fixtures/20261026210133-2.md", + "forges-fixtures/20261026210133-3.md" + ] + } +} diff --git a/test/fixtures/entire/recorded/entire.com-writes/steps/add-collaborator/01-post-01M5WYSQC41P69DTXEMZ0TE5YK-grants.json b/test/fixtures/entire/recorded/entire.com-writes/steps/add-collaborator/01-post-01M5WYSQC41P69DTXEMZ0TE5YK-grants.json new file mode 100644 index 000000000..905944f62 --- /dev/null +++ b/test/fixtures/entire/recorded/entire.com-writes/steps/add-collaborator/01-post-01M5WYSQC41P69DTXEMZ0TE5YK-grants.json @@ -0,0 +1,20 @@ +{ + "request": { + "method": "POST", + "url": "https://us.console.entire.io/api/v1/repos/01M5WYSQC41P69DTXEMZ0TE5YK/grants", + "body": { + "accountId": "01M5WRP9RJ4GVR2PA5PCNYP1FC", + "role": "writer" + } + }, + "response": { + "status": 201, + "headers": { + "link": "; rel=\"describedBy\"" + }, + "body": { + "$schema": "https://us.console.entire.io/api/v1/schemas/GrantRepoAccessOutputBody.json", + "status": "granted" + } + } +} diff --git a/test/fixtures/entire/recorded/entire.com-writes/steps/add-collaborator/02-post-repos-resolve.json b/test/fixtures/entire/recorded/entire.com-writes/steps/add-collaborator/02-post-repos-resolve.json new file mode 100644 index 000000000..0fea65502 --- /dev/null +++ b/test/fixtures/entire/recorded/entire.com-writes/steps/add-collaborator/02-post-repos-resolve.json @@ -0,0 +1,56 @@ +{ + "request": { + "method": "POST", + "url": "https://us.console.entire.io/api/v1/repos/resolve", + "body": { + "repositories": [ + { + "fullName": "forges-scratch/forges-fixtures", + "provider": "entire" + } + ] + } + }, + "response": { + "status": 200, + "headers": { + "link": "; rel=\"describedBy\"" + }, + "body": { + "$schema": "https://us.console.entire.io/api/v1/schemas/ResolveReposResponse.json", + "resolutions": [ + { + "provider": "entire", + "requestedFullName": "forges-scratch/forges-fixtures", + "fullName": "forges-scratch/forges-fixtures", + "status": "ready", + "repoId": "01M5WYSQC41P69DTXEMZ0TE5YK", + "repoGroupId": "01M5WYSQC42H6K0NWNZ6FYTSRQ", + "placements": [ + { + "id": "01M5WYSQC41P69DTXEMZ0TE5YK", + "jurisdiction": "eu", + "cell": "aws-eu-central-1", + "apiBaseUrl": "https://aws-eu-central-1.api.entire.io", + "clusterSlug": "aws-eu-central-1", + "mirror": false, + "status": "ready" + } + ], + "primaries": { + "git_data": "entire:01M5WYSQC41P69DTXEMZ0TE5YK", + "processing": "01M5WYSQC41P69DTXEMZ0TE5YK", + "data_primary": { + "forge": "entire", + "repo_id": "01M5WYSQC41P69DTXEMZ0TE5YK" + }, + "processing_primary": { + "forge": "entire", + "repo_id": "01M5WYSQC41P69DTXEMZ0TE5YK" + } + } + } + ] + } + } +} diff --git a/test/fixtures/entire/recorded/entire.com-writes/steps/add-collaborator/golden.json b/test/fixtures/entire/recorded/entire.com-writes/steps/add-collaborator/golden.json new file mode 100644 index 000000000..490680bdd --- /dev/null +++ b/test/fixtures/entire/recorded/entire.com-writes/steps/add-collaborator/golden.json @@ -0,0 +1,3 @@ +{ + "status": "added" +} diff --git a/test/fixtures/entire/recorded/entire.com-writes/steps/add-collaborator/step.json b/test/fixtures/entire/recorded/entire.com-writes/steps/add-collaborator/step.json new file mode 100644 index 000000000..b522b0e09 --- /dev/null +++ b/test/fixtures/entire/recorded/entire.com-writes/steps/add-collaborator/step.json @@ -0,0 +1,7 @@ +{ + "name": "add collaborator", + "recordedAt": "2026-10-26T21:00:32.537Z", + "needs": [ + "reviewer" + ] +} diff --git a/test/fixtures/entire/recorded/entire.com-writes/steps/approve/01-post-N-approvals.json b/test/fixtures/entire/recorded/entire.com-writes/steps/approve/01-post-N-approvals.json new file mode 100644 index 000000000..59d2bd6e5 --- /dev/null +++ b/test/fixtures/entire/recorded/entire.com-writes/steps/approve/01-post-N-approvals.json @@ -0,0 +1,138 @@ +{ + "request": { + "method": "POST", + "url": "https://aws-eu-central-1.api.entire.io/api/v1/trails/et/forges-scratch/forges-fixtures/9/approvals", + "body": { + "event": "approve" + } + }, + "response": { + "status": 200, + "headers": { + "link": "; rel=\"describedBy\"" + }, + "body": { + "$schema": "https://aws-eu-central-1.api.entire.io/api/v1/schemas/TrailApprovalSubmitResponse.json", + "ok": true, + "approval": { + "id": "01M5X0APDPB2XFXGPA85JXFMA4", + "author": "danielroe", + "event": "approved", + "body": null, + "commit_sha": "9f5e93477cecca4f94f1888d8680ab55c75fccba", + "created_at": "2026-10-26T21:02:13.430135692Z" + }, + "gates": { + "head_sha": "9f5e93477cecca4f94f1888d8680ab55c75fccba", + "gates": [ + { + "reviewers": [ + { + "login": "danielroe", + "actor_account_id": "01M5WRP9RJ4GVR2PA5PCNYP1FC", + "state": "approved", + "reviewed_head_sha": "9f5e93477cecca4f94f1888d8680ab55c75fccba", + "reason": null + } + ], + "runner_ids": [], + "id": "01M5X0APE62CD4GDEZHPF8PRZD", + "gate_definition_id": "01M5WZ6B2HAMXBN2SZ9TP2N3SN", + "gate_key": "approvals", + "gate_type": "approvals", + "blocking": true, + "status": "passed", + "head_sha": "9f5e93477cecca4f94f1888d8680ab55c75fccba", + "value": { + "approved": 1, + "changes_requested": false, + "config": { + "version": 1, + "min_reviewers": 1, + "allow_self_approval": false, + "dismiss_stale_approvals_on_push": false + }, + "required": 1, + "self_excluded": false, + "stale_dismissed": 0, + "total": 1 + }, + "rationale": "1 approval(s) recorded", + "created_at": "2026-10-26T21:02:13.446381654Z", + "completed_at": "2026-10-26T21:02:13.446381654Z", + "outcome": null, + "stale_reason": null, + "evaluated_at_sha": null, + "finding_count": null + }, + { + "reviewers": [], + "runner_ids": [], + "id": "01M5X0ANSHBMKPX71GYC40D1GV", + "gate_definition_id": "01M5WZ6B2M8PSY34EM5YJGG6ZR", + "gate_key": "findings", + "gate_type": "findings", + "blocking": false, + "status": "failed", + "head_sha": "9f5e93477cecca4f94f1888d8680ab55c75fccba", + "value": { + "config": { + "version": 1, + "agent_findings_min_severity": "high" + }, + "reviewed_head": false, + "agent_findings": { + "low": 0, + "high": 0, + "medium": 0, + "unspecified": 1 + }, + "review_in_flight": false, + "reviewer_configured": false, + "review_grace_expired": false, + "agent_blocking_findings": 1 + }, + "rationale": "Unresolved findings: 1 without a severity", + "created_at": "2026-10-26T21:02:12.7852Z", + "completed_at": "2026-10-26T21:02:12.7852Z", + "outcome": null, + "stale_reason": null, + "evaluated_at_sha": null, + "finding_count": null + }, + { + "reviewers": [], + "runner_ids": [], + "id": "01M5X0A4D1WK6QWSP6JXWFERW1", + "gate_definition_id": "01M5WZ6B2PC2X2BE023RX01WEY", + "gate_key": "up_to_date", + "gate_type": "up_to_date", + "blocking": true, + "status": "passed", + "head_sha": "9f5e93477cecca4f94f1888d8680ab55c75fccba", + "value": { + "config": { + "version": 1, + "allow_behind_if_mergeable": false + }, + "behind_by": 0, + "compare_status": "ahead", + "comparison_status": "available" + }, + "rationale": "Up to date", + "created_at": "2026-10-26T21:01:54.977313Z", + "completed_at": "2026-10-26T21:01:54.977313Z", + "outcome": null, + "stale_reason": null, + "evaluated_at_sha": null, + "finding_count": null + } + ], + "blocking_failures": [], + "mergeable": true, + "evaluated_at": "2026-10-26T21:02:13.446381654Z", + "gates_enabled": true + } + } + } +} diff --git a/test/fixtures/entire/recorded/entire.com-writes/steps/approve/golden.json b/test/fixtures/entire/recorded/entire.com-writes/steps/approve/golden.json new file mode 100644 index 000000000..c02ad5121 --- /dev/null +++ b/test/fixtures/entire/recorded/entire.com-writes/steps/approve/golden.json @@ -0,0 +1,31 @@ +{ + "ref": { + "forge": "entire", + "instance": "entire.com", + "thread": { + "forge": "entire", + "instance": "entire.com", + "repo": { + "forge": "entire", + "instance": "entire.com", + "owner": "forges-scratch", + "name": "forges-fixtures" + }, + "kind": "pull_request", + "number": "9", + "externalId": "01M5X0A49M70NAMJX878FD2QD1" + }, + "id": "01M5X0APDPB2XFXGPA85JXFMA4" + }, + "author": { + "forge": "entire", + "instance": "entire.com", + "login": "danielroe", + "id": "danielroe", + "isBotHint": false + }, + "state": "approved", + "stateRaw": "approved", + "submittedAt": "", + "comments": false +} diff --git a/test/fixtures/entire/recorded/entire.com-writes/steps/approve/step.json b/test/fixtures/entire/recorded/entire.com-writes/steps/approve/step.json new file mode 100644 index 000000000..a8c6b4e35 --- /dev/null +++ b/test/fixtures/entire/recorded/entire.com-writes/steps/approve/step.json @@ -0,0 +1,7 @@ +{ + "name": "approve", + "recordedAt": "2026-10-26T21:02:12.955Z", + "needs": [ + "create pull" + ] +} diff --git a/test/fixtures/entire/recorded/entire.com-writes/steps/author/01-get-v1-me.json b/test/fixtures/entire/recorded/entire.com-writes/steps/author/01-get-v1-me.json new file mode 100644 index 000000000..73a7d84c1 --- /dev/null +++ b/test/fixtures/entire/recorded/entire.com-writes/steps/author/01-get-v1-me.json @@ -0,0 +1,41 @@ +{ + "request": { + "method": "GET", + "url": "https://us.console.entire.io/api/v1/me" + }, + "response": { + "status": 200, + "headers": { + "link": "; rel=\"describedBy\"" + }, + "body": { + "$schema": "https://us.console.entire.io/api/v1/schemas/GetMeOutputBody.json", + "global": { + "accountId": "01M5WYRRVZNA1TXNET6KE4Q3WX", + "handle": "danielroe-bot", + "homeJurisdiction": "uk", + "createdAt": "2026-10-26T20:34:57.534531Z", + "avatarUrl": "https://avatars.githubusercontent.com/u/57801166?v=4", + "handles": [ + { + "provider": "github", + "handle": "danielroe-bot", + "providerUserId": "57801166" + } + ] + }, + "regionalUnavailable": { + "error": "foreign_jurisdiction", + "jurisdiction": "uk", + "homeCoreUrl": "https://uk.auth.entire.io", + "message": "Your profile is hosted in the uk jurisdiction." + }, + "auth": { + "provider": "github", + "providerUserId": "57801166" + }, + "mode": "regional", + "jurisdiction": "us" + } + } +} diff --git a/test/fixtures/entire/recorded/entire.com-writes/steps/author/golden.json b/test/fixtures/entire/recorded/entire.com-writes/steps/author/golden.json new file mode 100644 index 000000000..2d1091fe0 --- /dev/null +++ b/test/fixtures/entire/recorded/entire.com-writes/steps/author/golden.json @@ -0,0 +1,9 @@ +{ + "forge": "entire", + "instance": "entire.com", + "login": "danielroe-bot", + "id": "01M5WYRRVZNA1TXNET6KE4Q3WX", + "avatarUrl": "https://avatars.githubusercontent.com/u/57801166?v=4", + "isBotHint": false, + "createdAt": "" +} diff --git a/test/fixtures/entire/recorded/entire.com-writes/steps/author/step.json b/test/fixtures/entire/recorded/entire.com-writes/steps/author/step.json new file mode 100644 index 000000000..3db091827 --- /dev/null +++ b/test/fixtures/entire/recorded/entire.com-writes/steps/author/step.json @@ -0,0 +1,4 @@ +{ + "name": "author", + "recordedAt": "2026-10-26T20:52:03.172Z" +} diff --git a/test/fixtures/entire/recorded/entire.com-writes/steps/comment-review/01-post-N-reviews.json b/test/fixtures/entire/recorded/entire.com-writes/steps/comment-review/01-post-N-reviews.json new file mode 100644 index 000000000..a5b9fd1f2 --- /dev/null +++ b/test/fixtures/entire/recorded/entire.com-writes/steps/comment-review/01-post-N-reviews.json @@ -0,0 +1,29 @@ +{ + "request": { + "method": "POST", + "url": "https://aws-eu-central-1.api.entire.io/api/v1/trails/et/forges-scratch/forges-fixtures/9/reviews", + "body": {} + }, + "response": { + "status": 201, + "headers": { + "link": "; rel=\"describedBy\"", + "location": "https://aws-eu-central-1.api.entire.io/api/v1/trails/et/forges-scratch/forges-fixtures/9/reviews/01M5X0AGW04E508JH4BY5VE4V7" + }, + "body": { + "$schema": "https://aws-eu-central-1.api.entire.io/api/v1/schemas/StartReviewResponseBody.json", + "review_id": "01M5X0AGW04E508JH4BY5VE4V7", + "trail_id": "01M5X0A49M70NAMJX878FD2QD1", + "repo_id": "01M5WYSQC41P69DTXEMZ0TE5YK", + "code_version_id": "01M5X0AGVPHGGQD3ZADR9BX2KV", + "base_sha": "80c3e7d4c9f5e16f4e11cf7737f571c513d14ac2", + "head_sha": "9f5e93477cecca4f94f1888d8680ab55c75fccba", + "event_stream_url": "/api/v1/trails/et/forges-scratch/forges-fixtures/9/events", + "diff_url": "/api/v1/repos/01M5WYSQC41P69DTXEMZ0TE5YK/trails/9/reviews/01M5X0AGW04E508JH4BY5VE4V7/diff", + "files_url": "/api/v1/repos/01M5WYSQC41P69DTXEMZ0TE5YK/trails/9/reviews/01M5X0AGW04E508JH4BY5VE4V7/files", + "limits": { + "max_comments_per_batch": 100 + } + } + } +} diff --git a/test/fixtures/entire/recorded/entire.com-writes/steps/comment-review/02-post-01M5X0AGW04E508JH4BY5VE4V7-comments.json b/test/fixtures/entire/recorded/entire.com-writes/steps/comment-review/02-post-01M5X0AGW04E508JH4BY5VE4V7-comments.json new file mode 100644 index 000000000..93f3d351d --- /dev/null +++ b/test/fixtures/entire/recorded/entire.com-writes/steps/comment-review/02-post-01M5X0AGW04E508JH4BY5VE4V7-comments.json @@ -0,0 +1,95 @@ +{ + "request": { + "method": "POST", + "url": "https://aws-eu-central-1.api.entire.io/api/v1/trails/et/forges-scratch/forges-fixtures/9/reviews/01M5X0AGW04E508JH4BY5VE4V7/comments", + "body": { + "summary": "A review comment from run 20261026210133.", + "comments": [ + { + "client_id": "1", + "body": "A review comment from run 20261026210133.", + "location": { + "granularity": "whole_change" + } + } + ] + } + }, + "response": { + "status": 200, + "headers": { + "link": "; rel=\"describedBy\"" + }, + "body": { + "$schema": "https://aws-eu-central-1.api.entire.io/api/v1/schemas/ReviewCommentsBatchResponseBody.json", + "results": [ + { + "client_id": "1", + "status": "created", + "comment": { + "discussion_id": "01M5X0AHS4JAQ93WBG0CC9JN8M", + "discussion_message_count": 0, + "id": "01M5X0AHS47CKYTKRY42WT1YYD", + "trail_id": "01M5X0A49M70NAMJX878FD2QD1", + "repo_id": "01M5WYSQC41P69DTXEMZ0TE5YK", + "review_id": "01M5X0AGW04E508JH4BY5VE4V7", + "code_version_id": "01M5X0AGVPHGGQD3ZADR9BX2KV", + "actor_id": "01M5WRP9RJ4GVR2PA5PCNYP1FC", + "actor_display_name": "danielroe", + "actor_identity": { + "kind": "account", + "account_id": "01M5WRP9RJ4GVR2PA5PCNYP1FC", + "display_name": "Daniel Roe", + "avatar_url": "https://avatars.githubusercontent.com/u/28706372?v=4", + "handles": [ + { + "provider": "github", + "handle": "danielroe", + "is_primary": true + } + ] + }, + "body": "A review comment from run 20261026210133.", + "severity": null, + "confidence": null, + "status": "open", + "status_reason": null, + "status_actor_id": null, + "status_actor_display_name": null, + "status_actor_identity": { + "kind": "unknown", + "account_id": null, + "display_name": null, + "avatar_url": null, + "handles": [] + }, + "status_changed_at": null, + "status_source": null, + "status_actor_kind": null, + "stale_outcome": "current", + "stale_checked_at": null, + "stale_checked_code_version_id": null, + "client_id": "1", + "client_id_hash": "876dd2d2f894bbd709b9c4adf233e9cbe880d2c74674e9987f97a2d6c6e31faa", + "created_at": "2026-10-26T21:02:08.674Z", + "updated_at": "2026-10-26T21:02:08.674Z", + "location": { + "id": "01M5X0AHS4172XDD0412MR744W", + "review_comment_id": "01M5X0AHS47CKYTKRY42WT1YYD", + "code_version_id": "01M5X0AGVPHGGQD3ZADR9BX2KV", + "granularity": "whole_change", + "file_path": null, + "start_line": null, + "start_column": null, + "end_line": null, + "end_column": null, + "selected_text": null, + "nearby_text": null, + "language": null + } + } + } + ] + } + } +} diff --git a/test/fixtures/entire/recorded/entire.com-writes/steps/comment-review/golden.json b/test/fixtures/entire/recorded/entire.com-writes/steps/comment-review/golden.json new file mode 100644 index 000000000..c911eef52 --- /dev/null +++ b/test/fixtures/entire/recorded/entire.com-writes/steps/comment-review/golden.json @@ -0,0 +1,70 @@ +{ + "ref": { + "forge": "entire", + "instance": "entire.com", + "thread": { + "forge": "entire", + "instance": "entire.com", + "repo": { + "forge": "entire", + "instance": "entire.com", + "owner": "forges-scratch", + "name": "forges-fixtures" + }, + "kind": "pull_request", + "number": "9", + "externalId": "01M5X0A49M70NAMJX878FD2QD1" + }, + "id": "01M5X0AGW04E508JH4BY5VE4V7" + }, + "author": { + "forge": "entire", + "instance": "entire.com", + "login": "danielroe", + "id": "01M5WRP9RJ4GVR2PA5PCNYP1FC", + "name": "Daniel Roe", + "avatarUrl": "https://avatars.githubusercontent.com/u/28706372?v=4", + "isBotHint": false + }, + "state": "commented", + "stateRaw": "review", + "body": "A review comment from run 20261026210133.", + "submittedAt": "", + "comments": [ + { + "ref": { + "forge": "entire", + "instance": "entire.com", + "thread": { + "forge": "entire", + "instance": "entire.com", + "repo": { + "forge": "entire", + "instance": "entire.com", + "owner": "forges-scratch", + "name": "forges-fixtures" + }, + "kind": "pull_request", + "number": "9", + "externalId": "01M5X0A49M70NAMJX878FD2QD1" + }, + "id": "01M5X0AHS47CKYTKRY42WT1YYD" + }, + "body": "A review comment from run 20261026210133.", + "author": { + "forge": "entire", + "instance": "entire.com", + "login": "danielroe", + "id": "01M5WRP9RJ4GVR2PA5PCNYP1FC", + "name": "Daniel Roe", + "avatarUrl": "https://avatars.githubusercontent.com/u/28706372?v=4", + "isBotHint": false + }, + "thread": { + "id": "01M5X0AHS4JAQ93WBG0CC9JN8M", + "resolved": false + }, + "createdAt": "" + } + ] +} diff --git a/test/fixtures/entire/recorded/entire.com-writes/steps/comment-review/step.json b/test/fixtures/entire/recorded/entire.com-writes/steps/comment-review/step.json new file mode 100644 index 000000000..95ab0b231 --- /dev/null +++ b/test/fixtures/entire/recorded/entire.com-writes/steps/comment-review/step.json @@ -0,0 +1,7 @@ +{ + "name": "comment review", + "recordedAt": "2026-10-26T21:02:06.524Z", + "needs": [ + "create pull" + ] +} diff --git a/test/fixtures/entire/recorded/entire.com-writes/steps/create-duplicate-issue/01-post-forges-scratch-trails.json b/test/fixtures/entire/recorded/entire.com-writes/steps/create-duplicate-issue/01-post-forges-scratch-trails.json new file mode 100644 index 000000000..80aa561d7 --- /dev/null +++ b/test/fixtures/entire/recorded/entire.com-writes/steps/create-duplicate-issue/01-post-forges-scratch-trails.json @@ -0,0 +1,69 @@ +{ + "request": { + "method": "POST", + "url": "https://aws-eu-central-1.api.entire.io/api/v1/et/forges-scratch/trails", + "body": { + "title": "forges fixture 20261026210133: duplicate", + "body": "Opened by run 20261026210133.", + "repoIds": [ + "01M5WYSQC41P69DTXEMZ0TE5YK" + ] + } + }, + "response": { + "status": 201, + "headers": { + "link": "; rel=\"describedBy\"", + "etag": "W/\"2026-10-26T21:01:52.188419Z\"", + "location": "https://aws-eu-central-1.api.entire.io/api/v1/et/forges-scratch/trails/01M5X0A1NVH0ZAA8B1J3CQ1CSV" + }, + "body": { + "$schema": "https://aws-eu-central-1.api.entire.io/api/v1/schemas/TrailResponse.json", + "capabilities": { + "canEdit": true, + "canManageScope": true + }, + "author": { + "accountId": "01M5WYRRVZNA1TXNET6KE4Q3WX", + "login": "danielroe-bot", + "displayName": "", + "avatarUrl": "https://avatars.githubusercontent.com/u/57801166?v=4", + "identity": { + "kind": "account", + "account_id": "01M5WYRRVZNA1TXNET6KE4Q3WX", + "display_name": null, + "avatar_url": "https://avatars.githubusercontent.com/u/57801166?v=4", + "handles": [ + { + "provider": "github", + "handle": "danielroe-bot", + "is_primary": true + } + ] + } + }, + "id": "01M5X0A1NVH0ZAA8B1J3CQ1CSV", + "projectId": "01M5WYSMPPYRBB13ZB20H7NK2Q", + "number": 14, + "url": "https://entire.com/et/forges-scratch/-/trails/14", + "title": "forges fixture 20261026210133: duplicate", + "body": "Opened by run 20261026210133.", + "status": "open", + "phase": "planning", + "metadata": {}, + "type": "task", + "priority": "none", + "assignees": [], + "assigneeAccountIds": [], + "repoIds": [ + "01M5WYSQC41P69DTXEMZ0TE5YK" + ], + "authorAccountId": "01M5WYRRVZNA1TXNET6KE4Q3WX", + "createdAt": "2026-10-26T21:01:52.188Z", + "metadataUpdatedAt": "2026-10-26T21:01:52.188Z", + "closedAt": null, + "lastVisitedAt": null, + "lastActivityAt": "2026-10-26T21:01:52.188Z" + } + } +} diff --git a/test/fixtures/entire/recorded/entire.com-writes/steps/create-duplicate-issue/golden.json b/test/fixtures/entire/recorded/entire.com-writes/steps/create-duplicate-issue/golden.json new file mode 100644 index 000000000..2a051ae46 --- /dev/null +++ b/test/fixtures/entire/recorded/entire.com-writes/steps/create-duplicate-issue/golden.json @@ -0,0 +1,41 @@ +{ + "ref": { + "forge": "entire", + "instance": "entire.com", + "repo": { + "forge": "entire", + "instance": "entire.com", + "owner": "forges-scratch", + "name": "", + "kind": "namespace" + }, + "kind": "issue", + "number": "14", + "externalId": "01M5X0A1NVH0ZAA8B1J3CQ1CSV" + }, + "kind": "issue", + "title": "forges fixture 20261026210133: duplicate", + "body": "Opened by run 20261026210133.", + "state": "open", + "stateRaw": "open", + "isDraft": false, + "author": { + "forge": "entire", + "instance": "entire.com", + "login": "danielroe-bot", + "id": "01M5WYRRVZNA1TXNET6KE4Q3WX", + "avatarUrl": "https://avatars.githubusercontent.com/u/57801166?v=4", + "isBotHint": false + }, + "assignees": [], + "reviewers": [], + "labels": [], + "url": "https://entire.com/et/forges-scratch/-/trails/14", + "createdAt": "", + "updatedAt": "", + "lastActivityAt": "", + "issueType": { + "id": "task", + "name": "task" + } +} diff --git a/test/fixtures/entire/recorded/entire.com-writes/steps/create-duplicate-issue/step.json b/test/fixtures/entire/recorded/entire.com-writes/steps/create-duplicate-issue/step.json new file mode 100644 index 000000000..3fd6b69ee --- /dev/null +++ b/test/fixtures/entire/recorded/entire.com-writes/steps/create-duplicate-issue/step.json @@ -0,0 +1,4 @@ +{ + "name": "create duplicate issue", + "recordedAt": "2026-10-26T21:01:50.930Z" +} diff --git a/test/fixtures/entire/recorded/entire.com-writes/steps/create-issue/01-post-forges-scratch-trails.json b/test/fixtures/entire/recorded/entire.com-writes/steps/create-issue/01-post-forges-scratch-trails.json new file mode 100644 index 000000000..1ea49c77e --- /dev/null +++ b/test/fixtures/entire/recorded/entire.com-writes/steps/create-issue/01-post-forges-scratch-trails.json @@ -0,0 +1,69 @@ +{ + "request": { + "method": "POST", + "url": "https://aws-eu-central-1.api.entire.io/api/v1/et/forges-scratch/trails", + "body": { + "title": "forges fixture 20261026210133: issue", + "body": "Opened by run 20261026210133.", + "repoIds": [ + "01M5WYSQC41P69DTXEMZ0TE5YK" + ] + } + }, + "response": { + "status": 201, + "headers": { + "link": "; rel=\"describedBy\"", + "etag": "W/\"2026-10-26T21:01:44.774532Z\"", + "location": "https://aws-eu-central-1.api.entire.io/api/v1/et/forges-scratch/trails/01M5X09TE6P0R8TR8WPCVX7H6Y" + }, + "body": { + "$schema": "https://aws-eu-central-1.api.entire.io/api/v1/schemas/TrailResponse.json", + "capabilities": { + "canEdit": true, + "canManageScope": true + }, + "author": { + "accountId": "01M5WYRRVZNA1TXNET6KE4Q3WX", + "login": "danielroe-bot", + "displayName": "", + "avatarUrl": "https://avatars.githubusercontent.com/u/57801166?v=4", + "identity": { + "kind": "account", + "account_id": "01M5WYRRVZNA1TXNET6KE4Q3WX", + "display_name": null, + "avatar_url": "https://avatars.githubusercontent.com/u/57801166?v=4", + "handles": [ + { + "provider": "github", + "handle": "danielroe-bot", + "is_primary": true + } + ] + } + }, + "id": "01M5X09TE6P0R8TR8WPCVX7H6Y", + "projectId": "01M5WYSMPPYRBB13ZB20H7NK2Q", + "number": 13, + "url": "https://entire.com/et/forges-scratch/-/trails/13", + "title": "forges fixture 20261026210133: issue", + "body": "Opened by run 20261026210133.", + "status": "open", + "phase": "planning", + "metadata": {}, + "type": "task", + "priority": "none", + "assignees": [], + "assigneeAccountIds": [], + "repoIds": [ + "01M5WYSQC41P69DTXEMZ0TE5YK" + ], + "authorAccountId": "01M5WYRRVZNA1TXNET6KE4Q3WX", + "createdAt": "2026-10-26T21:01:44.774Z", + "metadataUpdatedAt": "2026-10-26T21:01:44.774Z", + "closedAt": null, + "lastVisitedAt": null, + "lastActivityAt": "2026-10-26T21:01:44.774Z" + } + } +} diff --git a/test/fixtures/entire/recorded/entire.com-writes/steps/create-issue/golden.json b/test/fixtures/entire/recorded/entire.com-writes/steps/create-issue/golden.json new file mode 100644 index 000000000..56b163910 --- /dev/null +++ b/test/fixtures/entire/recorded/entire.com-writes/steps/create-issue/golden.json @@ -0,0 +1,41 @@ +{ + "ref": { + "forge": "entire", + "instance": "entire.com", + "repo": { + "forge": "entire", + "instance": "entire.com", + "owner": "forges-scratch", + "name": "", + "kind": "namespace" + }, + "kind": "issue", + "number": "13", + "externalId": "01M5X09TE6P0R8TR8WPCVX7H6Y" + }, + "kind": "issue", + "title": "forges fixture 20261026210133: issue", + "body": "Opened by run 20261026210133.", + "state": "open", + "stateRaw": "open", + "isDraft": false, + "author": { + "forge": "entire", + "instance": "entire.com", + "login": "danielroe-bot", + "id": "01M5WYRRVZNA1TXNET6KE4Q3WX", + "avatarUrl": "https://avatars.githubusercontent.com/u/57801166?v=4", + "isBotHint": false + }, + "assignees": [], + "reviewers": [], + "labels": [], + "url": "https://entire.com/et/forges-scratch/-/trails/13", + "createdAt": "", + "updatedAt": "", + "lastActivityAt": "", + "issueType": { + "id": "task", + "name": "task" + } +} diff --git a/test/fixtures/entire/recorded/entire.com-writes/steps/create-issue/step.json b/test/fixtures/entire/recorded/entire.com-writes/steps/create-issue/step.json new file mode 100644 index 000000000..6e54aa1db --- /dev/null +++ b/test/fixtures/entire/recorded/entire.com-writes/steps/create-issue/step.json @@ -0,0 +1,7 @@ +{ + "name": "create issue", + "recordedAt": "2026-10-26T21:01:43.764Z", + "needs": [ + "author" + ] +} diff --git a/test/fixtures/entire/recorded/entire.com-writes/steps/create-pull/01-get-trails-01M5X0A493RSBKDGYF0ZWVG8E9.json b/test/fixtures/entire/recorded/entire.com-writes/steps/create-pull/01-get-trails-01M5X0A493RSBKDGYF0ZWVG8E9.json new file mode 100644 index 000000000..1337b01ba --- /dev/null +++ b/test/fixtures/entire/recorded/entire.com-writes/steps/create-pull/01-get-trails-01M5X0A493RSBKDGYF0ZWVG8E9.json @@ -0,0 +1,127 @@ +{ + "request": { + "method": "GET", + "url": "https://aws-eu-central-1.api.entire.io/api/v1/et/forges-scratch/trails/01M5X0A493RSBKDGYF0ZWVG8E9" + }, + "response": { + "status": 200, + "headers": { + "link": "; rel=\"describedBy\"", + "etag": "W/\"2026-10-26T21:01:54.892145Z\"" + }, + "body": { + "$schema": "https://aws-eu-central-1.api.entire.io/api/v1/schemas/TrailResponse.json", + "capabilities": { + "canEdit": true, + "canManageScope": true + }, + "project": { + "primaryProcessingCell": "aws-eu-central-1", + "id": "01M5WYSMPPYRBB13ZB20H7NK2Q", + "name": "forges-scratch", + "provider": "entire", + "reference": { + "forge": "et", + "project": "forges-scratch" + }, + "jurisdiction": "eu", + "capabilities": { + "canManageTrails": true + } + }, + "author": { + "accountId": "01M5WYRRVZNA1TXNET6KE4Q3WX", + "login": "danielroe-bot", + "displayName": "", + "avatarUrl": "https://avatars.githubusercontent.com/u/57801166?v=4", + "identity": { + "kind": "account", + "account_id": "01M5WYRRVZNA1TXNET6KE4Q3WX", + "display_name": null, + "avatar_url": "https://avatars.githubusercontent.com/u/57801166?v=4", + "handles": [ + { + "provider": "github", + "handle": "danielroe-bot", + "is_primary": true + } + ] + } + }, + "id": "01M5X0A493RSBKDGYF0ZWVG8E9", + "projectId": "01M5WYSMPPYRBB13ZB20H7NK2Q", + "number": 15, + "url": "https://entire.com/et/forges-scratch/-/trails/15", + "title": "forges fixture 20261026210133: pull 1", + "body": "Opened by run 20261026210133.", + "bodyDocument": { + "id": "", + "document_key": "project-trail:01M5X0A493RSBKDGYF0ZWVG8E9:body", + "schema_version": 1, + "content_json": { + "type": "doc", + "content": [ + { + "type": "paragraph", + "content": [ + { + "type": "text", + "text": "Opened by run 20261026210133." + } + ] + } + ] + }, + "text_snapshot": "Opened by run 20261026210133.", + "updated_at": "2026-10-26T21:01:54.892Z", + "etag": "" + }, + "status": "open", + "phase": "building", + "metadata": {}, + "type": "task", + "priority": "none", + "assignees": [], + "assigneeAccountIds": [], + "repoIds": [ + "01M5WYSQC41P69DTXEMZ0TE5YK" + ], + "authorAccountId": "01M5WYRRVZNA1TXNET6KE4Q3WX", + "createdAt": "2026-10-26T21:01:54.849Z", + "metadataUpdatedAt": "2026-10-26T21:01:54.892Z", + "closedAt": null, + "lastVisitedAt": null, + "lastActivityAt": "2026-10-26T21:01:54.892Z", + "changes": [ + { + "id": "01M5X0A49M70NAMJX878FD2QD1", + "repositoryId": "01M5WYSQC41P69DTXEMZ0TE5YK", + "repository": "forges-fixtures", + "branch": "forges-fixtures/20261026210133-1", + "originalBranch": "forges-fixtures/20261026210133-1", + "base": "main", + "number": 9, + "title": "forges fixture 20261026210133: pull 1", + "status": "open", + "hasCodeChanges": true, + "createdAt": "2026-10-26T21:01:54.849Z", + "updatedAt": "2026-10-26T21:01:54.919Z", + "lastActivityAt": "2026-10-26T21:01:54.849Z", + "deployments": { + "availability": "available", + "ready": 0, + "total": 0 + }, + "readiness": "in_review", + "mergeability": { + "conflict_status": "unknown", + "head_sha": "", + "refreshed_at": null, + "forge_merge_block": null + } + } + ], + "isPossiblyPartial": true + } + } +} diff --git a/test/fixtures/entire/recorded/entire.com-writes/steps/create-pull/02-get-forges-fixtures-N.json b/test/fixtures/entire/recorded/entire.com-writes/steps/create-pull/02-get-forges-fixtures-N.json new file mode 100644 index 000000000..75dc5538d --- /dev/null +++ b/test/fixtures/entire/recorded/entire.com-writes/steps/create-pull/02-get-forges-fixtures-N.json @@ -0,0 +1,243 @@ +{ + "request": { + "method": "GET", + "url": "https://aws-eu-central-1.api.entire.io/api/v1/trails/et/forges-scratch/forges-fixtures/9" + }, + "response": { + "status": 200, + "headers": { + "link": "; rel=\"describedBy\"" + }, + "body": { + "$schema": "https://aws-eu-central-1.api.entire.io/api/v1/schemas/TrailDetailResponse.json", + "id": "01M5X0A49M70NAMJX878FD2QD1", + "number": 9, + "url": "https://entire.com/et/forges-scratch/forges-fixtures/trails/9", + "title": "forges fixture 20261026210133: pull 1", + "status": "open", + "branch": "forges-fixtures/20261026210133-1", + "original_branch": "forges-fixtures/20261026210133-1", + "base": "main", + "type": "task", + "priority": "none", + "author": { + "id": "01M5WYRRVZNA1TXNET6KE4Q3WX", + "login": "danielroe-bot", + "identity": { + "kind": "account", + "account_id": "01M5WYRRVZNA1TXNET6KE4Q3WX", + "display_name": null, + "avatar_url": "https://avatars.githubusercontent.com/u/57801166?v=4", + "handles": [ + { + "provider": "github", + "handle": "danielroe-bot", + "is_primary": true + } + ] + } + }, + "assignees": [ + "danielroe-bot" + ], + "assignee_identities": [ + { + "login": "danielroe-bot", + "identity": { + "kind": "account", + "account_id": "01M5WYRRVZNA1TXNET6KE4Q3WX", + "display_name": null, + "avatar_url": "https://avatars.githubusercontent.com/u/57801166?v=4", + "handles": [ + { + "provider": "github", + "handle": "danielroe-bot", + "is_primary": true + } + ] + } + } + ], + "reviewers": [], + "ready_for_review": true, + "has_code_changes": true, + "comment_count": 0, + "unresolved_count": 0, + "created_at": "2026-10-26T21:01:54.849Z", + "updated_at": "2026-10-26T21:01:54.919Z", + "merged_at": null, + "last_activity_at": "2026-10-26T21:01:54.849Z", + "phase": "reviewing", + "parent": { + "id": "01M5X0A493RSBKDGYF0ZWVG8E9", + "number": 15, + "project_id": "01M5WYSMPPYRBB13ZB20H7NK2Q", + "host": "et", + "project": "forges-scratch", + "path": "/api/v1/et/forges-scratch/trails/01M5X0A493RSBKDGYF0ZWVG8E9", + "jurisdiction": "eu", + "primary_processing_cell": "aws-eu-central-1", + "url": "https://entire.com/et/forges-scratch/-/trails/15" + }, + "branch_state": "present", + "code_changes": "present", + "lifecycle_sync": "settled", + "body_document": { + "id": "01M5X0A4AGRFN6FB08AYTPCF6X", + "document_key": "trail:01M5X0A49M70NAMJX878FD2QD1:body", + "schema_version": 1, + "content_json": { + "type": "doc", + "content": [ + { + "type": "paragraph" + } + ] + }, + "text_snapshot": "", + "updated_at": "2026-10-26T21:01:54.849Z", + "etag": "W/\"2026-10-26T21:01:54.849162Z\"" + }, + "monitors": [], + "agents": [], + "runners": [], + "actions": { + "approve": { + "state": "blocked", + "reason": "self_approval_not_allowed" + }, + "create_ci_pr": { + "state": "unavailable", + "reason": "not_applicable" + }, + "merge": { + "state": "blocked", + "reason": "merge_gates_required" + }, + "merge_with_bypass": { + "state": "unavailable", + "reason": "merge_gates_bypass_forbidden" + }, + "update_branch": { + "state": "unavailable", + "reason": "branch_up_to_date" + }, + "restore_branch": { + "state": "unavailable", + "reason": "trail_not_merged" + }, + "delete_branch": { + "state": "unavailable", + "reason": "trail_not_merged" + } + }, + "mergeability": { + "delete_branch_on_merge": false, + "bypass_policy": "nobody", + "mergeable": false, + "behind_by": 0, + "comparison_status": "available", + "conflict_status": "clean", + "head_sha": "9f5e93477cecca4f94f1888d8680ab55c75fccba", + "gates": [ + { + "reviewers": [], + "runner_ids": [], + "id": "", + "gate_definition_id": "01M5WZ6B2HAMXBN2SZ9TP2N3SN", + "gate_key": "approvals", + "gate_type": "approvals", + "blocking": true, + "status": "failed", + "head_sha": "9f5e93477cecca4f94f1888d8680ab55c75fccba", + "value": { + "approved": 0, + "changes_requested": false, + "config": { + "version": 1, + "min_reviewers": 1, + "allow_self_approval": false, + "dismiss_stale_approvals_on_push": false + }, + "required": 1, + "self_excluded": false, + "stale_dismissed": 0, + "total": 0 + }, + "rationale": "No reviewers have approved this trail", + "created_at": "2026-10-26T21:01:55.274874765Z", + "completed_at": "2026-10-26T21:01:55.274874765Z", + "state": "evaluated", + "outcome": "failed", + "stale_reason": null, + "evaluated_at_sha": "9f5e93477cecca4f94f1888d8680ab55c75fccba", + "finding_count": null + }, + { + "reviewers": [], + "runner_ids": [], + "id": "", + "gate_definition_id": "01M5WZ6B2M8PSY34EM5YJGG6ZR", + "gate_key": "findings", + "gate_type": "findings", + "blocking": false, + "status": "pending", + "head_sha": "9f5e93477cecca4f94f1888d8680ab55c75fccba", + "value": null, + "rationale": "Gate has not been evaluated yet", + "created_at": "2026-10-26T20:42:22.164428Z", + "completed_at": null, + "state": "not_run", + "outcome": null, + "stale_reason": null, + "evaluated_at_sha": null, + "finding_count": null + }, + { + "reviewers": [], + "runner_ids": [], + "id": "01M5X0A4D1WK6QWSP6JXWFERW1", + "gate_definition_id": "01M5WZ6B2PC2X2BE023RX01WEY", + "gate_key": "up_to_date", + "gate_type": "up_to_date", + "blocking": true, + "status": "passed", + "head_sha": "9f5e93477cecca4f94f1888d8680ab55c75fccba", + "value": { + "config": { + "version": 1, + "allow_behind_if_mergeable": false + }, + "behind_by": 0, + "compare_status": "ahead", + "comparison_status": "available" + }, + "rationale": "Up to date", + "created_at": "2026-10-26T21:01:54.977313Z", + "completed_at": "2026-10-26T21:01:54.977313Z", + "state": "evaluated", + "outcome": "passed", + "stale_reason": null, + "evaluated_at_sha": "9f5e93477cecca4f94f1888d8680ab55c75fccba", + "finding_count": null + } + ], + "checks": { + "availability": "not_applicable", + "runs": [] + }, + "forge_merge_block": null + }, + "deployments": { + "availability": "available", + "ready": 0, + "total": 0, + "items": [] + }, + "config_source": "live", + "merge_base_sha": null, + "base_sha": null, + "head_sha": "9f5e93477cecca4f94f1888d8680ab55c75fccba" + } + } +} diff --git a/test/fixtures/entire/recorded/entire.com-writes/steps/create-pull/03-post-forges-scratch-trails.json b/test/fixtures/entire/recorded/entire.com-writes/steps/create-pull/03-post-forges-scratch-trails.json new file mode 100644 index 000000000..0bcf4b32a --- /dev/null +++ b/test/fixtures/entire/recorded/entire.com-writes/steps/create-pull/03-post-forges-scratch-trails.json @@ -0,0 +1,98 @@ +{ + "request": { + "method": "POST", + "url": "https://aws-eu-central-1.api.entire.io/api/v1/et/forges-scratch/trails", + "body": { + "title": "forges fixture 20261026210133: pull 1", + "body": "Opened by run 20261026210133.", + "repoIds": [ + "01M5WYSQC41P69DTXEMZ0TE5YK" + ], + "changes": [ + { + "repositoryId": "01M5WYSQC41P69DTXEMZ0TE5YK", + "branchName": "forges-fixtures/20261026210133-1", + "base": "main", + "branchAction": "link", + "title": "forges fixture 20261026210133: pull 1", + "readyForReview": true + } + ] + } + }, + "response": { + "status": 201, + "headers": { + "link": "; rel=\"describedBy\"", + "etag": "W/\"2026-10-26T21:01:54.892145Z\"", + "location": "https://aws-eu-central-1.api.entire.io/api/v1/et/forges-scratch/trails/01M5X0A493RSBKDGYF0ZWVG8E9" + }, + "body": { + "$schema": "https://aws-eu-central-1.api.entire.io/api/v1/schemas/TrailResponse.json", + "capabilities": { + "canEdit": true, + "canManageScope": true + }, + "author": { + "accountId": "01M5WYRRVZNA1TXNET6KE4Q3WX", + "login": "danielroe-bot", + "displayName": "", + "avatarUrl": "https://avatars.githubusercontent.com/u/57801166?v=4", + "identity": { + "kind": "account", + "account_id": "01M5WYRRVZNA1TXNET6KE4Q3WX", + "display_name": null, + "avatar_url": "https://avatars.githubusercontent.com/u/57801166?v=4", + "handles": [ + { + "provider": "github", + "handle": "danielroe-bot", + "is_primary": true + } + ] + } + }, + "id": "01M5X0A493RSBKDGYF0ZWVG8E9", + "projectId": "01M5WYSMPPYRBB13ZB20H7NK2Q", + "number": 15, + "url": "https://entire.com/et/forges-scratch/-/trails/15", + "title": "forges fixture 20261026210133: pull 1", + "body": "Opened by run 20261026210133.", + "status": "open", + "phase": "building", + "metadata": {}, + "type": "task", + "priority": "none", + "assignees": [], + "assigneeAccountIds": [], + "repoIds": [ + "01M5WYSQC41P69DTXEMZ0TE5YK" + ], + "authorAccountId": "01M5WYRRVZNA1TXNET6KE4Q3WX", + "createdAt": "2026-10-26T21:01:54.849Z", + "metadataUpdatedAt": "2026-10-26T21:01:54.892Z", + "closedAt": null, + "lastVisitedAt": null, + "lastActivityAt": "2026-10-26T21:01:54.892Z", + "changes": [ + { + "id": "01M5X0A49M70NAMJX878FD2QD1", + "repositoryId": "01M5WYSQC41P69DTXEMZ0TE5YK", + "repository": "forges-fixtures", + "branch": "forges-fixtures/20261026210133-1", + "originalBranch": "forges-fixtures/20261026210133-1", + "base": "main", + "number": 9, + "title": "forges fixture 20261026210133: pull 1", + "status": "open", + "hasCodeChanges": false, + "createdAt": "2026-10-26T21:01:54.849Z", + "updatedAt": "2026-10-26T21:01:54.849Z", + "lastActivityAt": "2026-10-26T21:01:54.849Z", + "readiness": "unknown", + "mergeability": null + } + ] + } + } +} diff --git a/test/fixtures/entire/recorded/entire.com-writes/steps/create-pull/golden.json b/test/fixtures/entire/recorded/entire.com-writes/steps/create-pull/golden.json new file mode 100644 index 000000000..6dc90adc1 --- /dev/null +++ b/test/fixtures/entire/recorded/entire.com-writes/steps/create-pull/golden.json @@ -0,0 +1,61 @@ +{ + "ref": { + "forge": "entire", + "instance": "entire.com", + "repo": { + "forge": "entire", + "instance": "entire.com", + "owner": "forges-scratch", + "name": "forges-fixtures" + }, + "kind": "pull_request", + "number": "9", + "externalId": "01M5X0A49M70NAMJX878FD2QD1" + }, + "kind": "pull_request", + "title": "forges fixture 20261026210133: pull 1", + "body": "Opened by run 20261026210133.", + "state": "open", + "stateRaw": "open", + "isDraft": false, + "author": { + "forge": "entire", + "instance": "entire.com", + "login": "danielroe-bot", + "id": "01M5WYRRVZNA1TXNET6KE4Q3WX", + "avatarUrl": "https://avatars.githubusercontent.com/u/57801166?v=4", + "isBotHint": false + }, + "assignees": [ + { + "forge": "entire", + "instance": "entire.com", + "login": "danielroe-bot", + "id": "01M5WYRRVZNA1TXNET6KE4Q3WX", + "avatarUrl": "https://avatars.githubusercontent.com/u/57801166?v=4", + "isBotHint": false + } + ], + "reviewers": [], + "labels": [], + "url": "https://entire.com/et/forges-scratch/forges-fixtures/trails/9", + "createdAt": "", + "updatedAt": "", + "lastActivityAt": "", + "commentCount": 0, + "branches": { + "head": { + "ref": "forges-fixtures/20261026210133-1", + "sha": "9f5e93477cecca4f94f1888d8680ab55c75fccba", + "repo": { + "forge": "entire", + "instance": "entire.com", + "owner": "forges-scratch", + "name": "forges-fixtures" + } + }, + "base": { + "ref": "main" + } + } +} diff --git a/test/fixtures/entire/recorded/entire.com-writes/steps/create-pull/step.json b/test/fixtures/entire/recorded/entire.com-writes/steps/create-pull/step.json new file mode 100644 index 000000000..3043cc78c --- /dev/null +++ b/test/fixtures/entire/recorded/entire.com-writes/steps/create-pull/step.json @@ -0,0 +1,4 @@ +{ + "name": "create pull", + "recordedAt": "2026-10-26T21:01:53.927Z" +} diff --git a/test/fixtures/entire/recorded/entire.com-writes/steps/create-second-pull/01-get-trails-01M5X0A57TTTYB6JDQBMBHG4V8.json b/test/fixtures/entire/recorded/entire.com-writes/steps/create-second-pull/01-get-trails-01M5X0A57TTTYB6JDQBMBHG4V8.json new file mode 100644 index 000000000..d13994e43 --- /dev/null +++ b/test/fixtures/entire/recorded/entire.com-writes/steps/create-second-pull/01-get-trails-01M5X0A57TTTYB6JDQBMBHG4V8.json @@ -0,0 +1,127 @@ +{ + "request": { + "method": "GET", + "url": "https://aws-eu-central-1.api.entire.io/api/v1/et/forges-scratch/trails/01M5X0A57TTTYB6JDQBMBHG4V8" + }, + "response": { + "status": 200, + "headers": { + "link": "; rel=\"describedBy\"", + "etag": "W/\"2026-10-26T21:01:55.894211Z\"" + }, + "body": { + "$schema": "https://aws-eu-central-1.api.entire.io/api/v1/schemas/TrailResponse.json", + "capabilities": { + "canEdit": true, + "canManageScope": true + }, + "project": { + "primaryProcessingCell": "aws-eu-central-1", + "id": "01M5WYSMPPYRBB13ZB20H7NK2Q", + "name": "forges-scratch", + "provider": "entire", + "reference": { + "forge": "et", + "project": "forges-scratch" + }, + "jurisdiction": "eu", + "capabilities": { + "canManageTrails": true + } + }, + "author": { + "accountId": "01M5WYRRVZNA1TXNET6KE4Q3WX", + "login": "danielroe-bot", + "displayName": "", + "avatarUrl": "https://avatars.githubusercontent.com/u/57801166?v=4", + "identity": { + "kind": "account", + "account_id": "01M5WYRRVZNA1TXNET6KE4Q3WX", + "display_name": null, + "avatar_url": "https://avatars.githubusercontent.com/u/57801166?v=4", + "handles": [ + { + "provider": "github", + "handle": "danielroe-bot", + "is_primary": true + } + ] + } + }, + "id": "01M5X0A57TTTYB6JDQBMBHG4V8", + "projectId": "01M5WYSMPPYRBB13ZB20H7NK2Q", + "number": 16, + "url": "https://entire.com/et/forges-scratch/-/trails/16", + "title": "forges fixture 20261026210133: pull 2", + "body": "Opened by run 20261026210133.", + "bodyDocument": { + "id": "", + "document_key": "project-trail:01M5X0A57TTTYB6JDQBMBHG4V8:body", + "schema_version": 1, + "content_json": { + "type": "doc", + "content": [ + { + "type": "paragraph", + "content": [ + { + "type": "text", + "text": "Opened by run 20261026210133." + } + ] + } + ] + }, + "text_snapshot": "Opened by run 20261026210133.", + "updated_at": "2026-10-26T21:01:55.894Z", + "etag": "" + }, + "status": "open", + "phase": "building", + "metadata": {}, + "type": "task", + "priority": "none", + "assignees": [], + "assigneeAccountIds": [], + "repoIds": [ + "01M5WYSQC41P69DTXEMZ0TE5YK" + ], + "authorAccountId": "01M5WYRRVZNA1TXNET6KE4Q3WX", + "createdAt": "2026-10-26T21:01:55.830Z", + "metadataUpdatedAt": "2026-10-26T21:01:55.894Z", + "closedAt": null, + "lastVisitedAt": null, + "lastActivityAt": "2026-10-26T21:01:55.894Z", + "changes": [ + { + "id": "01M5X0A58D0Z486R9F4Y7JKPDN", + "repositoryId": "01M5WYSQC41P69DTXEMZ0TE5YK", + "repository": "forges-fixtures", + "branch": "forges-fixtures/20261026210133-2", + "originalBranch": "forges-fixtures/20261026210133-2", + "base": "main", + "number": 10, + "title": "forges fixture 20261026210133: pull 2", + "status": "open", + "hasCodeChanges": true, + "createdAt": "2026-10-26T21:01:55.830Z", + "updatedAt": "2026-10-26T21:01:55.933Z", + "lastActivityAt": "2026-10-26T21:01:55.830Z", + "deployments": { + "availability": "available", + "ready": 0, + "total": 0 + }, + "readiness": "in_review", + "mergeability": { + "conflict_status": "unknown", + "head_sha": "", + "refreshed_at": null, + "forge_merge_block": null + } + } + ], + "isPossiblyPartial": true + } + } +} diff --git a/test/fixtures/entire/recorded/entire.com-writes/steps/create-second-pull/02-get-forges-fixtures-N.json b/test/fixtures/entire/recorded/entire.com-writes/steps/create-second-pull/02-get-forges-fixtures-N.json new file mode 100644 index 000000000..23a2514e7 --- /dev/null +++ b/test/fixtures/entire/recorded/entire.com-writes/steps/create-second-pull/02-get-forges-fixtures-N.json @@ -0,0 +1,243 @@ +{ + "request": { + "method": "GET", + "url": "https://aws-eu-central-1.api.entire.io/api/v1/trails/et/forges-scratch/forges-fixtures/10" + }, + "response": { + "status": 200, + "headers": { + "link": "; rel=\"describedBy\"" + }, + "body": { + "$schema": "https://aws-eu-central-1.api.entire.io/api/v1/schemas/TrailDetailResponse.json", + "id": "01M5X0A58D0Z486R9F4Y7JKPDN", + "number": 10, + "url": "https://entire.com/et/forges-scratch/forges-fixtures/trails/10", + "title": "forges fixture 20261026210133: pull 2", + "status": "open", + "branch": "forges-fixtures/20261026210133-2", + "original_branch": "forges-fixtures/20261026210133-2", + "base": "main", + "type": "task", + "priority": "none", + "author": { + "id": "01M5WYRRVZNA1TXNET6KE4Q3WX", + "login": "danielroe-bot", + "identity": { + "kind": "account", + "account_id": "01M5WYRRVZNA1TXNET6KE4Q3WX", + "display_name": null, + "avatar_url": "https://avatars.githubusercontent.com/u/57801166?v=4", + "handles": [ + { + "provider": "github", + "handle": "danielroe-bot", + "is_primary": true + } + ] + } + }, + "assignees": [ + "danielroe-bot" + ], + "assignee_identities": [ + { + "login": "danielroe-bot", + "identity": { + "kind": "account", + "account_id": "01M5WYRRVZNA1TXNET6KE4Q3WX", + "display_name": null, + "avatar_url": "https://avatars.githubusercontent.com/u/57801166?v=4", + "handles": [ + { + "provider": "github", + "handle": "danielroe-bot", + "is_primary": true + } + ] + } + } + ], + "reviewers": [], + "ready_for_review": true, + "has_code_changes": true, + "comment_count": 0, + "unresolved_count": 0, + "created_at": "2026-10-26T21:01:55.830Z", + "updated_at": "2026-10-26T21:01:55.933Z", + "merged_at": null, + "last_activity_at": "2026-10-26T21:01:55.830Z", + "phase": "reviewing", + "parent": { + "id": "01M5X0A57TTTYB6JDQBMBHG4V8", + "number": 16, + "project_id": "01M5WYSMPPYRBB13ZB20H7NK2Q", + "host": "et", + "project": "forges-scratch", + "path": "/api/v1/et/forges-scratch/trails/01M5X0A57TTTYB6JDQBMBHG4V8", + "jurisdiction": "eu", + "primary_processing_cell": "aws-eu-central-1", + "url": "https://entire.com/et/forges-scratch/-/trails/16" + }, + "branch_state": "present", + "code_changes": "present", + "lifecycle_sync": "settled", + "body_document": { + "id": "01M5X0A59VYSSJTW7ETN7R8D7J", + "document_key": "trail:01M5X0A58D0Z486R9F4Y7JKPDN:body", + "schema_version": 1, + "content_json": { + "type": "doc", + "content": [ + { + "type": "paragraph" + } + ] + }, + "text_snapshot": "", + "updated_at": "2026-10-26T21:01:55.830Z", + "etag": "W/\"2026-10-26T21:01:55.830929Z\"" + }, + "monitors": [], + "agents": [], + "runners": [], + "actions": { + "approve": { + "state": "blocked", + "reason": "self_approval_not_allowed" + }, + "create_ci_pr": { + "state": "unavailable", + "reason": "not_applicable" + }, + "merge": { + "state": "blocked", + "reason": "merge_gates_required" + }, + "merge_with_bypass": { + "state": "unavailable", + "reason": "merge_gates_bypass_forbidden" + }, + "update_branch": { + "state": "unavailable", + "reason": "branch_up_to_date" + }, + "restore_branch": { + "state": "unavailable", + "reason": "trail_not_merged" + }, + "delete_branch": { + "state": "unavailable", + "reason": "trail_not_merged" + } + }, + "mergeability": { + "delete_branch_on_merge": false, + "bypass_policy": "nobody", + "mergeable": false, + "behind_by": 0, + "comparison_status": "available", + "conflict_status": "clean", + "head_sha": "1728ca410ea20a6de3169562d0cf61d5432ae57d", + "gates": [ + { + "reviewers": [], + "runner_ids": [], + "id": "", + "gate_definition_id": "01M5WZ6B2HAMXBN2SZ9TP2N3SN", + "gate_key": "approvals", + "gate_type": "approvals", + "blocking": true, + "status": "failed", + "head_sha": "1728ca410ea20a6de3169562d0cf61d5432ae57d", + "value": { + "approved": 0, + "changes_requested": false, + "config": { + "version": 1, + "min_reviewers": 1, + "allow_self_approval": false, + "dismiss_stale_approvals_on_push": false + }, + "required": 1, + "self_excluded": false, + "stale_dismissed": 0, + "total": 0 + }, + "rationale": "No reviewers have approved this trail", + "created_at": "2026-10-26T21:01:56.235232Z", + "completed_at": "2026-10-26T21:01:56.235232Z", + "state": "evaluated", + "outcome": "failed", + "stale_reason": null, + "evaluated_at_sha": "1728ca410ea20a6de3169562d0cf61d5432ae57d", + "finding_count": null + }, + { + "reviewers": [], + "runner_ids": [], + "id": "", + "gate_definition_id": "01M5WZ6B2M8PSY34EM5YJGG6ZR", + "gate_key": "findings", + "gate_type": "findings", + "blocking": false, + "status": "pending", + "head_sha": "1728ca410ea20a6de3169562d0cf61d5432ae57d", + "value": null, + "rationale": "Gate has not been evaluated yet", + "created_at": "2026-10-26T20:42:22.164428Z", + "completed_at": null, + "state": "not_run", + "outcome": null, + "stale_reason": null, + "evaluated_at_sha": null, + "finding_count": null + }, + { + "reviewers": [], + "runner_ids": [], + "id": "01M5X0A5CJM66W2V438Q6C488K", + "gate_definition_id": "01M5WZ6B2PC2X2BE023RX01WEY", + "gate_key": "up_to_date", + "gate_type": "up_to_date", + "blocking": true, + "status": "passed", + "head_sha": "1728ca410ea20a6de3169562d0cf61d5432ae57d", + "value": { + "config": { + "version": 1, + "allow_behind_if_mergeable": false + }, + "behind_by": 0, + "compare_status": "ahead", + "comparison_status": "available" + }, + "rationale": "Up to date", + "created_at": "2026-10-26T21:01:55.986801Z", + "completed_at": "2026-10-26T21:01:55.986801Z", + "state": "evaluated", + "outcome": "passed", + "stale_reason": null, + "evaluated_at_sha": "1728ca410ea20a6de3169562d0cf61d5432ae57d", + "finding_count": null + } + ], + "checks": { + "availability": "not_applicable", + "runs": [] + }, + "forge_merge_block": null + }, + "deployments": { + "availability": "available", + "ready": 0, + "total": 0, + "items": [] + }, + "config_source": "live", + "merge_base_sha": null, + "base_sha": null, + "head_sha": "1728ca410ea20a6de3169562d0cf61d5432ae57d" + } + } +} diff --git a/test/fixtures/entire/recorded/entire.com-writes/steps/create-second-pull/03-post-forges-scratch-trails.json b/test/fixtures/entire/recorded/entire.com-writes/steps/create-second-pull/03-post-forges-scratch-trails.json new file mode 100644 index 000000000..3459b276d --- /dev/null +++ b/test/fixtures/entire/recorded/entire.com-writes/steps/create-second-pull/03-post-forges-scratch-trails.json @@ -0,0 +1,98 @@ +{ + "request": { + "method": "POST", + "url": "https://aws-eu-central-1.api.entire.io/api/v1/et/forges-scratch/trails", + "body": { + "title": "forges fixture 20261026210133: pull 2", + "body": "Opened by run 20261026210133.", + "repoIds": [ + "01M5WYSQC41P69DTXEMZ0TE5YK" + ], + "changes": [ + { + "repositoryId": "01M5WYSQC41P69DTXEMZ0TE5YK", + "branchName": "forges-fixtures/20261026210133-2", + "base": "main", + "branchAction": "link", + "title": "forges fixture 20261026210133: pull 2", + "readyForReview": true + } + ] + } + }, + "response": { + "status": 201, + "headers": { + "link": "; rel=\"describedBy\"", + "etag": "W/\"2026-10-26T21:01:55.894211Z\"", + "location": "https://aws-eu-central-1.api.entire.io/api/v1/et/forges-scratch/trails/01M5X0A57TTTYB6JDQBMBHG4V8" + }, + "body": { + "$schema": "https://aws-eu-central-1.api.entire.io/api/v1/schemas/TrailResponse.json", + "capabilities": { + "canEdit": true, + "canManageScope": true + }, + "author": { + "accountId": "01M5WYRRVZNA1TXNET6KE4Q3WX", + "login": "danielroe-bot", + "displayName": "", + "avatarUrl": "https://avatars.githubusercontent.com/u/57801166?v=4", + "identity": { + "kind": "account", + "account_id": "01M5WYRRVZNA1TXNET6KE4Q3WX", + "display_name": null, + "avatar_url": "https://avatars.githubusercontent.com/u/57801166?v=4", + "handles": [ + { + "provider": "github", + "handle": "danielroe-bot", + "is_primary": true + } + ] + } + }, + "id": "01M5X0A57TTTYB6JDQBMBHG4V8", + "projectId": "01M5WYSMPPYRBB13ZB20H7NK2Q", + "number": 16, + "url": "https://entire.com/et/forges-scratch/-/trails/16", + "title": "forges fixture 20261026210133: pull 2", + "body": "Opened by run 20261026210133.", + "status": "open", + "phase": "building", + "metadata": {}, + "type": "task", + "priority": "none", + "assignees": [], + "assigneeAccountIds": [], + "repoIds": [ + "01M5WYSQC41P69DTXEMZ0TE5YK" + ], + "authorAccountId": "01M5WYRRVZNA1TXNET6KE4Q3WX", + "createdAt": "2026-10-26T21:01:55.830Z", + "metadataUpdatedAt": "2026-10-26T21:01:55.894Z", + "closedAt": null, + "lastVisitedAt": null, + "lastActivityAt": "2026-10-26T21:01:55.894Z", + "changes": [ + { + "id": "01M5X0A58D0Z486R9F4Y7JKPDN", + "repositoryId": "01M5WYSQC41P69DTXEMZ0TE5YK", + "repository": "forges-fixtures", + "branch": "forges-fixtures/20261026210133-2", + "originalBranch": "forges-fixtures/20261026210133-2", + "base": "main", + "number": 10, + "title": "forges fixture 20261026210133: pull 2", + "status": "open", + "hasCodeChanges": false, + "createdAt": "2026-10-26T21:01:55.830Z", + "updatedAt": "2026-10-26T21:01:55.830Z", + "lastActivityAt": "2026-10-26T21:01:55.830Z", + "readiness": "unknown", + "mergeability": null + } + ] + } + } +} diff --git a/test/fixtures/entire/recorded/entire.com-writes/steps/create-second-pull/golden.json b/test/fixtures/entire/recorded/entire.com-writes/steps/create-second-pull/golden.json new file mode 100644 index 000000000..45ec9b65b --- /dev/null +++ b/test/fixtures/entire/recorded/entire.com-writes/steps/create-second-pull/golden.json @@ -0,0 +1,61 @@ +{ + "ref": { + "forge": "entire", + "instance": "entire.com", + "repo": { + "forge": "entire", + "instance": "entire.com", + "owner": "forges-scratch", + "name": "forges-fixtures" + }, + "kind": "pull_request", + "number": "10", + "externalId": "01M5X0A58D0Z486R9F4Y7JKPDN" + }, + "kind": "pull_request", + "title": "forges fixture 20261026210133: pull 2", + "body": "Opened by run 20261026210133.", + "state": "open", + "stateRaw": "open", + "isDraft": false, + "author": { + "forge": "entire", + "instance": "entire.com", + "login": "danielroe-bot", + "id": "01M5WYRRVZNA1TXNET6KE4Q3WX", + "avatarUrl": "https://avatars.githubusercontent.com/u/57801166?v=4", + "isBotHint": false + }, + "assignees": [ + { + "forge": "entire", + "instance": "entire.com", + "login": "danielroe-bot", + "id": "01M5WYRRVZNA1TXNET6KE4Q3WX", + "avatarUrl": "https://avatars.githubusercontent.com/u/57801166?v=4", + "isBotHint": false + } + ], + "reviewers": [], + "labels": [], + "url": "https://entire.com/et/forges-scratch/forges-fixtures/trails/10", + "createdAt": "", + "updatedAt": "", + "lastActivityAt": "", + "commentCount": 0, + "branches": { + "head": { + "ref": "forges-fixtures/20261026210133-2", + "sha": "1728ca410ea20a6de3169562d0cf61d5432ae57d", + "repo": { + "forge": "entire", + "instance": "entire.com", + "owner": "forges-scratch", + "name": "forges-fixtures" + } + }, + "base": { + "ref": "main" + } + } +} diff --git a/test/fixtures/entire/recorded/entire.com-writes/steps/create-second-pull/step.json b/test/fixtures/entire/recorded/entire.com-writes/steps/create-second-pull/step.json new file mode 100644 index 000000000..ce66feab6 --- /dev/null +++ b/test/fixtures/entire/recorded/entire.com-writes/steps/create-second-pull/step.json @@ -0,0 +1,4 @@ +{ + "name": "create second pull", + "recordedAt": "2026-10-26T21:01:55.599Z" +} diff --git a/test/fixtures/entire/recorded/entire.com-writes/steps/create-third-pull/01-get-trails-01M5X0A6D5Q8H8VHFN7M7HTKRS.json b/test/fixtures/entire/recorded/entire.com-writes/steps/create-third-pull/01-get-trails-01M5X0A6D5Q8H8VHFN7M7HTKRS.json new file mode 100644 index 000000000..08491c898 --- /dev/null +++ b/test/fixtures/entire/recorded/entire.com-writes/steps/create-third-pull/01-get-trails-01M5X0A6D5Q8H8VHFN7M7HTKRS.json @@ -0,0 +1,127 @@ +{ + "request": { + "method": "GET", + "url": "https://aws-eu-central-1.api.entire.io/api/v1/et/forges-scratch/trails/01M5X0A6D5Q8H8VHFN7M7HTKRS" + }, + "response": { + "status": 200, + "headers": { + "link": "; rel=\"describedBy\"", + "etag": "W/\"2026-10-26T21:01:57.046039Z\"" + }, + "body": { + "$schema": "https://aws-eu-central-1.api.entire.io/api/v1/schemas/TrailResponse.json", + "capabilities": { + "canEdit": true, + "canManageScope": true + }, + "project": { + "primaryProcessingCell": "aws-eu-central-1", + "id": "01M5WYSMPPYRBB13ZB20H7NK2Q", + "name": "forges-scratch", + "provider": "entire", + "reference": { + "forge": "et", + "project": "forges-scratch" + }, + "jurisdiction": "eu", + "capabilities": { + "canManageTrails": true + } + }, + "author": { + "accountId": "01M5WYRRVZNA1TXNET6KE4Q3WX", + "login": "danielroe-bot", + "displayName": "", + "avatarUrl": "https://avatars.githubusercontent.com/u/57801166?v=4", + "identity": { + "kind": "account", + "account_id": "01M5WYRRVZNA1TXNET6KE4Q3WX", + "display_name": null, + "avatar_url": "https://avatars.githubusercontent.com/u/57801166?v=4", + "handles": [ + { + "provider": "github", + "handle": "danielroe-bot", + "is_primary": true + } + ] + } + }, + "id": "01M5X0A6D5Q8H8VHFN7M7HTKRS", + "projectId": "01M5WYSMPPYRBB13ZB20H7NK2Q", + "number": 17, + "url": "https://entire.com/et/forges-scratch/-/trails/17", + "title": "forges fixture 20261026210133: pull 3", + "body": "Opened by run 20261026210133.", + "bodyDocument": { + "id": "", + "document_key": "project-trail:01M5X0A6D5Q8H8VHFN7M7HTKRS:body", + "schema_version": 1, + "content_json": { + "type": "doc", + "content": [ + { + "type": "paragraph", + "content": [ + { + "type": "text", + "text": "Opened by run 20261026210133." + } + ] + } + ] + }, + "text_snapshot": "Opened by run 20261026210133.", + "updated_at": "2026-10-26T21:01:57.046Z", + "etag": "" + }, + "status": "open", + "phase": "building", + "metadata": {}, + "type": "task", + "priority": "none", + "assignees": [], + "assigneeAccountIds": [], + "repoIds": [ + "01M5WYSQC41P69DTXEMZ0TE5YK" + ], + "authorAccountId": "01M5WYRRVZNA1TXNET6KE4Q3WX", + "createdAt": "2026-10-26T21:01:57.028Z", + "metadataUpdatedAt": "2026-10-26T21:01:57.046Z", + "closedAt": null, + "lastVisitedAt": null, + "lastActivityAt": "2026-10-26T21:01:57.046Z", + "changes": [ + { + "id": "01M5X0A6DAPK6DZNKVR2KEJNF8", + "repositoryId": "01M5WYSQC41P69DTXEMZ0TE5YK", + "repository": "forges-fixtures", + "branch": "forges-fixtures/20261026210133-3", + "originalBranch": "forges-fixtures/20261026210133-3", + "base": "main", + "number": 11, + "title": "forges fixture 20261026210133: pull 3", + "status": "open", + "hasCodeChanges": true, + "createdAt": "2026-10-26T21:01:57.028Z", + "updatedAt": "2026-10-26T21:01:57.061Z", + "lastActivityAt": "2026-10-26T21:01:57.028Z", + "deployments": { + "availability": "available", + "ready": 0, + "total": 0 + }, + "readiness": "in_review", + "mergeability": { + "conflict_status": "unknown", + "head_sha": "", + "refreshed_at": null, + "forge_merge_block": null + } + } + ], + "isPossiblyPartial": true + } + } +} diff --git a/test/fixtures/entire/recorded/entire.com-writes/steps/create-third-pull/02-get-forges-fixtures-N.json b/test/fixtures/entire/recorded/entire.com-writes/steps/create-third-pull/02-get-forges-fixtures-N.json new file mode 100644 index 000000000..a2a3732d4 --- /dev/null +++ b/test/fixtures/entire/recorded/entire.com-writes/steps/create-third-pull/02-get-forges-fixtures-N.json @@ -0,0 +1,243 @@ +{ + "request": { + "method": "GET", + "url": "https://aws-eu-central-1.api.entire.io/api/v1/trails/et/forges-scratch/forges-fixtures/11" + }, + "response": { + "status": 200, + "headers": { + "link": "; rel=\"describedBy\"" + }, + "body": { + "$schema": "https://aws-eu-central-1.api.entire.io/api/v1/schemas/TrailDetailResponse.json", + "id": "01M5X0A6DAPK6DZNKVR2KEJNF8", + "number": 11, + "url": "https://entire.com/et/forges-scratch/forges-fixtures/trails/11", + "title": "forges fixture 20261026210133: pull 3", + "status": "open", + "branch": "forges-fixtures/20261026210133-3", + "original_branch": "forges-fixtures/20261026210133-3", + "base": "main", + "type": "task", + "priority": "none", + "author": { + "id": "01M5WYRRVZNA1TXNET6KE4Q3WX", + "login": "danielroe-bot", + "identity": { + "kind": "account", + "account_id": "01M5WYRRVZNA1TXNET6KE4Q3WX", + "display_name": null, + "avatar_url": "https://avatars.githubusercontent.com/u/57801166?v=4", + "handles": [ + { + "provider": "github", + "handle": "danielroe-bot", + "is_primary": true + } + ] + } + }, + "assignees": [ + "danielroe-bot" + ], + "assignee_identities": [ + { + "login": "danielroe-bot", + "identity": { + "kind": "account", + "account_id": "01M5WYRRVZNA1TXNET6KE4Q3WX", + "display_name": null, + "avatar_url": "https://avatars.githubusercontent.com/u/57801166?v=4", + "handles": [ + { + "provider": "github", + "handle": "danielroe-bot", + "is_primary": true + } + ] + } + } + ], + "reviewers": [], + "ready_for_review": true, + "has_code_changes": true, + "comment_count": 0, + "unresolved_count": 0, + "created_at": "2026-10-26T21:01:57.028Z", + "updated_at": "2026-10-26T21:01:57.061Z", + "merged_at": null, + "last_activity_at": "2026-10-26T21:01:57.028Z", + "phase": "reviewing", + "parent": { + "id": "01M5X0A6D5Q8H8VHFN7M7HTKRS", + "number": 17, + "project_id": "01M5WYSMPPYRBB13ZB20H7NK2Q", + "host": "et", + "project": "forges-scratch", + "path": "/api/v1/et/forges-scratch/trails/01M5X0A6D5Q8H8VHFN7M7HTKRS", + "jurisdiction": "eu", + "primary_processing_cell": "aws-eu-central-1", + "url": "https://entire.com/et/forges-scratch/-/trails/17" + }, + "branch_state": "present", + "code_changes": "present", + "lifecycle_sync": "settled", + "body_document": { + "id": "01M5X0A6DQ168SD36K14JNJPYW", + "document_key": "trail:01M5X0A6DAPK6DZNKVR2KEJNF8:body", + "schema_version": 1, + "content_json": { + "type": "doc", + "content": [ + { + "type": "paragraph" + } + ] + }, + "text_snapshot": "", + "updated_at": "2026-10-26T21:01:57.028Z", + "etag": "W/\"2026-10-26T21:01:57.02813Z\"" + }, + "monitors": [], + "agents": [], + "runners": [], + "actions": { + "approve": { + "state": "blocked", + "reason": "self_approval_not_allowed" + }, + "create_ci_pr": { + "state": "unavailable", + "reason": "not_applicable" + }, + "merge": { + "state": "blocked", + "reason": "merge_gates_required" + }, + "merge_with_bypass": { + "state": "unavailable", + "reason": "merge_gates_bypass_forbidden" + }, + "update_branch": { + "state": "unavailable", + "reason": "branch_up_to_date" + }, + "restore_branch": { + "state": "unavailable", + "reason": "trail_not_merged" + }, + "delete_branch": { + "state": "unavailable", + "reason": "trail_not_merged" + } + }, + "mergeability": { + "delete_branch_on_merge": false, + "bypass_policy": "nobody", + "mergeable": false, + "behind_by": 0, + "comparison_status": "available", + "conflict_status": "clean", + "head_sha": "f483a62c7214e4cead9ef1df09a663324a4825ae", + "gates": [ + { + "reviewers": [], + "runner_ids": [], + "id": "", + "gate_definition_id": "01M5WZ6B2HAMXBN2SZ9TP2N3SN", + "gate_key": "approvals", + "gate_type": "approvals", + "blocking": true, + "status": "failed", + "head_sha": "f483a62c7214e4cead9ef1df09a663324a4825ae", + "value": { + "approved": 0, + "changes_requested": false, + "config": { + "version": 1, + "min_reviewers": 1, + "allow_self_approval": false, + "dismiss_stale_approvals_on_push": false + }, + "required": 1, + "self_excluded": false, + "stale_dismissed": 0, + "total": 0 + }, + "rationale": "No reviewers have approved this trail", + "created_at": "2026-10-26T21:01:57.586575738Z", + "completed_at": "2026-10-26T21:01:57.586575738Z", + "state": "evaluated", + "outcome": "failed", + "stale_reason": null, + "evaluated_at_sha": "f483a62c7214e4cead9ef1df09a663324a4825ae", + "finding_count": null + }, + { + "reviewers": [], + "runner_ids": [], + "id": "", + "gate_definition_id": "01M5WZ6B2M8PSY34EM5YJGG6ZR", + "gate_key": "findings", + "gate_type": "findings", + "blocking": false, + "status": "pending", + "head_sha": "f483a62c7214e4cead9ef1df09a663324a4825ae", + "value": null, + "rationale": "Gate has not been evaluated yet", + "created_at": "2026-10-26T20:42:22.164428Z", + "completed_at": null, + "state": "not_run", + "outcome": null, + "stale_reason": null, + "evaluated_at_sha": null, + "finding_count": null + }, + { + "reviewers": [], + "runner_ids": [], + "id": "01M5X0A6F5K3QMX8SRPSPC76YP", + "gate_definition_id": "01M5WZ6B2PC2X2BE023RX01WEY", + "gate_key": "up_to_date", + "gate_type": "up_to_date", + "blocking": true, + "status": "passed", + "head_sha": "f483a62c7214e4cead9ef1df09a663324a4825ae", + "value": { + "config": { + "version": 1, + "allow_behind_if_mergeable": false + }, + "behind_by": 0, + "compare_status": "ahead", + "comparison_status": "available" + }, + "rationale": "Up to date", + "created_at": "2026-10-26T21:01:57.093243Z", + "completed_at": "2026-10-26T21:01:57.093243Z", + "state": "evaluated", + "outcome": "passed", + "stale_reason": null, + "evaluated_at_sha": "f483a62c7214e4cead9ef1df09a663324a4825ae", + "finding_count": null + } + ], + "checks": { + "availability": "not_applicable", + "runs": [] + }, + "forge_merge_block": null + }, + "deployments": { + "availability": "available", + "ready": 0, + "total": 0, + "items": [] + }, + "config_source": "live", + "merge_base_sha": null, + "base_sha": null, + "head_sha": "f483a62c7214e4cead9ef1df09a663324a4825ae" + } + } +} diff --git a/test/fixtures/entire/recorded/entire.com-writes/steps/create-third-pull/03-post-forges-scratch-trails.json b/test/fixtures/entire/recorded/entire.com-writes/steps/create-third-pull/03-post-forges-scratch-trails.json new file mode 100644 index 000000000..3392bf064 --- /dev/null +++ b/test/fixtures/entire/recorded/entire.com-writes/steps/create-third-pull/03-post-forges-scratch-trails.json @@ -0,0 +1,98 @@ +{ + "request": { + "method": "POST", + "url": "https://aws-eu-central-1.api.entire.io/api/v1/et/forges-scratch/trails", + "body": { + "title": "forges fixture 20261026210133: pull 3", + "body": "Opened by run 20261026210133.", + "repoIds": [ + "01M5WYSQC41P69DTXEMZ0TE5YK" + ], + "changes": [ + { + "repositoryId": "01M5WYSQC41P69DTXEMZ0TE5YK", + "branchName": "forges-fixtures/20261026210133-3", + "base": "main", + "branchAction": "link", + "title": "forges fixture 20261026210133: pull 3", + "readyForReview": true + } + ] + } + }, + "response": { + "status": 201, + "headers": { + "link": "; rel=\"describedBy\"", + "etag": "W/\"2026-10-26T21:01:57.046039Z\"", + "location": "https://aws-eu-central-1.api.entire.io/api/v1/et/forges-scratch/trails/01M5X0A6D5Q8H8VHFN7M7HTKRS" + }, + "body": { + "$schema": "https://aws-eu-central-1.api.entire.io/api/v1/schemas/TrailResponse.json", + "capabilities": { + "canEdit": true, + "canManageScope": true + }, + "author": { + "accountId": "01M5WYRRVZNA1TXNET6KE4Q3WX", + "login": "danielroe-bot", + "displayName": "", + "avatarUrl": "https://avatars.githubusercontent.com/u/57801166?v=4", + "identity": { + "kind": "account", + "account_id": "01M5WYRRVZNA1TXNET6KE4Q3WX", + "display_name": null, + "avatar_url": "https://avatars.githubusercontent.com/u/57801166?v=4", + "handles": [ + { + "provider": "github", + "handle": "danielroe-bot", + "is_primary": true + } + ] + } + }, + "id": "01M5X0A6D5Q8H8VHFN7M7HTKRS", + "projectId": "01M5WYSMPPYRBB13ZB20H7NK2Q", + "number": 17, + "url": "https://entire.com/et/forges-scratch/-/trails/17", + "title": "forges fixture 20261026210133: pull 3", + "body": "Opened by run 20261026210133.", + "status": "open", + "phase": "building", + "metadata": {}, + "type": "task", + "priority": "none", + "assignees": [], + "assigneeAccountIds": [], + "repoIds": [ + "01M5WYSQC41P69DTXEMZ0TE5YK" + ], + "authorAccountId": "01M5WYRRVZNA1TXNET6KE4Q3WX", + "createdAt": "2026-10-26T21:01:57.028Z", + "metadataUpdatedAt": "2026-10-26T21:01:57.046Z", + "closedAt": null, + "lastVisitedAt": null, + "lastActivityAt": "2026-10-26T21:01:57.046Z", + "changes": [ + { + "id": "01M5X0A6DAPK6DZNKVR2KEJNF8", + "repositoryId": "01M5WYSQC41P69DTXEMZ0TE5YK", + "repository": "forges-fixtures", + "branch": "forges-fixtures/20261026210133-3", + "originalBranch": "forges-fixtures/20261026210133-3", + "base": "main", + "number": 11, + "title": "forges fixture 20261026210133: pull 3", + "status": "open", + "hasCodeChanges": false, + "createdAt": "2026-10-26T21:01:57.028Z", + "updatedAt": "2026-10-26T21:01:57.028Z", + "lastActivityAt": "2026-10-26T21:01:57.028Z", + "readiness": "unknown", + "mergeability": null + } + ] + } + } +} diff --git a/test/fixtures/entire/recorded/entire.com-writes/steps/create-third-pull/golden.json b/test/fixtures/entire/recorded/entire.com-writes/steps/create-third-pull/golden.json new file mode 100644 index 000000000..96022278c --- /dev/null +++ b/test/fixtures/entire/recorded/entire.com-writes/steps/create-third-pull/golden.json @@ -0,0 +1,61 @@ +{ + "ref": { + "forge": "entire", + "instance": "entire.com", + "repo": { + "forge": "entire", + "instance": "entire.com", + "owner": "forges-scratch", + "name": "forges-fixtures" + }, + "kind": "pull_request", + "number": "11", + "externalId": "01M5X0A6DAPK6DZNKVR2KEJNF8" + }, + "kind": "pull_request", + "title": "forges fixture 20261026210133: pull 3", + "body": "Opened by run 20261026210133.", + "state": "open", + "stateRaw": "open", + "isDraft": false, + "author": { + "forge": "entire", + "instance": "entire.com", + "login": "danielroe-bot", + "id": "01M5WYRRVZNA1TXNET6KE4Q3WX", + "avatarUrl": "https://avatars.githubusercontent.com/u/57801166?v=4", + "isBotHint": false + }, + "assignees": [ + { + "forge": "entire", + "instance": "entire.com", + "login": "danielroe-bot", + "id": "01M5WYRRVZNA1TXNET6KE4Q3WX", + "avatarUrl": "https://avatars.githubusercontent.com/u/57801166?v=4", + "isBotHint": false + } + ], + "reviewers": [], + "labels": [], + "url": "https://entire.com/et/forges-scratch/forges-fixtures/trails/11", + "createdAt": "", + "updatedAt": "", + "lastActivityAt": "", + "commentCount": 0, + "branches": { + "head": { + "ref": "forges-fixtures/20261026210133-3", + "sha": "f483a62c7214e4cead9ef1df09a663324a4825ae", + "repo": { + "forge": "entire", + "instance": "entire.com", + "owner": "forges-scratch", + "name": "forges-fixtures" + } + }, + "base": { + "ref": "main" + } + } +} diff --git a/test/fixtures/entire/recorded/entire.com-writes/steps/create-third-pull/step.json b/test/fixtures/entire/recorded/entire.com-writes/steps/create-third-pull/step.json new file mode 100644 index 000000000..dc14c9b6e --- /dev/null +++ b/test/fixtures/entire/recorded/entire.com-writes/steps/create-third-pull/step.json @@ -0,0 +1,4 @@ +{ + "name": "create third pull", + "recordedAt": "2026-10-26T21:01:56.531Z" +} diff --git a/test/fixtures/entire/recorded/entire.com-writes/steps/get-review-comment/01-get-N-discussions.json b/test/fixtures/entire/recorded/entire.com-writes/steps/get-review-comment/01-get-N-discussions.json new file mode 100644 index 000000000..650005cae --- /dev/null +++ b/test/fixtures/entire/recorded/entire.com-writes/steps/get-review-comment/01-get-N-discussions.json @@ -0,0 +1,235 @@ +{ + "request": { + "method": "GET", + "url": "https://aws-eu-central-1.api.entire.io/api/v1/trails/et/forges-scratch/forges-fixtures/9/discussions?include_messages=true&per_page=100" + }, + "response": { + "status": 200, + "headers": { + "link": "; rel=\"describedBy\"" + }, + "body": { + "$schema": "https://aws-eu-central-1.api.entire.io/api/v1/schemas/TrailDiscussionsListResponseBody.json", + "items": [ + { + "id": "01M5X0AHS4JAQ93WBG0CC9JN8M", + "trail_id": "01M5X0A49M70NAMJX878FD2QD1", + "title": "A review comment from run 20261026210133.", + "kind": "code_review", + "resolved": false, + "resolved_by": null, + "resolved_by_identity": { + "kind": "unknown", + "account_id": null, + "display_name": null, + "avatar_url": null, + "handles": [] + }, + "resolved_at": null, + "created_by": "01M5WRP9RJ4GVR2PA5PCNYP1FC", + "created_by_identity": { + "kind": "account", + "account_id": "01M5WRP9RJ4GVR2PA5PCNYP1FC", + "display_name": "Daniel Roe", + "avatar_url": "https://avatars.githubusercontent.com/u/28706372?v=4", + "handles": [ + { + "provider": "github", + "handle": "danielroe", + "is_primary": true + } + ] + }, + "created_at": "2026-10-26T21:02:08.674Z", + "updated_at": "2026-10-26T21:02:08.674Z", + "last_message_at": null, + "last_message_author": null, + "message_count": 0, + "participants": [], + "review_comment_id": "01M5X0AHS47CKYTKRY42WT1YYD", + "review_comment": { + "discussion_id": "01M5X0AHS4JAQ93WBG0CC9JN8M", + "discussion_message_count": 0, + "id": "01M5X0AHS47CKYTKRY42WT1YYD", + "trail_id": "01M5X0A49M70NAMJX878FD2QD1", + "repo_id": "01M5WYSQC41P69DTXEMZ0TE5YK", + "review_id": "01M5X0AGW04E508JH4BY5VE4V7", + "code_version_id": "01M5X0AGVPHGGQD3ZADR9BX2KV", + "actor_id": "01M5WRP9RJ4GVR2PA5PCNYP1FC", + "actor_display_name": "danielroe", + "actor_identity": { + "kind": "account", + "account_id": "01M5WRP9RJ4GVR2PA5PCNYP1FC", + "display_name": "Daniel Roe", + "avatar_url": "https://avatars.githubusercontent.com/u/28706372?v=4", + "handles": [ + { + "provider": "github", + "handle": "danielroe", + "is_primary": true + } + ] + }, + "body": "A review comment from run 20261026210133.", + "severity": null, + "confidence": null, + "status": "open", + "status_reason": null, + "status_actor_id": null, + "status_actor_display_name": null, + "status_actor_identity": { + "kind": "unknown", + "account_id": null, + "display_name": null, + "avatar_url": null, + "handles": [] + }, + "status_changed_at": null, + "status_source": null, + "status_actor_kind": null, + "stale_outcome": "current", + "stale_checked_at": null, + "stale_checked_code_version_id": null, + "client_id": "1", + "client_id_hash": "876dd2d2f894bbd709b9c4adf233e9cbe880d2c74674e9987f97a2d6c6e31faa", + "created_at": "2026-10-26T21:02:08.674Z", + "updated_at": "2026-10-26T21:02:08.674Z", + "location": { + "id": "01M5X0AHS4172XDD0412MR744W", + "review_comment_id": "01M5X0AHS47CKYTKRY42WT1YYD", + "code_version_id": "01M5X0AGVPHGGQD3ZADR9BX2KV", + "granularity": "whole_change", + "file_path": null, + "start_line": null, + "start_column": null, + "end_line": null, + "end_column": null, + "selected_text": null, + "nearby_text": null, + "language": null + } + }, + "messages": [] + }, + { + "id": "01M5X0A7TQB4NGZHFD3MVSJQTE", + "trail_id": "01M5X0A49M70NAMJX878FD2QD1", + "title": "Conversation", + "kind": "discussion", + "resolved": false, + "resolved_by": null, + "resolved_by_identity": { + "kind": "unknown", + "account_id": null, + "display_name": null, + "avatar_url": null, + "handles": [] + }, + "resolved_at": null, + "created_by": "01M5WYRRVZNA1TXNET6KE4Q3WX", + "created_by_identity": { + "kind": "account", + "account_id": "01M5WYRRVZNA1TXNET6KE4Q3WX", + "display_name": null, + "avatar_url": "https://avatars.githubusercontent.com/u/57801166?v=4", + "handles": [ + { + "provider": "github", + "handle": "danielroe-bot", + "is_primary": true + } + ] + }, + "created_at": "2026-10-26T21:01:58.487Z", + "updated_at": "2026-10-26T21:02:01.374Z", + "last_message_at": null, + "last_message_author": null, + "message_count": 0, + "participants": [], + "review_comment_id": null, + "review_comment": null, + "messages": [] + }, + { + "id": "01M5X0A9PBSMXT52PCMF5JCE0Y", + "trail_id": "01M5X0A49M70NAMJX878FD2QD1", + "title": "An upserted comment from run 20261026210133. ", + "kind": "discussion", + "resolved": false, + "resolved_by": null, + "resolved_by_identity": { + "kind": "unknown", + "account_id": null, + "display_name": null, + "avatar_url": null, + "handles": [] + }, + "resolved_at": null, + "created_by": "01M5WYRRVZNA1TXNET6KE4Q3WX", + "created_by_identity": { + "kind": "account", + "account_id": "01M5WYRRVZNA1TXNET6KE4Q3WX", + "display_name": null, + "avatar_url": "https://avatars.githubusercontent.com/u/57801166?v=4", + "handles": [ + { + "provider": "github", + "handle": "danielroe-bot", + "is_primary": true + } + ] + }, + "created_at": "2026-10-26T21:02:00.395Z", + "updated_at": "2026-10-26T21:02:00.395Z", + "last_message_at": "2026-10-26T21:02:00.395Z", + "last_message_author": "danielroe-bot", + "message_count": 1, + "participants": [ + { + "login": "danielroe-bot", + "actor_account_id": "01M5WYRRVZNA1TXNET6KE4Q3WX", + "identity": { + "kind": "account", + "account_id": "01M5WYRRVZNA1TXNET6KE4Q3WX", + "display_name": null, + "avatar_url": "https://avatars.githubusercontent.com/u/57801166?v=4", + "handles": [ + { + "provider": "github", + "handle": "danielroe-bot", + "is_primary": true + } + ] + } + } + ], + "review_comment_id": null, + "review_comment": null, + "messages": [ + { + "id": "01M5X0A9PCYAK06HK5CXJRQR2P", + "author": "danielroe-bot", + "identity": { + "kind": "account", + "account_id": "01M5WYRRVZNA1TXNET6KE4Q3WX", + "display_name": null, + "avatar_url": "https://avatars.githubusercontent.com/u/57801166?v=4", + "handles": [ + { + "provider": "github", + "handle": "danielroe-bot", + "is_primary": true + } + ] + }, + "created_at": "2026-10-26T21:02:00.395Z", + "body": "An upserted comment from run 20261026210133.\n\n", + "replies": [] + } + ] + } + ], + "event_cursor": "5" + } + } +} diff --git a/test/fixtures/entire/recorded/entire.com-writes/steps/get-review-comment/golden.json b/test/fixtures/entire/recorded/entire.com-writes/steps/get-review-comment/golden.json new file mode 100644 index 000000000..2a4e01e01 --- /dev/null +++ b/test/fixtures/entire/recorded/entire.com-writes/steps/get-review-comment/golden.json @@ -0,0 +1,36 @@ +{ + "ref": { + "forge": "entire", + "instance": "entire.com", + "thread": { + "forge": "entire", + "instance": "entire.com", + "repo": { + "forge": "entire", + "instance": "entire.com", + "owner": "forges-scratch", + "name": "forges-fixtures" + }, + "kind": "pull_request", + "number": "9", + "externalId": "01M5X0A49M70NAMJX878FD2QD1" + }, + "id": "01M5X0AHS47CKYTKRY42WT1YYD" + }, + "body": "A review comment from run 20261026210133.", + "author": { + "forge": "entire", + "instance": "entire.com", + "login": "danielroe", + "id": "01M5WRP9RJ4GVR2PA5PCNYP1FC", + "name": "Daniel Roe", + "avatarUrl": "https://avatars.githubusercontent.com/u/28706372?v=4", + "isBotHint": false + }, + "createdAt": "", + "updatedAt": "", + "thread": { + "id": "01M5X0AHS4JAQ93WBG0CC9JN8M", + "resolved": false + } +} diff --git a/test/fixtures/entire/recorded/entire.com-writes/steps/get-review-comment/step.json b/test/fixtures/entire/recorded/entire.com-writes/steps/get-review-comment/step.json new file mode 100644 index 000000000..9629699c4 --- /dev/null +++ b/test/fixtures/entire/recorded/entire.com-writes/steps/get-review-comment/step.json @@ -0,0 +1,7 @@ +{ + "name": "get review comment", + "recordedAt": "2026-10-26T21:02:08.977Z", + "needs": [ + "comment review" + ] +} diff --git a/test/fixtures/entire/recorded/entire.com-writes/steps/get-review/01-get-N-approvals.json b/test/fixtures/entire/recorded/entire.com-writes/steps/get-review/01-get-N-approvals.json new file mode 100644 index 000000000..a93f99e86 --- /dev/null +++ b/test/fixtures/entire/recorded/entire.com-writes/steps/get-review/01-get-N-approvals.json @@ -0,0 +1,25 @@ +{ + "request": { + "method": "GET", + "url": "https://aws-eu-central-1.api.entire.io/api/v1/trails/et/forges-scratch/forges-fixtures/11/approvals" + }, + "response": { + "status": 200, + "headers": { + "link": "; rel=\"describedBy\"" + }, + "body": { + "$schema": "https://aws-eu-central-1.api.entire.io/api/v1/schemas/TrailApprovalsResponse.json", + "approvals": [ + { + "id": "01M5X0AFJEGJWS360MQ5YST9XY", + "author": "danielroe", + "event": "approved", + "body": null, + "commit_sha": "f483a62c7214e4cead9ef1df09a663324a4825ae", + "created_at": "2026-10-26T21:02:06.414872128Z" + } + ] + } + } +} diff --git a/test/fixtures/entire/recorded/entire.com-writes/steps/get-review/golden.json b/test/fixtures/entire/recorded/entire.com-writes/steps/get-review/golden.json new file mode 100644 index 000000000..41ac0ddef --- /dev/null +++ b/test/fixtures/entire/recorded/entire.com-writes/steps/get-review/golden.json @@ -0,0 +1,31 @@ +{ + "ref": { + "forge": "entire", + "instance": "entire.com", + "thread": { + "forge": "entire", + "instance": "entire.com", + "repo": { + "forge": "entire", + "instance": "entire.com", + "owner": "forges-scratch", + "name": "forges-fixtures" + }, + "kind": "pull_request", + "number": "11", + "externalId": "01M5X0A6DAPK6DZNKVR2KEJNF8" + }, + "id": "01M5X0AFJEGJWS360MQ5YST9XY" + }, + "author": { + "forge": "entire", + "instance": "entire.com", + "login": "danielroe", + "id": "danielroe", + "isBotHint": false + }, + "state": "approved", + "stateRaw": "approved", + "submittedAt": "", + "comments": false +} diff --git a/test/fixtures/entire/recorded/entire.com-writes/steps/get-review/step.json b/test/fixtures/entire/recorded/entire.com-writes/steps/get-review/step.json new file mode 100644 index 000000000..bdd834758 --- /dev/null +++ b/test/fixtures/entire/recorded/entire.com-writes/steps/get-review/step.json @@ -0,0 +1,8 @@ +{ + "name": "get review", + "recordedAt": "2026-10-26T21:02:08.780Z", + "needs": [ + "pending review", + "comment review" + ] +} diff --git a/test/fixtures/entire/recorded/entire.com-writes/steps/issue-assign/01-patch-trails-N.json b/test/fixtures/entire/recorded/entire.com-writes/steps/issue-assign/01-patch-trails-N.json new file mode 100644 index 000000000..8141468dc --- /dev/null +++ b/test/fixtures/entire/recorded/entire.com-writes/steps/issue-assign/01-patch-trails-N.json @@ -0,0 +1,129 @@ +{ + "request": { + "method": "PATCH", + "url": "https://aws-eu-central-1.api.entire.io/api/v1/et/forges-scratch/trails/13", + "body": { + "assignees": [ + "ulid:01M5WYRRVZNA1TXNET6KE4Q3WX" + ] + } + }, + "response": { + "status": 200, + "headers": { + "link": "; rel=\"describedBy\"", + "etag": "W/\"2026-10-26T21:01:49.813331Z\"" + }, + "body": { + "$schema": "https://aws-eu-central-1.api.entire.io/api/v1/schemas/TrailResponse.json", + "capabilities": { + "canEdit": true, + "canManageScope": true + }, + "project": { + "primaryProcessingCell": "aws-eu-central-1", + "id": "01M5WYSMPPYRBB13ZB20H7NK2Q", + "name": "forges-scratch", + "provider": "entire", + "reference": { + "forge": "et", + "project": "forges-scratch" + }, + "jurisdiction": "eu", + "capabilities": { + "canManageTrails": true + } + }, + "author": { + "accountId": "01M5WYRRVZNA1TXNET6KE4Q3WX", + "login": "danielroe-bot", + "displayName": "", + "avatarUrl": "https://avatars.githubusercontent.com/u/57801166?v=4", + "identity": { + "kind": "account", + "account_id": "01M5WYRRVZNA1TXNET6KE4Q3WX", + "display_name": null, + "avatar_url": "https://avatars.githubusercontent.com/u/57801166?v=4", + "handles": [ + { + "provider": "github", + "handle": "danielroe-bot", + "is_primary": true + } + ] + } + }, + "assigneeProfiles": [ + { + "accountId": "01M5WYRRVZNA1TXNET6KE4Q3WX", + "login": "danielroe-bot", + "displayName": "", + "avatarUrl": "https://avatars.githubusercontent.com/u/57801166?v=4", + "identity": { + "kind": "account", + "account_id": "01M5WYRRVZNA1TXNET6KE4Q3WX", + "display_name": null, + "avatar_url": "https://avatars.githubusercontent.com/u/57801166?v=4", + "handles": [ + { + "provider": "github", + "handle": "danielroe-bot", + "is_primary": true + } + ] + } + } + ], + "id": "01M5X09TE6P0R8TR8WPCVX7H6Y", + "projectId": "01M5WYSMPPYRBB13ZB20H7NK2Q", + "number": 13, + "url": "https://entire.com/et/forges-scratch/-/trails/13", + "title": "forges fixture 20261026210133: issue", + "body": "Opened by run 20261026210133.", + "bodyDocument": { + "id": "", + "document_key": "project-trail:01M5X09TE6P0R8TR8WPCVX7H6Y:body", + "schema_version": 1, + "content_json": { + "type": "doc", + "content": [ + { + "type": "paragraph", + "content": [ + { + "type": "text", + "text": "Opened by run 20261026210133." + } + ] + } + ] + }, + "text_snapshot": "Opened by run 20261026210133.", + "updated_at": "2026-10-26T21:01:49.813Z", + "etag": "" + }, + "status": "open", + "phase": "planning", + "metadata": {}, + "type": "task", + "priority": "none", + "assignees": [ + "ulid:01M5WYRRVZNA1TXNET6KE4Q3WX" + ], + "assigneeAccountIds": [ + "01M5WYRRVZNA1TXNET6KE4Q3WX" + ], + "repoIds": [ + "01M5WYSQC41P69DTXEMZ0TE5YK" + ], + "authorAccountId": "01M5WYRRVZNA1TXNET6KE4Q3WX", + "createdAt": "2026-10-26T21:01:44.774Z", + "metadataUpdatedAt": "2026-10-26T21:01:49.813Z", + "closedAt": null, + "lastVisitedAt": null, + "lastActivityAt": "2026-10-26T21:01:49.813Z", + "changes": [], + "isPossiblyPartial": true + } + } +} diff --git a/test/fixtures/entire/recorded/entire.com-writes/steps/issue-assign/golden.json b/test/fixtures/entire/recorded/entire.com-writes/steps/issue-assign/golden.json new file mode 100644 index 000000000..4f87da032 --- /dev/null +++ b/test/fixtures/entire/recorded/entire.com-writes/steps/issue-assign/golden.json @@ -0,0 +1,10 @@ +[ + { + "forge": "entire", + "instance": "entire.com", + "login": "danielroe-bot", + "id": "01M5WYRRVZNA1TXNET6KE4Q3WX", + "avatarUrl": "https://avatars.githubusercontent.com/u/57801166?v=4", + "isBotHint": false + } +] diff --git a/test/fixtures/entire/recorded/entire.com-writes/steps/issue-assign/step.json b/test/fixtures/entire/recorded/entire.com-writes/steps/issue-assign/step.json new file mode 100644 index 000000000..e17731698 --- /dev/null +++ b/test/fixtures/entire/recorded/entire.com-writes/steps/issue-assign/step.json @@ -0,0 +1,8 @@ +{ + "name": "issue assign", + "recordedAt": "2026-10-26T21:01:48.904Z", + "needs": [ + "create issue", + "author" + ] +} diff --git a/test/fixtures/entire/recorded/entire.com-writes/steps/issue-close/01-patch-trails-N.json b/test/fixtures/entire/recorded/entire.com-writes/steps/issue-close/01-patch-trails-N.json new file mode 100644 index 000000000..98e1498b2 --- /dev/null +++ b/test/fixtures/entire/recorded/entire.com-writes/steps/issue-close/01-patch-trails-N.json @@ -0,0 +1,127 @@ +{ + "request": { + "method": "PATCH", + "url": "https://aws-eu-central-1.api.entire.io/api/v1/et/forges-scratch/trails/13", + "body": { + "status": "closed" + } + }, + "response": { + "status": 200, + "headers": { + "link": "; rel=\"describedBy\"", + "etag": "W/\"2026-10-26T21:01:52.804375Z\"" + }, + "body": { + "$schema": "https://aws-eu-central-1.api.entire.io/api/v1/schemas/TrailResponse.json", + "capabilities": { + "canEdit": true, + "canManageScope": true + }, + "project": { + "primaryProcessingCell": "aws-eu-central-1", + "id": "01M5WYSMPPYRBB13ZB20H7NK2Q", + "name": "forges-scratch", + "provider": "entire", + "reference": { + "forge": "et", + "project": "forges-scratch" + }, + "jurisdiction": "eu", + "capabilities": { + "canManageTrails": true + } + }, + "author": { + "accountId": "01M5WYRRVZNA1TXNET6KE4Q3WX", + "login": "danielroe-bot", + "displayName": "", + "avatarUrl": "https://avatars.githubusercontent.com/u/57801166?v=4", + "identity": { + "kind": "account", + "account_id": "01M5WYRRVZNA1TXNET6KE4Q3WX", + "display_name": null, + "avatar_url": "https://avatars.githubusercontent.com/u/57801166?v=4", + "handles": [ + { + "provider": "github", + "handle": "danielroe-bot", + "is_primary": true + } + ] + } + }, + "assigneeProfiles": [ + { + "accountId": "01M5WYRRVZNA1TXNET6KE4Q3WX", + "login": "danielroe-bot", + "displayName": "", + "avatarUrl": "https://avatars.githubusercontent.com/u/57801166?v=4", + "identity": { + "kind": "account", + "account_id": "01M5WYRRVZNA1TXNET6KE4Q3WX", + "display_name": null, + "avatar_url": "https://avatars.githubusercontent.com/u/57801166?v=4", + "handles": [ + { + "provider": "github", + "handle": "danielroe-bot", + "is_primary": true + } + ] + } + } + ], + "id": "01M5X09TE6P0R8TR8WPCVX7H6Y", + "projectId": "01M5WYSMPPYRBB13ZB20H7NK2Q", + "number": 13, + "url": "https://entire.com/et/forges-scratch/-/trails/13", + "title": "forges fixture 20261026210133: issue, edited", + "body": "Edited by run 20261026210133.", + "bodyDocument": { + "id": "", + "document_key": "project-trail:01M5X09TE6P0R8TR8WPCVX7H6Y:body", + "schema_version": 1, + "content_json": { + "type": "doc", + "content": [ + { + "type": "paragraph", + "content": [ + { + "type": "text", + "text": "Edited by run 20261026210133." + } + ] + } + ] + }, + "text_snapshot": "Edited by run 20261026210133.", + "updated_at": "2026-10-26T21:01:52.804Z", + "etag": "" + }, + "status": "closed", + "phase": "closed", + "metadata": {}, + "type": "task", + "priority": "none", + "assignees": [ + "ulid:01M5WYRRVZNA1TXNET6KE4Q3WX" + ], + "assigneeAccountIds": [ + "01M5WYRRVZNA1TXNET6KE4Q3WX" + ], + "repoIds": [ + "01M5WYSQC41P69DTXEMZ0TE5YK" + ], + "authorAccountId": "01M5WYRRVZNA1TXNET6KE4Q3WX", + "createdAt": "2026-10-26T21:01:44.774Z", + "metadataUpdatedAt": "2026-10-26T21:01:52.804Z", + "closedAt": "2026-10-26T21:01:52.804Z", + "lastVisitedAt": null, + "lastActivityAt": "2026-10-26T21:01:52.804Z", + "changes": [], + "isPossiblyPartial": true + } + } +} diff --git a/test/fixtures/entire/recorded/entire.com-writes/steps/issue-close/golden.json b/test/fixtures/entire/recorded/entire.com-writes/steps/issue-close/golden.json new file mode 100644 index 000000000..8c53f143e --- /dev/null +++ b/test/fixtures/entire/recorded/entire.com-writes/steps/issue-close/golden.json @@ -0,0 +1,51 @@ +{ + "ref": { + "forge": "entire", + "instance": "entire.com", + "repo": { + "forge": "entire", + "instance": "entire.com", + "owner": "forges-scratch", + "name": "", + "kind": "namespace" + }, + "kind": "issue", + "number": "13", + "externalId": "01M5X09TE6P0R8TR8WPCVX7H6Y" + }, + "kind": "issue", + "title": "forges fixture 20261026210133: issue, edited", + "body": "Edited by run 20261026210133.", + "state": "closed", + "stateRaw": "closed", + "isDraft": false, + "author": { + "forge": "entire", + "instance": "entire.com", + "login": "danielroe-bot", + "id": "01M5WYRRVZNA1TXNET6KE4Q3WX", + "avatarUrl": "https://avatars.githubusercontent.com/u/57801166?v=4", + "isBotHint": false + }, + "assignees": [ + { + "forge": "entire", + "instance": "entire.com", + "login": "danielroe-bot", + "id": "01M5WYRRVZNA1TXNET6KE4Q3WX", + "avatarUrl": "https://avatars.githubusercontent.com/u/57801166?v=4", + "isBotHint": false + } + ], + "reviewers": [], + "labels": [], + "url": "https://entire.com/et/forges-scratch/-/trails/13", + "createdAt": "", + "updatedAt": "", + "closedAt": "", + "lastActivityAt": "", + "issueType": { + "id": "task", + "name": "task" + } +} diff --git a/test/fixtures/entire/recorded/entire.com-writes/steps/issue-close/step.json b/test/fixtures/entire/recorded/entire.com-writes/steps/issue-close/step.json new file mode 100644 index 000000000..a01932ed7 --- /dev/null +++ b/test/fixtures/entire/recorded/entire.com-writes/steps/issue-close/step.json @@ -0,0 +1,7 @@ +{ + "name": "issue close", + "recordedAt": "2026-10-26T21:01:52.284Z", + "needs": [ + "create issue" + ] +} diff --git a/test/fixtures/entire/recorded/entire.com-writes/steps/issue-comment/01-get-et-forges-scratch.json b/test/fixtures/entire/recorded/entire.com-writes/steps/issue-comment/01-get-et-forges-scratch.json new file mode 100644 index 000000000..9895c159c --- /dev/null +++ b/test/fixtures/entire/recorded/entire.com-writes/steps/issue-comment/01-get-et-forges-scratch.json @@ -0,0 +1,38 @@ +{ + "request": { + "method": "GET", + "url": "https://us.console.entire.io/api/v1/projects/resolve/et/forges-scratch" + }, + "response": { + "status": 200, + "headers": { + "link": "; rel=\"describedBy\"" + }, + "body": { + "$schema": "https://us.console.entire.io/api/v1/schemas/ResolveProjectOutputBody.json", + "project": { + "id": "01M5WYSMPPYRBB13ZB20H7NK2Q", + "name": "forges-scratch", + "ownerType": "account", + "ownerId": "01M5WYRRVZNA1TXNET6KE4Q3WX", + "ownerName": "github:danielroe-bot", + "region": "eu", + "createdAt": "2026-10-26T20:35:26.151561Z", + "capabilities": { + "canDelete": true, + "canManageAccess": true, + "canCreateRepository": true, + "canManageTrails": true, + "canManagePlugins": true, + "canManageAgents": true + }, + "primaryProcessingCell": "aws-eu-central-1", + "apiUrl": "https://aws-eu-central-1.api.entire.io" + }, + "reference": { + "host": "et", + "project": "forges-scratch" + } + } + } +} diff --git a/test/fixtures/entire/recorded/entire.com-writes/steps/issue-comment/02-post-N-discussions.json b/test/fixtures/entire/recorded/entire.com-writes/steps/issue-comment/02-post-N-discussions.json new file mode 100644 index 000000000..0e3443e92 --- /dev/null +++ b/test/fixtures/entire/recorded/entire.com-writes/steps/issue-comment/02-post-N-discussions.json @@ -0,0 +1,98 @@ +{ + "request": { + "method": "POST", + "url": "https://aws-eu-central-1.api.entire.io/api/v1/et/forges-scratch/trails/13/discussions", + "body": { + "body": "A comment from run 20261026210133." + } + }, + "response": { + "status": 201, + "headers": { + "link": "; rel=\"describedBy\"", + "etag": "\"discussion:01M5X09V1QW77SKERM3TA6VTXC:1\"", + "location": "https://aws-eu-central-1.api.entire.io/api/v1/et/forges-scratch/trails/01M5X09TE6P0R8TR8WPCVX7H6Y/discussions/01M5X09V1QW77SKERM3TA6VTXC" + }, + "body": { + "$schema": "https://aws-eu-central-1.api.entire.io/api/v1/schemas/DiscussionCreateResponseBody.json", + "discussion": { + "etag": "\"discussion:01M5X09V1QW77SKERM3TA6VTXC:1\"", + "id": "01M5X09V1QW77SKERM3TA6VTXC", + "trail_id": "01M5X09TE6P0R8TR8WPCVX7H6Y", + "title": "A comment from run 20261026210133.", + "kind": "discussion", + "resolved": false, + "resolved_by": null, + "resolved_by_identity": { + "kind": "unknown", + "account_id": null, + "display_name": null, + "avatar_url": null, + "handles": [] + }, + "resolved_at": null, + "created_by": "01M5WYRRVZNA1TXNET6KE4Q3WX", + "created_by_identity": { + "kind": "account", + "account_id": "01M5WYRRVZNA1TXNET6KE4Q3WX", + "display_name": null, + "avatar_url": "https://avatars.githubusercontent.com/u/57801166?v=4", + "handles": [ + { + "provider": "github", + "handle": "danielroe-bot", + "is_primary": true + } + ] + }, + "created_at": "2026-10-26T21:01:45.399Z", + "updated_at": "2026-10-26T21:01:45.399Z", + "last_message_at": "2026-10-26T21:01:45.399Z", + "last_message_author": "danielroe-bot", + "message_count": 1, + "participants": [ + { + "login": "danielroe-bot", + "actor_account_id": "01M5WYRRVZNA1TXNET6KE4Q3WX", + "identity": { + "kind": "account", + "account_id": "01M5WYRRVZNA1TXNET6KE4Q3WX", + "display_name": null, + "avatar_url": "https://avatars.githubusercontent.com/u/57801166?v=4", + "handles": [ + { + "provider": "github", + "handle": "danielroe-bot", + "is_primary": true + } + ] + } + } + ], + "review_comment_id": null, + "review_comment": null + }, + "message": { + "etag": "\"message:01M5X09V1T11B2MR912QBBWXHP:1\"", + "id": "01M5X09V1T11B2MR912QBBWXHP", + "author": "danielroe-bot", + "identity": { + "kind": "account", + "account_id": "01M5WYRRVZNA1TXNET6KE4Q3WX", + "display_name": null, + "avatar_url": "https://avatars.githubusercontent.com/u/57801166?v=4", + "handles": [ + { + "provider": "github", + "handle": "danielroe-bot", + "is_primary": true + } + ] + }, + "created_at": "2026-10-26T21:01:45.399Z", + "body": "A comment from run 20261026210133.", + "replies": [] + } + } + } +} diff --git a/test/fixtures/entire/recorded/entire.com-writes/steps/issue-comment/golden.json b/test/fixtures/entire/recorded/entire.com-writes/steps/issue-comment/golden.json new file mode 100644 index 000000000..8d8662bc3 --- /dev/null +++ b/test/fixtures/entire/recorded/entire.com-writes/steps/issue-comment/golden.json @@ -0,0 +1,35 @@ +{ + "ref": { + "forge": "entire", + "instance": "entire.com", + "thread": { + "forge": "entire", + "instance": "entire.com", + "repo": { + "forge": "entire", + "instance": "entire.com", + "owner": "forges-scratch", + "name": "", + "kind": "namespace" + }, + "kind": "issue", + "number": "13", + "externalId": "01M5X09TE6P0R8TR8WPCVX7H6Y" + }, + "id": "01M5X09V1T11B2MR912QBBWXHP" + }, + "body": "A comment from run 20261026210133.", + "author": { + "forge": "entire", + "instance": "entire.com", + "login": "danielroe-bot", + "id": "01M5WYRRVZNA1TXNET6KE4Q3WX", + "avatarUrl": "https://avatars.githubusercontent.com/u/57801166?v=4", + "isBotHint": false + }, + "createdAt": "", + "thread": { + "id": "01M5X09V1QW77SKERM3TA6VTXC", + "resolved": false + } +} diff --git a/test/fixtures/entire/recorded/entire.com-writes/steps/issue-comment/step.json b/test/fixtures/entire/recorded/entire.com-writes/steps/issue-comment/step.json new file mode 100644 index 000000000..fb7563c73 --- /dev/null +++ b/test/fixtures/entire/recorded/entire.com-writes/steps/issue-comment/step.json @@ -0,0 +1,7 @@ +{ + "name": "issue comment", + "recordedAt": "2026-10-26T21:01:44.859Z", + "needs": [ + "create issue" + ] +} diff --git a/test/fixtures/entire/recorded/entire.com-writes/steps/issue-delete-comment/01-delete-messages-01M5X09V1T11B2MR912QBBWXHP.json b/test/fixtures/entire/recorded/entire.com-writes/steps/issue-delete-comment/01-delete-messages-01M5X09V1T11B2MR912QBBWXHP.json new file mode 100644 index 000000000..9f9c38c1d --- /dev/null +++ b/test/fixtures/entire/recorded/entire.com-writes/steps/issue-delete-comment/01-delete-messages-01M5X09V1T11B2MR912QBBWXHP.json @@ -0,0 +1,10 @@ +{ + "request": { + "method": "DELETE", + "url": "https://aws-eu-central-1.api.entire.io/api/v1/et/forges-scratch/trails/13/discussions/01M5X09V1QW77SKERM3TA6VTXC/messages/01M5X09V1T11B2MR912QBBWXHP" + }, + "response": { + "status": 204, + "headers": {} + } +} diff --git a/test/fixtures/entire/recorded/entire.com-writes/steps/issue-delete-comment/02-get-discussions-01M5X09V1QW77SKERM3TA6VTXC.json b/test/fixtures/entire/recorded/entire.com-writes/steps/issue-delete-comment/02-get-discussions-01M5X09V1QW77SKERM3TA6VTXC.json new file mode 100644 index 000000000..c0c343150 --- /dev/null +++ b/test/fixtures/entire/recorded/entire.com-writes/steps/issue-delete-comment/02-get-discussions-01M5X09V1QW77SKERM3TA6VTXC.json @@ -0,0 +1,97 @@ +{ + "request": { + "method": "GET", + "url": "https://aws-eu-central-1.api.entire.io/api/v1/et/forges-scratch/trails/13/discussions/01M5X09V1QW77SKERM3TA6VTXC" + }, + "response": { + "status": 200, + "headers": { + "link": "; rel=\"describedBy\"", + "etag": "\"discussion:01M5X09V1QW77SKERM3TA6VTXC:2\"" + }, + "body": { + "$schema": "https://aws-eu-central-1.api.entire.io/api/v1/schemas/DiscussionDetailResponseBody.json", + "discussion": { + "etag": "\"discussion:01M5X09V1QW77SKERM3TA6VTXC:2\"", + "id": "01M5X09V1QW77SKERM3TA6VTXC", + "trail_id": "01M5X09TE6P0R8TR8WPCVX7H6Y", + "title": "An edited comment from run 20261026210133.", + "kind": "discussion", + "resolved": false, + "resolved_by": null, + "resolved_by_identity": { + "kind": "unknown", + "account_id": null, + "display_name": null, + "avatar_url": null, + "handles": [] + }, + "resolved_at": null, + "created_by": "01M5WYRRVZNA1TXNET6KE4Q3WX", + "created_by_identity": { + "kind": "account", + "account_id": "01M5WYRRVZNA1TXNET6KE4Q3WX", + "display_name": null, + "avatar_url": "https://avatars.githubusercontent.com/u/57801166?v=4", + "handles": [ + { + "provider": "github", + "handle": "danielroe-bot", + "is_primary": true + } + ] + }, + "created_at": "2026-10-26T21:01:45.399Z", + "updated_at": "2026-10-26T21:01:46.409Z", + "last_message_at": "2026-10-26T21:01:45.399Z", + "last_message_author": "danielroe-bot", + "message_count": 1, + "participants": [ + { + "login": "danielroe-bot", + "actor_account_id": "01M5WYRRVZNA1TXNET6KE4Q3WX", + "identity": { + "kind": "account", + "account_id": "01M5WYRRVZNA1TXNET6KE4Q3WX", + "display_name": null, + "avatar_url": "https://avatars.githubusercontent.com/u/57801166?v=4", + "handles": [ + { + "provider": "github", + "handle": "danielroe-bot", + "is_primary": true + } + ] + } + } + ], + "review_comment_id": null, + "review_comment": null + }, + "messages": [ + { + "etag": "\"message:01M5X09V1T11B2MR912QBBWXHP:2\"", + "id": "01M5X09V1T11B2MR912QBBWXHP", + "author": "danielroe-bot", + "identity": { + "kind": "account", + "account_id": "01M5WYRRVZNA1TXNET6KE4Q3WX", + "display_name": null, + "avatar_url": "https://avatars.githubusercontent.com/u/57801166?v=4", + "handles": [ + { + "provider": "github", + "handle": "danielroe-bot", + "is_primary": true + } + ] + }, + "created_at": "2026-10-26T21:01:45.399Z", + "body": "An edited comment from run 20261026210133.", + "replies": [] + } + ], + "eventCursor": "3" + } + } +} diff --git a/test/fixtures/entire/recorded/entire.com-writes/steps/issue-delete-comment/03-get-discussions-01M5X09X6MW0ZY9BGSJQF9EP7F.json b/test/fixtures/entire/recorded/entire.com-writes/steps/issue-delete-comment/03-get-discussions-01M5X09X6MW0ZY9BGSJQF9EP7F.json new file mode 100644 index 000000000..b9510d269 --- /dev/null +++ b/test/fixtures/entire/recorded/entire.com-writes/steps/issue-delete-comment/03-get-discussions-01M5X09X6MW0ZY9BGSJQF9EP7F.json @@ -0,0 +1,97 @@ +{ + "request": { + "method": "GET", + "url": "https://aws-eu-central-1.api.entire.io/api/v1/et/forges-scratch/trails/13/discussions/01M5X09X6MW0ZY9BGSJQF9EP7F" + }, + "response": { + "status": 200, + "headers": { + "link": "; rel=\"describedBy\"", + "etag": "\"discussion:01M5X09X6MW0ZY9BGSJQF9EP7F:1\"" + }, + "body": { + "$schema": "https://aws-eu-central-1.api.entire.io/api/v1/schemas/DiscussionDetailResponseBody.json", + "discussion": { + "etag": "\"discussion:01M5X09X6MW0ZY9BGSJQF9EP7F:1\"", + "id": "01M5X09X6MW0ZY9BGSJQF9EP7F", + "trail_id": "01M5X09TE6P0R8TR8WPCVX7H6Y", + "title": "An upserted comment from run 20261026210133. ", + "kind": "discussion", + "resolved": false, + "resolved_by": null, + "resolved_by_identity": { + "kind": "unknown", + "account_id": null, + "display_name": null, + "avatar_url": null, + "handles": [] + }, + "resolved_at": null, + "created_by": "01M5WYRRVZNA1TXNET6KE4Q3WX", + "created_by_identity": { + "kind": "account", + "account_id": "01M5WYRRVZNA1TXNET6KE4Q3WX", + "display_name": null, + "avatar_url": "https://avatars.githubusercontent.com/u/57801166?v=4", + "handles": [ + { + "provider": "github", + "handle": "danielroe-bot", + "is_primary": true + } + ] + }, + "created_at": "2026-10-26T21:01:47.604Z", + "updated_at": "2026-10-26T21:01:47.604Z", + "last_message_at": "2026-10-26T21:01:47.604Z", + "last_message_author": "danielroe-bot", + "message_count": 1, + "participants": [ + { + "login": "danielroe-bot", + "actor_account_id": "01M5WYRRVZNA1TXNET6KE4Q3WX", + "identity": { + "kind": "account", + "account_id": "01M5WYRRVZNA1TXNET6KE4Q3WX", + "display_name": null, + "avatar_url": "https://avatars.githubusercontent.com/u/57801166?v=4", + "handles": [ + { + "provider": "github", + "handle": "danielroe-bot", + "is_primary": true + } + ] + } + } + ], + "review_comment_id": null, + "review_comment": null + }, + "messages": [ + { + "etag": "\"message:01M5X09X6NVNBBBXF1YX5PRNPV:1\"", + "id": "01M5X09X6NVNBBBXF1YX5PRNPV", + "author": "danielroe-bot", + "identity": { + "kind": "account", + "account_id": "01M5WYRRVZNA1TXNET6KE4Q3WX", + "display_name": null, + "avatar_url": "https://avatars.githubusercontent.com/u/57801166?v=4", + "handles": [ + { + "provider": "github", + "handle": "danielroe-bot", + "is_primary": true + } + ] + }, + "created_at": "2026-10-26T21:01:47.604Z", + "body": "An upserted comment from run 20261026210133.\n\n", + "replies": [] + } + ], + "eventCursor": "3" + } + } +} diff --git a/test/fixtures/entire/recorded/entire.com-writes/steps/issue-delete-comment/04-get-N-discussions.json b/test/fixtures/entire/recorded/entire.com-writes/steps/issue-delete-comment/04-get-N-discussions.json new file mode 100644 index 000000000..6eaab1dbd --- /dev/null +++ b/test/fixtures/entire/recorded/entire.com-writes/steps/issue-delete-comment/04-get-N-discussions.json @@ -0,0 +1,133 @@ +{ + "request": { + "method": "GET", + "url": "https://aws-eu-central-1.api.entire.io/api/v1/et/forges-scratch/trails/13/discussions?pageSize=100" + }, + "response": { + "status": 200, + "headers": { + "link": "; rel=\"describedBy\"" + }, + "body": { + "$schema": "https://aws-eu-central-1.api.entire.io/api/v1/schemas/DiscussionsListResponseBody.json", + "items": [ + { + "etag": "\"discussion:01M5X09X6MW0ZY9BGSJQF9EP7F:1\"", + "id": "01M5X09X6MW0ZY9BGSJQF9EP7F", + "trail_id": "01M5X09TE6P0R8TR8WPCVX7H6Y", + "title": "An upserted comment from run 20261026210133. ", + "kind": "discussion", + "resolved": false, + "resolved_by": null, + "resolved_by_identity": { + "kind": "unknown", + "account_id": null, + "display_name": null, + "avatar_url": null, + "handles": [] + }, + "resolved_at": null, + "created_by": "01M5WYRRVZNA1TXNET6KE4Q3WX", + "created_by_identity": { + "kind": "account", + "account_id": "01M5WYRRVZNA1TXNET6KE4Q3WX", + "display_name": null, + "avatar_url": "https://avatars.githubusercontent.com/u/57801166?v=4", + "handles": [ + { + "provider": "github", + "handle": "danielroe-bot", + "is_primary": true + } + ] + }, + "created_at": "2026-10-26T21:01:47.604Z", + "updated_at": "2026-10-26T21:01:47.604Z", + "last_message_at": "2026-10-26T21:01:47.604Z", + "last_message_author": "danielroe-bot", + "message_count": 1, + "participants": [ + { + "login": "danielroe-bot", + "actor_account_id": "01M5WYRRVZNA1TXNET6KE4Q3WX", + "identity": { + "kind": "account", + "account_id": "01M5WYRRVZNA1TXNET6KE4Q3WX", + "display_name": null, + "avatar_url": "https://avatars.githubusercontent.com/u/57801166?v=4", + "handles": [ + { + "provider": "github", + "handle": "danielroe-bot", + "is_primary": true + } + ] + } + } + ], + "review_comment_id": null, + "review_comment": null + }, + { + "etag": "\"discussion:01M5X09V1QW77SKERM3TA6VTXC:2\"", + "id": "01M5X09V1QW77SKERM3TA6VTXC", + "trail_id": "01M5X09TE6P0R8TR8WPCVX7H6Y", + "title": "An edited comment from run 20261026210133.", + "kind": "discussion", + "resolved": false, + "resolved_by": null, + "resolved_by_identity": { + "kind": "unknown", + "account_id": null, + "display_name": null, + "avatar_url": null, + "handles": [] + }, + "resolved_at": null, + "created_by": "01M5WYRRVZNA1TXNET6KE4Q3WX", + "created_by_identity": { + "kind": "account", + "account_id": "01M5WYRRVZNA1TXNET6KE4Q3WX", + "display_name": null, + "avatar_url": "https://avatars.githubusercontent.com/u/57801166?v=4", + "handles": [ + { + "provider": "github", + "handle": "danielroe-bot", + "is_primary": true + } + ] + }, + "created_at": "2026-10-26T21:01:45.399Z", + "updated_at": "2026-10-26T21:01:46.409Z", + "last_message_at": "2026-10-26T21:01:45.399Z", + "last_message_author": "danielroe-bot", + "message_count": 1, + "participants": [ + { + "login": "danielroe-bot", + "actor_account_id": "01M5WYRRVZNA1TXNET6KE4Q3WX", + "identity": { + "kind": "account", + "account_id": "01M5WYRRVZNA1TXNET6KE4Q3WX", + "display_name": null, + "avatar_url": "https://avatars.githubusercontent.com/u/57801166?v=4", + "handles": [ + { + "provider": "github", + "handle": "danielroe-bot", + "is_primary": true + } + ] + } + } + ], + "review_comment_id": null, + "review_comment": null + } + ], + "nextPageToken": null, + "eventCursor": "3" + } + } +} diff --git a/test/fixtures/entire/recorded/entire.com-writes/steps/issue-delete-comment/golden.json b/test/fixtures/entire/recorded/entire.com-writes/steps/issue-delete-comment/golden.json new file mode 100644 index 000000000..19765bd50 --- /dev/null +++ b/test/fixtures/entire/recorded/entire.com-writes/steps/issue-delete-comment/golden.json @@ -0,0 +1 @@ +null diff --git a/test/fixtures/entire/recorded/entire.com-writes/steps/issue-delete-comment/step.json b/test/fixtures/entire/recorded/entire.com-writes/steps/issue-delete-comment/step.json new file mode 100644 index 000000000..fce7c4a12 --- /dev/null +++ b/test/fixtures/entire/recorded/entire.com-writes/steps/issue-delete-comment/step.json @@ -0,0 +1,7 @@ +{ + "name": "issue delete comment", + "recordedAt": "2026-10-26T21:01:47.687Z", + "needs": [ + "issue comment" + ] +} diff --git a/test/fixtures/entire/recorded/entire.com-writes/steps/issue-edit-comment/01-get-discussions-01M5X09V1QW77SKERM3TA6VTXC.json b/test/fixtures/entire/recorded/entire.com-writes/steps/issue-edit-comment/01-get-discussions-01M5X09V1QW77SKERM3TA6VTXC.json new file mode 100644 index 000000000..f61040301 --- /dev/null +++ b/test/fixtures/entire/recorded/entire.com-writes/steps/issue-edit-comment/01-get-discussions-01M5X09V1QW77SKERM3TA6VTXC.json @@ -0,0 +1,97 @@ +{ + "request": { + "method": "GET", + "url": "https://aws-eu-central-1.api.entire.io/api/v1/et/forges-scratch/trails/13/discussions/01M5X09V1QW77SKERM3TA6VTXC" + }, + "response": { + "status": 200, + "headers": { + "link": "; rel=\"describedBy\"", + "etag": "\"discussion:01M5X09V1QW77SKERM3TA6VTXC:1\"" + }, + "body": { + "$schema": "https://aws-eu-central-1.api.entire.io/api/v1/schemas/DiscussionDetailResponseBody.json", + "discussion": { + "etag": "\"discussion:01M5X09V1QW77SKERM3TA6VTXC:1\"", + "id": "01M5X09V1QW77SKERM3TA6VTXC", + "trail_id": "01M5X09TE6P0R8TR8WPCVX7H6Y", + "title": "A comment from run 20261026210133.", + "kind": "discussion", + "resolved": false, + "resolved_by": null, + "resolved_by_identity": { + "kind": "unknown", + "account_id": null, + "display_name": null, + "avatar_url": null, + "handles": [] + }, + "resolved_at": null, + "created_by": "01M5WYRRVZNA1TXNET6KE4Q3WX", + "created_by_identity": { + "kind": "account", + "account_id": "01M5WYRRVZNA1TXNET6KE4Q3WX", + "display_name": null, + "avatar_url": "https://avatars.githubusercontent.com/u/57801166?v=4", + "handles": [ + { + "provider": "github", + "handle": "danielroe-bot", + "is_primary": true + } + ] + }, + "created_at": "2026-10-26T21:01:45.399Z", + "updated_at": "2026-10-26T21:01:45.399Z", + "last_message_at": "2026-10-26T21:01:45.399Z", + "last_message_author": "danielroe-bot", + "message_count": 1, + "participants": [ + { + "login": "danielroe-bot", + "actor_account_id": "01M5WYRRVZNA1TXNET6KE4Q3WX", + "identity": { + "kind": "account", + "account_id": "01M5WYRRVZNA1TXNET6KE4Q3WX", + "display_name": null, + "avatar_url": "https://avatars.githubusercontent.com/u/57801166?v=4", + "handles": [ + { + "provider": "github", + "handle": "danielroe-bot", + "is_primary": true + } + ] + } + } + ], + "review_comment_id": null, + "review_comment": null + }, + "messages": [ + { + "etag": "\"message:01M5X09V1T11B2MR912QBBWXHP:1\"", + "id": "01M5X09V1T11B2MR912QBBWXHP", + "author": "danielroe-bot", + "identity": { + "kind": "account", + "account_id": "01M5WYRRVZNA1TXNET6KE4Q3WX", + "display_name": null, + "avatar_url": "https://avatars.githubusercontent.com/u/57801166?v=4", + "handles": [ + { + "provider": "github", + "handle": "danielroe-bot", + "is_primary": true + } + ] + }, + "created_at": "2026-10-26T21:01:45.399Z", + "body": "A comment from run 20261026210133.", + "replies": [] + } + ], + "eventCursor": "1" + } + } +} diff --git a/test/fixtures/entire/recorded/entire.com-writes/steps/issue-edit-comment/02-get-N-discussions.json b/test/fixtures/entire/recorded/entire.com-writes/steps/issue-edit-comment/02-get-N-discussions.json new file mode 100644 index 000000000..35002c6ca --- /dev/null +++ b/test/fixtures/entire/recorded/entire.com-writes/steps/issue-edit-comment/02-get-N-discussions.json @@ -0,0 +1,76 @@ +{ + "request": { + "method": "GET", + "url": "https://aws-eu-central-1.api.entire.io/api/v1/et/forges-scratch/trails/13/discussions?pageSize=100" + }, + "response": { + "status": 200, + "headers": { + "link": "; rel=\"describedBy\"" + }, + "body": { + "$schema": "https://aws-eu-central-1.api.entire.io/api/v1/schemas/DiscussionsListResponseBody.json", + "items": [ + { + "etag": "\"discussion:01M5X09V1QW77SKERM3TA6VTXC:1\"", + "id": "01M5X09V1QW77SKERM3TA6VTXC", + "trail_id": "01M5X09TE6P0R8TR8WPCVX7H6Y", + "title": "A comment from run 20261026210133.", + "kind": "discussion", + "resolved": false, + "resolved_by": null, + "resolved_by_identity": { + "kind": "unknown", + "account_id": null, + "display_name": null, + "avatar_url": null, + "handles": [] + }, + "resolved_at": null, + "created_by": "01M5WYRRVZNA1TXNET6KE4Q3WX", + "created_by_identity": { + "kind": "account", + "account_id": "01M5WYRRVZNA1TXNET6KE4Q3WX", + "display_name": null, + "avatar_url": "https://avatars.githubusercontent.com/u/57801166?v=4", + "handles": [ + { + "provider": "github", + "handle": "danielroe-bot", + "is_primary": true + } + ] + }, + "created_at": "2026-10-26T21:01:45.399Z", + "updated_at": "2026-10-26T21:01:45.399Z", + "last_message_at": "2026-10-26T21:01:45.399Z", + "last_message_author": "danielroe-bot", + "message_count": 1, + "participants": [ + { + "login": "danielroe-bot", + "actor_account_id": "01M5WYRRVZNA1TXNET6KE4Q3WX", + "identity": { + "kind": "account", + "account_id": "01M5WYRRVZNA1TXNET6KE4Q3WX", + "display_name": null, + "avatar_url": "https://avatars.githubusercontent.com/u/57801166?v=4", + "handles": [ + { + "provider": "github", + "handle": "danielroe-bot", + "is_primary": true + } + ] + } + } + ], + "review_comment_id": null, + "review_comment": null + } + ], + "nextPageToken": null, + "eventCursor": "1" + } + } +} diff --git a/test/fixtures/entire/recorded/entire.com-writes/steps/issue-edit-comment/03-patch-messages-01M5X09V1T11B2MR912QBBWXHP.json b/test/fixtures/entire/recorded/entire.com-writes/steps/issue-edit-comment/03-patch-messages-01M5X09V1T11B2MR912QBBWXHP.json new file mode 100644 index 000000000..3ecb64c8b --- /dev/null +++ b/test/fixtures/entire/recorded/entire.com-writes/steps/issue-edit-comment/03-patch-messages-01M5X09V1T11B2MR912QBBWXHP.json @@ -0,0 +1,40 @@ +{ + "request": { + "method": "PATCH", + "url": "https://aws-eu-central-1.api.entire.io/api/v1/et/forges-scratch/trails/13/discussions/01M5X09V1QW77SKERM3TA6VTXC/messages/01M5X09V1T11B2MR912QBBWXHP", + "body": { + "body": "An edited comment from run 20261026210133." + } + }, + "response": { + "status": 200, + "headers": { + "link": "; rel=\"describedBy\"", + "etag": "W/\"message:01M5X09V1T11B2MR912QBBWXHP:2\"" + }, + "body": { + "$schema": "https://aws-eu-central-1.api.entire.io/api/v1/schemas/TrailDiscussionMessageResponseBody.json", + "message": { + "etag": "\"message:01M5X09V1T11B2MR912QBBWXHP:2\"", + "id": "01M5X09V1T11B2MR912QBBWXHP", + "author": "danielroe-bot", + "identity": { + "kind": "account", + "account_id": "01M5WYRRVZNA1TXNET6KE4Q3WX", + "display_name": null, + "avatar_url": "https://avatars.githubusercontent.com/u/57801166?v=4", + "handles": [ + { + "provider": "github", + "handle": "danielroe-bot", + "is_primary": true + } + ] + }, + "created_at": "2026-10-26T21:01:45.399Z", + "body": "An edited comment from run 20261026210133.", + "replies": [] + } + } + } +} diff --git a/test/fixtures/entire/recorded/entire.com-writes/steps/issue-edit-comment/golden.json b/test/fixtures/entire/recorded/entire.com-writes/steps/issue-edit-comment/golden.json new file mode 100644 index 000000000..bb7133927 --- /dev/null +++ b/test/fixtures/entire/recorded/entire.com-writes/steps/issue-edit-comment/golden.json @@ -0,0 +1,35 @@ +{ + "ref": { + "forge": "entire", + "instance": "entire.com", + "thread": { + "forge": "entire", + "instance": "entire.com", + "repo": { + "forge": "entire", + "instance": "entire.com", + "owner": "forges-scratch", + "name": "", + "kind": "namespace" + }, + "kind": "issue", + "number": "13", + "externalId": "01M5X09TE6P0R8TR8WPCVX7H6Y" + }, + "id": "01M5X09V1T11B2MR912QBBWXHP" + }, + "body": "An edited comment from run 20261026210133.", + "author": { + "forge": "entire", + "instance": "entire.com", + "login": "danielroe-bot", + "id": "01M5WYRRVZNA1TXNET6KE4Q3WX", + "avatarUrl": "https://avatars.githubusercontent.com/u/57801166?v=4", + "isBotHint": false + }, + "createdAt": "", + "thread": { + "id": "01M5X09V1QW77SKERM3TA6VTXC", + "resolved": false + } +} diff --git a/test/fixtures/entire/recorded/entire.com-writes/steps/issue-edit-comment/step.json b/test/fixtures/entire/recorded/entire.com-writes/steps/issue-edit-comment/step.json new file mode 100644 index 000000000..bc41942f0 --- /dev/null +++ b/test/fixtures/entire/recorded/entire.com-writes/steps/issue-edit-comment/step.json @@ -0,0 +1,7 @@ +{ + "name": "issue edit comment", + "recordedAt": "2026-10-26T21:01:45.493Z", + "needs": [ + "issue comment" + ] +} diff --git a/test/fixtures/entire/recorded/entire.com-writes/steps/issue-get-comment/01-get-discussions-01M5X09V1QW77SKERM3TA6VTXC.json b/test/fixtures/entire/recorded/entire.com-writes/steps/issue-get-comment/01-get-discussions-01M5X09V1QW77SKERM3TA6VTXC.json new file mode 100644 index 000000000..5e0f3ab56 --- /dev/null +++ b/test/fixtures/entire/recorded/entire.com-writes/steps/issue-get-comment/01-get-discussions-01M5X09V1QW77SKERM3TA6VTXC.json @@ -0,0 +1,97 @@ +{ + "request": { + "method": "GET", + "url": "https://aws-eu-central-1.api.entire.io/api/v1/et/forges-scratch/trails/13/discussions/01M5X09V1QW77SKERM3TA6VTXC" + }, + "response": { + "status": 200, + "headers": { + "link": "; rel=\"describedBy\"", + "etag": "\"discussion:01M5X09V1QW77SKERM3TA6VTXC:2\"" + }, + "body": { + "$schema": "https://aws-eu-central-1.api.entire.io/api/v1/schemas/DiscussionDetailResponseBody.json", + "discussion": { + "etag": "\"discussion:01M5X09V1QW77SKERM3TA6VTXC:2\"", + "id": "01M5X09V1QW77SKERM3TA6VTXC", + "trail_id": "01M5X09TE6P0R8TR8WPCVX7H6Y", + "title": "An edited comment from run 20261026210133.", + "kind": "discussion", + "resolved": false, + "resolved_by": null, + "resolved_by_identity": { + "kind": "unknown", + "account_id": null, + "display_name": null, + "avatar_url": null, + "handles": [] + }, + "resolved_at": null, + "created_by": "01M5WYRRVZNA1TXNET6KE4Q3WX", + "created_by_identity": { + "kind": "account", + "account_id": "01M5WYRRVZNA1TXNET6KE4Q3WX", + "display_name": null, + "avatar_url": "https://avatars.githubusercontent.com/u/57801166?v=4", + "handles": [ + { + "provider": "github", + "handle": "danielroe-bot", + "is_primary": true + } + ] + }, + "created_at": "2026-10-26T21:01:45.399Z", + "updated_at": "2026-10-26T21:01:46.409Z", + "last_message_at": "2026-10-26T21:01:45.399Z", + "last_message_author": "danielroe-bot", + "message_count": 1, + "participants": [ + { + "login": "danielroe-bot", + "actor_account_id": "01M5WYRRVZNA1TXNET6KE4Q3WX", + "identity": { + "kind": "account", + "account_id": "01M5WYRRVZNA1TXNET6KE4Q3WX", + "display_name": null, + "avatar_url": "https://avatars.githubusercontent.com/u/57801166?v=4", + "handles": [ + { + "provider": "github", + "handle": "danielroe-bot", + "is_primary": true + } + ] + } + } + ], + "review_comment_id": null, + "review_comment": null + }, + "messages": [ + { + "etag": "\"message:01M5X09V1T11B2MR912QBBWXHP:2\"", + "id": "01M5X09V1T11B2MR912QBBWXHP", + "author": "danielroe-bot", + "identity": { + "kind": "account", + "account_id": "01M5WYRRVZNA1TXNET6KE4Q3WX", + "display_name": null, + "avatar_url": "https://avatars.githubusercontent.com/u/57801166?v=4", + "handles": [ + { + "provider": "github", + "handle": "danielroe-bot", + "is_primary": true + } + ] + }, + "created_at": "2026-10-26T21:01:45.399Z", + "body": "An edited comment from run 20261026210133.", + "replies": [] + } + ], + "eventCursor": "2" + } + } +} diff --git a/test/fixtures/entire/recorded/entire.com-writes/steps/issue-get-comment/02-get-N-discussions.json b/test/fixtures/entire/recorded/entire.com-writes/steps/issue-get-comment/02-get-N-discussions.json new file mode 100644 index 000000000..b03afc264 --- /dev/null +++ b/test/fixtures/entire/recorded/entire.com-writes/steps/issue-get-comment/02-get-N-discussions.json @@ -0,0 +1,76 @@ +{ + "request": { + "method": "GET", + "url": "https://aws-eu-central-1.api.entire.io/api/v1/et/forges-scratch/trails/13/discussions?pageSize=100" + }, + "response": { + "status": 200, + "headers": { + "link": "; rel=\"describedBy\"" + }, + "body": { + "$schema": "https://aws-eu-central-1.api.entire.io/api/v1/schemas/DiscussionsListResponseBody.json", + "items": [ + { + "etag": "\"discussion:01M5X09V1QW77SKERM3TA6VTXC:2\"", + "id": "01M5X09V1QW77SKERM3TA6VTXC", + "trail_id": "01M5X09TE6P0R8TR8WPCVX7H6Y", + "title": "An edited comment from run 20261026210133.", + "kind": "discussion", + "resolved": false, + "resolved_by": null, + "resolved_by_identity": { + "kind": "unknown", + "account_id": null, + "display_name": null, + "avatar_url": null, + "handles": [] + }, + "resolved_at": null, + "created_by": "01M5WYRRVZNA1TXNET6KE4Q3WX", + "created_by_identity": { + "kind": "account", + "account_id": "01M5WYRRVZNA1TXNET6KE4Q3WX", + "display_name": null, + "avatar_url": "https://avatars.githubusercontent.com/u/57801166?v=4", + "handles": [ + { + "provider": "github", + "handle": "danielroe-bot", + "is_primary": true + } + ] + }, + "created_at": "2026-10-26T21:01:45.399Z", + "updated_at": "2026-10-26T21:01:46.409Z", + "last_message_at": "2026-10-26T21:01:45.399Z", + "last_message_author": "danielroe-bot", + "message_count": 1, + "participants": [ + { + "login": "danielroe-bot", + "actor_account_id": "01M5WYRRVZNA1TXNET6KE4Q3WX", + "identity": { + "kind": "account", + "account_id": "01M5WYRRVZNA1TXNET6KE4Q3WX", + "display_name": null, + "avatar_url": "https://avatars.githubusercontent.com/u/57801166?v=4", + "handles": [ + { + "provider": "github", + "handle": "danielroe-bot", + "is_primary": true + } + ] + } + } + ], + "review_comment_id": null, + "review_comment": null + } + ], + "nextPageToken": null, + "eventCursor": "2" + } + } +} diff --git a/test/fixtures/entire/recorded/entire.com-writes/steps/issue-get-comment/golden.json b/test/fixtures/entire/recorded/entire.com-writes/steps/issue-get-comment/golden.json new file mode 100644 index 000000000..bb7133927 --- /dev/null +++ b/test/fixtures/entire/recorded/entire.com-writes/steps/issue-get-comment/golden.json @@ -0,0 +1,35 @@ +{ + "ref": { + "forge": "entire", + "instance": "entire.com", + "thread": { + "forge": "entire", + "instance": "entire.com", + "repo": { + "forge": "entire", + "instance": "entire.com", + "owner": "forges-scratch", + "name": "", + "kind": "namespace" + }, + "kind": "issue", + "number": "13", + "externalId": "01M5X09TE6P0R8TR8WPCVX7H6Y" + }, + "id": "01M5X09V1T11B2MR912QBBWXHP" + }, + "body": "An edited comment from run 20261026210133.", + "author": { + "forge": "entire", + "instance": "entire.com", + "login": "danielroe-bot", + "id": "01M5WYRRVZNA1TXNET6KE4Q3WX", + "avatarUrl": "https://avatars.githubusercontent.com/u/57801166?v=4", + "isBotHint": false + }, + "createdAt": "", + "thread": { + "id": "01M5X09V1QW77SKERM3TA6VTXC", + "resolved": false + } +} diff --git a/test/fixtures/entire/recorded/entire.com-writes/steps/issue-get-comment/step.json b/test/fixtures/entire/recorded/entire.com-writes/steps/issue-get-comment/step.json new file mode 100644 index 000000000..1b3842cf3 --- /dev/null +++ b/test/fixtures/entire/recorded/entire.com-writes/steps/issue-get-comment/step.json @@ -0,0 +1,7 @@ +{ + "name": "issue get comment", + "recordedAt": "2026-10-26T21:01:46.502Z", + "needs": [ + "issue comment" + ] +} diff --git a/test/fixtures/entire/recorded/entire.com-writes/steps/issue-reopen/01-patch-trails-N.json b/test/fixtures/entire/recorded/entire.com-writes/steps/issue-reopen/01-patch-trails-N.json new file mode 100644 index 000000000..94d15a2e0 --- /dev/null +++ b/test/fixtures/entire/recorded/entire.com-writes/steps/issue-reopen/01-patch-trails-N.json @@ -0,0 +1,127 @@ +{ + "request": { + "method": "PATCH", + "url": "https://aws-eu-central-1.api.entire.io/api/v1/et/forges-scratch/trails/13", + "body": { + "status": "open" + } + }, + "response": { + "status": 200, + "headers": { + "link": "; rel=\"describedBy\"", + "etag": "W/\"2026-10-26T21:01:53.8364Z\"" + }, + "body": { + "$schema": "https://aws-eu-central-1.api.entire.io/api/v1/schemas/TrailResponse.json", + "capabilities": { + "canEdit": true, + "canManageScope": true + }, + "project": { + "primaryProcessingCell": "aws-eu-central-1", + "id": "01M5WYSMPPYRBB13ZB20H7NK2Q", + "name": "forges-scratch", + "provider": "entire", + "reference": { + "forge": "et", + "project": "forges-scratch" + }, + "jurisdiction": "eu", + "capabilities": { + "canManageTrails": true + } + }, + "author": { + "accountId": "01M5WYRRVZNA1TXNET6KE4Q3WX", + "login": "danielroe-bot", + "displayName": "", + "avatarUrl": "https://avatars.githubusercontent.com/u/57801166?v=4", + "identity": { + "kind": "account", + "account_id": "01M5WYRRVZNA1TXNET6KE4Q3WX", + "display_name": null, + "avatar_url": "https://avatars.githubusercontent.com/u/57801166?v=4", + "handles": [ + { + "provider": "github", + "handle": "danielroe-bot", + "is_primary": true + } + ] + } + }, + "assigneeProfiles": [ + { + "accountId": "01M5WYRRVZNA1TXNET6KE4Q3WX", + "login": "danielroe-bot", + "displayName": "", + "avatarUrl": "https://avatars.githubusercontent.com/u/57801166?v=4", + "identity": { + "kind": "account", + "account_id": "01M5WYRRVZNA1TXNET6KE4Q3WX", + "display_name": null, + "avatar_url": "https://avatars.githubusercontent.com/u/57801166?v=4", + "handles": [ + { + "provider": "github", + "handle": "danielroe-bot", + "is_primary": true + } + ] + } + } + ], + "id": "01M5X09TE6P0R8TR8WPCVX7H6Y", + "projectId": "01M5WYSMPPYRBB13ZB20H7NK2Q", + "number": 13, + "url": "https://entire.com/et/forges-scratch/-/trails/13", + "title": "forges fixture 20261026210133: issue, edited", + "body": "Edited by run 20261026210133.", + "bodyDocument": { + "id": "", + "document_key": "project-trail:01M5X09TE6P0R8TR8WPCVX7H6Y:body", + "schema_version": 1, + "content_json": { + "type": "doc", + "content": [ + { + "type": "paragraph", + "content": [ + { + "type": "text", + "text": "Edited by run 20261026210133." + } + ] + } + ] + }, + "text_snapshot": "Edited by run 20261026210133.", + "updated_at": "2026-10-26T21:01:53.836Z", + "etag": "" + }, + "status": "open", + "phase": "planning", + "metadata": {}, + "type": "task", + "priority": "none", + "assignees": [ + "ulid:01M5WYRRVZNA1TXNET6KE4Q3WX" + ], + "assigneeAccountIds": [ + "01M5WYRRVZNA1TXNET6KE4Q3WX" + ], + "repoIds": [ + "01M5WYSQC41P69DTXEMZ0TE5YK" + ], + "authorAccountId": "01M5WYRRVZNA1TXNET6KE4Q3WX", + "createdAt": "2026-10-26T21:01:44.774Z", + "metadataUpdatedAt": "2026-10-26T21:01:53.836Z", + "closedAt": null, + "lastVisitedAt": null, + "lastActivityAt": "2026-10-26T21:01:53.836Z", + "changes": [], + "isPossiblyPartial": true + } + } +} diff --git a/test/fixtures/entire/recorded/entire.com-writes/steps/issue-reopen/golden.json b/test/fixtures/entire/recorded/entire.com-writes/steps/issue-reopen/golden.json new file mode 100644 index 000000000..4f2d42c71 --- /dev/null +++ b/test/fixtures/entire/recorded/entire.com-writes/steps/issue-reopen/golden.json @@ -0,0 +1,50 @@ +{ + "ref": { + "forge": "entire", + "instance": "entire.com", + "repo": { + "forge": "entire", + "instance": "entire.com", + "owner": "forges-scratch", + "name": "", + "kind": "namespace" + }, + "kind": "issue", + "number": "13", + "externalId": "01M5X09TE6P0R8TR8WPCVX7H6Y" + }, + "kind": "issue", + "title": "forges fixture 20261026210133: issue, edited", + "body": "Edited by run 20261026210133.", + "state": "open", + "stateRaw": "open", + "isDraft": false, + "author": { + "forge": "entire", + "instance": "entire.com", + "login": "danielroe-bot", + "id": "01M5WYRRVZNA1TXNET6KE4Q3WX", + "avatarUrl": "https://avatars.githubusercontent.com/u/57801166?v=4", + "isBotHint": false + }, + "assignees": [ + { + "forge": "entire", + "instance": "entire.com", + "login": "danielroe-bot", + "id": "01M5WYRRVZNA1TXNET6KE4Q3WX", + "avatarUrl": "https://avatars.githubusercontent.com/u/57801166?v=4", + "isBotHint": false + } + ], + "reviewers": [], + "labels": [], + "url": "https://entire.com/et/forges-scratch/-/trails/13", + "createdAt": "", + "updatedAt": "", + "lastActivityAt": "", + "issueType": { + "id": "task", + "name": "task" + } +} diff --git a/test/fixtures/entire/recorded/entire.com-writes/steps/issue-reopen/step.json b/test/fixtures/entire/recorded/entire.com-writes/steps/issue-reopen/step.json new file mode 100644 index 000000000..00f1daa82 --- /dev/null +++ b/test/fixtures/entire/recorded/entire.com-writes/steps/issue-reopen/step.json @@ -0,0 +1,7 @@ +{ + "name": "issue reopen", + "recordedAt": "2026-10-26T21:01:52.889Z", + "needs": [ + "create issue" + ] +} diff --git a/test/fixtures/entire/recorded/entire.com-writes/steps/issue-update/01-patch-trails-N.json b/test/fixtures/entire/recorded/entire.com-writes/steps/issue-update/01-patch-trails-N.json new file mode 100644 index 000000000..ac007a9de --- /dev/null +++ b/test/fixtures/entire/recorded/entire.com-writes/steps/issue-update/01-patch-trails-N.json @@ -0,0 +1,128 @@ +{ + "request": { + "method": "PATCH", + "url": "https://aws-eu-central-1.api.entire.io/api/v1/et/forges-scratch/trails/13", + "body": { + "title": "forges fixture 20261026210133: issue, edited", + "body": "Edited by run 20261026210133." + } + }, + "response": { + "status": 200, + "headers": { + "link": "; rel=\"describedBy\"", + "etag": "W/\"2026-10-26T21:01:50.840469Z\"" + }, + "body": { + "$schema": "https://aws-eu-central-1.api.entire.io/api/v1/schemas/TrailResponse.json", + "capabilities": { + "canEdit": true, + "canManageScope": true + }, + "project": { + "primaryProcessingCell": "aws-eu-central-1", + "id": "01M5WYSMPPYRBB13ZB20H7NK2Q", + "name": "forges-scratch", + "provider": "entire", + "reference": { + "forge": "et", + "project": "forges-scratch" + }, + "jurisdiction": "eu", + "capabilities": { + "canManageTrails": true + } + }, + "author": { + "accountId": "01M5WYRRVZNA1TXNET6KE4Q3WX", + "login": "danielroe-bot", + "displayName": "", + "avatarUrl": "https://avatars.githubusercontent.com/u/57801166?v=4", + "identity": { + "kind": "account", + "account_id": "01M5WYRRVZNA1TXNET6KE4Q3WX", + "display_name": null, + "avatar_url": "https://avatars.githubusercontent.com/u/57801166?v=4", + "handles": [ + { + "provider": "github", + "handle": "danielroe-bot", + "is_primary": true + } + ] + } + }, + "assigneeProfiles": [ + { + "accountId": "01M5WYRRVZNA1TXNET6KE4Q3WX", + "login": "danielroe-bot", + "displayName": "", + "avatarUrl": "https://avatars.githubusercontent.com/u/57801166?v=4", + "identity": { + "kind": "account", + "account_id": "01M5WYRRVZNA1TXNET6KE4Q3WX", + "display_name": null, + "avatar_url": "https://avatars.githubusercontent.com/u/57801166?v=4", + "handles": [ + { + "provider": "github", + "handle": "danielroe-bot", + "is_primary": true + } + ] + } + } + ], + "id": "01M5X09TE6P0R8TR8WPCVX7H6Y", + "projectId": "01M5WYSMPPYRBB13ZB20H7NK2Q", + "number": 13, + "url": "https://entire.com/et/forges-scratch/-/trails/13", + "title": "forges fixture 20261026210133: issue, edited", + "body": "Edited by run 20261026210133.", + "bodyDocument": { + "id": "", + "document_key": "project-trail:01M5X09TE6P0R8TR8WPCVX7H6Y:body", + "schema_version": 1, + "content_json": { + "type": "doc", + "content": [ + { + "type": "paragraph", + "content": [ + { + "type": "text", + "text": "Edited by run 20261026210133." + } + ] + } + ] + }, + "text_snapshot": "Edited by run 20261026210133.", + "updated_at": "2026-10-26T21:01:50.840Z", + "etag": "" + }, + "status": "open", + "phase": "planning", + "metadata": {}, + "type": "task", + "priority": "none", + "assignees": [ + "ulid:01M5WYRRVZNA1TXNET6KE4Q3WX" + ], + "assigneeAccountIds": [ + "01M5WYRRVZNA1TXNET6KE4Q3WX" + ], + "repoIds": [ + "01M5WYSQC41P69DTXEMZ0TE5YK" + ], + "authorAccountId": "01M5WYRRVZNA1TXNET6KE4Q3WX", + "createdAt": "2026-10-26T21:01:44.774Z", + "metadataUpdatedAt": "2026-10-26T21:01:50.840Z", + "closedAt": null, + "lastVisitedAt": null, + "lastActivityAt": "2026-10-26T21:01:50.840Z", + "changes": [], + "isPossiblyPartial": true + } + } +} diff --git a/test/fixtures/entire/recorded/entire.com-writes/steps/issue-update/golden.json b/test/fixtures/entire/recorded/entire.com-writes/steps/issue-update/golden.json new file mode 100644 index 000000000..4f2d42c71 --- /dev/null +++ b/test/fixtures/entire/recorded/entire.com-writes/steps/issue-update/golden.json @@ -0,0 +1,50 @@ +{ + "ref": { + "forge": "entire", + "instance": "entire.com", + "repo": { + "forge": "entire", + "instance": "entire.com", + "owner": "forges-scratch", + "name": "", + "kind": "namespace" + }, + "kind": "issue", + "number": "13", + "externalId": "01M5X09TE6P0R8TR8WPCVX7H6Y" + }, + "kind": "issue", + "title": "forges fixture 20261026210133: issue, edited", + "body": "Edited by run 20261026210133.", + "state": "open", + "stateRaw": "open", + "isDraft": false, + "author": { + "forge": "entire", + "instance": "entire.com", + "login": "danielroe-bot", + "id": "01M5WYRRVZNA1TXNET6KE4Q3WX", + "avatarUrl": "https://avatars.githubusercontent.com/u/57801166?v=4", + "isBotHint": false + }, + "assignees": [ + { + "forge": "entire", + "instance": "entire.com", + "login": "danielroe-bot", + "id": "01M5WYRRVZNA1TXNET6KE4Q3WX", + "avatarUrl": "https://avatars.githubusercontent.com/u/57801166?v=4", + "isBotHint": false + } + ], + "reviewers": [], + "labels": [], + "url": "https://entire.com/et/forges-scratch/-/trails/13", + "createdAt": "", + "updatedAt": "", + "lastActivityAt": "", + "issueType": { + "id": "task", + "name": "task" + } +} diff --git a/test/fixtures/entire/recorded/entire.com-writes/steps/issue-update/step.json b/test/fixtures/entire/recorded/entire.com-writes/steps/issue-update/step.json new file mode 100644 index 000000000..ee8526e1b --- /dev/null +++ b/test/fixtures/entire/recorded/entire.com-writes/steps/issue-update/step.json @@ -0,0 +1,7 @@ +{ + "name": "issue update", + "recordedAt": "2026-10-26T21:01:49.902Z", + "needs": [ + "create issue" + ] +} diff --git a/test/fixtures/entire/recorded/entire.com-writes/steps/issue-upsert-comment/01-get-discussions-01M5X09V1QW77SKERM3TA6VTXC.json b/test/fixtures/entire/recorded/entire.com-writes/steps/issue-upsert-comment/01-get-discussions-01M5X09V1QW77SKERM3TA6VTXC.json new file mode 100644 index 000000000..5e0f3ab56 --- /dev/null +++ b/test/fixtures/entire/recorded/entire.com-writes/steps/issue-upsert-comment/01-get-discussions-01M5X09V1QW77SKERM3TA6VTXC.json @@ -0,0 +1,97 @@ +{ + "request": { + "method": "GET", + "url": "https://aws-eu-central-1.api.entire.io/api/v1/et/forges-scratch/trails/13/discussions/01M5X09V1QW77SKERM3TA6VTXC" + }, + "response": { + "status": 200, + "headers": { + "link": "; rel=\"describedBy\"", + "etag": "\"discussion:01M5X09V1QW77SKERM3TA6VTXC:2\"" + }, + "body": { + "$schema": "https://aws-eu-central-1.api.entire.io/api/v1/schemas/DiscussionDetailResponseBody.json", + "discussion": { + "etag": "\"discussion:01M5X09V1QW77SKERM3TA6VTXC:2\"", + "id": "01M5X09V1QW77SKERM3TA6VTXC", + "trail_id": "01M5X09TE6P0R8TR8WPCVX7H6Y", + "title": "An edited comment from run 20261026210133.", + "kind": "discussion", + "resolved": false, + "resolved_by": null, + "resolved_by_identity": { + "kind": "unknown", + "account_id": null, + "display_name": null, + "avatar_url": null, + "handles": [] + }, + "resolved_at": null, + "created_by": "01M5WYRRVZNA1TXNET6KE4Q3WX", + "created_by_identity": { + "kind": "account", + "account_id": "01M5WYRRVZNA1TXNET6KE4Q3WX", + "display_name": null, + "avatar_url": "https://avatars.githubusercontent.com/u/57801166?v=4", + "handles": [ + { + "provider": "github", + "handle": "danielroe-bot", + "is_primary": true + } + ] + }, + "created_at": "2026-10-26T21:01:45.399Z", + "updated_at": "2026-10-26T21:01:46.409Z", + "last_message_at": "2026-10-26T21:01:45.399Z", + "last_message_author": "danielroe-bot", + "message_count": 1, + "participants": [ + { + "login": "danielroe-bot", + "actor_account_id": "01M5WYRRVZNA1TXNET6KE4Q3WX", + "identity": { + "kind": "account", + "account_id": "01M5WYRRVZNA1TXNET6KE4Q3WX", + "display_name": null, + "avatar_url": "https://avatars.githubusercontent.com/u/57801166?v=4", + "handles": [ + { + "provider": "github", + "handle": "danielroe-bot", + "is_primary": true + } + ] + } + } + ], + "review_comment_id": null, + "review_comment": null + }, + "messages": [ + { + "etag": "\"message:01M5X09V1T11B2MR912QBBWXHP:2\"", + "id": "01M5X09V1T11B2MR912QBBWXHP", + "author": "danielroe-bot", + "identity": { + "kind": "account", + "account_id": "01M5WYRRVZNA1TXNET6KE4Q3WX", + "display_name": null, + "avatar_url": "https://avatars.githubusercontent.com/u/57801166?v=4", + "handles": [ + { + "provider": "github", + "handle": "danielroe-bot", + "is_primary": true + } + ] + }, + "created_at": "2026-10-26T21:01:45.399Z", + "body": "An edited comment from run 20261026210133.", + "replies": [] + } + ], + "eventCursor": "2" + } + } +} diff --git a/test/fixtures/entire/recorded/entire.com-writes/steps/issue-upsert-comment/02-get-N-discussions.json b/test/fixtures/entire/recorded/entire.com-writes/steps/issue-upsert-comment/02-get-N-discussions.json new file mode 100644 index 000000000..b03afc264 --- /dev/null +++ b/test/fixtures/entire/recorded/entire.com-writes/steps/issue-upsert-comment/02-get-N-discussions.json @@ -0,0 +1,76 @@ +{ + "request": { + "method": "GET", + "url": "https://aws-eu-central-1.api.entire.io/api/v1/et/forges-scratch/trails/13/discussions?pageSize=100" + }, + "response": { + "status": 200, + "headers": { + "link": "; rel=\"describedBy\"" + }, + "body": { + "$schema": "https://aws-eu-central-1.api.entire.io/api/v1/schemas/DiscussionsListResponseBody.json", + "items": [ + { + "etag": "\"discussion:01M5X09V1QW77SKERM3TA6VTXC:2\"", + "id": "01M5X09V1QW77SKERM3TA6VTXC", + "trail_id": "01M5X09TE6P0R8TR8WPCVX7H6Y", + "title": "An edited comment from run 20261026210133.", + "kind": "discussion", + "resolved": false, + "resolved_by": null, + "resolved_by_identity": { + "kind": "unknown", + "account_id": null, + "display_name": null, + "avatar_url": null, + "handles": [] + }, + "resolved_at": null, + "created_by": "01M5WYRRVZNA1TXNET6KE4Q3WX", + "created_by_identity": { + "kind": "account", + "account_id": "01M5WYRRVZNA1TXNET6KE4Q3WX", + "display_name": null, + "avatar_url": "https://avatars.githubusercontent.com/u/57801166?v=4", + "handles": [ + { + "provider": "github", + "handle": "danielroe-bot", + "is_primary": true + } + ] + }, + "created_at": "2026-10-26T21:01:45.399Z", + "updated_at": "2026-10-26T21:01:46.409Z", + "last_message_at": "2026-10-26T21:01:45.399Z", + "last_message_author": "danielroe-bot", + "message_count": 1, + "participants": [ + { + "login": "danielroe-bot", + "actor_account_id": "01M5WYRRVZNA1TXNET6KE4Q3WX", + "identity": { + "kind": "account", + "account_id": "01M5WYRRVZNA1TXNET6KE4Q3WX", + "display_name": null, + "avatar_url": "https://avatars.githubusercontent.com/u/57801166?v=4", + "handles": [ + { + "provider": "github", + "handle": "danielroe-bot", + "is_primary": true + } + ] + } + } + ], + "review_comment_id": null, + "review_comment": null + } + ], + "nextPageToken": null, + "eventCursor": "2" + } + } +} diff --git a/test/fixtures/entire/recorded/entire.com-writes/steps/issue-upsert-comment/03-post-N-discussions.json b/test/fixtures/entire/recorded/entire.com-writes/steps/issue-upsert-comment/03-post-N-discussions.json new file mode 100644 index 000000000..d15d7c983 --- /dev/null +++ b/test/fixtures/entire/recorded/entire.com-writes/steps/issue-upsert-comment/03-post-N-discussions.json @@ -0,0 +1,98 @@ +{ + "request": { + "method": "POST", + "url": "https://aws-eu-central-1.api.entire.io/api/v1/et/forges-scratch/trails/13/discussions", + "body": { + "body": "An upserted comment from run 20261026210133.\n\n" + } + }, + "response": { + "status": 201, + "headers": { + "link": "; rel=\"describedBy\"", + "etag": "\"discussion:01M5X09X6MW0ZY9BGSJQF9EP7F:1\"", + "location": "https://aws-eu-central-1.api.entire.io/api/v1/et/forges-scratch/trails/01M5X09TE6P0R8TR8WPCVX7H6Y/discussions/01M5X09X6MW0ZY9BGSJQF9EP7F" + }, + "body": { + "$schema": "https://aws-eu-central-1.api.entire.io/api/v1/schemas/DiscussionCreateResponseBody.json", + "discussion": { + "etag": "\"discussion:01M5X09X6MW0ZY9BGSJQF9EP7F:1\"", + "id": "01M5X09X6MW0ZY9BGSJQF9EP7F", + "trail_id": "01M5X09TE6P0R8TR8WPCVX7H6Y", + "title": "An upserted comment from run 20261026210133. ", + "kind": "discussion", + "resolved": false, + "resolved_by": null, + "resolved_by_identity": { + "kind": "unknown", + "account_id": null, + "display_name": null, + "avatar_url": null, + "handles": [] + }, + "resolved_at": null, + "created_by": "01M5WYRRVZNA1TXNET6KE4Q3WX", + "created_by_identity": { + "kind": "account", + "account_id": "01M5WYRRVZNA1TXNET6KE4Q3WX", + "display_name": null, + "avatar_url": "https://avatars.githubusercontent.com/u/57801166?v=4", + "handles": [ + { + "provider": "github", + "handle": "danielroe-bot", + "is_primary": true + } + ] + }, + "created_at": "2026-10-26T21:01:47.604Z", + "updated_at": "2026-10-26T21:01:47.604Z", + "last_message_at": "2026-10-26T21:01:47.604Z", + "last_message_author": "danielroe-bot", + "message_count": 1, + "participants": [ + { + "login": "danielroe-bot", + "actor_account_id": "01M5WYRRVZNA1TXNET6KE4Q3WX", + "identity": { + "kind": "account", + "account_id": "01M5WYRRVZNA1TXNET6KE4Q3WX", + "display_name": null, + "avatar_url": "https://avatars.githubusercontent.com/u/57801166?v=4", + "handles": [ + { + "provider": "github", + "handle": "danielroe-bot", + "is_primary": true + } + ] + } + } + ], + "review_comment_id": null, + "review_comment": null + }, + "message": { + "etag": "\"message:01M5X09X6NVNBBBXF1YX5PRNPV:1\"", + "id": "01M5X09X6NVNBBBXF1YX5PRNPV", + "author": "danielroe-bot", + "identity": { + "kind": "account", + "account_id": "01M5WYRRVZNA1TXNET6KE4Q3WX", + "display_name": null, + "avatar_url": "https://avatars.githubusercontent.com/u/57801166?v=4", + "handles": [ + { + "provider": "github", + "handle": "danielroe-bot", + "is_primary": true + } + ] + }, + "created_at": "2026-10-26T21:01:47.604Z", + "body": "An upserted comment from run 20261026210133.\n\n", + "replies": [] + } + } + } +} diff --git a/test/fixtures/entire/recorded/entire.com-writes/steps/issue-upsert-comment/golden.json b/test/fixtures/entire/recorded/entire.com-writes/steps/issue-upsert-comment/golden.json new file mode 100644 index 000000000..c4c4160f9 --- /dev/null +++ b/test/fixtures/entire/recorded/entire.com-writes/steps/issue-upsert-comment/golden.json @@ -0,0 +1,38 @@ +{ + "comment": { + "ref": { + "forge": "entire", + "instance": "entire.com", + "thread": { + "forge": "entire", + "instance": "entire.com", + "repo": { + "forge": "entire", + "instance": "entire.com", + "owner": "forges-scratch", + "name": "", + "kind": "namespace" + }, + "kind": "issue", + "number": "13", + "externalId": "01M5X09TE6P0R8TR8WPCVX7H6Y" + }, + "id": "01M5X09X6NVNBBBXF1YX5PRNPV" + }, + "body": "An upserted comment from run 20261026210133.\n\n", + "author": { + "forge": "entire", + "instance": "entire.com", + "login": "danielroe-bot", + "id": "01M5WYRRVZNA1TXNET6KE4Q3WX", + "avatarUrl": "https://avatars.githubusercontent.com/u/57801166?v=4", + "isBotHint": false + }, + "createdAt": "", + "thread": { + "id": "01M5X09X6MW0ZY9BGSJQF9EP7F", + "resolved": false + } + }, + "created": true +} diff --git a/test/fixtures/entire/recorded/entire.com-writes/steps/issue-upsert-comment/step.json b/test/fixtures/entire/recorded/entire.com-writes/steps/issue-upsert-comment/step.json new file mode 100644 index 000000000..3b694f681 --- /dev/null +++ b/test/fixtures/entire/recorded/entire.com-writes/steps/issue-upsert-comment/step.json @@ -0,0 +1,7 @@ +{ + "name": "issue upsert comment", + "recordedAt": "2026-10-26T21:01:46.990Z", + "needs": [ + "create issue" + ] +} diff --git a/test/fixtures/entire/recorded/entire.com-writes/steps/mention-author/01-get-repos-01M5WYSQC41P69DTXEMZ0TE5YK.json b/test/fixtures/entire/recorded/entire.com-writes/steps/mention-author/01-get-repos-01M5WYSQC41P69DTXEMZ0TE5YK.json new file mode 100644 index 000000000..1b66e5639 --- /dev/null +++ b/test/fixtures/entire/recorded/entire.com-writes/steps/mention-author/01-get-repos-01M5WYSQC41P69DTXEMZ0TE5YK.json @@ -0,0 +1,42 @@ +{ + "request": { + "method": "GET", + "url": "https://aws-eu-central-1.api.entire.io/api/v1/repos/01M5WYSQC41P69DTXEMZ0TE5YK" + }, + "response": { + "status": 200, + "headers": { + "link": "; rel=\"describedBy\"" + }, + "body": { + "$schema": "https://aws-eu-central-1.api.entire.io/api/v1/schemas/RepoListItem.json", + "owning_project_id": "01M5WYSMPPYRBB13ZB20H7NK2Q", + "id": "01M5WYSQC41P69DTXEMZ0TE5YK", + "github_id": 0, + "name": "forges-fixtures", + "full_name": "forges-scratch/forges-fixtures", + "description": null, + "html_url": null, + "stargazers_count": 0, + "language": null, + "private": false, + "archived": false, + "updated_at": "2026-10-26T21:02:17.328Z", + "default_branch": "main", + "permission": "write", + "capabilities": { + "data_role": "write", + "can_manage_settings": false, + "can_manage_access": false + }, + "checkpoint_count": 0, + "viewer_can_see_checkpoint_data": true, + "runners_enabled": false, + "trails_enabled": true, + "auto_run_on_push": false, + "public_sharing_enabled": false, + "open_pr_count": 0, + "repo_group_id": "01M5WYSQC42H6K0NWNZ6FYTSRQ" + } + } +} diff --git a/test/fixtures/entire/recorded/entire.com-writes/steps/mention-author/02-get-et-forges-scratch.json b/test/fixtures/entire/recorded/entire.com-writes/steps/mention-author/02-get-et-forges-scratch.json new file mode 100644 index 000000000..0cdc30069 --- /dev/null +++ b/test/fixtures/entire/recorded/entire.com-writes/steps/mention-author/02-get-et-forges-scratch.json @@ -0,0 +1,18 @@ +{ + "request": { + "method": "GET", + "url": "https://us.console.entire.io/api/v1/projects/resolve/et/forges-scratch" + }, + "response": { + "status": 403, + "headers": { + "link": "; rel=\"describedBy\"" + }, + "body": { + "$schema": "https://us.console.entire.io/api/v1/schemas/ErrorModel.json", + "title": "Forbidden", + "status": 403, + "detail": "project is not accessible" + } + } +} diff --git a/test/fixtures/entire/recorded/entire.com-writes/steps/mention-author/03-get-v1-repos.json b/test/fixtures/entire/recorded/entire.com-writes/steps/mention-author/03-get-v1-repos.json new file mode 100644 index 000000000..a9b7aa158 --- /dev/null +++ b/test/fixtures/entire/recorded/entire.com-writes/steps/mention-author/03-get-v1-repos.json @@ -0,0 +1,56 @@ +{ + "request": { + "method": "GET", + "url": "https://us.console.entire.io/api/v1/repos?org=forges-scratch&pageSize=1" + }, + "response": { + "status": 200, + "headers": { + "link": "; rel=\"describedBy\"" + }, + "body": { + "$schema": "https://us.console.entire.io/api/v1/schemas/ListReposOutputBody.json", + "repos": [ + { + "id": "01M5WYSQC41P69DTXEMZ0TE5YK", + "repoGroupId": "01M5WYSQC42H6K0NWNZ6FYTSRQ", + "jurisdiction": "eu", + "cell": "aws-eu-central-1", + "clusterSlug": "aws-eu-central-1", + "name": "forges-fixtures", + "full_name": "forges-scratch/forges-fixtures", + "org": "forges-scratch", + "provider": "entire", + "visibility": "public", + "permission": "write", + "placements": [ + { + "id": "01M5WYSQC41P69DTXEMZ0TE5YK", + "jurisdiction": "eu", + "cell": "aws-eu-central-1", + "apiBaseUrl": "https://aws-eu-central-1.api.entire.io", + "clusterSlug": "aws-eu-central-1", + "mirror": false, + "status": "ready" + } + ], + "primaries": { + "git_data": "entire:01M5WYSQC41P69DTXEMZ0TE5YK", + "processing": "01M5WYSQC41P69DTXEMZ0TE5YK", + "data_primary": { + "forge": "entire", + "repo_id": "01M5WYSQC41P69DTXEMZ0TE5YK" + }, + "processing_primary": { + "forge": "entire", + "repo_id": "01M5WYSQC41P69DTXEMZ0TE5YK" + } + }, + "lastPushedAt": "2026-10-26T21:02:14.258085Z" + } + ], + "truncated": false, + "candidatesIncomplete": false + } + } +} diff --git a/test/fixtures/entire/recorded/entire.com-writes/steps/mention-author/04-post-N-discussions.json b/test/fixtures/entire/recorded/entire.com-writes/steps/mention-author/04-post-N-discussions.json new file mode 100644 index 000000000..41957919a --- /dev/null +++ b/test/fixtures/entire/recorded/entire.com-writes/steps/mention-author/04-post-N-discussions.json @@ -0,0 +1,98 @@ +{ + "request": { + "method": "POST", + "url": "https://aws-eu-central-1.api.entire.io/api/v1/et/forges-scratch/trails/13/discussions", + "body": { + "body": "@danielroe-bot a mention from run 20261026210133." + } + }, + "response": { + "status": 201, + "headers": { + "link": "; rel=\"describedBy\"", + "etag": "\"discussion:01M5X0AXP2TZKAGWA9N0KWXVZQ:1\"", + "location": "https://aws-eu-central-1.api.entire.io/api/v1/et/forges-scratch/trails/01M5X09TE6P0R8TR8WPCVX7H6Y/discussions/01M5X0AXP2TZKAGWA9N0KWXVZQ" + }, + "body": { + "$schema": "https://aws-eu-central-1.api.entire.io/api/v1/schemas/DiscussionCreateResponseBody.json", + "discussion": { + "etag": "\"discussion:01M5X0AXP2TZKAGWA9N0KWXVZQ:1\"", + "id": "01M5X0AXP2TZKAGWA9N0KWXVZQ", + "trail_id": "01M5X09TE6P0R8TR8WPCVX7H6Y", + "title": "@danielroe-bot a mention from run 20261026210133.", + "kind": "discussion", + "resolved": false, + "resolved_by": null, + "resolved_by_identity": { + "kind": "unknown", + "account_id": null, + "display_name": null, + "avatar_url": null, + "handles": [] + }, + "resolved_at": null, + "created_by": "01M5WRP9RJ4GVR2PA5PCNYP1FC", + "created_by_identity": { + "kind": "account", + "account_id": "01M5WRP9RJ4GVR2PA5PCNYP1FC", + "display_name": "Daniel Roe", + "avatar_url": "https://avatars.githubusercontent.com/u/28706372?v=4", + "handles": [ + { + "provider": "github", + "handle": "danielroe", + "is_primary": true + } + ] + }, + "created_at": "2026-10-26T21:02:20.866Z", + "updated_at": "2026-10-26T21:02:20.866Z", + "last_message_at": "2026-10-26T21:02:20.866Z", + "last_message_author": "danielroe", + "message_count": 1, + "participants": [ + { + "login": "danielroe", + "actor_account_id": "01M5WRP9RJ4GVR2PA5PCNYP1FC", + "identity": { + "kind": "account", + "account_id": "01M5WRP9RJ4GVR2PA5PCNYP1FC", + "display_name": "Daniel Roe", + "avatar_url": "https://avatars.githubusercontent.com/u/28706372?v=4", + "handles": [ + { + "provider": "github", + "handle": "danielroe", + "is_primary": true + } + ] + } + } + ], + "review_comment_id": null, + "review_comment": null + }, + "message": { + "etag": "\"message:01M5X0AXP4NWPTC707S4SNYQYA:1\"", + "id": "01M5X0AXP4NWPTC707S4SNYQYA", + "author": "danielroe", + "identity": { + "kind": "account", + "account_id": "01M5WRP9RJ4GVR2PA5PCNYP1FC", + "display_name": "Daniel Roe", + "avatar_url": "https://avatars.githubusercontent.com/u/28706372?v=4", + "handles": [ + { + "provider": "github", + "handle": "danielroe", + "is_primary": true + } + ] + }, + "created_at": "2026-10-26T21:02:20.866Z", + "body": "@danielroe-bot a mention from run 20261026210133.", + "replies": [] + } + } + } +} diff --git a/test/fixtures/entire/recorded/entire.com-writes/steps/mention-author/golden.json b/test/fixtures/entire/recorded/entire.com-writes/steps/mention-author/golden.json new file mode 100644 index 000000000..caa7d2d32 --- /dev/null +++ b/test/fixtures/entire/recorded/entire.com-writes/steps/mention-author/golden.json @@ -0,0 +1,36 @@ +{ + "ref": { + "forge": "entire", + "instance": "entire.com", + "thread": { + "forge": "entire", + "instance": "entire.com", + "repo": { + "forge": "entire", + "instance": "entire.com", + "owner": "forges-scratch", + "name": "", + "kind": "namespace" + }, + "kind": "issue", + "number": "13", + "externalId": "01M5X09TE6P0R8TR8WPCVX7H6Y" + }, + "id": "01M5X0AXP4NWPTC707S4SNYQYA" + }, + "body": "@danielroe-bot a mention from run 20261026210133.", + "author": { + "forge": "entire", + "instance": "entire.com", + "login": "danielroe", + "id": "01M5WRP9RJ4GVR2PA5PCNYP1FC", + "name": "Daniel Roe", + "avatarUrl": "https://avatars.githubusercontent.com/u/28706372?v=4", + "isBotHint": false + }, + "createdAt": "", + "thread": { + "id": "01M5X0AXP2TZKAGWA9N0KWXVZQ", + "resolved": false + } +} diff --git a/test/fixtures/entire/recorded/entire.com-writes/steps/mention-author/step.json b/test/fixtures/entire/recorded/entire.com-writes/steps/mention-author/step.json new file mode 100644 index 000000000..d2423eca6 --- /dev/null +++ b/test/fixtures/entire/recorded/entire.com-writes/steps/mention-author/step.json @@ -0,0 +1,8 @@ +{ + "name": "mention author", + "recordedAt": "2026-10-26T21:02:18.553Z", + "needs": [ + "author", + "create issue" + ] +} diff --git a/test/fixtures/entire/recorded/entire.com-writes/steps/merge/01-post-N-merge.json b/test/fixtures/entire/recorded/entire.com-writes/steps/merge/01-post-N-merge.json new file mode 100644 index 000000000..554325def --- /dev/null +++ b/test/fixtures/entire/recorded/entire.com-writes/steps/merge/01-post-N-merge.json @@ -0,0 +1,22 @@ +{ + "request": { + "method": "POST", + "url": "https://aws-eu-central-1.api.entire.io/api/v1/repos/01M5WYSQC41P69DTXEMZ0TE5YK/trails/9/merge", + "body": { + "deleteBranch": false + } + }, + "response": { + "status": 200, + "headers": { + "link": "; rel=\"describedBy\"" + }, + "body": { + "$schema": "https://aws-eu-central-1.api.entire.io/api/v1/schemas/TrailMergeSubmitResponse.json", + "ok": true, + "mergeCommitSha": "", + "branchDeleted": false, + "branchKeptReason": "not_requested" + } + } +} diff --git a/test/fixtures/entire/recorded/entire.com-writes/steps/merge/golden.json b/test/fixtures/entire/recorded/entire.com-writes/steps/merge/golden.json new file mode 100644 index 000000000..38ac4b869 --- /dev/null +++ b/test/fixtures/entire/recorded/entire.com-writes/steps/merge/golden.json @@ -0,0 +1,3 @@ +{ + "status": "merged" +} diff --git a/test/fixtures/entire/recorded/entire.com-writes/steps/merge/step.json b/test/fixtures/entire/recorded/entire.com-writes/steps/merge/step.json new file mode 100644 index 000000000..5a0cdfbd5 --- /dev/null +++ b/test/fixtures/entire/recorded/entire.com-writes/steps/merge/step.json @@ -0,0 +1,7 @@ +{ + "name": "merge", + "recordedAt": "2026-10-26T21:02:13.541Z", + "needs": [ + "create pull" + ] +} diff --git a/test/fixtures/entire/recorded/entire.com-writes/steps/pending-review/01-post-N-approvals.json b/test/fixtures/entire/recorded/entire.com-writes/steps/pending-review/01-post-N-approvals.json new file mode 100644 index 000000000..9a8a5dc38 --- /dev/null +++ b/test/fixtures/entire/recorded/entire.com-writes/steps/pending-review/01-post-N-approvals.json @@ -0,0 +1,122 @@ +{ + "request": { + "method": "POST", + "url": "https://aws-eu-central-1.api.entire.io/api/v1/trails/et/forges-scratch/forges-fixtures/11/approvals", + "body": { + "event": "approve" + } + }, + "response": { + "status": 200, + "headers": { + "link": "; rel=\"describedBy\"" + }, + "body": { + "$schema": "https://aws-eu-central-1.api.entire.io/api/v1/schemas/TrailApprovalSubmitResponse.json", + "ok": true, + "approval": { + "id": "01M5X0AFJEGJWS360MQ5YST9XY", + "author": "danielroe", + "event": "approved", + "body": null, + "commit_sha": "f483a62c7214e4cead9ef1df09a663324a4825ae", + "created_at": "2026-10-26T21:02:06.414872128Z" + }, + "gates": { + "head_sha": "f483a62c7214e4cead9ef1df09a663324a4825ae", + "gates": [ + { + "reviewers": [ + { + "login": "danielroe", + "actor_account_id": "01M5WRP9RJ4GVR2PA5PCNYP1FC", + "state": "approved", + "reviewed_head_sha": "f483a62c7214e4cead9ef1df09a663324a4825ae", + "reason": null + } + ], + "runner_ids": [], + "id": "01M5X0AFK10B04M0VR1DS05YNN", + "gate_definition_id": "01M5WZ6B2HAMXBN2SZ9TP2N3SN", + "gate_key": "approvals", + "gate_type": "approvals", + "blocking": true, + "status": "passed", + "head_sha": "f483a62c7214e4cead9ef1df09a663324a4825ae", + "value": { + "approved": 1, + "changes_requested": false, + "config": { + "version": 1, + "min_reviewers": 1, + "allow_self_approval": false, + "dismiss_stale_approvals_on_push": false + }, + "required": 1, + "self_excluded": false, + "stale_dismissed": 0, + "total": 1 + }, + "rationale": "1 approval(s) recorded", + "created_at": "2026-10-26T21:02:06.433525857Z", + "completed_at": "2026-10-26T21:02:06.433525857Z", + "outcome": null, + "stale_reason": null, + "evaluated_at_sha": null, + "finding_count": null + }, + { + "reviewers": [], + "runner_ids": [], + "id": "", + "gate_definition_id": "01M5WZ6B2M8PSY34EM5YJGG6ZR", + "gate_key": "findings", + "gate_type": "findings", + "blocking": false, + "status": "pending", + "head_sha": "f483a62c7214e4cead9ef1df09a663324a4825ae", + "value": null, + "rationale": "Gate has not been evaluated yet", + "created_at": "2026-10-26T20:42:22.164428Z", + "completed_at": null, + "outcome": null, + "stale_reason": null, + "evaluated_at_sha": null, + "finding_count": null + }, + { + "reviewers": [], + "runner_ids": [], + "id": "01M5X0A6F5K3QMX8SRPSPC76YP", + "gate_definition_id": "01M5WZ6B2PC2X2BE023RX01WEY", + "gate_key": "up_to_date", + "gate_type": "up_to_date", + "blocking": true, + "status": "passed", + "head_sha": "f483a62c7214e4cead9ef1df09a663324a4825ae", + "value": { + "config": { + "version": 1, + "allow_behind_if_mergeable": false + }, + "behind_by": 0, + "compare_status": "ahead", + "comparison_status": "available" + }, + "rationale": "Up to date", + "created_at": "2026-10-26T21:01:57.093243Z", + "completed_at": "2026-10-26T21:01:57.093243Z", + "outcome": null, + "stale_reason": null, + "evaluated_at_sha": null, + "finding_count": null + } + ], + "blocking_failures": [], + "mergeable": true, + "evaluated_at": "2026-10-26T21:02:06.433525857Z", + "gates_enabled": true + } + } + } +} diff --git a/test/fixtures/entire/recorded/entire.com-writes/steps/pending-review/02-post-repos-resolve.json b/test/fixtures/entire/recorded/entire.com-writes/steps/pending-review/02-post-repos-resolve.json new file mode 100644 index 000000000..0fea65502 --- /dev/null +++ b/test/fixtures/entire/recorded/entire.com-writes/steps/pending-review/02-post-repos-resolve.json @@ -0,0 +1,56 @@ +{ + "request": { + "method": "POST", + "url": "https://us.console.entire.io/api/v1/repos/resolve", + "body": { + "repositories": [ + { + "fullName": "forges-scratch/forges-fixtures", + "provider": "entire" + } + ] + } + }, + "response": { + "status": 200, + "headers": { + "link": "; rel=\"describedBy\"" + }, + "body": { + "$schema": "https://us.console.entire.io/api/v1/schemas/ResolveReposResponse.json", + "resolutions": [ + { + "provider": "entire", + "requestedFullName": "forges-scratch/forges-fixtures", + "fullName": "forges-scratch/forges-fixtures", + "status": "ready", + "repoId": "01M5WYSQC41P69DTXEMZ0TE5YK", + "repoGroupId": "01M5WYSQC42H6K0NWNZ6FYTSRQ", + "placements": [ + { + "id": "01M5WYSQC41P69DTXEMZ0TE5YK", + "jurisdiction": "eu", + "cell": "aws-eu-central-1", + "apiBaseUrl": "https://aws-eu-central-1.api.entire.io", + "clusterSlug": "aws-eu-central-1", + "mirror": false, + "status": "ready" + } + ], + "primaries": { + "git_data": "entire:01M5WYSQC41P69DTXEMZ0TE5YK", + "processing": "01M5WYSQC41P69DTXEMZ0TE5YK", + "data_primary": { + "forge": "entire", + "repo_id": "01M5WYSQC41P69DTXEMZ0TE5YK" + }, + "processing_primary": { + "forge": "entire", + "repo_id": "01M5WYSQC41P69DTXEMZ0TE5YK" + } + } + } + ] + } + } +} diff --git a/test/fixtures/entire/recorded/entire.com-writes/steps/pending-review/golden.json b/test/fixtures/entire/recorded/entire.com-writes/steps/pending-review/golden.json new file mode 100644 index 000000000..41ac0ddef --- /dev/null +++ b/test/fixtures/entire/recorded/entire.com-writes/steps/pending-review/golden.json @@ -0,0 +1,31 @@ +{ + "ref": { + "forge": "entire", + "instance": "entire.com", + "thread": { + "forge": "entire", + "instance": "entire.com", + "repo": { + "forge": "entire", + "instance": "entire.com", + "owner": "forges-scratch", + "name": "forges-fixtures" + }, + "kind": "pull_request", + "number": "11", + "externalId": "01M5X0A6DAPK6DZNKVR2KEJNF8" + }, + "id": "01M5X0AFJEGJWS360MQ5YST9XY" + }, + "author": { + "forge": "entire", + "instance": "entire.com", + "login": "danielroe", + "id": "danielroe", + "isBotHint": false + }, + "state": "approved", + "stateRaw": "approved", + "submittedAt": "", + "comments": false +} diff --git a/test/fixtures/entire/recorded/entire.com-writes/steps/pending-review/step.json b/test/fixtures/entire/recorded/entire.com-writes/steps/pending-review/step.json new file mode 100644 index 000000000..9750c8e43 --- /dev/null +++ b/test/fixtures/entire/recorded/entire.com-writes/steps/pending-review/step.json @@ -0,0 +1,7 @@ +{ + "name": "pending review", + "recordedAt": "2026-10-26T21:02:04.927Z", + "needs": [ + "create third pull" + ] +} diff --git a/test/fixtures/entire/recorded/entire.com-writes/steps/pull-assign/01-get-trails-01M5X0A493RSBKDGYF0ZWVG8E9.json b/test/fixtures/entire/recorded/entire.com-writes/steps/pull-assign/01-get-trails-01M5X0A493RSBKDGYF0ZWVG8E9.json new file mode 100644 index 000000000..7ac6db04f --- /dev/null +++ b/test/fixtures/entire/recorded/entire.com-writes/steps/pull-assign/01-get-trails-01M5X0A493RSBKDGYF0ZWVG8E9.json @@ -0,0 +1,127 @@ +{ + "request": { + "method": "GET", + "url": "https://aws-eu-central-1.api.entire.io/api/v1/et/forges-scratch/trails/01M5X0A493RSBKDGYF0ZWVG8E9" + }, + "response": { + "status": 200, + "headers": { + "link": "; rel=\"describedBy\"", + "etag": "W/\"2026-10-26T21:01:54.892145Z\"" + }, + "body": { + "$schema": "https://aws-eu-central-1.api.entire.io/api/v1/schemas/TrailResponse.json", + "capabilities": { + "canEdit": true, + "canManageScope": true + }, + "project": { + "primaryProcessingCell": "aws-eu-central-1", + "id": "01M5WYSMPPYRBB13ZB20H7NK2Q", + "name": "forges-scratch", + "provider": "entire", + "reference": { + "forge": "et", + "project": "forges-scratch" + }, + "jurisdiction": "eu", + "capabilities": { + "canManageTrails": true + } + }, + "author": { + "accountId": "01M5WYRRVZNA1TXNET6KE4Q3WX", + "login": "danielroe-bot", + "displayName": "", + "avatarUrl": "https://avatars.githubusercontent.com/u/57801166?v=4", + "identity": { + "kind": "account", + "account_id": "01M5WYRRVZNA1TXNET6KE4Q3WX", + "display_name": null, + "avatar_url": "https://avatars.githubusercontent.com/u/57801166?v=4", + "handles": [ + { + "provider": "github", + "handle": "danielroe-bot", + "is_primary": true + } + ] + } + }, + "id": "01M5X0A493RSBKDGYF0ZWVG8E9", + "projectId": "01M5WYSMPPYRBB13ZB20H7NK2Q", + "number": 15, + "url": "https://entire.com/et/forges-scratch/-/trails/15", + "title": "forges fixture 20261026210133: pull 1", + "body": "Opened by run 20261026210133.", + "bodyDocument": { + "id": "", + "document_key": "project-trail:01M5X0A493RSBKDGYF0ZWVG8E9:body", + "schema_version": 1, + "content_json": { + "type": "doc", + "content": [ + { + "type": "paragraph", + "content": [ + { + "type": "text", + "text": "Opened by run 20261026210133." + } + ] + } + ] + }, + "text_snapshot": "Opened by run 20261026210133.", + "updated_at": "2026-10-26T21:01:54.892Z", + "etag": "" + }, + "status": "open", + "phase": "building", + "metadata": {}, + "type": "task", + "priority": "none", + "assignees": [], + "assigneeAccountIds": [], + "repoIds": [ + "01M5WYSQC41P69DTXEMZ0TE5YK" + ], + "authorAccountId": "01M5WYRRVZNA1TXNET6KE4Q3WX", + "createdAt": "2026-10-26T21:01:54.849Z", + "metadataUpdatedAt": "2026-10-26T21:01:54.892Z", + "closedAt": null, + "lastVisitedAt": null, + "lastActivityAt": "2026-10-26T21:02:01.374Z", + "changes": [ + { + "id": "01M5X0A49M70NAMJX878FD2QD1", + "repositoryId": "01M5WYSQC41P69DTXEMZ0TE5YK", + "repository": "forges-fixtures", + "branch": "forges-fixtures/20261026210133-1", + "originalBranch": "forges-fixtures/20261026210133-1", + "base": "main", + "number": 9, + "title": "forges fixture 20261026210133: pull 1", + "status": "open", + "hasCodeChanges": true, + "createdAt": "2026-10-26T21:01:54.849Z", + "updatedAt": "2026-10-26T21:02:02.357Z", + "lastActivityAt": "2026-10-26T21:02:01.374Z", + "deployments": { + "availability": "available", + "ready": 0, + "total": 0 + }, + "readiness": "in_review", + "mergeability": { + "conflict_status": "unknown", + "head_sha": "", + "refreshed_at": null, + "forge_merge_block": null + } + } + ], + "isPossiblyPartial": true + } + } +} diff --git a/test/fixtures/entire/recorded/entire.com-writes/steps/pull-assign/02-get-forges-fixtures-N.json b/test/fixtures/entire/recorded/entire.com-writes/steps/pull-assign/02-get-forges-fixtures-N.json new file mode 100644 index 000000000..cbb7a74fa --- /dev/null +++ b/test/fixtures/entire/recorded/entire.com-writes/steps/pull-assign/02-get-forges-fixtures-N.json @@ -0,0 +1,243 @@ +{ + "request": { + "method": "GET", + "url": "https://aws-eu-central-1.api.entire.io/api/v1/trails/et/forges-scratch/forges-fixtures/9" + }, + "response": { + "status": 200, + "headers": { + "link": "; rel=\"describedBy\"" + }, + "body": { + "$schema": "https://aws-eu-central-1.api.entire.io/api/v1/schemas/TrailDetailResponse.json", + "id": "01M5X0A49M70NAMJX878FD2QD1", + "number": 9, + "url": "https://entire.com/et/forges-scratch/forges-fixtures/trails/9", + "title": "forges fixture 20261026210133: pull 1", + "status": "open", + "branch": "forges-fixtures/20261026210133-1", + "original_branch": "forges-fixtures/20261026210133-1", + "base": "main", + "type": "task", + "priority": "none", + "author": { + "id": "01M5WYRRVZNA1TXNET6KE4Q3WX", + "login": "danielroe-bot", + "identity": { + "kind": "account", + "account_id": "01M5WYRRVZNA1TXNET6KE4Q3WX", + "display_name": null, + "avatar_url": "https://avatars.githubusercontent.com/u/57801166?v=4", + "handles": [ + { + "provider": "github", + "handle": "danielroe-bot", + "is_primary": true + } + ] + } + }, + "assignees": [ + "danielroe-bot" + ], + "assignee_identities": [ + { + "login": "danielroe-bot", + "identity": { + "kind": "account", + "account_id": "01M5WYRRVZNA1TXNET6KE4Q3WX", + "display_name": null, + "avatar_url": "https://avatars.githubusercontent.com/u/57801166?v=4", + "handles": [ + { + "provider": "github", + "handle": "danielroe-bot", + "is_primary": true + } + ] + } + } + ], + "reviewers": [], + "ready_for_review": true, + "has_code_changes": true, + "comment_count": 1, + "unresolved_count": 1, + "created_at": "2026-10-26T21:01:54.849Z", + "updated_at": "2026-10-26T21:02:02.357Z", + "merged_at": null, + "last_activity_at": "2026-10-26T21:02:01.374Z", + "phase": "reviewing", + "parent": { + "id": "01M5X0A493RSBKDGYF0ZWVG8E9", + "number": 15, + "project_id": "01M5WYSMPPYRBB13ZB20H7NK2Q", + "host": "et", + "project": "forges-scratch", + "path": "/api/v1/et/forges-scratch/trails/01M5X0A493RSBKDGYF0ZWVG8E9", + "jurisdiction": "eu", + "primary_processing_cell": "aws-eu-central-1", + "url": "https://entire.com/et/forges-scratch/-/trails/15" + }, + "branch_state": "present", + "code_changes": "present", + "lifecycle_sync": "settled", + "body_document": { + "id": "01M5X0A4AGRFN6FB08AYTPCF6X", + "document_key": "trail:01M5X0A49M70NAMJX878FD2QD1:body", + "schema_version": 1, + "content_json": { + "type": "doc", + "content": [ + { + "type": "paragraph" + } + ] + }, + "text_snapshot": "", + "updated_at": "2026-10-26T21:01:54.849Z", + "etag": "W/\"2026-10-26T21:01:54.849162Z\"" + }, + "monitors": [], + "agents": [], + "runners": [], + "actions": { + "approve": { + "state": "blocked", + "reason": "self_approval_not_allowed" + }, + "create_ci_pr": { + "state": "unavailable", + "reason": "not_applicable" + }, + "merge": { + "state": "blocked", + "reason": "merge_gates_required" + }, + "merge_with_bypass": { + "state": "unavailable", + "reason": "merge_gates_bypass_forbidden" + }, + "update_branch": { + "state": "unavailable", + "reason": "branch_up_to_date" + }, + "restore_branch": { + "state": "unavailable", + "reason": "trail_not_merged" + }, + "delete_branch": { + "state": "unavailable", + "reason": "trail_not_merged" + } + }, + "mergeability": { + "delete_branch_on_merge": false, + "bypass_policy": "nobody", + "mergeable": false, + "behind_by": 0, + "comparison_status": "available", + "conflict_status": "clean", + "head_sha": "9f5e93477cecca4f94f1888d8680ab55c75fccba", + "gates": [ + { + "reviewers": [], + "runner_ids": [], + "id": "", + "gate_definition_id": "01M5WZ6B2HAMXBN2SZ9TP2N3SN", + "gate_key": "approvals", + "gate_type": "approvals", + "blocking": true, + "status": "failed", + "head_sha": "9f5e93477cecca4f94f1888d8680ab55c75fccba", + "value": { + "approved": 0, + "changes_requested": false, + "config": { + "version": 1, + "min_reviewers": 1, + "allow_self_approval": false, + "dismiss_stale_approvals_on_push": false + }, + "required": 1, + "self_excluded": false, + "stale_dismissed": 0, + "total": 0 + }, + "rationale": "No reviewers have approved this trail", + "created_at": "2026-10-26T21:02:02.590144769Z", + "completed_at": "2026-10-26T21:02:02.590144769Z", + "state": "evaluated", + "outcome": "failed", + "stale_reason": null, + "evaluated_at_sha": "9f5e93477cecca4f94f1888d8680ab55c75fccba", + "finding_count": null + }, + { + "reviewers": [], + "runner_ids": [], + "id": "", + "gate_definition_id": "01M5WZ6B2M8PSY34EM5YJGG6ZR", + "gate_key": "findings", + "gate_type": "findings", + "blocking": false, + "status": "pending", + "head_sha": "9f5e93477cecca4f94f1888d8680ab55c75fccba", + "value": null, + "rationale": "Gate has not been evaluated yet", + "created_at": "2026-10-26T20:42:22.164428Z", + "completed_at": null, + "state": "not_run", + "outcome": null, + "stale_reason": null, + "evaluated_at_sha": null, + "finding_count": null + }, + { + "reviewers": [], + "runner_ids": [], + "id": "01M5X0A4D1WK6QWSP6JXWFERW1", + "gate_definition_id": "01M5WZ6B2PC2X2BE023RX01WEY", + "gate_key": "up_to_date", + "gate_type": "up_to_date", + "blocking": true, + "status": "passed", + "head_sha": "9f5e93477cecca4f94f1888d8680ab55c75fccba", + "value": { + "config": { + "version": 1, + "allow_behind_if_mergeable": false + }, + "behind_by": 0, + "compare_status": "ahead", + "comparison_status": "available" + }, + "rationale": "Up to date", + "created_at": "2026-10-26T21:01:54.977313Z", + "completed_at": "2026-10-26T21:01:54.977313Z", + "state": "evaluated", + "outcome": "passed", + "stale_reason": null, + "evaluated_at_sha": "9f5e93477cecca4f94f1888d8680ab55c75fccba", + "finding_count": null + } + ], + "checks": { + "availability": "not_applicable", + "runs": [] + }, + "forge_merge_block": null + }, + "deployments": { + "availability": "available", + "ready": 0, + "total": 0, + "items": [] + }, + "config_source": "live", + "merge_base_sha": null, + "base_sha": null, + "head_sha": "9f5e93477cecca4f94f1888d8680ab55c75fccba" + } + } +} diff --git a/test/fixtures/entire/recorded/entire.com-writes/steps/pull-assign/03-patch-forges-fixtures-N.json b/test/fixtures/entire/recorded/entire.com-writes/steps/pull-assign/03-patch-forges-fixtures-N.json new file mode 100644 index 000000000..569c79853 --- /dev/null +++ b/test/fixtures/entire/recorded/entire.com-writes/steps/pull-assign/03-patch-forges-fixtures-N.json @@ -0,0 +1,101 @@ +{ + "request": { + "method": "PATCH", + "url": "https://aws-eu-central-1.api.entire.io/api/v1/trails/et/forges-scratch/forges-fixtures/9", + "body": { + "assignees": [ + "ulid:01M5WYRRVZNA1TXNET6KE4Q3WX" + ] + } + }, + "response": { + "status": 200, + "headers": { + "link": "; rel=\"describedBy\"", + "etag": "W/\"2026-10-26T21:02:02.357222Z\"" + }, + "body": { + "$schema": "https://aws-eu-central-1.api.entire.io/api/v1/schemas/TrailUpdateResponseBody.json", + "trail": { + "id": "01M5X0A49M70NAMJX878FD2QD1", + "number": 9, + "url": "https://entire.com/et/forges-scratch/forges-fixtures/trails/9", + "title": "forges fixture 20261026210133: pull 1", + "status": "open", + "branch": "forges-fixtures/20261026210133-1", + "original_branch": "forges-fixtures/20261026210133-1", + "base": "main", + "type": "task", + "priority": "none", + "author": { + "id": "01M5WYRRVZNA1TXNET6KE4Q3WX", + "login": "danielroe-bot", + "identity": { + "kind": "account", + "account_id": "01M5WYRRVZNA1TXNET6KE4Q3WX", + "display_name": null, + "avatar_url": "https://avatars.githubusercontent.com/u/57801166?v=4", + "handles": [ + { + "provider": "github", + "handle": "danielroe-bot", + "is_primary": true + } + ] + } + }, + "assignees": [ + "danielroe-bot" + ], + "assignee_identities": [ + { + "login": "danielroe-bot", + "identity": { + "kind": "account", + "account_id": "01M5WYRRVZNA1TXNET6KE4Q3WX", + "display_name": null, + "avatar_url": "https://avatars.githubusercontent.com/u/57801166?v=4", + "handles": [ + { + "provider": "github", + "handle": "danielroe-bot", + "is_primary": true + } + ] + } + } + ], + "reviewers": [], + "ready_for_review": true, + "has_code_changes": true, + "comment_count": 1, + "unresolved_count": 1, + "created_at": "2026-10-26T21:01:54.849Z", + "updated_at": "2026-10-26T21:02:02.357Z", + "merged_at": null, + "last_activity_at": "2026-10-26T21:02:01.374Z", + "phase": "reviewing", + "checkpoint_count": 0, + "body_document": { + "id": "01M5X0A4AGRFN6FB08AYTPCF6X", + "document_key": "trail:01M5X0A49M70NAMJX878FD2QD1:body", + "schema_version": 1, + "content_json": { + "type": "doc", + "content": [ + { + "type": "paragraph" + } + ] + }, + "text_snapshot": "", + "updated_at": "2026-10-26T21:01:54.849Z", + "etag": "W/\"2026-10-26T21:01:54.849162Z\"" + }, + "merge_base_sha": null, + "base_sha": null, + "head_sha": "9f5e93477cecca4f94f1888d8680ab55c75fccba" + } + } + } +} diff --git a/test/fixtures/entire/recorded/entire.com-writes/steps/pull-assign/golden.json b/test/fixtures/entire/recorded/entire.com-writes/steps/pull-assign/golden.json new file mode 100644 index 000000000..4f87da032 --- /dev/null +++ b/test/fixtures/entire/recorded/entire.com-writes/steps/pull-assign/golden.json @@ -0,0 +1,10 @@ +[ + { + "forge": "entire", + "instance": "entire.com", + "login": "danielroe-bot", + "id": "01M5WYRRVZNA1TXNET6KE4Q3WX", + "avatarUrl": "https://avatars.githubusercontent.com/u/57801166?v=4", + "isBotHint": false + } +] diff --git a/test/fixtures/entire/recorded/entire.com-writes/steps/pull-assign/step.json b/test/fixtures/entire/recorded/entire.com-writes/steps/pull-assign/step.json new file mode 100644 index 000000000..b87b1db02 --- /dev/null +++ b/test/fixtures/entire/recorded/entire.com-writes/steps/pull-assign/step.json @@ -0,0 +1,8 @@ +{ + "name": "pull assign", + "recordedAt": "2026-10-26T21:02:01.457Z", + "needs": [ + "create pull", + "author" + ] +} diff --git a/test/fixtures/entire/recorded/entire.com-writes/steps/pull-close/01-get-trails-01M5X0A6D5Q8H8VHFN7M7HTKRS.json b/test/fixtures/entire/recorded/entire.com-writes/steps/pull-close/01-get-trails-01M5X0A6D5Q8H8VHFN7M7HTKRS.json new file mode 100644 index 000000000..5ab00f717 --- /dev/null +++ b/test/fixtures/entire/recorded/entire.com-writes/steps/pull-close/01-get-trails-01M5X0A6D5Q8H8VHFN7M7HTKRS.json @@ -0,0 +1,122 @@ +{ + "request": { + "method": "GET", + "url": "https://aws-eu-central-1.api.entire.io/api/v1/et/forges-scratch/trails/01M5X0A6D5Q8H8VHFN7M7HTKRS" + }, + "response": { + "status": 200, + "headers": { + "link": "; rel=\"describedBy\"", + "etag": "W/\"2026-10-26T21:01:57.046039Z\"" + }, + "body": { + "$schema": "https://aws-eu-central-1.api.entire.io/api/v1/schemas/TrailResponse.json", + "capabilities": { + "canEdit": true, + "canManageScope": true + }, + "project": { + "primaryProcessingCell": "aws-eu-central-1", + "id": "01M5WYSMPPYRBB13ZB20H7NK2Q", + "name": "forges-scratch", + "provider": "entire", + "reference": { + "forge": "et", + "project": "forges-scratch" + }, + "jurisdiction": "eu", + "capabilities": { + "canManageTrails": true + } + }, + "author": { + "accountId": "01M5WYRRVZNA1TXNET6KE4Q3WX", + "login": "danielroe-bot", + "displayName": "", + "avatarUrl": "https://avatars.githubusercontent.com/u/57801166?v=4", + "identity": { + "kind": "account", + "account_id": "01M5WYRRVZNA1TXNET6KE4Q3WX", + "display_name": null, + "avatar_url": "https://avatars.githubusercontent.com/u/57801166?v=4", + "handles": [ + { + "provider": "github", + "handle": "danielroe-bot", + "is_primary": true + } + ] + } + }, + "id": "01M5X0A6D5Q8H8VHFN7M7HTKRS", + "projectId": "01M5WYSMPPYRBB13ZB20H7NK2Q", + "number": 17, + "url": "https://entire.com/et/forges-scratch/-/trails/17", + "title": "forges fixture 20261026210133: pull 3", + "body": "Opened by run 20261026210133.", + "bodyDocument": { + "id": "", + "document_key": "project-trail:01M5X0A6D5Q8H8VHFN7M7HTKRS:body", + "schema_version": 1, + "content_json": { + "type": "doc", + "content": [ + { + "type": "paragraph", + "content": [ + { + "type": "text", + "text": "Opened by run 20261026210133." + } + ] + } + ] + }, + "text_snapshot": "Opened by run 20261026210133.", + "updated_at": "2026-10-26T21:01:57.046Z", + "etag": "" + }, + "status": "open", + "phase": "complete", + "metadata": {}, + "type": "task", + "priority": "none", + "assignees": [], + "assigneeAccountIds": [], + "repoIds": [ + "01M5WYSQC41P69DTXEMZ0TE5YK" + ], + "authorAccountId": "01M5WYRRVZNA1TXNET6KE4Q3WX", + "createdAt": "2026-10-26T21:01:57.028Z", + "metadataUpdatedAt": "2026-10-26T21:01:57.046Z", + "closedAt": null, + "lastVisitedAt": null, + "lastActivityAt": "2026-10-26T21:02:15.260Z", + "changes": [ + { + "id": "01M5X0A6DAPK6DZNKVR2KEJNF8", + "repositoryId": "01M5WYSQC41P69DTXEMZ0TE5YK", + "repository": "forges-fixtures", + "branch": "forges-fixtures/20261026210133-3", + "originalBranch": "forges-fixtures/20261026210133-3", + "base": "main", + "number": 11, + "title": "forges fixture 20261026210133: pull 3", + "status": "closed", + "hasCodeChanges": false, + "createdAt": "2026-10-26T21:01:57.028Z", + "updatedAt": "2026-10-26T21:02:15.260Z", + "lastActivityAt": "2026-10-26T21:02:15.260Z", + "deployments": { + "availability": "available", + "ready": 0, + "total": 0 + }, + "readiness": "none", + "mergeability": null + } + ], + "isPossiblyPartial": true + } + } +} diff --git a/test/fixtures/entire/recorded/entire.com-writes/steps/pull-close/02-get-forges-fixtures-N.json b/test/fixtures/entire/recorded/entire.com-writes/steps/pull-close/02-get-forges-fixtures-N.json new file mode 100644 index 000000000..8ac2e001f --- /dev/null +++ b/test/fixtures/entire/recorded/entire.com-writes/steps/pull-close/02-get-forges-fixtures-N.json @@ -0,0 +1,270 @@ +{ + "request": { + "method": "GET", + "url": "https://aws-eu-central-1.api.entire.io/api/v1/trails/et/forges-scratch/forges-fixtures/11" + }, + "response": { + "status": 200, + "headers": { + "link": "; rel=\"describedBy\"" + }, + "body": { + "$schema": "https://aws-eu-central-1.api.entire.io/api/v1/schemas/TrailDetailResponse.json", + "id": "01M5X0A6DAPK6DZNKVR2KEJNF8", + "number": 11, + "url": "https://entire.com/et/forges-scratch/forges-fixtures/trails/11", + "title": "forges fixture 20261026210133: pull 3", + "status": "closed", + "branch": "forges-fixtures/20261026210133-3", + "original_branch": "forges-fixtures/20261026210133-3", + "base": "main", + "type": "task", + "priority": "none", + "author": { + "id": "01M5WYRRVZNA1TXNET6KE4Q3WX", + "login": "danielroe-bot", + "identity": { + "kind": "account", + "account_id": "01M5WYRRVZNA1TXNET6KE4Q3WX", + "display_name": null, + "avatar_url": "https://avatars.githubusercontent.com/u/57801166?v=4", + "handles": [ + { + "provider": "github", + "handle": "danielroe-bot", + "is_primary": true + } + ] + } + }, + "assignees": [ + "danielroe-bot" + ], + "assignee_identities": [ + { + "login": "danielroe-bot", + "identity": { + "kind": "account", + "account_id": "01M5WYRRVZNA1TXNET6KE4Q3WX", + "display_name": null, + "avatar_url": "https://avatars.githubusercontent.com/u/57801166?v=4", + "handles": [ + { + "provider": "github", + "handle": "danielroe-bot", + "is_primary": true + } + ] + } + } + ], + "reviewers": [ + { + "login": "danielroe", + "status": "approved", + "actor_account_id": "01M5WRP9RJ4GVR2PA5PCNYP1FC", + "identity": { + "kind": "account", + "account_id": "01M5WRP9RJ4GVR2PA5PCNYP1FC", + "display_name": "Daniel Roe", + "avatar_url": "https://avatars.githubusercontent.com/u/28706372?v=4", + "handles": [ + { + "provider": "github", + "handle": "danielroe", + "is_primary": true + } + ] + } + } + ], + "ready_for_review": false, + "has_code_changes": false, + "comment_count": 0, + "unresolved_count": 0, + "created_at": "2026-10-26T21:01:57.028Z", + "updated_at": "2026-10-26T21:02:15.260Z", + "merged_at": null, + "last_activity_at": "2026-10-26T21:02:15.260Z", + "phase": null, + "parent": { + "id": "01M5X0A6D5Q8H8VHFN7M7HTKRS", + "number": 17, + "project_id": "01M5WYSMPPYRBB13ZB20H7NK2Q", + "host": "et", + "project": "forges-scratch", + "path": "/api/v1/et/forges-scratch/trails/01M5X0A6D5Q8H8VHFN7M7HTKRS", + "jurisdiction": "eu", + "primary_processing_cell": "aws-eu-central-1", + "url": "https://entire.com/et/forges-scratch/-/trails/17" + }, + "branch_state": "unknown", + "code_changes": "not_applicable", + "lifecycle_sync": "settled", + "body_document": { + "id": "01M5X0A6DQ168SD36K14JNJPYW", + "document_key": "trail:01M5X0A6DAPK6DZNKVR2KEJNF8:body", + "schema_version": 1, + "content_json": { + "type": "doc", + "content": [ + { + "type": "paragraph" + } + ] + }, + "text_snapshot": "", + "updated_at": "2026-10-26T21:01:57.028Z", + "etag": "W/\"2026-10-26T21:01:57.02813Z\"" + }, + "monitors": [], + "agents": [], + "runners": [], + "actions": { + "approve": { + "state": "unavailable", + "reason": "trail_not_open" + }, + "create_ci_pr": { + "state": "unavailable", + "reason": "trail_not_open" + }, + "merge": { + "state": "unavailable", + "reason": "trail_not_open" + }, + "merge_with_bypass": { + "state": "unavailable", + "reason": "trail_not_open" + }, + "update_branch": { + "state": "unavailable", + "reason": "trail_not_open" + }, + "restore_branch": { + "state": "unavailable", + "reason": "trail_not_merged" + }, + "delete_branch": { + "state": "unavailable", + "reason": "trail_not_merged" + } + }, + "mergeability": { + "delete_branch_on_merge": false, + "bypass_policy": "nobody", + "mergeable": false, + "behind_by": 1, + "comparison_status": "available", + "conflict_status": "unknown", + "head_sha": "f483a62c7214e4cead9ef1df09a663324a4825ae", + "gates": [ + { + "reviewers": [ + { + "login": "danielroe", + "actor_account_id": "01M5WRP9RJ4GVR2PA5PCNYP1FC", + "state": "approved", + "reviewed_head_sha": "f483a62c7214e4cead9ef1df09a663324a4825ae", + "reason": null + } + ], + "runner_ids": [], + "id": "01M5X0AFK10B04M0VR1DS05YNN", + "gate_definition_id": "01M5WZ6B2HAMXBN2SZ9TP2N3SN", + "gate_key": "approvals", + "gate_type": "approvals", + "blocking": true, + "status": "passed", + "head_sha": "f483a62c7214e4cead9ef1df09a663324a4825ae", + "value": { + "approved": 1, + "changes_requested": false, + "config": { + "version": 1, + "min_reviewers": 1, + "allow_self_approval": false, + "dismiss_stale_approvals_on_push": false + }, + "required": 1, + "self_excluded": false, + "stale_dismissed": 0, + "total": 1 + }, + "rationale": "1 approval(s) recorded", + "created_at": "2026-10-26T21:02:06.433525Z", + "completed_at": "2026-10-26T21:02:06.433525Z", + "state": "evaluated", + "outcome": "passed", + "stale_reason": null, + "evaluated_at_sha": "f483a62c7214e4cead9ef1df09a663324a4825ae", + "finding_count": null + }, + { + "reviewers": [], + "runner_ids": [], + "id": "", + "gate_definition_id": "01M5WZ6B2M8PSY34EM5YJGG6ZR", + "gate_key": "findings", + "gate_type": "findings", + "blocking": false, + "status": "pending", + "head_sha": "f483a62c7214e4cead9ef1df09a663324a4825ae", + "value": null, + "rationale": "Gate has not been evaluated yet", + "created_at": "2026-10-26T21:02:15.279935Z", + "completed_at": null, + "state": "not_run", + "outcome": null, + "stale_reason": null, + "evaluated_at_sha": null, + "finding_count": null + }, + { + "reviewers": [], + "runner_ids": [], + "id": "01M5X0AQA2B9ZDQMTB47V2M5V2", + "gate_definition_id": "01M5WZ6B2PC2X2BE023RX01WEY", + "gate_key": "up_to_date", + "gate_type": "up_to_date", + "blocking": true, + "status": "failed", + "head_sha": "f483a62c7214e4cead9ef1df09a663324a4825ae", + "value": { + "config": { + "version": 1, + "allow_behind_if_mergeable": false + }, + "behind_by": 1, + "compare_status": "diverged", + "comparison_status": "available" + }, + "rationale": "1 commit behind", + "created_at": "2026-10-26T21:02:14.338494Z", + "completed_at": "2026-10-26T21:02:14.338494Z", + "state": "evaluated", + "outcome": "failed", + "stale_reason": null, + "evaluated_at_sha": "f483a62c7214e4cead9ef1df09a663324a4825ae", + "finding_count": null + } + ], + "checks": { + "availability": "not_applicable", + "runs": [] + }, + "forge_merge_block": null + }, + "deployments": { + "availability": "available", + "ready": 0, + "total": 0, + "items": [] + }, + "config_source": "snapshot", + "merge_base_sha": "80c3e7d4c9f5e16f4e11cf7737f571c513d14ac2", + "base_sha": null, + "head_sha": "f483a62c7214e4cead9ef1df09a663324a4825ae" + } + } +} diff --git a/test/fixtures/entire/recorded/entire.com-writes/steps/pull-close/03-patch-forges-fixtures-N.json b/test/fixtures/entire/recorded/entire.com-writes/steps/pull-close/03-patch-forges-fixtures-N.json new file mode 100644 index 000000000..144602b33 --- /dev/null +++ b/test/fixtures/entire/recorded/entire.com-writes/steps/pull-close/03-patch-forges-fixtures-N.json @@ -0,0 +1,118 @@ +{ + "request": { + "method": "PATCH", + "url": "https://aws-eu-central-1.api.entire.io/api/v1/trails/et/forges-scratch/forges-fixtures/11", + "body": { + "status": "closed" + } + }, + "response": { + "status": 200, + "headers": { + "link": "; rel=\"describedBy\"", + "etag": "W/\"2026-10-26T21:02:15.260166Z\"" + }, + "body": { + "$schema": "https://aws-eu-central-1.api.entire.io/api/v1/schemas/TrailUpdateResponseBody.json", + "trail": { + "id": "01M5X0A6DAPK6DZNKVR2KEJNF8", + "number": 11, + "url": "https://entire.com/et/forges-scratch/forges-fixtures/trails/11", + "title": "forges fixture 20261026210133: pull 3", + "status": "closed", + "branch": "forges-fixtures/20261026210133-3", + "original_branch": "forges-fixtures/20261026210133-3", + "base": "main", + "type": "task", + "priority": "none", + "author": { + "id": "01M5WYRRVZNA1TXNET6KE4Q3WX", + "login": "danielroe-bot", + "identity": { + "kind": "account", + "account_id": "01M5WYRRVZNA1TXNET6KE4Q3WX", + "display_name": null, + "avatar_url": "https://avatars.githubusercontent.com/u/57801166?v=4", + "handles": [ + { + "provider": "github", + "handle": "danielroe-bot", + "is_primary": true + } + ] + } + }, + "assignees": [ + "danielroe-bot" + ], + "assignee_identities": [ + { + "login": "danielroe-bot", + "identity": { + "kind": "account", + "account_id": "01M5WYRRVZNA1TXNET6KE4Q3WX", + "display_name": null, + "avatar_url": "https://avatars.githubusercontent.com/u/57801166?v=4", + "handles": [ + { + "provider": "github", + "handle": "danielroe-bot", + "is_primary": true + } + ] + } + } + ], + "reviewers": [ + { + "login": "danielroe", + "status": "approved", + "actor_account_id": "01M5WRP9RJ4GVR2PA5PCNYP1FC", + "identity": { + "kind": "account", + "account_id": "01M5WRP9RJ4GVR2PA5PCNYP1FC", + "display_name": "Daniel Roe", + "avatar_url": "https://avatars.githubusercontent.com/u/28706372?v=4", + "handles": [ + { + "provider": "github", + "handle": "danielroe", + "is_primary": true + } + ] + } + } + ], + "ready_for_review": false, + "has_code_changes": false, + "comment_count": 0, + "unresolved_count": 0, + "created_at": "2026-10-26T21:01:57.028Z", + "updated_at": "2026-10-26T21:02:15.260Z", + "merged_at": null, + "last_activity_at": "2026-10-26T21:02:15.260Z", + "phase": null, + "checkpoint_count": 0, + "body_document": { + "id": "01M5X0A6DQ168SD36K14JNJPYW", + "document_key": "trail:01M5X0A6DAPK6DZNKVR2KEJNF8:body", + "schema_version": 1, + "content_json": { + "type": "doc", + "content": [ + { + "type": "paragraph" + } + ] + }, + "text_snapshot": "", + "updated_at": "2026-10-26T21:01:57.028Z", + "etag": "W/\"2026-10-26T21:01:57.02813Z\"" + }, + "merge_base_sha": "80c3e7d4c9f5e16f4e11cf7737f571c513d14ac2", + "base_sha": null, + "head_sha": "f483a62c7214e4cead9ef1df09a663324a4825ae" + } + } + } +} diff --git a/test/fixtures/entire/recorded/entire.com-writes/steps/pull-close/golden.json b/test/fixtures/entire/recorded/entire.com-writes/steps/pull-close/golden.json new file mode 100644 index 000000000..7a20f5038 --- /dev/null +++ b/test/fixtures/entire/recorded/entire.com-writes/steps/pull-close/golden.json @@ -0,0 +1,75 @@ +{ + "ref": { + "forge": "entire", + "instance": "entire.com", + "repo": { + "forge": "entire", + "instance": "entire.com", + "owner": "forges-scratch", + "name": "forges-fixtures" + }, + "kind": "pull_request", + "number": "11", + "externalId": "01M5X0A6DAPK6DZNKVR2KEJNF8" + }, + "kind": "pull_request", + "title": "forges fixture 20261026210133: pull 3", + "body": "Opened by run 20261026210133.", + "state": "closed", + "stateRaw": "closed", + "isDraft": true, + "author": { + "forge": "entire", + "instance": "entire.com", + "login": "danielroe-bot", + "id": "01M5WYRRVZNA1TXNET6KE4Q3WX", + "avatarUrl": "https://avatars.githubusercontent.com/u/57801166?v=4", + "isBotHint": false + }, + "assignees": [ + { + "forge": "entire", + "instance": "entire.com", + "login": "danielroe-bot", + "id": "01M5WYRRVZNA1TXNET6KE4Q3WX", + "avatarUrl": "https://avatars.githubusercontent.com/u/57801166?v=4", + "isBotHint": false + } + ], + "reviewers": [ + { + "actor": { + "forge": "entire", + "instance": "entire.com", + "login": "danielroe", + "id": "01M5WRP9RJ4GVR2PA5PCNYP1FC", + "name": "Daniel Roe", + "avatarUrl": "https://avatars.githubusercontent.com/u/28706372?v=4", + "isBotHint": false + }, + "state": "approved", + "stateRaw": "approved" + } + ], + "labels": [], + "url": "https://entire.com/et/forges-scratch/forges-fixtures/trails/11", + "createdAt": "", + "updatedAt": "", + "lastActivityAt": "", + "commentCount": 0, + "branches": { + "head": { + "ref": "forges-fixtures/20261026210133-3", + "sha": "f483a62c7214e4cead9ef1df09a663324a4825ae", + "repo": { + "forge": "entire", + "instance": "entire.com", + "owner": "forges-scratch", + "name": "forges-fixtures" + } + }, + "base": { + "ref": "main" + } + } +} diff --git a/test/fixtures/entire/recorded/entire.com-writes/steps/pull-close/step.json b/test/fixtures/entire/recorded/entire.com-writes/steps/pull-close/step.json new file mode 100644 index 000000000..5ef17e345 --- /dev/null +++ b/test/fixtures/entire/recorded/entire.com-writes/steps/pull-close/step.json @@ -0,0 +1,7 @@ +{ + "name": "pull close", + "recordedAt": "2026-10-26T21:02:14.364Z", + "needs": [ + "create third pull" + ] +} diff --git a/test/fixtures/entire/recorded/entire.com-writes/steps/pull-comment/01-post-N-discussions.json b/test/fixtures/entire/recorded/entire.com-writes/steps/pull-comment/01-post-N-discussions.json new file mode 100644 index 000000000..704c7c732 --- /dev/null +++ b/test/fixtures/entire/recorded/entire.com-writes/steps/pull-comment/01-post-N-discussions.json @@ -0,0 +1,95 @@ +{ + "request": { + "method": "POST", + "url": "https://aws-eu-central-1.api.entire.io/api/v1/trails/et/forges-scratch/forges-fixtures/9/discussions", + "body": { + "body": "A comment from run 20261026210133." + } + }, + "response": { + "status": 201, + "headers": { + "link": "; rel=\"describedBy\"", + "location": "https://aws-eu-central-1.api.entire.io/api/v1/trails/et/forges-scratch/forges-fixtures/9/discussions/01M5X0A7TQB4NGZHFD3MVSJQTE" + }, + "body": { + "$schema": "https://aws-eu-central-1.api.entire.io/api/v1/schemas/TrailDiscussionCreateResponseBody.json", + "discussion": { + "id": "01M5X0A7TQB4NGZHFD3MVSJQTE", + "trail_id": "01M5X0A49M70NAMJX878FD2QD1", + "title": "A comment from run 20261026210133.", + "kind": "discussion", + "resolved": false, + "resolved_by": null, + "resolved_by_identity": { + "kind": "unknown", + "account_id": null, + "display_name": null, + "avatar_url": null, + "handles": [] + }, + "resolved_at": null, + "created_by": "01M5WYRRVZNA1TXNET6KE4Q3WX", + "created_by_identity": { + "kind": "account", + "account_id": "01M5WYRRVZNA1TXNET6KE4Q3WX", + "display_name": null, + "avatar_url": "https://avatars.githubusercontent.com/u/57801166?v=4", + "handles": [ + { + "provider": "github", + "handle": "danielroe-bot", + "is_primary": true + } + ] + }, + "created_at": "2026-10-26T21:01:58.487Z", + "updated_at": "2026-10-26T21:01:58.487Z", + "last_message_at": "2026-10-26T21:01:58.487Z", + "last_message_author": "danielroe-bot", + "message_count": 1, + "participants": [ + { + "login": "danielroe-bot", + "actor_account_id": "01M5WYRRVZNA1TXNET6KE4Q3WX", + "identity": { + "kind": "account", + "account_id": "01M5WYRRVZNA1TXNET6KE4Q3WX", + "display_name": null, + "avatar_url": "https://avatars.githubusercontent.com/u/57801166?v=4", + "handles": [ + { + "provider": "github", + "handle": "danielroe-bot", + "is_primary": true + } + ] + } + } + ], + "review_comment_id": null, + "review_comment": null + }, + "message": { + "id": "01M5X0A7TRJFRP22WZ8RWZZ0NQ", + "author": "danielroe-bot", + "identity": { + "kind": "account", + "account_id": "01M5WYRRVZNA1TXNET6KE4Q3WX", + "display_name": null, + "avatar_url": "https://avatars.githubusercontent.com/u/57801166?v=4", + "handles": [ + { + "provider": "github", + "handle": "danielroe-bot", + "is_primary": true + } + ] + }, + "created_at": "2026-10-26T21:01:58.487Z", + "body": "A comment from run 20261026210133.", + "replies": [] + } + } + } +} diff --git a/test/fixtures/entire/recorded/entire.com-writes/steps/pull-comment/golden.json b/test/fixtures/entire/recorded/entire.com-writes/steps/pull-comment/golden.json new file mode 100644 index 000000000..5024353cb --- /dev/null +++ b/test/fixtures/entire/recorded/entire.com-writes/steps/pull-comment/golden.json @@ -0,0 +1,34 @@ +{ + "ref": { + "forge": "entire", + "instance": "entire.com", + "thread": { + "forge": "entire", + "instance": "entire.com", + "repo": { + "forge": "entire", + "instance": "entire.com", + "owner": "forges-scratch", + "name": "forges-fixtures" + }, + "kind": "pull_request", + "number": "9", + "externalId": "01M5X0A49M70NAMJX878FD2QD1" + }, + "id": "01M5X0A7TRJFRP22WZ8RWZZ0NQ" + }, + "body": "A comment from run 20261026210133.", + "author": { + "forge": "entire", + "instance": "entire.com", + "login": "danielroe-bot", + "id": "01M5WYRRVZNA1TXNET6KE4Q3WX", + "avatarUrl": "https://avatars.githubusercontent.com/u/57801166?v=4", + "isBotHint": false + }, + "createdAt": "", + "thread": { + "id": "01M5X0A7TQB4NGZHFD3MVSJQTE", + "resolved": false + } +} diff --git a/test/fixtures/entire/recorded/entire.com-writes/steps/pull-comment/step.json b/test/fixtures/entire/recorded/entire.com-writes/steps/pull-comment/step.json new file mode 100644 index 000000000..95f451d70 --- /dev/null +++ b/test/fixtures/entire/recorded/entire.com-writes/steps/pull-comment/step.json @@ -0,0 +1,7 @@ +{ + "name": "pull comment", + "recordedAt": "2026-10-26T21:01:58.239Z", + "needs": [ + "create pull" + ] +} diff --git a/test/fixtures/entire/recorded/entire.com-writes/steps/pull-delete-comment/01-delete-messages-01M5X0A7TRJFRP22WZ8RWZZ0NQ.json b/test/fixtures/entire/recorded/entire.com-writes/steps/pull-delete-comment/01-delete-messages-01M5X0A7TRJFRP22WZ8RWZZ0NQ.json new file mode 100644 index 000000000..2abf3e49d --- /dev/null +++ b/test/fixtures/entire/recorded/entire.com-writes/steps/pull-delete-comment/01-delete-messages-01M5X0A7TRJFRP22WZ8RWZZ0NQ.json @@ -0,0 +1,10 @@ +{ + "request": { + "method": "DELETE", + "url": "https://aws-eu-central-1.api.entire.io/api/v1/trails/et/forges-scratch/forges-fixtures/9/discussions/01M5X0A7TQB4NGZHFD3MVSJQTE/messages/01M5X0A7TRJFRP22WZ8RWZZ0NQ" + }, + "response": { + "status": 204, + "headers": {} + } +} diff --git a/test/fixtures/entire/recorded/entire.com-writes/steps/pull-delete-comment/02-get-N-discussions.json b/test/fixtures/entire/recorded/entire.com-writes/steps/pull-delete-comment/02-get-N-discussions.json new file mode 100644 index 000000000..784fa9d3c --- /dev/null +++ b/test/fixtures/entire/recorded/entire.com-writes/steps/pull-delete-comment/02-get-N-discussions.json @@ -0,0 +1,174 @@ +{ + "request": { + "method": "GET", + "url": "https://aws-eu-central-1.api.entire.io/api/v1/trails/et/forges-scratch/forges-fixtures/9/discussions?include_messages=true&per_page=100" + }, + "response": { + "status": 200, + "headers": { + "link": "; rel=\"describedBy\"" + }, + "body": { + "$schema": "https://aws-eu-central-1.api.entire.io/api/v1/schemas/TrailDiscussionsListResponseBody.json", + "items": [ + { + "id": "01M5X0A9PBSMXT52PCMF5JCE0Y", + "trail_id": "01M5X0A49M70NAMJX878FD2QD1", + "title": "An upserted comment from run 20261026210133. ", + "kind": "discussion", + "resolved": false, + "resolved_by": null, + "resolved_by_identity": { + "kind": "unknown", + "account_id": null, + "display_name": null, + "avatar_url": null, + "handles": [] + }, + "resolved_at": null, + "created_by": "01M5WYRRVZNA1TXNET6KE4Q3WX", + "created_by_identity": { + "kind": "account", + "account_id": "01M5WYRRVZNA1TXNET6KE4Q3WX", + "display_name": null, + "avatar_url": "https://avatars.githubusercontent.com/u/57801166?v=4", + "handles": [ + { + "provider": "github", + "handle": "danielroe-bot", + "is_primary": true + } + ] + }, + "created_at": "2026-10-26T21:02:00.395Z", + "updated_at": "2026-10-26T21:02:00.395Z", + "last_message_at": "2026-10-26T21:02:00.395Z", + "last_message_author": "danielroe-bot", + "message_count": 1, + "participants": [ + { + "login": "danielroe-bot", + "actor_account_id": "01M5WYRRVZNA1TXNET6KE4Q3WX", + "identity": { + "kind": "account", + "account_id": "01M5WYRRVZNA1TXNET6KE4Q3WX", + "display_name": null, + "avatar_url": "https://avatars.githubusercontent.com/u/57801166?v=4", + "handles": [ + { + "provider": "github", + "handle": "danielroe-bot", + "is_primary": true + } + ] + } + } + ], + "review_comment_id": null, + "review_comment": null, + "messages": [ + { + "id": "01M5X0A9PCYAK06HK5CXJRQR2P", + "author": "danielroe-bot", + "identity": { + "kind": "account", + "account_id": "01M5WYRRVZNA1TXNET6KE4Q3WX", + "display_name": null, + "avatar_url": "https://avatars.githubusercontent.com/u/57801166?v=4", + "handles": [ + { + "provider": "github", + "handle": "danielroe-bot", + "is_primary": true + } + ] + }, + "created_at": "2026-10-26T21:02:00.395Z", + "body": "An upserted comment from run 20261026210133.\n\n", + "replies": [] + } + ] + }, + { + "id": "01M5X0A7TQB4NGZHFD3MVSJQTE", + "trail_id": "01M5X0A49M70NAMJX878FD2QD1", + "title": "An edited comment from run 20261026210133.", + "kind": "discussion", + "resolved": false, + "resolved_by": null, + "resolved_by_identity": { + "kind": "unknown", + "account_id": null, + "display_name": null, + "avatar_url": null, + "handles": [] + }, + "resolved_at": null, + "created_by": "01M5WYRRVZNA1TXNET6KE4Q3WX", + "created_by_identity": { + "kind": "account", + "account_id": "01M5WYRRVZNA1TXNET6KE4Q3WX", + "display_name": null, + "avatar_url": "https://avatars.githubusercontent.com/u/57801166?v=4", + "handles": [ + { + "provider": "github", + "handle": "danielroe-bot", + "is_primary": true + } + ] + }, + "created_at": "2026-10-26T21:01:58.487Z", + "updated_at": "2026-10-26T21:01:59.356Z", + "last_message_at": "2026-10-26T21:01:58.487Z", + "last_message_author": "danielroe-bot", + "message_count": 1, + "participants": [ + { + "login": "danielroe-bot", + "actor_account_id": "01M5WYRRVZNA1TXNET6KE4Q3WX", + "identity": { + "kind": "account", + "account_id": "01M5WYRRVZNA1TXNET6KE4Q3WX", + "display_name": null, + "avatar_url": "https://avatars.githubusercontent.com/u/57801166?v=4", + "handles": [ + { + "provider": "github", + "handle": "danielroe-bot", + "is_primary": true + } + ] + } + } + ], + "review_comment_id": null, + "review_comment": null, + "messages": [ + { + "id": "01M5X0A7TRJFRP22WZ8RWZZ0NQ", + "author": "danielroe-bot", + "identity": { + "kind": "account", + "account_id": "01M5WYRRVZNA1TXNET6KE4Q3WX", + "display_name": null, + "avatar_url": "https://avatars.githubusercontent.com/u/57801166?v=4", + "handles": [ + { + "provider": "github", + "handle": "danielroe-bot", + "is_primary": true + } + ] + }, + "created_at": "2026-10-26T21:01:58.487Z", + "body": "An edited comment from run 20261026210133.", + "replies": [] + } + ] + } + ], + "event_cursor": "3" + } + } +} diff --git a/test/fixtures/entire/recorded/entire.com-writes/steps/pull-delete-comment/golden.json b/test/fixtures/entire/recorded/entire.com-writes/steps/pull-delete-comment/golden.json new file mode 100644 index 000000000..19765bd50 --- /dev/null +++ b/test/fixtures/entire/recorded/entire.com-writes/steps/pull-delete-comment/golden.json @@ -0,0 +1 @@ +null diff --git a/test/fixtures/entire/recorded/entire.com-writes/steps/pull-delete-comment/step.json b/test/fixtures/entire/recorded/entire.com-writes/steps/pull-delete-comment/step.json new file mode 100644 index 000000000..343b9a53f --- /dev/null +++ b/test/fixtures/entire/recorded/entire.com-writes/steps/pull-delete-comment/step.json @@ -0,0 +1,7 @@ +{ + "name": "pull delete comment", + "recordedAt": "2026-10-26T21:02:00.476Z", + "needs": [ + "pull comment" + ] +} diff --git a/test/fixtures/entire/recorded/entire.com-writes/steps/pull-edit-comment/01-get-N-discussions.json b/test/fixtures/entire/recorded/entire.com-writes/steps/pull-edit-comment/01-get-N-discussions.json new file mode 100644 index 000000000..72ac0bb26 --- /dev/null +++ b/test/fixtures/entire/recorded/entire.com-writes/steps/pull-edit-comment/01-get-N-discussions.json @@ -0,0 +1,96 @@ +{ + "request": { + "method": "GET", + "url": "https://aws-eu-central-1.api.entire.io/api/v1/trails/et/forges-scratch/forges-fixtures/9/discussions?include_messages=true&per_page=100" + }, + "response": { + "status": 200, + "headers": { + "link": "; rel=\"describedBy\"" + }, + "body": { + "$schema": "https://aws-eu-central-1.api.entire.io/api/v1/schemas/TrailDiscussionsListResponseBody.json", + "items": [ + { + "id": "01M5X0A7TQB4NGZHFD3MVSJQTE", + "trail_id": "01M5X0A49M70NAMJX878FD2QD1", + "title": "A comment from run 20261026210133.", + "kind": "discussion", + "resolved": false, + "resolved_by": null, + "resolved_by_identity": { + "kind": "unknown", + "account_id": null, + "display_name": null, + "avatar_url": null, + "handles": [] + }, + "resolved_at": null, + "created_by": "01M5WYRRVZNA1TXNET6KE4Q3WX", + "created_by_identity": { + "kind": "account", + "account_id": "01M5WYRRVZNA1TXNET6KE4Q3WX", + "display_name": null, + "avatar_url": "https://avatars.githubusercontent.com/u/57801166?v=4", + "handles": [ + { + "provider": "github", + "handle": "danielroe-bot", + "is_primary": true + } + ] + }, + "created_at": "2026-10-26T21:01:58.487Z", + "updated_at": "2026-10-26T21:01:58.487Z", + "last_message_at": "2026-10-26T21:01:58.487Z", + "last_message_author": "danielroe-bot", + "message_count": 1, + "participants": [ + { + "login": "danielroe-bot", + "actor_account_id": "01M5WYRRVZNA1TXNET6KE4Q3WX", + "identity": { + "kind": "account", + "account_id": "01M5WYRRVZNA1TXNET6KE4Q3WX", + "display_name": null, + "avatar_url": "https://avatars.githubusercontent.com/u/57801166?v=4", + "handles": [ + { + "provider": "github", + "handle": "danielroe-bot", + "is_primary": true + } + ] + } + } + ], + "review_comment_id": null, + "review_comment": null, + "messages": [ + { + "id": "01M5X0A7TRJFRP22WZ8RWZZ0NQ", + "author": "danielroe-bot", + "identity": { + "kind": "account", + "account_id": "01M5WYRRVZNA1TXNET6KE4Q3WX", + "display_name": null, + "avatar_url": "https://avatars.githubusercontent.com/u/57801166?v=4", + "handles": [ + { + "provider": "github", + "handle": "danielroe-bot", + "is_primary": true + } + ] + }, + "created_at": "2026-10-26T21:01:58.487Z", + "body": "A comment from run 20261026210133.", + "replies": [] + } + ] + } + ], + "event_cursor": "1" + } + } +} diff --git a/test/fixtures/entire/recorded/entire.com-writes/steps/pull-edit-comment/02-patch-messages-01M5X0A7TRJFRP22WZ8RWZZ0NQ.json b/test/fixtures/entire/recorded/entire.com-writes/steps/pull-edit-comment/02-patch-messages-01M5X0A7TRJFRP22WZ8RWZZ0NQ.json new file mode 100644 index 000000000..974908017 --- /dev/null +++ b/test/fixtures/entire/recorded/entire.com-writes/steps/pull-edit-comment/02-patch-messages-01M5X0A7TRJFRP22WZ8RWZZ0NQ.json @@ -0,0 +1,38 @@ +{ + "request": { + "method": "PATCH", + "url": "https://aws-eu-central-1.api.entire.io/api/v1/trails/et/forges-scratch/forges-fixtures/9/discussions/01M5X0A7TQB4NGZHFD3MVSJQTE/messages/01M5X0A7TRJFRP22WZ8RWZZ0NQ", + "body": { + "body": "An edited comment from run 20261026210133." + } + }, + "response": { + "status": 200, + "headers": { + "link": "; rel=\"describedBy\"" + }, + "body": { + "$schema": "https://aws-eu-central-1.api.entire.io/api/v1/schemas/TrailDiscussionMessageResponseBody.json", + "message": { + "id": "01M5X0A7TRJFRP22WZ8RWZZ0NQ", + "author": "danielroe-bot", + "identity": { + "kind": "account", + "account_id": "01M5WYRRVZNA1TXNET6KE4Q3WX", + "display_name": null, + "avatar_url": "https://avatars.githubusercontent.com/u/57801166?v=4", + "handles": [ + { + "provider": "github", + "handle": "danielroe-bot", + "is_primary": true + } + ] + }, + "created_at": "2026-10-26T21:01:58.487Z", + "body": "An edited comment from run 20261026210133.", + "replies": [] + } + } + } +} diff --git a/test/fixtures/entire/recorded/entire.com-writes/steps/pull-edit-comment/golden.json b/test/fixtures/entire/recorded/entire.com-writes/steps/pull-edit-comment/golden.json new file mode 100644 index 000000000..cb706a473 --- /dev/null +++ b/test/fixtures/entire/recorded/entire.com-writes/steps/pull-edit-comment/golden.json @@ -0,0 +1,34 @@ +{ + "ref": { + "forge": "entire", + "instance": "entire.com", + "thread": { + "forge": "entire", + "instance": "entire.com", + "repo": { + "forge": "entire", + "instance": "entire.com", + "owner": "forges-scratch", + "name": "forges-fixtures" + }, + "kind": "pull_request", + "number": "9", + "externalId": "01M5X0A49M70NAMJX878FD2QD1" + }, + "id": "01M5X0A7TRJFRP22WZ8RWZZ0NQ" + }, + "body": "An edited comment from run 20261026210133.", + "author": { + "forge": "entire", + "instance": "entire.com", + "login": "danielroe-bot", + "id": "01M5WYRRVZNA1TXNET6KE4Q3WX", + "avatarUrl": "https://avatars.githubusercontent.com/u/57801166?v=4", + "isBotHint": false + }, + "createdAt": "", + "thread": { + "id": "01M5X0A7TQB4NGZHFD3MVSJQTE", + "resolved": false + } +} diff --git a/test/fixtures/entire/recorded/entire.com-writes/steps/pull-edit-comment/step.json b/test/fixtures/entire/recorded/entire.com-writes/steps/pull-edit-comment/step.json new file mode 100644 index 000000000..a3692a990 --- /dev/null +++ b/test/fixtures/entire/recorded/entire.com-writes/steps/pull-edit-comment/step.json @@ -0,0 +1,7 @@ +{ + "name": "pull edit comment", + "recordedAt": "2026-10-26T21:01:58.574Z", + "needs": [ + "pull comment" + ] +} diff --git a/test/fixtures/entire/recorded/entire.com-writes/steps/pull-get-comment/01-get-N-discussions.json b/test/fixtures/entire/recorded/entire.com-writes/steps/pull-get-comment/01-get-N-discussions.json new file mode 100644 index 000000000..c445ba59b --- /dev/null +++ b/test/fixtures/entire/recorded/entire.com-writes/steps/pull-get-comment/01-get-N-discussions.json @@ -0,0 +1,96 @@ +{ + "request": { + "method": "GET", + "url": "https://aws-eu-central-1.api.entire.io/api/v1/trails/et/forges-scratch/forges-fixtures/9/discussions?include_messages=true&per_page=100" + }, + "response": { + "status": 200, + "headers": { + "link": "; rel=\"describedBy\"" + }, + "body": { + "$schema": "https://aws-eu-central-1.api.entire.io/api/v1/schemas/TrailDiscussionsListResponseBody.json", + "items": [ + { + "id": "01M5X0A7TQB4NGZHFD3MVSJQTE", + "trail_id": "01M5X0A49M70NAMJX878FD2QD1", + "title": "An edited comment from run 20261026210133.", + "kind": "discussion", + "resolved": false, + "resolved_by": null, + "resolved_by_identity": { + "kind": "unknown", + "account_id": null, + "display_name": null, + "avatar_url": null, + "handles": [] + }, + "resolved_at": null, + "created_by": "01M5WYRRVZNA1TXNET6KE4Q3WX", + "created_by_identity": { + "kind": "account", + "account_id": "01M5WYRRVZNA1TXNET6KE4Q3WX", + "display_name": null, + "avatar_url": "https://avatars.githubusercontent.com/u/57801166?v=4", + "handles": [ + { + "provider": "github", + "handle": "danielroe-bot", + "is_primary": true + } + ] + }, + "created_at": "2026-10-26T21:01:58.487Z", + "updated_at": "2026-10-26T21:01:59.356Z", + "last_message_at": "2026-10-26T21:01:58.487Z", + "last_message_author": "danielroe-bot", + "message_count": 1, + "participants": [ + { + "login": "danielroe-bot", + "actor_account_id": "01M5WYRRVZNA1TXNET6KE4Q3WX", + "identity": { + "kind": "account", + "account_id": "01M5WYRRVZNA1TXNET6KE4Q3WX", + "display_name": null, + "avatar_url": "https://avatars.githubusercontent.com/u/57801166?v=4", + "handles": [ + { + "provider": "github", + "handle": "danielroe-bot", + "is_primary": true + } + ] + } + } + ], + "review_comment_id": null, + "review_comment": null, + "messages": [ + { + "id": "01M5X0A7TRJFRP22WZ8RWZZ0NQ", + "author": "danielroe-bot", + "identity": { + "kind": "account", + "account_id": "01M5WYRRVZNA1TXNET6KE4Q3WX", + "display_name": null, + "avatar_url": "https://avatars.githubusercontent.com/u/57801166?v=4", + "handles": [ + { + "provider": "github", + "handle": "danielroe-bot", + "is_primary": true + } + ] + }, + "created_at": "2026-10-26T21:01:58.487Z", + "body": "An edited comment from run 20261026210133.", + "replies": [] + } + ] + } + ], + "event_cursor": "2" + } + } +} diff --git a/test/fixtures/entire/recorded/entire.com-writes/steps/pull-get-comment/golden.json b/test/fixtures/entire/recorded/entire.com-writes/steps/pull-get-comment/golden.json new file mode 100644 index 000000000..cb706a473 --- /dev/null +++ b/test/fixtures/entire/recorded/entire.com-writes/steps/pull-get-comment/golden.json @@ -0,0 +1,34 @@ +{ + "ref": { + "forge": "entire", + "instance": "entire.com", + "thread": { + "forge": "entire", + "instance": "entire.com", + "repo": { + "forge": "entire", + "instance": "entire.com", + "owner": "forges-scratch", + "name": "forges-fixtures" + }, + "kind": "pull_request", + "number": "9", + "externalId": "01M5X0A49M70NAMJX878FD2QD1" + }, + "id": "01M5X0A7TRJFRP22WZ8RWZZ0NQ" + }, + "body": "An edited comment from run 20261026210133.", + "author": { + "forge": "entire", + "instance": "entire.com", + "login": "danielroe-bot", + "id": "01M5WYRRVZNA1TXNET6KE4Q3WX", + "avatarUrl": "https://avatars.githubusercontent.com/u/57801166?v=4", + "isBotHint": false + }, + "createdAt": "", + "thread": { + "id": "01M5X0A7TQB4NGZHFD3MVSJQTE", + "resolved": false + } +} diff --git a/test/fixtures/entire/recorded/entire.com-writes/steps/pull-get-comment/step.json b/test/fixtures/entire/recorded/entire.com-writes/steps/pull-get-comment/step.json new file mode 100644 index 000000000..fac38ace3 --- /dev/null +++ b/test/fixtures/entire/recorded/entire.com-writes/steps/pull-get-comment/step.json @@ -0,0 +1,7 @@ +{ + "name": "pull get comment", + "recordedAt": "2026-10-26T21:01:59.456Z", + "needs": [ + "pull comment" + ] +} diff --git a/test/fixtures/entire/recorded/entire.com-writes/steps/pull-reopen/01-get-trails-01M5X0A6D5Q8H8VHFN7M7HTKRS.json b/test/fixtures/entire/recorded/entire.com-writes/steps/pull-reopen/01-get-trails-01M5X0A6D5Q8H8VHFN7M7HTKRS.json new file mode 100644 index 000000000..ba5e638a8 --- /dev/null +++ b/test/fixtures/entire/recorded/entire.com-writes/steps/pull-reopen/01-get-trails-01M5X0A6D5Q8H8VHFN7M7HTKRS.json @@ -0,0 +1,127 @@ +{ + "request": { + "method": "GET", + "url": "https://aws-eu-central-1.api.entire.io/api/v1/et/forges-scratch/trails/01M5X0A6D5Q8H8VHFN7M7HTKRS" + }, + "response": { + "status": 200, + "headers": { + "link": "; rel=\"describedBy\"", + "etag": "W/\"2026-10-26T21:01:57.046039Z\"" + }, + "body": { + "$schema": "https://aws-eu-central-1.api.entire.io/api/v1/schemas/TrailResponse.json", + "capabilities": { + "canEdit": true, + "canManageScope": true + }, + "project": { + "primaryProcessingCell": "aws-eu-central-1", + "id": "01M5WYSMPPYRBB13ZB20H7NK2Q", + "name": "forges-scratch", + "provider": "entire", + "reference": { + "forge": "et", + "project": "forges-scratch" + }, + "jurisdiction": "eu", + "capabilities": { + "canManageTrails": true + } + }, + "author": { + "accountId": "01M5WYRRVZNA1TXNET6KE4Q3WX", + "login": "danielroe-bot", + "displayName": "", + "avatarUrl": "https://avatars.githubusercontent.com/u/57801166?v=4", + "identity": { + "kind": "account", + "account_id": "01M5WYRRVZNA1TXNET6KE4Q3WX", + "display_name": null, + "avatar_url": "https://avatars.githubusercontent.com/u/57801166?v=4", + "handles": [ + { + "provider": "github", + "handle": "danielroe-bot", + "is_primary": true + } + ] + } + }, + "id": "01M5X0A6D5Q8H8VHFN7M7HTKRS", + "projectId": "01M5WYSMPPYRBB13ZB20H7NK2Q", + "number": 17, + "url": "https://entire.com/et/forges-scratch/-/trails/17", + "title": "forges fixture 20261026210133: pull 3", + "body": "Opened by run 20261026210133.", + "bodyDocument": { + "id": "", + "document_key": "project-trail:01M5X0A6D5Q8H8VHFN7M7HTKRS:body", + "schema_version": 1, + "content_json": { + "type": "doc", + "content": [ + { + "type": "paragraph", + "content": [ + { + "type": "text", + "text": "Opened by run 20261026210133." + } + ] + } + ] + }, + "text_snapshot": "Opened by run 20261026210133.", + "updated_at": "2026-10-26T21:01:57.046Z", + "etag": "" + }, + "status": "open", + "phase": "building", + "metadata": {}, + "type": "task", + "priority": "none", + "assignees": [], + "assigneeAccountIds": [], + "repoIds": [ + "01M5WYSQC41P69DTXEMZ0TE5YK" + ], + "authorAccountId": "01M5WYRRVZNA1TXNET6KE4Q3WX", + "createdAt": "2026-10-26T21:01:57.028Z", + "metadataUpdatedAt": "2026-10-26T21:01:57.046Z", + "closedAt": null, + "lastVisitedAt": null, + "lastActivityAt": "2026-10-26T21:02:16.190Z", + "changes": [ + { + "id": "01M5X0A6DAPK6DZNKVR2KEJNF8", + "repositoryId": "01M5WYSQC41P69DTXEMZ0TE5YK", + "repository": "forges-fixtures", + "branch": "forges-fixtures/20261026210133-3", + "originalBranch": "forges-fixtures/20261026210133-3", + "base": "main", + "number": 11, + "title": "forges fixture 20261026210133: pull 3", + "status": "open", + "hasCodeChanges": true, + "createdAt": "2026-10-26T21:01:57.028Z", + "updatedAt": "2026-10-26T21:02:16.213Z", + "lastActivityAt": "2026-10-26T21:02:16.190Z", + "deployments": { + "availability": "available", + "ready": 0, + "total": 0 + }, + "readiness": "unknown", + "mergeability": { + "conflict_status": "unknown", + "head_sha": "", + "refreshed_at": null, + "forge_merge_block": null + } + } + ], + "isPossiblyPartial": true + } + } +} diff --git a/test/fixtures/entire/recorded/entire.com-writes/steps/pull-reopen/02-get-forges-fixtures-N.json b/test/fixtures/entire/recorded/entire.com-writes/steps/pull-reopen/02-get-forges-fixtures-N.json new file mode 100644 index 000000000..2cbdde5b5 --- /dev/null +++ b/test/fixtures/entire/recorded/entire.com-writes/steps/pull-reopen/02-get-forges-fixtures-N.json @@ -0,0 +1,262 @@ +{ + "request": { + "method": "GET", + "url": "https://aws-eu-central-1.api.entire.io/api/v1/trails/et/forges-scratch/forges-fixtures/11" + }, + "response": { + "status": 200, + "headers": { + "link": "; rel=\"describedBy\"" + }, + "body": { + "$schema": "https://aws-eu-central-1.api.entire.io/api/v1/schemas/TrailDetailResponse.json", + "id": "01M5X0A6DAPK6DZNKVR2KEJNF8", + "number": 11, + "url": "https://entire.com/et/forges-scratch/forges-fixtures/trails/11", + "title": "forges fixture 20261026210133: pull 3", + "status": "open", + "branch": "forges-fixtures/20261026210133-3", + "original_branch": "forges-fixtures/20261026210133-3", + "base": "main", + "type": "task", + "priority": "none", + "author": { + "id": "01M5WYRRVZNA1TXNET6KE4Q3WX", + "login": "danielroe-bot", + "identity": { + "kind": "account", + "account_id": "01M5WYRRVZNA1TXNET6KE4Q3WX", + "display_name": null, + "avatar_url": "https://avatars.githubusercontent.com/u/57801166?v=4", + "handles": [ + { + "provider": "github", + "handle": "danielroe-bot", + "is_primary": true + } + ] + } + }, + "assignees": [ + "danielroe-bot" + ], + "assignee_identities": [ + { + "login": "danielroe-bot", + "identity": { + "kind": "account", + "account_id": "01M5WYRRVZNA1TXNET6KE4Q3WX", + "display_name": null, + "avatar_url": "https://avatars.githubusercontent.com/u/57801166?v=4", + "handles": [ + { + "provider": "github", + "handle": "danielroe-bot", + "is_primary": true + } + ] + } + } + ], + "reviewers": [ + { + "login": "danielroe", + "status": "approved", + "actor_account_id": "01M5WRP9RJ4GVR2PA5PCNYP1FC", + "identity": { + "kind": "account", + "account_id": "01M5WRP9RJ4GVR2PA5PCNYP1FC", + "display_name": "Daniel Roe", + "avatar_url": "https://avatars.githubusercontent.com/u/28706372?v=4", + "handles": [ + { + "provider": "github", + "handle": "danielroe", + "is_primary": true + } + ] + } + } + ], + "ready_for_review": false, + "has_code_changes": true, + "comment_count": 0, + "unresolved_count": 0, + "created_at": "2026-10-26T21:01:57.028Z", + "updated_at": "2026-10-26T21:02:16.213Z", + "merged_at": null, + "last_activity_at": "2026-10-26T21:02:16.190Z", + "phase": "building", + "parent": { + "id": "01M5X0A6D5Q8H8VHFN7M7HTKRS", + "number": 17, + "project_id": "01M5WYSMPPYRBB13ZB20H7NK2Q", + "host": "et", + "project": "forges-scratch", + "path": "/api/v1/et/forges-scratch/trails/01M5X0A6D5Q8H8VHFN7M7HTKRS", + "jurisdiction": "eu", + "primary_processing_cell": "aws-eu-central-1", + "url": "https://entire.com/et/forges-scratch/-/trails/17" + }, + "branch_state": "present", + "code_changes": "present", + "lifecycle_sync": "settled", + "body_document": { + "id": "01M5X0A6DQ168SD36K14JNJPYW", + "document_key": "trail:01M5X0A6DAPK6DZNKVR2KEJNF8:body", + "schema_version": 1, + "content_json": { + "type": "doc", + "content": [ + { + "type": "paragraph" + } + ] + }, + "text_snapshot": "", + "updated_at": "2026-10-26T21:01:57.028Z", + "etag": "W/\"2026-10-26T21:01:57.02813Z\"" + }, + "monitors": [], + "agents": [], + "runners": [], + "actions": { + "approve": { + "state": "unavailable", + "reason": "not_ready_for_review" + }, + "create_ci_pr": { + "state": "unavailable", + "reason": "not_applicable" + }, + "merge": { + "state": "blocked", + "reason": "merge_gates_required" + }, + "merge_with_bypass": { + "state": "unavailable", + "reason": "merge_gates_bypass_forbidden" + }, + "update_branch": { + "state": "blocked", + "reason": "comparison_unavailable" + }, + "restore_branch": { + "state": "unavailable", + "reason": "trail_not_merged" + }, + "delete_branch": { + "state": "unavailable", + "reason": "trail_not_merged" + } + }, + "mergeability": { + "delete_branch_on_merge": false, + "bypass_policy": "nobody", + "mergeable": false, + "behind_by": 0, + "comparison_status": "unknown", + "conflict_status": "clean", + "head_sha": "f483a62c7214e4cead9ef1df09a663324a4825ae", + "gates": [ + { + "reviewers": [ + { + "login": "danielroe", + "actor_account_id": "01M5WRP9RJ4GVR2PA5PCNYP1FC", + "state": "approved", + "reviewed_head_sha": "f483a62c7214e4cead9ef1df09a663324a4825ae", + "reason": null + } + ], + "runner_ids": [], + "id": "", + "gate_definition_id": "01M5WZ6B2HAMXBN2SZ9TP2N3SN", + "gate_key": "approvals", + "gate_type": "approvals", + "blocking": true, + "status": "passed", + "head_sha": "f483a62c7214e4cead9ef1df09a663324a4825ae", + "value": { + "approved": 1, + "changes_requested": false, + "config": { + "version": 1, + "min_reviewers": 1, + "allow_self_approval": false, + "dismiss_stale_approvals_on_push": false + }, + "required": 1, + "self_excluded": false, + "stale_dismissed": 0, + "total": 1 + }, + "rationale": "1 approval(s) recorded", + "created_at": "2026-10-26T21:02:16.456969574Z", + "completed_at": "2026-10-26T21:02:16.456969574Z", + "state": "evaluated", + "outcome": "passed", + "stale_reason": null, + "evaluated_at_sha": "f483a62c7214e4cead9ef1df09a663324a4825ae", + "finding_count": null + }, + { + "reviewers": [], + "runner_ids": [], + "id": "", + "gate_definition_id": "01M5WZ6B2M8PSY34EM5YJGG6ZR", + "gate_key": "findings", + "gate_type": "findings", + "blocking": false, + "status": "pending", + "head_sha": "f483a62c7214e4cead9ef1df09a663324a4825ae", + "value": null, + "rationale": "Gate has not been evaluated yet", + "created_at": "2026-10-26T20:42:22.164428Z", + "completed_at": null, + "state": "not_run", + "outcome": null, + "stale_reason": null, + "evaluated_at_sha": null, + "finding_count": null + }, + { + "reviewers": [], + "runner_ids": [], + "id": "", + "gate_definition_id": "01M5WZ6B2PC2X2BE023RX01WEY", + "gate_key": "up_to_date", + "gate_type": "up_to_date", + "blocking": true, + "status": "pending", + "head_sha": "f483a62c7214e4cead9ef1df09a663324a4825ae", + "value": null, + "rationale": "Gate has not been evaluated yet", + "created_at": "2026-10-26T20:42:22.166595Z", + "completed_at": null, + "state": "not_run", + "outcome": null, + "stale_reason": null, + "evaluated_at_sha": null, + "finding_count": null + } + ], + "checks": { + "availability": "not_applicable", + "runs": [] + }, + "forge_merge_block": null + }, + "deployments": { + "availability": "available", + "ready": 0, + "total": 0, + "items": [] + }, + "config_source": "live", + "merge_base_sha": null, + "base_sha": null, + "head_sha": "f483a62c7214e4cead9ef1df09a663324a4825ae" + } + } +} diff --git a/test/fixtures/entire/recorded/entire.com-writes/steps/pull-reopen/03-patch-forges-fixtures-N.json b/test/fixtures/entire/recorded/entire.com-writes/steps/pull-reopen/03-patch-forges-fixtures-N.json new file mode 100644 index 000000000..27f8235c7 --- /dev/null +++ b/test/fixtures/entire/recorded/entire.com-writes/steps/pull-reopen/03-patch-forges-fixtures-N.json @@ -0,0 +1,118 @@ +{ + "request": { + "method": "PATCH", + "url": "https://aws-eu-central-1.api.entire.io/api/v1/trails/et/forges-scratch/forges-fixtures/11", + "body": { + "status": "open" + } + }, + "response": { + "status": 200, + "headers": { + "link": "; rel=\"describedBy\"", + "etag": "W/\"2026-10-26T21:02:16.213122Z\"" + }, + "body": { + "$schema": "https://aws-eu-central-1.api.entire.io/api/v1/schemas/TrailUpdateResponseBody.json", + "trail": { + "id": "01M5X0A6DAPK6DZNKVR2KEJNF8", + "number": 11, + "url": "https://entire.com/et/forges-scratch/forges-fixtures/trails/11", + "title": "forges fixture 20261026210133: pull 3", + "status": "open", + "branch": "forges-fixtures/20261026210133-3", + "original_branch": "forges-fixtures/20261026210133-3", + "base": "main", + "type": "task", + "priority": "none", + "author": { + "id": "01M5WYRRVZNA1TXNET6KE4Q3WX", + "login": "danielroe-bot", + "identity": { + "kind": "account", + "account_id": "01M5WYRRVZNA1TXNET6KE4Q3WX", + "display_name": null, + "avatar_url": "https://avatars.githubusercontent.com/u/57801166?v=4", + "handles": [ + { + "provider": "github", + "handle": "danielroe-bot", + "is_primary": true + } + ] + } + }, + "assignees": [ + "danielroe-bot" + ], + "assignee_identities": [ + { + "login": "danielroe-bot", + "identity": { + "kind": "account", + "account_id": "01M5WYRRVZNA1TXNET6KE4Q3WX", + "display_name": null, + "avatar_url": "https://avatars.githubusercontent.com/u/57801166?v=4", + "handles": [ + { + "provider": "github", + "handle": "danielroe-bot", + "is_primary": true + } + ] + } + } + ], + "reviewers": [ + { + "login": "danielroe", + "status": "approved", + "actor_account_id": "01M5WRP9RJ4GVR2PA5PCNYP1FC", + "identity": { + "kind": "account", + "account_id": "01M5WRP9RJ4GVR2PA5PCNYP1FC", + "display_name": "Daniel Roe", + "avatar_url": "https://avatars.githubusercontent.com/u/28706372?v=4", + "handles": [ + { + "provider": "github", + "handle": "danielroe", + "is_primary": true + } + ] + } + } + ], + "ready_for_review": false, + "has_code_changes": true, + "comment_count": 0, + "unresolved_count": 0, + "created_at": "2026-10-26T21:01:57.028Z", + "updated_at": "2026-10-26T21:02:16.213Z", + "merged_at": null, + "last_activity_at": "2026-10-26T21:02:16.190Z", + "phase": "building", + "checkpoint_count": 0, + "body_document": { + "id": "01M5X0A6DQ168SD36K14JNJPYW", + "document_key": "trail:01M5X0A6DAPK6DZNKVR2KEJNF8:body", + "schema_version": 1, + "content_json": { + "type": "doc", + "content": [ + { + "type": "paragraph" + } + ] + }, + "text_snapshot": "", + "updated_at": "2026-10-26T21:01:57.028Z", + "etag": "W/\"2026-10-26T21:01:57.02813Z\"" + }, + "merge_base_sha": null, + "base_sha": null, + "head_sha": "f483a62c7214e4cead9ef1df09a663324a4825ae" + } + } + } +} diff --git a/test/fixtures/entire/recorded/entire.com-writes/steps/pull-reopen/golden.json b/test/fixtures/entire/recorded/entire.com-writes/steps/pull-reopen/golden.json new file mode 100644 index 000000000..e33068638 --- /dev/null +++ b/test/fixtures/entire/recorded/entire.com-writes/steps/pull-reopen/golden.json @@ -0,0 +1,75 @@ +{ + "ref": { + "forge": "entire", + "instance": "entire.com", + "repo": { + "forge": "entire", + "instance": "entire.com", + "owner": "forges-scratch", + "name": "forges-fixtures" + }, + "kind": "pull_request", + "number": "11", + "externalId": "01M5X0A6DAPK6DZNKVR2KEJNF8" + }, + "kind": "pull_request", + "title": "forges fixture 20261026210133: pull 3", + "body": "Opened by run 20261026210133.", + "state": "open", + "stateRaw": "open", + "isDraft": true, + "author": { + "forge": "entire", + "instance": "entire.com", + "login": "danielroe-bot", + "id": "01M5WYRRVZNA1TXNET6KE4Q3WX", + "avatarUrl": "https://avatars.githubusercontent.com/u/57801166?v=4", + "isBotHint": false + }, + "assignees": [ + { + "forge": "entire", + "instance": "entire.com", + "login": "danielroe-bot", + "id": "01M5WYRRVZNA1TXNET6KE4Q3WX", + "avatarUrl": "https://avatars.githubusercontent.com/u/57801166?v=4", + "isBotHint": false + } + ], + "reviewers": [ + { + "actor": { + "forge": "entire", + "instance": "entire.com", + "login": "danielroe", + "id": "01M5WRP9RJ4GVR2PA5PCNYP1FC", + "name": "Daniel Roe", + "avatarUrl": "https://avatars.githubusercontent.com/u/28706372?v=4", + "isBotHint": false + }, + "state": "approved", + "stateRaw": "approved" + } + ], + "labels": [], + "url": "https://entire.com/et/forges-scratch/forges-fixtures/trails/11", + "createdAt": "", + "updatedAt": "", + "lastActivityAt": "", + "commentCount": 0, + "branches": { + "head": { + "ref": "forges-fixtures/20261026210133-3", + "sha": "f483a62c7214e4cead9ef1df09a663324a4825ae", + "repo": { + "forge": "entire", + "instance": "entire.com", + "owner": "forges-scratch", + "name": "forges-fixtures" + } + }, + "base": { + "ref": "main" + } + } +} diff --git a/test/fixtures/entire/recorded/entire.com-writes/steps/pull-reopen/step.json b/test/fixtures/entire/recorded/entire.com-writes/steps/pull-reopen/step.json new file mode 100644 index 000000000..d6ab4efc3 --- /dev/null +++ b/test/fixtures/entire/recorded/entire.com-writes/steps/pull-reopen/step.json @@ -0,0 +1,7 @@ +{ + "name": "pull reopen", + "recordedAt": "2026-10-26T21:02:15.772Z", + "needs": [ + "create third pull" + ] +} diff --git a/test/fixtures/entire/recorded/entire.com-writes/steps/pull-update-branch-by-rebase/01-get-forges-fixtures-N.json b/test/fixtures/entire/recorded/entire.com-writes/steps/pull-update-branch-by-rebase/01-get-forges-fixtures-N.json new file mode 100644 index 000000000..5c126f020 --- /dev/null +++ b/test/fixtures/entire/recorded/entire.com-writes/steps/pull-update-branch-by-rebase/01-get-forges-fixtures-N.json @@ -0,0 +1,262 @@ +{ + "request": { + "method": "GET", + "url": "https://aws-eu-central-1.api.entire.io/api/v1/trails/et/forges-scratch/forges-fixtures/11" + }, + "response": { + "status": 200, + "headers": { + "link": "; rel=\"describedBy\"" + }, + "body": { + "$schema": "https://aws-eu-central-1.api.entire.io/api/v1/schemas/TrailDetailResponse.json", + "id": "01M5X0A6DAPK6DZNKVR2KEJNF8", + "number": 11, + "url": "https://entire.com/et/forges-scratch/forges-fixtures/trails/11", + "title": "forges fixture 20261026210133: pull 3", + "status": "open", + "branch": "forges-fixtures/20261026210133-3", + "original_branch": "forges-fixtures/20261026210133-3", + "base": "main", + "type": "task", + "priority": "none", + "author": { + "id": "01M5WYRRVZNA1TXNET6KE4Q3WX", + "login": "danielroe-bot", + "identity": { + "kind": "account", + "account_id": "01M5WYRRVZNA1TXNET6KE4Q3WX", + "display_name": null, + "avatar_url": "https://avatars.githubusercontent.com/u/57801166?v=4", + "handles": [ + { + "provider": "github", + "handle": "danielroe-bot", + "is_primary": true + } + ] + } + }, + "assignees": [ + "danielroe-bot" + ], + "assignee_identities": [ + { + "login": "danielroe-bot", + "identity": { + "kind": "account", + "account_id": "01M5WYRRVZNA1TXNET6KE4Q3WX", + "display_name": null, + "avatar_url": "https://avatars.githubusercontent.com/u/57801166?v=4", + "handles": [ + { + "provider": "github", + "handle": "danielroe-bot", + "is_primary": true + } + ] + } + } + ], + "reviewers": [ + { + "login": "danielroe", + "status": "approved", + "actor_account_id": "01M5WRP9RJ4GVR2PA5PCNYP1FC", + "identity": { + "kind": "account", + "account_id": "01M5WRP9RJ4GVR2PA5PCNYP1FC", + "display_name": "Daniel Roe", + "avatar_url": "https://avatars.githubusercontent.com/u/28706372?v=4", + "handles": [ + { + "provider": "github", + "handle": "danielroe", + "is_primary": true + } + ] + } + } + ], + "ready_for_review": false, + "has_code_changes": true, + "comment_count": 0, + "unresolved_count": 0, + "created_at": "2026-10-26T21:01:57.028Z", + "updated_at": "2026-10-26T21:02:16.213Z", + "merged_at": null, + "last_activity_at": "2026-10-26T21:02:16.190Z", + "phase": "building", + "parent": { + "id": "01M5X0A6D5Q8H8VHFN7M7HTKRS", + "number": 17, + "project_id": "01M5WYSMPPYRBB13ZB20H7NK2Q", + "host": "et", + "project": "forges-scratch", + "path": "/api/v1/et/forges-scratch/trails/01M5X0A6D5Q8H8VHFN7M7HTKRS", + "jurisdiction": "eu", + "primary_processing_cell": "aws-eu-central-1", + "url": "https://entire.com/et/forges-scratch/-/trails/17" + }, + "branch_state": "present", + "code_changes": "present", + "lifecycle_sync": "settled", + "body_document": { + "id": "01M5X0A6DQ168SD36K14JNJPYW", + "document_key": "trail:01M5X0A6DAPK6DZNKVR2KEJNF8:body", + "schema_version": 1, + "content_json": { + "type": "doc", + "content": [ + { + "type": "paragraph" + } + ] + }, + "text_snapshot": "", + "updated_at": "2026-10-26T21:01:57.028Z", + "etag": "W/\"2026-10-26T21:01:57.02813Z\"" + }, + "monitors": [], + "agents": [], + "runners": [], + "actions": { + "approve": { + "state": "unavailable", + "reason": "not_ready_for_review" + }, + "create_ci_pr": { + "state": "unavailable", + "reason": "not_applicable" + }, + "merge": { + "state": "blocked", + "reason": "merge_gates_required" + }, + "merge_with_bypass": { + "state": "unavailable", + "reason": "merge_gates_bypass_forbidden" + }, + "update_branch": { + "state": "blocked", + "reason": "comparison_unavailable" + }, + "restore_branch": { + "state": "unavailable", + "reason": "trail_not_merged" + }, + "delete_branch": { + "state": "unavailable", + "reason": "trail_not_merged" + } + }, + "mergeability": { + "delete_branch_on_merge": false, + "bypass_policy": "nobody", + "mergeable": false, + "behind_by": 0, + "comparison_status": "unknown", + "conflict_status": "clean", + "head_sha": "f483a62c7214e4cead9ef1df09a663324a4825ae", + "gates": [ + { + "reviewers": [ + { + "login": "danielroe", + "actor_account_id": "01M5WRP9RJ4GVR2PA5PCNYP1FC", + "state": "approved", + "reviewed_head_sha": "f483a62c7214e4cead9ef1df09a663324a4825ae", + "reason": null + } + ], + "runner_ids": [], + "id": "", + "gate_definition_id": "01M5WZ6B2HAMXBN2SZ9TP2N3SN", + "gate_key": "approvals", + "gate_type": "approvals", + "blocking": true, + "status": "passed", + "head_sha": "f483a62c7214e4cead9ef1df09a663324a4825ae", + "value": { + "approved": 1, + "changes_requested": false, + "config": { + "version": 1, + "min_reviewers": 1, + "allow_self_approval": false, + "dismiss_stale_approvals_on_push": false + }, + "required": 1, + "self_excluded": false, + "stale_dismissed": 0, + "total": 1 + }, + "rationale": "1 approval(s) recorded", + "created_at": "2026-10-26T21:02:17.073853636Z", + "completed_at": "2026-10-26T21:02:17.073853636Z", + "state": "evaluated", + "outcome": "passed", + "stale_reason": null, + "evaluated_at_sha": "f483a62c7214e4cead9ef1df09a663324a4825ae", + "finding_count": null + }, + { + "reviewers": [], + "runner_ids": [], + "id": "", + "gate_definition_id": "01M5WZ6B2M8PSY34EM5YJGG6ZR", + "gate_key": "findings", + "gate_type": "findings", + "blocking": false, + "status": "pending", + "head_sha": "f483a62c7214e4cead9ef1df09a663324a4825ae", + "value": null, + "rationale": "Gate has not been evaluated yet", + "created_at": "2026-10-26T20:42:22.164428Z", + "completed_at": null, + "state": "not_run", + "outcome": null, + "stale_reason": null, + "evaluated_at_sha": null, + "finding_count": null + }, + { + "reviewers": [], + "runner_ids": [], + "id": "", + "gate_definition_id": "01M5WZ6B2PC2X2BE023RX01WEY", + "gate_key": "up_to_date", + "gate_type": "up_to_date", + "blocking": true, + "status": "pending", + "head_sha": "f483a62c7214e4cead9ef1df09a663324a4825ae", + "value": null, + "rationale": "Gate has not been evaluated yet", + "created_at": "2026-10-26T20:42:22.166595Z", + "completed_at": null, + "state": "not_run", + "outcome": null, + "stale_reason": null, + "evaluated_at_sha": null, + "finding_count": null + } + ], + "checks": { + "availability": "not_applicable", + "runs": [] + }, + "forge_merge_block": null + }, + "deployments": { + "availability": "available", + "ready": 0, + "total": 0, + "items": [] + }, + "config_source": "live", + "merge_base_sha": null, + "base_sha": null, + "head_sha": "f483a62c7214e4cead9ef1df09a663324a4825ae" + } + } +} diff --git a/test/fixtures/entire/recorded/entire.com-writes/steps/pull-update-branch-by-rebase/02-post-01M5WYSQC41P69DTXEMZ0TE5YK-rebases.json b/test/fixtures/entire/recorded/entire.com-writes/steps/pull-update-branch-by-rebase/02-post-01M5WYSQC41P69DTXEMZ0TE5YK-rebases.json new file mode 100644 index 000000000..0e78a5113 --- /dev/null +++ b/test/fixtures/entire/recorded/entire.com-writes/steps/pull-update-branch-by-rebase/02-post-01M5WYSQC41P69DTXEMZ0TE5YK-rebases.json @@ -0,0 +1,16 @@ +{ + "request": { + "method": "POST", + "url": "https://aws-eu-central-1.api.entire.io/api/v1/git/repos/01M5WYSQC41P69DTXEMZ0TE5YK/rebases", + "body": { + "branch": "forges-fixtures/20261026210133-3", + "onto": "main", + "expectedBranchSHA": "f483a62c7214e4cead9ef1df09a663324a4825ae" + } + }, + "response": { + "status": 200, + "headers": {}, + "body": "{\"type\":\"started\",\"mergeBaseSHA\":\"80c3e7d4c9f5e16f4e11cf7737f571c513d14ac2\",\"commitsToApply\":[\"f483a62c7214e4cead9ef1df09a663324a4825ae\"],\"ontoTipSHA\":\"9f5e93477cecca4f94f1888d8680ab55c75fccba\"}\n{\"type\":\"applied\",\"originalSHA\":\"f483a62c7214e4cead9ef1df09a663324a4825ae\",\"newSHA\":\"553f4166982b4a17d17dfd37ec253da9440d01ab\"}\n{\"type\":\"completed\",\"newBranchSHA\":\"553f4166982b4a17d17dfd37ec253da9440d01ab\",\"mapping\":[{\"originalSHA\":\"f483a62c7214e4cead9ef1df09a663324a4825ae\",\"newSHA\":\"553f4166982b4a17d17dfd37ec253da9440d01ab\",\"dropped\":false}]}\n" + } +} diff --git a/test/fixtures/entire/recorded/entire.com-writes/steps/pull-update-branch-by-rebase/golden.json b/test/fixtures/entire/recorded/entire.com-writes/steps/pull-update-branch-by-rebase/golden.json new file mode 100644 index 000000000..705afed38 --- /dev/null +++ b/test/fixtures/entire/recorded/entire.com-writes/steps/pull-update-branch-by-rebase/golden.json @@ -0,0 +1,3 @@ +{ + "status": "updated" +} diff --git a/test/fixtures/entire/recorded/entire.com-writes/steps/pull-update-branch-by-rebase/step.json b/test/fixtures/entire/recorded/entire.com-writes/steps/pull-update-branch-by-rebase/step.json new file mode 100644 index 000000000..1ea1d5cf9 --- /dev/null +++ b/test/fixtures/entire/recorded/entire.com-writes/steps/pull-update-branch-by-rebase/step.json @@ -0,0 +1,7 @@ +{ + "name": "pull update branch by rebase", + "recordedAt": "2026-10-26T21:02:16.756Z", + "needs": [ + "create third pull" + ] +} diff --git a/test/fixtures/entire/recorded/entire.com-writes/steps/pull-update-branch/01-get-forges-fixtures-N.json b/test/fixtures/entire/recorded/entire.com-writes/steps/pull-update-branch/01-get-forges-fixtures-N.json new file mode 100644 index 000000000..0480b308d --- /dev/null +++ b/test/fixtures/entire/recorded/entire.com-writes/steps/pull-update-branch/01-get-forges-fixtures-N.json @@ -0,0 +1,286 @@ +{ + "request": { + "method": "GET", + "url": "https://aws-eu-central-1.api.entire.io/api/v1/trails/et/forges-scratch/forges-fixtures/11" + }, + "response": { + "status": 200, + "headers": { + "link": "; rel=\"describedBy\"" + }, + "body": { + "$schema": "https://aws-eu-central-1.api.entire.io/api/v1/schemas/TrailDetailResponse.json", + "id": "01M5X0A6DAPK6DZNKVR2KEJNF8", + "number": 11, + "url": "https://entire.com/et/forges-scratch/forges-fixtures/trails/11", + "title": "forges fixture 20261026210133: pull 3", + "status": "open", + "branch": "forges-fixtures/20261026210133-3", + "original_branch": "forges-fixtures/20261026210133-3", + "base": "main", + "type": "task", + "priority": "none", + "author": { + "id": "01M5WYRRVZNA1TXNET6KE4Q3WX", + "login": "danielroe-bot", + "identity": { + "kind": "account", + "account_id": "01M5WYRRVZNA1TXNET6KE4Q3WX", + "display_name": null, + "avatar_url": "https://avatars.githubusercontent.com/u/57801166?v=4", + "handles": [ + { + "provider": "github", + "handle": "danielroe-bot", + "is_primary": true + } + ] + } + }, + "assignees": [ + "danielroe-bot" + ], + "assignee_identities": [ + { + "login": "danielroe-bot", + "identity": { + "kind": "account", + "account_id": "01M5WYRRVZNA1TXNET6KE4Q3WX", + "display_name": null, + "avatar_url": "https://avatars.githubusercontent.com/u/57801166?v=4", + "handles": [ + { + "provider": "github", + "handle": "danielroe-bot", + "is_primary": true + } + ] + } + } + ], + "reviewers": [ + { + "login": "danielroe", + "status": "approved", + "actor_account_id": "01M5WRP9RJ4GVR2PA5PCNYP1FC", + "identity": { + "kind": "account", + "account_id": "01M5WRP9RJ4GVR2PA5PCNYP1FC", + "display_name": "Daniel Roe", + "avatar_url": "https://avatars.githubusercontent.com/u/28706372?v=4", + "handles": [ + { + "provider": "github", + "handle": "danielroe", + "is_primary": true + } + ] + } + } + ], + "ready_for_review": false, + "has_code_changes": true, + "comment_count": 0, + "unresolved_count": 0, + "created_at": "2026-10-26T21:01:57.028Z", + "updated_at": "2026-10-26T21:02:17.316Z", + "merged_at": null, + "last_activity_at": "2026-10-26T21:02:17.318Z", + "phase": "building", + "parent": { + "id": "01M5X0A6D5Q8H8VHFN7M7HTKRS", + "number": 17, + "project_id": "01M5WYSMPPYRBB13ZB20H7NK2Q", + "host": "et", + "project": "forges-scratch", + "path": "/api/v1/et/forges-scratch/trails/01M5X0A6D5Q8H8VHFN7M7HTKRS", + "jurisdiction": "eu", + "primary_processing_cell": "aws-eu-central-1", + "url": "https://entire.com/et/forges-scratch/-/trails/17" + }, + "branch_state": "present", + "code_changes": "present", + "lifecycle_sync": "settled", + "body_document": { + "id": "01M5X0A6DQ168SD36K14JNJPYW", + "document_key": "trail:01M5X0A6DAPK6DZNKVR2KEJNF8:body", + "schema_version": 1, + "content_json": { + "type": "doc", + "content": [ + { + "type": "paragraph" + } + ] + }, + "text_snapshot": "", + "updated_at": "2026-10-26T21:01:57.028Z", + "etag": "W/\"2026-10-26T21:01:57.02813Z\"" + }, + "monitors": [], + "agents": [], + "runners": [], + "actions": { + "approve": { + "state": "unavailable", + "reason": "not_ready_for_review" + }, + "create_ci_pr": { + "state": "unavailable", + "reason": "not_applicable" + }, + "merge": { + "state": "enabled", + "reason": null + }, + "merge_with_bypass": { + "state": "unavailable", + "reason": "bypass_not_required" + }, + "update_branch": { + "state": "unavailable", + "reason": "branch_up_to_date" + }, + "restore_branch": { + "state": "unavailable", + "reason": "trail_not_merged" + }, + "delete_branch": { + "state": "unavailable", + "reason": "trail_not_merged" + } + }, + "mergeability": { + "delete_branch_on_merge": false, + "bypass_policy": "nobody", + "mergeable": true, + "behind_by": 0, + "comparison_status": "available", + "conflict_status": "clean", + "head_sha": "553f4166982b4a17d17dfd37ec253da9440d01ab", + "gates": [ + { + "reviewers": [ + { + "login": "danielroe", + "actor_account_id": "01M5WRP9RJ4GVR2PA5PCNYP1FC", + "state": "approved", + "reviewed_head_sha": "f483a62c7214e4cead9ef1df09a663324a4825ae", + "reason": null + } + ], + "runner_ids": [], + "id": "", + "gate_definition_id": "01M5WZ6B2HAMXBN2SZ9TP2N3SN", + "gate_key": "approvals", + "gate_type": "approvals", + "blocking": true, + "status": "passed", + "head_sha": "553f4166982b4a17d17dfd37ec253da9440d01ab", + "value": { + "approved": 1, + "changes_requested": false, + "config": { + "version": 1, + "min_reviewers": 1, + "allow_self_approval": false, + "dismiss_stale_approvals_on_push": false + }, + "required": 1, + "self_excluded": false, + "stale_dismissed": 0, + "total": 1 + }, + "rationale": "1 approval(s) recorded", + "created_at": "2026-10-26T21:02:17.480094293Z", + "completed_at": "2026-10-26T21:02:17.480094293Z", + "state": "evaluated", + "outcome": "passed", + "stale_reason": null, + "evaluated_at_sha": "553f4166982b4a17d17dfd37ec253da9440d01ab", + "finding_count": null + }, + { + "reviewers": [], + "runner_ids": [], + "id": "01M5X0AT98BGQN9K7BC7RM57B2", + "gate_definition_id": "01M5WZ6B2M8PSY34EM5YJGG6ZR", + "gate_key": "findings", + "gate_type": "findings", + "blocking": false, + "status": "passed", + "head_sha": "553f4166982b4a17d17dfd37ec253da9440d01ab", + "value": { + "config": { + "version": 1, + "agent_findings_min_severity": "high" + }, + "reviewed_head": false, + "agent_findings": { + "low": 0, + "high": 0, + "medium": 0, + "unspecified": 0 + }, + "review_in_flight": false, + "reviewer_configured": false, + "review_grace_expired": false, + "agent_blocking_findings": 0 + }, + "rationale": "No blocking findings", + "created_at": "2026-10-26T21:02:17.384974Z", + "completed_at": "2026-10-26T21:02:17.384974Z", + "state": "evaluated", + "outcome": "passed", + "stale_reason": null, + "evaluated_at_sha": "553f4166982b4a17d17dfd37ec253da9440d01ab", + "finding_count": 0 + }, + { + "reviewers": [], + "runner_ids": [], + "id": "01M5X0ATAH24JW8AN09P13R793", + "gate_definition_id": "01M5WZ6B2PC2X2BE023RX01WEY", + "gate_key": "up_to_date", + "gate_type": "up_to_date", + "blocking": true, + "status": "passed", + "head_sha": "553f4166982b4a17d17dfd37ec253da9440d01ab", + "value": { + "config": { + "version": 1, + "allow_behind_if_mergeable": false + }, + "behind_by": 0, + "compare_status": "ahead", + "comparison_status": "available" + }, + "rationale": "Up to date", + "created_at": "2026-10-26T21:02:17.425879Z", + "completed_at": "2026-10-26T21:02:17.425879Z", + "state": "evaluated", + "outcome": "passed", + "stale_reason": null, + "evaluated_at_sha": "553f4166982b4a17d17dfd37ec253da9440d01ab", + "finding_count": null + } + ], + "checks": { + "availability": "not_applicable", + "runs": [] + }, + "forge_merge_block": null + }, + "deployments": { + "availability": "available", + "ready": 0, + "total": 0, + "items": [] + }, + "config_source": "live", + "merge_base_sha": null, + "base_sha": null, + "head_sha": "553f4166982b4a17d17dfd37ec253da9440d01ab" + } + } +} diff --git a/test/fixtures/entire/recorded/entire.com-writes/steps/pull-update-branch/02-post-N-update-branch.json b/test/fixtures/entire/recorded/entire.com-writes/steps/pull-update-branch/02-post-N-update-branch.json new file mode 100644 index 000000000..28b30c922 --- /dev/null +++ b/test/fixtures/entire/recorded/entire.com-writes/steps/pull-update-branch/02-post-N-update-branch.json @@ -0,0 +1,16 @@ +{ + "request": { + "method": "POST", + "url": "https://aws-eu-central-1.api.entire.io/api/v1/repos/01M5WYSQC41P69DTXEMZ0TE5YK/trails/11/update-branch" + }, + "response": { + "status": 200, + "headers": { + "link": "; rel=\"describedBy\"" + }, + "body": { + "$schema": "https://aws-eu-central-1.api.entire.io/api/v1/schemas/TrailUpdateBranchResponse.json", + "mergeCommitSha": "" + } + } +} diff --git a/test/fixtures/entire/recorded/entire.com-writes/steps/pull-update-branch/golden.json b/test/fixtures/entire/recorded/entire.com-writes/steps/pull-update-branch/golden.json new file mode 100644 index 000000000..705afed38 --- /dev/null +++ b/test/fixtures/entire/recorded/entire.com-writes/steps/pull-update-branch/golden.json @@ -0,0 +1,3 @@ +{ + "status": "updated" +} diff --git a/test/fixtures/entire/recorded/entire.com-writes/steps/pull-update-branch/step.json b/test/fixtures/entire/recorded/entire.com-writes/steps/pull-update-branch/step.json new file mode 100644 index 000000000..2ec93ead3 --- /dev/null +++ b/test/fixtures/entire/recorded/entire.com-writes/steps/pull-update-branch/step.json @@ -0,0 +1,7 @@ +{ + "name": "pull update branch", + "recordedAt": "2026-10-26T21:02:17.363Z", + "needs": [ + "create third pull" + ] +} diff --git a/test/fixtures/entire/recorded/entire.com-writes/steps/pull-update/01-get-trails-01M5X0A493RSBKDGYF0ZWVG8E9.json b/test/fixtures/entire/recorded/entire.com-writes/steps/pull-update/01-get-trails-01M5X0A493RSBKDGYF0ZWVG8E9.json new file mode 100644 index 000000000..a3e8772a7 --- /dev/null +++ b/test/fixtures/entire/recorded/entire.com-writes/steps/pull-update/01-get-trails-01M5X0A493RSBKDGYF0ZWVG8E9.json @@ -0,0 +1,127 @@ +{ + "request": { + "method": "GET", + "url": "https://aws-eu-central-1.api.entire.io/api/v1/et/forges-scratch/trails/01M5X0A493RSBKDGYF0ZWVG8E9" + }, + "response": { + "status": 200, + "headers": { + "link": "; rel=\"describedBy\"", + "etag": "W/\"2026-10-26T21:02:04.373663Z\"" + }, + "body": { + "$schema": "https://aws-eu-central-1.api.entire.io/api/v1/schemas/TrailResponse.json", + "capabilities": { + "canEdit": true, + "canManageScope": true + }, + "project": { + "primaryProcessingCell": "aws-eu-central-1", + "id": "01M5WYSMPPYRBB13ZB20H7NK2Q", + "name": "forges-scratch", + "provider": "entire", + "reference": { + "forge": "et", + "project": "forges-scratch" + }, + "jurisdiction": "eu", + "capabilities": { + "canManageTrails": true + } + }, + "author": { + "accountId": "01M5WYRRVZNA1TXNET6KE4Q3WX", + "login": "danielroe-bot", + "displayName": "", + "avatarUrl": "https://avatars.githubusercontent.com/u/57801166?v=4", + "identity": { + "kind": "account", + "account_id": "01M5WYRRVZNA1TXNET6KE4Q3WX", + "display_name": null, + "avatar_url": "https://avatars.githubusercontent.com/u/57801166?v=4", + "handles": [ + { + "provider": "github", + "handle": "danielroe-bot", + "is_primary": true + } + ] + } + }, + "id": "01M5X0A493RSBKDGYF0ZWVG8E9", + "projectId": "01M5WYSMPPYRBB13ZB20H7NK2Q", + "number": 15, + "url": "https://entire.com/et/forges-scratch/-/trails/15", + "title": "forges fixture 20261026210133: pull 1", + "body": "Edited by run 20261026210133.", + "bodyDocument": { + "id": "", + "document_key": "project-trail:01M5X0A493RSBKDGYF0ZWVG8E9:body", + "schema_version": 1, + "content_json": { + "type": "doc", + "content": [ + { + "type": "paragraph", + "content": [ + { + "type": "text", + "text": "Edited by run 20261026210133." + } + ] + } + ] + }, + "text_snapshot": "Edited by run 20261026210133.", + "updated_at": "2026-10-26T21:02:04.373Z", + "etag": "" + }, + "status": "open", + "phase": "building", + "metadata": {}, + "type": "task", + "priority": "none", + "assignees": [], + "assigneeAccountIds": [], + "repoIds": [ + "01M5WYSQC41P69DTXEMZ0TE5YK" + ], + "authorAccountId": "01M5WYRRVZNA1TXNET6KE4Q3WX", + "createdAt": "2026-10-26T21:01:54.849Z", + "metadataUpdatedAt": "2026-10-26T21:02:04.373Z", + "closedAt": null, + "lastVisitedAt": null, + "lastActivityAt": "2026-10-26T21:02:04.373Z", + "changes": [ + { + "id": "01M5X0A49M70NAMJX878FD2QD1", + "repositoryId": "01M5WYSQC41P69DTXEMZ0TE5YK", + "repository": "forges-fixtures", + "branch": "forges-fixtures/20261026210133-1", + "originalBranch": "forges-fixtures/20261026210133-1", + "base": "main", + "number": 9, + "title": "forges fixture 20261026210133: pull, edited", + "status": "open", + "hasCodeChanges": true, + "createdAt": "2026-10-26T21:01:54.849Z", + "updatedAt": "2026-10-26T21:02:03.358Z", + "lastActivityAt": "2026-10-26T21:02:03.358Z", + "deployments": { + "availability": "available", + "ready": 0, + "total": 0 + }, + "readiness": "in_review", + "mergeability": { + "conflict_status": "unknown", + "head_sha": "", + "refreshed_at": null, + "forge_merge_block": null + } + } + ], + "isPossiblyPartial": true + } + } +} diff --git a/test/fixtures/entire/recorded/entire.com-writes/steps/pull-update/02-get-forges-fixtures-N.json b/test/fixtures/entire/recorded/entire.com-writes/steps/pull-update/02-get-forges-fixtures-N.json new file mode 100644 index 000000000..60f018da1 --- /dev/null +++ b/test/fixtures/entire/recorded/entire.com-writes/steps/pull-update/02-get-forges-fixtures-N.json @@ -0,0 +1,243 @@ +{ + "request": { + "method": "GET", + "url": "https://aws-eu-central-1.api.entire.io/api/v1/trails/et/forges-scratch/forges-fixtures/9" + }, + "response": { + "status": 200, + "headers": { + "link": "; rel=\"describedBy\"" + }, + "body": { + "$schema": "https://aws-eu-central-1.api.entire.io/api/v1/schemas/TrailDetailResponse.json", + "id": "01M5X0A49M70NAMJX878FD2QD1", + "number": 9, + "url": "https://entire.com/et/forges-scratch/forges-fixtures/trails/9", + "title": "forges fixture 20261026210133: pull, edited", + "status": "open", + "branch": "forges-fixtures/20261026210133-1", + "original_branch": "forges-fixtures/20261026210133-1", + "base": "main", + "type": "task", + "priority": "none", + "author": { + "id": "01M5WYRRVZNA1TXNET6KE4Q3WX", + "login": "danielroe-bot", + "identity": { + "kind": "account", + "account_id": "01M5WYRRVZNA1TXNET6KE4Q3WX", + "display_name": null, + "avatar_url": "https://avatars.githubusercontent.com/u/57801166?v=4", + "handles": [ + { + "provider": "github", + "handle": "danielroe-bot", + "is_primary": true + } + ] + } + }, + "assignees": [ + "danielroe-bot" + ], + "assignee_identities": [ + { + "login": "danielroe-bot", + "identity": { + "kind": "account", + "account_id": "01M5WYRRVZNA1TXNET6KE4Q3WX", + "display_name": null, + "avatar_url": "https://avatars.githubusercontent.com/u/57801166?v=4", + "handles": [ + { + "provider": "github", + "handle": "danielroe-bot", + "is_primary": true + } + ] + } + } + ], + "reviewers": [], + "ready_for_review": true, + "has_code_changes": true, + "comment_count": 1, + "unresolved_count": 1, + "created_at": "2026-10-26T21:01:54.849Z", + "updated_at": "2026-10-26T21:02:03.358Z", + "merged_at": null, + "last_activity_at": "2026-10-26T21:02:03.358Z", + "phase": "reviewing", + "parent": { + "id": "01M5X0A493RSBKDGYF0ZWVG8E9", + "number": 15, + "project_id": "01M5WYSMPPYRBB13ZB20H7NK2Q", + "host": "et", + "project": "forges-scratch", + "path": "/api/v1/et/forges-scratch/trails/01M5X0A493RSBKDGYF0ZWVG8E9", + "jurisdiction": "eu", + "primary_processing_cell": "aws-eu-central-1", + "url": "https://entire.com/et/forges-scratch/-/trails/15" + }, + "branch_state": "present", + "code_changes": "present", + "lifecycle_sync": "settled", + "body_document": { + "id": "01M5X0A4AGRFN6FB08AYTPCF6X", + "document_key": "trail:01M5X0A49M70NAMJX878FD2QD1:body", + "schema_version": 1, + "content_json": { + "type": "doc", + "content": [ + { + "type": "paragraph" + } + ] + }, + "text_snapshot": "", + "updated_at": "2026-10-26T21:01:54.849Z", + "etag": "W/\"2026-10-26T21:01:54.849162Z\"" + }, + "monitors": [], + "agents": [], + "runners": [], + "actions": { + "approve": { + "state": "blocked", + "reason": "self_approval_not_allowed" + }, + "create_ci_pr": { + "state": "unavailable", + "reason": "not_applicable" + }, + "merge": { + "state": "blocked", + "reason": "merge_gates_required" + }, + "merge_with_bypass": { + "state": "unavailable", + "reason": "merge_gates_bypass_forbidden" + }, + "update_branch": { + "state": "unavailable", + "reason": "branch_up_to_date" + }, + "restore_branch": { + "state": "unavailable", + "reason": "trail_not_merged" + }, + "delete_branch": { + "state": "unavailable", + "reason": "trail_not_merged" + } + }, + "mergeability": { + "delete_branch_on_merge": false, + "bypass_policy": "nobody", + "mergeable": false, + "behind_by": 0, + "comparison_status": "available", + "conflict_status": "clean", + "head_sha": "9f5e93477cecca4f94f1888d8680ab55c75fccba", + "gates": [ + { + "reviewers": [], + "runner_ids": [], + "id": "", + "gate_definition_id": "01M5WZ6B2HAMXBN2SZ9TP2N3SN", + "gate_key": "approvals", + "gate_type": "approvals", + "blocking": true, + "status": "failed", + "head_sha": "9f5e93477cecca4f94f1888d8680ab55c75fccba", + "value": { + "approved": 0, + "changes_requested": false, + "config": { + "version": 1, + "min_reviewers": 1, + "allow_self_approval": false, + "dismiss_stale_approvals_on_push": false + }, + "required": 1, + "self_excluded": false, + "stale_dismissed": 0, + "total": 0 + }, + "rationale": "No reviewers have approved this trail", + "created_at": "2026-10-26T21:02:03.593036408Z", + "completed_at": "2026-10-26T21:02:03.593036408Z", + "state": "evaluated", + "outcome": "failed", + "stale_reason": null, + "evaluated_at_sha": "9f5e93477cecca4f94f1888d8680ab55c75fccba", + "finding_count": null + }, + { + "reviewers": [], + "runner_ids": [], + "id": "", + "gate_definition_id": "01M5WZ6B2M8PSY34EM5YJGG6ZR", + "gate_key": "findings", + "gate_type": "findings", + "blocking": false, + "status": "pending", + "head_sha": "9f5e93477cecca4f94f1888d8680ab55c75fccba", + "value": null, + "rationale": "Gate has not been evaluated yet", + "created_at": "2026-10-26T20:42:22.164428Z", + "completed_at": null, + "state": "not_run", + "outcome": null, + "stale_reason": null, + "evaluated_at_sha": null, + "finding_count": null + }, + { + "reviewers": [], + "runner_ids": [], + "id": "01M5X0A4D1WK6QWSP6JXWFERW1", + "gate_definition_id": "01M5WZ6B2PC2X2BE023RX01WEY", + "gate_key": "up_to_date", + "gate_type": "up_to_date", + "blocking": true, + "status": "passed", + "head_sha": "9f5e93477cecca4f94f1888d8680ab55c75fccba", + "value": { + "config": { + "version": 1, + "allow_behind_if_mergeable": false + }, + "behind_by": 0, + "compare_status": "ahead", + "comparison_status": "available" + }, + "rationale": "Up to date", + "created_at": "2026-10-26T21:01:54.977313Z", + "completed_at": "2026-10-26T21:01:54.977313Z", + "state": "evaluated", + "outcome": "passed", + "stale_reason": null, + "evaluated_at_sha": "9f5e93477cecca4f94f1888d8680ab55c75fccba", + "finding_count": null + } + ], + "checks": { + "availability": "not_applicable", + "runs": [] + }, + "forge_merge_block": null + }, + "deployments": { + "availability": "available", + "ready": 0, + "total": 0, + "items": [] + }, + "config_source": "live", + "merge_base_sha": null, + "base_sha": null, + "head_sha": "9f5e93477cecca4f94f1888d8680ab55c75fccba" + } + } +} diff --git a/test/fixtures/entire/recorded/entire.com-writes/steps/pull-update/03-get-forges-fixtures-N.json b/test/fixtures/entire/recorded/entire.com-writes/steps/pull-update/03-get-forges-fixtures-N.json new file mode 100644 index 000000000..47abd9cfb --- /dev/null +++ b/test/fixtures/entire/recorded/entire.com-writes/steps/pull-update/03-get-forges-fixtures-N.json @@ -0,0 +1,243 @@ +{ + "request": { + "method": "GET", + "url": "https://aws-eu-central-1.api.entire.io/api/v1/trails/et/forges-scratch/forges-fixtures/9" + }, + "response": { + "status": 200, + "headers": { + "link": "; rel=\"describedBy\"" + }, + "body": { + "$schema": "https://aws-eu-central-1.api.entire.io/api/v1/schemas/TrailDetailResponse.json", + "id": "01M5X0A49M70NAMJX878FD2QD1", + "number": 9, + "url": "https://entire.com/et/forges-scratch/forges-fixtures/trails/9", + "title": "forges fixture 20261026210133: pull, edited", + "status": "open", + "branch": "forges-fixtures/20261026210133-1", + "original_branch": "forges-fixtures/20261026210133-1", + "base": "main", + "type": "task", + "priority": "none", + "author": { + "id": "01M5WYRRVZNA1TXNET6KE4Q3WX", + "login": "danielroe-bot", + "identity": { + "kind": "account", + "account_id": "01M5WYRRVZNA1TXNET6KE4Q3WX", + "display_name": null, + "avatar_url": "https://avatars.githubusercontent.com/u/57801166?v=4", + "handles": [ + { + "provider": "github", + "handle": "danielroe-bot", + "is_primary": true + } + ] + } + }, + "assignees": [ + "danielroe-bot" + ], + "assignee_identities": [ + { + "login": "danielroe-bot", + "identity": { + "kind": "account", + "account_id": "01M5WYRRVZNA1TXNET6KE4Q3WX", + "display_name": null, + "avatar_url": "https://avatars.githubusercontent.com/u/57801166?v=4", + "handles": [ + { + "provider": "github", + "handle": "danielroe-bot", + "is_primary": true + } + ] + } + } + ], + "reviewers": [], + "ready_for_review": true, + "has_code_changes": true, + "comment_count": 1, + "unresolved_count": 1, + "created_at": "2026-10-26T21:01:54.849Z", + "updated_at": "2026-10-26T21:02:03.358Z", + "merged_at": null, + "last_activity_at": "2026-10-26T21:02:03.358Z", + "phase": "reviewing", + "parent": { + "id": "01M5X0A493RSBKDGYF0ZWVG8E9", + "number": 15, + "project_id": "01M5WYSMPPYRBB13ZB20H7NK2Q", + "host": "et", + "project": "forges-scratch", + "path": "/api/v1/et/forges-scratch/trails/01M5X0A493RSBKDGYF0ZWVG8E9", + "jurisdiction": "eu", + "primary_processing_cell": "aws-eu-central-1", + "url": "https://entire.com/et/forges-scratch/-/trails/15" + }, + "branch_state": "present", + "code_changes": "present", + "lifecycle_sync": "settled", + "body_document": { + "id": "01M5X0A4AGRFN6FB08AYTPCF6X", + "document_key": "trail:01M5X0A49M70NAMJX878FD2QD1:body", + "schema_version": 1, + "content_json": { + "type": "doc", + "content": [ + { + "type": "paragraph" + } + ] + }, + "text_snapshot": "", + "updated_at": "2026-10-26T21:01:54.849Z", + "etag": "W/\"2026-10-26T21:01:54.849162Z\"" + }, + "monitors": [], + "agents": [], + "runners": [], + "actions": { + "approve": { + "state": "blocked", + "reason": "self_approval_not_allowed" + }, + "create_ci_pr": { + "state": "unavailable", + "reason": "not_applicable" + }, + "merge": { + "state": "blocked", + "reason": "merge_gates_required" + }, + "merge_with_bypass": { + "state": "unavailable", + "reason": "merge_gates_bypass_forbidden" + }, + "update_branch": { + "state": "unavailable", + "reason": "branch_up_to_date" + }, + "restore_branch": { + "state": "unavailable", + "reason": "trail_not_merged" + }, + "delete_branch": { + "state": "unavailable", + "reason": "trail_not_merged" + } + }, + "mergeability": { + "delete_branch_on_merge": false, + "bypass_policy": "nobody", + "mergeable": false, + "behind_by": 0, + "comparison_status": "available", + "conflict_status": "clean", + "head_sha": "9f5e93477cecca4f94f1888d8680ab55c75fccba", + "gates": [ + { + "reviewers": [], + "runner_ids": [], + "id": "", + "gate_definition_id": "01M5WZ6B2HAMXBN2SZ9TP2N3SN", + "gate_key": "approvals", + "gate_type": "approvals", + "blocking": true, + "status": "failed", + "head_sha": "9f5e93477cecca4f94f1888d8680ab55c75fccba", + "value": { + "approved": 0, + "changes_requested": false, + "config": { + "version": 1, + "min_reviewers": 1, + "allow_self_approval": false, + "dismiss_stale_approvals_on_push": false + }, + "required": 1, + "self_excluded": false, + "stale_dismissed": 0, + "total": 0 + }, + "rationale": "No reviewers have approved this trail", + "created_at": "2026-10-26T21:02:04.612485905Z", + "completed_at": "2026-10-26T21:02:04.612485905Z", + "state": "evaluated", + "outcome": "failed", + "stale_reason": null, + "evaluated_at_sha": "9f5e93477cecca4f94f1888d8680ab55c75fccba", + "finding_count": null + }, + { + "reviewers": [], + "runner_ids": [], + "id": "", + "gate_definition_id": "01M5WZ6B2M8PSY34EM5YJGG6ZR", + "gate_key": "findings", + "gate_type": "findings", + "blocking": false, + "status": "pending", + "head_sha": "9f5e93477cecca4f94f1888d8680ab55c75fccba", + "value": null, + "rationale": "Gate has not been evaluated yet", + "created_at": "2026-10-26T20:42:22.164428Z", + "completed_at": null, + "state": "not_run", + "outcome": null, + "stale_reason": null, + "evaluated_at_sha": null, + "finding_count": null + }, + { + "reviewers": [], + "runner_ids": [], + "id": "01M5X0A4D1WK6QWSP6JXWFERW1", + "gate_definition_id": "01M5WZ6B2PC2X2BE023RX01WEY", + "gate_key": "up_to_date", + "gate_type": "up_to_date", + "blocking": true, + "status": "passed", + "head_sha": "9f5e93477cecca4f94f1888d8680ab55c75fccba", + "value": { + "config": { + "version": 1, + "allow_behind_if_mergeable": false + }, + "behind_by": 0, + "compare_status": "ahead", + "comparison_status": "available" + }, + "rationale": "Up to date", + "created_at": "2026-10-26T21:01:54.977313Z", + "completed_at": "2026-10-26T21:01:54.977313Z", + "state": "evaluated", + "outcome": "passed", + "stale_reason": null, + "evaluated_at_sha": "9f5e93477cecca4f94f1888d8680ab55c75fccba", + "finding_count": null + } + ], + "checks": { + "availability": "not_applicable", + "runs": [] + }, + "forge_merge_block": null + }, + "deployments": { + "availability": "available", + "ready": 0, + "total": 0, + "items": [] + }, + "config_source": "live", + "merge_base_sha": null, + "base_sha": null, + "head_sha": "9f5e93477cecca4f94f1888d8680ab55c75fccba" + } + } +} diff --git a/test/fixtures/entire/recorded/entire.com-writes/steps/pull-update/04-patch-trails-01M5X0A493RSBKDGYF0ZWVG8E9.json b/test/fixtures/entire/recorded/entire.com-writes/steps/pull-update/04-patch-trails-01M5X0A493RSBKDGYF0ZWVG8E9.json new file mode 100644 index 000000000..9877408a2 --- /dev/null +++ b/test/fixtures/entire/recorded/entire.com-writes/steps/pull-update/04-patch-trails-01M5X0A493RSBKDGYF0ZWVG8E9.json @@ -0,0 +1,130 @@ +{ + "request": { + "method": "PATCH", + "url": "https://aws-eu-central-1.api.entire.io/api/v1/et/forges-scratch/trails/01M5X0A493RSBKDGYF0ZWVG8E9", + "body": { + "body": "Edited by run 20261026210133." + } + }, + "response": { + "status": 200, + "headers": { + "link": "; rel=\"describedBy\"", + "etag": "W/\"2026-10-26T21:02:04.373663Z\"" + }, + "body": { + "$schema": "https://aws-eu-central-1.api.entire.io/api/v1/schemas/TrailResponse.json", + "capabilities": { + "canEdit": true, + "canManageScope": true + }, + "project": { + "primaryProcessingCell": "aws-eu-central-1", + "id": "01M5WYSMPPYRBB13ZB20H7NK2Q", + "name": "forges-scratch", + "provider": "entire", + "reference": { + "forge": "et", + "project": "forges-scratch" + }, + "jurisdiction": "eu", + "capabilities": { + "canManageTrails": true + } + }, + "author": { + "accountId": "01M5WYRRVZNA1TXNET6KE4Q3WX", + "login": "danielroe-bot", + "displayName": "", + "avatarUrl": "https://avatars.githubusercontent.com/u/57801166?v=4", + "identity": { + "kind": "account", + "account_id": "01M5WYRRVZNA1TXNET6KE4Q3WX", + "display_name": null, + "avatar_url": "https://avatars.githubusercontent.com/u/57801166?v=4", + "handles": [ + { + "provider": "github", + "handle": "danielroe-bot", + "is_primary": true + } + ] + } + }, + "id": "01M5X0A493RSBKDGYF0ZWVG8E9", + "projectId": "01M5WYSMPPYRBB13ZB20H7NK2Q", + "number": 15, + "url": "https://entire.com/et/forges-scratch/-/trails/15", + "title": "forges fixture 20261026210133: pull 1", + "body": "Edited by run 20261026210133.", + "bodyDocument": { + "id": "", + "document_key": "project-trail:01M5X0A493RSBKDGYF0ZWVG8E9:body", + "schema_version": 1, + "content_json": { + "type": "doc", + "content": [ + { + "type": "paragraph", + "content": [ + { + "type": "text", + "text": "Edited by run 20261026210133." + } + ] + } + ] + }, + "text_snapshot": "Edited by run 20261026210133.", + "updated_at": "2026-10-26T21:02:04.373Z", + "etag": "" + }, + "status": "open", + "phase": "building", + "metadata": {}, + "type": "task", + "priority": "none", + "assignees": [], + "assigneeAccountIds": [], + "repoIds": [ + "01M5WYSQC41P69DTXEMZ0TE5YK" + ], + "authorAccountId": "01M5WYRRVZNA1TXNET6KE4Q3WX", + "createdAt": "2026-10-26T21:01:54.849Z", + "metadataUpdatedAt": "2026-10-26T21:02:04.373Z", + "closedAt": null, + "lastVisitedAt": null, + "lastActivityAt": "2026-10-26T21:02:04.373Z", + "changes": [ + { + "id": "01M5X0A49M70NAMJX878FD2QD1", + "repositoryId": "01M5WYSQC41P69DTXEMZ0TE5YK", + "repository": "forges-fixtures", + "branch": "forges-fixtures/20261026210133-1", + "originalBranch": "forges-fixtures/20261026210133-1", + "base": "main", + "number": 9, + "title": "forges fixture 20261026210133: pull, edited", + "status": "open", + "hasCodeChanges": true, + "createdAt": "2026-10-26T21:01:54.849Z", + "updatedAt": "2026-10-26T21:02:03.358Z", + "lastActivityAt": "2026-10-26T21:02:03.358Z", + "deployments": { + "availability": "available", + "ready": 0, + "total": 0 + }, + "readiness": "in_review", + "mergeability": { + "conflict_status": "unknown", + "head_sha": "", + "refreshed_at": null, + "forge_merge_block": null + } + } + ], + "isPossiblyPartial": true + } + } +} diff --git a/test/fixtures/entire/recorded/entire.com-writes/steps/pull-update/05-patch-forges-fixtures-N.json b/test/fixtures/entire/recorded/entire.com-writes/steps/pull-update/05-patch-forges-fixtures-N.json new file mode 100644 index 000000000..9232554d8 --- /dev/null +++ b/test/fixtures/entire/recorded/entire.com-writes/steps/pull-update/05-patch-forges-fixtures-N.json @@ -0,0 +1,99 @@ +{ + "request": { + "method": "PATCH", + "url": "https://aws-eu-central-1.api.entire.io/api/v1/trails/et/forges-scratch/forges-fixtures/9", + "body": { + "title": "forges fixture 20261026210133: pull, edited" + } + }, + "response": { + "status": 200, + "headers": { + "link": "; rel=\"describedBy\"", + "etag": "W/\"2026-10-26T21:02:03.358195Z\"" + }, + "body": { + "$schema": "https://aws-eu-central-1.api.entire.io/api/v1/schemas/TrailUpdateResponseBody.json", + "trail": { + "id": "01M5X0A49M70NAMJX878FD2QD1", + "number": 9, + "url": "https://entire.com/et/forges-scratch/forges-fixtures/trails/9", + "title": "forges fixture 20261026210133: pull, edited", + "status": "open", + "branch": "forges-fixtures/20261026210133-1", + "original_branch": "forges-fixtures/20261026210133-1", + "base": "main", + "type": "task", + "priority": "none", + "author": { + "id": "01M5WYRRVZNA1TXNET6KE4Q3WX", + "login": "danielroe-bot", + "identity": { + "kind": "account", + "account_id": "01M5WYRRVZNA1TXNET6KE4Q3WX", + "display_name": null, + "avatar_url": "https://avatars.githubusercontent.com/u/57801166?v=4", + "handles": [ + { + "provider": "github", + "handle": "danielroe-bot", + "is_primary": true + } + ] + } + }, + "assignees": [ + "danielroe-bot" + ], + "assignee_identities": [ + { + "login": "danielroe-bot", + "identity": { + "kind": "account", + "account_id": "01M5WYRRVZNA1TXNET6KE4Q3WX", + "display_name": null, + "avatar_url": "https://avatars.githubusercontent.com/u/57801166?v=4", + "handles": [ + { + "provider": "github", + "handle": "danielroe-bot", + "is_primary": true + } + ] + } + } + ], + "reviewers": [], + "ready_for_review": true, + "has_code_changes": true, + "comment_count": 1, + "unresolved_count": 1, + "created_at": "2026-10-26T21:01:54.849Z", + "updated_at": "2026-10-26T21:02:03.358Z", + "merged_at": null, + "last_activity_at": "2026-10-26T21:02:03.358Z", + "phase": "reviewing", + "checkpoint_count": 0, + "body_document": { + "id": "01M5X0A4AGRFN6FB08AYTPCF6X", + "document_key": "trail:01M5X0A49M70NAMJX878FD2QD1:body", + "schema_version": 1, + "content_json": { + "type": "doc", + "content": [ + { + "type": "paragraph" + } + ] + }, + "text_snapshot": "", + "updated_at": "2026-10-26T21:01:54.849Z", + "etag": "W/\"2026-10-26T21:01:54.849162Z\"" + }, + "merge_base_sha": null, + "base_sha": null, + "head_sha": "9f5e93477cecca4f94f1888d8680ab55c75fccba" + } + } + } +} diff --git a/test/fixtures/entire/recorded/entire.com-writes/steps/pull-update/golden.json b/test/fixtures/entire/recorded/entire.com-writes/steps/pull-update/golden.json new file mode 100644 index 000000000..e2b9df736 --- /dev/null +++ b/test/fixtures/entire/recorded/entire.com-writes/steps/pull-update/golden.json @@ -0,0 +1,61 @@ +{ + "ref": { + "forge": "entire", + "instance": "entire.com", + "repo": { + "forge": "entire", + "instance": "entire.com", + "owner": "forges-scratch", + "name": "forges-fixtures" + }, + "kind": "pull_request", + "number": "9", + "externalId": "01M5X0A49M70NAMJX878FD2QD1" + }, + "kind": "pull_request", + "title": "forges fixture 20261026210133: pull, edited", + "body": "Edited by run 20261026210133.", + "state": "open", + "stateRaw": "open", + "isDraft": false, + "author": { + "forge": "entire", + "instance": "entire.com", + "login": "danielroe-bot", + "id": "01M5WYRRVZNA1TXNET6KE4Q3WX", + "avatarUrl": "https://avatars.githubusercontent.com/u/57801166?v=4", + "isBotHint": false + }, + "assignees": [ + { + "forge": "entire", + "instance": "entire.com", + "login": "danielroe-bot", + "id": "01M5WYRRVZNA1TXNET6KE4Q3WX", + "avatarUrl": "https://avatars.githubusercontent.com/u/57801166?v=4", + "isBotHint": false + } + ], + "reviewers": [], + "labels": [], + "url": "https://entire.com/et/forges-scratch/forges-fixtures/trails/9", + "createdAt": "", + "updatedAt": "", + "lastActivityAt": "", + "commentCount": 1, + "branches": { + "head": { + "ref": "forges-fixtures/20261026210133-1", + "sha": "9f5e93477cecca4f94f1888d8680ab55c75fccba", + "repo": { + "forge": "entire", + "instance": "entire.com", + "owner": "forges-scratch", + "name": "forges-fixtures" + } + }, + "base": { + "ref": "main" + } + } +} diff --git a/test/fixtures/entire/recorded/entire.com-writes/steps/pull-update/step.json b/test/fixtures/entire/recorded/entire.com-writes/steps/pull-update/step.json new file mode 100644 index 000000000..ac01fe78e --- /dev/null +++ b/test/fixtures/entire/recorded/entire.com-writes/steps/pull-update/step.json @@ -0,0 +1,7 @@ +{ + "name": "pull update", + "recordedAt": "2026-10-26T21:02:02.874Z", + "needs": [ + "create pull" + ] +} diff --git a/test/fixtures/entire/recorded/entire.com-writes/steps/pull-upsert-comment/01-get-N-discussions.json b/test/fixtures/entire/recorded/entire.com-writes/steps/pull-upsert-comment/01-get-N-discussions.json new file mode 100644 index 000000000..c445ba59b --- /dev/null +++ b/test/fixtures/entire/recorded/entire.com-writes/steps/pull-upsert-comment/01-get-N-discussions.json @@ -0,0 +1,96 @@ +{ + "request": { + "method": "GET", + "url": "https://aws-eu-central-1.api.entire.io/api/v1/trails/et/forges-scratch/forges-fixtures/9/discussions?include_messages=true&per_page=100" + }, + "response": { + "status": 200, + "headers": { + "link": "; rel=\"describedBy\"" + }, + "body": { + "$schema": "https://aws-eu-central-1.api.entire.io/api/v1/schemas/TrailDiscussionsListResponseBody.json", + "items": [ + { + "id": "01M5X0A7TQB4NGZHFD3MVSJQTE", + "trail_id": "01M5X0A49M70NAMJX878FD2QD1", + "title": "An edited comment from run 20261026210133.", + "kind": "discussion", + "resolved": false, + "resolved_by": null, + "resolved_by_identity": { + "kind": "unknown", + "account_id": null, + "display_name": null, + "avatar_url": null, + "handles": [] + }, + "resolved_at": null, + "created_by": "01M5WYRRVZNA1TXNET6KE4Q3WX", + "created_by_identity": { + "kind": "account", + "account_id": "01M5WYRRVZNA1TXNET6KE4Q3WX", + "display_name": null, + "avatar_url": "https://avatars.githubusercontent.com/u/57801166?v=4", + "handles": [ + { + "provider": "github", + "handle": "danielroe-bot", + "is_primary": true + } + ] + }, + "created_at": "2026-10-26T21:01:58.487Z", + "updated_at": "2026-10-26T21:01:59.356Z", + "last_message_at": "2026-10-26T21:01:58.487Z", + "last_message_author": "danielroe-bot", + "message_count": 1, + "participants": [ + { + "login": "danielroe-bot", + "actor_account_id": "01M5WYRRVZNA1TXNET6KE4Q3WX", + "identity": { + "kind": "account", + "account_id": "01M5WYRRVZNA1TXNET6KE4Q3WX", + "display_name": null, + "avatar_url": "https://avatars.githubusercontent.com/u/57801166?v=4", + "handles": [ + { + "provider": "github", + "handle": "danielroe-bot", + "is_primary": true + } + ] + } + } + ], + "review_comment_id": null, + "review_comment": null, + "messages": [ + { + "id": "01M5X0A7TRJFRP22WZ8RWZZ0NQ", + "author": "danielroe-bot", + "identity": { + "kind": "account", + "account_id": "01M5WYRRVZNA1TXNET6KE4Q3WX", + "display_name": null, + "avatar_url": "https://avatars.githubusercontent.com/u/57801166?v=4", + "handles": [ + { + "provider": "github", + "handle": "danielroe-bot", + "is_primary": true + } + ] + }, + "created_at": "2026-10-26T21:01:58.487Z", + "body": "An edited comment from run 20261026210133.", + "replies": [] + } + ] + } + ], + "event_cursor": "2" + } + } +} diff --git a/test/fixtures/entire/recorded/entire.com-writes/steps/pull-upsert-comment/02-post-N-discussions.json b/test/fixtures/entire/recorded/entire.com-writes/steps/pull-upsert-comment/02-post-N-discussions.json new file mode 100644 index 000000000..eafd34056 --- /dev/null +++ b/test/fixtures/entire/recorded/entire.com-writes/steps/pull-upsert-comment/02-post-N-discussions.json @@ -0,0 +1,95 @@ +{ + "request": { + "method": "POST", + "url": "https://aws-eu-central-1.api.entire.io/api/v1/trails/et/forges-scratch/forges-fixtures/9/discussions", + "body": { + "body": "An upserted comment from run 20261026210133.\n\n" + } + }, + "response": { + "status": 201, + "headers": { + "link": "; rel=\"describedBy\"", + "location": "https://aws-eu-central-1.api.entire.io/api/v1/trails/et/forges-scratch/forges-fixtures/9/discussions/01M5X0A9PBSMXT52PCMF5JCE0Y" + }, + "body": { + "$schema": "https://aws-eu-central-1.api.entire.io/api/v1/schemas/TrailDiscussionCreateResponseBody.json", + "discussion": { + "id": "01M5X0A9PBSMXT52PCMF5JCE0Y", + "trail_id": "01M5X0A49M70NAMJX878FD2QD1", + "title": "An upserted comment from run 20261026210133. ", + "kind": "discussion", + "resolved": false, + "resolved_by": null, + "resolved_by_identity": { + "kind": "unknown", + "account_id": null, + "display_name": null, + "avatar_url": null, + "handles": [] + }, + "resolved_at": null, + "created_by": "01M5WYRRVZNA1TXNET6KE4Q3WX", + "created_by_identity": { + "kind": "account", + "account_id": "01M5WYRRVZNA1TXNET6KE4Q3WX", + "display_name": null, + "avatar_url": "https://avatars.githubusercontent.com/u/57801166?v=4", + "handles": [ + { + "provider": "github", + "handle": "danielroe-bot", + "is_primary": true + } + ] + }, + "created_at": "2026-10-26T21:02:00.395Z", + "updated_at": "2026-10-26T21:02:00.395Z", + "last_message_at": "2026-10-26T21:02:00.395Z", + "last_message_author": "danielroe-bot", + "message_count": 1, + "participants": [ + { + "login": "danielroe-bot", + "actor_account_id": "01M5WYRRVZNA1TXNET6KE4Q3WX", + "identity": { + "kind": "account", + "account_id": "01M5WYRRVZNA1TXNET6KE4Q3WX", + "display_name": null, + "avatar_url": "https://avatars.githubusercontent.com/u/57801166?v=4", + "handles": [ + { + "provider": "github", + "handle": "danielroe-bot", + "is_primary": true + } + ] + } + } + ], + "review_comment_id": null, + "review_comment": null + }, + "message": { + "id": "01M5X0A9PCYAK06HK5CXJRQR2P", + "author": "danielroe-bot", + "identity": { + "kind": "account", + "account_id": "01M5WYRRVZNA1TXNET6KE4Q3WX", + "display_name": null, + "avatar_url": "https://avatars.githubusercontent.com/u/57801166?v=4", + "handles": [ + { + "provider": "github", + "handle": "danielroe-bot", + "is_primary": true + } + ] + }, + "created_at": "2026-10-26T21:02:00.395Z", + "body": "An upserted comment from run 20261026210133.\n\n", + "replies": [] + } + } + } +} diff --git a/test/fixtures/entire/recorded/entire.com-writes/steps/pull-upsert-comment/golden.json b/test/fixtures/entire/recorded/entire.com-writes/steps/pull-upsert-comment/golden.json new file mode 100644 index 000000000..095862b95 --- /dev/null +++ b/test/fixtures/entire/recorded/entire.com-writes/steps/pull-upsert-comment/golden.json @@ -0,0 +1,37 @@ +{ + "comment": { + "ref": { + "forge": "entire", + "instance": "entire.com", + "thread": { + "forge": "entire", + "instance": "entire.com", + "repo": { + "forge": "entire", + "instance": "entire.com", + "owner": "forges-scratch", + "name": "forges-fixtures" + }, + "kind": "pull_request", + "number": "9", + "externalId": "01M5X0A49M70NAMJX878FD2QD1" + }, + "id": "01M5X0A9PCYAK06HK5CXJRQR2P" + }, + "body": "An upserted comment from run 20261026210133.\n\n", + "author": { + "forge": "entire", + "instance": "entire.com", + "login": "danielroe-bot", + "id": "01M5WYRRVZNA1TXNET6KE4Q3WX", + "avatarUrl": "https://avatars.githubusercontent.com/u/57801166?v=4", + "isBotHint": false + }, + "createdAt": "", + "thread": { + "id": "01M5X0A9PBSMXT52PCMF5JCE0Y", + "resolved": false + } + }, + "created": true +} diff --git a/test/fixtures/entire/recorded/entire.com-writes/steps/pull-upsert-comment/step.json b/test/fixtures/entire/recorded/entire.com-writes/steps/pull-upsert-comment/step.json new file mode 100644 index 000000000..c37698e9c --- /dev/null +++ b/test/fixtures/entire/recorded/entire.com-writes/steps/pull-upsert-comment/step.json @@ -0,0 +1,7 @@ +{ + "name": "pull upsert comment", + "recordedAt": "2026-10-26T21:01:59.686Z", + "needs": [ + "create pull" + ] +} diff --git a/test/fixtures/entire/recorded/entire.com-writes/steps/reply-to-review-comment/01-get-N-approvals.json b/test/fixtures/entire/recorded/entire.com-writes/steps/reply-to-review-comment/01-get-N-approvals.json new file mode 100644 index 000000000..f58b19751 --- /dev/null +++ b/test/fixtures/entire/recorded/entire.com-writes/steps/reply-to-review-comment/01-get-N-approvals.json @@ -0,0 +1,16 @@ +{ + "request": { + "method": "GET", + "url": "https://aws-eu-central-1.api.entire.io/api/v1/trails/et/forges-scratch/forges-fixtures/9/approvals" + }, + "response": { + "status": 200, + "headers": { + "link": "; rel=\"describedBy\"" + }, + "body": { + "$schema": "https://aws-eu-central-1.api.entire.io/api/v1/schemas/TrailApprovalsResponse.json", + "approvals": [] + } + } +} diff --git a/test/fixtures/entire/recorded/entire.com-writes/steps/reply-to-review-comment/02-get-reviews-01M5X0AGW04E508JH4BY5VE4V7.json b/test/fixtures/entire/recorded/entire.com-writes/steps/reply-to-review-comment/02-get-reviews-01M5X0AGW04E508JH4BY5VE4V7.json new file mode 100644 index 000000000..232cd2ce3 --- /dev/null +++ b/test/fixtures/entire/recorded/entire.com-writes/steps/reply-to-review-comment/02-get-reviews-01M5X0AGW04E508JH4BY5VE4V7.json @@ -0,0 +1,108 @@ +{ + "request": { + "method": "GET", + "url": "https://aws-eu-central-1.api.entire.io/api/v1/trails/et/forges-scratch/forges-fixtures/9/reviews/01M5X0AGW04E508JH4BY5VE4V7" + }, + "response": { + "status": 200, + "headers": { + "link": "; rel=\"describedBy\"" + }, + "body": { + "$schema": "https://aws-eu-central-1.api.entire.io/api/v1/schemas/ReviewSnapshotResponseBody.json", + "review": { + "id": "01M5X0AGW04E508JH4BY5VE4V7", + "trail_id": "01M5X0A49M70NAMJX878FD2QD1", + "code_version_id": "01M5X0AGVPHGGQD3ZADR9BX2KV", + "actor_id": "01M5WRP9RJ4GVR2PA5PCNYP1FC", + "summary": null, + "started_at": "2026-10-26T21:02:07.744Z", + "source_execution_id": null + }, + "code_version": { + "id": "01M5X0AGVPHGGQD3ZADR9BX2KV", + "trail_id": "01M5X0A49M70NAMJX878FD2QD1", + "repo_id": "01M5WYSQC41P69DTXEMZ0TE5YK", + "base_ref": null, + "head_ref": null, + "base_sha": "80c3e7d4c9f5e16f4e11cf7737f571c513d14ac2", + "head_sha": "9f5e93477cecca4f94f1888d8680ab55c75fccba", + "captured_at": "2026-10-26T21:02:07.734Z" + }, + "counts": { + "open": 1, + "resolved": 0, + "dismissed": 0, + "stale": 0, + "total": 1 + }, + "comments": [ + { + "discussion_id": "01M5X0AHS4JAQ93WBG0CC9JN8M", + "discussion_message_count": 0, + "id": "01M5X0AHS47CKYTKRY42WT1YYD", + "trail_id": "01M5X0A49M70NAMJX878FD2QD1", + "repo_id": "01M5WYSQC41P69DTXEMZ0TE5YK", + "review_id": "01M5X0AGW04E508JH4BY5VE4V7", + "code_version_id": "01M5X0AGVPHGGQD3ZADR9BX2KV", + "actor_id": "01M5WRP9RJ4GVR2PA5PCNYP1FC", + "actor_display_name": "danielroe", + "actor_identity": { + "kind": "account", + "account_id": "01M5WRP9RJ4GVR2PA5PCNYP1FC", + "display_name": "Daniel Roe", + "avatar_url": "https://avatars.githubusercontent.com/u/28706372?v=4", + "handles": [ + { + "provider": "github", + "handle": "danielroe", + "is_primary": true + } + ] + }, + "body": "A review comment from run 20261026210133.", + "severity": null, + "confidence": null, + "status": "open", + "status_reason": null, + "status_actor_id": null, + "status_actor_display_name": null, + "status_actor_identity": { + "kind": "unknown", + "account_id": null, + "display_name": null, + "avatar_url": null, + "handles": [] + }, + "status_changed_at": null, + "status_source": null, + "status_actor_kind": null, + "stale_outcome": "current", + "stale_checked_at": null, + "stale_checked_code_version_id": null, + "client_id": "1", + "client_id_hash": "876dd2d2f894bbd709b9c4adf233e9cbe880d2c74674e9987f97a2d6c6e31faa", + "created_at": "2026-10-26T21:02:08.674Z", + "updated_at": "2026-10-26T21:02:08.674Z", + "location": { + "id": "01M5X0AHS4172XDD0412MR744W", + "review_comment_id": "01M5X0AHS47CKYTKRY42WT1YYD", + "code_version_id": "01M5X0AGVPHGGQD3ZADR9BX2KV", + "granularity": "whole_change", + "file_path": null, + "start_line": null, + "start_column": null, + "end_line": null, + "end_column": null, + "selected_text": null, + "nearby_text": null, + "language": null + }, + "suggested_changes": [], + "outgoing_links": [] + } + ], + "event_cursor": "6" + } + } +} diff --git a/test/fixtures/entire/recorded/entire.com-writes/steps/reply-to-review-comment/03-get-reviews-comments.json b/test/fixtures/entire/recorded/entire.com-writes/steps/reply-to-review-comment/03-get-reviews-comments.json new file mode 100644 index 000000000..97a4fe38a --- /dev/null +++ b/test/fixtures/entire/recorded/entire.com-writes/steps/reply-to-review-comment/03-get-reviews-comments.json @@ -0,0 +1,80 @@ +{ + "request": { + "method": "GET", + "url": "https://aws-eu-central-1.api.entire.io/api/v1/trails/et/forges-scratch/forges-fixtures/9/reviews/comments?per_page=100" + }, + "response": { + "status": 200, + "headers": { + "link": "; rel=\"describedBy\"" + }, + "body": { + "$schema": "https://aws-eu-central-1.api.entire.io/api/v1/schemas/ReviewCommentsPage.json", + "comments": [ + { + "discussion_id": "01M5X0AHS4JAQ93WBG0CC9JN8M", + "discussion_message_count": 0, + "id": "01M5X0AHS47CKYTKRY42WT1YYD", + "trail_id": "01M5X0A49M70NAMJX878FD2QD1", + "repo_id": "01M5WYSQC41P69DTXEMZ0TE5YK", + "review_id": "01M5X0AGW04E508JH4BY5VE4V7", + "code_version_id": "01M5X0AGVPHGGQD3ZADR9BX2KV", + "actor_id": "01M5WRP9RJ4GVR2PA5PCNYP1FC", + "actor_display_name": "danielroe", + "actor_identity": { + "kind": "account", + "account_id": "01M5WRP9RJ4GVR2PA5PCNYP1FC", + "display_name": "Daniel Roe", + "avatar_url": "https://avatars.githubusercontent.com/u/28706372?v=4", + "handles": [ + { + "provider": "github", + "handle": "danielroe", + "is_primary": true + } + ] + }, + "body": "A review comment from run 20261026210133.", + "severity": null, + "confidence": null, + "status": "open", + "status_reason": null, + "status_actor_id": null, + "status_actor_display_name": null, + "status_actor_identity": { + "kind": "unknown", + "account_id": null, + "display_name": null, + "avatar_url": null, + "handles": [] + }, + "status_changed_at": null, + "status_source": null, + "status_actor_kind": null, + "stale_outcome": "current", + "stale_checked_at": null, + "stale_checked_code_version_id": null, + "client_id": "1", + "client_id_hash": "876dd2d2f894bbd709b9c4adf233e9cbe880d2c74674e9987f97a2d6c6e31faa", + "created_at": "2026-10-26T21:02:08.674Z", + "updated_at": "2026-10-26T21:02:08.674Z", + "location": { + "id": "01M5X0AHS4172XDD0412MR744W", + "review_comment_id": "01M5X0AHS47CKYTKRY42WT1YYD", + "code_version_id": "01M5X0AGVPHGGQD3ZADR9BX2KV", + "granularity": "whole_change", + "file_path": null, + "start_line": null, + "start_column": null, + "end_line": null, + "end_column": null, + "selected_text": null, + "nearby_text": null, + "language": null + } + } + ], + "event_cursor": "6" + } + } +} diff --git a/test/fixtures/entire/recorded/entire.com-writes/steps/reply-to-review-comment/04-post-01M5X0AHS4JAQ93WBG0CC9JN8M-messages.json b/test/fixtures/entire/recorded/entire.com-writes/steps/reply-to-review-comment/04-post-01M5X0AHS4JAQ93WBG0CC9JN8M-messages.json new file mode 100644 index 000000000..7aab5ab57 --- /dev/null +++ b/test/fixtures/entire/recorded/entire.com-writes/steps/reply-to-review-comment/04-post-01M5X0AHS4JAQ93WBG0CC9JN8M-messages.json @@ -0,0 +1,39 @@ +{ + "request": { + "method": "POST", + "url": "https://aws-eu-central-1.api.entire.io/api/v1/trails/et/forges-scratch/forges-fixtures/9/discussions/01M5X0AHS4JAQ93WBG0CC9JN8M/messages", + "body": { + "body": "A reply from run 20261026210133." + } + }, + "response": { + "status": 201, + "headers": { + "link": "; rel=\"describedBy\"", + "location": "https://aws-eu-central-1.api.entire.io/api/v1/trails/et/forges-scratch/forges-fixtures/9/discussions/01M5X0AHS4JAQ93WBG0CC9JN8M/messages/01M5X0AK7JFP7KMT95DH7TEQ5S" + }, + "body": { + "$schema": "https://aws-eu-central-1.api.entire.io/api/v1/schemas/TrailDiscussionMessageResponseBody.json", + "message": { + "id": "01M5X0AK7JFP7KMT95DH7TEQ5S", + "author": "danielroe-bot", + "identity": { + "kind": "account", + "account_id": "01M5WYRRVZNA1TXNET6KE4Q3WX", + "display_name": null, + "avatar_url": "https://avatars.githubusercontent.com/u/57801166?v=4", + "handles": [ + { + "provider": "github", + "handle": "danielroe-bot", + "is_primary": true + } + ] + }, + "created_at": "2026-10-26T21:02:10.162Z", + "body": "A reply from run 20261026210133.", + "replies": [] + } + } + } +} diff --git a/test/fixtures/entire/recorded/entire.com-writes/steps/reply-to-review-comment/golden.json b/test/fixtures/entire/recorded/entire.com-writes/steps/reply-to-review-comment/golden.json new file mode 100644 index 000000000..66c7aec3a --- /dev/null +++ b/test/fixtures/entire/recorded/entire.com-writes/steps/reply-to-review-comment/golden.json @@ -0,0 +1,110 @@ +{ + "reviews": { + "items": [ + { + "ref": { + "forge": "entire", + "instance": "entire.com", + "thread": { + "forge": "entire", + "instance": "entire.com", + "repo": { + "forge": "entire", + "instance": "entire.com", + "owner": "forges-scratch", + "name": "forges-fixtures" + }, + "kind": "pull_request", + "number": "9", + "externalId": "01M5X0A49M70NAMJX878FD2QD1" + }, + "id": "01M5X0AGW04E508JH4BY5VE4V7" + }, + "author": { + "forge": "entire", + "instance": "entire.com", + "login": "danielroe", + "id": "01M5WRP9RJ4GVR2PA5PCNYP1FC", + "name": "Daniel Roe", + "avatarUrl": "https://avatars.githubusercontent.com/u/28706372?v=4", + "isBotHint": false + }, + "state": "commented", + "stateRaw": "review", + "submittedAt": "", + "comments": [ + { + "ref": { + "forge": "entire", + "instance": "entire.com", + "thread": { + "forge": "entire", + "instance": "entire.com", + "repo": { + "forge": "entire", + "instance": "entire.com", + "owner": "forges-scratch", + "name": "forges-fixtures" + }, + "kind": "pull_request", + "number": "9", + "externalId": "01M5X0A49M70NAMJX878FD2QD1" + }, + "id": "01M5X0AHS47CKYTKRY42WT1YYD" + }, + "body": "A review comment from run 20261026210133.", + "author": { + "forge": "entire", + "instance": "entire.com", + "login": "danielroe", + "id": "01M5WRP9RJ4GVR2PA5PCNYP1FC", + "name": "Daniel Roe", + "avatarUrl": "https://avatars.githubusercontent.com/u/28706372?v=4", + "isBotHint": false + }, + "thread": { + "id": "01M5X0AHS4JAQ93WBG0CC9JN8M", + "resolved": false + }, + "createdAt": "" + } + ] + } + ] + }, + "reply": { + "ref": { + "forge": "entire", + "instance": "entire.com", + "thread": { + "forge": "entire", + "instance": "entire.com", + "repo": { + "forge": "entire", + "instance": "entire.com", + "owner": "forges-scratch", + "name": "forges-fixtures" + }, + "kind": "pull_request", + "number": "9", + "externalId": "01M5X0A49M70NAMJX878FD2QD1" + }, + "id": "01M5X0AK7JFP7KMT95DH7TEQ5S" + }, + "body": "A reply from run 20261026210133.", + "author": { + "forge": "entire", + "instance": "entire.com", + "login": "danielroe-bot", + "id": "01M5WYRRVZNA1TXNET6KE4Q3WX", + "avatarUrl": "https://avatars.githubusercontent.com/u/57801166?v=4", + "isBotHint": false + }, + "createdAt": "", + "thread": { + "id": "01M5X0AHS4JAQ93WBG0CC9JN8M", + "resolved": false + }, + "inReplyTo": "01M5X0AHS47CKYTKRY42WT1YYD" + } +} diff --git a/test/fixtures/entire/recorded/entire.com-writes/steps/reply-to-review-comment/step.json b/test/fixtures/entire/recorded/entire.com-writes/steps/reply-to-review-comment/step.json new file mode 100644 index 000000000..f16dc822e --- /dev/null +++ b/test/fixtures/entire/recorded/entire.com-writes/steps/reply-to-review-comment/step.json @@ -0,0 +1,7 @@ +{ + "name": "reply to review comment", + "recordedAt": "2026-10-26T21:02:09.180Z", + "needs": [ + "create pull" + ] +} diff --git a/test/fixtures/entire/recorded/entire.com-writes/steps/resolve-review-thread/01-get-N-approvals.json b/test/fixtures/entire/recorded/entire.com-writes/steps/resolve-review-thread/01-get-N-approvals.json new file mode 100644 index 000000000..f58b19751 --- /dev/null +++ b/test/fixtures/entire/recorded/entire.com-writes/steps/resolve-review-thread/01-get-N-approvals.json @@ -0,0 +1,16 @@ +{ + "request": { + "method": "GET", + "url": "https://aws-eu-central-1.api.entire.io/api/v1/trails/et/forges-scratch/forges-fixtures/9/approvals" + }, + "response": { + "status": 200, + "headers": { + "link": "; rel=\"describedBy\"" + }, + "body": { + "$schema": "https://aws-eu-central-1.api.entire.io/api/v1/schemas/TrailApprovalsResponse.json", + "approvals": [] + } + } +} diff --git a/test/fixtures/entire/recorded/entire.com-writes/steps/resolve-review-thread/02-get-reviews-01M5X0AGW04E508JH4BY5VE4V7.json b/test/fixtures/entire/recorded/entire.com-writes/steps/resolve-review-thread/02-get-reviews-01M5X0AGW04E508JH4BY5VE4V7.json new file mode 100644 index 000000000..242753c41 --- /dev/null +++ b/test/fixtures/entire/recorded/entire.com-writes/steps/resolve-review-thread/02-get-reviews-01M5X0AGW04E508JH4BY5VE4V7.json @@ -0,0 +1,108 @@ +{ + "request": { + "method": "GET", + "url": "https://aws-eu-central-1.api.entire.io/api/v1/trails/et/forges-scratch/forges-fixtures/9/reviews/01M5X0AGW04E508JH4BY5VE4V7" + }, + "response": { + "status": 200, + "headers": { + "link": "; rel=\"describedBy\"" + }, + "body": { + "$schema": "https://aws-eu-central-1.api.entire.io/api/v1/schemas/ReviewSnapshotResponseBody.json", + "review": { + "id": "01M5X0AGW04E508JH4BY5VE4V7", + "trail_id": "01M5X0A49M70NAMJX878FD2QD1", + "code_version_id": "01M5X0AGVPHGGQD3ZADR9BX2KV", + "actor_id": "01M5WRP9RJ4GVR2PA5PCNYP1FC", + "summary": null, + "started_at": "2026-10-26T21:02:07.744Z", + "source_execution_id": null + }, + "code_version": { + "id": "01M5X0AGVPHGGQD3ZADR9BX2KV", + "trail_id": "01M5X0A49M70NAMJX878FD2QD1", + "repo_id": "01M5WYSQC41P69DTXEMZ0TE5YK", + "base_ref": null, + "head_ref": null, + "base_sha": "80c3e7d4c9f5e16f4e11cf7737f571c513d14ac2", + "head_sha": "9f5e93477cecca4f94f1888d8680ab55c75fccba", + "captured_at": "2026-10-26T21:02:07.734Z" + }, + "counts": { + "open": 1, + "resolved": 0, + "dismissed": 0, + "stale": 0, + "total": 1 + }, + "comments": [ + { + "discussion_id": "01M5X0AHS4JAQ93WBG0CC9JN8M", + "discussion_message_count": 1, + "id": "01M5X0AHS47CKYTKRY42WT1YYD", + "trail_id": "01M5X0A49M70NAMJX878FD2QD1", + "repo_id": "01M5WYSQC41P69DTXEMZ0TE5YK", + "review_id": "01M5X0AGW04E508JH4BY5VE4V7", + "code_version_id": "01M5X0AGVPHGGQD3ZADR9BX2KV", + "actor_id": "01M5WRP9RJ4GVR2PA5PCNYP1FC", + "actor_display_name": "danielroe", + "actor_identity": { + "kind": "account", + "account_id": "01M5WRP9RJ4GVR2PA5PCNYP1FC", + "display_name": "Daniel Roe", + "avatar_url": "https://avatars.githubusercontent.com/u/28706372?v=4", + "handles": [ + { + "provider": "github", + "handle": "danielroe", + "is_primary": true + } + ] + }, + "body": "A review comment from run 20261026210133.", + "severity": null, + "confidence": null, + "status": "open", + "status_reason": null, + "status_actor_id": null, + "status_actor_display_name": null, + "status_actor_identity": { + "kind": "unknown", + "account_id": null, + "display_name": null, + "avatar_url": null, + "handles": [] + }, + "status_changed_at": null, + "status_source": null, + "status_actor_kind": null, + "stale_outcome": "current", + "stale_checked_at": null, + "stale_checked_code_version_id": null, + "client_id": "1", + "client_id_hash": "876dd2d2f894bbd709b9c4adf233e9cbe880d2c74674e9987f97a2d6c6e31faa", + "created_at": "2026-10-26T21:02:08.674Z", + "updated_at": "2026-10-26T21:02:08.674Z", + "location": { + "id": "01M5X0AHS4172XDD0412MR744W", + "review_comment_id": "01M5X0AHS47CKYTKRY42WT1YYD", + "code_version_id": "01M5X0AGVPHGGQD3ZADR9BX2KV", + "granularity": "whole_change", + "file_path": null, + "start_line": null, + "start_column": null, + "end_line": null, + "end_column": null, + "selected_text": null, + "nearby_text": null, + "language": null + }, + "suggested_changes": [], + "outgoing_links": [] + } + ], + "event_cursor": "6" + } + } +} diff --git a/test/fixtures/entire/recorded/entire.com-writes/steps/resolve-review-thread/03-get-reviews-comments.json b/test/fixtures/entire/recorded/entire.com-writes/steps/resolve-review-thread/03-get-reviews-comments.json new file mode 100644 index 000000000..a8c118749 --- /dev/null +++ b/test/fixtures/entire/recorded/entire.com-writes/steps/resolve-review-thread/03-get-reviews-comments.json @@ -0,0 +1,80 @@ +{ + "request": { + "method": "GET", + "url": "https://aws-eu-central-1.api.entire.io/api/v1/trails/et/forges-scratch/forges-fixtures/9/reviews/comments?per_page=100" + }, + "response": { + "status": 200, + "headers": { + "link": "; rel=\"describedBy\"" + }, + "body": { + "$schema": "https://aws-eu-central-1.api.entire.io/api/v1/schemas/ReviewCommentsPage.json", + "comments": [ + { + "discussion_id": "01M5X0AHS4JAQ93WBG0CC9JN8M", + "discussion_message_count": 1, + "id": "01M5X0AHS47CKYTKRY42WT1YYD", + "trail_id": "01M5X0A49M70NAMJX878FD2QD1", + "repo_id": "01M5WYSQC41P69DTXEMZ0TE5YK", + "review_id": "01M5X0AGW04E508JH4BY5VE4V7", + "code_version_id": "01M5X0AGVPHGGQD3ZADR9BX2KV", + "actor_id": "01M5WRP9RJ4GVR2PA5PCNYP1FC", + "actor_display_name": "danielroe", + "actor_identity": { + "kind": "account", + "account_id": "01M5WRP9RJ4GVR2PA5PCNYP1FC", + "display_name": "Daniel Roe", + "avatar_url": "https://avatars.githubusercontent.com/u/28706372?v=4", + "handles": [ + { + "provider": "github", + "handle": "danielroe", + "is_primary": true + } + ] + }, + "body": "A review comment from run 20261026210133.", + "severity": null, + "confidence": null, + "status": "open", + "status_reason": null, + "status_actor_id": null, + "status_actor_display_name": null, + "status_actor_identity": { + "kind": "unknown", + "account_id": null, + "display_name": null, + "avatar_url": null, + "handles": [] + }, + "status_changed_at": null, + "status_source": null, + "status_actor_kind": null, + "stale_outcome": "current", + "stale_checked_at": null, + "stale_checked_code_version_id": null, + "client_id": "1", + "client_id_hash": "876dd2d2f894bbd709b9c4adf233e9cbe880d2c74674e9987f97a2d6c6e31faa", + "created_at": "2026-10-26T21:02:08.674Z", + "updated_at": "2026-10-26T21:02:08.674Z", + "location": { + "id": "01M5X0AHS4172XDD0412MR744W", + "review_comment_id": "01M5X0AHS47CKYTKRY42WT1YYD", + "code_version_id": "01M5X0AGVPHGGQD3ZADR9BX2KV", + "granularity": "whole_change", + "file_path": null, + "start_line": null, + "start_column": null, + "end_line": null, + "end_column": null, + "selected_text": null, + "nearby_text": null, + "language": null + } + } + ], + "event_cursor": "6" + } + } +} diff --git a/test/fixtures/entire/recorded/entire.com-writes/steps/resolve-review-thread/04-patch-discussions-01M5X0AHS4JAQ93WBG0CC9JN8M.json b/test/fixtures/entire/recorded/entire.com-writes/steps/resolve-review-thread/04-patch-discussions-01M5X0AHS4JAQ93WBG0CC9JN8M.json new file mode 100644 index 000000000..50e492e33 --- /dev/null +++ b/test/fixtures/entire/recorded/entire.com-writes/steps/resolve-review-thread/04-patch-discussions-01M5X0AHS4JAQ93WBG0CC9JN8M.json @@ -0,0 +1,147 @@ +{ + "request": { + "method": "PATCH", + "url": "https://aws-eu-central-1.api.entire.io/api/v1/trails/et/forges-scratch/forges-fixtures/9/discussions/01M5X0AHS4JAQ93WBG0CC9JN8M", + "body": { + "resolved": true + } + }, + "response": { + "status": 200, + "headers": { + "link": "; rel=\"describedBy\"" + }, + "body": { + "$schema": "https://aws-eu-central-1.api.entire.io/api/v1/schemas/TrailDiscussionUpdateResponseBody.json", + "discussion": { + "id": "01M5X0AHS4JAQ93WBG0CC9JN8M", + "trail_id": "01M5X0A49M70NAMJX878FD2QD1", + "title": "A review comment from run 20261026210133.", + "kind": "code_review", + "resolved": true, + "resolved_by": "01M5WYRRVZNA1TXNET6KE4Q3WX", + "resolved_by_identity": { + "kind": "account", + "account_id": "01M5WYRRVZNA1TXNET6KE4Q3WX", + "display_name": null, + "avatar_url": "https://avatars.githubusercontent.com/u/57801166?v=4", + "handles": [ + { + "provider": "github", + "handle": "danielroe-bot", + "is_primary": true + } + ] + }, + "resolved_at": "2026-10-26T21:02:11.209Z", + "created_by": "01M5WRP9RJ4GVR2PA5PCNYP1FC", + "created_by_identity": { + "kind": "account", + "account_id": "01M5WRP9RJ4GVR2PA5PCNYP1FC", + "display_name": "Daniel Roe", + "avatar_url": "https://avatars.githubusercontent.com/u/28706372?v=4", + "handles": [ + { + "provider": "github", + "handle": "danielroe", + "is_primary": true + } + ] + }, + "created_at": "2026-10-26T21:02:08.674Z", + "updated_at": "2026-10-26T21:02:11.209Z", + "last_message_at": "2026-10-26T21:02:10.162Z", + "last_message_author": "danielroe-bot", + "message_count": 1, + "participants": [ + { + "login": "danielroe-bot", + "actor_account_id": "01M5WYRRVZNA1TXNET6KE4Q3WX", + "identity": { + "kind": "account", + "account_id": "01M5WYRRVZNA1TXNET6KE4Q3WX", + "display_name": null, + "avatar_url": "https://avatars.githubusercontent.com/u/57801166?v=4", + "handles": [ + { + "provider": "github", + "handle": "danielroe-bot", + "is_primary": true + } + ] + } + } + ], + "review_comment_id": "01M5X0AHS47CKYTKRY42WT1YYD", + "review_comment": { + "discussion_id": "01M5X0AHS4JAQ93WBG0CC9JN8M", + "discussion_message_count": 1, + "id": "01M5X0AHS47CKYTKRY42WT1YYD", + "trail_id": "01M5X0A49M70NAMJX878FD2QD1", + "repo_id": "01M5WYSQC41P69DTXEMZ0TE5YK", + "review_id": "01M5X0AGW04E508JH4BY5VE4V7", + "code_version_id": "01M5X0AGVPHGGQD3ZADR9BX2KV", + "actor_id": "01M5WRP9RJ4GVR2PA5PCNYP1FC", + "actor_display_name": "danielroe", + "actor_identity": { + "kind": "account", + "account_id": "01M5WRP9RJ4GVR2PA5PCNYP1FC", + "display_name": "Daniel Roe", + "avatar_url": "https://avatars.githubusercontent.com/u/28706372?v=4", + "handles": [ + { + "provider": "github", + "handle": "danielroe", + "is_primary": true + } + ] + }, + "body": "A review comment from run 20261026210133.", + "severity": null, + "confidence": null, + "status": "resolved", + "status_reason": null, + "status_actor_id": "01M5WYRRVZNA1TXNET6KE4Q3WX", + "status_actor_display_name": "danielroe-bot", + "status_actor_identity": { + "kind": "account", + "account_id": "01M5WYRRVZNA1TXNET6KE4Q3WX", + "display_name": null, + "avatar_url": "https://avatars.githubusercontent.com/u/57801166?v=4", + "handles": [ + { + "provider": "github", + "handle": "danielroe-bot", + "is_primary": true + } + ] + }, + "status_changed_at": "2026-10-26T21:02:11.209Z", + "status_source": "discussion_resolve", + "status_actor_kind": "human", + "stale_outcome": "current", + "stale_checked_at": null, + "stale_checked_code_version_id": null, + "client_id": "1", + "client_id_hash": "876dd2d2f894bbd709b9c4adf233e9cbe880d2c74674e9987f97a2d6c6e31faa", + "created_at": "2026-10-26T21:02:08.674Z", + "updated_at": "2026-10-26T21:02:11.209Z", + "location": { + "id": "01M5X0AHS4172XDD0412MR744W", + "review_comment_id": "01M5X0AHS47CKYTKRY42WT1YYD", + "code_version_id": "01M5X0AGVPHGGQD3ZADR9BX2KV", + "granularity": "whole_change", + "file_path": null, + "start_line": null, + "start_column": null, + "end_line": null, + "end_column": null, + "selected_text": null, + "nearby_text": null, + "language": null + } + } + } + } + } +} diff --git a/test/fixtures/entire/recorded/entire.com-writes/steps/resolve-review-thread/golden.json b/test/fixtures/entire/recorded/entire.com-writes/steps/resolve-review-thread/golden.json new file mode 100644 index 000000000..b1e7091e0 --- /dev/null +++ b/test/fixtures/entire/recorded/entire.com-writes/steps/resolve-review-thread/golden.json @@ -0,0 +1,76 @@ +{ + "reviews": { + "items": [ + { + "ref": { + "forge": "entire", + "instance": "entire.com", + "thread": { + "forge": "entire", + "instance": "entire.com", + "repo": { + "forge": "entire", + "instance": "entire.com", + "owner": "forges-scratch", + "name": "forges-fixtures" + }, + "kind": "pull_request", + "number": "9", + "externalId": "01M5X0A49M70NAMJX878FD2QD1" + }, + "id": "01M5X0AGW04E508JH4BY5VE4V7" + }, + "author": { + "forge": "entire", + "instance": "entire.com", + "login": "danielroe", + "id": "01M5WRP9RJ4GVR2PA5PCNYP1FC", + "name": "Daniel Roe", + "avatarUrl": "https://avatars.githubusercontent.com/u/28706372?v=4", + "isBotHint": false + }, + "state": "commented", + "stateRaw": "review", + "submittedAt": "", + "comments": [ + { + "ref": { + "forge": "entire", + "instance": "entire.com", + "thread": { + "forge": "entire", + "instance": "entire.com", + "repo": { + "forge": "entire", + "instance": "entire.com", + "owner": "forges-scratch", + "name": "forges-fixtures" + }, + "kind": "pull_request", + "number": "9", + "externalId": "01M5X0A49M70NAMJX878FD2QD1" + }, + "id": "01M5X0AHS47CKYTKRY42WT1YYD" + }, + "body": "A review comment from run 20261026210133.", + "author": { + "forge": "entire", + "instance": "entire.com", + "login": "danielroe", + "id": "01M5WRP9RJ4GVR2PA5PCNYP1FC", + "name": "Daniel Roe", + "avatarUrl": "https://avatars.githubusercontent.com/u/28706372?v=4", + "isBotHint": false + }, + "thread": { + "id": "01M5X0AHS4JAQ93WBG0CC9JN8M", + "resolved": false + }, + "createdAt": "" + } + ] + } + ] + }, + "id": "01M5X0AHS4JAQ93WBG0CC9JN8M" +} diff --git a/test/fixtures/entire/recorded/entire.com-writes/steps/resolve-review-thread/step.json b/test/fixtures/entire/recorded/entire.com-writes/steps/resolve-review-thread/step.json new file mode 100644 index 000000000..ebdbb7cf8 --- /dev/null +++ b/test/fixtures/entire/recorded/entire.com-writes/steps/resolve-review-thread/step.json @@ -0,0 +1,7 @@ +{ + "name": "resolve review thread", + "recordedAt": "2026-10-26T21:02:10.255Z", + "needs": [ + "create pull" + ] +} diff --git a/test/fixtures/entire/recorded/entire.com-writes/steps/review-threads/01-get-N-discussions.json b/test/fixtures/entire/recorded/entire.com-writes/steps/review-threads/01-get-N-discussions.json new file mode 100644 index 000000000..8342a1eb6 --- /dev/null +++ b/test/fixtures/entire/recorded/entire.com-writes/steps/review-threads/01-get-N-discussions.json @@ -0,0 +1,286 @@ +{ + "request": { + "method": "GET", + "url": "https://aws-eu-central-1.api.entire.io/api/v1/trails/et/forges-scratch/forges-fixtures/9/discussions?include_messages=true&per_page=100" + }, + "response": { + "status": 200, + "headers": { + "link": "; rel=\"describedBy\"" + }, + "body": { + "$schema": "https://aws-eu-central-1.api.entire.io/api/v1/schemas/TrailDiscussionsListResponseBody.json", + "items": [ + { + "id": "01M5X0AHS4JAQ93WBG0CC9JN8M", + "trail_id": "01M5X0A49M70NAMJX878FD2QD1", + "title": "A review comment from run 20261026210133.", + "kind": "code_review", + "resolved": true, + "resolved_by": "01M5WYRRVZNA1TXNET6KE4Q3WX", + "resolved_by_identity": { + "kind": "account", + "account_id": "01M5WYRRVZNA1TXNET6KE4Q3WX", + "display_name": null, + "avatar_url": "https://avatars.githubusercontent.com/u/57801166?v=4", + "handles": [ + { + "provider": "github", + "handle": "danielroe-bot", + "is_primary": true + } + ] + }, + "resolved_at": "2026-10-26T21:02:11.209Z", + "created_by": "01M5WRP9RJ4GVR2PA5PCNYP1FC", + "created_by_identity": { + "kind": "account", + "account_id": "01M5WRP9RJ4GVR2PA5PCNYP1FC", + "display_name": "Daniel Roe", + "avatar_url": "https://avatars.githubusercontent.com/u/28706372?v=4", + "handles": [ + { + "provider": "github", + "handle": "danielroe", + "is_primary": true + } + ] + }, + "created_at": "2026-10-26T21:02:08.674Z", + "updated_at": "2026-10-26T21:02:11.209Z", + "last_message_at": "2026-10-26T21:02:10.162Z", + "last_message_author": "danielroe-bot", + "message_count": 1, + "participants": [ + { + "login": "danielroe-bot", + "actor_account_id": "01M5WYRRVZNA1TXNET6KE4Q3WX", + "identity": { + "kind": "account", + "account_id": "01M5WYRRVZNA1TXNET6KE4Q3WX", + "display_name": null, + "avatar_url": "https://avatars.githubusercontent.com/u/57801166?v=4", + "handles": [ + { + "provider": "github", + "handle": "danielroe-bot", + "is_primary": true + } + ] + } + } + ], + "review_comment_id": "01M5X0AHS47CKYTKRY42WT1YYD", + "review_comment": { + "discussion_id": "01M5X0AHS4JAQ93WBG0CC9JN8M", + "discussion_message_count": 1, + "id": "01M5X0AHS47CKYTKRY42WT1YYD", + "trail_id": "01M5X0A49M70NAMJX878FD2QD1", + "repo_id": "01M5WYSQC41P69DTXEMZ0TE5YK", + "review_id": "01M5X0AGW04E508JH4BY5VE4V7", + "code_version_id": "01M5X0AGVPHGGQD3ZADR9BX2KV", + "actor_id": "01M5WRP9RJ4GVR2PA5PCNYP1FC", + "actor_display_name": "danielroe", + "actor_identity": { + "kind": "account", + "account_id": "01M5WRP9RJ4GVR2PA5PCNYP1FC", + "display_name": "Daniel Roe", + "avatar_url": "https://avatars.githubusercontent.com/u/28706372?v=4", + "handles": [ + { + "provider": "github", + "handle": "danielroe", + "is_primary": true + } + ] + }, + "body": "A review comment from run 20261026210133.", + "severity": null, + "confidence": null, + "status": "resolved", + "status_reason": null, + "status_actor_id": "01M5WYRRVZNA1TXNET6KE4Q3WX", + "status_actor_display_name": "danielroe-bot", + "status_actor_identity": { + "kind": "account", + "account_id": "01M5WYRRVZNA1TXNET6KE4Q3WX", + "display_name": null, + "avatar_url": "https://avatars.githubusercontent.com/u/57801166?v=4", + "handles": [ + { + "provider": "github", + "handle": "danielroe-bot", + "is_primary": true + } + ] + }, + "status_changed_at": "2026-10-26T21:02:11.209Z", + "status_source": "discussion_resolve", + "status_actor_kind": "human", + "stale_outcome": "current", + "stale_checked_at": null, + "stale_checked_code_version_id": null, + "client_id": "1", + "client_id_hash": "876dd2d2f894bbd709b9c4adf233e9cbe880d2c74674e9987f97a2d6c6e31faa", + "created_at": "2026-10-26T21:02:08.674Z", + "updated_at": "2026-10-26T21:02:11.209Z", + "location": { + "id": "01M5X0AHS4172XDD0412MR744W", + "review_comment_id": "01M5X0AHS47CKYTKRY42WT1YYD", + "code_version_id": "01M5X0AGVPHGGQD3ZADR9BX2KV", + "granularity": "whole_change", + "file_path": null, + "start_line": null, + "start_column": null, + "end_line": null, + "end_column": null, + "selected_text": null, + "nearby_text": null, + "language": null + } + }, + "messages": [ + { + "id": "01M5X0AK7JFP7KMT95DH7TEQ5S", + "author": "danielroe-bot", + "identity": { + "kind": "account", + "account_id": "01M5WYRRVZNA1TXNET6KE4Q3WX", + "display_name": null, + "avatar_url": "https://avatars.githubusercontent.com/u/57801166?v=4", + "handles": [ + { + "provider": "github", + "handle": "danielroe-bot", + "is_primary": true + } + ] + }, + "created_at": "2026-10-26T21:02:10.162Z", + "body": "A reply from run 20261026210133.", + "replies": [] + } + ] + }, + { + "id": "01M5X0A7TQB4NGZHFD3MVSJQTE", + "trail_id": "01M5X0A49M70NAMJX878FD2QD1", + "title": "Conversation", + "kind": "discussion", + "resolved": false, + "resolved_by": null, + "resolved_by_identity": { + "kind": "unknown", + "account_id": null, + "display_name": null, + "avatar_url": null, + "handles": [] + }, + "resolved_at": null, + "created_by": "01M5WYRRVZNA1TXNET6KE4Q3WX", + "created_by_identity": { + "kind": "account", + "account_id": "01M5WYRRVZNA1TXNET6KE4Q3WX", + "display_name": null, + "avatar_url": "https://avatars.githubusercontent.com/u/57801166?v=4", + "handles": [ + { + "provider": "github", + "handle": "danielroe-bot", + "is_primary": true + } + ] + }, + "created_at": "2026-10-26T21:01:58.487Z", + "updated_at": "2026-10-26T21:02:01.374Z", + "last_message_at": null, + "last_message_author": null, + "message_count": 0, + "participants": [], + "review_comment_id": null, + "review_comment": null, + "messages": [] + }, + { + "id": "01M5X0A9PBSMXT52PCMF5JCE0Y", + "trail_id": "01M5X0A49M70NAMJX878FD2QD1", + "title": "An upserted comment from run 20261026210133. ", + "kind": "discussion", + "resolved": false, + "resolved_by": null, + "resolved_by_identity": { + "kind": "unknown", + "account_id": null, + "display_name": null, + "avatar_url": null, + "handles": [] + }, + "resolved_at": null, + "created_by": "01M5WYRRVZNA1TXNET6KE4Q3WX", + "created_by_identity": { + "kind": "account", + "account_id": "01M5WYRRVZNA1TXNET6KE4Q3WX", + "display_name": null, + "avatar_url": "https://avatars.githubusercontent.com/u/57801166?v=4", + "handles": [ + { + "provider": "github", + "handle": "danielroe-bot", + "is_primary": true + } + ] + }, + "created_at": "2026-10-26T21:02:00.395Z", + "updated_at": "2026-10-26T21:02:00.395Z", + "last_message_at": "2026-10-26T21:02:00.395Z", + "last_message_author": "danielroe-bot", + "message_count": 1, + "participants": [ + { + "login": "danielroe-bot", + "actor_account_id": "01M5WYRRVZNA1TXNET6KE4Q3WX", + "identity": { + "kind": "account", + "account_id": "01M5WYRRVZNA1TXNET6KE4Q3WX", + "display_name": null, + "avatar_url": "https://avatars.githubusercontent.com/u/57801166?v=4", + "handles": [ + { + "provider": "github", + "handle": "danielroe-bot", + "is_primary": true + } + ] + } + } + ], + "review_comment_id": null, + "review_comment": null, + "messages": [ + { + "id": "01M5X0A9PCYAK06HK5CXJRQR2P", + "author": "danielroe-bot", + "identity": { + "kind": "account", + "account_id": "01M5WYRRVZNA1TXNET6KE4Q3WX", + "display_name": null, + "avatar_url": "https://avatars.githubusercontent.com/u/57801166?v=4", + "handles": [ + { + "provider": "github", + "handle": "danielroe-bot", + "is_primary": true + } + ] + }, + "created_at": "2026-10-26T21:02:00.395Z", + "body": "An upserted comment from run 20261026210133.\n\n", + "replies": [] + } + ] + } + ], + "event_cursor": "6" + } + } +} diff --git a/test/fixtures/entire/recorded/entire.com-writes/steps/review-threads/golden.json b/test/fixtures/entire/recorded/entire.com-writes/steps/review-threads/golden.json new file mode 100644 index 000000000..ddb438707 --- /dev/null +++ b/test/fixtures/entire/recorded/entire.com-writes/steps/review-threads/golden.json @@ -0,0 +1,81 @@ +{ + "items": [ + { + "id": "01M5X0AHS4JAQ93WBG0CC9JN8M", + "resolved": true, + "outdated": false, + "comments": [ + { + "ref": { + "forge": "entire", + "instance": "entire.com", + "thread": { + "forge": "entire", + "instance": "entire.com", + "repo": { + "forge": "entire", + "instance": "entire.com", + "owner": "forges-scratch", + "name": "forges-fixtures" + }, + "kind": "pull_request", + "number": "9", + "externalId": "01M5X0A49M70NAMJX878FD2QD1" + }, + "id": "01M5X0AHS47CKYTKRY42WT1YYD" + }, + "body": "A review comment from run 20261026210133.", + "author": { + "forge": "entire", + "instance": "entire.com", + "login": "danielroe", + "id": "01M5WRP9RJ4GVR2PA5PCNYP1FC", + "name": "Daniel Roe", + "avatarUrl": "https://avatars.githubusercontent.com/u/28706372?v=4", + "isBotHint": false + }, + "thread": { + "id": "01M5X0AHS4JAQ93WBG0CC9JN8M", + "resolved": true + }, + "createdAt": "" + }, + { + "ref": { + "forge": "entire", + "instance": "entire.com", + "thread": { + "forge": "entire", + "instance": "entire.com", + "repo": { + "forge": "entire", + "instance": "entire.com", + "owner": "forges-scratch", + "name": "forges-fixtures" + }, + "kind": "pull_request", + "number": "9", + "externalId": "01M5X0A49M70NAMJX878FD2QD1" + }, + "id": "01M5X0AK7JFP7KMT95DH7TEQ5S" + }, + "body": "A reply from run 20261026210133.", + "author": { + "forge": "entire", + "instance": "entire.com", + "login": "danielroe-bot", + "id": "01M5WYRRVZNA1TXNET6KE4Q3WX", + "avatarUrl": "https://avatars.githubusercontent.com/u/57801166?v=4", + "isBotHint": false + }, + "inReplyTo": "01M5X0AHS47CKYTKRY42WT1YYD", + "thread": { + "id": "01M5X0AHS4JAQ93WBG0CC9JN8M", + "resolved": true + }, + "createdAt": "" + } + ] + } + ] +} diff --git a/test/fixtures/entire/recorded/entire.com-writes/steps/review-threads/step.json b/test/fixtures/entire/recorded/entire.com-writes/steps/review-threads/step.json new file mode 100644 index 000000000..92e0e4257 --- /dev/null +++ b/test/fixtures/entire/recorded/entire.com-writes/steps/review-threads/step.json @@ -0,0 +1,7 @@ +{ + "name": "review threads", + "recordedAt": "2026-10-26T21:02:11.299Z", + "needs": [ + "create pull" + ] +} diff --git a/test/fixtures/entire/recorded/entire.com-writes/steps/reviewer/01-get-v1-me.json b/test/fixtures/entire/recorded/entire.com-writes/steps/reviewer/01-get-v1-me.json new file mode 100644 index 000000000..e8c185f22 --- /dev/null +++ b/test/fixtures/entire/recorded/entire.com-writes/steps/reviewer/01-get-v1-me.json @@ -0,0 +1,44 @@ +{ + "request": { + "method": "GET", + "url": "https://us.console.entire.io/api/v1/me" + }, + "response": { + "status": 200, + "headers": { + "link": "; rel=\"describedBy\"" + }, + "body": { + "$schema": "https://us.console.entire.io/api/v1/schemas/GetMeOutputBody.json", + "global": { + "accountId": "01M5WRP9RJ4GVR2PA5PCNYP1FC", + "handle": "danielroe", + "username": "danielroe", + "homeJurisdiction": "uk", + "createdAt": "2026-10-26T18:48:45.073805Z", + "avatarUrl": "https://avatars.githubusercontent.com/u/28706372?v=4", + "displayName": "Daniel Roe", + "handles": [ + { + "provider": "github", + "handle": "danielroe", + "providerUserId": "28706372", + "email": "redacted@example.invalid" + } + ] + }, + "regionalUnavailable": { + "error": "foreign_jurisdiction", + "jurisdiction": "uk", + "homeCoreUrl": "https://uk.auth.entire.io", + "message": "Your profile is hosted in the uk jurisdiction." + }, + "auth": { + "provider": "github", + "providerUserId": "28706372" + }, + "mode": "regional", + "jurisdiction": "us" + } + } +} diff --git a/test/fixtures/entire/recorded/entire.com-writes/steps/reviewer/golden.json b/test/fixtures/entire/recorded/entire.com-writes/steps/reviewer/golden.json new file mode 100644 index 000000000..2bced59d2 --- /dev/null +++ b/test/fixtures/entire/recorded/entire.com-writes/steps/reviewer/golden.json @@ -0,0 +1,10 @@ +{ + "forge": "entire", + "instance": "entire.com", + "login": "danielroe", + "id": "01M5WRP9RJ4GVR2PA5PCNYP1FC", + "name": "Daniel Roe", + "avatarUrl": "https://avatars.githubusercontent.com/u/28706372?v=4", + "isBotHint": false, + "createdAt": "2026-10-26T18:48:45.073Z" +} diff --git a/test/fixtures/entire/recorded/entire.com-writes/steps/reviewer/step.json b/test/fixtures/entire/recorded/entire.com-writes/steps/reviewer/step.json new file mode 100644 index 000000000..0bb8c737a --- /dev/null +++ b/test/fixtures/entire/recorded/entire.com-writes/steps/reviewer/step.json @@ -0,0 +1,4 @@ +{ + "name": "reviewer", + "recordedAt": "2026-10-26T20:52:03.496Z" +} diff --git a/test/fixtures/entire/recorded/entire.com-writes/steps/unresolve-review-thread/01-patch-discussions-01M5X0AHS4JAQ93WBG0CC9JN8M.json b/test/fixtures/entire/recorded/entire.com-writes/steps/unresolve-review-thread/01-patch-discussions-01M5X0AHS4JAQ93WBG0CC9JN8M.json new file mode 100644 index 000000000..068ed5692 --- /dev/null +++ b/test/fixtures/entire/recorded/entire.com-writes/steps/unresolve-review-thread/01-patch-discussions-01M5X0AHS4JAQ93WBG0CC9JN8M.json @@ -0,0 +1,135 @@ +{ + "request": { + "method": "PATCH", + "url": "https://aws-eu-central-1.api.entire.io/api/v1/trails/et/forges-scratch/forges-fixtures/9/discussions/01M5X0AHS4JAQ93WBG0CC9JN8M", + "body": { + "resolved": false + } + }, + "response": { + "status": 200, + "headers": { + "link": "; rel=\"describedBy\"" + }, + "body": { + "$schema": "https://aws-eu-central-1.api.entire.io/api/v1/schemas/TrailDiscussionUpdateResponseBody.json", + "discussion": { + "id": "01M5X0AHS4JAQ93WBG0CC9JN8M", + "trail_id": "01M5X0A49M70NAMJX878FD2QD1", + "title": "A review comment from run 20261026210133.", + "kind": "code_review", + "resolved": false, + "resolved_by": null, + "resolved_by_identity": { + "kind": "unknown", + "account_id": null, + "display_name": null, + "avatar_url": null, + "handles": [] + }, + "resolved_at": null, + "created_by": "01M5WRP9RJ4GVR2PA5PCNYP1FC", + "created_by_identity": { + "kind": "account", + "account_id": "01M5WRP9RJ4GVR2PA5PCNYP1FC", + "display_name": "Daniel Roe", + "avatar_url": "https://avatars.githubusercontent.com/u/28706372?v=4", + "handles": [ + { + "provider": "github", + "handle": "danielroe", + "is_primary": true + } + ] + }, + "created_at": "2026-10-26T21:02:08.674Z", + "updated_at": "2026-10-26T21:02:12.756Z", + "last_message_at": "2026-10-26T21:02:10.162Z", + "last_message_author": "danielroe-bot", + "message_count": 1, + "participants": [ + { + "login": "danielroe-bot", + "actor_account_id": "01M5WYRRVZNA1TXNET6KE4Q3WX", + "identity": { + "kind": "account", + "account_id": "01M5WYRRVZNA1TXNET6KE4Q3WX", + "display_name": null, + "avatar_url": "https://avatars.githubusercontent.com/u/57801166?v=4", + "handles": [ + { + "provider": "github", + "handle": "danielroe-bot", + "is_primary": true + } + ] + } + } + ], + "review_comment_id": "01M5X0AHS47CKYTKRY42WT1YYD", + "review_comment": { + "discussion_id": "01M5X0AHS4JAQ93WBG0CC9JN8M", + "discussion_message_count": 1, + "id": "01M5X0AHS47CKYTKRY42WT1YYD", + "trail_id": "01M5X0A49M70NAMJX878FD2QD1", + "repo_id": "01M5WYSQC41P69DTXEMZ0TE5YK", + "review_id": "01M5X0AGW04E508JH4BY5VE4V7", + "code_version_id": "01M5X0AGVPHGGQD3ZADR9BX2KV", + "actor_id": "01M5WRP9RJ4GVR2PA5PCNYP1FC", + "actor_display_name": "danielroe", + "actor_identity": { + "kind": "account", + "account_id": "01M5WRP9RJ4GVR2PA5PCNYP1FC", + "display_name": "Daniel Roe", + "avatar_url": "https://avatars.githubusercontent.com/u/28706372?v=4", + "handles": [ + { + "provider": "github", + "handle": "danielroe", + "is_primary": true + } + ] + }, + "body": "A review comment from run 20261026210133.", + "severity": null, + "confidence": null, + "status": "open", + "status_reason": null, + "status_actor_id": null, + "status_actor_display_name": null, + "status_actor_identity": { + "kind": "unknown", + "account_id": null, + "display_name": null, + "avatar_url": null, + "handles": [] + }, + "status_changed_at": null, + "status_source": null, + "status_actor_kind": null, + "stale_outcome": "current", + "stale_checked_at": null, + "stale_checked_code_version_id": null, + "client_id": "1", + "client_id_hash": "876dd2d2f894bbd709b9c4adf233e9cbe880d2c74674e9987f97a2d6c6e31faa", + "created_at": "2026-10-26T21:02:08.674Z", + "updated_at": "2026-10-26T21:02:12.756Z", + "location": { + "id": "01M5X0AHS4172XDD0412MR744W", + "review_comment_id": "01M5X0AHS47CKYTKRY42WT1YYD", + "code_version_id": "01M5X0AGVPHGGQD3ZADR9BX2KV", + "granularity": "whole_change", + "file_path": null, + "start_line": null, + "start_column": null, + "end_line": null, + "end_column": null, + "selected_text": null, + "nearby_text": null, + "language": null + } + } + } + } + } +} diff --git a/test/fixtures/entire/recorded/entire.com-writes/steps/unresolve-review-thread/golden.json b/test/fixtures/entire/recorded/entire.com-writes/steps/unresolve-review-thread/golden.json new file mode 100644 index 000000000..19765bd50 --- /dev/null +++ b/test/fixtures/entire/recorded/entire.com-writes/steps/unresolve-review-thread/golden.json @@ -0,0 +1 @@ +null diff --git a/test/fixtures/entire/recorded/entire.com-writes/steps/unresolve-review-thread/step.json b/test/fixtures/entire/recorded/entire.com-writes/steps/unresolve-review-thread/step.json new file mode 100644 index 000000000..5b938d60a --- /dev/null +++ b/test/fixtures/entire/recorded/entire.com-writes/steps/unresolve-review-thread/step.json @@ -0,0 +1,8 @@ +{ + "name": "unresolve review thread", + "recordedAt": "2026-10-26T21:02:11.505Z", + "needs": [ + "create pull", + "resolve review thread" + ] +} diff --git a/test/fixtures/entire/recorded/entire.com/manifest.json b/test/fixtures/entire/recorded/entire.com/manifest.json new file mode 100644 index 000000000..8c1d72a87 --- /dev/null +++ b/test/fixtures/entire/recorded/entire.com/manifest.json @@ -0,0 +1,40 @@ +{ + "baseUrl": "https://us.console.entire.io/api/v1", + "repo": { + "forge": "entire", + "instance": "entire.com", + "owner": "forges", + "name": "forges-fixtures" + }, + "issue": { + "forge": "entire", + "instance": "entire.com", + "repo": { + "forge": "entire", + "instance": "entire.com", + "owner": "forges", + "name": "", + "kind": "namespace" + }, + "kind": "issue", + "number": "1" + }, + "pull": { + "forge": "entire", + "instance": "entire.com", + "repo": { + "forge": "entire", + "instance": "entire.com", + "owner": "forges", + "name": "forges-fixtures" + }, + "kind": "pull_request", + "number": "1" + }, + "scratch": { + "forge": "entire", + "instance": "entire.com", + "owner": "forges-scratch", + "name": "forges-fixtures" + } +} diff --git a/test/fixtures/entire/recorded/entire.com/steps/branches/01-get-01M5WS0P331VQ3AARB26Z9DGV7-branches.json b/test/fixtures/entire/recorded/entire.com/steps/branches/01-get-01M5WS0P331VQ3AARB26Z9DGV7-branches.json new file mode 100644 index 000000000..3eed2b53b --- /dev/null +++ b/test/fixtures/entire/recorded/entire.com/steps/branches/01-get-01M5WS0P331VQ3AARB26Z9DGV7-branches.json @@ -0,0 +1,29 @@ +{ + "request": { + "method": "GET", + "url": "https://aws-eu-west-2.api.entire.io/api/v1/git/repos/01M5WS0P331VQ3AARB26Z9DGV7/branches?pageSize=3" + }, + "response": { + "status": 200, + "headers": { + "link": "; rel=\"describedBy\"" + }, + "body": { + "$schema": "https://aws-eu-west-2.api.entire.io/api/v1/schemas/ListBranchesResponse.json", + "branches": [ + { + "name": "feature/shout", + "commitSHA": "9ec20061f17f35212247320f525ec51d3e00c41a" + }, + { + "name": "fix/typo", + "commitSHA": "dd07002e23c86b5e68d53ebe9949e1bf5549c8ca" + }, + { + "name": "main", + "commitSHA": "dd07002e23c86b5e68d53ebe9949e1bf5549c8ca" + } + ] + } + } +} diff --git a/test/fixtures/entire/recorded/entire.com/steps/branches/02-get-01M5WS0P331VQ3AARB26Z9DGV7-refs.json b/test/fixtures/entire/recorded/entire.com/steps/branches/02-get-01M5WS0P331VQ3AARB26Z9DGV7-refs.json new file mode 100644 index 000000000..47fc7932b --- /dev/null +++ b/test/fixtures/entire/recorded/entire.com/steps/branches/02-get-01M5WS0P331VQ3AARB26Z9DGV7-refs.json @@ -0,0 +1,22 @@ +{ + "request": { + "method": "GET", + "url": "https://aws-eu-west-2.api.entire.io/api/v1/git/repos/01M5WS0P331VQ3AARB26Z9DGV7/refs?prefix=HEAD&symrefs=true" + }, + "response": { + "status": 200, + "headers": { + "link": "; rel=\"describedBy\"" + }, + "body": { + "$schema": "https://aws-eu-west-2.api.entire.io/api/v1/schemas/ListRefsResponse.json", + "refs": [ + { + "name": "HEAD", + "oid": "dd07002e23c86b5e68d53ebe9949e1bf5549c8ca", + "symrefTarget": "refs/heads/main" + } + ] + } + } +} diff --git a/test/fixtures/entire/recorded/entire.com/steps/branches/golden.json b/test/fixtures/entire/recorded/entire.com/steps/branches/golden.json new file mode 100644 index 000000000..2684e627c --- /dev/null +++ b/test/fixtures/entire/recorded/entire.com/steps/branches/golden.json @@ -0,0 +1,19 @@ +{ + "items": [ + { + "name": "feature/shout", + "sha": "9ec20061f17f35212247320f525ec51d3e00c41a", + "isDefault": false + }, + { + "name": "fix/typo", + "sha": "dd07002e23c86b5e68d53ebe9949e1bf5549c8ca", + "isDefault": false + }, + { + "name": "main", + "sha": "dd07002e23c86b5e68d53ebe9949e1bf5549c8ca", + "isDefault": true + } + ] +} diff --git a/test/fixtures/entire/recorded/entire.com/steps/branches/step.json b/test/fixtures/entire/recorded/entire.com/steps/branches/step.json new file mode 100644 index 000000000..0fcb070b7 --- /dev/null +++ b/test/fixtures/entire/recorded/entire.com/steps/branches/step.json @@ -0,0 +1,4 @@ +{ + "name": "branches", + "recordedAt": "2026-10-26T19:57:22.982Z" +} diff --git a/test/fixtures/entire/recorded/entire.com/steps/collaborators/01-get-01M5WS0P331VQ3AARB26Z9DGV7-collaborators.json b/test/fixtures/entire/recorded/entire.com/steps/collaborators/01-get-01M5WS0P331VQ3AARB26Z9DGV7-collaborators.json new file mode 100644 index 000000000..bd1888b6b --- /dev/null +++ b/test/fixtures/entire/recorded/entire.com/steps/collaborators/01-get-01M5WS0P331VQ3AARB26Z9DGV7-collaborators.json @@ -0,0 +1,28 @@ +{ + "request": { + "method": "GET", + "url": "https://us.console.entire.io/api/v1/repos/01M5WS0P331VQ3AARB26Z9DGV7/collaborators?pageSize=3" + }, + "response": { + "status": 200, + "headers": { + "link": "; rel=\"describedBy\"" + }, + "body": { + "$schema": "https://us.console.entire.io/api/v1/schemas/ListRepoCollaboratorsOutputBody.json", + "collaborators": [ + { + "accountId": "01M5WRP9RJ4GVR2PA5PCNYP1FC", + "username": "danielroe", + "handle": "github:danielroe", + "role": "admin" + }, + { + "accountId": "01M5WYRRVZNA1TXNET6KE4Q3WX", + "handle": "github:danielroe-bot", + "role": "admin" + } + ] + } + } +} diff --git a/test/fixtures/entire/recorded/entire.com/steps/collaborators/golden.json b/test/fixtures/entire/recorded/entire.com/steps/collaborators/golden.json new file mode 100644 index 000000000..21c8b1c86 --- /dev/null +++ b/test/fixtures/entire/recorded/entire.com/steps/collaborators/golden.json @@ -0,0 +1,25 @@ +{ + "items": [ + { + "actor": { + "forge": "entire", + "instance": "entire.com", + "login": "danielroe", + "id": "01M5WRP9RJ4GVR2PA5PCNYP1FC", + "isBotHint": false + }, + "role": "admin", + "roleRaw": "admin" + }, + { + "actor": { + "forge": "entire", + "instance": "entire.com", + "id": "01M5WYRRVZNA1TXNET6KE4Q3WX", + "isBotHint": false + }, + "role": "admin", + "roleRaw": "admin" + } + ] +} diff --git a/test/fixtures/entire/recorded/entire.com/steps/collaborators/step.json b/test/fixtures/entire/recorded/entire.com/steps/collaborators/step.json new file mode 100644 index 000000000..dbcb25272 --- /dev/null +++ b/test/fixtures/entire/recorded/entire.com/steps/collaborators/step.json @@ -0,0 +1,4 @@ +{ + "name": "collaborators", + "recordedAt": "2026-10-26T21:02:26.415Z" +} diff --git a/test/fixtures/entire/recorded/entire.com/steps/commit/01-get-01M5WS0P331VQ3AARB26Z9DGV7-commits.json b/test/fixtures/entire/recorded/entire.com/steps/commit/01-get-01M5WS0P331VQ3AARB26Z9DGV7-commits.json new file mode 100644 index 000000000..c45b6604f --- /dev/null +++ b/test/fixtures/entire/recorded/entire.com/steps/commit/01-get-01M5WS0P331VQ3AARB26Z9DGV7-commits.json @@ -0,0 +1,41 @@ +{ + "request": { + "method": "GET", + "url": "https://aws-eu-west-2.api.entire.io/api/v1/git/repos/01M5WS0P331VQ3AARB26Z9DGV7/commits?ref=9ec20061f17f35212247320f525ec51d3e00c41a&pageSize=1&includeStats=true" + }, + "response": { + "status": 200, + "headers": { + "link": "; rel=\"describedBy\"" + }, + "body": { + "$schema": "https://aws-eu-west-2.api.entire.io/api/v1/schemas/ListCommitsResponse.json", + "commits": [ + { + "sha": "9ec20061f17f35212247320f525ec51d3e00c41a", + "parents": [ + "c83b64d5032ae0ee89ecbaeea7273b2291b4d2e5" + ], + "message": "docs: mention shouting\n", + "author": { + "name": "forges fixtures", + "email": "redacted@example.invalid", + "date": "2026-10-02T10:01:00Z" + }, + "committer": { + "name": "forges fixtures", + "email": "redacted@example.invalid", + "date": "2026-10-02T10:01:00Z" + }, + "stats": { + "additions": 2, + "deletions": 0, + "filesChanged": 1, + "truncated": false + } + } + ], + "nextPageToken": "eyJmIjpbImM4M2I2NGQ1MDMyYWUwZWU4OWVjYmFlZWE3MjczYjIyOTFiNGQyZTUiXX0" + } + } +} diff --git a/test/fixtures/entire/recorded/entire.com/steps/commit/02-get-commits-SHA.json b/test/fixtures/entire/recorded/entire.com/steps/commit/02-get-commits-SHA.json new file mode 100644 index 000000000..fdb43b2ef --- /dev/null +++ b/test/fixtures/entire/recorded/entire.com/steps/commit/02-get-commits-SHA.json @@ -0,0 +1,50 @@ +{ + "request": { + "method": "GET", + "url": "https://aws-eu-west-2.api.entire.io/api/v1/repos/01M5WS0P331VQ3AARB26Z9DGV7/commits/9ec20061f17f35212247320f525ec51d3e00c41a" + }, + "response": { + "status": 200, + "headers": { + "link": "; rel=\"describedBy\"" + }, + "body": { + "$schema": "https://aws-eu-west-2.api.entire.io/api/v1/schemas/CommitDetailOutputBody.json", + "commit_sha": "9ec20061f17f35212247320f525ec51d3e00c41a", + "branches": [], + "default_branch": "main", + "suggested_branch": null, + "commit": { + "commitSha": "9ec20061f17f35212247320f525ec51d3e00c41a", + "commitMessage": "docs: mention shouting", + "commitSubject": "docs: mention shouting", + "commitBody": null, + "commitAuthor": "forges fixtures", + "commitAuthorUsername": null, + "commitDate": "2026-10-02T10:01:00.000Z", + "additions": 2, + "deletions": 0, + "filesChanged": 1, + "filesTouched": [ + "README.md" + ], + "fileStats": [ + { + "filename": "README.md", + "status": "modified", + "additions": 2, + "deletions": 0, + "patch": "diff --git a/README.md b/README.md\nindex a38a42678a31fbc0dd0be8e507f33c82c9fd12e0..3a191c52c3aba859eed62de00fe26038570e0c92 100644\n--- a/README.md\n+++ b/README.md\n@@ -1,3 +1,5 @@\n # forges-fixtures\n \n A repository for the Entire recordings of [forges](https://forges.link).\n+\n+Pass `--shout` to greet loudly.\n" + } + ], + "url": null, + "checkpoints": [], + "trailNumber": 1, + "trailNumbers": [ + 1 + ] + }, + "repo_full_name": "forges/forges-fixtures" + } + } +} diff --git a/test/fixtures/entire/recorded/entire.com/steps/commit/golden.json b/test/fixtures/entire/recorded/entire.com/steps/commit/golden.json new file mode 100644 index 000000000..6953ae27b --- /dev/null +++ b/test/fixtures/entire/recorded/entire.com/steps/commit/golden.json @@ -0,0 +1,43 @@ +{ + "ref": { + "forge": "entire", + "instance": "entire.com", + "repo": { + "forge": "entire", + "instance": "entire.com", + "owner": "forges", + "name": "forges-fixtures" + }, + "sha": "9ec20061f17f35212247320f525ec51d3e00c41a" + }, + "sha": "9ec20061f17f35212247320f525ec51d3e00c41a", + "message": "docs: mention shouting", + "author": { + "name": "forges fixtures", + "email": "redacted@example.invalid", + "date": "2026-10-02T10:01:00.000Z" + }, + "committer": { + "name": "forges fixtures", + "email": "redacted@example.invalid", + "date": "2026-10-02T10:01:00.000Z" + }, + "parents": [ + "c83b64d5032ae0ee89ecbaeea7273b2291b4d2e5" + ], + "stats": { + "additions": 2, + "deletions": 0, + "total": 2 + }, + "files": [ + { + "path": "README.md", + "status": "modified", + "statusRaw": "modified", + "additions": 2, + "deletions": 0, + "patch": "diff --git a/README.md b/README.md\nindex a38a42678a31fbc0dd0be8e507f33c82c9fd12e0..3a191c52c3aba859eed62de00fe26038570e0c92 100644\n--- a/README.md\n+++ b/README.md\n@@ -1,3 +1,5 @@\n # forges-fixtures\n \n A repository for the Entire recordings of [forges](https://forges.link).\n+\n+Pass `--shout` to greet loudly.\n" + } + ] +} diff --git a/test/fixtures/entire/recorded/entire.com/steps/commit/step.json b/test/fixtures/entire/recorded/entire.com/steps/commit/step.json new file mode 100644 index 000000000..eb71b147c --- /dev/null +++ b/test/fixtures/entire/recorded/entire.com/steps/commit/step.json @@ -0,0 +1,7 @@ +{ + "name": "commit", + "recordedAt": "2026-10-26T19:57:23.749Z", + "needs": [ + "pull" + ] +} diff --git a/test/fixtures/entire/recorded/entire.com/steps/commits/01-get-01M5WS0P331VQ3AARB26Z9DGV7-commits.json b/test/fixtures/entire/recorded/entire.com/steps/commits/01-get-01M5WS0P331VQ3AARB26Z9DGV7-commits.json new file mode 100644 index 000000000..c759cc60d --- /dev/null +++ b/test/fixtures/entire/recorded/entire.com/steps/commits/01-get-01M5WS0P331VQ3AARB26Z9DGV7-commits.json @@ -0,0 +1,87 @@ +{ + "request": { + "method": "GET", + "url": "https://aws-eu-west-2.api.entire.io/api/v1/git/repos/01M5WS0P331VQ3AARB26Z9DGV7/commits?ref=HEAD&includeStats=true&pageSize=3" + }, + "response": { + "status": 200, + "headers": { + "link": "; rel=\"describedBy\"" + }, + "body": { + "$schema": "https://aws-eu-west-2.api.entire.io/api/v1/schemas/ListCommitsResponse.json", + "commits": [ + { + "sha": "dd07002e23c86b5e68d53ebe9949e1bf5549c8ca", + "parents": [ + "8127b4c88662985c819a6b3cabecde203907c3e2" + ], + "message": "docs: say what forges is\n", + "author": { + "name": "forges fixtures", + "email": "redacted@example.invalid", + "date": "2026-10-02T11:00:00Z" + }, + "committer": { + "name": "forges fixtures", + "email": "redacted@example.invalid", + "date": "2026-10-02T11:00:00Z" + }, + "stats": { + "additions": 1, + "deletions": 1, + "filesChanged": 1, + "truncated": false + } + }, + { + "sha": "8127b4c88662985c819a6b3cabecde203907c3e2", + "parents": [ + "df5c2c540bd97eb54ae4369e7a24dda6c551a9fb" + ], + "message": "feat: add a command line entry\n", + "author": { + "name": "forges fixtures", + "email": "redacted@example.invalid", + "date": "2026-10-01T10:04:00Z" + }, + "committer": { + "name": "forges fixtures", + "email": "redacted@example.invalid", + "date": "2026-10-01T10:04:00Z" + }, + "stats": { + "additions": 3, + "deletions": 0, + "filesChanged": 1, + "truncated": false + } + }, + { + "sha": "df5c2c540bd97eb54ae4369e7a24dda6c551a9fb", + "parents": [ + "8344a38e82f7cf7fd830a450b7de4a382ac0de1f" + ], + "message": "chore: add a licence\n", + "author": { + "name": "forges fixtures", + "email": "redacted@example.invalid", + "date": "2026-10-01T10:03:00Z" + }, + "committer": { + "name": "forges fixtures", + "email": "redacted@example.invalid", + "date": "2026-10-01T10:03:00Z" + }, + "stats": { + "additions": 21, + "deletions": 0, + "filesChanged": 1, + "truncated": false + } + } + ], + "nextPageToken": "eyJmIjpbIjgzNDRhMzhlODJmN2NmN2ZkODMwYTQ1MGI3ZGU0YTM4MmFjMGRlMWYiXX0" + } + } +} diff --git a/test/fixtures/entire/recorded/entire.com/steps/commits/golden.json b/test/fixtures/entire/recorded/entire.com/steps/commits/golden.json new file mode 100644 index 000000000..a21125171 --- /dev/null +++ b/test/fixtures/entire/recorded/entire.com/steps/commits/golden.json @@ -0,0 +1,106 @@ +{ + "items": [ + { + "ref": { + "forge": "entire", + "instance": "entire.com", + "repo": { + "forge": "entire", + "instance": "entire.com", + "owner": "forges", + "name": "forges-fixtures" + }, + "sha": "dd07002e23c86b5e68d53ebe9949e1bf5549c8ca" + }, + "sha": "dd07002e23c86b5e68d53ebe9949e1bf5549c8ca", + "message": "docs: say what forges is", + "author": { + "name": "forges fixtures", + "email": "redacted@example.invalid", + "date": "2026-10-02T11:00:00.000Z" + }, + "committer": { + "name": "forges fixtures", + "email": "redacted@example.invalid", + "date": "2026-10-02T11:00:00.000Z" + }, + "parents": [ + "8127b4c88662985c819a6b3cabecde203907c3e2" + ], + "stats": { + "additions": 1, + "deletions": 1, + "total": 2 + } + }, + { + "ref": { + "forge": "entire", + "instance": "entire.com", + "repo": { + "forge": "entire", + "instance": "entire.com", + "owner": "forges", + "name": "forges-fixtures" + }, + "sha": "8127b4c88662985c819a6b3cabecde203907c3e2" + }, + "sha": "8127b4c88662985c819a6b3cabecde203907c3e2", + "message": "feat: add a command line entry", + "author": { + "name": "forges fixtures", + "email": "redacted@example.invalid", + "date": "2026-10-01T10:04:00.000Z" + }, + "committer": { + "name": "forges fixtures", + "email": "redacted@example.invalid", + "date": "2026-10-01T10:04:00.000Z" + }, + "parents": [ + "df5c2c540bd97eb54ae4369e7a24dda6c551a9fb" + ], + "stats": { + "additions": 3, + "deletions": 0, + "total": 3 + } + }, + { + "ref": { + "forge": "entire", + "instance": "entire.com", + "repo": { + "forge": "entire", + "instance": "entire.com", + "owner": "forges", + "name": "forges-fixtures" + }, + "sha": "df5c2c540bd97eb54ae4369e7a24dda6c551a9fb" + }, + "sha": "df5c2c540bd97eb54ae4369e7a24dda6c551a9fb", + "message": "chore: add a licence", + "author": { + "name": "forges fixtures", + "email": "redacted@example.invalid", + "date": "2026-10-01T10:03:00.000Z" + }, + "committer": { + "name": "forges fixtures", + "email": "redacted@example.invalid", + "date": "2026-10-01T10:03:00.000Z" + }, + "parents": [ + "8344a38e82f7cf7fd830a450b7de4a382ac0de1f" + ], + "stats": { + "additions": 21, + "deletions": 0, + "total": 21 + } + } + ], + "cursor": { + "token": "eyJmIjpbIjgzNDRhMzhlODJmN2NmN2ZkODMwYTQ1MGI3ZGU0YTM4MmFjMGRlMWYiXX0" + } +} diff --git a/test/fixtures/entire/recorded/entire.com/steps/commits/step.json b/test/fixtures/entire/recorded/entire.com/steps/commits/step.json new file mode 100644 index 000000000..cd5544b2c --- /dev/null +++ b/test/fixtures/entire/recorded/entire.com/steps/commits/step.json @@ -0,0 +1,4 @@ +{ + "name": "commits", + "recordedAt": "2026-10-26T19:57:23.580Z" +} diff --git a/test/fixtures/entire/recorded/entire.com/steps/compare-limited/01-get-01M5WS0P331VQ3AARB26Z9DGV7-commits.json b/test/fixtures/entire/recorded/entire.com/steps/compare-limited/01-get-01M5WS0P331VQ3AARB26Z9DGV7-commits.json new file mode 100644 index 000000000..146d4e348 --- /dev/null +++ b/test/fixtures/entire/recorded/entire.com/steps/compare-limited/01-get-01M5WS0P331VQ3AARB26Z9DGV7-commits.json @@ -0,0 +1,133 @@ +{ + "request": { + "method": "GET", + "url": "https://aws-eu-west-2.api.entire.io/api/v1/git/repos/01M5WS0P331VQ3AARB26Z9DGV7/commits?ref=main&includeStats=true&pageSize=5" + }, + "response": { + "status": 200, + "headers": { + "link": "; rel=\"describedBy\"" + }, + "body": { + "$schema": "https://aws-eu-west-2.api.entire.io/api/v1/schemas/ListCommitsResponse.json", + "commits": [ + { + "sha": "dd07002e23c86b5e68d53ebe9949e1bf5549c8ca", + "parents": [ + "8127b4c88662985c819a6b3cabecde203907c3e2" + ], + "message": "docs: say what forges is\n", + "author": { + "name": "forges fixtures", + "email": "redacted@example.invalid", + "date": "2026-10-02T11:00:00Z" + }, + "committer": { + "name": "forges fixtures", + "email": "redacted@example.invalid", + "date": "2026-10-02T11:00:00Z" + }, + "stats": { + "additions": 1, + "deletions": 1, + "filesChanged": 1, + "truncated": false + } + }, + { + "sha": "8127b4c88662985c819a6b3cabecde203907c3e2", + "parents": [ + "df5c2c540bd97eb54ae4369e7a24dda6c551a9fb" + ], + "message": "feat: add a command line entry\n", + "author": { + "name": "forges fixtures", + "email": "redacted@example.invalid", + "date": "2026-10-01T10:04:00Z" + }, + "committer": { + "name": "forges fixtures", + "email": "redacted@example.invalid", + "date": "2026-10-01T10:04:00Z" + }, + "stats": { + "additions": 3, + "deletions": 0, + "filesChanged": 1, + "truncated": false + } + }, + { + "sha": "df5c2c540bd97eb54ae4369e7a24dda6c551a9fb", + "parents": [ + "8344a38e82f7cf7fd830a450b7de4a382ac0de1f" + ], + "message": "chore: add a licence\n", + "author": { + "name": "forges fixtures", + "email": "redacted@example.invalid", + "date": "2026-10-01T10:03:00Z" + }, + "committer": { + "name": "forges fixtures", + "email": "redacted@example.invalid", + "date": "2026-10-01T10:03:00Z" + }, + "stats": { + "additions": 21, + "deletions": 0, + "filesChanged": 1, + "truncated": false + } + }, + { + "sha": "8344a38e82f7cf7fd830a450b7de4a382ac0de1f", + "parents": [ + "fc6d8c9fb93b340e7d064fee866d49d70073ff34" + ], + "message": "docs: describe the fixture\n", + "author": { + "name": "forges fixtures", + "email": "redacted@example.invalid", + "date": "2026-10-01T10:02:00Z" + }, + "committer": { + "name": "forges fixtures", + "email": "redacted@example.invalid", + "date": "2026-10-01T10:02:00Z" + }, + "stats": { + "additions": 2, + "deletions": 0, + "filesChanged": 1, + "truncated": false + } + }, + { + "sha": "fc6d8c9fb93b340e7d064fee866d49d70073ff34", + "parents": [ + "3e43c73635a4b6242ec9be1b632d929bec20a909" + ], + "message": "fix: greet the world when no name is given\n", + "author": { + "name": "forges fixtures", + "email": "redacted@example.invalid", + "date": "2026-10-01T10:01:00Z" + }, + "committer": { + "name": "forges fixtures", + "email": "redacted@example.invalid", + "date": "2026-10-01T10:01:00Z" + }, + "stats": { + "additions": 1, + "deletions": 1, + "filesChanged": 1, + "truncated": false + } + } + ], + "nextPageToken": "eyJmIjpbIjNlNDNjNzM2MzVhNGI2MjQyZWM5YmUxYjYzMmQ5MjliZWMyMGE5MDkiXX0" + } + } +} diff --git a/test/fixtures/entire/recorded/entire.com/steps/compare-limited/02-get-01M5WS0P331VQ3AARB26Z9DGV7-commits.json b/test/fixtures/entire/recorded/entire.com/steps/compare-limited/02-get-01M5WS0P331VQ3AARB26Z9DGV7-commits.json new file mode 100644 index 000000000..afff5ce8c --- /dev/null +++ b/test/fixtures/entire/recorded/entire.com/steps/compare-limited/02-get-01M5WS0P331VQ3AARB26Z9DGV7-commits.json @@ -0,0 +1,52 @@ +{ + "request": { + "method": "GET", + "url": "https://aws-eu-west-2.api.entire.io/api/v1/git/repos/01M5WS0P331VQ3AARB26Z9DGV7/commits?ref=main¬Ref=fc6d8c9fb93b340e7d064fee866d49d70073ff34&pageSize=2" + }, + "response": { + "status": 200, + "headers": { + "link": "; rel=\"describedBy\"" + }, + "body": { + "$schema": "https://aws-eu-west-2.api.entire.io/api/v1/schemas/ListCommitsResponse.json", + "commits": [ + { + "sha": "dd07002e23c86b5e68d53ebe9949e1bf5549c8ca", + "parents": [ + "8127b4c88662985c819a6b3cabecde203907c3e2" + ], + "message": "docs: say what forges is\n", + "author": { + "name": "forges fixtures", + "email": "redacted@example.invalid", + "date": "2026-10-02T11:00:00Z" + }, + "committer": { + "name": "forges fixtures", + "email": "redacted@example.invalid", + "date": "2026-10-02T11:00:00Z" + } + }, + { + "sha": "8127b4c88662985c819a6b3cabecde203907c3e2", + "parents": [ + "df5c2c540bd97eb54ae4369e7a24dda6c551a9fb" + ], + "message": "feat: add a command line entry\n", + "author": { + "name": "forges fixtures", + "email": "redacted@example.invalid", + "date": "2026-10-01T10:04:00Z" + }, + "committer": { + "name": "forges fixtures", + "email": "redacted@example.invalid", + "date": "2026-10-01T10:04:00Z" + } + } + ], + "nextPageToken": "eyJmIjpbImRmNWMyYzU0MGJkOTdlYjU0YWU0MzY5ZTdhMjRkZGE2YzU1MWE5ZmIiXX0" + } + } +} diff --git a/test/fixtures/entire/recorded/entire.com/steps/compare-limited/03-get-compare-status.json b/test/fixtures/entire/recorded/entire.com/steps/compare-limited/03-get-compare-status.json new file mode 100644 index 000000000..1400a22b6 --- /dev/null +++ b/test/fixtures/entire/recorded/entire.com/steps/compare-limited/03-get-compare-status.json @@ -0,0 +1,21 @@ +{ + "request": { + "method": "GET", + "url": "https://aws-eu-west-2.api.entire.io/api/v1/git/repos/01M5WS0P331VQ3AARB26Z9DGV7/compare/status?base=fc6d8c9fb93b340e7d064fee866d49d70073ff34&head=main" + }, + "response": { + "status": 200, + "headers": { + "link": "; rel=\"describedBy\"" + }, + "body": { + "$schema": "https://aws-eu-west-2.api.entire.io/api/v1/schemas/CompareStatusResponse.json", + "commitsAhead": 4, + "commitsBehind": 0, + "mergeBaseSHA": "fc6d8c9fb93b340e7d064fee866d49d70073ff34", + "resolvedBaseSHA": "fc6d8c9fb93b340e7d064fee866d49d70073ff34", + "resolvedHeadSHA": "dd07002e23c86b5e68d53ebe9949e1bf5549c8ca", + "truncated": false + } + } +} diff --git a/test/fixtures/entire/recorded/entire.com/steps/compare-limited/golden.json b/test/fixtures/entire/recorded/entire.com/steps/compare-limited/golden.json new file mode 100644 index 000000000..9a7d2cb76 --- /dev/null +++ b/test/fixtures/entire/recorded/entire.com/steps/compare-limited/golden.json @@ -0,0 +1,66 @@ +{ + "base": "fc6d8c9fb93b340e7d064fee866d49d70073ff34", + "head": "main", + "aheadBy": 4, + "behindBy": 0, + "commits": [ + { + "ref": { + "forge": "entire", + "instance": "entire.com", + "repo": { + "forge": "entire", + "instance": "entire.com", + "owner": "forges", + "name": "forges-fixtures" + }, + "sha": "dd07002e23c86b5e68d53ebe9949e1bf5549c8ca" + }, + "sha": "dd07002e23c86b5e68d53ebe9949e1bf5549c8ca", + "message": "docs: say what forges is", + "author": { + "name": "forges fixtures", + "email": "redacted@example.invalid", + "date": "2026-10-02T11:00:00.000Z" + }, + "committer": { + "name": "forges fixtures", + "email": "redacted@example.invalid", + "date": "2026-10-02T11:00:00.000Z" + }, + "parents": [ + "8127b4c88662985c819a6b3cabecde203907c3e2" + ] + }, + { + "ref": { + "forge": "entire", + "instance": "entire.com", + "repo": { + "forge": "entire", + "instance": "entire.com", + "owner": "forges", + "name": "forges-fixtures" + }, + "sha": "8127b4c88662985c819a6b3cabecde203907c3e2" + }, + "sha": "8127b4c88662985c819a6b3cabecde203907c3e2", + "message": "feat: add a command line entry", + "author": { + "name": "forges fixtures", + "email": "redacted@example.invalid", + "date": "2026-10-01T10:04:00.000Z" + }, + "committer": { + "name": "forges fixtures", + "email": "redacted@example.invalid", + "date": "2026-10-01T10:04:00.000Z" + }, + "parents": [ + "df5c2c540bd97eb54ae4369e7a24dda6c551a9fb" + ] + } + ], + "files": [], + "mergeBaseSha": "fc6d8c9fb93b340e7d064fee866d49d70073ff34" +} diff --git a/test/fixtures/entire/recorded/entire.com/steps/compare-limited/step.json b/test/fixtures/entire/recorded/entire.com/steps/compare-limited/step.json new file mode 100644 index 000000000..9120ccd13 --- /dev/null +++ b/test/fixtures/entire/recorded/entire.com/steps/compare-limited/step.json @@ -0,0 +1,7 @@ +{ + "name": "compare limited", + "recordedAt": "2026-10-26T19:57:24.349Z", + "needs": [ + "repo" + ] +} diff --git a/test/fixtures/entire/recorded/entire.com/steps/compare/01-get-01M5WS0P331VQ3AARB26Z9DGV7-commits.json b/test/fixtures/entire/recorded/entire.com/steps/compare/01-get-01M5WS0P331VQ3AARB26Z9DGV7-commits.json new file mode 100644 index 000000000..c0f0622e1 --- /dev/null +++ b/test/fixtures/entire/recorded/entire.com/steps/compare/01-get-01M5WS0P331VQ3AARB26Z9DGV7-commits.json @@ -0,0 +1,51 @@ +{ + "request": { + "method": "GET", + "url": "https://aws-eu-west-2.api.entire.io/api/v1/git/repos/01M5WS0P331VQ3AARB26Z9DGV7/commits?ref=9ec20061f17f35212247320f525ec51d3e00c41a¬Ref=8127b4c88662985c819a6b3cabecde203907c3e2&pageSize=200" + }, + "response": { + "status": 200, + "headers": { + "link": "; rel=\"describedBy\"" + }, + "body": { + "$schema": "https://aws-eu-west-2.api.entire.io/api/v1/schemas/ListCommitsResponse.json", + "commits": [ + { + "sha": "9ec20061f17f35212247320f525ec51d3e00c41a", + "parents": [ + "c83b64d5032ae0ee89ecbaeea7273b2291b4d2e5" + ], + "message": "docs: mention shouting\n", + "author": { + "name": "forges fixtures", + "email": "redacted@example.invalid", + "date": "2026-10-02T10:01:00Z" + }, + "committer": { + "name": "forges fixtures", + "email": "redacted@example.invalid", + "date": "2026-10-02T10:01:00Z" + } + }, + { + "sha": "c83b64d5032ae0ee89ecbaeea7273b2291b4d2e5", + "parents": [ + "8127b4c88662985c819a6b3cabecde203907c3e2" + ], + "message": "feat: shout greetings\n", + "author": { + "name": "forges fixtures", + "email": "redacted@example.invalid", + "date": "2026-10-02T10:00:00Z" + }, + "committer": { + "name": "forges fixtures", + "email": "redacted@example.invalid", + "date": "2026-10-02T10:00:00Z" + } + } + ] + } + } +} diff --git a/test/fixtures/entire/recorded/entire.com/steps/compare/02-get-compare-status.json b/test/fixtures/entire/recorded/entire.com/steps/compare/02-get-compare-status.json new file mode 100644 index 000000000..5fd5279e3 --- /dev/null +++ b/test/fixtures/entire/recorded/entire.com/steps/compare/02-get-compare-status.json @@ -0,0 +1,21 @@ +{ + "request": { + "method": "GET", + "url": "https://aws-eu-west-2.api.entire.io/api/v1/git/repos/01M5WS0P331VQ3AARB26Z9DGV7/compare/status?base=main&head=9ec20061f17f35212247320f525ec51d3e00c41a" + }, + "response": { + "status": 200, + "headers": { + "link": "; rel=\"describedBy\"" + }, + "body": { + "$schema": "https://aws-eu-west-2.api.entire.io/api/v1/schemas/CompareStatusResponse.json", + "commitsAhead": 2, + "commitsBehind": 1, + "mergeBaseSHA": "8127b4c88662985c819a6b3cabecde203907c3e2", + "resolvedBaseSHA": "dd07002e23c86b5e68d53ebe9949e1bf5549c8ca", + "resolvedHeadSHA": "9ec20061f17f35212247320f525ec51d3e00c41a", + "truncated": false + } + } +} diff --git a/test/fixtures/entire/recorded/entire.com/steps/compare/03-get-01M5WS0P331VQ3AARB26Z9DGV7-compare.json b/test/fixtures/entire/recorded/entire.com/steps/compare/03-get-01M5WS0P331VQ3AARB26Z9DGV7-compare.json new file mode 100644 index 000000000..b019208a7 --- /dev/null +++ b/test/fixtures/entire/recorded/entire.com/steps/compare/03-get-01M5WS0P331VQ3AARB26Z9DGV7-compare.json @@ -0,0 +1,34 @@ +{ + "request": { + "method": "GET", + "url": "https://aws-eu-west-2.api.entire.io/api/v1/git/repos/01M5WS0P331VQ3AARB26Z9DGV7/compare?base=8127b4c88662985c819a6b3cabecde203907c3e2&head=9ec20061f17f35212247320f525ec51d3e00c41a" + }, + "response": { + "status": 200, + "headers": { + "link": "; rel=\"describedBy\"" + }, + "body": { + "$schema": "https://aws-eu-west-2.api.entire.io/api/v1/schemas/CompareResponse.json", + "files": [ + { + "path": "README.md", + "status": "modified", + "additions": 2, + "deletions": 0, + "binary": false, + "tooLarge": false + }, + { + "path": "src/greet.ts", + "status": "modified", + "additions": 3, + "deletions": 2, + "binary": false, + "tooLarge": false + } + ], + "truncated": false + } + } +} diff --git a/test/fixtures/entire/recorded/entire.com/steps/compare/golden.json b/test/fixtures/entire/recorded/entire.com/steps/compare/golden.json new file mode 100644 index 000000000..ef34fec3e --- /dev/null +++ b/test/fixtures/entire/recorded/entire.com/steps/compare/golden.json @@ -0,0 +1,81 @@ +{ + "base": "main", + "head": "9ec20061f17f35212247320f525ec51d3e00c41a", + "aheadBy": 2, + "behindBy": 1, + "commits": [ + { + "ref": { + "forge": "entire", + "instance": "entire.com", + "repo": { + "forge": "entire", + "instance": "entire.com", + "owner": "forges", + "name": "forges-fixtures" + }, + "sha": "9ec20061f17f35212247320f525ec51d3e00c41a" + }, + "sha": "9ec20061f17f35212247320f525ec51d3e00c41a", + "message": "docs: mention shouting", + "author": { + "name": "forges fixtures", + "email": "redacted@example.invalid", + "date": "2026-10-02T10:01:00.000Z" + }, + "committer": { + "name": "forges fixtures", + "email": "redacted@example.invalid", + "date": "2026-10-02T10:01:00.000Z" + }, + "parents": [ + "c83b64d5032ae0ee89ecbaeea7273b2291b4d2e5" + ] + }, + { + "ref": { + "forge": "entire", + "instance": "entire.com", + "repo": { + "forge": "entire", + "instance": "entire.com", + "owner": "forges", + "name": "forges-fixtures" + }, + "sha": "c83b64d5032ae0ee89ecbaeea7273b2291b4d2e5" + }, + "sha": "c83b64d5032ae0ee89ecbaeea7273b2291b4d2e5", + "message": "feat: shout greetings", + "author": { + "name": "forges fixtures", + "email": "redacted@example.invalid", + "date": "2026-10-02T10:00:00.000Z" + }, + "committer": { + "name": "forges fixtures", + "email": "redacted@example.invalid", + "date": "2026-10-02T10:00:00.000Z" + }, + "parents": [ + "8127b4c88662985c819a6b3cabecde203907c3e2" + ] + } + ], + "files": [ + { + "path": "README.md", + "status": "modified", + "statusRaw": "modified", + "additions": 2, + "deletions": 0 + }, + { + "path": "src/greet.ts", + "status": "modified", + "statusRaw": "modified", + "additions": 3, + "deletions": 2 + } + ], + "mergeBaseSha": "8127b4c88662985c819a6b3cabecde203907c3e2" +} diff --git a/test/fixtures/entire/recorded/entire.com/steps/compare/step.json b/test/fixtures/entire/recorded/entire.com/steps/compare/step.json new file mode 100644 index 000000000..ff4ae5b38 --- /dev/null +++ b/test/fixtures/entire/recorded/entire.com/steps/compare/step.json @@ -0,0 +1,7 @@ +{ + "name": "compare", + "recordedAt": "2026-10-26T19:57:23.972Z", + "needs": [ + "pull" + ] +} diff --git a/test/fixtures/entire/recorded/entire.com/steps/issue-comments/01-get-discussions-01M5WVPAJVPM8Y1B7N1EVF8ZPV.json b/test/fixtures/entire/recorded/entire.com/steps/issue-comments/01-get-discussions-01M5WVPAJVPM8Y1B7N1EVF8ZPV.json new file mode 100644 index 000000000..10287973b --- /dev/null +++ b/test/fixtures/entire/recorded/entire.com/steps/issue-comments/01-get-discussions-01M5WVPAJVPM8Y1B7N1EVF8ZPV.json @@ -0,0 +1,97 @@ +{ + "request": { + "method": "GET", + "url": "https://aws-eu-west-2.api.entire.io/api/v1/et/forges/trails/1/discussions/01M5WVPAJVPM8Y1B7N1EVF8ZPV" + }, + "response": { + "status": 200, + "headers": { + "link": "; rel=\"describedBy\"", + "etag": "\"discussion:01M5WVPAJVPM8Y1B7N1EVF8ZPV:1\"" + }, + "body": { + "$schema": "https://aws-eu-west-2.api.entire.io/api/v1/schemas/DiscussionDetailResponseBody.json", + "discussion": { + "etag": "\"discussion:01M5WVPAJVPM8Y1B7N1EVF8ZPV:1\"", + "id": "01M5WVPAJVPM8Y1B7N1EVF8ZPV", + "trail_id": "01M5WVMY3H5EDDRN67H0AXA3H0", + "title": "French first, then German.", + "kind": "discussion", + "resolved": false, + "resolved_by": null, + "resolved_by_identity": { + "kind": "unknown", + "account_id": null, + "display_name": null, + "avatar_url": null, + "handles": [] + }, + "resolved_at": null, + "created_by": "01M5WRP9RJ4GVR2PA5PCNYP1FC", + "created_by_identity": { + "kind": "account", + "account_id": "01M5WRP9RJ4GVR2PA5PCNYP1FC", + "display_name": "Daniel Roe", + "avatar_url": "https://avatars.githubusercontent.com/u/28706372?v=4", + "handles": [ + { + "provider": "github", + "handle": "danielroe", + "is_primary": true + } + ] + }, + "created_at": "2026-10-26T19:41:11.643Z", + "updated_at": "2026-10-26T19:41:11.643Z", + "last_message_at": "2026-10-26T19:41:11.643Z", + "last_message_author": "danielroe", + "message_count": 1, + "participants": [ + { + "login": "danielroe", + "actor_account_id": "01M5WRP9RJ4GVR2PA5PCNYP1FC", + "identity": { + "kind": "account", + "account_id": "01M5WRP9RJ4GVR2PA5PCNYP1FC", + "display_name": "Daniel Roe", + "avatar_url": "https://avatars.githubusercontent.com/u/28706372?v=4", + "handles": [ + { + "provider": "github", + "handle": "danielroe", + "is_primary": true + } + ] + } + } + ], + "review_comment_id": null, + "review_comment": null + }, + "messages": [ + { + "etag": "\"message:01M5WVPAKKTQ8B5ZX1HK69FDM0:1\"", + "id": "01M5WVPAKKTQ8B5ZX1HK69FDM0", + "author": "danielroe", + "identity": { + "kind": "account", + "account_id": "01M5WRP9RJ4GVR2PA5PCNYP1FC", + "display_name": "Daniel Roe", + "avatar_url": "https://avatars.githubusercontent.com/u/28706372?v=4", + "handles": [ + { + "provider": "github", + "handle": "danielroe", + "is_primary": true + } + ] + }, + "created_at": "2026-10-26T19:41:11.643Z", + "body": "French first, then German.", + "replies": [] + } + ], + "eventCursor": "1" + } + } +} diff --git a/test/fixtures/entire/recorded/entire.com/steps/issue-comments/02-get-N-discussions.json b/test/fixtures/entire/recorded/entire.com/steps/issue-comments/02-get-N-discussions.json new file mode 100644 index 000000000..82816830e --- /dev/null +++ b/test/fixtures/entire/recorded/entire.com/steps/issue-comments/02-get-N-discussions.json @@ -0,0 +1,76 @@ +{ + "request": { + "method": "GET", + "url": "https://aws-eu-west-2.api.entire.io/api/v1/et/forges/trails/1/discussions?pageSize=100" + }, + "response": { + "status": 200, + "headers": { + "link": "; rel=\"describedBy\"" + }, + "body": { + "$schema": "https://aws-eu-west-2.api.entire.io/api/v1/schemas/DiscussionsListResponseBody.json", + "items": [ + { + "etag": "\"discussion:01M5WVPAJVPM8Y1B7N1EVF8ZPV:1\"", + "id": "01M5WVPAJVPM8Y1B7N1EVF8ZPV", + "trail_id": "01M5WVMY3H5EDDRN67H0AXA3H0", + "title": "French first, then German.", + "kind": "discussion", + "resolved": false, + "resolved_by": null, + "resolved_by_identity": { + "kind": "unknown", + "account_id": null, + "display_name": null, + "avatar_url": null, + "handles": [] + }, + "resolved_at": null, + "created_by": "01M5WRP9RJ4GVR2PA5PCNYP1FC", + "created_by_identity": { + "kind": "account", + "account_id": "01M5WRP9RJ4GVR2PA5PCNYP1FC", + "display_name": "Daniel Roe", + "avatar_url": "https://avatars.githubusercontent.com/u/28706372?v=4", + "handles": [ + { + "provider": "github", + "handle": "danielroe", + "is_primary": true + } + ] + }, + "created_at": "2026-10-26T19:41:11.643Z", + "updated_at": "2026-10-26T19:41:11.643Z", + "last_message_at": "2026-10-26T19:41:11.643Z", + "last_message_author": "danielroe", + "message_count": 1, + "participants": [ + { + "login": "danielroe", + "actor_account_id": "01M5WRP9RJ4GVR2PA5PCNYP1FC", + "identity": { + "kind": "account", + "account_id": "01M5WRP9RJ4GVR2PA5PCNYP1FC", + "display_name": "Daniel Roe", + "avatar_url": "https://avatars.githubusercontent.com/u/28706372?v=4", + "handles": [ + { + "provider": "github", + "handle": "danielroe", + "is_primary": true + } + ] + } + } + ], + "review_comment_id": null, + "review_comment": null + } + ], + "nextPageToken": null, + "eventCursor": "1" + } + } +} diff --git a/test/fixtures/entire/recorded/entire.com/steps/issue-comments/golden.json b/test/fixtures/entire/recorded/entire.com/steps/issue-comments/golden.json new file mode 100644 index 000000000..ad9de9e54 --- /dev/null +++ b/test/fixtures/entire/recorded/entire.com/steps/issue-comments/golden.json @@ -0,0 +1,39 @@ +{ + "items": [ + { + "ref": { + "forge": "entire", + "instance": "entire.com", + "thread": { + "forge": "entire", + "instance": "entire.com", + "repo": { + "forge": "entire", + "instance": "entire.com", + "owner": "forges", + "name": "", + "kind": "namespace" + }, + "kind": "issue", + "number": "1" + }, + "id": "01M5WVPAKKTQ8B5ZX1HK69FDM0" + }, + "body": "French first, then German.", + "author": { + "forge": "entire", + "instance": "entire.com", + "login": "danielroe", + "id": "01M5WRP9RJ4GVR2PA5PCNYP1FC", + "name": "Daniel Roe", + "avatarUrl": "https://avatars.githubusercontent.com/u/28706372?v=4", + "isBotHint": false + }, + "createdAt": "", + "thread": { + "id": "01M5WVPAJVPM8Y1B7N1EVF8ZPV", + "resolved": false + } + } + ] +} diff --git a/test/fixtures/entire/recorded/entire.com/steps/issue-comments/step.json b/test/fixtures/entire/recorded/entire.com/steps/issue-comments/step.json new file mode 100644 index 000000000..ce2f6eb90 --- /dev/null +++ b/test/fixtures/entire/recorded/entire.com/steps/issue-comments/step.json @@ -0,0 +1,4 @@ +{ + "name": "issue comments", + "recordedAt": "2026-10-26T19:57:19.690Z" +} diff --git a/test/fixtures/entire/recorded/entire.com/steps/issue-events/01-get-N-timeline.json b/test/fixtures/entire/recorded/entire.com/steps/issue-events/01-get-N-timeline.json new file mode 100644 index 000000000..d05d67fe9 --- /dev/null +++ b/test/fixtures/entire/recorded/entire.com/steps/issue-events/01-get-N-timeline.json @@ -0,0 +1,62 @@ +{ + "request": { + "method": "GET", + "url": "https://aws-eu-west-2.api.entire.io/api/v1/et/forges/trails/1/timeline?per_page=3" + }, + "response": { + "status": 200, + "headers": { + "link": "; rel=\"describedBy\"" + }, + "body": { + "$schema": "https://aws-eu-west-2.api.entire.io/api/v1/schemas/ProjectTrailTimelineResponse.json", + "items": [ + { + "id": "trail-message-01M5WVPAKKTQ8B5ZX1HK69FDM0", + "kind": "comment", + "actor": { + "login": "danielroe", + "identity": { + "kind": "account", + "account_id": "01M5WRP9RJ4GVR2PA5PCNYP1FC", + "display_name": "Daniel Roe", + "avatar_url": "https://avatars.githubusercontent.com/u/28706372?v=4", + "handles": [ + { + "provider": "github", + "handle": "danielroe", + "is_primary": true + } + ] + } + }, + "occurred_at": "2026-10-26T19:41:11.643Z", + "comment_id": "01M5WVPAKKTQ8B5ZX1HK69FDM0", + "discussion_id": "01M5WVPAJVPM8Y1B7N1EVF8ZPV", + "is_reply": false + }, + { + "id": "trail-created-1", + "kind": "trail_created", + "actor": { + "login": "danielroe", + "identity": { + "kind": "account", + "account_id": "01M5WRP9RJ4GVR2PA5PCNYP1FC", + "display_name": "Daniel Roe", + "avatar_url": "https://avatars.githubusercontent.com/u/28706372?v=4", + "handles": [ + { + "provider": "github", + "handle": "danielroe", + "is_primary": true + } + ] + } + }, + "occurred_at": "2026-10-26T19:40:26.099Z" + } + ] + } + } +} diff --git a/test/fixtures/entire/recorded/entire.com/steps/issue-events/golden.json b/test/fixtures/entire/recorded/entire.com/steps/issue-events/golden.json new file mode 100644 index 000000000..a5f4d710e --- /dev/null +++ b/test/fixtures/entire/recorded/entire.com/steps/issue-events/golden.json @@ -0,0 +1,109 @@ +{ + "items": [ + { + "forge": "entire", + "instance": "entire.com", + "id": "trail-message-01M5WVPAKKTQ8B5ZX1HK69FDM0", + "kindRaw": "comment", + "occurredAt": "", + "actor": { + "forge": "entire", + "instance": "entire.com", + "login": "danielroe", + "id": "01M5WRP9RJ4GVR2PA5PCNYP1FC", + "name": "Daniel Roe", + "avatarUrl": "https://avatars.githubusercontent.com/u/28706372?v=4", + "isBotHint": false + }, + "repo": { + "forge": "entire", + "instance": "entire.com", + "owner": "forges", + "name": "", + "kind": "namespace" + }, + "thread": { + "forge": "entire", + "instance": "entire.com", + "repo": { + "forge": "entire", + "instance": "entire.com", + "owner": "forges", + "name": "", + "kind": "namespace" + }, + "kind": "issue", + "number": "1" + }, + "source": "poll", + "kind": "comment", + "summary": "danielroe commented", + "detail": { + "type": "comment", + "comment": { + "forge": "entire", + "instance": "entire.com", + "thread": { + "forge": "entire", + "instance": "entire.com", + "repo": { + "forge": "entire", + "instance": "entire.com", + "owner": "forges", + "name": "", + "kind": "namespace" + }, + "kind": "issue", + "number": "1" + }, + "id": "01M5WVPAKKTQ8B5ZX1HK69FDM0" + } + }, + "action": "created" + }, + { + "forge": "entire", + "instance": "entire.com", + "id": "trail-created-1", + "kindRaw": "trail_created", + "occurredAt": "", + "actor": { + "forge": "entire", + "instance": "entire.com", + "login": "danielroe", + "id": "01M5WRP9RJ4GVR2PA5PCNYP1FC", + "name": "Daniel Roe", + "avatarUrl": "https://avatars.githubusercontent.com/u/28706372?v=4", + "isBotHint": false + }, + "repo": { + "forge": "entire", + "instance": "entire.com", + "owner": "forges", + "name": "", + "kind": "namespace" + }, + "thread": { + "forge": "entire", + "instance": "entire.com", + "repo": { + "forge": "entire", + "instance": "entire.com", + "owner": "forges", + "name": "", + "kind": "namespace" + }, + "kind": "issue", + "number": "1" + }, + "source": "poll", + "kind": "state_change", + "action": "opened", + "summary": "danielroe opened the trail", + "detail": { + "type": "state_change", + "state": "open" + } + } + ] +} diff --git a/test/fixtures/entire/recorded/entire.com/steps/issue-events/step.json b/test/fixtures/entire/recorded/entire.com/steps/issue-events/step.json new file mode 100644 index 000000000..a493b2a45 --- /dev/null +++ b/test/fixtures/entire/recorded/entire.com/steps/issue-events/step.json @@ -0,0 +1,4 @@ +{ + "name": "issue events", + "recordedAt": "2026-10-26T19:57:19.368Z" +} diff --git a/test/fixtures/entire/recorded/entire.com/steps/issue-getcomment/01-get-discussions-01M5WVPAJVPM8Y1B7N1EVF8ZPV.json b/test/fixtures/entire/recorded/entire.com/steps/issue-getcomment/01-get-discussions-01M5WVPAJVPM8Y1B7N1EVF8ZPV.json new file mode 100644 index 000000000..10287973b --- /dev/null +++ b/test/fixtures/entire/recorded/entire.com/steps/issue-getcomment/01-get-discussions-01M5WVPAJVPM8Y1B7N1EVF8ZPV.json @@ -0,0 +1,97 @@ +{ + "request": { + "method": "GET", + "url": "https://aws-eu-west-2.api.entire.io/api/v1/et/forges/trails/1/discussions/01M5WVPAJVPM8Y1B7N1EVF8ZPV" + }, + "response": { + "status": 200, + "headers": { + "link": "; rel=\"describedBy\"", + "etag": "\"discussion:01M5WVPAJVPM8Y1B7N1EVF8ZPV:1\"" + }, + "body": { + "$schema": "https://aws-eu-west-2.api.entire.io/api/v1/schemas/DiscussionDetailResponseBody.json", + "discussion": { + "etag": "\"discussion:01M5WVPAJVPM8Y1B7N1EVF8ZPV:1\"", + "id": "01M5WVPAJVPM8Y1B7N1EVF8ZPV", + "trail_id": "01M5WVMY3H5EDDRN67H0AXA3H0", + "title": "French first, then German.", + "kind": "discussion", + "resolved": false, + "resolved_by": null, + "resolved_by_identity": { + "kind": "unknown", + "account_id": null, + "display_name": null, + "avatar_url": null, + "handles": [] + }, + "resolved_at": null, + "created_by": "01M5WRP9RJ4GVR2PA5PCNYP1FC", + "created_by_identity": { + "kind": "account", + "account_id": "01M5WRP9RJ4GVR2PA5PCNYP1FC", + "display_name": "Daniel Roe", + "avatar_url": "https://avatars.githubusercontent.com/u/28706372?v=4", + "handles": [ + { + "provider": "github", + "handle": "danielroe", + "is_primary": true + } + ] + }, + "created_at": "2026-10-26T19:41:11.643Z", + "updated_at": "2026-10-26T19:41:11.643Z", + "last_message_at": "2026-10-26T19:41:11.643Z", + "last_message_author": "danielroe", + "message_count": 1, + "participants": [ + { + "login": "danielroe", + "actor_account_id": "01M5WRP9RJ4GVR2PA5PCNYP1FC", + "identity": { + "kind": "account", + "account_id": "01M5WRP9RJ4GVR2PA5PCNYP1FC", + "display_name": "Daniel Roe", + "avatar_url": "https://avatars.githubusercontent.com/u/28706372?v=4", + "handles": [ + { + "provider": "github", + "handle": "danielroe", + "is_primary": true + } + ] + } + } + ], + "review_comment_id": null, + "review_comment": null + }, + "messages": [ + { + "etag": "\"message:01M5WVPAKKTQ8B5ZX1HK69FDM0:1\"", + "id": "01M5WVPAKKTQ8B5ZX1HK69FDM0", + "author": "danielroe", + "identity": { + "kind": "account", + "account_id": "01M5WRP9RJ4GVR2PA5PCNYP1FC", + "display_name": "Daniel Roe", + "avatar_url": "https://avatars.githubusercontent.com/u/28706372?v=4", + "handles": [ + { + "provider": "github", + "handle": "danielroe", + "is_primary": true + } + ] + }, + "created_at": "2026-10-26T19:41:11.643Z", + "body": "French first, then German.", + "replies": [] + } + ], + "eventCursor": "1" + } + } +} diff --git a/test/fixtures/entire/recorded/entire.com/steps/issue-getcomment/02-get-N-discussions.json b/test/fixtures/entire/recorded/entire.com/steps/issue-getcomment/02-get-N-discussions.json new file mode 100644 index 000000000..82816830e --- /dev/null +++ b/test/fixtures/entire/recorded/entire.com/steps/issue-getcomment/02-get-N-discussions.json @@ -0,0 +1,76 @@ +{ + "request": { + "method": "GET", + "url": "https://aws-eu-west-2.api.entire.io/api/v1/et/forges/trails/1/discussions?pageSize=100" + }, + "response": { + "status": 200, + "headers": { + "link": "; rel=\"describedBy\"" + }, + "body": { + "$schema": "https://aws-eu-west-2.api.entire.io/api/v1/schemas/DiscussionsListResponseBody.json", + "items": [ + { + "etag": "\"discussion:01M5WVPAJVPM8Y1B7N1EVF8ZPV:1\"", + "id": "01M5WVPAJVPM8Y1B7N1EVF8ZPV", + "trail_id": "01M5WVMY3H5EDDRN67H0AXA3H0", + "title": "French first, then German.", + "kind": "discussion", + "resolved": false, + "resolved_by": null, + "resolved_by_identity": { + "kind": "unknown", + "account_id": null, + "display_name": null, + "avatar_url": null, + "handles": [] + }, + "resolved_at": null, + "created_by": "01M5WRP9RJ4GVR2PA5PCNYP1FC", + "created_by_identity": { + "kind": "account", + "account_id": "01M5WRP9RJ4GVR2PA5PCNYP1FC", + "display_name": "Daniel Roe", + "avatar_url": "https://avatars.githubusercontent.com/u/28706372?v=4", + "handles": [ + { + "provider": "github", + "handle": "danielroe", + "is_primary": true + } + ] + }, + "created_at": "2026-10-26T19:41:11.643Z", + "updated_at": "2026-10-26T19:41:11.643Z", + "last_message_at": "2026-10-26T19:41:11.643Z", + "last_message_author": "danielroe", + "message_count": 1, + "participants": [ + { + "login": "danielroe", + "actor_account_id": "01M5WRP9RJ4GVR2PA5PCNYP1FC", + "identity": { + "kind": "account", + "account_id": "01M5WRP9RJ4GVR2PA5PCNYP1FC", + "display_name": "Daniel Roe", + "avatar_url": "https://avatars.githubusercontent.com/u/28706372?v=4", + "handles": [ + { + "provider": "github", + "handle": "danielroe", + "is_primary": true + } + ] + } + } + ], + "review_comment_id": null, + "review_comment": null + } + ], + "nextPageToken": null, + "eventCursor": "1" + } + } +} diff --git a/test/fixtures/entire/recorded/entire.com/steps/issue-getcomment/golden.json b/test/fixtures/entire/recorded/entire.com/steps/issue-getcomment/golden.json new file mode 100644 index 000000000..101f064a4 --- /dev/null +++ b/test/fixtures/entire/recorded/entire.com/steps/issue-getcomment/golden.json @@ -0,0 +1,35 @@ +{ + "ref": { + "forge": "entire", + "instance": "entire.com", + "thread": { + "forge": "entire", + "instance": "entire.com", + "repo": { + "forge": "entire", + "instance": "entire.com", + "owner": "forges", + "name": "", + "kind": "namespace" + }, + "kind": "issue", + "number": "1" + }, + "id": "01M5WVPAKKTQ8B5ZX1HK69FDM0" + }, + "body": "French first, then German.", + "author": { + "forge": "entire", + "instance": "entire.com", + "login": "danielroe", + "id": "01M5WRP9RJ4GVR2PA5PCNYP1FC", + "name": "Daniel Roe", + "avatarUrl": "https://avatars.githubusercontent.com/u/28706372?v=4", + "isBotHint": false + }, + "createdAt": "", + "thread": { + "id": "01M5WVPAJVPM8Y1B7N1EVF8ZPV", + "resolved": false + } +} diff --git a/test/fixtures/entire/recorded/entire.com/steps/issue-getcomment/step.json b/test/fixtures/entire/recorded/entire.com/steps/issue-getcomment/step.json new file mode 100644 index 000000000..5af624216 --- /dev/null +++ b/test/fixtures/entire/recorded/entire.com/steps/issue-getcomment/step.json @@ -0,0 +1,7 @@ +{ + "name": "issue getComment", + "recordedAt": "2026-10-26T19:57:20.213Z", + "needs": [ + "issue comments" + ] +} diff --git a/test/fixtures/entire/recorded/entire.com/steps/issue-getmany/01-get-trails-N.json b/test/fixtures/entire/recorded/entire.com/steps/issue-getmany/01-get-trails-N.json new file mode 100644 index 000000000..456d17d80 --- /dev/null +++ b/test/fixtures/entire/recorded/entire.com/steps/issue-getmany/01-get-trails-N.json @@ -0,0 +1,157 @@ +{ + "request": { + "method": "GET", + "url": "https://aws-eu-west-2.api.entire.io/api/v1/et/forges/trails/1" + }, + "response": { + "status": 200, + "headers": { + "link": "; rel=\"describedBy\"", + "etag": "W/\"2026-10-26T19:40:26.099783Z\"" + }, + "body": { + "$schema": "https://aws-eu-west-2.api.entire.io/api/v1/schemas/TrailResponse.json", + "capabilities": { + "canEdit": true, + "canManageScope": true + }, + "project": { + "primaryProcessingCell": "aws-eu-west-2", + "id": "01M5WS0JJNP4V9AW20MZ3MKF5M", + "name": "forges", + "provider": "entire", + "reference": { + "forge": "et", + "project": "forges" + }, + "jurisdiction": "uk", + "capabilities": { + "canManageTrails": true + } + }, + "author": { + "accountId": "01M5WRP9RJ4GVR2PA5PCNYP1FC", + "login": "danielroe", + "displayName": "Daniel Roe", + "avatarUrl": "https://avatars.githubusercontent.com/u/28706372?v=4", + "identity": { + "kind": "account", + "account_id": "01M5WRP9RJ4GVR2PA5PCNYP1FC", + "display_name": "Daniel Roe", + "avatar_url": "https://avatars.githubusercontent.com/u/28706372?v=4", + "handles": [ + { + "provider": "github", + "handle": "danielroe", + "is_primary": true + } + ] + } + }, + "assigneeProfiles": [ + { + "accountId": "01M5WRP9RJ4GVR2PA5PCNYP1FC", + "login": "danielroe", + "displayName": "Daniel Roe", + "avatarUrl": "https://avatars.githubusercontent.com/u/28706372?v=4", + "identity": { + "kind": "account", + "account_id": "01M5WRP9RJ4GVR2PA5PCNYP1FC", + "display_name": "Daniel Roe", + "avatar_url": "https://avatars.githubusercontent.com/u/28706372?v=4", + "handles": [ + { + "provider": "github", + "handle": "danielroe", + "is_primary": true + } + ] + } + } + ], + "id": "01M5WVMY3H5EDDRN67H0AXA3H0", + "projectId": "01M5WS0JJNP4V9AW20MZ3MKF5M", + "number": 1, + "url": "https://entire.com/et/forges/-/trails/1", + "title": "Greet in other languages", + "body": "It would be nice to greet people in their own language.\n\n- [ ] French\n- [ ] German", + "bodyDocument": { + "id": "", + "document_key": "project-trail:01M5WVMY3H5EDDRN67H0AXA3H0:body", + "schema_version": 1, + "content_json": { + "type": "doc", + "content": [ + { + "type": "paragraph", + "content": [ + { + "type": "text", + "text": "It would be nice to greet people in their own language." + } + ] + }, + { + "type": "bulletList", + "content": [ + { + "type": "listItem", + "content": [ + { + "type": "paragraph", + "content": [ + { + "type": "text", + "text": "[ ] French" + } + ] + } + ] + }, + { + "type": "listItem", + "content": [ + { + "type": "paragraph", + "content": [ + { + "type": "text", + "text": "[ ] German" + } + ] + } + ] + } + ] + } + ] + }, + "text_snapshot": "It would be nice to greet people in their own language.\n[ ] French\n[ ] German", + "updated_at": "2026-10-26T19:40:26.099Z", + "etag": "" + }, + "status": "open", + "phase": "planning", + "metadata": {}, + "type": "feature", + "priority": "low", + "assignees": [ + "ulid:01M5WRP9RJ4GVR2PA5PCNYP1FC" + ], + "assigneeAccountIds": [ + "01M5WRP9RJ4GVR2PA5PCNYP1FC" + ], + "repoIds": [ + "01M5WS0P331VQ3AARB26Z9DGV7" + ], + "authorAccountId": "01M5WRP9RJ4GVR2PA5PCNYP1FC", + "createdAt": "2026-10-26T19:40:26.099Z", + "metadataUpdatedAt": "2026-10-26T19:40:26.099Z", + "closedAt": null, + "lastVisitedAt": null, + "lastActivityAt": "2026-10-26T19:41:11.643Z", + "changes": [], + "isPossiblyPartial": true + } + } +} diff --git a/test/fixtures/entire/recorded/entire.com/steps/issue-getmany/golden.json b/test/fixtures/entire/recorded/entire.com/steps/issue-getmany/golden.json new file mode 100644 index 000000000..ce7ed5162 --- /dev/null +++ b/test/fixtures/entire/recorded/entire.com/steps/issue-getmany/golden.json @@ -0,0 +1,70 @@ +[ + { + "ok": true, + "ref": { + "forge": "entire", + "instance": "entire.com", + "repo": { + "forge": "entire", + "instance": "entire.com", + "owner": "forges", + "name": "", + "kind": "namespace" + }, + "kind": "issue", + "number": "1" + }, + "thread": { + "ref": { + "forge": "entire", + "instance": "entire.com", + "repo": { + "forge": "entire", + "instance": "entire.com", + "owner": "forges", + "name": "", + "kind": "namespace" + }, + "kind": "issue", + "number": "1", + "externalId": "01M5WVMY3H5EDDRN67H0AXA3H0" + }, + "kind": "issue", + "title": "Greet in other languages", + "body": "It would be nice to greet people in their own language.\n\n- [ ] French\n- [ ] German", + "state": "open", + "stateRaw": "open", + "isDraft": false, + "author": { + "forge": "entire", + "instance": "entire.com", + "login": "danielroe", + "id": "01M5WRP9RJ4GVR2PA5PCNYP1FC", + "name": "Daniel Roe", + "avatarUrl": "https://avatars.githubusercontent.com/u/28706372?v=4", + "isBotHint": false + }, + "assignees": [ + { + "forge": "entire", + "instance": "entire.com", + "login": "danielroe", + "id": "01M5WRP9RJ4GVR2PA5PCNYP1FC", + "name": "Daniel Roe", + "avatarUrl": "https://avatars.githubusercontent.com/u/28706372?v=4", + "isBotHint": false + } + ], + "reviewers": [], + "labels": [], + "url": "https://entire.com/et/forges/-/trails/1", + "createdAt": "", + "updatedAt": "", + "lastActivityAt": "", + "issueType": { + "id": "feature", + "name": "feature" + } + } + } +] diff --git a/test/fixtures/entire/recorded/entire.com/steps/issue-getmany/step.json b/test/fixtures/entire/recorded/entire.com/steps/issue-getmany/step.json new file mode 100644 index 000000000..85ab1dfbc --- /dev/null +++ b/test/fixtures/entire/recorded/entire.com/steps/issue-getmany/step.json @@ -0,0 +1,4 @@ +{ + "name": "issue getMany", + "recordedAt": "2026-10-26T19:57:18.977Z" +} diff --git a/test/fixtures/entire/recorded/entire.com/steps/issue-list/01-get-v1-trails.json b/test/fixtures/entire/recorded/entire.com/steps/issue-list/01-get-v1-trails.json new file mode 100644 index 000000000..063355f94 --- /dev/null +++ b/test/fixtures/entire/recorded/entire.com/steps/issue-list/01-get-v1-trails.json @@ -0,0 +1,238 @@ +{ + "request": { + "method": "GET", + "url": "https://aws-eu-west-2.api.entire.io/api/v1/trails?projectId=01M5WS0JJNP4V9AW20MZ3MKF5M&status=open&pageSize=3" + }, + "response": { + "status": 200, + "headers": { + "link": "; rel=\"describedBy\"" + }, + "body": { + "$schema": "https://aws-eu-west-2.api.entire.io/api/v1/schemas/ProjectTrailsListResponse.json", + "capabilities": { + "canManageTrails": true + }, + "items": [ + { + "capabilities": { + "canEdit": true, + "canManageScope": true + }, + "author": { + "accountId": "01M5WRP9RJ4GVR2PA5PCNYP1FC", + "login": "danielroe", + "displayName": "Daniel Roe", + "avatarUrl": "https://avatars.githubusercontent.com/u/28706372?v=4", + "identity": { + "kind": "account", + "account_id": "01M5WRP9RJ4GVR2PA5PCNYP1FC", + "display_name": "Daniel Roe", + "avatar_url": "https://avatars.githubusercontent.com/u/28706372?v=4", + "handles": [ + { + "provider": "github", + "handle": "danielroe", + "is_primary": true + } + ] + } + }, + "id": "01M5WVNFY1D7AHX0KJW2ANZP14", + "projectId": "01M5WS0JJNP4V9AW20MZ3MKF5M", + "number": 2, + "title": "Shout greetings", + "body": "Adds a `shout` option to `greet()`.", + "status": "open", + "phase": "building", + "metadata": {}, + "type": "feature", + "priority": "medium", + "assignees": [], + "assigneeAccountIds": [], + "repoIds": [ + "01M5WS0P331VQ3AARB26Z9DGV7" + ], + "authorAccountId": "01M5WRP9RJ4GVR2PA5PCNYP1FC", + "createdAt": "2026-10-26T19:40:44.349Z", + "metadataUpdatedAt": "2026-10-26T19:40:44.561Z", + "closedAt": null, + "lastVisitedAt": null, + "lastActivityAt": "2026-10-26T19:42:13.290Z", + "isPossiblyPartial": true, + "groupKey": "", + "readiness": "in_review", + "changes": [ + { + "id": "01M5WVNG0FK8S3JBBFYZGK1VFD", + "repositoryId": "01M5WS0P331VQ3AARB26Z9DGV7", + "repository": "forges-fixtures", + "branch": "feature/shout", + "originalBranch": "feature/shout", + "base": "main", + "number": 1, + "title": "feat: shout greetings", + "status": "open", + "hasCodeChanges": true, + "createdAt": "2026-10-26T19:40:44.349Z", + "updatedAt": "2026-10-26T19:42:13.290Z", + "lastActivityAt": "2026-10-26T19:42:13.290Z", + "readiness": "in_review", + "mergeability": { + "conflict_status": "unknown", + "head_sha": "", + "refreshed_at": null, + "forge_merge_block": null + } + } + ] + }, + { + "capabilities": { + "canEdit": true, + "canManageScope": true + }, + "author": { + "accountId": "01M5WRP9RJ4GVR2PA5PCNYP1FC", + "login": "danielroe", + "displayName": "Daniel Roe", + "avatarUrl": "https://avatars.githubusercontent.com/u/28706372?v=4", + "identity": { + "kind": "account", + "account_id": "01M5WRP9RJ4GVR2PA5PCNYP1FC", + "display_name": "Daniel Roe", + "avatar_url": "https://avatars.githubusercontent.com/u/28706372?v=4", + "handles": [ + { + "provider": "github", + "handle": "danielroe", + "is_primary": true + } + ] + } + }, + "id": "01M5WVNH9VCQPGCDV2QJVA6K0Y", + "projectId": "01M5WS0JJNP4V9AW20MZ3MKF5M", + "number": 3, + "title": "Say what forges is", + "body": "", + "status": "open", + "phase": "complete", + "metadata": {}, + "type": "task", + "priority": "none", + "assignees": [], + "assigneeAccountIds": [], + "repoIds": [ + "01M5WS0P331VQ3AARB26Z9DGV7" + ], + "authorAccountId": "01M5WRP9RJ4GVR2PA5PCNYP1FC", + "createdAt": "2026-10-26T19:40:45.752Z", + "metadataUpdatedAt": "2026-10-26T19:40:45.813Z", + "closedAt": null, + "lastVisitedAt": null, + "lastActivityAt": "2026-10-26T19:41:42.414Z", + "isPossiblyPartial": true, + "groupKey": "", + "readiness": "none", + "changes": [] + }, + { + "capabilities": { + "canEdit": true, + "canManageScope": true + }, + "author": { + "accountId": "01M5WRP9RJ4GVR2PA5PCNYP1FC", + "login": "danielroe", + "displayName": "Daniel Roe", + "avatarUrl": "https://avatars.githubusercontent.com/u/28706372?v=4", + "identity": { + "kind": "account", + "account_id": "01M5WRP9RJ4GVR2PA5PCNYP1FC", + "display_name": "Daniel Roe", + "avatar_url": "https://avatars.githubusercontent.com/u/28706372?v=4", + "handles": [ + { + "provider": "github", + "handle": "danielroe", + "is_primary": true + } + ] + } + }, + "assigneeProfiles": [ + { + "accountId": "01M5WRP9RJ4GVR2PA5PCNYP1FC", + "login": "danielroe", + "displayName": "Daniel Roe", + "avatarUrl": "https://avatars.githubusercontent.com/u/28706372?v=4", + "identity": { + "kind": "account", + "account_id": "01M5WRP9RJ4GVR2PA5PCNYP1FC", + "display_name": "Daniel Roe", + "avatar_url": "https://avatars.githubusercontent.com/u/28706372?v=4", + "handles": [ + { + "provider": "github", + "handle": "danielroe", + "is_primary": true + } + ] + } + } + ], + "id": "01M5WVMY3H5EDDRN67H0AXA3H0", + "projectId": "01M5WS0JJNP4V9AW20MZ3MKF5M", + "number": 1, + "title": "Greet in other languages", + "body": "It would be nice to greet people in their own language.\n\n- [ ] French\n- [ ] German", + "status": "open", + "phase": "planning", + "metadata": {}, + "type": "feature", + "priority": "low", + "assignees": [ + "ulid:01M5WRP9RJ4GVR2PA5PCNYP1FC" + ], + "assigneeAccountIds": [ + "01M5WRP9RJ4GVR2PA5PCNYP1FC" + ], + "repoIds": [ + "01M5WS0P331VQ3AARB26Z9DGV7" + ], + "authorAccountId": "01M5WRP9RJ4GVR2PA5PCNYP1FC", + "createdAt": "2026-10-26T19:40:26.099Z", + "metadataUpdatedAt": "2026-10-26T19:40:26.099Z", + "closedAt": null, + "lastVisitedAt": null, + "lastActivityAt": "2026-10-26T19:41:11.643Z", + "isPossiblyPartial": true, + "groupKey": "", + "readiness": "none", + "changes": [] + } + ], + "groups": [ + { + "rank": 0, + "key": "", + "label": "All trails", + "totalCount": 3, + "itemCount": 3 + } + ], + "groupTotals": [ + { + "rank": 0, + "key": "", + "label": "All trails", + "totalCount": 3 + } + ], + "groupBy": "none", + "jurisdiction": "uk", + "nextPageToken": null + } + } +} diff --git a/test/fixtures/entire/recorded/entire.com/steps/issue-list/golden.json b/test/fixtures/entire/recorded/entire.com/steps/issue-list/golden.json new file mode 100644 index 000000000..f5cefbda1 --- /dev/null +++ b/test/fixtures/entire/recorded/entire.com/steps/issue-list/golden.json @@ -0,0 +1,136 @@ +{ + "items": [ + { + "ref": { + "forge": "entire", + "instance": "entire.com", + "repo": { + "forge": "entire", + "instance": "entire.com", + "owner": "forges", + "name": "", + "kind": "namespace" + }, + "kind": "issue", + "number": "2", + "externalId": "01M5WVNFY1D7AHX0KJW2ANZP14" + }, + "kind": "issue", + "title": "Shout greetings", + "body": "Adds a `shout` option to `greet()`.", + "state": "open", + "stateRaw": "open", + "isDraft": false, + "author": { + "forge": "entire", + "instance": "entire.com", + "login": "danielroe", + "id": "01M5WRP9RJ4GVR2PA5PCNYP1FC", + "name": "Daniel Roe", + "avatarUrl": "https://avatars.githubusercontent.com/u/28706372?v=4", + "isBotHint": false + }, + "assignees": [], + "reviewers": [], + "labels": [], + "createdAt": "", + "updatedAt": "", + "lastActivityAt": "", + "issueType": { + "id": "feature", + "name": "feature" + } + }, + { + "ref": { + "forge": "entire", + "instance": "entire.com", + "repo": { + "forge": "entire", + "instance": "entire.com", + "owner": "forges", + "name": "", + "kind": "namespace" + }, + "kind": "issue", + "number": "3", + "externalId": "01M5WVNH9VCQPGCDV2QJVA6K0Y" + }, + "kind": "issue", + "title": "Say what forges is", + "state": "open", + "stateRaw": "open", + "isDraft": false, + "author": { + "forge": "entire", + "instance": "entire.com", + "login": "danielroe", + "id": "01M5WRP9RJ4GVR2PA5PCNYP1FC", + "name": "Daniel Roe", + "avatarUrl": "https://avatars.githubusercontent.com/u/28706372?v=4", + "isBotHint": false + }, + "assignees": [], + "reviewers": [], + "labels": [], + "createdAt": "", + "updatedAt": "", + "lastActivityAt": "", + "issueType": { + "id": "task", + "name": "task" + } + }, + { + "ref": { + "forge": "entire", + "instance": "entire.com", + "repo": { + "forge": "entire", + "instance": "entire.com", + "owner": "forges", + "name": "", + "kind": "namespace" + }, + "kind": "issue", + "number": "1", + "externalId": "01M5WVMY3H5EDDRN67H0AXA3H0" + }, + "kind": "issue", + "title": "Greet in other languages", + "body": "It would be nice to greet people in their own language.\n\n- [ ] French\n- [ ] German", + "state": "open", + "stateRaw": "open", + "isDraft": false, + "author": { + "forge": "entire", + "instance": "entire.com", + "login": "danielroe", + "id": "01M5WRP9RJ4GVR2PA5PCNYP1FC", + "name": "Daniel Roe", + "avatarUrl": "https://avatars.githubusercontent.com/u/28706372?v=4", + "isBotHint": false + }, + "assignees": [ + { + "forge": "entire", + "instance": "entire.com", + "login": "danielroe", + "id": "01M5WRP9RJ4GVR2PA5PCNYP1FC", + "name": "Daniel Roe", + "avatarUrl": "https://avatars.githubusercontent.com/u/28706372?v=4", + "isBotHint": false + } + ], + "reviewers": [], + "labels": [], + "createdAt": "", + "updatedAt": "", + "lastActivityAt": "", + "issueType": { + "id": "feature", + "name": "feature" + } + } + ] +} diff --git a/test/fixtures/entire/recorded/entire.com/steps/issue-list/step.json b/test/fixtures/entire/recorded/entire.com/steps/issue-list/step.json new file mode 100644 index 000000000..3a320e9b9 --- /dev/null +++ b/test/fixtures/entire/recorded/entire.com/steps/issue-list/step.json @@ -0,0 +1,4 @@ +{ + "name": "issue list", + "recordedAt": "2026-10-26T19:57:18.761Z" +} diff --git a/test/fixtures/entire/recorded/entire.com/steps/issue/01-get-trails-N.json b/test/fixtures/entire/recorded/entire.com/steps/issue/01-get-trails-N.json new file mode 100644 index 000000000..456d17d80 --- /dev/null +++ b/test/fixtures/entire/recorded/entire.com/steps/issue/01-get-trails-N.json @@ -0,0 +1,157 @@ +{ + "request": { + "method": "GET", + "url": "https://aws-eu-west-2.api.entire.io/api/v1/et/forges/trails/1" + }, + "response": { + "status": 200, + "headers": { + "link": "; rel=\"describedBy\"", + "etag": "W/\"2026-10-26T19:40:26.099783Z\"" + }, + "body": { + "$schema": "https://aws-eu-west-2.api.entire.io/api/v1/schemas/TrailResponse.json", + "capabilities": { + "canEdit": true, + "canManageScope": true + }, + "project": { + "primaryProcessingCell": "aws-eu-west-2", + "id": "01M5WS0JJNP4V9AW20MZ3MKF5M", + "name": "forges", + "provider": "entire", + "reference": { + "forge": "et", + "project": "forges" + }, + "jurisdiction": "uk", + "capabilities": { + "canManageTrails": true + } + }, + "author": { + "accountId": "01M5WRP9RJ4GVR2PA5PCNYP1FC", + "login": "danielroe", + "displayName": "Daniel Roe", + "avatarUrl": "https://avatars.githubusercontent.com/u/28706372?v=4", + "identity": { + "kind": "account", + "account_id": "01M5WRP9RJ4GVR2PA5PCNYP1FC", + "display_name": "Daniel Roe", + "avatar_url": "https://avatars.githubusercontent.com/u/28706372?v=4", + "handles": [ + { + "provider": "github", + "handle": "danielroe", + "is_primary": true + } + ] + } + }, + "assigneeProfiles": [ + { + "accountId": "01M5WRP9RJ4GVR2PA5PCNYP1FC", + "login": "danielroe", + "displayName": "Daniel Roe", + "avatarUrl": "https://avatars.githubusercontent.com/u/28706372?v=4", + "identity": { + "kind": "account", + "account_id": "01M5WRP9RJ4GVR2PA5PCNYP1FC", + "display_name": "Daniel Roe", + "avatar_url": "https://avatars.githubusercontent.com/u/28706372?v=4", + "handles": [ + { + "provider": "github", + "handle": "danielroe", + "is_primary": true + } + ] + } + } + ], + "id": "01M5WVMY3H5EDDRN67H0AXA3H0", + "projectId": "01M5WS0JJNP4V9AW20MZ3MKF5M", + "number": 1, + "url": "https://entire.com/et/forges/-/trails/1", + "title": "Greet in other languages", + "body": "It would be nice to greet people in their own language.\n\n- [ ] French\n- [ ] German", + "bodyDocument": { + "id": "", + "document_key": "project-trail:01M5WVMY3H5EDDRN67H0AXA3H0:body", + "schema_version": 1, + "content_json": { + "type": "doc", + "content": [ + { + "type": "paragraph", + "content": [ + { + "type": "text", + "text": "It would be nice to greet people in their own language." + } + ] + }, + { + "type": "bulletList", + "content": [ + { + "type": "listItem", + "content": [ + { + "type": "paragraph", + "content": [ + { + "type": "text", + "text": "[ ] French" + } + ] + } + ] + }, + { + "type": "listItem", + "content": [ + { + "type": "paragraph", + "content": [ + { + "type": "text", + "text": "[ ] German" + } + ] + } + ] + } + ] + } + ] + }, + "text_snapshot": "It would be nice to greet people in their own language.\n[ ] French\n[ ] German", + "updated_at": "2026-10-26T19:40:26.099Z", + "etag": "" + }, + "status": "open", + "phase": "planning", + "metadata": {}, + "type": "feature", + "priority": "low", + "assignees": [ + "ulid:01M5WRP9RJ4GVR2PA5PCNYP1FC" + ], + "assigneeAccountIds": [ + "01M5WRP9RJ4GVR2PA5PCNYP1FC" + ], + "repoIds": [ + "01M5WS0P331VQ3AARB26Z9DGV7" + ], + "authorAccountId": "01M5WRP9RJ4GVR2PA5PCNYP1FC", + "createdAt": "2026-10-26T19:40:26.099Z", + "metadataUpdatedAt": "2026-10-26T19:40:26.099Z", + "closedAt": null, + "lastVisitedAt": null, + "lastActivityAt": "2026-10-26T19:41:11.643Z", + "changes": [], + "isPossiblyPartial": true + } + } +} diff --git a/test/fixtures/entire/recorded/entire.com/steps/issue/02-get-et-forges.json b/test/fixtures/entire/recorded/entire.com/steps/issue/02-get-et-forges.json new file mode 100644 index 000000000..860a633ec --- /dev/null +++ b/test/fixtures/entire/recorded/entire.com/steps/issue/02-get-et-forges.json @@ -0,0 +1,38 @@ +{ + "request": { + "method": "GET", + "url": "https://us.console.entire.io/api/v1/projects/resolve/et/forges" + }, + "response": { + "status": 200, + "headers": { + "link": "; rel=\"describedBy\"" + }, + "body": { + "$schema": "https://us.console.entire.io/api/v1/schemas/ResolveProjectOutputBody.json", + "project": { + "id": "01M5WS0JJNP4V9AW20MZ3MKF5M", + "name": "forges", + "ownerType": "account", + "ownerId": "01M5WRP9RJ4GVR2PA5PCNYP1FC", + "ownerName": "github:danielroe", + "region": "uk", + "createdAt": "2026-10-26T18:54:22.183414Z", + "capabilities": { + "canDelete": true, + "canManageAccess": true, + "canCreateRepository": true, + "canManageTrails": true, + "canManagePlugins": true, + "canManageAgents": true + }, + "primaryProcessingCell": "aws-eu-west-2", + "apiUrl": "https://aws-eu-west-2.api.entire.io" + }, + "reference": { + "host": "et", + "project": "forges" + } + } + } +} diff --git a/test/fixtures/entire/recorded/entire.com/steps/issue/golden.json b/test/fixtures/entire/recorded/entire.com/steps/issue/golden.json new file mode 100644 index 000000000..4256a8804 --- /dev/null +++ b/test/fixtures/entire/recorded/entire.com/steps/issue/golden.json @@ -0,0 +1,52 @@ +{ + "ref": { + "forge": "entire", + "instance": "entire.com", + "repo": { + "forge": "entire", + "instance": "entire.com", + "owner": "forges", + "name": "", + "kind": "namespace" + }, + "kind": "issue", + "number": "1", + "externalId": "01M5WVMY3H5EDDRN67H0AXA3H0" + }, + "kind": "issue", + "title": "Greet in other languages", + "body": "It would be nice to greet people in their own language.\n\n- [ ] French\n- [ ] German", + "state": "open", + "stateRaw": "open", + "isDraft": false, + "author": { + "forge": "entire", + "instance": "entire.com", + "login": "danielroe", + "id": "01M5WRP9RJ4GVR2PA5PCNYP1FC", + "name": "Daniel Roe", + "avatarUrl": "https://avatars.githubusercontent.com/u/28706372?v=4", + "isBotHint": false + }, + "assignees": [ + { + "forge": "entire", + "instance": "entire.com", + "login": "danielroe", + "id": "01M5WRP9RJ4GVR2PA5PCNYP1FC", + "name": "Daniel Roe", + "avatarUrl": "https://avatars.githubusercontent.com/u/28706372?v=4", + "isBotHint": false + } + ], + "reviewers": [], + "labels": [], + "url": "https://entire.com/et/forges/-/trails/1", + "createdAt": "2026-10-26T19:40:26.099Z", + "updatedAt": "2026-10-26T19:40:26.099Z", + "lastActivityAt": "2026-10-26T19:41:11.643Z", + "issueType": { + "id": "feature", + "name": "feature" + } +} diff --git a/test/fixtures/entire/recorded/entire.com/steps/issue/step.json b/test/fixtures/entire/recorded/entire.com/steps/issue/step.json new file mode 100644 index 000000000..daf6bd80a --- /dev/null +++ b/test/fixtures/entire/recorded/entire.com/steps/issue/step.json @@ -0,0 +1,7 @@ +{ + "name": "issue", + "recordedAt": "2026-10-26T21:02:33.232Z", + "needs": [ + "pull" + ] +} diff --git a/test/fixtures/entire/recorded/entire.com/steps/me/01-get-v1-me.json b/test/fixtures/entire/recorded/entire.com/steps/me/01-get-v1-me.json new file mode 100644 index 000000000..e8c185f22 --- /dev/null +++ b/test/fixtures/entire/recorded/entire.com/steps/me/01-get-v1-me.json @@ -0,0 +1,44 @@ +{ + "request": { + "method": "GET", + "url": "https://us.console.entire.io/api/v1/me" + }, + "response": { + "status": 200, + "headers": { + "link": "; rel=\"describedBy\"" + }, + "body": { + "$schema": "https://us.console.entire.io/api/v1/schemas/GetMeOutputBody.json", + "global": { + "accountId": "01M5WRP9RJ4GVR2PA5PCNYP1FC", + "handle": "danielroe", + "username": "danielroe", + "homeJurisdiction": "uk", + "createdAt": "2026-10-26T18:48:45.073805Z", + "avatarUrl": "https://avatars.githubusercontent.com/u/28706372?v=4", + "displayName": "Daniel Roe", + "handles": [ + { + "provider": "github", + "handle": "danielroe", + "providerUserId": "28706372", + "email": "redacted@example.invalid" + } + ] + }, + "regionalUnavailable": { + "error": "foreign_jurisdiction", + "jurisdiction": "uk", + "homeCoreUrl": "https://uk.auth.entire.io", + "message": "Your profile is hosted in the uk jurisdiction." + }, + "auth": { + "provider": "github", + "providerUserId": "28706372" + }, + "mode": "regional", + "jurisdiction": "us" + } + } +} diff --git a/test/fixtures/entire/recorded/entire.com/steps/me/golden.json b/test/fixtures/entire/recorded/entire.com/steps/me/golden.json new file mode 100644 index 000000000..2bced59d2 --- /dev/null +++ b/test/fixtures/entire/recorded/entire.com/steps/me/golden.json @@ -0,0 +1,10 @@ +{ + "forge": "entire", + "instance": "entire.com", + "login": "danielroe", + "id": "01M5WRP9RJ4GVR2PA5PCNYP1FC", + "name": "Daniel Roe", + "avatarUrl": "https://avatars.githubusercontent.com/u/28706372?v=4", + "isBotHint": false, + "createdAt": "2026-10-26T18:48:45.073Z" +} diff --git a/test/fixtures/entire/recorded/entire.com/steps/me/step.json b/test/fixtures/entire/recorded/entire.com/steps/me/step.json new file mode 100644 index 000000000..cfc1738da --- /dev/null +++ b/test/fixtures/entire/recorded/entire.com/steps/me/step.json @@ -0,0 +1,4 @@ +{ + "name": "me", + "recordedAt": "2026-10-26T19:57:20.718Z" +} diff --git a/test/fixtures/entire/recorded/entire.com/steps/merged-pull/01-get-trails-01M5WVNH9VCQPGCDV2QJVA6K0Y.json b/test/fixtures/entire/recorded/entire.com/steps/merged-pull/01-get-trails-01M5WVNH9VCQPGCDV2QJVA6K0Y.json new file mode 100644 index 000000000..8c6a4495e --- /dev/null +++ b/test/fixtures/entire/recorded/entire.com/steps/merged-pull/01-get-trails-01M5WVNH9VCQPGCDV2QJVA6K0Y.json @@ -0,0 +1,116 @@ +{ + "request": { + "method": "GET", + "url": "https://aws-eu-west-2.api.entire.io/api/v1/et/forges/trails/01M5WVNH9VCQPGCDV2QJVA6K0Y" + }, + "response": { + "status": 200, + "headers": { + "link": "; rel=\"describedBy\"", + "etag": "W/\"2026-10-26T19:40:45.813788Z\"" + }, + "body": { + "$schema": "https://aws-eu-west-2.api.entire.io/api/v1/schemas/TrailResponse.json", + "capabilities": { + "canEdit": true, + "canManageScope": true + }, + "project": { + "primaryProcessingCell": "aws-eu-west-2", + "id": "01M5WS0JJNP4V9AW20MZ3MKF5M", + "name": "forges", + "provider": "entire", + "reference": { + "forge": "et", + "project": "forges" + }, + "jurisdiction": "uk", + "capabilities": { + "canManageTrails": true + } + }, + "author": { + "accountId": "01M5WRP9RJ4GVR2PA5PCNYP1FC", + "login": "danielroe", + "displayName": "Daniel Roe", + "avatarUrl": "https://avatars.githubusercontent.com/u/28706372?v=4", + "identity": { + "kind": "account", + "account_id": "01M5WRP9RJ4GVR2PA5PCNYP1FC", + "display_name": "Daniel Roe", + "avatar_url": "https://avatars.githubusercontent.com/u/28706372?v=4", + "handles": [ + { + "provider": "github", + "handle": "danielroe", + "is_primary": true + } + ] + } + }, + "id": "01M5WVNH9VCQPGCDV2QJVA6K0Y", + "projectId": "01M5WS0JJNP4V9AW20MZ3MKF5M", + "number": 3, + "url": "https://entire.com/et/forges/-/trails/3", + "title": "Say what forges is", + "body": "", + "bodyDocument": { + "id": "", + "document_key": "project-trail:01M5WVNH9VCQPGCDV2QJVA6K0Y:body", + "schema_version": 1, + "content_json": { + "type": "doc", + "content": [ + { + "type": "paragraph" + } + ] + }, + "text_snapshot": "", + "updated_at": "2026-10-26T19:40:45.813Z", + "etag": "" + }, + "status": "open", + "phase": "complete", + "metadata": {}, + "type": "task", + "priority": "none", + "assignees": [], + "assigneeAccountIds": [], + "repoIds": [ + "01M5WS0P331VQ3AARB26Z9DGV7" + ], + "authorAccountId": "01M5WRP9RJ4GVR2PA5PCNYP1FC", + "createdAt": "2026-10-26T19:40:45.752Z", + "metadataUpdatedAt": "2026-10-26T19:40:45.813Z", + "closedAt": null, + "lastVisitedAt": null, + "lastActivityAt": "2026-10-26T19:41:42.414Z", + "changes": [ + { + "id": "01M5WVNHA7JVWPZP7W0SWDQKYY", + "repositoryId": "01M5WS0P331VQ3AARB26Z9DGV7", + "repository": "forges-fixtures", + "branch": "fix/typo", + "originalBranch": "fix/typo", + "base": "main", + "number": 2, + "title": "docs: say what forges is", + "status": "merged", + "hasCodeChanges": false, + "createdAt": "2026-10-26T19:40:45.752Z", + "updatedAt": "2026-10-26T19:41:42.414Z", + "lastActivityAt": "2026-10-26T19:41:42.414Z", + "deployments": { + "availability": "available", + "ready": 0, + "total": 0 + }, + "readiness": "none", + "mergeability": null + } + ], + "isPossiblyPartial": true + } + } +} diff --git a/test/fixtures/entire/recorded/entire.com/steps/merged-pull/02-get-forges-fixtures-N.json b/test/fixtures/entire/recorded/entire.com/steps/merged-pull/02-get-forges-fixtures-N.json new file mode 100644 index 000000000..62dda7129 --- /dev/null +++ b/test/fixtures/entire/recorded/entire.com/steps/merged-pull/02-get-forges-fixtures-N.json @@ -0,0 +1,286 @@ +{ + "request": { + "method": "GET", + "url": "https://aws-eu-west-2.api.entire.io/api/v1/trails/et/forges/forges-fixtures/2" + }, + "response": { + "status": 200, + "headers": { + "link": "; rel=\"describedBy\"" + }, + "body": { + "$schema": "https://aws-eu-west-2.api.entire.io/api/v1/schemas/TrailDetailResponse.json", + "id": "01M5WVNHA7JVWPZP7W0SWDQKYY", + "number": 2, + "url": "https://entire.com/et/forges/forges-fixtures/trails/2", + "title": "docs: say what forges is", + "status": "merged", + "branch": "fix/typo", + "original_branch": "fix/typo", + "base": "main", + "type": "task", + "priority": "none", + "author": { + "id": "01M5WRP9RJ4GVR2PA5PCNYP1FC", + "login": "danielroe", + "identity": { + "kind": "account", + "account_id": "01M5WRP9RJ4GVR2PA5PCNYP1FC", + "display_name": "Daniel Roe", + "avatar_url": "https://avatars.githubusercontent.com/u/28706372?v=4", + "handles": [ + { + "provider": "github", + "handle": "danielroe", + "is_primary": true + } + ] + } + }, + "assignees": [ + "danielroe" + ], + "assignee_identities": [ + { + "login": "danielroe", + "identity": { + "kind": "account", + "account_id": "01M5WRP9RJ4GVR2PA5PCNYP1FC", + "display_name": "Daniel Roe", + "avatar_url": "https://avatars.githubusercontent.com/u/28706372?v=4", + "handles": [ + { + "provider": "github", + "handle": "danielroe", + "is_primary": true + } + ] + } + } + ], + "reviewers": [ + { + "login": "danielroe", + "status": "approved", + "actor_account_id": "01M5WRP9RJ4GVR2PA5PCNYP1FC", + "identity": { + "kind": "account", + "account_id": "01M5WRP9RJ4GVR2PA5PCNYP1FC", + "display_name": "Daniel Roe", + "avatar_url": "https://avatars.githubusercontent.com/u/28706372?v=4", + "handles": [ + { + "provider": "github", + "handle": "danielroe", + "is_primary": true + } + ] + } + } + ], + "ready_for_review": false, + "has_code_changes": false, + "comment_count": 0, + "unresolved_count": 0, + "created_at": "2026-10-26T19:40:45.752Z", + "updated_at": "2026-10-26T19:41:42.414Z", + "merged_at": "2026-10-26T19:41:42.414Z", + "last_activity_at": "2026-10-26T19:41:42.414Z", + "phase": null, + "parent": { + "id": "01M5WVNH9VCQPGCDV2QJVA6K0Y", + "number": 3, + "project_id": "01M5WS0JJNP4V9AW20MZ3MKF5M", + "host": "et", + "project": "forges", + "path": "/api/v1/et/forges/trails/01M5WVNH9VCQPGCDV2QJVA6K0Y", + "jurisdiction": "uk", + "primary_processing_cell": "aws-eu-west-2", + "url": "https://entire.com/et/forges/-/trails/3" + }, + "branch_state": "unknown", + "code_changes": "not_applicable", + "lifecycle_sync": "settled", + "body_document": { + "id": "01M5WVNHBT9SNFF17Q2VTA66AJ", + "document_key": "trail:01M5WVNHA7JVWPZP7W0SWDQKYY:body", + "schema_version": 1, + "content_json": { + "type": "doc", + "content": [ + { + "type": "paragraph" + } + ] + }, + "text_snapshot": "", + "updated_at": "2026-10-26T19:40:45.752Z", + "etag": "W/\"2026-10-26T19:40:45.752733Z\"" + }, + "monitors": [], + "agents": [], + "runners": [], + "actions": { + "approve": { + "state": "unavailable", + "reason": "trail_not_open" + }, + "create_ci_pr": { + "state": "unavailable", + "reason": "trail_not_open" + }, + "merge": { + "state": "unavailable", + "reason": "trail_not_open" + }, + "merge_with_bypass": { + "state": "unavailable", + "reason": "trail_not_open" + }, + "update_branch": { + "state": "unavailable", + "reason": "trail_not_open" + }, + "restore_branch": { + "state": "unavailable", + "reason": "branch_exists" + }, + "delete_branch": { + "state": "enabled", + "reason": null + } + }, + "mergeability": { + "delete_branch_on_merge": false, + "bypass_policy": "nobody", + "mergeable": true, + "behind_by": 0, + "comparison_status": "available", + "conflict_status": "unknown", + "head_sha": "dd07002e23c86b5e68d53ebe9949e1bf5549c8ca", + "gates": [ + { + "reviewers": [ + { + "login": "danielroe", + "actor_account_id": "01M5WRP9RJ4GVR2PA5PCNYP1FC", + "state": "approved", + "reviewed_head_sha": "dd07002e23c86b5e68d53ebe9949e1bf5549c8ca", + "reason": null + } + ], + "runner_ids": [], + "id": "01M5WVPPCKAK64REFZ7Z59APSB", + "gate_definition_id": "01M5WTJP4MSACMEJ1KK4FGP2B1", + "gate_key": "approvals", + "gate_type": "approvals", + "blocking": true, + "status": "passed", + "head_sha": "dd07002e23c86b5e68d53ebe9949e1bf5549c8ca", + "value": { + "approved": 1, + "changes_requested": false, + "config": { + "version": 1, + "min_reviewers": 1, + "allow_self_approval": true, + "dismiss_stale_approvals_on_push": false + }, + "required": 1, + "self_excluded": false, + "stale_dismissed": 0, + "total": 1 + }, + "rationale": "1 approval(s) recorded", + "created_at": "2026-10-26T19:41:23.731872Z", + "completed_at": "2026-10-26T19:41:23.731872Z", + "state": "evaluated", + "outcome": "passed", + "stale_reason": null, + "evaluated_at_sha": "dd07002e23c86b5e68d53ebe9949e1bf5549c8ca", + "finding_count": null + }, + { + "reviewers": [], + "runner_ids": [], + "id": "01M5WVPXW16SZKPVENFYE9DYFK", + "gate_definition_id": "01M5WTJP5MDYCYNF3Z6BWN7NZ0", + "gate_key": "findings", + "gate_type": "findings", + "blocking": true, + "status": "passed", + "head_sha": "dd07002e23c86b5e68d53ebe9949e1bf5549c8ca", + "value": { + "config": { + "version": 1, + "agent_findings_min_severity": "high" + }, + "reviewed_head": false, + "agent_findings": { + "low": 0, + "high": 0, + "medium": 0, + "unspecified": 0 + }, + "review_in_flight": false, + "reviewer_configured": false, + "review_grace_expired": false, + "agent_blocking_findings": 0 + }, + "rationale": "No blocking findings", + "created_at": "2026-10-26T19:41:31.393501Z", + "completed_at": "2026-10-26T19:41:31.393501Z", + "state": "evaluated", + "outcome": "passed", + "stale_reason": null, + "evaluated_at_sha": "dd07002e23c86b5e68d53ebe9949e1bf5549c8ca", + "finding_count": 0 + }, + { + "reviewers": [], + "runner_ids": [], + "id": "01M5WVNHERD57DMBSKD0MMREKD", + "gate_definition_id": "01M5WTJP5QR0FQ7TWGE7Y3QCJC", + "gate_key": "up_to_date", + "gate_type": "up_to_date", + "blocking": true, + "status": "passed", + "head_sha": "dd07002e23c86b5e68d53ebe9949e1bf5549c8ca", + "value": { + "config": { + "version": 1, + "allow_behind_if_mergeable": false + }, + "behind_by": 0, + "compare_status": "ahead", + "comparison_status": "available" + }, + "rationale": "Up to date", + "created_at": "2026-10-26T19:40:45.912404Z", + "completed_at": "2026-10-26T19:40:45.912404Z", + "state": "evaluated", + "outcome": "passed", + "stale_reason": null, + "evaluated_at_sha": "dd07002e23c86b5e68d53ebe9949e1bf5549c8ca", + "finding_count": null + } + ], + "checks": { + "availability": "not_applicable", + "runs": [] + }, + "forge_merge_block": null + }, + "deployments": { + "availability": "available", + "ready": 0, + "total": 0, + "items": [] + }, + "config_source": "snapshot", + "merge_base_sha": "8127b4c88662985c819a6b3cabecde203907c3e2", + "base_sha": "8127b4c88662985c819a6b3cabecde203907c3e2", + "head_sha": "dd07002e23c86b5e68d53ebe9949e1bf5549c8ca" + } + } +} diff --git a/test/fixtures/entire/recorded/entire.com/steps/merged-pull/03-get-forges-forges-fixtures.json b/test/fixtures/entire/recorded/entire.com/steps/merged-pull/03-get-forges-forges-fixtures.json new file mode 100644 index 000000000..b18a769eb --- /dev/null +++ b/test/fixtures/entire/recorded/entire.com/steps/merged-pull/03-get-forges-forges-fixtures.json @@ -0,0 +1,108 @@ +{ + "request": { + "method": "GET", + "url": "https://aws-eu-west-2.api.entire.io/api/v1/trails/et/forges/forges-fixtures?status=merged&per_page=10" + }, + "response": { + "status": 200, + "headers": { + "link": "; rel=\"describedBy\"" + }, + "body": { + "$schema": "https://aws-eu-west-2.api.entire.io/api/v1/schemas/TrailsListResponse.json", + "items": [ + { + "id": "01M5WVNHA7JVWPZP7W0SWDQKYY", + "number": 2, + "url": "https://entire.com/et/forges/forges-fixtures/trails/2", + "title": "docs: say what forges is", + "status": "merged", + "branch": "fix/typo", + "original_branch": "fix/typo", + "base": "main", + "type": "task", + "priority": "none", + "author": { + "id": "01M5WRP9RJ4GVR2PA5PCNYP1FC", + "login": "danielroe", + "identity": { + "kind": "account", + "account_id": "01M5WRP9RJ4GVR2PA5PCNYP1FC", + "display_name": "Daniel Roe", + "avatar_url": "https://avatars.githubusercontent.com/u/28706372?v=4", + "handles": [ + { + "provider": "github", + "handle": "danielroe", + "is_primary": true + } + ] + } + }, + "assignees": [ + "danielroe" + ], + "assignee_identities": [ + { + "login": "danielroe", + "identity": { + "kind": "account", + "account_id": "01M5WRP9RJ4GVR2PA5PCNYP1FC", + "display_name": "Daniel Roe", + "avatar_url": "https://avatars.githubusercontent.com/u/28706372?v=4", + "handles": [ + { + "provider": "github", + "handle": "danielroe", + "is_primary": true + } + ] + } + } + ], + "reviewers": [ + { + "login": "danielroe", + "status": "approved", + "actor_account_id": "01M5WRP9RJ4GVR2PA5PCNYP1FC", + "identity": { + "kind": "account", + "account_id": "01M5WRP9RJ4GVR2PA5PCNYP1FC", + "display_name": "Daniel Roe", + "avatar_url": "https://avatars.githubusercontent.com/u/28706372?v=4", + "handles": [ + { + "provider": "github", + "handle": "danielroe", + "is_primary": true + } + ] + } + } + ], + "ready_for_review": false, + "has_code_changes": false, + "comment_count": 0, + "unresolved_count": 0, + "created_at": "2026-10-26T19:40:45.752Z", + "updated_at": "2026-10-26T19:41:42.414Z", + "merged_at": "2026-10-26T19:41:42.414Z", + "last_activity_at": "2026-10-26T19:41:42.414Z", + "phase": null, + "parent": { + "id": "01M5WVNH9VCQPGCDV2QJVA6K0Y", + "number": 3, + "project_id": "01M5WS0JJNP4V9AW20MZ3MKF5M", + "host": "et", + "project": "forges", + "path": "/api/v1/et/forges/trails/01M5WVNH9VCQPGCDV2QJVA6K0Y", + "jurisdiction": "uk", + "primary_processing_cell": "aws-eu-west-2", + "url": "https://entire.com/et/forges/-/trails/3" + } + } + ], + "total_count": 1 + } + } +} diff --git a/test/fixtures/entire/recorded/entire.com/steps/merged-pull/golden.json b/test/fixtures/entire/recorded/entire.com/steps/merged-pull/golden.json new file mode 100644 index 000000000..efadfaa40 --- /dev/null +++ b/test/fixtures/entire/recorded/entire.com/steps/merged-pull/golden.json @@ -0,0 +1,158 @@ +{ + "listed": { + "ref": { + "forge": "entire", + "instance": "entire.com", + "repo": { + "forge": "entire", + "instance": "entire.com", + "owner": "forges", + "name": "forges-fixtures" + }, + "kind": "pull_request", + "number": "2", + "externalId": "01M5WVNHA7JVWPZP7W0SWDQKYY" + }, + "kind": "pull_request", + "title": "docs: say what forges is", + "state": "merged", + "stateRaw": "merged", + "isDraft": true, + "author": { + "forge": "entire", + "instance": "entire.com", + "login": "danielroe", + "id": "01M5WRP9RJ4GVR2PA5PCNYP1FC", + "name": "Daniel Roe", + "avatarUrl": "https://avatars.githubusercontent.com/u/28706372?v=4", + "isBotHint": false + }, + "assignees": [ + { + "forge": "entire", + "instance": "entire.com", + "login": "danielroe", + "id": "01M5WRP9RJ4GVR2PA5PCNYP1FC", + "name": "Daniel Roe", + "avatarUrl": "https://avatars.githubusercontent.com/u/28706372?v=4", + "isBotHint": false + } + ], + "reviewers": [ + { + "actor": { + "forge": "entire", + "instance": "entire.com", + "login": "danielroe", + "id": "01M5WRP9RJ4GVR2PA5PCNYP1FC", + "name": "Daniel Roe", + "avatarUrl": "https://avatars.githubusercontent.com/u/28706372?v=4", + "isBotHint": false + }, + "state": "approved", + "stateRaw": "approved" + } + ], + "labels": [], + "url": "https://entire.com/et/forges/forges-fixtures/trails/2", + "createdAt": "2026-10-26T19:40:45.752Z", + "updatedAt": "2026-10-26T19:41:42.414Z", + "mergedAt": "2026-10-26T19:41:42.414Z", + "closedAt": "2026-10-26T19:41:42.414Z", + "lastActivityAt": "2026-10-26T19:41:42.414Z", + "commentCount": 0, + "branches": { + "head": { + "ref": "fix/typo", + "repo": { + "forge": "entire", + "instance": "entire.com", + "owner": "forges", + "name": "forges-fixtures" + } + }, + "base": { + "ref": "main" + } + } + }, + "read": { + "ref": { + "forge": "entire", + "instance": "entire.com", + "repo": { + "forge": "entire", + "instance": "entire.com", + "owner": "forges", + "name": "forges-fixtures" + }, + "kind": "pull_request", + "number": "2", + "externalId": "01M5WVNHA7JVWPZP7W0SWDQKYY" + }, + "kind": "pull_request", + "title": "docs: say what forges is", + "state": "merged", + "stateRaw": "merged", + "isDraft": true, + "author": { + "forge": "entire", + "instance": "entire.com", + "login": "danielroe", + "id": "01M5WRP9RJ4GVR2PA5PCNYP1FC", + "name": "Daniel Roe", + "avatarUrl": "https://avatars.githubusercontent.com/u/28706372?v=4", + "isBotHint": false + }, + "assignees": [ + { + "forge": "entire", + "instance": "entire.com", + "login": "danielroe", + "id": "01M5WRP9RJ4GVR2PA5PCNYP1FC", + "name": "Daniel Roe", + "avatarUrl": "https://avatars.githubusercontent.com/u/28706372?v=4", + "isBotHint": false + } + ], + "reviewers": [ + { + "actor": { + "forge": "entire", + "instance": "entire.com", + "login": "danielroe", + "id": "01M5WRP9RJ4GVR2PA5PCNYP1FC", + "name": "Daniel Roe", + "avatarUrl": "https://avatars.githubusercontent.com/u/28706372?v=4", + "isBotHint": false + }, + "state": "approved", + "stateRaw": "approved" + } + ], + "labels": [], + "url": "https://entire.com/et/forges/forges-fixtures/trails/2", + "createdAt": "2026-10-26T19:40:45.752Z", + "updatedAt": "2026-10-26T19:41:42.414Z", + "mergedAt": "2026-10-26T19:41:42.414Z", + "closedAt": "2026-10-26T19:41:42.414Z", + "lastActivityAt": "2026-10-26T19:41:42.414Z", + "commentCount": 0, + "branches": { + "head": { + "ref": "fix/typo", + "sha": "dd07002e23c86b5e68d53ebe9949e1bf5549c8ca", + "repo": { + "forge": "entire", + "instance": "entire.com", + "owner": "forges", + "name": "forges-fixtures" + } + }, + "base": { + "ref": "main", + "sha": "8127b4c88662985c819a6b3cabecde203907c3e2" + } + } + } +} diff --git a/test/fixtures/entire/recorded/entire.com/steps/merged-pull/step.json b/test/fixtures/entire/recorded/entire.com/steps/merged-pull/step.json new file mode 100644 index 000000000..a99f9242e --- /dev/null +++ b/test/fixtures/entire/recorded/entire.com/steps/merged-pull/step.json @@ -0,0 +1,4 @@ +{ + "name": "merged pull", + "recordedAt": "2026-10-26T21:02:32.217Z" +} diff --git a/test/fixtures/entire/recorded/entire.com/steps/own-repos/01-get-v1-repos.json b/test/fixtures/entire/recorded/entire.com/steps/own-repos/01-get-v1-repos.json new file mode 100644 index 000000000..713d5be2e --- /dev/null +++ b/test/fixtures/entire/recorded/entire.com/steps/own-repos/01-get-v1-repos.json @@ -0,0 +1,56 @@ +{ + "request": { + "method": "GET", + "url": "https://us.console.entire.io/api/v1/repos?pageSize=3" + }, + "response": { + "status": 200, + "headers": { + "link": "; rel=\"describedBy\"" + }, + "body": { + "$schema": "https://us.console.entire.io/api/v1/schemas/ListReposOutputBody.json", + "repos": [ + { + "id": "01M5WYSQC41P69DTXEMZ0TE5YK", + "repoGroupId": "01M5WYSQC42H6K0NWNZ6FYTSRQ", + "jurisdiction": "eu", + "cell": "aws-eu-central-1", + "clusterSlug": "aws-eu-central-1", + "name": "forges-fixtures", + "full_name": "forges-scratch/forges-fixtures", + "org": "forges-scratch", + "provider": "entire", + "visibility": "public", + "permission": "write", + "placements": [ + { + "id": "01M5WYSQC41P69DTXEMZ0TE5YK", + "jurisdiction": "eu", + "cell": "aws-eu-central-1", + "apiBaseUrl": "https://aws-eu-central-1.api.entire.io", + "clusterSlug": "aws-eu-central-1", + "mirror": false, + "status": "ready" + } + ], + "primaries": { + "git_data": "entire:01M5WYSQC41P69DTXEMZ0TE5YK", + "processing": "01M5WYSQC41P69DTXEMZ0TE5YK", + "data_primary": { + "forge": "entire", + "repo_id": "01M5WYSQC41P69DTXEMZ0TE5YK" + }, + "processing_primary": { + "forge": "entire", + "repo_id": "01M5WYSQC41P69DTXEMZ0TE5YK" + } + }, + "lastPushedAt": "2026-10-26T21:02:24.149427Z" + } + ], + "truncated": false, + "candidatesIncomplete": false + } + } +} diff --git a/test/fixtures/entire/recorded/entire.com/steps/own-repos/golden.json b/test/fixtures/entire/recorded/entire.com/steps/own-repos/golden.json new file mode 100644 index 000000000..930f26755 --- /dev/null +++ b/test/fixtures/entire/recorded/entire.com/steps/own-repos/golden.json @@ -0,0 +1,25 @@ +{ + "items": [ + { + "ref": { + "forge": "entire", + "instance": "entire.com", + "owner": "forges-scratch", + "name": "forges-fixtures", + "externalId": "01M5WYSQC41P69DTXEMZ0TE5YK" + }, + "visibility": "public", + "isFork": false, + "isArchived": false, + "topics": [], + "pushedAt": "", + "permissions": { + "admin": false, + "maintain": false, + "push": true, + "triage": true, + "pull": true + } + } + ] +} diff --git a/test/fixtures/entire/recorded/entire.com/steps/own-repos/step.json b/test/fixtures/entire/recorded/entire.com/steps/own-repos/step.json new file mode 100644 index 000000000..6fe2f18f2 --- /dev/null +++ b/test/fixtures/entire/recorded/entire.com/steps/own-repos/step.json @@ -0,0 +1,4 @@ +{ + "name": "own repos", + "recordedAt": "2026-10-26T21:02:36.097Z" +} diff --git a/test/fixtures/entire/recorded/entire.com/steps/owner-repos/01-get-01M5WS0JJNP4V9AW20MZ3MKF5M-repos.json b/test/fixtures/entire/recorded/entire.com/steps/owner-repos/01-get-01M5WS0JJNP4V9AW20MZ3MKF5M-repos.json new file mode 100644 index 000000000..a15ef5fb7 --- /dev/null +++ b/test/fixtures/entire/recorded/entire.com/steps/owner-repos/01-get-01M5WS0JJNP4V9AW20MZ3MKF5M-repos.json @@ -0,0 +1,16 @@ +{ + "request": { + "method": "GET", + "url": "https://us.console.entire.io/api/v1/projects/01M5WS0JJNP4V9AW20MZ3MKF5M/repos?pageSize=3" + }, + "response": { + "status": 200, + "headers": { + "link": "; rel=\"describedBy\"" + }, + "body": { + "$schema": "https://us.console.entire.io/api/v1/schemas/ListProjectReposOutputBody.json", + "repos": [] + } + } +} diff --git a/test/fixtures/entire/recorded/entire.com/steps/owner-repos/golden.json b/test/fixtures/entire/recorded/entire.com/steps/owner-repos/golden.json new file mode 100644 index 000000000..2feb21015 --- /dev/null +++ b/test/fixtures/entire/recorded/entire.com/steps/owner-repos/golden.json @@ -0,0 +1,3 @@ +{ + "items": [] +} diff --git a/test/fixtures/entire/recorded/entire.com/steps/owner-repos/step.json b/test/fixtures/entire/recorded/entire.com/steps/owner-repos/step.json new file mode 100644 index 000000000..0fa78203c --- /dev/null +++ b/test/fixtures/entire/recorded/entire.com/steps/owner-repos/step.json @@ -0,0 +1,4 @@ +{ + "name": "owner repos", + "recordedAt": "2026-10-26T20:01:21.788Z" +} diff --git a/test/fixtures/entire/recorded/entire.com/steps/pull-comments/01-get-N-discussions.json b/test/fixtures/entire/recorded/entire.com/steps/pull-comments/01-get-N-discussions.json new file mode 100644 index 000000000..0e3836d99 --- /dev/null +++ b/test/fixtures/entire/recorded/entire.com/steps/pull-comments/01-get-N-discussions.json @@ -0,0 +1,433 @@ +{ + "request": { + "method": "GET", + "url": "https://aws-eu-west-2.api.entire.io/api/v1/trails/et/forges/forges-fixtures/1/discussions?include_messages=true&per_page=100" + }, + "response": { + "status": 200, + "headers": { + "link": "; rel=\"describedBy\"" + }, + "body": { + "$schema": "https://aws-eu-west-2.api.entire.io/api/v1/schemas/TrailDiscussionsListResponseBody.json", + "items": [ + { + "id": "01M5WVQW2ZPDDH5X0C5SWM3KVM", + "trail_id": "01M5WVNG0FK8S3JBBFYZGK1VFD", + "title": "`toUpperCase()` ignores the locale, so Turkish names shout incorrectly. Consider `toLocaleUpperCase()`.", + "kind": "code_review", + "resolved": false, + "resolved_by": null, + "resolved_by_identity": { + "kind": "unknown", + "account_id": null, + "display_name": null, + "avatar_url": null, + "handles": [] + }, + "resolved_at": null, + "created_by": "01M5WRP9RJ4GVR2PA5PCNYP1FC", + "created_by_identity": { + "kind": "account", + "account_id": "01M5WRP9RJ4GVR2PA5PCNYP1FC", + "display_name": "Daniel Roe", + "avatar_url": "https://avatars.githubusercontent.com/u/28706372?v=4", + "handles": [ + { + "provider": "github", + "handle": "danielroe", + "is_primary": true + } + ] + }, + "created_at": "2026-10-26T19:42:02.333Z", + "updated_at": "2026-10-26T19:42:13.290Z", + "last_message_at": "2026-10-26T19:42:13.290Z", + "last_message_author": "danielroe", + "message_count": 1, + "participants": [ + { + "login": "danielroe", + "actor_account_id": "01M5WRP9RJ4GVR2PA5PCNYP1FC", + "identity": { + "kind": "account", + "account_id": "01M5WRP9RJ4GVR2PA5PCNYP1FC", + "display_name": "Daniel Roe", + "avatar_url": "https://avatars.githubusercontent.com/u/28706372?v=4", + "handles": [ + { + "provider": "github", + "handle": "danielroe", + "is_primary": true + } + ] + } + } + ], + "review_comment_id": "01M5WVQW2ZTEEA9V72FF81J46Q", + "review_comment": { + "discussion_id": "01M5WVQW2ZPDDH5X0C5SWM3KVM", + "discussion_message_count": 1, + "id": "01M5WVQW2ZTEEA9V72FF81J46Q", + "trail_id": "01M5WVNG0FK8S3JBBFYZGK1VFD", + "repo_id": "01M5WS0P331VQ3AARB26Z9DGV7", + "review_id": "01M5WVQNQSS4DQNQB5Z00WA4V7", + "code_version_id": "01M5WVQNQG83V6VQT17G0M6DBJ", + "actor_id": "01M5WRP9RJ4GVR2PA5PCNYP1FC", + "actor_display_name": "danielroe", + "actor_identity": { + "kind": "account", + "account_id": "01M5WRP9RJ4GVR2PA5PCNYP1FC", + "display_name": "Daniel Roe", + "avatar_url": "https://avatars.githubusercontent.com/u/28706372?v=4", + "handles": [ + { + "provider": "github", + "handle": "danielroe", + "is_primary": true + } + ] + }, + "body": "`toUpperCase()` ignores the locale, so Turkish names shout incorrectly. Consider `toLocaleUpperCase()`.", + "severity": "low", + "confidence": null, + "status": "open", + "status_reason": null, + "status_actor_id": null, + "status_actor_display_name": null, + "status_actor_identity": { + "kind": "unknown", + "account_id": null, + "display_name": null, + "avatar_url": null, + "handles": [] + }, + "status_changed_at": null, + "status_source": null, + "status_actor_kind": null, + "stale_outcome": "current", + "stale_checked_at": null, + "stale_checked_code_version_id": null, + "client_id": "shout-case", + "client_id_hash": "ea05e251d04f3b2e1dbf616445b14d9faba65c96f60b955c61a748fb186cd26d", + "created_at": "2026-10-26T19:42:02.333Z", + "updated_at": "2026-10-26T19:42:02.333Z", + "location": { + "id": "01M5WVQW2Z3NCP4Y284CQ5DE3Y", + "review_comment_id": "01M5WVQW2ZTEEA9V72FF81J46Q", + "code_version_id": "01M5WVQNQG83V6VQT17G0M6DBJ", + "granularity": "line", + "file_path": "src/greet.ts", + "start_line": 3, + "start_column": null, + "end_line": 3, + "end_column": null, + "selected_text": " return options.shout ? greeting.toUpperCase() : greeting", + "nearby_text": null, + "language": null + } + }, + "messages": [ + { + "id": "01M5WVR6SAXG323XBRAH7G0Q3V", + "author": "danielroe", + "identity": { + "kind": "account", + "account_id": "01M5WRP9RJ4GVR2PA5PCNYP1FC", + "display_name": "Daniel Roe", + "avatar_url": "https://avatars.githubusercontent.com/u/28706372?v=4", + "handles": [ + { + "provider": "github", + "handle": "danielroe", + "is_primary": true + } + ] + }, + "created_at": "2026-10-26T19:42:13.290Z", + "body": "Good catch, switching to `toLocaleUpperCase()`.", + "replies": [] + } + ] + }, + { + "id": "01M5WVQW42CZ9N82B1QV6B6GTP", + "trail_id": "01M5WVNG0FK8S3JBBFYZGK1VFD", + "title": "No tests cover the `shout` option.", + "kind": "code_review", + "resolved": false, + "resolved_by": null, + "resolved_by_identity": { + "kind": "unknown", + "account_id": null, + "display_name": null, + "avatar_url": null, + "handles": [] + }, + "resolved_at": null, + "created_by": "01M5WRP9RJ4GVR2PA5PCNYP1FC", + "created_by_identity": { + "kind": "account", + "account_id": "01M5WRP9RJ4GVR2PA5PCNYP1FC", + "display_name": "Daniel Roe", + "avatar_url": "https://avatars.githubusercontent.com/u/28706372?v=4", + "handles": [ + { + "provider": "github", + "handle": "danielroe", + "is_primary": true + } + ] + }, + "created_at": "2026-10-26T19:42:02.368Z", + "updated_at": "2026-10-26T19:42:02.368Z", + "last_message_at": null, + "last_message_author": null, + "message_count": 0, + "participants": [], + "review_comment_id": "01M5WVQW423TPZGYYS4025JBCT", + "review_comment": { + "discussion_id": "01M5WVQW42CZ9N82B1QV6B6GTP", + "discussion_message_count": 0, + "id": "01M5WVQW423TPZGYYS4025JBCT", + "trail_id": "01M5WVNG0FK8S3JBBFYZGK1VFD", + "repo_id": "01M5WS0P331VQ3AARB26Z9DGV7", + "review_id": "01M5WVQNQSS4DQNQB5Z00WA4V7", + "code_version_id": "01M5WVQNQG83V6VQT17G0M6DBJ", + "actor_id": "01M5WRP9RJ4GVR2PA5PCNYP1FC", + "actor_display_name": "danielroe", + "actor_identity": { + "kind": "account", + "account_id": "01M5WRP9RJ4GVR2PA5PCNYP1FC", + "display_name": "Daniel Roe", + "avatar_url": "https://avatars.githubusercontent.com/u/28706372?v=4", + "handles": [ + { + "provider": "github", + "handle": "danielroe", + "is_primary": true + } + ] + }, + "body": "No tests cover the `shout` option.", + "severity": "medium", + "confidence": null, + "status": "open", + "status_reason": null, + "status_actor_id": null, + "status_actor_display_name": null, + "status_actor_identity": { + "kind": "unknown", + "account_id": null, + "display_name": null, + "avatar_url": null, + "handles": [] + }, + "status_changed_at": null, + "status_source": null, + "status_actor_kind": null, + "stale_outcome": "current", + "stale_checked_at": null, + "stale_checked_code_version_id": null, + "client_id": "whole", + "client_id_hash": "a00f6d308f3eb66bbf8828200158393d01575a3bfc9f750bacf1b11ed8d9430a", + "created_at": "2026-10-26T19:42:02.368Z", + "updated_at": "2026-10-26T19:42:02.368Z", + "location": { + "id": "01M5WVQW42ER5GPTS4JM719TDV", + "review_comment_id": "01M5WVQW423TPZGYYS4025JBCT", + "code_version_id": "01M5WVQNQG83V6VQT17G0M6DBJ", + "granularity": "whole_change", + "file_path": null, + "start_line": null, + "start_column": null, + "end_line": null, + "end_column": null, + "selected_text": null, + "nearby_text": null, + "language": null + } + }, + "messages": [] + }, + { + "id": "01M5WVP9QKVVQWQQWRFW4K3T94", + "trail_id": "01M5WVNG0FK8S3JBBFYZGK1VFD", + "title": "Naming", + "kind": "discussion", + "resolved": false, + "resolved_by": null, + "resolved_by_identity": { + "kind": "unknown", + "account_id": null, + "display_name": null, + "avatar_url": null, + "handles": [] + }, + "resolved_at": null, + "created_by": "01M5WRP9RJ4GVR2PA5PCNYP1FC", + "created_by_identity": { + "kind": "account", + "account_id": "01M5WRP9RJ4GVR2PA5PCNYP1FC", + "display_name": "Daniel Roe", + "avatar_url": "https://avatars.githubusercontent.com/u/28706372?v=4", + "handles": [ + { + "provider": "github", + "handle": "danielroe", + "is_primary": true + } + ] + }, + "created_at": "2026-10-26T19:41:10.771Z", + "updated_at": "2026-10-26T19:41:10.771Z", + "last_message_at": "2026-10-26T19:41:10.771Z", + "last_message_author": "danielroe", + "message_count": 1, + "participants": [ + { + "login": "danielroe", + "actor_account_id": "01M5WRP9RJ4GVR2PA5PCNYP1FC", + "identity": { + "kind": "account", + "account_id": "01M5WRP9RJ4GVR2PA5PCNYP1FC", + "display_name": "Daniel Roe", + "avatar_url": "https://avatars.githubusercontent.com/u/28706372?v=4", + "handles": [ + { + "provider": "github", + "handle": "danielroe", + "is_primary": true + } + ] + } + } + ], + "review_comment_id": null, + "review_comment": null, + "messages": [ + { + "id": "01M5WVP9QQB7HMVGA0SRF76KED", + "author": "danielroe", + "identity": { + "kind": "account", + "account_id": "01M5WRP9RJ4GVR2PA5PCNYP1FC", + "display_name": "Daniel Roe", + "avatar_url": "https://avatars.githubusercontent.com/u/28706372?v=4", + "handles": [ + { + "provider": "github", + "handle": "danielroe", + "is_primary": true + } + ] + }, + "created_at": "2026-10-26T19:41:10.771Z", + "body": "`shout` or `loud`? I lean towards `shout`.", + "replies": [] + } + ] + }, + { + "id": "01M5WVP84KN3H6SFHM77XGN8WE", + "trail_id": "01M5WVNG0FK8S3JBBFYZGK1VFD", + "title": "Should `shout` also add an exclamation mark?", + "kind": "discussion", + "resolved": false, + "resolved_by": null, + "resolved_by_identity": { + "kind": "unknown", + "account_id": null, + "display_name": null, + "avatar_url": null, + "handles": [] + }, + "resolved_at": null, + "created_by": "01M5WRP9RJ4GVR2PA5PCNYP1FC", + "created_by_identity": { + "kind": "account", + "account_id": "01M5WRP9RJ4GVR2PA5PCNYP1FC", + "display_name": "Daniel Roe", + "avatar_url": "https://avatars.githubusercontent.com/u/28706372?v=4", + "handles": [ + { + "provider": "github", + "handle": "danielroe", + "is_primary": true + } + ] + }, + "created_at": "2026-10-26T19:41:09.139Z", + "updated_at": "2026-10-26T19:41:09.989Z", + "last_message_at": "2026-10-26T19:41:09.989Z", + "last_message_author": "danielroe", + "message_count": 2, + "participants": [ + { + "login": "danielroe", + "actor_account_id": "01M5WRP9RJ4GVR2PA5PCNYP1FC", + "identity": { + "kind": "account", + "account_id": "01M5WRP9RJ4GVR2PA5PCNYP1FC", + "display_name": "Daniel Roe", + "avatar_url": "https://avatars.githubusercontent.com/u/28706372?v=4", + "handles": [ + { + "provider": "github", + "handle": "danielroe", + "is_primary": true + } + ] + } + } + ], + "review_comment_id": null, + "review_comment": null, + "messages": [ + { + "id": "01M5WVP8552KBGTR9NZCXY91QQ", + "author": "danielroe", + "identity": { + "kind": "account", + "account_id": "01M5WRP9RJ4GVR2PA5PCNYP1FC", + "display_name": "Daniel Roe", + "avatar_url": "https://avatars.githubusercontent.com/u/28706372?v=4", + "handles": [ + { + "provider": "github", + "handle": "danielroe", + "is_primary": true + } + ] + }, + "created_at": "2026-10-26T19:41:09.139Z", + "body": "Should `shout` also add an exclamation mark?", + "replies": [] + }, + { + "id": "01M5WVP8Z53BEF7ZA2WFQ2RQAX", + "author": "danielroe", + "identity": { + "kind": "account", + "account_id": "01M5WRP9RJ4GVR2PA5PCNYP1FC", + "display_name": "Daniel Roe", + "avatar_url": "https://avatars.githubusercontent.com/u/28706372?v=4", + "handles": [ + { + "provider": "github", + "handle": "danielroe", + "is_primary": true + } + ] + }, + "created_at": "2026-10-26T19:41:09.989Z", + "body": "I think it reads fine without one.", + "replies": [] + } + ] + } + ], + "event_cursor": "4" + } + } +} diff --git a/test/fixtures/entire/recorded/entire.com/steps/pull-comments/golden.json b/test/fixtures/entire/recorded/entire.com/steps/pull-comments/golden.json new file mode 100644 index 000000000..9f58cfcec --- /dev/null +++ b/test/fixtures/entire/recorded/entire.com/steps/pull-comments/golden.json @@ -0,0 +1,106 @@ +{ + "items": [ + { + "ref": { + "forge": "entire", + "instance": "entire.com", + "thread": { + "forge": "entire", + "instance": "entire.com", + "repo": { + "forge": "entire", + "instance": "entire.com", + "owner": "forges", + "name": "forges-fixtures" + }, + "kind": "pull_request", + "number": "1" + }, + "id": "01M5WVP8552KBGTR9NZCXY91QQ" + }, + "body": "Should `shout` also add an exclamation mark?", + "author": { + "forge": "entire", + "instance": "entire.com", + "login": "danielroe", + "id": "01M5WRP9RJ4GVR2PA5PCNYP1FC", + "name": "Daniel Roe", + "avatarUrl": "https://avatars.githubusercontent.com/u/28706372?v=4", + "isBotHint": false + }, + "createdAt": "", + "thread": { + "id": "01M5WVP84KN3H6SFHM77XGN8WE", + "resolved": false + } + }, + { + "ref": { + "forge": "entire", + "instance": "entire.com", + "thread": { + "forge": "entire", + "instance": "entire.com", + "repo": { + "forge": "entire", + "instance": "entire.com", + "owner": "forges", + "name": "forges-fixtures" + }, + "kind": "pull_request", + "number": "1" + }, + "id": "01M5WVP8Z53BEF7ZA2WFQ2RQAX" + }, + "body": "I think it reads fine without one.", + "author": { + "forge": "entire", + "instance": "entire.com", + "login": "danielroe", + "id": "01M5WRP9RJ4GVR2PA5PCNYP1FC", + "name": "Daniel Roe", + "avatarUrl": "https://avatars.githubusercontent.com/u/28706372?v=4", + "isBotHint": false + }, + "createdAt": "", + "thread": { + "id": "01M5WVP84KN3H6SFHM77XGN8WE", + "resolved": false + } + }, + { + "ref": { + "forge": "entire", + "instance": "entire.com", + "thread": { + "forge": "entire", + "instance": "entire.com", + "repo": { + "forge": "entire", + "instance": "entire.com", + "owner": "forges", + "name": "forges-fixtures" + }, + "kind": "pull_request", + "number": "1" + }, + "id": "01M5WVP9QQB7HMVGA0SRF76KED" + }, + "body": "`shout` or `loud`? I lean towards `shout`.", + "author": { + "forge": "entire", + "instance": "entire.com", + "login": "danielroe", + "id": "01M5WRP9RJ4GVR2PA5PCNYP1FC", + "name": "Daniel Roe", + "avatarUrl": "https://avatars.githubusercontent.com/u/28706372?v=4", + "isBotHint": false + }, + "createdAt": "", + "thread": { + "id": "01M5WVP9QKVVQWQQWRFW4K3T94", + "resolved": false + } + } + ] +} diff --git a/test/fixtures/entire/recorded/entire.com/steps/pull-comments/step.json b/test/fixtures/entire/recorded/entire.com/steps/pull-comments/step.json new file mode 100644 index 000000000..8aa7fe729 --- /dev/null +++ b/test/fixtures/entire/recorded/entire.com/steps/pull-comments/step.json @@ -0,0 +1,4 @@ +{ + "name": "pull comments", + "recordedAt": "2026-10-26T19:57:14.913Z" +} diff --git a/test/fixtures/entire/recorded/entire.com/steps/pull-commits/01-get-01M5WS0P331VQ3AARB26Z9DGV7-commits.json b/test/fixtures/entire/recorded/entire.com/steps/pull-commits/01-get-01M5WS0P331VQ3AARB26Z9DGV7-commits.json new file mode 100644 index 000000000..5e4e836d7 --- /dev/null +++ b/test/fixtures/entire/recorded/entire.com/steps/pull-commits/01-get-01M5WS0P331VQ3AARB26Z9DGV7-commits.json @@ -0,0 +1,51 @@ +{ + "request": { + "method": "GET", + "url": "https://aws-eu-west-2.api.entire.io/api/v1/git/repos/01M5WS0P331VQ3AARB26Z9DGV7/commits?ref=9ec20061f17f35212247320f525ec51d3e00c41a¬Ref=8127b4c88662985c819a6b3cabecde203907c3e2&pageSize=3" + }, + "response": { + "status": 200, + "headers": { + "link": "; rel=\"describedBy\"" + }, + "body": { + "$schema": "https://aws-eu-west-2.api.entire.io/api/v1/schemas/ListCommitsResponse.json", + "commits": [ + { + "sha": "9ec20061f17f35212247320f525ec51d3e00c41a", + "parents": [ + "c83b64d5032ae0ee89ecbaeea7273b2291b4d2e5" + ], + "message": "docs: mention shouting\n", + "author": { + "name": "forges fixtures", + "email": "redacted@example.invalid", + "date": "2026-10-02T10:01:00Z" + }, + "committer": { + "name": "forges fixtures", + "email": "redacted@example.invalid", + "date": "2026-10-02T10:01:00Z" + } + }, + { + "sha": "c83b64d5032ae0ee89ecbaeea7273b2291b4d2e5", + "parents": [ + "8127b4c88662985c819a6b3cabecde203907c3e2" + ], + "message": "feat: shout greetings\n", + "author": { + "name": "forges fixtures", + "email": "redacted@example.invalid", + "date": "2026-10-02T10:00:00Z" + }, + "committer": { + "name": "forges fixtures", + "email": "redacted@example.invalid", + "date": "2026-10-02T10:00:00Z" + } + } + ] + } + } +} diff --git a/test/fixtures/entire/recorded/entire.com/steps/pull-commits/02-get-compare-status.json b/test/fixtures/entire/recorded/entire.com/steps/pull-commits/02-get-compare-status.json new file mode 100644 index 000000000..5fd5279e3 --- /dev/null +++ b/test/fixtures/entire/recorded/entire.com/steps/pull-commits/02-get-compare-status.json @@ -0,0 +1,21 @@ +{ + "request": { + "method": "GET", + "url": "https://aws-eu-west-2.api.entire.io/api/v1/git/repos/01M5WS0P331VQ3AARB26Z9DGV7/compare/status?base=main&head=9ec20061f17f35212247320f525ec51d3e00c41a" + }, + "response": { + "status": 200, + "headers": { + "link": "; rel=\"describedBy\"" + }, + "body": { + "$schema": "https://aws-eu-west-2.api.entire.io/api/v1/schemas/CompareStatusResponse.json", + "commitsAhead": 2, + "commitsBehind": 1, + "mergeBaseSHA": "8127b4c88662985c819a6b3cabecde203907c3e2", + "resolvedBaseSHA": "dd07002e23c86b5e68d53ebe9949e1bf5549c8ca", + "resolvedHeadSHA": "9ec20061f17f35212247320f525ec51d3e00c41a", + "truncated": false + } + } +} diff --git a/test/fixtures/entire/recorded/entire.com/steps/pull-commits/03-get-forges-fixtures-N.json b/test/fixtures/entire/recorded/entire.com/steps/pull-commits/03-get-forges-fixtures-N.json new file mode 100644 index 000000000..06fea9967 --- /dev/null +++ b/test/fixtures/entire/recorded/entire.com/steps/pull-commits/03-get-forges-fixtures-N.json @@ -0,0 +1,287 @@ +{ + "request": { + "method": "GET", + "url": "https://aws-eu-west-2.api.entire.io/api/v1/trails/et/forges/forges-fixtures/1" + }, + "response": { + "status": 200, + "headers": { + "link": "; rel=\"describedBy\"" + }, + "body": { + "$schema": "https://aws-eu-west-2.api.entire.io/api/v1/schemas/TrailDetailResponse.json", + "id": "01M5WVNG0FK8S3JBBFYZGK1VFD", + "number": 1, + "url": "https://entire.com/et/forges/forges-fixtures/trails/1", + "title": "feat: shout greetings", + "status": "open", + "branch": "feature/shout", + "original_branch": "feature/shout", + "base": "main", + "type": "task", + "priority": "none", + "author": { + "id": "01M5WRP9RJ4GVR2PA5PCNYP1FC", + "login": "danielroe", + "identity": { + "kind": "account", + "account_id": "01M5WRP9RJ4GVR2PA5PCNYP1FC", + "display_name": "Daniel Roe", + "avatar_url": "https://avatars.githubusercontent.com/u/28706372?v=4", + "handles": [ + { + "provider": "github", + "handle": "danielroe", + "is_primary": true + } + ] + } + }, + "assignees": [ + "danielroe" + ], + "assignee_identities": [ + { + "login": "danielroe", + "identity": { + "kind": "account", + "account_id": "01M5WRP9RJ4GVR2PA5PCNYP1FC", + "display_name": "Daniel Roe", + "avatar_url": "https://avatars.githubusercontent.com/u/28706372?v=4", + "handles": [ + { + "provider": "github", + "handle": "danielroe", + "is_primary": true + } + ] + } + } + ], + "reviewers": [ + { + "login": "danielroe", + "status": "changes_requested", + "actor_account_id": "01M5WRP9RJ4GVR2PA5PCNYP1FC", + "identity": { + "kind": "account", + "account_id": "01M5WRP9RJ4GVR2PA5PCNYP1FC", + "display_name": "Daniel Roe", + "avatar_url": "https://avatars.githubusercontent.com/u/28706372?v=4", + "handles": [ + { + "provider": "github", + "handle": "danielroe", + "is_primary": true + } + ] + } + } + ], + "ready_for_review": true, + "has_code_changes": true, + "comment_count": 4, + "unresolved_count": 4, + "created_at": "2026-10-26T19:40:44.349Z", + "updated_at": "2026-10-26T19:42:13.290Z", + "merged_at": null, + "last_activity_at": "2026-10-26T19:42:13.290Z", + "phase": "reviewing", + "parent": { + "id": "01M5WVNFY1D7AHX0KJW2ANZP14", + "number": 2, + "project_id": "01M5WS0JJNP4V9AW20MZ3MKF5M", + "host": "et", + "project": "forges", + "path": "/api/v1/et/forges/trails/01M5WVNFY1D7AHX0KJW2ANZP14", + "jurisdiction": "uk", + "primary_processing_cell": "aws-eu-west-2", + "url": "https://entire.com/et/forges/-/trails/2" + }, + "branch_state": "present", + "code_changes": "present", + "lifecycle_sync": "settled", + "body_document": { + "id": "01M5WVNG4RWC7X4X51BHP5Q5M2", + "document_key": "trail:01M5WVNG0FK8S3JBBFYZGK1VFD:body", + "schema_version": 1, + "content_json": { + "type": "doc", + "content": [ + { + "type": "paragraph" + } + ] + }, + "text_snapshot": "", + "updated_at": "2026-10-26T19:40:44.349Z", + "etag": "W/\"2026-10-26T19:40:44.349281Z\"" + }, + "monitors": [], + "agents": [], + "runners": [], + "actions": { + "approve": { + "state": "enabled", + "reason": null + }, + "create_ci_pr": { + "state": "unavailable", + "reason": "not_applicable" + }, + "merge": { + "state": "blocked", + "reason": "merge_conflict" + }, + "merge_with_bypass": { + "state": "unavailable", + "reason": "merge_gates_bypass_forbidden" + }, + "update_branch": { + "state": "unavailable", + "reason": "merge_conflict" + }, + "restore_branch": { + "state": "unavailable", + "reason": "trail_not_merged" + }, + "delete_branch": { + "state": "unavailable", + "reason": "trail_not_merged" + } + }, + "mergeability": { + "delete_branch_on_merge": false, + "bypass_policy": "nobody", + "mergeable": false, + "behind_by": 1, + "comparison_status": "available", + "conflict_status": "conflicting", + "head_sha": "9ec20061f17f35212247320f525ec51d3e00c41a", + "gates": [ + { + "reviewers": [ + { + "login": "danielroe", + "actor_account_id": "01M5WRP9RJ4GVR2PA5PCNYP1FC", + "state": "changes_requested", + "reviewed_head_sha": "9ec20061f17f35212247320f525ec51d3e00c41a", + "reason": null + } + ], + "runner_ids": [], + "id": "", + "gate_definition_id": "01M5WTJP4MSACMEJ1KK4FGP2B1", + "gate_key": "approvals", + "gate_type": "approvals", + "blocking": true, + "status": "failed", + "head_sha": "9ec20061f17f35212247320f525ec51d3e00c41a", + "value": { + "approved": 0, + "changes_requested": true, + "config": { + "version": 1, + "min_reviewers": 1, + "allow_self_approval": true, + "dismiss_stale_approvals_on_push": false + }, + "required": 1, + "self_excluded": false, + "stale_dismissed": 0, + "total": 1 + }, + "rationale": "Changes have been requested", + "created_at": "2026-10-26T21:02:31.570655543Z", + "completed_at": "2026-10-26T21:02:31.570655543Z", + "state": "evaluated", + "outcome": "failed", + "stale_reason": null, + "evaluated_at_sha": "9ec20061f17f35212247320f525ec51d3e00c41a", + "finding_count": null + }, + { + "reviewers": [], + "runner_ids": [], + "id": "01M5WVQW5BHQ3CSVZJTM3595D5", + "gate_definition_id": "01M5WTJP5MDYCYNF3Z6BWN7NZ0", + "gate_key": "findings", + "gate_type": "findings", + "blocking": true, + "status": "passed", + "head_sha": "9ec20061f17f35212247320f525ec51d3e00c41a", + "value": { + "config": { + "version": 1, + "agent_findings_min_severity": "high" + }, + "reviewed_head": false, + "agent_findings": { + "low": 1, + "high": 0, + "medium": 1, + "unspecified": 0 + }, + "review_in_flight": false, + "reviewer_configured": false, + "review_grace_expired": false, + "agent_blocking_findings": 0 + }, + "rationale": "No blocking findings", + "created_at": "2026-10-26T19:42:02.411692Z", + "completed_at": "2026-10-26T19:42:02.411692Z", + "state": "evaluated", + "outcome": "passed", + "stale_reason": null, + "evaluated_at_sha": "9ec20061f17f35212247320f525ec51d3e00c41a", + "finding_count": 0 + }, + { + "reviewers": [], + "runner_ids": [], + "id": "", + "gate_definition_id": "01M5WTJP5QR0FQ7TWGE7Y3QCJC", + "gate_key": "up_to_date", + "gate_type": "up_to_date", + "blocking": true, + "status": "failed", + "head_sha": "9ec20061f17f35212247320f525ec51d3e00c41a", + "value": { + "comparison_status": "available", + "behind_by": 1, + "compare_status": "diverged", + "merge_status": "conflicting", + "config": { + "version": 1, + "allow_behind_if_mergeable": false + } + }, + "rationale": "Merge conflicts", + "created_at": "2026-10-26T19:41:42.616528Z", + "completed_at": null, + "state": "evaluated", + "outcome": "failed", + "stale_reason": null, + "evaluated_at_sha": "9ec20061f17f35212247320f525ec51d3e00c41a", + "finding_count": null + } + ], + "checks": { + "availability": "not_applicable", + "runs": [] + }, + "forge_merge_block": null + }, + "deployments": { + "availability": "available", + "ready": 0, + "total": 0, + "items": [] + }, + "config_source": "live", + "merge_base_sha": null, + "base_sha": null, + "head_sha": "9ec20061f17f35212247320f525ec51d3e00c41a" + } + } +} diff --git a/test/fixtures/entire/recorded/entire.com/steps/pull-commits/golden.json b/test/fixtures/entire/recorded/entire.com/steps/pull-commits/golden.json new file mode 100644 index 000000000..265331712 --- /dev/null +++ b/test/fixtures/entire/recorded/entire.com/steps/pull-commits/golden.json @@ -0,0 +1,60 @@ +{ + "items": [ + { + "ref": { + "forge": "entire", + "instance": "entire.com", + "repo": { + "forge": "entire", + "instance": "entire.com", + "owner": "forges", + "name": "forges-fixtures" + }, + "sha": "9ec20061f17f35212247320f525ec51d3e00c41a" + }, + "sha": "9ec20061f17f35212247320f525ec51d3e00c41a", + "message": "docs: mention shouting", + "author": { + "name": "forges fixtures", + "email": "redacted@example.invalid", + "date": "2026-10-02T10:01:00.000Z" + }, + "committer": { + "name": "forges fixtures", + "email": "redacted@example.invalid", + "date": "2026-10-02T10:01:00.000Z" + }, + "parents": [ + "c83b64d5032ae0ee89ecbaeea7273b2291b4d2e5" + ] + }, + { + "ref": { + "forge": "entire", + "instance": "entire.com", + "repo": { + "forge": "entire", + "instance": "entire.com", + "owner": "forges", + "name": "forges-fixtures" + }, + "sha": "c83b64d5032ae0ee89ecbaeea7273b2291b4d2e5" + }, + "sha": "c83b64d5032ae0ee89ecbaeea7273b2291b4d2e5", + "message": "feat: shout greetings", + "author": { + "name": "forges fixtures", + "email": "redacted@example.invalid", + "date": "2026-10-02T10:00:00.000Z" + }, + "committer": { + "name": "forges fixtures", + "email": "redacted@example.invalid", + "date": "2026-10-02T10:00:00.000Z" + }, + "parents": [ + "8127b4c88662985c819a6b3cabecde203907c3e2" + ] + } + ] +} diff --git a/test/fixtures/entire/recorded/entire.com/steps/pull-commits/step.json b/test/fixtures/entire/recorded/entire.com/steps/pull-commits/step.json new file mode 100644 index 000000000..01015e368 --- /dev/null +++ b/test/fixtures/entire/recorded/entire.com/steps/pull-commits/step.json @@ -0,0 +1,4 @@ +{ + "name": "pull commits", + "recordedAt": "2026-10-26T21:02:31.439Z" +} diff --git a/test/fixtures/entire/recorded/entire.com/steps/pull-events/01-get-N-timeline.json b/test/fixtures/entire/recorded/entire.com/steps/pull-events/01-get-N-timeline.json new file mode 100644 index 000000000..0bdd9e4fd --- /dev/null +++ b/test/fixtures/entire/recorded/entire.com/steps/pull-events/01-get-N-timeline.json @@ -0,0 +1,90 @@ +{ + "request": { + "method": "GET", + "url": "https://aws-eu-west-2.api.entire.io/api/v1/repos/01M5WS0P331VQ3AARB26Z9DGV7/trails/1/timeline?pageSize=3" + }, + "response": { + "status": 200, + "headers": { + "link": "; rel=\"describedBy\"" + }, + "body": { + "$schema": "https://aws-eu-west-2.api.entire.io/api/v1/schemas/TrailTimelineResponse.json", + "items": [ + { + "id": "trail-message-01M5WVR6SAXG323XBRAH7G0Q3V", + "kind": "comment", + "actor": { + "login": "danielroe", + "identity": { + "kind": "account", + "account_id": "01M5WRP9RJ4GVR2PA5PCNYP1FC", + "display_name": "Daniel Roe", + "avatar_url": "https://avatars.githubusercontent.com/u/28706372?v=4", + "handles": [ + { + "provider": "github", + "handle": "danielroe", + "is_primary": true + } + ] + } + }, + "occurredAt": "2026-10-26T19:42:13.290Z", + "commentId": "01M5WVR6SAXG323XBRAH7G0Q3V", + "discussionId": "01M5WVQW2ZPDDH5X0C5SWM3KVM", + "isReply": false + }, + { + "id": "trail-review-01M5WVQNQSS4DQNQB5Z00WA4V7", + "kind": "review_posted", + "actor": { + "login": "danielroe", + "identity": { + "kind": "account", + "account_id": "01M5WRP9RJ4GVR2PA5PCNYP1FC", + "display_name": "Daniel Roe", + "avatar_url": "https://avatars.githubusercontent.com/u/28706372?v=4", + "handles": [ + { + "provider": "github", + "handle": "danielroe", + "is_primary": true + } + ] + } + }, + "occurredAt": "2026-10-26T19:42:02.333Z", + "findingCount": 2, + "commentId": "01M5WVQW2ZTEEA9V72FF81J46Q" + }, + { + "id": "trail-approval-01M5WVPQ2KX1QCY97NEWDQWTB8", + "kind": "approval", + "actor": { + "login": "danielroe", + "identity": { + "kind": "account", + "account_id": "01M5WRP9RJ4GVR2PA5PCNYP1FC", + "display_name": "Daniel Roe", + "avatar_url": "https://avatars.githubusercontent.com/u/28706372?v=4", + "handles": [ + { + "provider": "github", + "handle": "danielroe", + "is_primary": true + } + ] + } + }, + "occurredAt": "2026-10-26T19:41:24.435Z", + "approvalStatus": "changes_requested", + "body": "Please add a test for shouting." + } + ], + "nextPageToken": "eyJvY2N1cnJlZEF0IjoiMjAyNi0xMC0yNlQxOTo0MToyNC40MzU0MTQwNDdaIiwiaWQiOiJ0cmFpbC1hcHByb3ZhbC0wMU01V1ZQUTJLWDFRQ1k5N05FV0RRV1RCOCJ9", + "commitCount": 2, + "incomplete": false + } + } +} diff --git a/test/fixtures/entire/recorded/entire.com/steps/pull-events/02-get-N-discussions.json b/test/fixtures/entire/recorded/entire.com/steps/pull-events/02-get-N-discussions.json new file mode 100644 index 000000000..0e3836d99 --- /dev/null +++ b/test/fixtures/entire/recorded/entire.com/steps/pull-events/02-get-N-discussions.json @@ -0,0 +1,433 @@ +{ + "request": { + "method": "GET", + "url": "https://aws-eu-west-2.api.entire.io/api/v1/trails/et/forges/forges-fixtures/1/discussions?include_messages=true&per_page=100" + }, + "response": { + "status": 200, + "headers": { + "link": "; rel=\"describedBy\"" + }, + "body": { + "$schema": "https://aws-eu-west-2.api.entire.io/api/v1/schemas/TrailDiscussionsListResponseBody.json", + "items": [ + { + "id": "01M5WVQW2ZPDDH5X0C5SWM3KVM", + "trail_id": "01M5WVNG0FK8S3JBBFYZGK1VFD", + "title": "`toUpperCase()` ignores the locale, so Turkish names shout incorrectly. Consider `toLocaleUpperCase()`.", + "kind": "code_review", + "resolved": false, + "resolved_by": null, + "resolved_by_identity": { + "kind": "unknown", + "account_id": null, + "display_name": null, + "avatar_url": null, + "handles": [] + }, + "resolved_at": null, + "created_by": "01M5WRP9RJ4GVR2PA5PCNYP1FC", + "created_by_identity": { + "kind": "account", + "account_id": "01M5WRP9RJ4GVR2PA5PCNYP1FC", + "display_name": "Daniel Roe", + "avatar_url": "https://avatars.githubusercontent.com/u/28706372?v=4", + "handles": [ + { + "provider": "github", + "handle": "danielroe", + "is_primary": true + } + ] + }, + "created_at": "2026-10-26T19:42:02.333Z", + "updated_at": "2026-10-26T19:42:13.290Z", + "last_message_at": "2026-10-26T19:42:13.290Z", + "last_message_author": "danielroe", + "message_count": 1, + "participants": [ + { + "login": "danielroe", + "actor_account_id": "01M5WRP9RJ4GVR2PA5PCNYP1FC", + "identity": { + "kind": "account", + "account_id": "01M5WRP9RJ4GVR2PA5PCNYP1FC", + "display_name": "Daniel Roe", + "avatar_url": "https://avatars.githubusercontent.com/u/28706372?v=4", + "handles": [ + { + "provider": "github", + "handle": "danielroe", + "is_primary": true + } + ] + } + } + ], + "review_comment_id": "01M5WVQW2ZTEEA9V72FF81J46Q", + "review_comment": { + "discussion_id": "01M5WVQW2ZPDDH5X0C5SWM3KVM", + "discussion_message_count": 1, + "id": "01M5WVQW2ZTEEA9V72FF81J46Q", + "trail_id": "01M5WVNG0FK8S3JBBFYZGK1VFD", + "repo_id": "01M5WS0P331VQ3AARB26Z9DGV7", + "review_id": "01M5WVQNQSS4DQNQB5Z00WA4V7", + "code_version_id": "01M5WVQNQG83V6VQT17G0M6DBJ", + "actor_id": "01M5WRP9RJ4GVR2PA5PCNYP1FC", + "actor_display_name": "danielroe", + "actor_identity": { + "kind": "account", + "account_id": "01M5WRP9RJ4GVR2PA5PCNYP1FC", + "display_name": "Daniel Roe", + "avatar_url": "https://avatars.githubusercontent.com/u/28706372?v=4", + "handles": [ + { + "provider": "github", + "handle": "danielroe", + "is_primary": true + } + ] + }, + "body": "`toUpperCase()` ignores the locale, so Turkish names shout incorrectly. Consider `toLocaleUpperCase()`.", + "severity": "low", + "confidence": null, + "status": "open", + "status_reason": null, + "status_actor_id": null, + "status_actor_display_name": null, + "status_actor_identity": { + "kind": "unknown", + "account_id": null, + "display_name": null, + "avatar_url": null, + "handles": [] + }, + "status_changed_at": null, + "status_source": null, + "status_actor_kind": null, + "stale_outcome": "current", + "stale_checked_at": null, + "stale_checked_code_version_id": null, + "client_id": "shout-case", + "client_id_hash": "ea05e251d04f3b2e1dbf616445b14d9faba65c96f60b955c61a748fb186cd26d", + "created_at": "2026-10-26T19:42:02.333Z", + "updated_at": "2026-10-26T19:42:02.333Z", + "location": { + "id": "01M5WVQW2Z3NCP4Y284CQ5DE3Y", + "review_comment_id": "01M5WVQW2ZTEEA9V72FF81J46Q", + "code_version_id": "01M5WVQNQG83V6VQT17G0M6DBJ", + "granularity": "line", + "file_path": "src/greet.ts", + "start_line": 3, + "start_column": null, + "end_line": 3, + "end_column": null, + "selected_text": " return options.shout ? greeting.toUpperCase() : greeting", + "nearby_text": null, + "language": null + } + }, + "messages": [ + { + "id": "01M5WVR6SAXG323XBRAH7G0Q3V", + "author": "danielroe", + "identity": { + "kind": "account", + "account_id": "01M5WRP9RJ4GVR2PA5PCNYP1FC", + "display_name": "Daniel Roe", + "avatar_url": "https://avatars.githubusercontent.com/u/28706372?v=4", + "handles": [ + { + "provider": "github", + "handle": "danielroe", + "is_primary": true + } + ] + }, + "created_at": "2026-10-26T19:42:13.290Z", + "body": "Good catch, switching to `toLocaleUpperCase()`.", + "replies": [] + } + ] + }, + { + "id": "01M5WVQW42CZ9N82B1QV6B6GTP", + "trail_id": "01M5WVNG0FK8S3JBBFYZGK1VFD", + "title": "No tests cover the `shout` option.", + "kind": "code_review", + "resolved": false, + "resolved_by": null, + "resolved_by_identity": { + "kind": "unknown", + "account_id": null, + "display_name": null, + "avatar_url": null, + "handles": [] + }, + "resolved_at": null, + "created_by": "01M5WRP9RJ4GVR2PA5PCNYP1FC", + "created_by_identity": { + "kind": "account", + "account_id": "01M5WRP9RJ4GVR2PA5PCNYP1FC", + "display_name": "Daniel Roe", + "avatar_url": "https://avatars.githubusercontent.com/u/28706372?v=4", + "handles": [ + { + "provider": "github", + "handle": "danielroe", + "is_primary": true + } + ] + }, + "created_at": "2026-10-26T19:42:02.368Z", + "updated_at": "2026-10-26T19:42:02.368Z", + "last_message_at": null, + "last_message_author": null, + "message_count": 0, + "participants": [], + "review_comment_id": "01M5WVQW423TPZGYYS4025JBCT", + "review_comment": { + "discussion_id": "01M5WVQW42CZ9N82B1QV6B6GTP", + "discussion_message_count": 0, + "id": "01M5WVQW423TPZGYYS4025JBCT", + "trail_id": "01M5WVNG0FK8S3JBBFYZGK1VFD", + "repo_id": "01M5WS0P331VQ3AARB26Z9DGV7", + "review_id": "01M5WVQNQSS4DQNQB5Z00WA4V7", + "code_version_id": "01M5WVQNQG83V6VQT17G0M6DBJ", + "actor_id": "01M5WRP9RJ4GVR2PA5PCNYP1FC", + "actor_display_name": "danielroe", + "actor_identity": { + "kind": "account", + "account_id": "01M5WRP9RJ4GVR2PA5PCNYP1FC", + "display_name": "Daniel Roe", + "avatar_url": "https://avatars.githubusercontent.com/u/28706372?v=4", + "handles": [ + { + "provider": "github", + "handle": "danielroe", + "is_primary": true + } + ] + }, + "body": "No tests cover the `shout` option.", + "severity": "medium", + "confidence": null, + "status": "open", + "status_reason": null, + "status_actor_id": null, + "status_actor_display_name": null, + "status_actor_identity": { + "kind": "unknown", + "account_id": null, + "display_name": null, + "avatar_url": null, + "handles": [] + }, + "status_changed_at": null, + "status_source": null, + "status_actor_kind": null, + "stale_outcome": "current", + "stale_checked_at": null, + "stale_checked_code_version_id": null, + "client_id": "whole", + "client_id_hash": "a00f6d308f3eb66bbf8828200158393d01575a3bfc9f750bacf1b11ed8d9430a", + "created_at": "2026-10-26T19:42:02.368Z", + "updated_at": "2026-10-26T19:42:02.368Z", + "location": { + "id": "01M5WVQW42ER5GPTS4JM719TDV", + "review_comment_id": "01M5WVQW423TPZGYYS4025JBCT", + "code_version_id": "01M5WVQNQG83V6VQT17G0M6DBJ", + "granularity": "whole_change", + "file_path": null, + "start_line": null, + "start_column": null, + "end_line": null, + "end_column": null, + "selected_text": null, + "nearby_text": null, + "language": null + } + }, + "messages": [] + }, + { + "id": "01M5WVP9QKVVQWQQWRFW4K3T94", + "trail_id": "01M5WVNG0FK8S3JBBFYZGK1VFD", + "title": "Naming", + "kind": "discussion", + "resolved": false, + "resolved_by": null, + "resolved_by_identity": { + "kind": "unknown", + "account_id": null, + "display_name": null, + "avatar_url": null, + "handles": [] + }, + "resolved_at": null, + "created_by": "01M5WRP9RJ4GVR2PA5PCNYP1FC", + "created_by_identity": { + "kind": "account", + "account_id": "01M5WRP9RJ4GVR2PA5PCNYP1FC", + "display_name": "Daniel Roe", + "avatar_url": "https://avatars.githubusercontent.com/u/28706372?v=4", + "handles": [ + { + "provider": "github", + "handle": "danielroe", + "is_primary": true + } + ] + }, + "created_at": "2026-10-26T19:41:10.771Z", + "updated_at": "2026-10-26T19:41:10.771Z", + "last_message_at": "2026-10-26T19:41:10.771Z", + "last_message_author": "danielroe", + "message_count": 1, + "participants": [ + { + "login": "danielroe", + "actor_account_id": "01M5WRP9RJ4GVR2PA5PCNYP1FC", + "identity": { + "kind": "account", + "account_id": "01M5WRP9RJ4GVR2PA5PCNYP1FC", + "display_name": "Daniel Roe", + "avatar_url": "https://avatars.githubusercontent.com/u/28706372?v=4", + "handles": [ + { + "provider": "github", + "handle": "danielroe", + "is_primary": true + } + ] + } + } + ], + "review_comment_id": null, + "review_comment": null, + "messages": [ + { + "id": "01M5WVP9QQB7HMVGA0SRF76KED", + "author": "danielroe", + "identity": { + "kind": "account", + "account_id": "01M5WRP9RJ4GVR2PA5PCNYP1FC", + "display_name": "Daniel Roe", + "avatar_url": "https://avatars.githubusercontent.com/u/28706372?v=4", + "handles": [ + { + "provider": "github", + "handle": "danielroe", + "is_primary": true + } + ] + }, + "created_at": "2026-10-26T19:41:10.771Z", + "body": "`shout` or `loud`? I lean towards `shout`.", + "replies": [] + } + ] + }, + { + "id": "01M5WVP84KN3H6SFHM77XGN8WE", + "trail_id": "01M5WVNG0FK8S3JBBFYZGK1VFD", + "title": "Should `shout` also add an exclamation mark?", + "kind": "discussion", + "resolved": false, + "resolved_by": null, + "resolved_by_identity": { + "kind": "unknown", + "account_id": null, + "display_name": null, + "avatar_url": null, + "handles": [] + }, + "resolved_at": null, + "created_by": "01M5WRP9RJ4GVR2PA5PCNYP1FC", + "created_by_identity": { + "kind": "account", + "account_id": "01M5WRP9RJ4GVR2PA5PCNYP1FC", + "display_name": "Daniel Roe", + "avatar_url": "https://avatars.githubusercontent.com/u/28706372?v=4", + "handles": [ + { + "provider": "github", + "handle": "danielroe", + "is_primary": true + } + ] + }, + "created_at": "2026-10-26T19:41:09.139Z", + "updated_at": "2026-10-26T19:41:09.989Z", + "last_message_at": "2026-10-26T19:41:09.989Z", + "last_message_author": "danielroe", + "message_count": 2, + "participants": [ + { + "login": "danielroe", + "actor_account_id": "01M5WRP9RJ4GVR2PA5PCNYP1FC", + "identity": { + "kind": "account", + "account_id": "01M5WRP9RJ4GVR2PA5PCNYP1FC", + "display_name": "Daniel Roe", + "avatar_url": "https://avatars.githubusercontent.com/u/28706372?v=4", + "handles": [ + { + "provider": "github", + "handle": "danielroe", + "is_primary": true + } + ] + } + } + ], + "review_comment_id": null, + "review_comment": null, + "messages": [ + { + "id": "01M5WVP8552KBGTR9NZCXY91QQ", + "author": "danielroe", + "identity": { + "kind": "account", + "account_id": "01M5WRP9RJ4GVR2PA5PCNYP1FC", + "display_name": "Daniel Roe", + "avatar_url": "https://avatars.githubusercontent.com/u/28706372?v=4", + "handles": [ + { + "provider": "github", + "handle": "danielroe", + "is_primary": true + } + ] + }, + "created_at": "2026-10-26T19:41:09.139Z", + "body": "Should `shout` also add an exclamation mark?", + "replies": [] + }, + { + "id": "01M5WVP8Z53BEF7ZA2WFQ2RQAX", + "author": "danielroe", + "identity": { + "kind": "account", + "account_id": "01M5WRP9RJ4GVR2PA5PCNYP1FC", + "display_name": "Daniel Roe", + "avatar_url": "https://avatars.githubusercontent.com/u/28706372?v=4", + "handles": [ + { + "provider": "github", + "handle": "danielroe", + "is_primary": true + } + ] + }, + "created_at": "2026-10-26T19:41:09.989Z", + "body": "I think it reads fine without one.", + "replies": [] + } + ] + } + ], + "event_cursor": "4" + } + } +} diff --git a/test/fixtures/entire/recorded/entire.com/steps/pull-events/golden.json b/test/fixtures/entire/recorded/entire.com/steps/pull-events/golden.json new file mode 100644 index 000000000..45808066d --- /dev/null +++ b/test/fixtures/entire/recorded/entire.com/steps/pull-events/golden.json @@ -0,0 +1,189 @@ +{ + "items": [ + { + "forge": "entire", + "instance": "entire.com", + "id": "trail-message-01M5WVR6SAXG323XBRAH7G0Q3V", + "kindRaw": "comment", + "occurredAt": "", + "actor": { + "forge": "entire", + "instance": "entire.com", + "login": "danielroe", + "id": "01M5WRP9RJ4GVR2PA5PCNYP1FC", + "name": "Daniel Roe", + "avatarUrl": "https://avatars.githubusercontent.com/u/28706372?v=4", + "isBotHint": false + }, + "repo": { + "forge": "entire", + "instance": "entire.com", + "owner": "forges", + "name": "forges-fixtures" + }, + "thread": { + "forge": "entire", + "instance": "entire.com", + "repo": { + "forge": "entire", + "instance": "entire.com", + "owner": "forges", + "name": "forges-fixtures" + }, + "kind": "pull_request", + "number": "1" + }, + "source": "poll", + "kind": "review_comment", + "summary": "danielroe commented on a review", + "detail": { + "type": "review_comment", + "comment": { + "forge": "entire", + "instance": "entire.com", + "thread": { + "forge": "entire", + "instance": "entire.com", + "repo": { + "forge": "entire", + "instance": "entire.com", + "owner": "forges", + "name": "forges-fixtures" + }, + "kind": "pull_request", + "number": "1" + }, + "id": "01M5WVR6SAXG323XBRAH7G0Q3V" + }, + "body": "Good catch, switching to `toLocaleUpperCase()`.", + "path": "src/greet.ts", + "line": 3 + }, + "action": "created" + }, + { + "forge": "entire", + "instance": "entire.com", + "id": "trail-review-01M5WVQNQSS4DQNQB5Z00WA4V7", + "kindRaw": "review_posted", + "occurredAt": "", + "actor": { + "forge": "entire", + "instance": "entire.com", + "login": "danielroe", + "id": "01M5WRP9RJ4GVR2PA5PCNYP1FC", + "name": "Daniel Roe", + "avatarUrl": "https://avatars.githubusercontent.com/u/28706372?v=4", + "isBotHint": false + }, + "repo": { + "forge": "entire", + "instance": "entire.com", + "owner": "forges", + "name": "forges-fixtures" + }, + "thread": { + "forge": "entire", + "instance": "entire.com", + "repo": { + "forge": "entire", + "instance": "entire.com", + "owner": "forges", + "name": "forges-fixtures" + }, + "kind": "pull_request", + "number": "1" + }, + "source": "poll", + "kind": "review", + "summary": "danielroe reviewed", + "detail": { + "type": "review", + "state": "commented", + "stateRaw": "review_posted", + "review": { + "forge": "entire", + "instance": "entire.com", + "thread": { + "forge": "entire", + "instance": "entire.com", + "repo": { + "forge": "entire", + "instance": "entire.com", + "owner": "forges", + "name": "forges-fixtures" + }, + "kind": "pull_request", + "number": "1" + }, + "id": "01M5WVQNQSS4DQNQB5Z00WA4V7" + } + }, + "action": "submitted" + }, + { + "forge": "entire", + "instance": "entire.com", + "id": "trail-approval-01M5WVPQ2KX1QCY97NEWDQWTB8", + "kindRaw": "approval", + "occurredAt": "", + "actor": { + "forge": "entire", + "instance": "entire.com", + "login": "danielroe", + "id": "01M5WRP9RJ4GVR2PA5PCNYP1FC", + "name": "Daniel Roe", + "avatarUrl": "https://avatars.githubusercontent.com/u/28706372?v=4", + "isBotHint": false + }, + "repo": { + "forge": "entire", + "instance": "entire.com", + "owner": "forges", + "name": "forges-fixtures" + }, + "thread": { + "forge": "entire", + "instance": "entire.com", + "repo": { + "forge": "entire", + "instance": "entire.com", + "owner": "forges", + "name": "forges-fixtures" + }, + "kind": "pull_request", + "number": "1" + }, + "source": "poll", + "kind": "review", + "summary": "danielroe requested changes", + "detail": { + "type": "review", + "state": "changes_requested", + "stateRaw": "changes_requested", + "body": "Please add a test for shouting.", + "review": { + "forge": "entire", + "instance": "entire.com", + "thread": { + "forge": "entire", + "instance": "entire.com", + "repo": { + "forge": "entire", + "instance": "entire.com", + "owner": "forges", + "name": "forges-fixtures" + }, + "kind": "pull_request", + "number": "1" + }, + "id": "01M5WVPQ2KX1QCY97NEWDQWTB8" + } + }, + "action": "submitted" + } + ], + "cursor": { + "token": "eyJvY2N1cnJlZEF0IjoiMjAyNi0xMC0yNlQxOTo0MToyNC40MzU0MTQwNDdaIiwiaWQiOiJ0cmFpbC1hcHByb3ZhbC0wMU01V1ZQUTJLWDFRQ1k5N05FV0RRV1RCOCJ9" + } +} diff --git a/test/fixtures/entire/recorded/entire.com/steps/pull-events/step.json b/test/fixtures/entire/recorded/entire.com/steps/pull-events/step.json new file mode 100644 index 000000000..72293a438 --- /dev/null +++ b/test/fixtures/entire/recorded/entire.com/steps/pull-events/step.json @@ -0,0 +1,4 @@ +{ + "name": "pull events", + "recordedAt": "2026-10-26T19:58:25.584Z" +} diff --git a/test/fixtures/entire/recorded/entire.com/steps/pull-files/01-get-compare-status.json b/test/fixtures/entire/recorded/entire.com/steps/pull-files/01-get-compare-status.json new file mode 100644 index 000000000..5fd5279e3 --- /dev/null +++ b/test/fixtures/entire/recorded/entire.com/steps/pull-files/01-get-compare-status.json @@ -0,0 +1,21 @@ +{ + "request": { + "method": "GET", + "url": "https://aws-eu-west-2.api.entire.io/api/v1/git/repos/01M5WS0P331VQ3AARB26Z9DGV7/compare/status?base=main&head=9ec20061f17f35212247320f525ec51d3e00c41a" + }, + "response": { + "status": 200, + "headers": { + "link": "; rel=\"describedBy\"" + }, + "body": { + "$schema": "https://aws-eu-west-2.api.entire.io/api/v1/schemas/CompareStatusResponse.json", + "commitsAhead": 2, + "commitsBehind": 1, + "mergeBaseSHA": "8127b4c88662985c819a6b3cabecde203907c3e2", + "resolvedBaseSHA": "dd07002e23c86b5e68d53ebe9949e1bf5549c8ca", + "resolvedHeadSHA": "9ec20061f17f35212247320f525ec51d3e00c41a", + "truncated": false + } + } +} diff --git a/test/fixtures/entire/recorded/entire.com/steps/pull-files/02-get-01M5WS0P331VQ3AARB26Z9DGV7-compare.json b/test/fixtures/entire/recorded/entire.com/steps/pull-files/02-get-01M5WS0P331VQ3AARB26Z9DGV7-compare.json new file mode 100644 index 000000000..b019208a7 --- /dev/null +++ b/test/fixtures/entire/recorded/entire.com/steps/pull-files/02-get-01M5WS0P331VQ3AARB26Z9DGV7-compare.json @@ -0,0 +1,34 @@ +{ + "request": { + "method": "GET", + "url": "https://aws-eu-west-2.api.entire.io/api/v1/git/repos/01M5WS0P331VQ3AARB26Z9DGV7/compare?base=8127b4c88662985c819a6b3cabecde203907c3e2&head=9ec20061f17f35212247320f525ec51d3e00c41a" + }, + "response": { + "status": 200, + "headers": { + "link": "; rel=\"describedBy\"" + }, + "body": { + "$schema": "https://aws-eu-west-2.api.entire.io/api/v1/schemas/CompareResponse.json", + "files": [ + { + "path": "README.md", + "status": "modified", + "additions": 2, + "deletions": 0, + "binary": false, + "tooLarge": false + }, + { + "path": "src/greet.ts", + "status": "modified", + "additions": 3, + "deletions": 2, + "binary": false, + "tooLarge": false + } + ], + "truncated": false + } + } +} diff --git a/test/fixtures/entire/recorded/entire.com/steps/pull-files/03-get-forges-fixtures-N.json b/test/fixtures/entire/recorded/entire.com/steps/pull-files/03-get-forges-fixtures-N.json new file mode 100644 index 000000000..76527be0d --- /dev/null +++ b/test/fixtures/entire/recorded/entire.com/steps/pull-files/03-get-forges-fixtures-N.json @@ -0,0 +1,287 @@ +{ + "request": { + "method": "GET", + "url": "https://aws-eu-west-2.api.entire.io/api/v1/trails/et/forges/forges-fixtures/1" + }, + "response": { + "status": 200, + "headers": { + "link": "; rel=\"describedBy\"" + }, + "body": { + "$schema": "https://aws-eu-west-2.api.entire.io/api/v1/schemas/TrailDetailResponse.json", + "id": "01M5WVNG0FK8S3JBBFYZGK1VFD", + "number": 1, + "url": "https://entire.com/et/forges/forges-fixtures/trails/1", + "title": "feat: shout greetings", + "status": "open", + "branch": "feature/shout", + "original_branch": "feature/shout", + "base": "main", + "type": "task", + "priority": "none", + "author": { + "id": "01M5WRP9RJ4GVR2PA5PCNYP1FC", + "login": "danielroe", + "identity": { + "kind": "account", + "account_id": "01M5WRP9RJ4GVR2PA5PCNYP1FC", + "display_name": "Daniel Roe", + "avatar_url": "https://avatars.githubusercontent.com/u/28706372?v=4", + "handles": [ + { + "provider": "github", + "handle": "danielroe", + "is_primary": true + } + ] + } + }, + "assignees": [ + "danielroe" + ], + "assignee_identities": [ + { + "login": "danielroe", + "identity": { + "kind": "account", + "account_id": "01M5WRP9RJ4GVR2PA5PCNYP1FC", + "display_name": "Daniel Roe", + "avatar_url": "https://avatars.githubusercontent.com/u/28706372?v=4", + "handles": [ + { + "provider": "github", + "handle": "danielroe", + "is_primary": true + } + ] + } + } + ], + "reviewers": [ + { + "login": "danielroe", + "status": "changes_requested", + "actor_account_id": "01M5WRP9RJ4GVR2PA5PCNYP1FC", + "identity": { + "kind": "account", + "account_id": "01M5WRP9RJ4GVR2PA5PCNYP1FC", + "display_name": "Daniel Roe", + "avatar_url": "https://avatars.githubusercontent.com/u/28706372?v=4", + "handles": [ + { + "provider": "github", + "handle": "danielroe", + "is_primary": true + } + ] + } + } + ], + "ready_for_review": true, + "has_code_changes": true, + "comment_count": 4, + "unresolved_count": 4, + "created_at": "2026-10-26T19:40:44.349Z", + "updated_at": "2026-10-26T19:42:13.290Z", + "merged_at": null, + "last_activity_at": "2026-10-26T19:42:13.290Z", + "phase": "reviewing", + "parent": { + "id": "01M5WVNFY1D7AHX0KJW2ANZP14", + "number": 2, + "project_id": "01M5WS0JJNP4V9AW20MZ3MKF5M", + "host": "et", + "project": "forges", + "path": "/api/v1/et/forges/trails/01M5WVNFY1D7AHX0KJW2ANZP14", + "jurisdiction": "uk", + "primary_processing_cell": "aws-eu-west-2", + "url": "https://entire.com/et/forges/-/trails/2" + }, + "branch_state": "present", + "code_changes": "present", + "lifecycle_sync": "settled", + "body_document": { + "id": "01M5WVNG4RWC7X4X51BHP5Q5M2", + "document_key": "trail:01M5WVNG0FK8S3JBBFYZGK1VFD:body", + "schema_version": 1, + "content_json": { + "type": "doc", + "content": [ + { + "type": "paragraph" + } + ] + }, + "text_snapshot": "", + "updated_at": "2026-10-26T19:40:44.349Z", + "etag": "W/\"2026-10-26T19:40:44.349281Z\"" + }, + "monitors": [], + "agents": [], + "runners": [], + "actions": { + "approve": { + "state": "enabled", + "reason": null + }, + "create_ci_pr": { + "state": "unavailable", + "reason": "not_applicable" + }, + "merge": { + "state": "blocked", + "reason": "merge_conflict" + }, + "merge_with_bypass": { + "state": "unavailable", + "reason": "merge_gates_bypass_forbidden" + }, + "update_branch": { + "state": "unavailable", + "reason": "merge_conflict" + }, + "restore_branch": { + "state": "unavailable", + "reason": "trail_not_merged" + }, + "delete_branch": { + "state": "unavailable", + "reason": "trail_not_merged" + } + }, + "mergeability": { + "delete_branch_on_merge": false, + "bypass_policy": "nobody", + "mergeable": false, + "behind_by": 1, + "comparison_status": "available", + "conflict_status": "conflicting", + "head_sha": "9ec20061f17f35212247320f525ec51d3e00c41a", + "gates": [ + { + "reviewers": [ + { + "login": "danielroe", + "actor_account_id": "01M5WRP9RJ4GVR2PA5PCNYP1FC", + "state": "changes_requested", + "reviewed_head_sha": "9ec20061f17f35212247320f525ec51d3e00c41a", + "reason": null + } + ], + "runner_ids": [], + "id": "", + "gate_definition_id": "01M5WTJP4MSACMEJ1KK4FGP2B1", + "gate_key": "approvals", + "gate_type": "approvals", + "blocking": true, + "status": "failed", + "head_sha": "9ec20061f17f35212247320f525ec51d3e00c41a", + "value": { + "approved": 0, + "changes_requested": true, + "config": { + "version": 1, + "min_reviewers": 1, + "allow_self_approval": true, + "dismiss_stale_approvals_on_push": false + }, + "required": 1, + "self_excluded": false, + "stale_dismissed": 0, + "total": 1 + }, + "rationale": "Changes have been requested", + "created_at": "2026-10-26T21:02:30.955307204Z", + "completed_at": "2026-10-26T21:02:30.955307204Z", + "state": "evaluated", + "outcome": "failed", + "stale_reason": null, + "evaluated_at_sha": "9ec20061f17f35212247320f525ec51d3e00c41a", + "finding_count": null + }, + { + "reviewers": [], + "runner_ids": [], + "id": "01M5WVQW5BHQ3CSVZJTM3595D5", + "gate_definition_id": "01M5WTJP5MDYCYNF3Z6BWN7NZ0", + "gate_key": "findings", + "gate_type": "findings", + "blocking": true, + "status": "passed", + "head_sha": "9ec20061f17f35212247320f525ec51d3e00c41a", + "value": { + "config": { + "version": 1, + "agent_findings_min_severity": "high" + }, + "reviewed_head": false, + "agent_findings": { + "low": 1, + "high": 0, + "medium": 1, + "unspecified": 0 + }, + "review_in_flight": false, + "reviewer_configured": false, + "review_grace_expired": false, + "agent_blocking_findings": 0 + }, + "rationale": "No blocking findings", + "created_at": "2026-10-26T19:42:02.411692Z", + "completed_at": "2026-10-26T19:42:02.411692Z", + "state": "evaluated", + "outcome": "passed", + "stale_reason": null, + "evaluated_at_sha": "9ec20061f17f35212247320f525ec51d3e00c41a", + "finding_count": 0 + }, + { + "reviewers": [], + "runner_ids": [], + "id": "", + "gate_definition_id": "01M5WTJP5QR0FQ7TWGE7Y3QCJC", + "gate_key": "up_to_date", + "gate_type": "up_to_date", + "blocking": true, + "status": "failed", + "head_sha": "9ec20061f17f35212247320f525ec51d3e00c41a", + "value": { + "comparison_status": "available", + "behind_by": 1, + "compare_status": "diverged", + "merge_status": "conflicting", + "config": { + "version": 1, + "allow_behind_if_mergeable": false + } + }, + "rationale": "Merge conflicts", + "created_at": "2026-10-26T19:41:42.616528Z", + "completed_at": null, + "state": "evaluated", + "outcome": "failed", + "stale_reason": null, + "evaluated_at_sha": "9ec20061f17f35212247320f525ec51d3e00c41a", + "finding_count": null + } + ], + "checks": { + "availability": "not_applicable", + "runs": [] + }, + "forge_merge_block": null + }, + "deployments": { + "availability": "available", + "ready": 0, + "total": 0, + "items": [] + }, + "config_source": "live", + "merge_base_sha": null, + "base_sha": null, + "head_sha": "9ec20061f17f35212247320f525ec51d3e00c41a" + } + } +} diff --git a/test/fixtures/entire/recorded/entire.com/steps/pull-files/golden.json b/test/fixtures/entire/recorded/entire.com/steps/pull-files/golden.json new file mode 100644 index 000000000..b33638686 --- /dev/null +++ b/test/fixtures/entire/recorded/entire.com/steps/pull-files/golden.json @@ -0,0 +1,18 @@ +{ + "items": [ + { + "path": "README.md", + "status": "modified", + "statusRaw": "modified", + "additions": 2, + "deletions": 0 + }, + { + "path": "src/greet.ts", + "status": "modified", + "statusRaw": "modified", + "additions": 3, + "deletions": 2 + } + ] +} diff --git a/test/fixtures/entire/recorded/entire.com/steps/pull-files/step.json b/test/fixtures/entire/recorded/entire.com/steps/pull-files/step.json new file mode 100644 index 000000000..7fef45b3c --- /dev/null +++ b/test/fixtures/entire/recorded/entire.com/steps/pull-files/step.json @@ -0,0 +1,4 @@ +{ + "name": "pull files", + "recordedAt": "2026-10-26T21:02:30.597Z" +} diff --git a/test/fixtures/entire/recorded/entire.com/steps/pull-getcomment/01-get-N-discussions.json b/test/fixtures/entire/recorded/entire.com/steps/pull-getcomment/01-get-N-discussions.json new file mode 100644 index 000000000..0e3836d99 --- /dev/null +++ b/test/fixtures/entire/recorded/entire.com/steps/pull-getcomment/01-get-N-discussions.json @@ -0,0 +1,433 @@ +{ + "request": { + "method": "GET", + "url": "https://aws-eu-west-2.api.entire.io/api/v1/trails/et/forges/forges-fixtures/1/discussions?include_messages=true&per_page=100" + }, + "response": { + "status": 200, + "headers": { + "link": "; rel=\"describedBy\"" + }, + "body": { + "$schema": "https://aws-eu-west-2.api.entire.io/api/v1/schemas/TrailDiscussionsListResponseBody.json", + "items": [ + { + "id": "01M5WVQW2ZPDDH5X0C5SWM3KVM", + "trail_id": "01M5WVNG0FK8S3JBBFYZGK1VFD", + "title": "`toUpperCase()` ignores the locale, so Turkish names shout incorrectly. Consider `toLocaleUpperCase()`.", + "kind": "code_review", + "resolved": false, + "resolved_by": null, + "resolved_by_identity": { + "kind": "unknown", + "account_id": null, + "display_name": null, + "avatar_url": null, + "handles": [] + }, + "resolved_at": null, + "created_by": "01M5WRP9RJ4GVR2PA5PCNYP1FC", + "created_by_identity": { + "kind": "account", + "account_id": "01M5WRP9RJ4GVR2PA5PCNYP1FC", + "display_name": "Daniel Roe", + "avatar_url": "https://avatars.githubusercontent.com/u/28706372?v=4", + "handles": [ + { + "provider": "github", + "handle": "danielroe", + "is_primary": true + } + ] + }, + "created_at": "2026-10-26T19:42:02.333Z", + "updated_at": "2026-10-26T19:42:13.290Z", + "last_message_at": "2026-10-26T19:42:13.290Z", + "last_message_author": "danielroe", + "message_count": 1, + "participants": [ + { + "login": "danielroe", + "actor_account_id": "01M5WRP9RJ4GVR2PA5PCNYP1FC", + "identity": { + "kind": "account", + "account_id": "01M5WRP9RJ4GVR2PA5PCNYP1FC", + "display_name": "Daniel Roe", + "avatar_url": "https://avatars.githubusercontent.com/u/28706372?v=4", + "handles": [ + { + "provider": "github", + "handle": "danielroe", + "is_primary": true + } + ] + } + } + ], + "review_comment_id": "01M5WVQW2ZTEEA9V72FF81J46Q", + "review_comment": { + "discussion_id": "01M5WVQW2ZPDDH5X0C5SWM3KVM", + "discussion_message_count": 1, + "id": "01M5WVQW2ZTEEA9V72FF81J46Q", + "trail_id": "01M5WVNG0FK8S3JBBFYZGK1VFD", + "repo_id": "01M5WS0P331VQ3AARB26Z9DGV7", + "review_id": "01M5WVQNQSS4DQNQB5Z00WA4V7", + "code_version_id": "01M5WVQNQG83V6VQT17G0M6DBJ", + "actor_id": "01M5WRP9RJ4GVR2PA5PCNYP1FC", + "actor_display_name": "danielroe", + "actor_identity": { + "kind": "account", + "account_id": "01M5WRP9RJ4GVR2PA5PCNYP1FC", + "display_name": "Daniel Roe", + "avatar_url": "https://avatars.githubusercontent.com/u/28706372?v=4", + "handles": [ + { + "provider": "github", + "handle": "danielroe", + "is_primary": true + } + ] + }, + "body": "`toUpperCase()` ignores the locale, so Turkish names shout incorrectly. Consider `toLocaleUpperCase()`.", + "severity": "low", + "confidence": null, + "status": "open", + "status_reason": null, + "status_actor_id": null, + "status_actor_display_name": null, + "status_actor_identity": { + "kind": "unknown", + "account_id": null, + "display_name": null, + "avatar_url": null, + "handles": [] + }, + "status_changed_at": null, + "status_source": null, + "status_actor_kind": null, + "stale_outcome": "current", + "stale_checked_at": null, + "stale_checked_code_version_id": null, + "client_id": "shout-case", + "client_id_hash": "ea05e251d04f3b2e1dbf616445b14d9faba65c96f60b955c61a748fb186cd26d", + "created_at": "2026-10-26T19:42:02.333Z", + "updated_at": "2026-10-26T19:42:02.333Z", + "location": { + "id": "01M5WVQW2Z3NCP4Y284CQ5DE3Y", + "review_comment_id": "01M5WVQW2ZTEEA9V72FF81J46Q", + "code_version_id": "01M5WVQNQG83V6VQT17G0M6DBJ", + "granularity": "line", + "file_path": "src/greet.ts", + "start_line": 3, + "start_column": null, + "end_line": 3, + "end_column": null, + "selected_text": " return options.shout ? greeting.toUpperCase() : greeting", + "nearby_text": null, + "language": null + } + }, + "messages": [ + { + "id": "01M5WVR6SAXG323XBRAH7G0Q3V", + "author": "danielroe", + "identity": { + "kind": "account", + "account_id": "01M5WRP9RJ4GVR2PA5PCNYP1FC", + "display_name": "Daniel Roe", + "avatar_url": "https://avatars.githubusercontent.com/u/28706372?v=4", + "handles": [ + { + "provider": "github", + "handle": "danielroe", + "is_primary": true + } + ] + }, + "created_at": "2026-10-26T19:42:13.290Z", + "body": "Good catch, switching to `toLocaleUpperCase()`.", + "replies": [] + } + ] + }, + { + "id": "01M5WVQW42CZ9N82B1QV6B6GTP", + "trail_id": "01M5WVNG0FK8S3JBBFYZGK1VFD", + "title": "No tests cover the `shout` option.", + "kind": "code_review", + "resolved": false, + "resolved_by": null, + "resolved_by_identity": { + "kind": "unknown", + "account_id": null, + "display_name": null, + "avatar_url": null, + "handles": [] + }, + "resolved_at": null, + "created_by": "01M5WRP9RJ4GVR2PA5PCNYP1FC", + "created_by_identity": { + "kind": "account", + "account_id": "01M5WRP9RJ4GVR2PA5PCNYP1FC", + "display_name": "Daniel Roe", + "avatar_url": "https://avatars.githubusercontent.com/u/28706372?v=4", + "handles": [ + { + "provider": "github", + "handle": "danielroe", + "is_primary": true + } + ] + }, + "created_at": "2026-10-26T19:42:02.368Z", + "updated_at": "2026-10-26T19:42:02.368Z", + "last_message_at": null, + "last_message_author": null, + "message_count": 0, + "participants": [], + "review_comment_id": "01M5WVQW423TPZGYYS4025JBCT", + "review_comment": { + "discussion_id": "01M5WVQW42CZ9N82B1QV6B6GTP", + "discussion_message_count": 0, + "id": "01M5WVQW423TPZGYYS4025JBCT", + "trail_id": "01M5WVNG0FK8S3JBBFYZGK1VFD", + "repo_id": "01M5WS0P331VQ3AARB26Z9DGV7", + "review_id": "01M5WVQNQSS4DQNQB5Z00WA4V7", + "code_version_id": "01M5WVQNQG83V6VQT17G0M6DBJ", + "actor_id": "01M5WRP9RJ4GVR2PA5PCNYP1FC", + "actor_display_name": "danielroe", + "actor_identity": { + "kind": "account", + "account_id": "01M5WRP9RJ4GVR2PA5PCNYP1FC", + "display_name": "Daniel Roe", + "avatar_url": "https://avatars.githubusercontent.com/u/28706372?v=4", + "handles": [ + { + "provider": "github", + "handle": "danielroe", + "is_primary": true + } + ] + }, + "body": "No tests cover the `shout` option.", + "severity": "medium", + "confidence": null, + "status": "open", + "status_reason": null, + "status_actor_id": null, + "status_actor_display_name": null, + "status_actor_identity": { + "kind": "unknown", + "account_id": null, + "display_name": null, + "avatar_url": null, + "handles": [] + }, + "status_changed_at": null, + "status_source": null, + "status_actor_kind": null, + "stale_outcome": "current", + "stale_checked_at": null, + "stale_checked_code_version_id": null, + "client_id": "whole", + "client_id_hash": "a00f6d308f3eb66bbf8828200158393d01575a3bfc9f750bacf1b11ed8d9430a", + "created_at": "2026-10-26T19:42:02.368Z", + "updated_at": "2026-10-26T19:42:02.368Z", + "location": { + "id": "01M5WVQW42ER5GPTS4JM719TDV", + "review_comment_id": "01M5WVQW423TPZGYYS4025JBCT", + "code_version_id": "01M5WVQNQG83V6VQT17G0M6DBJ", + "granularity": "whole_change", + "file_path": null, + "start_line": null, + "start_column": null, + "end_line": null, + "end_column": null, + "selected_text": null, + "nearby_text": null, + "language": null + } + }, + "messages": [] + }, + { + "id": "01M5WVP9QKVVQWQQWRFW4K3T94", + "trail_id": "01M5WVNG0FK8S3JBBFYZGK1VFD", + "title": "Naming", + "kind": "discussion", + "resolved": false, + "resolved_by": null, + "resolved_by_identity": { + "kind": "unknown", + "account_id": null, + "display_name": null, + "avatar_url": null, + "handles": [] + }, + "resolved_at": null, + "created_by": "01M5WRP9RJ4GVR2PA5PCNYP1FC", + "created_by_identity": { + "kind": "account", + "account_id": "01M5WRP9RJ4GVR2PA5PCNYP1FC", + "display_name": "Daniel Roe", + "avatar_url": "https://avatars.githubusercontent.com/u/28706372?v=4", + "handles": [ + { + "provider": "github", + "handle": "danielroe", + "is_primary": true + } + ] + }, + "created_at": "2026-10-26T19:41:10.771Z", + "updated_at": "2026-10-26T19:41:10.771Z", + "last_message_at": "2026-10-26T19:41:10.771Z", + "last_message_author": "danielroe", + "message_count": 1, + "participants": [ + { + "login": "danielroe", + "actor_account_id": "01M5WRP9RJ4GVR2PA5PCNYP1FC", + "identity": { + "kind": "account", + "account_id": "01M5WRP9RJ4GVR2PA5PCNYP1FC", + "display_name": "Daniel Roe", + "avatar_url": "https://avatars.githubusercontent.com/u/28706372?v=4", + "handles": [ + { + "provider": "github", + "handle": "danielroe", + "is_primary": true + } + ] + } + } + ], + "review_comment_id": null, + "review_comment": null, + "messages": [ + { + "id": "01M5WVP9QQB7HMVGA0SRF76KED", + "author": "danielroe", + "identity": { + "kind": "account", + "account_id": "01M5WRP9RJ4GVR2PA5PCNYP1FC", + "display_name": "Daniel Roe", + "avatar_url": "https://avatars.githubusercontent.com/u/28706372?v=4", + "handles": [ + { + "provider": "github", + "handle": "danielroe", + "is_primary": true + } + ] + }, + "created_at": "2026-10-26T19:41:10.771Z", + "body": "`shout` or `loud`? I lean towards `shout`.", + "replies": [] + } + ] + }, + { + "id": "01M5WVP84KN3H6SFHM77XGN8WE", + "trail_id": "01M5WVNG0FK8S3JBBFYZGK1VFD", + "title": "Should `shout` also add an exclamation mark?", + "kind": "discussion", + "resolved": false, + "resolved_by": null, + "resolved_by_identity": { + "kind": "unknown", + "account_id": null, + "display_name": null, + "avatar_url": null, + "handles": [] + }, + "resolved_at": null, + "created_by": "01M5WRP9RJ4GVR2PA5PCNYP1FC", + "created_by_identity": { + "kind": "account", + "account_id": "01M5WRP9RJ4GVR2PA5PCNYP1FC", + "display_name": "Daniel Roe", + "avatar_url": "https://avatars.githubusercontent.com/u/28706372?v=4", + "handles": [ + { + "provider": "github", + "handle": "danielroe", + "is_primary": true + } + ] + }, + "created_at": "2026-10-26T19:41:09.139Z", + "updated_at": "2026-10-26T19:41:09.989Z", + "last_message_at": "2026-10-26T19:41:09.989Z", + "last_message_author": "danielroe", + "message_count": 2, + "participants": [ + { + "login": "danielroe", + "actor_account_id": "01M5WRP9RJ4GVR2PA5PCNYP1FC", + "identity": { + "kind": "account", + "account_id": "01M5WRP9RJ4GVR2PA5PCNYP1FC", + "display_name": "Daniel Roe", + "avatar_url": "https://avatars.githubusercontent.com/u/28706372?v=4", + "handles": [ + { + "provider": "github", + "handle": "danielroe", + "is_primary": true + } + ] + } + } + ], + "review_comment_id": null, + "review_comment": null, + "messages": [ + { + "id": "01M5WVP8552KBGTR9NZCXY91QQ", + "author": "danielroe", + "identity": { + "kind": "account", + "account_id": "01M5WRP9RJ4GVR2PA5PCNYP1FC", + "display_name": "Daniel Roe", + "avatar_url": "https://avatars.githubusercontent.com/u/28706372?v=4", + "handles": [ + { + "provider": "github", + "handle": "danielroe", + "is_primary": true + } + ] + }, + "created_at": "2026-10-26T19:41:09.139Z", + "body": "Should `shout` also add an exclamation mark?", + "replies": [] + }, + { + "id": "01M5WVP8Z53BEF7ZA2WFQ2RQAX", + "author": "danielroe", + "identity": { + "kind": "account", + "account_id": "01M5WRP9RJ4GVR2PA5PCNYP1FC", + "display_name": "Daniel Roe", + "avatar_url": "https://avatars.githubusercontent.com/u/28706372?v=4", + "handles": [ + { + "provider": "github", + "handle": "danielroe", + "is_primary": true + } + ] + }, + "created_at": "2026-10-26T19:41:09.989Z", + "body": "I think it reads fine without one.", + "replies": [] + } + ] + } + ], + "event_cursor": "4" + } + } +} diff --git a/test/fixtures/entire/recorded/entire.com/steps/pull-getcomment/golden.json b/test/fixtures/entire/recorded/entire.com/steps/pull-getcomment/golden.json new file mode 100644 index 000000000..6725b792a --- /dev/null +++ b/test/fixtures/entire/recorded/entire.com/steps/pull-getcomment/golden.json @@ -0,0 +1,34 @@ +{ + "ref": { + "forge": "entire", + "instance": "entire.com", + "thread": { + "forge": "entire", + "instance": "entire.com", + "repo": { + "forge": "entire", + "instance": "entire.com", + "owner": "forges", + "name": "forges-fixtures" + }, + "kind": "pull_request", + "number": "1" + }, + "id": "01M5WVP8552KBGTR9NZCXY91QQ" + }, + "body": "Should `shout` also add an exclamation mark?", + "author": { + "forge": "entire", + "instance": "entire.com", + "login": "danielroe", + "id": "01M5WRP9RJ4GVR2PA5PCNYP1FC", + "name": "Daniel Roe", + "avatarUrl": "https://avatars.githubusercontent.com/u/28706372?v=4", + "isBotHint": false + }, + "createdAt": "", + "thread": { + "id": "01M5WVP84KN3H6SFHM77XGN8WE", + "resolved": false + } +} diff --git a/test/fixtures/entire/recorded/entire.com/steps/pull-getcomment/step.json b/test/fixtures/entire/recorded/entire.com/steps/pull-getcomment/step.json new file mode 100644 index 000000000..cba5322c4 --- /dev/null +++ b/test/fixtures/entire/recorded/entire.com/steps/pull-getcomment/step.json @@ -0,0 +1,7 @@ +{ + "name": "pull getComment", + "recordedAt": "2026-10-26T19:57:15.120Z", + "needs": [ + "pull comments" + ] +} diff --git a/test/fixtures/entire/recorded/entire.com/steps/pull-getmany/01-get-trails-01M5WVNFY1D7AHX0KJW2ANZP14.json b/test/fixtures/entire/recorded/entire.com/steps/pull-getmany/01-get-trails-01M5WVNFY1D7AHX0KJW2ANZP14.json new file mode 100644 index 000000000..1dfbfb50b --- /dev/null +++ b/test/fixtures/entire/recorded/entire.com/steps/pull-getmany/01-get-trails-01M5WVNFY1D7AHX0KJW2ANZP14.json @@ -0,0 +1,153 @@ +{ + "request": { + "method": "GET", + "url": "https://aws-eu-west-2.api.entire.io/api/v1/et/forges/trails/01M5WVNFY1D7AHX0KJW2ANZP14" + }, + "response": { + "status": 200, + "headers": { + "link": "; rel=\"describedBy\"", + "etag": "W/\"2026-10-26T19:40:44.561257Z\"" + }, + "body": { + "$schema": "https://aws-eu-west-2.api.entire.io/api/v1/schemas/TrailResponse.json", + "capabilities": { + "canEdit": true, + "canManageScope": true + }, + "project": { + "primaryProcessingCell": "aws-eu-west-2", + "id": "01M5WS0JJNP4V9AW20MZ3MKF5M", + "name": "forges", + "provider": "entire", + "reference": { + "forge": "et", + "project": "forges" + }, + "jurisdiction": "uk", + "capabilities": { + "canManageTrails": true + } + }, + "author": { + "accountId": "01M5WRP9RJ4GVR2PA5PCNYP1FC", + "login": "danielroe", + "displayName": "Daniel Roe", + "avatarUrl": "https://avatars.githubusercontent.com/u/28706372?v=4", + "identity": { + "kind": "account", + "account_id": "01M5WRP9RJ4GVR2PA5PCNYP1FC", + "display_name": "Daniel Roe", + "avatar_url": "https://avatars.githubusercontent.com/u/28706372?v=4", + "handles": [ + { + "provider": "github", + "handle": "danielroe", + "is_primary": true + } + ] + } + }, + "id": "01M5WVNFY1D7AHX0KJW2ANZP14", + "projectId": "01M5WS0JJNP4V9AW20MZ3MKF5M", + "number": 2, + "url": "https://entire.com/et/forges/-/trails/2", + "title": "Shout greetings", + "body": "Adds a `shout` option to `greet()`.", + "bodyDocument": { + "id": "", + "document_key": "project-trail:01M5WVNFY1D7AHX0KJW2ANZP14:body", + "schema_version": 1, + "content_json": { + "type": "doc", + "content": [ + { + "type": "paragraph", + "content": [ + { + "type": "text", + "text": "Adds a " + }, + { + "type": "text", + "marks": [ + { + "type": "code" + } + ], + "text": "shout" + }, + { + "type": "text", + "text": " option to " + }, + { + "type": "text", + "marks": [ + { + "type": "code" + } + ], + "text": "greet()" + }, + { + "type": "text", + "text": "." + } + ] + } + ] + }, + "text_snapshot": "Adds a shout option to greet().", + "updated_at": "2026-10-26T19:40:44.561Z", + "etag": "" + }, + "status": "open", + "phase": "building", + "metadata": {}, + "type": "feature", + "priority": "medium", + "assignees": [], + "assigneeAccountIds": [], + "repoIds": [ + "01M5WS0P331VQ3AARB26Z9DGV7" + ], + "authorAccountId": "01M5WRP9RJ4GVR2PA5PCNYP1FC", + "createdAt": "2026-10-26T19:40:44.349Z", + "metadataUpdatedAt": "2026-10-26T19:40:44.561Z", + "closedAt": null, + "lastVisitedAt": null, + "lastActivityAt": "2026-10-26T19:42:13.290Z", + "changes": [ + { + "id": "01M5WVNG0FK8S3JBBFYZGK1VFD", + "repositoryId": "01M5WS0P331VQ3AARB26Z9DGV7", + "repository": "forges-fixtures", + "branch": "feature/shout", + "originalBranch": "feature/shout", + "base": "main", + "number": 1, + "title": "feat: shout greetings", + "status": "open", + "hasCodeChanges": true, + "createdAt": "2026-10-26T19:40:44.349Z", + "updatedAt": "2026-10-26T19:42:13.290Z", + "lastActivityAt": "2026-10-26T19:42:13.290Z", + "deployments": { + "availability": "available", + "ready": 0, + "total": 0 + }, + "readiness": "in_review", + "mergeability": { + "conflict_status": "unknown", + "head_sha": "", + "refreshed_at": null, + "forge_merge_block": null + } + } + ], + "isPossiblyPartial": true + } + } +} diff --git a/test/fixtures/entire/recorded/entire.com/steps/pull-getmany/02-get-forges-fixtures-N.json b/test/fixtures/entire/recorded/entire.com/steps/pull-getmany/02-get-forges-fixtures-N.json new file mode 100644 index 000000000..a5eb6b48d --- /dev/null +++ b/test/fixtures/entire/recorded/entire.com/steps/pull-getmany/02-get-forges-fixtures-N.json @@ -0,0 +1,287 @@ +{ + "request": { + "method": "GET", + "url": "https://aws-eu-west-2.api.entire.io/api/v1/trails/et/forges/forges-fixtures/1" + }, + "response": { + "status": 200, + "headers": { + "link": "; rel=\"describedBy\"" + }, + "body": { + "$schema": "https://aws-eu-west-2.api.entire.io/api/v1/schemas/TrailDetailResponse.json", + "id": "01M5WVNG0FK8S3JBBFYZGK1VFD", + "number": 1, + "url": "https://entire.com/et/forges/forges-fixtures/trails/1", + "title": "feat: shout greetings", + "status": "open", + "branch": "feature/shout", + "original_branch": "feature/shout", + "base": "main", + "type": "task", + "priority": "none", + "author": { + "id": "01M5WRP9RJ4GVR2PA5PCNYP1FC", + "login": "danielroe", + "identity": { + "kind": "account", + "account_id": "01M5WRP9RJ4GVR2PA5PCNYP1FC", + "display_name": "Daniel Roe", + "avatar_url": "https://avatars.githubusercontent.com/u/28706372?v=4", + "handles": [ + { + "provider": "github", + "handle": "danielroe", + "is_primary": true + } + ] + } + }, + "assignees": [ + "danielroe" + ], + "assignee_identities": [ + { + "login": "danielroe", + "identity": { + "kind": "account", + "account_id": "01M5WRP9RJ4GVR2PA5PCNYP1FC", + "display_name": "Daniel Roe", + "avatar_url": "https://avatars.githubusercontent.com/u/28706372?v=4", + "handles": [ + { + "provider": "github", + "handle": "danielroe", + "is_primary": true + } + ] + } + } + ], + "reviewers": [ + { + "login": "danielroe", + "status": "changes_requested", + "actor_account_id": "01M5WRP9RJ4GVR2PA5PCNYP1FC", + "identity": { + "kind": "account", + "account_id": "01M5WRP9RJ4GVR2PA5PCNYP1FC", + "display_name": "Daniel Roe", + "avatar_url": "https://avatars.githubusercontent.com/u/28706372?v=4", + "handles": [ + { + "provider": "github", + "handle": "danielroe", + "is_primary": true + } + ] + } + } + ], + "ready_for_review": true, + "has_code_changes": true, + "comment_count": 4, + "unresolved_count": 4, + "created_at": "2026-10-26T19:40:44.349Z", + "updated_at": "2026-10-26T19:42:13.290Z", + "merged_at": null, + "last_activity_at": "2026-10-26T19:42:13.290Z", + "phase": "reviewing", + "parent": { + "id": "01M5WVNFY1D7AHX0KJW2ANZP14", + "number": 2, + "project_id": "01M5WS0JJNP4V9AW20MZ3MKF5M", + "host": "et", + "project": "forges", + "path": "/api/v1/et/forges/trails/01M5WVNFY1D7AHX0KJW2ANZP14", + "jurisdiction": "uk", + "primary_processing_cell": "aws-eu-west-2", + "url": "https://entire.com/et/forges/-/trails/2" + }, + "branch_state": "present", + "code_changes": "present", + "lifecycle_sync": "settled", + "body_document": { + "id": "01M5WVNG4RWC7X4X51BHP5Q5M2", + "document_key": "trail:01M5WVNG0FK8S3JBBFYZGK1VFD:body", + "schema_version": 1, + "content_json": { + "type": "doc", + "content": [ + { + "type": "paragraph" + } + ] + }, + "text_snapshot": "", + "updated_at": "2026-10-26T19:40:44.349Z", + "etag": "W/\"2026-10-26T19:40:44.349281Z\"" + }, + "monitors": [], + "agents": [], + "runners": [], + "actions": { + "approve": { + "state": "enabled", + "reason": null + }, + "create_ci_pr": { + "state": "unavailable", + "reason": "not_applicable" + }, + "merge": { + "state": "blocked", + "reason": "merge_conflict" + }, + "merge_with_bypass": { + "state": "unavailable", + "reason": "merge_gates_bypass_forbidden" + }, + "update_branch": { + "state": "unavailable", + "reason": "merge_conflict" + }, + "restore_branch": { + "state": "unavailable", + "reason": "trail_not_merged" + }, + "delete_branch": { + "state": "unavailable", + "reason": "trail_not_merged" + } + }, + "mergeability": { + "delete_branch_on_merge": false, + "bypass_policy": "nobody", + "mergeable": false, + "behind_by": 1, + "comparison_status": "available", + "conflict_status": "conflicting", + "head_sha": "9ec20061f17f35212247320f525ec51d3e00c41a", + "gates": [ + { + "reviewers": [ + { + "login": "danielroe", + "actor_account_id": "01M5WRP9RJ4GVR2PA5PCNYP1FC", + "state": "changes_requested", + "reviewed_head_sha": "9ec20061f17f35212247320f525ec51d3e00c41a", + "reason": null + } + ], + "runner_ids": [], + "id": "", + "gate_definition_id": "01M5WTJP4MSACMEJ1KK4FGP2B1", + "gate_key": "approvals", + "gate_type": "approvals", + "blocking": true, + "status": "failed", + "head_sha": "9ec20061f17f35212247320f525ec51d3e00c41a", + "value": { + "approved": 0, + "changes_requested": true, + "config": { + "version": 1, + "min_reviewers": 1, + "allow_self_approval": true, + "dismiss_stale_approvals_on_push": false + }, + "required": 1, + "self_excluded": false, + "stale_dismissed": 0, + "total": 1 + }, + "rationale": "Changes have been requested", + "created_at": "2026-10-26T21:02:28.033199186Z", + "completed_at": "2026-10-26T21:02:28.033199186Z", + "state": "evaluated", + "outcome": "failed", + "stale_reason": null, + "evaluated_at_sha": "9ec20061f17f35212247320f525ec51d3e00c41a", + "finding_count": null + }, + { + "reviewers": [], + "runner_ids": [], + "id": "01M5WVQW5BHQ3CSVZJTM3595D5", + "gate_definition_id": "01M5WTJP5MDYCYNF3Z6BWN7NZ0", + "gate_key": "findings", + "gate_type": "findings", + "blocking": true, + "status": "passed", + "head_sha": "9ec20061f17f35212247320f525ec51d3e00c41a", + "value": { + "config": { + "version": 1, + "agent_findings_min_severity": "high" + }, + "reviewed_head": false, + "agent_findings": { + "low": 1, + "high": 0, + "medium": 1, + "unspecified": 0 + }, + "review_in_flight": false, + "reviewer_configured": false, + "review_grace_expired": false, + "agent_blocking_findings": 0 + }, + "rationale": "No blocking findings", + "created_at": "2026-10-26T19:42:02.411692Z", + "completed_at": "2026-10-26T19:42:02.411692Z", + "state": "evaluated", + "outcome": "passed", + "stale_reason": null, + "evaluated_at_sha": "9ec20061f17f35212247320f525ec51d3e00c41a", + "finding_count": 0 + }, + { + "reviewers": [], + "runner_ids": [], + "id": "", + "gate_definition_id": "01M5WTJP5QR0FQ7TWGE7Y3QCJC", + "gate_key": "up_to_date", + "gate_type": "up_to_date", + "blocking": true, + "status": "failed", + "head_sha": "9ec20061f17f35212247320f525ec51d3e00c41a", + "value": { + "comparison_status": "available", + "behind_by": 1, + "compare_status": "diverged", + "merge_status": "conflicting", + "config": { + "version": 1, + "allow_behind_if_mergeable": false + } + }, + "rationale": "Merge conflicts", + "created_at": "2026-10-26T19:41:42.616528Z", + "completed_at": null, + "state": "evaluated", + "outcome": "failed", + "stale_reason": null, + "evaluated_at_sha": "9ec20061f17f35212247320f525ec51d3e00c41a", + "finding_count": null + } + ], + "checks": { + "availability": "not_applicable", + "runs": [] + }, + "forge_merge_block": null + }, + "deployments": { + "availability": "available", + "ready": 0, + "total": 0, + "items": [] + }, + "config_source": "live", + "merge_base_sha": null, + "base_sha": null, + "head_sha": "9ec20061f17f35212247320f525ec51d3e00c41a" + } + } +} diff --git a/test/fixtures/entire/recorded/entire.com/steps/pull-getmany/golden.json b/test/fixtures/entire/recorded/entire.com/steps/pull-getmany/golden.json new file mode 100644 index 000000000..26f5d44e2 --- /dev/null +++ b/test/fixtures/entire/recorded/entire.com/steps/pull-getmany/golden.json @@ -0,0 +1,94 @@ +[ + { + "ok": true, + "ref": { + "forge": "entire", + "instance": "entire.com", + "repo": { + "forge": "entire", + "instance": "entire.com", + "owner": "forges", + "name": "forges-fixtures" + }, + "kind": "pull_request", + "number": "1" + }, + "thread": { + "ref": { + "forge": "entire", + "instance": "entire.com", + "repo": { + "forge": "entire", + "instance": "entire.com", + "owner": "forges", + "name": "forges-fixtures" + }, + "kind": "pull_request", + "number": "1", + "externalId": "01M5WVNG0FK8S3JBBFYZGK1VFD" + }, + "kind": "pull_request", + "title": "feat: shout greetings", + "body": "Adds a `shout` option to `greet()`.", + "state": "open", + "stateRaw": "open", + "isDraft": false, + "author": { + "forge": "entire", + "instance": "entire.com", + "login": "danielroe", + "id": "01M5WRP9RJ4GVR2PA5PCNYP1FC", + "name": "Daniel Roe", + "avatarUrl": "https://avatars.githubusercontent.com/u/28706372?v=4", + "isBotHint": false + }, + "assignees": [ + { + "forge": "entire", + "instance": "entire.com", + "login": "danielroe", + "id": "01M5WRP9RJ4GVR2PA5PCNYP1FC", + "name": "Daniel Roe", + "avatarUrl": "https://avatars.githubusercontent.com/u/28706372?v=4", + "isBotHint": false + } + ], + "reviewers": [ + { + "actor": { + "forge": "entire", + "instance": "entire.com", + "login": "danielroe", + "id": "01M5WRP9RJ4GVR2PA5PCNYP1FC", + "name": "Daniel Roe", + "avatarUrl": "https://avatars.githubusercontent.com/u/28706372?v=4", + "isBotHint": false + }, + "state": "changes_requested", + "stateRaw": "changes_requested" + } + ], + "labels": [], + "url": "https://entire.com/et/forges/forges-fixtures/trails/1", + "createdAt": "2026-10-26T19:40:44.349Z", + "updatedAt": "2026-10-26T19:42:13.290Z", + "lastActivityAt": "2026-10-26T19:42:13.290Z", + "commentCount": 4, + "branches": { + "head": { + "ref": "feature/shout", + "sha": "9ec20061f17f35212247320f525ec51d3e00c41a", + "repo": { + "forge": "entire", + "instance": "entire.com", + "owner": "forges", + "name": "forges-fixtures" + } + }, + "base": { + "ref": "main" + } + } + } + } +] diff --git a/test/fixtures/entire/recorded/entire.com/steps/pull-getmany/step.json b/test/fixtures/entire/recorded/entire.com/steps/pull-getmany/step.json new file mode 100644 index 000000000..45e9f3763 --- /dev/null +++ b/test/fixtures/entire/recorded/entire.com/steps/pull-getmany/step.json @@ -0,0 +1,4 @@ +{ + "name": "pull getMany", + "recordedAt": "2026-10-26T21:02:27.854Z" +} diff --git a/test/fixtures/entire/recorded/entire.com/steps/pull-getreview/01-get-N-approvals.json b/test/fixtures/entire/recorded/entire.com/steps/pull-getreview/01-get-N-approvals.json new file mode 100644 index 000000000..c9882402d --- /dev/null +++ b/test/fixtures/entire/recorded/entire.com/steps/pull-getreview/01-get-N-approvals.json @@ -0,0 +1,25 @@ +{ + "request": { + "method": "GET", + "url": "https://aws-eu-west-2.api.entire.io/api/v1/trails/et/forges/forges-fixtures/1/approvals" + }, + "response": { + "status": 200, + "headers": { + "link": "; rel=\"describedBy\"" + }, + "body": { + "$schema": "https://aws-eu-west-2.api.entire.io/api/v1/schemas/TrailApprovalsResponse.json", + "approvals": [ + { + "id": "01M5WVPQ2KX1QCY97NEWDQWTB8", + "author": "danielroe", + "event": "changes_requested", + "body": "Please add a test for shouting.", + "commit_sha": "9ec20061f17f35212247320f525ec51d3e00c41a", + "created_at": "2026-10-26T19:41:24.435414047Z" + } + ] + } + } +} diff --git a/test/fixtures/entire/recorded/entire.com/steps/pull-getreview/golden.json b/test/fixtures/entire/recorded/entire.com/steps/pull-getreview/golden.json new file mode 100644 index 000000000..2d26fe527 --- /dev/null +++ b/test/fixtures/entire/recorded/entire.com/steps/pull-getreview/golden.json @@ -0,0 +1,31 @@ +{ + "ref": { + "forge": "entire", + "instance": "entire.com", + "thread": { + "forge": "entire", + "instance": "entire.com", + "repo": { + "forge": "entire", + "instance": "entire.com", + "owner": "forges", + "name": "forges-fixtures" + }, + "kind": "pull_request", + "number": "1" + }, + "id": "01M5WVPQ2KX1QCY97NEWDQWTB8" + }, + "author": { + "forge": "entire", + "instance": "entire.com", + "login": "danielroe", + "id": "danielroe", + "isBotHint": false + }, + "state": "changes_requested", + "stateRaw": "changes_requested", + "body": "Please add a test for shouting.", + "submittedAt": "2026-10-26T19:41:24.435Z", + "comments": false +} diff --git a/test/fixtures/entire/recorded/entire.com/steps/pull-getreview/step.json b/test/fixtures/entire/recorded/entire.com/steps/pull-getreview/step.json new file mode 100644 index 000000000..bc2f1ef1c --- /dev/null +++ b/test/fixtures/entire/recorded/entire.com/steps/pull-getreview/step.json @@ -0,0 +1,7 @@ +{ + "name": "pull getReview", + "recordedAt": "2026-10-26T21:02:30.137Z", + "needs": [ + "pull reviews" + ] +} diff --git a/test/fixtures/entire/recorded/entire.com/steps/pull-list/01-get-forges-forges-fixtures.json b/test/fixtures/entire/recorded/entire.com/steps/pull-list/01-get-forges-forges-fixtures.json new file mode 100644 index 000000000..9034fff80 --- /dev/null +++ b/test/fixtures/entire/recorded/entire.com/steps/pull-list/01-get-forges-forges-fixtures.json @@ -0,0 +1,108 @@ +{ + "request": { + "method": "GET", + "url": "https://aws-eu-west-2.api.entire.io/api/v1/trails/et/forges/forges-fixtures?status=open&per_page=3" + }, + "response": { + "status": 200, + "headers": { + "link": "; rel=\"describedBy\"" + }, + "body": { + "$schema": "https://aws-eu-west-2.api.entire.io/api/v1/schemas/TrailsListResponse.json", + "items": [ + { + "id": "01M5WVNG0FK8S3JBBFYZGK1VFD", + "number": 1, + "url": "https://entire.com/et/forges/forges-fixtures/trails/1", + "title": "feat: shout greetings", + "status": "open", + "branch": "feature/shout", + "original_branch": "feature/shout", + "base": "main", + "type": "task", + "priority": "none", + "author": { + "id": "01M5WRP9RJ4GVR2PA5PCNYP1FC", + "login": "danielroe", + "identity": { + "kind": "account", + "account_id": "01M5WRP9RJ4GVR2PA5PCNYP1FC", + "display_name": "Daniel Roe", + "avatar_url": "https://avatars.githubusercontent.com/u/28706372?v=4", + "handles": [ + { + "provider": "github", + "handle": "danielroe", + "is_primary": true + } + ] + } + }, + "assignees": [ + "danielroe" + ], + "assignee_identities": [ + { + "login": "danielroe", + "identity": { + "kind": "account", + "account_id": "01M5WRP9RJ4GVR2PA5PCNYP1FC", + "display_name": "Daniel Roe", + "avatar_url": "https://avatars.githubusercontent.com/u/28706372?v=4", + "handles": [ + { + "provider": "github", + "handle": "danielroe", + "is_primary": true + } + ] + } + } + ], + "reviewers": [ + { + "login": "danielroe", + "status": "changes_requested", + "actor_account_id": "01M5WRP9RJ4GVR2PA5PCNYP1FC", + "identity": { + "kind": "account", + "account_id": "01M5WRP9RJ4GVR2PA5PCNYP1FC", + "display_name": "Daniel Roe", + "avatar_url": "https://avatars.githubusercontent.com/u/28706372?v=4", + "handles": [ + { + "provider": "github", + "handle": "danielroe", + "is_primary": true + } + ] + } + } + ], + "ready_for_review": true, + "has_code_changes": true, + "comment_count": 4, + "unresolved_count": 4, + "created_at": "2026-10-26T19:40:44.349Z", + "updated_at": "2026-10-26T19:42:13.290Z", + "merged_at": null, + "last_activity_at": "2026-10-26T19:42:13.290Z", + "phase": "reviewing", + "parent": { + "id": "01M5WVNFY1D7AHX0KJW2ANZP14", + "number": 2, + "project_id": "01M5WS0JJNP4V9AW20MZ3MKF5M", + "host": "et", + "project": "forges", + "path": "/api/v1/et/forges/trails/01M5WVNFY1D7AHX0KJW2ANZP14", + "jurisdiction": "uk", + "primary_processing_cell": "aws-eu-west-2", + "url": "https://entire.com/et/forges/-/trails/2" + } + } + ], + "total_count": 1 + } + } +} diff --git a/test/fixtures/entire/recorded/entire.com/steps/pull-list/golden.json b/test/fixtures/entire/recorded/entire.com/steps/pull-list/golden.json new file mode 100644 index 000000000..592ce42cb --- /dev/null +++ b/test/fixtures/entire/recorded/entire.com/steps/pull-list/golden.json @@ -0,0 +1,80 @@ +{ + "items": [ + { + "ref": { + "forge": "entire", + "instance": "entire.com", + "repo": { + "forge": "entire", + "instance": "entire.com", + "owner": "forges", + "name": "forges-fixtures" + }, + "kind": "pull_request", + "number": "1", + "externalId": "01M5WVNG0FK8S3JBBFYZGK1VFD" + }, + "kind": "pull_request", + "title": "feat: shout greetings", + "state": "open", + "stateRaw": "open", + "isDraft": false, + "author": { + "forge": "entire", + "instance": "entire.com", + "login": "danielroe", + "id": "01M5WRP9RJ4GVR2PA5PCNYP1FC", + "name": "Daniel Roe", + "avatarUrl": "https://avatars.githubusercontent.com/u/28706372?v=4", + "isBotHint": false + }, + "assignees": [ + { + "forge": "entire", + "instance": "entire.com", + "login": "danielroe", + "id": "01M5WRP9RJ4GVR2PA5PCNYP1FC", + "name": "Daniel Roe", + "avatarUrl": "https://avatars.githubusercontent.com/u/28706372?v=4", + "isBotHint": false + } + ], + "reviewers": [ + { + "actor": { + "forge": "entire", + "instance": "entire.com", + "login": "danielroe", + "id": "01M5WRP9RJ4GVR2PA5PCNYP1FC", + "name": "Daniel Roe", + "avatarUrl": "https://avatars.githubusercontent.com/u/28706372?v=4", + "isBotHint": false + }, + "state": "changes_requested", + "stateRaw": "changes_requested" + } + ], + "labels": [], + "url": "https://entire.com/et/forges/forges-fixtures/trails/1", + "createdAt": "", + "updatedAt": "", + "lastActivityAt": "", + "commentCount": 4, + "branches": { + "head": { + "ref": "feature/shout", + "repo": { + "forge": "entire", + "instance": "entire.com", + "owner": "forges", + "name": "forges-fixtures" + } + }, + "base": { + "ref": "main" + } + } + } + ], + "total": 1 +} diff --git a/test/fixtures/entire/recorded/entire.com/steps/pull-list/step.json b/test/fixtures/entire/recorded/entire.com/steps/pull-list/step.json new file mode 100644 index 000000000..892d09ffa --- /dev/null +++ b/test/fixtures/entire/recorded/entire.com/steps/pull-list/step.json @@ -0,0 +1,4 @@ +{ + "name": "pull list", + "recordedAt": "2026-10-26T19:57:13.944Z" +} diff --git a/test/fixtures/entire/recorded/entire.com/steps/pull-review-threads/01-get-N-discussions.json b/test/fixtures/entire/recorded/entire.com/steps/pull-review-threads/01-get-N-discussions.json new file mode 100644 index 000000000..0e3836d99 --- /dev/null +++ b/test/fixtures/entire/recorded/entire.com/steps/pull-review-threads/01-get-N-discussions.json @@ -0,0 +1,433 @@ +{ + "request": { + "method": "GET", + "url": "https://aws-eu-west-2.api.entire.io/api/v1/trails/et/forges/forges-fixtures/1/discussions?include_messages=true&per_page=100" + }, + "response": { + "status": 200, + "headers": { + "link": "; rel=\"describedBy\"" + }, + "body": { + "$schema": "https://aws-eu-west-2.api.entire.io/api/v1/schemas/TrailDiscussionsListResponseBody.json", + "items": [ + { + "id": "01M5WVQW2ZPDDH5X0C5SWM3KVM", + "trail_id": "01M5WVNG0FK8S3JBBFYZGK1VFD", + "title": "`toUpperCase()` ignores the locale, so Turkish names shout incorrectly. Consider `toLocaleUpperCase()`.", + "kind": "code_review", + "resolved": false, + "resolved_by": null, + "resolved_by_identity": { + "kind": "unknown", + "account_id": null, + "display_name": null, + "avatar_url": null, + "handles": [] + }, + "resolved_at": null, + "created_by": "01M5WRP9RJ4GVR2PA5PCNYP1FC", + "created_by_identity": { + "kind": "account", + "account_id": "01M5WRP9RJ4GVR2PA5PCNYP1FC", + "display_name": "Daniel Roe", + "avatar_url": "https://avatars.githubusercontent.com/u/28706372?v=4", + "handles": [ + { + "provider": "github", + "handle": "danielroe", + "is_primary": true + } + ] + }, + "created_at": "2026-10-26T19:42:02.333Z", + "updated_at": "2026-10-26T19:42:13.290Z", + "last_message_at": "2026-10-26T19:42:13.290Z", + "last_message_author": "danielroe", + "message_count": 1, + "participants": [ + { + "login": "danielroe", + "actor_account_id": "01M5WRP9RJ4GVR2PA5PCNYP1FC", + "identity": { + "kind": "account", + "account_id": "01M5WRP9RJ4GVR2PA5PCNYP1FC", + "display_name": "Daniel Roe", + "avatar_url": "https://avatars.githubusercontent.com/u/28706372?v=4", + "handles": [ + { + "provider": "github", + "handle": "danielroe", + "is_primary": true + } + ] + } + } + ], + "review_comment_id": "01M5WVQW2ZTEEA9V72FF81J46Q", + "review_comment": { + "discussion_id": "01M5WVQW2ZPDDH5X0C5SWM3KVM", + "discussion_message_count": 1, + "id": "01M5WVQW2ZTEEA9V72FF81J46Q", + "trail_id": "01M5WVNG0FK8S3JBBFYZGK1VFD", + "repo_id": "01M5WS0P331VQ3AARB26Z9DGV7", + "review_id": "01M5WVQNQSS4DQNQB5Z00WA4V7", + "code_version_id": "01M5WVQNQG83V6VQT17G0M6DBJ", + "actor_id": "01M5WRP9RJ4GVR2PA5PCNYP1FC", + "actor_display_name": "danielroe", + "actor_identity": { + "kind": "account", + "account_id": "01M5WRP9RJ4GVR2PA5PCNYP1FC", + "display_name": "Daniel Roe", + "avatar_url": "https://avatars.githubusercontent.com/u/28706372?v=4", + "handles": [ + { + "provider": "github", + "handle": "danielroe", + "is_primary": true + } + ] + }, + "body": "`toUpperCase()` ignores the locale, so Turkish names shout incorrectly. Consider `toLocaleUpperCase()`.", + "severity": "low", + "confidence": null, + "status": "open", + "status_reason": null, + "status_actor_id": null, + "status_actor_display_name": null, + "status_actor_identity": { + "kind": "unknown", + "account_id": null, + "display_name": null, + "avatar_url": null, + "handles": [] + }, + "status_changed_at": null, + "status_source": null, + "status_actor_kind": null, + "stale_outcome": "current", + "stale_checked_at": null, + "stale_checked_code_version_id": null, + "client_id": "shout-case", + "client_id_hash": "ea05e251d04f3b2e1dbf616445b14d9faba65c96f60b955c61a748fb186cd26d", + "created_at": "2026-10-26T19:42:02.333Z", + "updated_at": "2026-10-26T19:42:02.333Z", + "location": { + "id": "01M5WVQW2Z3NCP4Y284CQ5DE3Y", + "review_comment_id": "01M5WVQW2ZTEEA9V72FF81J46Q", + "code_version_id": "01M5WVQNQG83V6VQT17G0M6DBJ", + "granularity": "line", + "file_path": "src/greet.ts", + "start_line": 3, + "start_column": null, + "end_line": 3, + "end_column": null, + "selected_text": " return options.shout ? greeting.toUpperCase() : greeting", + "nearby_text": null, + "language": null + } + }, + "messages": [ + { + "id": "01M5WVR6SAXG323XBRAH7G0Q3V", + "author": "danielroe", + "identity": { + "kind": "account", + "account_id": "01M5WRP9RJ4GVR2PA5PCNYP1FC", + "display_name": "Daniel Roe", + "avatar_url": "https://avatars.githubusercontent.com/u/28706372?v=4", + "handles": [ + { + "provider": "github", + "handle": "danielroe", + "is_primary": true + } + ] + }, + "created_at": "2026-10-26T19:42:13.290Z", + "body": "Good catch, switching to `toLocaleUpperCase()`.", + "replies": [] + } + ] + }, + { + "id": "01M5WVQW42CZ9N82B1QV6B6GTP", + "trail_id": "01M5WVNG0FK8S3JBBFYZGK1VFD", + "title": "No tests cover the `shout` option.", + "kind": "code_review", + "resolved": false, + "resolved_by": null, + "resolved_by_identity": { + "kind": "unknown", + "account_id": null, + "display_name": null, + "avatar_url": null, + "handles": [] + }, + "resolved_at": null, + "created_by": "01M5WRP9RJ4GVR2PA5PCNYP1FC", + "created_by_identity": { + "kind": "account", + "account_id": "01M5WRP9RJ4GVR2PA5PCNYP1FC", + "display_name": "Daniel Roe", + "avatar_url": "https://avatars.githubusercontent.com/u/28706372?v=4", + "handles": [ + { + "provider": "github", + "handle": "danielroe", + "is_primary": true + } + ] + }, + "created_at": "2026-10-26T19:42:02.368Z", + "updated_at": "2026-10-26T19:42:02.368Z", + "last_message_at": null, + "last_message_author": null, + "message_count": 0, + "participants": [], + "review_comment_id": "01M5WVQW423TPZGYYS4025JBCT", + "review_comment": { + "discussion_id": "01M5WVQW42CZ9N82B1QV6B6GTP", + "discussion_message_count": 0, + "id": "01M5WVQW423TPZGYYS4025JBCT", + "trail_id": "01M5WVNG0FK8S3JBBFYZGK1VFD", + "repo_id": "01M5WS0P331VQ3AARB26Z9DGV7", + "review_id": "01M5WVQNQSS4DQNQB5Z00WA4V7", + "code_version_id": "01M5WVQNQG83V6VQT17G0M6DBJ", + "actor_id": "01M5WRP9RJ4GVR2PA5PCNYP1FC", + "actor_display_name": "danielroe", + "actor_identity": { + "kind": "account", + "account_id": "01M5WRP9RJ4GVR2PA5PCNYP1FC", + "display_name": "Daniel Roe", + "avatar_url": "https://avatars.githubusercontent.com/u/28706372?v=4", + "handles": [ + { + "provider": "github", + "handle": "danielroe", + "is_primary": true + } + ] + }, + "body": "No tests cover the `shout` option.", + "severity": "medium", + "confidence": null, + "status": "open", + "status_reason": null, + "status_actor_id": null, + "status_actor_display_name": null, + "status_actor_identity": { + "kind": "unknown", + "account_id": null, + "display_name": null, + "avatar_url": null, + "handles": [] + }, + "status_changed_at": null, + "status_source": null, + "status_actor_kind": null, + "stale_outcome": "current", + "stale_checked_at": null, + "stale_checked_code_version_id": null, + "client_id": "whole", + "client_id_hash": "a00f6d308f3eb66bbf8828200158393d01575a3bfc9f750bacf1b11ed8d9430a", + "created_at": "2026-10-26T19:42:02.368Z", + "updated_at": "2026-10-26T19:42:02.368Z", + "location": { + "id": "01M5WVQW42ER5GPTS4JM719TDV", + "review_comment_id": "01M5WVQW423TPZGYYS4025JBCT", + "code_version_id": "01M5WVQNQG83V6VQT17G0M6DBJ", + "granularity": "whole_change", + "file_path": null, + "start_line": null, + "start_column": null, + "end_line": null, + "end_column": null, + "selected_text": null, + "nearby_text": null, + "language": null + } + }, + "messages": [] + }, + { + "id": "01M5WVP9QKVVQWQQWRFW4K3T94", + "trail_id": "01M5WVNG0FK8S3JBBFYZGK1VFD", + "title": "Naming", + "kind": "discussion", + "resolved": false, + "resolved_by": null, + "resolved_by_identity": { + "kind": "unknown", + "account_id": null, + "display_name": null, + "avatar_url": null, + "handles": [] + }, + "resolved_at": null, + "created_by": "01M5WRP9RJ4GVR2PA5PCNYP1FC", + "created_by_identity": { + "kind": "account", + "account_id": "01M5WRP9RJ4GVR2PA5PCNYP1FC", + "display_name": "Daniel Roe", + "avatar_url": "https://avatars.githubusercontent.com/u/28706372?v=4", + "handles": [ + { + "provider": "github", + "handle": "danielroe", + "is_primary": true + } + ] + }, + "created_at": "2026-10-26T19:41:10.771Z", + "updated_at": "2026-10-26T19:41:10.771Z", + "last_message_at": "2026-10-26T19:41:10.771Z", + "last_message_author": "danielroe", + "message_count": 1, + "participants": [ + { + "login": "danielroe", + "actor_account_id": "01M5WRP9RJ4GVR2PA5PCNYP1FC", + "identity": { + "kind": "account", + "account_id": "01M5WRP9RJ4GVR2PA5PCNYP1FC", + "display_name": "Daniel Roe", + "avatar_url": "https://avatars.githubusercontent.com/u/28706372?v=4", + "handles": [ + { + "provider": "github", + "handle": "danielroe", + "is_primary": true + } + ] + } + } + ], + "review_comment_id": null, + "review_comment": null, + "messages": [ + { + "id": "01M5WVP9QQB7HMVGA0SRF76KED", + "author": "danielroe", + "identity": { + "kind": "account", + "account_id": "01M5WRP9RJ4GVR2PA5PCNYP1FC", + "display_name": "Daniel Roe", + "avatar_url": "https://avatars.githubusercontent.com/u/28706372?v=4", + "handles": [ + { + "provider": "github", + "handle": "danielroe", + "is_primary": true + } + ] + }, + "created_at": "2026-10-26T19:41:10.771Z", + "body": "`shout` or `loud`? I lean towards `shout`.", + "replies": [] + } + ] + }, + { + "id": "01M5WVP84KN3H6SFHM77XGN8WE", + "trail_id": "01M5WVNG0FK8S3JBBFYZGK1VFD", + "title": "Should `shout` also add an exclamation mark?", + "kind": "discussion", + "resolved": false, + "resolved_by": null, + "resolved_by_identity": { + "kind": "unknown", + "account_id": null, + "display_name": null, + "avatar_url": null, + "handles": [] + }, + "resolved_at": null, + "created_by": "01M5WRP9RJ4GVR2PA5PCNYP1FC", + "created_by_identity": { + "kind": "account", + "account_id": "01M5WRP9RJ4GVR2PA5PCNYP1FC", + "display_name": "Daniel Roe", + "avatar_url": "https://avatars.githubusercontent.com/u/28706372?v=4", + "handles": [ + { + "provider": "github", + "handle": "danielroe", + "is_primary": true + } + ] + }, + "created_at": "2026-10-26T19:41:09.139Z", + "updated_at": "2026-10-26T19:41:09.989Z", + "last_message_at": "2026-10-26T19:41:09.989Z", + "last_message_author": "danielroe", + "message_count": 2, + "participants": [ + { + "login": "danielroe", + "actor_account_id": "01M5WRP9RJ4GVR2PA5PCNYP1FC", + "identity": { + "kind": "account", + "account_id": "01M5WRP9RJ4GVR2PA5PCNYP1FC", + "display_name": "Daniel Roe", + "avatar_url": "https://avatars.githubusercontent.com/u/28706372?v=4", + "handles": [ + { + "provider": "github", + "handle": "danielroe", + "is_primary": true + } + ] + } + } + ], + "review_comment_id": null, + "review_comment": null, + "messages": [ + { + "id": "01M5WVP8552KBGTR9NZCXY91QQ", + "author": "danielroe", + "identity": { + "kind": "account", + "account_id": "01M5WRP9RJ4GVR2PA5PCNYP1FC", + "display_name": "Daniel Roe", + "avatar_url": "https://avatars.githubusercontent.com/u/28706372?v=4", + "handles": [ + { + "provider": "github", + "handle": "danielroe", + "is_primary": true + } + ] + }, + "created_at": "2026-10-26T19:41:09.139Z", + "body": "Should `shout` also add an exclamation mark?", + "replies": [] + }, + { + "id": "01M5WVP8Z53BEF7ZA2WFQ2RQAX", + "author": "danielroe", + "identity": { + "kind": "account", + "account_id": "01M5WRP9RJ4GVR2PA5PCNYP1FC", + "display_name": "Daniel Roe", + "avatar_url": "https://avatars.githubusercontent.com/u/28706372?v=4", + "handles": [ + { + "provider": "github", + "handle": "danielroe", + "is_primary": true + } + ] + }, + "created_at": "2026-10-26T19:41:09.989Z", + "body": "I think it reads fine without one.", + "replies": [] + } + ] + } + ], + "event_cursor": "4" + } + } +} diff --git a/test/fixtures/entire/recorded/entire.com/steps/pull-review-threads/golden.json b/test/fixtures/entire/recorded/entire.com/steps/pull-review-threads/golden.json new file mode 100644 index 000000000..77d38bc9e --- /dev/null +++ b/test/fixtures/entire/recorded/entire.com/steps/pull-review-threads/golden.json @@ -0,0 +1,130 @@ +{ + "items": [ + { + "id": "01M5WVQW2ZPDDH5X0C5SWM3KVM", + "resolved": false, + "outdated": false, + "path": "src/greet.ts", + "line": 3, + "side": "right", + "comments": [ + { + "ref": { + "forge": "entire", + "instance": "entire.com", + "thread": { + "forge": "entire", + "instance": "entire.com", + "repo": { + "forge": "entire", + "instance": "entire.com", + "owner": "forges", + "name": "forges-fixtures" + }, + "kind": "pull_request", + "number": "1" + }, + "id": "01M5WVQW2ZTEEA9V72FF81J46Q" + }, + "body": "`toUpperCase()` ignores the locale, so Turkish names shout incorrectly. Consider `toLocaleUpperCase()`.", + "author": { + "forge": "entire", + "instance": "entire.com", + "login": "danielroe", + "id": "01M5WRP9RJ4GVR2PA5PCNYP1FC", + "name": "Daniel Roe", + "avatarUrl": "https://avatars.githubusercontent.com/u/28706372?v=4", + "isBotHint": false + }, + "path": "src/greet.ts", + "line": 3, + "side": "right", + "thread": { + "id": "01M5WVQW2ZPDDH5X0C5SWM3KVM", + "resolved": false + }, + "createdAt": "" + }, + { + "ref": { + "forge": "entire", + "instance": "entire.com", + "thread": { + "forge": "entire", + "instance": "entire.com", + "repo": { + "forge": "entire", + "instance": "entire.com", + "owner": "forges", + "name": "forges-fixtures" + }, + "kind": "pull_request", + "number": "1" + }, + "id": "01M5WVR6SAXG323XBRAH7G0Q3V" + }, + "body": "Good catch, switching to `toLocaleUpperCase()`.", + "author": { + "forge": "entire", + "instance": "entire.com", + "login": "danielroe", + "id": "01M5WRP9RJ4GVR2PA5PCNYP1FC", + "name": "Daniel Roe", + "avatarUrl": "https://avatars.githubusercontent.com/u/28706372?v=4", + "isBotHint": false + }, + "path": "src/greet.ts", + "line": 3, + "side": "right", + "inReplyTo": "01M5WVQW2ZTEEA9V72FF81J46Q", + "thread": { + "id": "01M5WVQW2ZPDDH5X0C5SWM3KVM", + "resolved": false + }, + "createdAt": "" + } + ] + }, + { + "id": "01M5WVQW42CZ9N82B1QV6B6GTP", + "resolved": false, + "outdated": false, + "comments": [ + { + "ref": { + "forge": "entire", + "instance": "entire.com", + "thread": { + "forge": "entire", + "instance": "entire.com", + "repo": { + "forge": "entire", + "instance": "entire.com", + "owner": "forges", + "name": "forges-fixtures" + }, + "kind": "pull_request", + "number": "1" + }, + "id": "01M5WVQW423TPZGYYS4025JBCT" + }, + "body": "No tests cover the `shout` option.", + "author": { + "forge": "entire", + "instance": "entire.com", + "login": "danielroe", + "id": "01M5WRP9RJ4GVR2PA5PCNYP1FC", + "name": "Daniel Roe", + "avatarUrl": "https://avatars.githubusercontent.com/u/28706372?v=4", + "isBotHint": false + }, + "thread": { + "id": "01M5WVQW42CZ9N82B1QV6B6GTP", + "resolved": false + }, + "createdAt": "" + } + ] + } + ] +} diff --git a/test/fixtures/entire/recorded/entire.com/steps/pull-review-threads/step.json b/test/fixtures/entire/recorded/entire.com/steps/pull-review-threads/step.json new file mode 100644 index 000000000..5698c2adf --- /dev/null +++ b/test/fixtures/entire/recorded/entire.com/steps/pull-review-threads/step.json @@ -0,0 +1,4 @@ +{ + "name": "pull review threads", + "recordedAt": "2026-10-26T19:57:16.349Z" +} diff --git a/test/fixtures/entire/recorded/entire.com/steps/pull-reviews/01-get-N-approvals.json b/test/fixtures/entire/recorded/entire.com/steps/pull-reviews/01-get-N-approvals.json new file mode 100644 index 000000000..c9882402d --- /dev/null +++ b/test/fixtures/entire/recorded/entire.com/steps/pull-reviews/01-get-N-approvals.json @@ -0,0 +1,25 @@ +{ + "request": { + "method": "GET", + "url": "https://aws-eu-west-2.api.entire.io/api/v1/trails/et/forges/forges-fixtures/1/approvals" + }, + "response": { + "status": 200, + "headers": { + "link": "; rel=\"describedBy\"" + }, + "body": { + "$schema": "https://aws-eu-west-2.api.entire.io/api/v1/schemas/TrailApprovalsResponse.json", + "approvals": [ + { + "id": "01M5WVPQ2KX1QCY97NEWDQWTB8", + "author": "danielroe", + "event": "changes_requested", + "body": "Please add a test for shouting.", + "commit_sha": "9ec20061f17f35212247320f525ec51d3e00c41a", + "created_at": "2026-10-26T19:41:24.435414047Z" + } + ] + } + } +} diff --git a/test/fixtures/entire/recorded/entire.com/steps/pull-reviews/02-get-reviews-01M5WVQNQSS4DQNQB5Z00WA4V7.json b/test/fixtures/entire/recorded/entire.com/steps/pull-reviews/02-get-reviews-01M5WVQNQSS4DQNQB5Z00WA4V7.json new file mode 100644 index 000000000..6c4a30a2c --- /dev/null +++ b/test/fixtures/entire/recorded/entire.com/steps/pull-reviews/02-get-reviews-01M5WVQNQSS4DQNQB5Z00WA4V7.json @@ -0,0 +1,172 @@ +{ + "request": { + "method": "GET", + "url": "https://aws-eu-west-2.api.entire.io/api/v1/trails/et/forges/forges-fixtures/1/reviews/01M5WVQNQSS4DQNQB5Z00WA4V7" + }, + "response": { + "status": 200, + "headers": { + "link": "; rel=\"describedBy\"" + }, + "body": { + "$schema": "https://aws-eu-west-2.api.entire.io/api/v1/schemas/ReviewSnapshotResponseBody.json", + "review": { + "id": "01M5WVQNQSS4DQNQB5Z00WA4V7", + "trail_id": "01M5WVNG0FK8S3JBBFYZGK1VFD", + "code_version_id": "01M5WVQNQG83V6VQT17G0M6DBJ", + "actor_id": "01M5WRP9RJ4GVR2PA5PCNYP1FC", + "summary": null, + "started_at": "2026-10-26T19:41:55.833Z", + "source_execution_id": null + }, + "code_version": { + "id": "01M5WVQNQG83V6VQT17G0M6DBJ", + "trail_id": "01M5WVNG0FK8S3JBBFYZGK1VFD", + "repo_id": "01M5WS0P331VQ3AARB26Z9DGV7", + "base_ref": null, + "head_ref": null, + "base_sha": "8127b4c88662985c819a6b3cabecde203907c3e2", + "head_sha": "9ec20061f17f35212247320f525ec51d3e00c41a", + "captured_at": "2026-10-26T19:41:55.824Z" + }, + "counts": { + "open": 2, + "resolved": 0, + "dismissed": 0, + "stale": 0, + "total": 2 + }, + "comments": [ + { + "discussion_id": "01M5WVQW42CZ9N82B1QV6B6GTP", + "discussion_message_count": 0, + "id": "01M5WVQW423TPZGYYS4025JBCT", + "trail_id": "01M5WVNG0FK8S3JBBFYZGK1VFD", + "repo_id": "01M5WS0P331VQ3AARB26Z9DGV7", + "review_id": "01M5WVQNQSS4DQNQB5Z00WA4V7", + "code_version_id": "01M5WVQNQG83V6VQT17G0M6DBJ", + "actor_id": "01M5WRP9RJ4GVR2PA5PCNYP1FC", + "actor_display_name": "danielroe", + "actor_identity": { + "kind": "account", + "account_id": "01M5WRP9RJ4GVR2PA5PCNYP1FC", + "display_name": "Daniel Roe", + "avatar_url": "https://avatars.githubusercontent.com/u/28706372?v=4", + "handles": [ + { + "provider": "github", + "handle": "danielroe", + "is_primary": true + } + ] + }, + "body": "No tests cover the `shout` option.", + "severity": "medium", + "confidence": null, + "status": "open", + "status_reason": null, + "status_actor_id": null, + "status_actor_display_name": null, + "status_actor_identity": { + "kind": "unknown", + "account_id": null, + "display_name": null, + "avatar_url": null, + "handles": [] + }, + "status_changed_at": null, + "status_source": null, + "status_actor_kind": null, + "stale_outcome": "current", + "stale_checked_at": null, + "stale_checked_code_version_id": null, + "client_id": "whole", + "client_id_hash": "a00f6d308f3eb66bbf8828200158393d01575a3bfc9f750bacf1b11ed8d9430a", + "created_at": "2026-10-26T19:42:02.368Z", + "updated_at": "2026-10-26T19:42:02.368Z", + "location": { + "id": "01M5WVQW42ER5GPTS4JM719TDV", + "review_comment_id": "01M5WVQW423TPZGYYS4025JBCT", + "code_version_id": "01M5WVQNQG83V6VQT17G0M6DBJ", + "granularity": "whole_change", + "file_path": null, + "start_line": null, + "start_column": null, + "end_line": null, + "end_column": null, + "selected_text": null, + "nearby_text": null, + "language": null + }, + "suggested_changes": [], + "outgoing_links": [] + }, + { + "discussion_id": "01M5WVQW2ZPDDH5X0C5SWM3KVM", + "discussion_message_count": 1, + "id": "01M5WVQW2ZTEEA9V72FF81J46Q", + "trail_id": "01M5WVNG0FK8S3JBBFYZGK1VFD", + "repo_id": "01M5WS0P331VQ3AARB26Z9DGV7", + "review_id": "01M5WVQNQSS4DQNQB5Z00WA4V7", + "code_version_id": "01M5WVQNQG83V6VQT17G0M6DBJ", + "actor_id": "01M5WRP9RJ4GVR2PA5PCNYP1FC", + "actor_display_name": "danielroe", + "actor_identity": { + "kind": "account", + "account_id": "01M5WRP9RJ4GVR2PA5PCNYP1FC", + "display_name": "Daniel Roe", + "avatar_url": "https://avatars.githubusercontent.com/u/28706372?v=4", + "handles": [ + { + "provider": "github", + "handle": "danielroe", + "is_primary": true + } + ] + }, + "body": "`toUpperCase()` ignores the locale, so Turkish names shout incorrectly. Consider `toLocaleUpperCase()`.", + "severity": "low", + "confidence": null, + "status": "open", + "status_reason": null, + "status_actor_id": null, + "status_actor_display_name": null, + "status_actor_identity": { + "kind": "unknown", + "account_id": null, + "display_name": null, + "avatar_url": null, + "handles": [] + }, + "status_changed_at": null, + "status_source": null, + "status_actor_kind": null, + "stale_outcome": "current", + "stale_checked_at": null, + "stale_checked_code_version_id": null, + "client_id": "shout-case", + "client_id_hash": "ea05e251d04f3b2e1dbf616445b14d9faba65c96f60b955c61a748fb186cd26d", + "created_at": "2026-10-26T19:42:02.333Z", + "updated_at": "2026-10-26T19:42:02.333Z", + "location": { + "id": "01M5WVQW2Z3NCP4Y284CQ5DE3Y", + "review_comment_id": "01M5WVQW2ZTEEA9V72FF81J46Q", + "code_version_id": "01M5WVQNQG83V6VQT17G0M6DBJ", + "granularity": "line", + "file_path": "src/greet.ts", + "start_line": 3, + "start_column": null, + "end_line": 3, + "end_column": null, + "selected_text": " return options.shout ? greeting.toUpperCase() : greeting", + "nearby_text": null, + "language": null + }, + "suggested_changes": [], + "outgoing_links": [] + } + ], + "event_cursor": "11" + } + } +} diff --git a/test/fixtures/entire/recorded/entire.com/steps/pull-reviews/03-get-reviews-comments.json b/test/fixtures/entire/recorded/entire.com/steps/pull-reviews/03-get-reviews-comments.json new file mode 100644 index 000000000..edb17befd --- /dev/null +++ b/test/fixtures/entire/recorded/entire.com/steps/pull-reviews/03-get-reviews-comments.json @@ -0,0 +1,142 @@ +{ + "request": { + "method": "GET", + "url": "https://aws-eu-west-2.api.entire.io/api/v1/trails/et/forges/forges-fixtures/1/reviews/comments?per_page=100" + }, + "response": { + "status": 200, + "headers": { + "link": "; rel=\"describedBy\"" + }, + "body": { + "$schema": "https://aws-eu-west-2.api.entire.io/api/v1/schemas/ReviewCommentsPage.json", + "comments": [ + { + "discussion_id": "01M5WVQW42CZ9N82B1QV6B6GTP", + "discussion_message_count": 0, + "id": "01M5WVQW423TPZGYYS4025JBCT", + "trail_id": "01M5WVNG0FK8S3JBBFYZGK1VFD", + "repo_id": "01M5WS0P331VQ3AARB26Z9DGV7", + "review_id": "01M5WVQNQSS4DQNQB5Z00WA4V7", + "code_version_id": "01M5WVQNQG83V6VQT17G0M6DBJ", + "actor_id": "01M5WRP9RJ4GVR2PA5PCNYP1FC", + "actor_display_name": "danielroe", + "actor_identity": { + "kind": "account", + "account_id": "01M5WRP9RJ4GVR2PA5PCNYP1FC", + "display_name": "Daniel Roe", + "avatar_url": "https://avatars.githubusercontent.com/u/28706372?v=4", + "handles": [ + { + "provider": "github", + "handle": "danielroe", + "is_primary": true + } + ] + }, + "body": "No tests cover the `shout` option.", + "severity": "medium", + "confidence": null, + "status": "open", + "status_reason": null, + "status_actor_id": null, + "status_actor_display_name": null, + "status_actor_identity": { + "kind": "unknown", + "account_id": null, + "display_name": null, + "avatar_url": null, + "handles": [] + }, + "status_changed_at": null, + "status_source": null, + "status_actor_kind": null, + "stale_outcome": "current", + "stale_checked_at": null, + "stale_checked_code_version_id": null, + "client_id": "whole", + "client_id_hash": "a00f6d308f3eb66bbf8828200158393d01575a3bfc9f750bacf1b11ed8d9430a", + "created_at": "2026-10-26T19:42:02.368Z", + "updated_at": "2026-10-26T19:42:02.368Z", + "location": { + "id": "01M5WVQW42ER5GPTS4JM719TDV", + "review_comment_id": "01M5WVQW423TPZGYYS4025JBCT", + "code_version_id": "01M5WVQNQG83V6VQT17G0M6DBJ", + "granularity": "whole_change", + "file_path": null, + "start_line": null, + "start_column": null, + "end_line": null, + "end_column": null, + "selected_text": null, + "nearby_text": null, + "language": null + } + }, + { + "discussion_id": "01M5WVQW2ZPDDH5X0C5SWM3KVM", + "discussion_message_count": 1, + "id": "01M5WVQW2ZTEEA9V72FF81J46Q", + "trail_id": "01M5WVNG0FK8S3JBBFYZGK1VFD", + "repo_id": "01M5WS0P331VQ3AARB26Z9DGV7", + "review_id": "01M5WVQNQSS4DQNQB5Z00WA4V7", + "code_version_id": "01M5WVQNQG83V6VQT17G0M6DBJ", + "actor_id": "01M5WRP9RJ4GVR2PA5PCNYP1FC", + "actor_display_name": "danielroe", + "actor_identity": { + "kind": "account", + "account_id": "01M5WRP9RJ4GVR2PA5PCNYP1FC", + "display_name": "Daniel Roe", + "avatar_url": "https://avatars.githubusercontent.com/u/28706372?v=4", + "handles": [ + { + "provider": "github", + "handle": "danielroe", + "is_primary": true + } + ] + }, + "body": "`toUpperCase()` ignores the locale, so Turkish names shout incorrectly. Consider `toLocaleUpperCase()`.", + "severity": "low", + "confidence": null, + "status": "open", + "status_reason": null, + "status_actor_id": null, + "status_actor_display_name": null, + "status_actor_identity": { + "kind": "unknown", + "account_id": null, + "display_name": null, + "avatar_url": null, + "handles": [] + }, + "status_changed_at": null, + "status_source": null, + "status_actor_kind": null, + "stale_outcome": "current", + "stale_checked_at": null, + "stale_checked_code_version_id": null, + "client_id": "shout-case", + "client_id_hash": "ea05e251d04f3b2e1dbf616445b14d9faba65c96f60b955c61a748fb186cd26d", + "created_at": "2026-10-26T19:42:02.333Z", + "updated_at": "2026-10-26T19:42:02.333Z", + "location": { + "id": "01M5WVQW2Z3NCP4Y284CQ5DE3Y", + "review_comment_id": "01M5WVQW2ZTEEA9V72FF81J46Q", + "code_version_id": "01M5WVQNQG83V6VQT17G0M6DBJ", + "granularity": "line", + "file_path": "src/greet.ts", + "start_line": 3, + "start_column": null, + "end_line": 3, + "end_column": null, + "selected_text": " return options.shout ? greeting.toUpperCase() : greeting", + "nearby_text": null, + "language": null + } + } + ], + "event_cursor": "11" + } + } +} diff --git a/test/fixtures/entire/recorded/entire.com/steps/pull-reviews/golden.json b/test/fixtures/entire/recorded/entire.com/steps/pull-reviews/golden.json new file mode 100644 index 000000000..797e8a62e --- /dev/null +++ b/test/fixtures/entire/recorded/entire.com/steps/pull-reviews/golden.json @@ -0,0 +1,139 @@ +{ + "items": [ + { + "ref": { + "forge": "entire", + "instance": "entire.com", + "thread": { + "forge": "entire", + "instance": "entire.com", + "repo": { + "forge": "entire", + "instance": "entire.com", + "owner": "forges", + "name": "forges-fixtures" + }, + "kind": "pull_request", + "number": "1" + }, + "id": "01M5WVPQ2KX1QCY97NEWDQWTB8" + }, + "author": { + "forge": "entire", + "instance": "entire.com", + "login": "danielroe", + "id": "danielroe", + "isBotHint": false + }, + "state": "changes_requested", + "stateRaw": "changes_requested", + "body": "Please add a test for shouting.", + "submittedAt": "2026-10-26T19:41:24.435Z", + "comments": false + }, + { + "ref": { + "forge": "entire", + "instance": "entire.com", + "thread": { + "forge": "entire", + "instance": "entire.com", + "repo": { + "forge": "entire", + "instance": "entire.com", + "owner": "forges", + "name": "forges-fixtures" + }, + "kind": "pull_request", + "number": "1" + }, + "id": "01M5WVQNQSS4DQNQB5Z00WA4V7" + }, + "author": { + "forge": "entire", + "instance": "entire.com", + "login": "danielroe", + "id": "01M5WRP9RJ4GVR2PA5PCNYP1FC", + "name": "Daniel Roe", + "avatarUrl": "https://avatars.githubusercontent.com/u/28706372?v=4", + "isBotHint": false + }, + "state": "commented", + "stateRaw": "review", + "submittedAt": "2026-10-26T19:42:02.333Z", + "comments": [ + { + "ref": { + "forge": "entire", + "instance": "entire.com", + "thread": { + "forge": "entire", + "instance": "entire.com", + "repo": { + "forge": "entire", + "instance": "entire.com", + "owner": "forges", + "name": "forges-fixtures" + }, + "kind": "pull_request", + "number": "1" + }, + "id": "01M5WVQW2ZTEEA9V72FF81J46Q" + }, + "body": "`toUpperCase()` ignores the locale, so Turkish names shout incorrectly. Consider `toLocaleUpperCase()`.", + "author": { + "forge": "entire", + "instance": "entire.com", + "login": "danielroe", + "id": "01M5WRP9RJ4GVR2PA5PCNYP1FC", + "name": "Daniel Roe", + "avatarUrl": "https://avatars.githubusercontent.com/u/28706372?v=4", + "isBotHint": false + }, + "path": "src/greet.ts", + "line": 3, + "side": "right", + "thread": { + "id": "01M5WVQW2ZPDDH5X0C5SWM3KVM", + "resolved": false + }, + "createdAt": "2026-10-26T19:42:02.333Z" + }, + { + "ref": { + "forge": "entire", + "instance": "entire.com", + "thread": { + "forge": "entire", + "instance": "entire.com", + "repo": { + "forge": "entire", + "instance": "entire.com", + "owner": "forges", + "name": "forges-fixtures" + }, + "kind": "pull_request", + "number": "1" + }, + "id": "01M5WVQW423TPZGYYS4025JBCT" + }, + "body": "No tests cover the `shout` option.", + "author": { + "forge": "entire", + "instance": "entire.com", + "login": "danielroe", + "id": "01M5WRP9RJ4GVR2PA5PCNYP1FC", + "name": "Daniel Roe", + "avatarUrl": "https://avatars.githubusercontent.com/u/28706372?v=4", + "isBotHint": false + }, + "thread": { + "id": "01M5WVQW42CZ9N82B1QV6B6GTP", + "resolved": false + }, + "createdAt": "2026-10-26T19:42:02.368Z" + } + ] + } + ] +} diff --git a/test/fixtures/entire/recorded/entire.com/steps/pull-reviews/step.json b/test/fixtures/entire/recorded/entire.com/steps/pull-reviews/step.json new file mode 100644 index 000000000..d2b2d9944 --- /dev/null +++ b/test/fixtures/entire/recorded/entire.com/steps/pull-reviews/step.json @@ -0,0 +1,4 @@ +{ + "name": "pull reviews", + "recordedAt": "2026-10-26T21:02:29.586Z" +} diff --git a/test/fixtures/entire/recorded/entire.com/steps/pull/01-get-trails-01M5WVNFY1D7AHX0KJW2ANZP14.json b/test/fixtures/entire/recorded/entire.com/steps/pull/01-get-trails-01M5WVNFY1D7AHX0KJW2ANZP14.json new file mode 100644 index 000000000..1dfbfb50b --- /dev/null +++ b/test/fixtures/entire/recorded/entire.com/steps/pull/01-get-trails-01M5WVNFY1D7AHX0KJW2ANZP14.json @@ -0,0 +1,153 @@ +{ + "request": { + "method": "GET", + "url": "https://aws-eu-west-2.api.entire.io/api/v1/et/forges/trails/01M5WVNFY1D7AHX0KJW2ANZP14" + }, + "response": { + "status": 200, + "headers": { + "link": "; rel=\"describedBy\"", + "etag": "W/\"2026-10-26T19:40:44.561257Z\"" + }, + "body": { + "$schema": "https://aws-eu-west-2.api.entire.io/api/v1/schemas/TrailResponse.json", + "capabilities": { + "canEdit": true, + "canManageScope": true + }, + "project": { + "primaryProcessingCell": "aws-eu-west-2", + "id": "01M5WS0JJNP4V9AW20MZ3MKF5M", + "name": "forges", + "provider": "entire", + "reference": { + "forge": "et", + "project": "forges" + }, + "jurisdiction": "uk", + "capabilities": { + "canManageTrails": true + } + }, + "author": { + "accountId": "01M5WRP9RJ4GVR2PA5PCNYP1FC", + "login": "danielroe", + "displayName": "Daniel Roe", + "avatarUrl": "https://avatars.githubusercontent.com/u/28706372?v=4", + "identity": { + "kind": "account", + "account_id": "01M5WRP9RJ4GVR2PA5PCNYP1FC", + "display_name": "Daniel Roe", + "avatar_url": "https://avatars.githubusercontent.com/u/28706372?v=4", + "handles": [ + { + "provider": "github", + "handle": "danielroe", + "is_primary": true + } + ] + } + }, + "id": "01M5WVNFY1D7AHX0KJW2ANZP14", + "projectId": "01M5WS0JJNP4V9AW20MZ3MKF5M", + "number": 2, + "url": "https://entire.com/et/forges/-/trails/2", + "title": "Shout greetings", + "body": "Adds a `shout` option to `greet()`.", + "bodyDocument": { + "id": "", + "document_key": "project-trail:01M5WVNFY1D7AHX0KJW2ANZP14:body", + "schema_version": 1, + "content_json": { + "type": "doc", + "content": [ + { + "type": "paragraph", + "content": [ + { + "type": "text", + "text": "Adds a " + }, + { + "type": "text", + "marks": [ + { + "type": "code" + } + ], + "text": "shout" + }, + { + "type": "text", + "text": " option to " + }, + { + "type": "text", + "marks": [ + { + "type": "code" + } + ], + "text": "greet()" + }, + { + "type": "text", + "text": "." + } + ] + } + ] + }, + "text_snapshot": "Adds a shout option to greet().", + "updated_at": "2026-10-26T19:40:44.561Z", + "etag": "" + }, + "status": "open", + "phase": "building", + "metadata": {}, + "type": "feature", + "priority": "medium", + "assignees": [], + "assigneeAccountIds": [], + "repoIds": [ + "01M5WS0P331VQ3AARB26Z9DGV7" + ], + "authorAccountId": "01M5WRP9RJ4GVR2PA5PCNYP1FC", + "createdAt": "2026-10-26T19:40:44.349Z", + "metadataUpdatedAt": "2026-10-26T19:40:44.561Z", + "closedAt": null, + "lastVisitedAt": null, + "lastActivityAt": "2026-10-26T19:42:13.290Z", + "changes": [ + { + "id": "01M5WVNG0FK8S3JBBFYZGK1VFD", + "repositoryId": "01M5WS0P331VQ3AARB26Z9DGV7", + "repository": "forges-fixtures", + "branch": "feature/shout", + "originalBranch": "feature/shout", + "base": "main", + "number": 1, + "title": "feat: shout greetings", + "status": "open", + "hasCodeChanges": true, + "createdAt": "2026-10-26T19:40:44.349Z", + "updatedAt": "2026-10-26T19:42:13.290Z", + "lastActivityAt": "2026-10-26T19:42:13.290Z", + "deployments": { + "availability": "available", + "ready": 0, + "total": 0 + }, + "readiness": "in_review", + "mergeability": { + "conflict_status": "unknown", + "head_sha": "", + "refreshed_at": null, + "forge_merge_block": null + } + } + ], + "isPossiblyPartial": true + } + } +} diff --git a/test/fixtures/entire/recorded/entire.com/steps/pull/02-get-forges-fixtures-N.json b/test/fixtures/entire/recorded/entire.com/steps/pull/02-get-forges-fixtures-N.json new file mode 100644 index 000000000..e93c190c8 --- /dev/null +++ b/test/fixtures/entire/recorded/entire.com/steps/pull/02-get-forges-fixtures-N.json @@ -0,0 +1,287 @@ +{ + "request": { + "method": "GET", + "url": "https://aws-eu-west-2.api.entire.io/api/v1/trails/et/forges/forges-fixtures/1" + }, + "response": { + "status": 200, + "headers": { + "link": "; rel=\"describedBy\"" + }, + "body": { + "$schema": "https://aws-eu-west-2.api.entire.io/api/v1/schemas/TrailDetailResponse.json", + "id": "01M5WVNG0FK8S3JBBFYZGK1VFD", + "number": 1, + "url": "https://entire.com/et/forges/forges-fixtures/trails/1", + "title": "feat: shout greetings", + "status": "open", + "branch": "feature/shout", + "original_branch": "feature/shout", + "base": "main", + "type": "task", + "priority": "none", + "author": { + "id": "01M5WRP9RJ4GVR2PA5PCNYP1FC", + "login": "danielroe", + "identity": { + "kind": "account", + "account_id": "01M5WRP9RJ4GVR2PA5PCNYP1FC", + "display_name": "Daniel Roe", + "avatar_url": "https://avatars.githubusercontent.com/u/28706372?v=4", + "handles": [ + { + "provider": "github", + "handle": "danielroe", + "is_primary": true + } + ] + } + }, + "assignees": [ + "danielroe" + ], + "assignee_identities": [ + { + "login": "danielroe", + "identity": { + "kind": "account", + "account_id": "01M5WRP9RJ4GVR2PA5PCNYP1FC", + "display_name": "Daniel Roe", + "avatar_url": "https://avatars.githubusercontent.com/u/28706372?v=4", + "handles": [ + { + "provider": "github", + "handle": "danielroe", + "is_primary": true + } + ] + } + } + ], + "reviewers": [ + { + "login": "danielroe", + "status": "changes_requested", + "actor_account_id": "01M5WRP9RJ4GVR2PA5PCNYP1FC", + "identity": { + "kind": "account", + "account_id": "01M5WRP9RJ4GVR2PA5PCNYP1FC", + "display_name": "Daniel Roe", + "avatar_url": "https://avatars.githubusercontent.com/u/28706372?v=4", + "handles": [ + { + "provider": "github", + "handle": "danielroe", + "is_primary": true + } + ] + } + } + ], + "ready_for_review": true, + "has_code_changes": true, + "comment_count": 4, + "unresolved_count": 4, + "created_at": "2026-10-26T19:40:44.349Z", + "updated_at": "2026-10-26T19:42:13.290Z", + "merged_at": null, + "last_activity_at": "2026-10-26T19:42:13.290Z", + "phase": "reviewing", + "parent": { + "id": "01M5WVNFY1D7AHX0KJW2ANZP14", + "number": 2, + "project_id": "01M5WS0JJNP4V9AW20MZ3MKF5M", + "host": "et", + "project": "forges", + "path": "/api/v1/et/forges/trails/01M5WVNFY1D7AHX0KJW2ANZP14", + "jurisdiction": "uk", + "primary_processing_cell": "aws-eu-west-2", + "url": "https://entire.com/et/forges/-/trails/2" + }, + "branch_state": "present", + "code_changes": "present", + "lifecycle_sync": "settled", + "body_document": { + "id": "01M5WVNG4RWC7X4X51BHP5Q5M2", + "document_key": "trail:01M5WVNG0FK8S3JBBFYZGK1VFD:body", + "schema_version": 1, + "content_json": { + "type": "doc", + "content": [ + { + "type": "paragraph" + } + ] + }, + "text_snapshot": "", + "updated_at": "2026-10-26T19:40:44.349Z", + "etag": "W/\"2026-10-26T19:40:44.349281Z\"" + }, + "monitors": [], + "agents": [], + "runners": [], + "actions": { + "approve": { + "state": "enabled", + "reason": null + }, + "create_ci_pr": { + "state": "unavailable", + "reason": "not_applicable" + }, + "merge": { + "state": "blocked", + "reason": "merge_conflict" + }, + "merge_with_bypass": { + "state": "unavailable", + "reason": "merge_gates_bypass_forbidden" + }, + "update_branch": { + "state": "unavailable", + "reason": "merge_conflict" + }, + "restore_branch": { + "state": "unavailable", + "reason": "trail_not_merged" + }, + "delete_branch": { + "state": "unavailable", + "reason": "trail_not_merged" + } + }, + "mergeability": { + "delete_branch_on_merge": false, + "bypass_policy": "nobody", + "mergeable": false, + "behind_by": 1, + "comparison_status": "available", + "conflict_status": "conflicting", + "head_sha": "9ec20061f17f35212247320f525ec51d3e00c41a", + "gates": [ + { + "reviewers": [ + { + "login": "danielroe", + "actor_account_id": "01M5WRP9RJ4GVR2PA5PCNYP1FC", + "state": "changes_requested", + "reviewed_head_sha": "9ec20061f17f35212247320f525ec51d3e00c41a", + "reason": null + } + ], + "runner_ids": [], + "id": "", + "gate_definition_id": "01M5WTJP4MSACMEJ1KK4FGP2B1", + "gate_key": "approvals", + "gate_type": "approvals", + "blocking": true, + "status": "failed", + "head_sha": "9ec20061f17f35212247320f525ec51d3e00c41a", + "value": { + "approved": 0, + "changes_requested": true, + "config": { + "version": 1, + "min_reviewers": 1, + "allow_self_approval": true, + "dismiss_stale_approvals_on_push": false + }, + "required": 1, + "self_excluded": false, + "stale_dismissed": 0, + "total": 1 + }, + "rationale": "Changes have been requested", + "created_at": "2026-10-26T21:02:27.139303741Z", + "completed_at": "2026-10-26T21:02:27.139303741Z", + "state": "evaluated", + "outcome": "failed", + "stale_reason": null, + "evaluated_at_sha": "9ec20061f17f35212247320f525ec51d3e00c41a", + "finding_count": null + }, + { + "reviewers": [], + "runner_ids": [], + "id": "01M5WVQW5BHQ3CSVZJTM3595D5", + "gate_definition_id": "01M5WTJP5MDYCYNF3Z6BWN7NZ0", + "gate_key": "findings", + "gate_type": "findings", + "blocking": true, + "status": "passed", + "head_sha": "9ec20061f17f35212247320f525ec51d3e00c41a", + "value": { + "config": { + "version": 1, + "agent_findings_min_severity": "high" + }, + "reviewed_head": false, + "agent_findings": { + "low": 1, + "high": 0, + "medium": 1, + "unspecified": 0 + }, + "review_in_flight": false, + "reviewer_configured": false, + "review_grace_expired": false, + "agent_blocking_findings": 0 + }, + "rationale": "No blocking findings", + "created_at": "2026-10-26T19:42:02.411692Z", + "completed_at": "2026-10-26T19:42:02.411692Z", + "state": "evaluated", + "outcome": "passed", + "stale_reason": null, + "evaluated_at_sha": "9ec20061f17f35212247320f525ec51d3e00c41a", + "finding_count": 0 + }, + { + "reviewers": [], + "runner_ids": [], + "id": "", + "gate_definition_id": "01M5WTJP5QR0FQ7TWGE7Y3QCJC", + "gate_key": "up_to_date", + "gate_type": "up_to_date", + "blocking": true, + "status": "failed", + "head_sha": "9ec20061f17f35212247320f525ec51d3e00c41a", + "value": { + "comparison_status": "available", + "behind_by": 1, + "compare_status": "diverged", + "merge_status": "conflicting", + "config": { + "version": 1, + "allow_behind_if_mergeable": false + } + }, + "rationale": "Merge conflicts", + "created_at": "2026-10-26T19:41:42.616528Z", + "completed_at": null, + "state": "evaluated", + "outcome": "failed", + "stale_reason": null, + "evaluated_at_sha": "9ec20061f17f35212247320f525ec51d3e00c41a", + "finding_count": null + } + ], + "checks": { + "availability": "not_applicable", + "runs": [] + }, + "forge_merge_block": null + }, + "deployments": { + "availability": "available", + "ready": 0, + "total": 0, + "items": [] + }, + "config_source": "live", + "merge_base_sha": null, + "base_sha": null, + "head_sha": "9ec20061f17f35212247320f525ec51d3e00c41a" + } + } +} diff --git a/test/fixtures/entire/recorded/entire.com/steps/pull/golden.json b/test/fixtures/entire/recorded/entire.com/steps/pull/golden.json new file mode 100644 index 000000000..9f77e9465 --- /dev/null +++ b/test/fixtures/entire/recorded/entire.com/steps/pull/golden.json @@ -0,0 +1,77 @@ +{ + "ref": { + "forge": "entire", + "instance": "entire.com", + "repo": { + "forge": "entire", + "instance": "entire.com", + "owner": "forges", + "name": "forges-fixtures" + }, + "kind": "pull_request", + "number": "1", + "externalId": "01M5WVNG0FK8S3JBBFYZGK1VFD" + }, + "kind": "pull_request", + "title": "feat: shout greetings", + "body": "Adds a `shout` option to `greet()`.", + "state": "open", + "stateRaw": "open", + "isDraft": false, + "author": { + "forge": "entire", + "instance": "entire.com", + "login": "danielroe", + "id": "01M5WRP9RJ4GVR2PA5PCNYP1FC", + "name": "Daniel Roe", + "avatarUrl": "https://avatars.githubusercontent.com/u/28706372?v=4", + "isBotHint": false + }, + "assignees": [ + { + "forge": "entire", + "instance": "entire.com", + "login": "danielroe", + "id": "01M5WRP9RJ4GVR2PA5PCNYP1FC", + "name": "Daniel Roe", + "avatarUrl": "https://avatars.githubusercontent.com/u/28706372?v=4", + "isBotHint": false + } + ], + "reviewers": [ + { + "actor": { + "forge": "entire", + "instance": "entire.com", + "login": "danielroe", + "id": "01M5WRP9RJ4GVR2PA5PCNYP1FC", + "name": "Daniel Roe", + "avatarUrl": "https://avatars.githubusercontent.com/u/28706372?v=4", + "isBotHint": false + }, + "state": "changes_requested", + "stateRaw": "changes_requested" + } + ], + "labels": [], + "url": "https://entire.com/et/forges/forges-fixtures/trails/1", + "createdAt": "2026-10-26T19:40:44.349Z", + "updatedAt": "2026-10-26T19:42:13.290Z", + "lastActivityAt": "2026-10-26T19:42:13.290Z", + "commentCount": 4, + "branches": { + "head": { + "ref": "feature/shout", + "sha": "9ec20061f17f35212247320f525ec51d3e00c41a", + "repo": { + "forge": "entire", + "instance": "entire.com", + "owner": "forges", + "name": "forges-fixtures" + } + }, + "base": { + "ref": "main" + } + } +} diff --git a/test/fixtures/entire/recorded/entire.com/steps/pull/step.json b/test/fixtures/entire/recorded/entire.com/steps/pull/step.json new file mode 100644 index 000000000..4236a57a7 --- /dev/null +++ b/test/fixtures/entire/recorded/entire.com/steps/pull/step.json @@ -0,0 +1,4 @@ +{ + "name": "pull", + "recordedAt": "2026-10-26T21:02:26.761Z" +} diff --git a/test/fixtures/entire/recorded/entire.com/steps/readme-without-metadata/01-get-01M5WS0P331VQ3AARB26Z9DGV7-raw.json b/test/fixtures/entire/recorded/entire.com/steps/readme-without-metadata/01-get-01M5WS0P331VQ3AARB26Z9DGV7-raw.json new file mode 100644 index 000000000..cb287450c --- /dev/null +++ b/test/fixtures/entire/recorded/entire.com/steps/readme-without-metadata/01-get-01M5WS0P331VQ3AARB26Z9DGV7-raw.json @@ -0,0 +1,11 @@ +{ + "request": { + "method": "GET", + "url": "https://aws-eu-west-2.api.entire.io/api/v1/git/repos/01M5WS0P331VQ3AARB26Z9DGV7/raw?ref=HEAD&path=README.md" + }, + "response": { + "status": 200, + "headers": {}, + "body": "# forges-fixtures\n\nA repository for the Entire recordings of [forges](https://forges.link), a forge client.\n" + } +} diff --git a/test/fixtures/entire/recorded/entire.com/steps/readme-without-metadata/golden.json b/test/fixtures/entire/recorded/entire.com/steps/readme-without-metadata/golden.json new file mode 100644 index 000000000..f80fc04a6 --- /dev/null +++ b/test/fixtures/entire/recorded/entire.com/steps/readme-without-metadata/golden.json @@ -0,0 +1,6 @@ +{ + "path": "README.md", + "size": 108, + "content": "# forges-fixtures\n\nA repository for the Entire recordings of [forges](https://forges.link), a forge client.\n", + "encoding": "utf-8" +} diff --git a/test/fixtures/entire/recorded/entire.com/steps/readme-without-metadata/step.json b/test/fixtures/entire/recorded/entire.com/steps/readme-without-metadata/step.json new file mode 100644 index 000000000..705a46788 --- /dev/null +++ b/test/fixtures/entire/recorded/entire.com/steps/readme-without-metadata/step.json @@ -0,0 +1,4 @@ +{ + "name": "readme without metadata", + "recordedAt": "2026-10-26T19:57:22.098Z" +} diff --git a/test/fixtures/entire/recorded/entire.com/steps/readme/01-get-01M5WS0P331VQ3AARB26Z9DGV7-raw.json b/test/fixtures/entire/recorded/entire.com/steps/readme/01-get-01M5WS0P331VQ3AARB26Z9DGV7-raw.json new file mode 100644 index 000000000..cb287450c --- /dev/null +++ b/test/fixtures/entire/recorded/entire.com/steps/readme/01-get-01M5WS0P331VQ3AARB26Z9DGV7-raw.json @@ -0,0 +1,11 @@ +{ + "request": { + "method": "GET", + "url": "https://aws-eu-west-2.api.entire.io/api/v1/git/repos/01M5WS0P331VQ3AARB26Z9DGV7/raw?ref=HEAD&path=README.md" + }, + "response": { + "status": 200, + "headers": {}, + "body": "# forges-fixtures\n\nA repository for the Entire recordings of [forges](https://forges.link), a forge client.\n" + } +} diff --git a/test/fixtures/entire/recorded/entire.com/steps/readme/golden.json b/test/fixtures/entire/recorded/entire.com/steps/readme/golden.json new file mode 100644 index 000000000..f80fc04a6 --- /dev/null +++ b/test/fixtures/entire/recorded/entire.com/steps/readme/golden.json @@ -0,0 +1,6 @@ +{ + "path": "README.md", + "size": 108, + "content": "# forges-fixtures\n\nA repository for the Entire recordings of [forges](https://forges.link), a forge client.\n", + "encoding": "utf-8" +} diff --git a/test/fixtures/entire/recorded/entire.com/steps/readme/step.json b/test/fixtures/entire/recorded/entire.com/steps/readme/step.json new file mode 100644 index 000000000..df00a3868 --- /dev/null +++ b/test/fixtures/entire/recorded/entire.com/steps/readme/step.json @@ -0,0 +1,4 @@ +{ + "name": "readme", + "recordedAt": "2026-10-26T19:57:21.909Z" +} diff --git a/test/fixtures/entire/recorded/entire.com/steps/repo-licence/01-get-repos-01M5WS0P331VQ3AARB26Z9DGV7.json b/test/fixtures/entire/recorded/entire.com/steps/repo-licence/01-get-repos-01M5WS0P331VQ3AARB26Z9DGV7.json new file mode 100644 index 000000000..44aab1e74 --- /dev/null +++ b/test/fixtures/entire/recorded/entire.com/steps/repo-licence/01-get-repos-01M5WS0P331VQ3AARB26Z9DGV7.json @@ -0,0 +1,42 @@ +{ + "request": { + "method": "GET", + "url": "https://aws-eu-west-2.api.entire.io/api/v1/repos/01M5WS0P331VQ3AARB26Z9DGV7" + }, + "response": { + "status": 200, + "headers": { + "link": "; rel=\"describedBy\"" + }, + "body": { + "$schema": "https://aws-eu-west-2.api.entire.io/api/v1/schemas/RepoListItem.json", + "owning_project_id": "01M5WS0JJNP4V9AW20MZ3MKF5M", + "id": "01M5WS0P331VQ3AARB26Z9DGV7", + "github_id": 0, + "name": "forges-fixtures", + "full_name": "forges/forges-fixtures", + "description": null, + "html_url": null, + "stargazers_count": 0, + "language": null, + "private": true, + "archived": false, + "updated_at": "2026-10-26T19:41:42.564Z", + "default_branch": "main", + "permission": "admin", + "capabilities": { + "data_role": "write", + "can_manage_settings": true, + "can_manage_access": true + }, + "checkpoint_count": 0, + "viewer_can_see_checkpoint_data": true, + "runners_enabled": false, + "trails_enabled": true, + "auto_run_on_push": false, + "public_sharing_enabled": false, + "open_pr_count": 0, + "repo_group_id": "01M5WS0P33VDWTEFK1HZ5QDEPA" + } + } +} diff --git a/test/fixtures/entire/recorded/entire.com/steps/repo-licence/golden.json b/test/fixtures/entire/recorded/entire.com/steps/repo-licence/golden.json new file mode 100644 index 000000000..e067fb171 --- /dev/null +++ b/test/fixtures/entire/recorded/entire.com/steps/repo-licence/golden.json @@ -0,0 +1,24 @@ +{ + "ref": { + "forge": "entire", + "instance": "entire.com", + "owner": "forges", + "name": "forges-fixtures", + "externalId": "01M5WS0P331VQ3AARB26Z9DGV7" + }, + "defaultBranch": "main", + "visibility": "private", + "isFork": false, + "isArchived": false, + "topics": [], + "updatedAt": "", + "stars": 0, + "openPullCount": 0, + "permissions": { + "admin": true, + "maintain": true, + "push": true, + "triage": true, + "pull": true + } +} diff --git a/test/fixtures/entire/recorded/entire.com/steps/repo-licence/step.json b/test/fixtures/entire/recorded/entire.com/steps/repo-licence/step.json new file mode 100644 index 000000000..b142cdf5e --- /dev/null +++ b/test/fixtures/entire/recorded/entire.com/steps/repo-licence/step.json @@ -0,0 +1,4 @@ +{ + "name": "repo licence", + "recordedAt": "2026-10-26T19:57:13.055Z" +} diff --git a/test/fixtures/entire/recorded/entire.com/steps/repo/01-get-repos-01M5WS0P331VQ3AARB26Z9DGV7.json b/test/fixtures/entire/recorded/entire.com/steps/repo/01-get-repos-01M5WS0P331VQ3AARB26Z9DGV7.json new file mode 100644 index 000000000..44aab1e74 --- /dev/null +++ b/test/fixtures/entire/recorded/entire.com/steps/repo/01-get-repos-01M5WS0P331VQ3AARB26Z9DGV7.json @@ -0,0 +1,42 @@ +{ + "request": { + "method": "GET", + "url": "https://aws-eu-west-2.api.entire.io/api/v1/repos/01M5WS0P331VQ3AARB26Z9DGV7" + }, + "response": { + "status": 200, + "headers": { + "link": "; rel=\"describedBy\"" + }, + "body": { + "$schema": "https://aws-eu-west-2.api.entire.io/api/v1/schemas/RepoListItem.json", + "owning_project_id": "01M5WS0JJNP4V9AW20MZ3MKF5M", + "id": "01M5WS0P331VQ3AARB26Z9DGV7", + "github_id": 0, + "name": "forges-fixtures", + "full_name": "forges/forges-fixtures", + "description": null, + "html_url": null, + "stargazers_count": 0, + "language": null, + "private": true, + "archived": false, + "updated_at": "2026-10-26T19:41:42.564Z", + "default_branch": "main", + "permission": "admin", + "capabilities": { + "data_role": "write", + "can_manage_settings": true, + "can_manage_access": true + }, + "checkpoint_count": 0, + "viewer_can_see_checkpoint_data": true, + "runners_enabled": false, + "trails_enabled": true, + "auto_run_on_push": false, + "public_sharing_enabled": false, + "open_pr_count": 0, + "repo_group_id": "01M5WS0P33VDWTEFK1HZ5QDEPA" + } + } +} diff --git a/test/fixtures/entire/recorded/entire.com/steps/repo/02-post-repos-resolve.json b/test/fixtures/entire/recorded/entire.com/steps/repo/02-post-repos-resolve.json new file mode 100644 index 000000000..1d83a6321 --- /dev/null +++ b/test/fixtures/entire/recorded/entire.com/steps/repo/02-post-repos-resolve.json @@ -0,0 +1,48 @@ +{ + "request": { + "method": "POST", + "url": "https://us.console.entire.io/api/v1/repos/resolve" + }, + "response": { + "status": 200, + "headers": { + "link": "; rel=\"describedBy\"" + }, + "body": { + "$schema": "https://us.console.entire.io/api/v1/schemas/ResolveReposResponse.json", + "resolutions": [ + { + "provider": "entire", + "requestedFullName": "forges/forges-fixtures", + "fullName": "forges/forges-fixtures", + "status": "ready", + "repoId": "01M5WS0P331VQ3AARB26Z9DGV7", + "repoGroupId": "01M5WS0P33VDWTEFK1HZ5QDEPA", + "placements": [ + { + "id": "01M5WS0P331VQ3AARB26Z9DGV7", + "jurisdiction": "uk", + "cell": "aws-eu-west-2", + "apiBaseUrl": "https://aws-eu-west-2.api.entire.io", + "clusterSlug": "aws-eu-west-2", + "mirror": false, + "status": "ready" + } + ], + "primaries": { + "git_data": "entire:01M5WS0P331VQ3AARB26Z9DGV7", + "processing": "01M5WS0P331VQ3AARB26Z9DGV7", + "data_primary": { + "forge": "entire", + "repo_id": "01M5WS0P331VQ3AARB26Z9DGV7" + }, + "processing_primary": { + "forge": "entire", + "repo_id": "01M5WS0P331VQ3AARB26Z9DGV7" + } + } + } + ] + } + } +} diff --git a/test/fixtures/entire/recorded/entire.com/steps/repo/golden.json b/test/fixtures/entire/recorded/entire.com/steps/repo/golden.json new file mode 100644 index 000000000..eb84ea979 --- /dev/null +++ b/test/fixtures/entire/recorded/entire.com/steps/repo/golden.json @@ -0,0 +1,24 @@ +{ + "ref": { + "forge": "entire", + "instance": "entire.com", + "owner": "forges", + "name": "forges-fixtures", + "externalId": "01M5WS0P331VQ3AARB26Z9DGV7" + }, + "defaultBranch": "main", + "visibility": "private", + "isFork": false, + "isArchived": false, + "topics": [], + "updatedAt": "2026-10-26T19:41:42.564Z", + "stars": 0, + "openPullCount": 0, + "permissions": { + "admin": true, + "maintain": true, + "push": true, + "triage": true, + "pull": true + } +} diff --git a/test/fixtures/entire/recorded/entire.com/steps/repo/step.json b/test/fixtures/entire/recorded/entire.com/steps/repo/step.json new file mode 100644 index 000000000..254fc7494 --- /dev/null +++ b/test/fixtures/entire/recorded/entire.com/steps/repo/step.json @@ -0,0 +1,4 @@ +{ + "name": "repo", + "recordedAt": "2026-10-26T21:02:24.670Z" +} diff --git a/test/fixtures/entire/recorded/entire.com/steps/resolve-default-branch/01-get-01M5WS0P331VQ3AARB26Z9DGV7-commits.json b/test/fixtures/entire/recorded/entire.com/steps/resolve-default-branch/01-get-01M5WS0P331VQ3AARB26Z9DGV7-commits.json new file mode 100644 index 000000000..1997b17c1 --- /dev/null +++ b/test/fixtures/entire/recorded/entire.com/steps/resolve-default-branch/01-get-01M5WS0P331VQ3AARB26Z9DGV7-commits.json @@ -0,0 +1,35 @@ +{ + "request": { + "method": "GET", + "url": "https://aws-eu-west-2.api.entire.io/api/v1/git/repos/01M5WS0P331VQ3AARB26Z9DGV7/commits?ref=main&pageSize=1" + }, + "response": { + "status": 200, + "headers": { + "link": "; rel=\"describedBy\"" + }, + "body": { + "$schema": "https://aws-eu-west-2.api.entire.io/api/v1/schemas/ListCommitsResponse.json", + "commits": [ + { + "sha": "dd07002e23c86b5e68d53ebe9949e1bf5549c8ca", + "parents": [ + "8127b4c88662985c819a6b3cabecde203907c3e2" + ], + "message": "docs: say what forges is\n", + "author": { + "name": "forges fixtures", + "email": "redacted@example.invalid", + "date": "2026-10-02T11:00:00Z" + }, + "committer": { + "name": "forges fixtures", + "email": "redacted@example.invalid", + "date": "2026-10-02T11:00:00Z" + } + } + ], + "nextPageToken": "eyJmIjpbIjgxMjdiNGM4ODY2Mjk4NWM4MTlhNmIzY2FiZWNkZTIwMzkwN2MzZTIiXX0" + } + } +} diff --git a/test/fixtures/entire/recorded/entire.com/steps/resolve-default-branch/golden.json b/test/fixtures/entire/recorded/entire.com/steps/resolve-default-branch/golden.json new file mode 100644 index 000000000..fae5a61ad --- /dev/null +++ b/test/fixtures/entire/recorded/entire.com/steps/resolve-default-branch/golden.json @@ -0,0 +1 @@ +"dd07002e23c86b5e68d53ebe9949e1bf5549c8ca" diff --git a/test/fixtures/entire/recorded/entire.com/steps/resolve-default-branch/step.json b/test/fixtures/entire/recorded/entire.com/steps/resolve-default-branch/step.json new file mode 100644 index 000000000..48e0732aa --- /dev/null +++ b/test/fixtures/entire/recorded/entire.com/steps/resolve-default-branch/step.json @@ -0,0 +1,7 @@ +{ + "name": "resolve default branch", + "recordedAt": "2026-10-26T19:57:23.390Z", + "needs": [ + "repo" + ] +} diff --git a/test/fixtures/entire/recorded/entire.com/steps/tags/01-get-01M5WS0P331VQ3AARB26Z9DGV7-refs.json b/test/fixtures/entire/recorded/entire.com/steps/tags/01-get-01M5WS0P331VQ3AARB26Z9DGV7-refs.json new file mode 100644 index 000000000..56c9c3ad7 --- /dev/null +++ b/test/fixtures/entire/recorded/entire.com/steps/tags/01-get-01M5WS0P331VQ3AARB26Z9DGV7-refs.json @@ -0,0 +1,26 @@ +{ + "request": { + "method": "GET", + "url": "https://aws-eu-west-2.api.entire.io/api/v1/git/repos/01M5WS0P331VQ3AARB26Z9DGV7/refs?prefix=refs%2Ftags%2F&peel=true&symrefs=true&pageSize=3" + }, + "response": { + "status": 200, + "headers": { + "link": "; rel=\"describedBy\"" + }, + "body": { + "$schema": "https://aws-eu-west-2.api.entire.io/api/v1/schemas/ListRefsResponse.json", + "refs": [ + { + "name": "refs/tags/v0.0.1", + "oid": "fc6d8c9fb93b340e7d064fee866d49d70073ff34" + }, + { + "name": "refs/tags/v0.1.0", + "oid": "5637ee18aa488d037aabeea7ce5981ba2037b50c", + "peeled": "8127b4c88662985c819a6b3cabecde203907c3e2" + } + ] + } + } +} diff --git a/test/fixtures/entire/recorded/entire.com/steps/tags/golden.json b/test/fixtures/entire/recorded/entire.com/steps/tags/golden.json new file mode 100644 index 000000000..1e2534193 --- /dev/null +++ b/test/fixtures/entire/recorded/entire.com/steps/tags/golden.json @@ -0,0 +1,12 @@ +{ + "items": [ + { + "name": "v0.0.1", + "sha": "fc6d8c9fb93b340e7d064fee866d49d70073ff34" + }, + { + "name": "v0.1.0", + "sha": "8127b4c88662985c819a6b3cabecde203907c3e2" + } + ] +} diff --git a/test/fixtures/entire/recorded/entire.com/steps/tags/step.json b/test/fixtures/entire/recorded/entire.com/steps/tags/step.json new file mode 100644 index 000000000..32f54b4cf --- /dev/null +++ b/test/fixtures/entire/recorded/entire.com/steps/tags/step.json @@ -0,0 +1,4 @@ +{ + "name": "tags", + "recordedAt": "2026-10-26T19:57:23.212Z" +} diff --git a/test/fixtures/entire/recorded/entire.com/steps/tree-file/01-get-01M5WS0P331VQ3AARB26Z9DGV7-raw.json b/test/fixtures/entire/recorded/entire.com/steps/tree-file/01-get-01M5WS0P331VQ3AARB26Z9DGV7-raw.json new file mode 100644 index 000000000..3d39b7d2a --- /dev/null +++ b/test/fixtures/entire/recorded/entire.com/steps/tree-file/01-get-01M5WS0P331VQ3AARB26Z9DGV7-raw.json @@ -0,0 +1,11 @@ +{ + "request": { + "method": "GET", + "url": "https://aws-eu-west-2.api.entire.io/api/v1/git/repos/01M5WS0P331VQ3AARB26Z9DGV7/raw?ref=HEAD&path=LICENCE" + }, + "response": { + "status": 200, + "headers": {}, + "body": "MIT License\n\nCopyright (c) 2026 forges fixtures\n\nPermission is hereby granted, free of charge, to any person obtaining a copy\nof this software and associated documentation files (the \"Software\"), to deal\nin the Software without restriction, including without limitation the rights\nto use, copy, modify, merge, publish, distribute, sublicense, and/or sell\ncopies of the Software, and to permit persons to whom the Software is\nfurnished to do so, subject to the following conditions:\n\nThe above copyright notice and this permission notice shall be included in all\ncopies or substantial portions of the Software.\n\nTHE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\nIMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\nFITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\nAUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\nLIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\nOUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE\nSOFTWARE.\n" + } +} diff --git a/test/fixtures/entire/recorded/entire.com/steps/tree-file/golden.json b/test/fixtures/entire/recorded/entire.com/steps/tree-file/golden.json new file mode 100644 index 000000000..db284e859 --- /dev/null +++ b/test/fixtures/entire/recorded/entire.com/steps/tree-file/golden.json @@ -0,0 +1,6 @@ +{ + "path": "LICENCE", + "size": 1072, + "content": "MIT License\n\nCopyright (c) 2026 forges fixtures\n\nPermission is hereby granted, free of charge, to any person obtaining a copy\nof this software and associated documentation files (the \"Software\"), to deal\nin the Software without restriction, including without limitation the rights\nto use, copy, modify, merge, publish, distribute, sublicense, and/or sell\ncopies of the Software, and to permit persons to whom the Software is\nfurnished to do so, subject to the following conditions:\n\nThe above copyright notice and this permission notice shall be included in all\ncopies or substantial portions of the Software.\n\nTHE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\nIMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\nFITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\nAUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\nLIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\nOUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE\nSOFTWARE.\n", + "encoding": "utf-8" +} diff --git a/test/fixtures/entire/recorded/entire.com/steps/tree-file/step.json b/test/fixtures/entire/recorded/entire.com/steps/tree-file/step.json new file mode 100644 index 000000000..78cd3807b --- /dev/null +++ b/test/fixtures/entire/recorded/entire.com/steps/tree-file/step.json @@ -0,0 +1,7 @@ +{ + "name": "tree file", + "recordedAt": "2026-10-26T19:57:22.772Z", + "needs": [ + "tree" + ] +} diff --git a/test/fixtures/entire/recorded/entire.com/steps/tree/01-get-01M5WS0P331VQ3AARB26Z9DGV7-tree.json b/test/fixtures/entire/recorded/entire.com/steps/tree/01-get-01M5WS0P331VQ3AARB26Z9DGV7-tree.json new file mode 100644 index 000000000..ee95b4058 --- /dev/null +++ b/test/fixtures/entire/recorded/entire.com/steps/tree/01-get-01M5WS0P331VQ3AARB26Z9DGV7-tree.json @@ -0,0 +1,54 @@ +{ + "request": { + "method": "GET", + "url": "https://aws-eu-west-2.api.entire.io/api/v1/git/repos/01M5WS0P331VQ3AARB26Z9DGV7/tree?ref=HEAD" + }, + "response": { + "status": 200, + "headers": { + "link": "; rel=\"describedBy\"" + }, + "body": { + "$schema": "https://aws-eu-west-2.api.entire.io/api/v1/schemas/GetTreeResponse.json", + "sha": "f6bd8f24e749f053439a5c5adc275b42762e04e1", + "entries": [ + { + "path": "LICENCE", + "mode": "100644", + "type": "blob", + "sha": "5ce04d65bd2730e802c0ecd64a3d375bd0e24181", + "size": 1072 + }, + { + "path": "README.md", + "mode": "100644", + "type": "blob", + "sha": "5e0c7c77ed6919d484c7bf5956816ad63dd2e5ed", + "size": 108 + }, + { + "path": "cli.ts", + "mode": "100644", + "type": "blob", + "sha": "d5da9c7b1a41ace3ab5cedf0176e9c3ad0dbe592", + "size": 82 + }, + { + "path": "package.json", + "mode": "100644", + "type": "blob", + "sha": "674b2088dda09d12850a9c65ac84ff90b9730b6b", + "size": 71 + }, + { + "path": "src", + "mode": "040000", + "type": "tree", + "sha": "88b193b2013af32600d786477091f6b73d83482a", + "size": 0 + } + ], + "truncated": false + } + } +} diff --git a/test/fixtures/entire/recorded/entire.com/steps/tree/golden.json b/test/fixtures/entire/recorded/entire.com/steps/tree/golden.json new file mode 100644 index 000000000..39c639708 --- /dev/null +++ b/test/fixtures/entire/recorded/entire.com/steps/tree/golden.json @@ -0,0 +1,28 @@ +{ + "items": [ + { + "path": "LICENCE", + "type": "file", + "sha": "5ce04d65bd2730e802c0ecd64a3d375bd0e24181", + "size": 1072, + "mode": "100644" + }, + { + "path": "README.md", + "type": "file", + "sha": "5e0c7c77ed6919d484c7bf5956816ad63dd2e5ed", + "size": 108, + "mode": "100644" + }, + { + "path": "cli.ts", + "type": "file", + "sha": "d5da9c7b1a41ace3ab5cedf0176e9c3ad0dbe592", + "size": 82, + "mode": "100644" + } + ], + "cursor": { + "token": "3" + } +} diff --git a/test/fixtures/entire/recorded/entire.com/steps/tree/step.json b/test/fixtures/entire/recorded/entire.com/steps/tree/step.json new file mode 100644 index 000000000..acffc27dc --- /dev/null +++ b/test/fixtures/entire/recorded/entire.com/steps/tree/step.json @@ -0,0 +1,4 @@ +{ + "name": "tree", + "recordedAt": "2026-10-26T19:57:22.603Z" +} diff --git a/test/recorded.test.ts b/test/recorded.test.ts index 10a7c2f2a..2ac06c3af 100644 --- a/test/recorded.test.ts +++ b/test/recorded.test.ts @@ -40,7 +40,7 @@ const REASONS: NotificationReason[] = [ /** The forges, by display name, on which a recording reads each listing again with its first page's `etag`. */ const conditionalListings = new Map>() -const FORGE_NAMES: Record = { 'github': 'GitHub', 'gitlab': 'GitLab', 'bitbucket': 'Bitbucket', 'forgejo': 'Forgejo', 'gitea': 'Gitea', 'gitee': 'Gitee', 'azure-devops': 'Azure DevOps', 'cursor-origin': 'Cursor Origin', 'pushin': 'Pushin.eu', 'tangled': 'Tangled', 'cloudflare-artifacts': 'Cloudflare Artifacts', 'sourcehut': 'Sourcehut' } +const FORGE_NAMES: Record = { 'github': 'GitHub', 'gitlab': 'GitLab', 'bitbucket': 'Bitbucket', 'forgejo': 'Forgejo', 'gitea': 'Gitea', 'gitee': 'Gitee', 'azure-devops': 'Azure DevOps', 'cursor-origin': 'Cursor Origin', 'pushin': 'Pushin.eu', 'tangled': 'Tangled', 'cloudflare-artifacts': 'Cloudflare Artifacts', 'sourcehut': 'Sourcehut', 'entire': 'Entire' } function sameRequest(a: string, b: string): boolean { const [first, second] = [new URL(a), new URL(b)] diff --git a/test/recording/replay.ts b/test/recording/replay.ts index 779149204..20aa59730 100644 --- a/test/recording/replay.ts +++ b/test/recording/replay.ts @@ -5,6 +5,7 @@ import { generateKeyPairSync } from 'node:crypto' import { azureDevOps } from '../../src/azure-devops/index.ts' import { bitbucket } from '../../src/bitbucket/index.ts' import { cloudflareArtifacts } from '../../src/cloudflare-artifacts/index.ts' +import { entire } from '../../src/entire/index.ts' import { forgejo } from '../../src/forgejo/index.ts' import { gitea } from '../../src/gitea/index.ts' import { gitee } from '../../src/gitee/index.ts' @@ -32,6 +33,7 @@ export const REPLAYED_PROVIDERS: Array<{ name: string, create: Create }> = [ { name: 'cloudflare-artifacts', create: (fetch, manifest) => cloudflareArtifacts({ auth: token, accountId: manifest.repo.instance.split('.')[0]!, baseUrl: manifest.baseUrl, fetch }) }, { name: 'pushin', create: (fetch, manifest) => pushin({ auth: authFor(manifest), baseUrl: manifest.baseUrl, fetch }) }, { name: 'sourcehut', create: (fetch, manifest) => sourcehut({ auth: authFor(manifest) ?? token, baseUrl: manifest.baseUrl, fetch }) }, + { name: 'entire', create: (fetch, manifest) => entire({ auth: token, baseUrl: manifest.baseUrl, fetch }) }, { name: 'gitee', create: (fetch, manifest) => gitee({ auth: authFor(manifest), fetch }) }, { name: 'azure-devops', create: (fetch, manifest) => azureDevOps({ auth: authFor(manifest), organization: manifest.repo.owner.split('/')[0]!, fetch }) }, { diff --git a/test/unit/auth.test.ts b/test/unit/auth.test.ts index e38f943d1..b12c9bee4 100644 --- a/test/unit/auth.test.ts +++ b/test/unit/auth.test.ts @@ -5,6 +5,7 @@ import { azureDevOps } from '../../src/azure-devops/index.ts' import { bitbucket } from '../../src/bitbucket/index.ts' import { cloudflareArtifacts } from '../../src/cloudflare-artifacts/index.ts' import { cursorOrigin } from '../../src/cursor-origin/index.ts' +import { entire } from '../../src/entire/index.ts' import { forgejo } from '../../src/forgejo/index.ts' import { gitea } from '../../src/gitea/index.ts' import { gitee } from '../../src/gitee/index.ts' @@ -27,6 +28,7 @@ const FACTORIES: Record = { 'pushin': (token, fetch) => pushin({ auth: { type: 'token', token }, fetch }), 'cloudflare-artifacts': (token, fetch) => cloudflareArtifacts({ auth: { type: 'token', token }, accountId: 'acme', fetch }), 'sourcehut': (token, fetch) => sourcehut({ auth: { type: 'token', token }, fetch }), + 'entire': (token, fetch) => entire({ auth: { type: 'token', token }, fetch }), } describe('token auth', () => { diff --git a/test/unit/entire.test.ts b/test/unit/entire.test.ts new file mode 100644 index 000000000..f43c2003a --- /dev/null +++ b/test/unit/entire.test.ts @@ -0,0 +1,66 @@ +import { describe, expect, it } from 'vitest' +import { entire } from '../../src/entire/index.ts' +import { BranchMovedError, UnsupportedOperationError } from '../../src/errors.ts' +import { fixtureFetch } from '../../src/testing/index.ts' + +const origin = { forge: 'entire', instance: 'entire.com' } as const +const repo = { ...origin, owner: 'acme', name: 'widgets' } +const pull = { ...origin, repo, kind: 'pull_request', number: '3' } as const +const core = 'https://us.console.entire.io/api/v1' +const cell = 'https://aws-eu-west-2.api.entire.io/api/v1' +const change = `${cell}/trails/et/acme/widgets/3` +const resolved = { status: 200, body: { resolutions: [{ requestedFullName: 'acme/widgets', status: 'resolved', placements: [{ id: 'repo1', apiBaseUrl: 'https://aws-eu-west-2.api.entire.io' }] }] } } + +function provider(overrides: Parameters[1]) { + const fixtures = fixtureFetch([], { [`POST ${core}/repos/resolve`]: resolved, ...overrides }) + return { ...fixtures, forge: entire({ auth: { type: 'token', token: 't' }, fetch: fixtures.fetch }) } +} + +describe('entire', () => { + it('quotes the commented lines of the change head in a line finding', async () => { + const finding = { id: 'f1', review_id: 'r1', status: 'open', created_at: '2026-01-01T00:00:00Z', body: 'Shout less', location: { granularity: 'range', file_path: 'src/a.ts', start_line: 2, end_line: 3 } } + const { forge, calls } = provider({ + [`GET ${change}`]: { status: 200, body: { id: 'c1', number: 3, title: 'Shout', status: 'open', branch: 'feat', base: 'main', head_sha: 'abc' } }, + [`GET ${cell}/git/repos/repo1/raw?ref=abc&path=src%2Fa.ts`]: { status: 200, body: 'one\ntwo\nthree\nfour\n' }, + [`POST ${change}/reviews`]: { status: 201, body: { review_id: 'r1' } }, + [`POST ${change}/reviews/r1/comments`]: { status: 201, body: { results: [{ client_id: '1', status: 'created', comment: finding }] } }, + }) + + const review = await forge.threads.createReview(pull, { event: 'comment', body: 'Summary', comments: [{ path: 'src/a.ts', startLine: 2, line: 3, body: 'Shout less' }] }) + + expect(JSON.parse(calls.find(call => call.url.endsWith('/reviews/r1/comments'))!.body!)).toEqual({ + summary: 'Summary', + comments: [{ client_id: '1', body: 'Shout less', location: { granularity: 'range', file_path: 'src/a.ts', start_line: 2, end_line: 3, selected_text: 'two\nthree' } }], + }) + expect(review).toMatchObject({ state: 'commented', body: 'Summary' }) + }) + + it('recomputes pending gates once before merging again', async () => { + const merge = { method: 'POST', url: `${cell}/repos/repo1/trails/3/merge` } + const { fetch, calls } = fixtureFetch([ + { handAuthored: true, request: merge, response: { status: 422, body: { code: 'merge_gates_pending' } } }, + { handAuthored: true, request: merge, response: { status: 200, body: { ok: true, mergeCommitSha: 'def' } } }, + ], { + [`POST ${core}/repos/resolve`]: resolved, + [`POST ${cell}/repos/repo1/trails/3/gates/recompute`]: { status: 200, body: {} }, + }, { sequential: true }) + const forge = entire({ auth: { type: 'token', token: 't' }, fetch }) + + expect(await forge.threads.merge(pull, { sha: 'abc' })).toMatchObject({ status: 'merged', sha: 'def' }) + expect(calls.map(call => call.url.replace(cell, ''))).toEqual([`${core}/repos/resolve`, '/repos/repo1/trails/3/merge', '/repos/repo1/trails/3/gates/recompute', '/repos/repo1/trails/3/merge']) + }) + + it.each([412, 409])('reads a %i from a merge at a stale sha as a moved branch', async (status) => { + const { forge } = provider({ + [`POST ${cell}/repos/repo1/trails/3/merge`]: { status, body: { code: 'head_mismatch' } }, + }) + await expect(forge.threads.merge(pull, { sha: 'abc' })).rejects.toBeInstanceOf(BranchMovedError) + }) + + it('refuses merge methods and labels that Entire has no equivalent for', async () => { + const { forge, calls } = provider({}) + await expect(forge.threads.merge(pull, { method: 'squash' })).rejects.toBeInstanceOf(UnsupportedOperationError) + await expect(forge.threads.create(repo, { kind: 'issue', title: 'A', labels: ['bug'] })).rejects.toBeInstanceOf(UnsupportedOperationError) + expect(calls).toEqual([]) + }) +}) diff --git a/test/unit/web-entry.test.ts b/test/unit/web-entry.test.ts index 31ca21abe..90e90a60c 100644 --- a/test/unit/web-entry.test.ts +++ b/test/unit/web-entry.test.ts @@ -19,6 +19,7 @@ const cases: Array<[keyof typeof web & keyof typeof providers, WebOptions, strin ['bitbucket', {}, ['https://bitbucket.org/acme/widgets/pull-requests/42']], ['azureDevOps', {}, ['https://dev.azure.com/contoso/Widgets/_git/widgets/pullrequest/42']], ['sourcehut', {}, [`https://git.sr.ht/~acme/widgets/commit/${sha}`]], + ['entire', {}, ['https://entire.com/et/acme/widgets/trails/2', 'https://entire.com/et/acme/-/trails/1']], ['tangled', {}, ['https://tangled.sh/@acme.dev/core/issues/4', 'https://tangled.sh/@acme.dev/core/compare/main...feat']], ] diff --git a/tsdown.config.ts b/tsdown.config.ts index dbae5d908..d626c23d0 100644 --- a/tsdown.config.ts +++ b/tsdown.config.ts @@ -3,7 +3,7 @@ import { defineConfig } from 'tsdown' import { standaloneSchema } from './scripts/generate-schemas.ts' export default defineConfig({ - entry: ['src/index.ts', 'src/github/index.ts', 'src/gitlab/index.ts', 'src/bitbucket/index.ts', 'src/forgejo/index.ts', 'src/gitea/index.ts', 'src/tangled/index.ts', 'src/cursor-origin/index.ts', 'src/gitee/index.ts', 'src/pushin/index.ts', 'src/azure-devops/index.ts', 'src/cloudflare-artifacts/index.ts', 'src/sourcehut/index.ts', 'src/env.ts', 'src/helpers.ts', 'src/kit.ts', 'src/schema/index.ts', 'src/testing/index.ts', 'src/fake/index.ts', 'src/web/index.ts'], + entry: ['src/index.ts', 'src/github/index.ts', 'src/gitlab/index.ts', 'src/bitbucket/index.ts', 'src/forgejo/index.ts', 'src/gitea/index.ts', 'src/tangled/index.ts', 'src/cursor-origin/index.ts', 'src/gitee/index.ts', 'src/pushin/index.ts', 'src/azure-devops/index.ts', 'src/cloudflare-artifacts/index.ts', 'src/sourcehut/index.ts', 'src/entire/index.ts', 'src/env.ts', 'src/helpers.ts', 'src/kit.ts', 'src/schema/index.ts', 'src/testing/index.ts', 'src/fake/index.ts', 'src/web/index.ts'], dts: { generator: 'oxc' }, exports: { devExports: true,