Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
The table of contents is too big for display.
Diff view
Diff view
  •  
  •  
  •  
3 changes: 3 additions & 0 deletions docs/app/assets/icons/entire.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
233 changes: 233 additions & 0 deletions docs/content/4.providers/entire.md
Original file line number Diff line number Diff line change
@@ -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).

<!-- header:start -->
<!-- Generated by `pnpm capability-matrix`; do not edit by hand. -->
::provider-header{provider="entire"}
| Detail | Value |
| --- | --- |
| Import | `forges/entire` |
| Factories | `entire()` |
| Auth | `token` |
::
<!-- header:end -->

## 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 <token>`:

```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/<project>/-/trails/<number>`, and a change's page is `https://entire.com/et/<project>/<repository>/trails/<number>`. `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 `@<login>`.

`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:start -->
## Capabilities

<!-- Generated by `pnpm capability-matrix`; do not edit by hand. -->
::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 |
::
<!-- capabilities:end -->
1 change: 1 addition & 0 deletions docs/content/4.providers/index.md
Original file line number Diff line number Diff line change
Expand Up @@ -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()` |
::
<!-- capabilities:end -->

Expand Down
Loading
Loading