~ knotless Search/
↑↓ move↵ open⇧↵ all results

chadtmiller.com/pds.js

An atproto PDS in JavaScript, for Cloudflare Workers and Node

0
0
main
357 lines · 16.5 KB Raw History
# @pdsjs/git-ci

## 0.5.2

### Patch Changes

- Updated dependencies
  - @pdsjs/core@2.5.2
  - @pdsjs/git@0.1.5

## 0.5.1

### Patch Changes

- Updated dependencies [542c4dc]
  - @pdsjs/core@2.5.1
  - @pdsjs/git@0.1.4

## 0.5.0

### Minor Changes

- 861663f: Startup no longer adopts a ref whose latest check is still `running`. A run
  cut off mid-flight leaves its check record half written, and adopting the ref
  told the daemon that ref was handled, so nothing ever finished the record and
  the check read `running` for good. The runner's own check records outlive its
  state file, so startup reads them: a ref left mid-run stays unadopted and runs
  again on the next event for that repository.

### Patch Changes

- 04b15d0: The Jetstream re-exports are gone. `subscribeJetstream`, `jetstreamUrl` and
  `jetstreamWrite` were reachable from the package root, and nothing consumed
  them: the watch loop reads the repository's own firehose. `@pdsjs/appview`
  leaves the dependency list with them.
- 0466ca6: `@pdsjs/git-ci` exports its record-key module under `./spec`. A reader that
  wants the latest check for one ref computes the key rather than paging the
  runner's history, and the derivation has to match the runner's exactly. The
  root entry pulls in the checkout, the daemon and the firehose reader, so a
  browser could not import it; `./spec` holds the key functions alone.
- c3c4caa: A repository's config record carries two DID lists, `collaborators` and
  `reviewers`, read by `collaboratorsOf` and `reviewersOf`. A collaborator holds
  their own copy of the repository under the same name, and a reader that knows
  where to look can gather the open branches across every copy. atproto has no
  reverse index, so a copy names no upstream and an upstream finds no copy
  without being told. Neither list grants anything: nobody can write into
  somebody else's repo whatever they say.

  A pull request is a branch in one account's copy, identified by that account's
  DID and the ref name. The pair survives amend, rebase, force-push and a commit
  added on top, so a check or a review written against one version still names
  the work after any of them. A branch canonical main reaches is merged and one
  it does not is open, both read from the graph rather than from a stored state.

  The `dev.pdsjs.git.pull` lexicon describes what the author says about their own
  branch: a title, an optional `status` of draft or withdrawn, and a note. It is
  in the author's own repo and nothing is written to the repository it names. A
  push with no such record is still a pull request, titled by its tip commit.
  `dev.pdsjs.git.pulls` is the index a runner publishes of the records it has
  seen, under `pullsKey`, because atproto has no reverse index and the owner has
  no inbound address. The config may name several runners (`runnersOf`), and a
  reader unions their indexes, so one runner omitting a pull request does not
  bury it.

  The `dev.pdsjs.git.review` lexicon describes a verdict on one version of one
  pull request, published in the reviewer's own repo. `author` and `ref` name the
  pull request and `sha` names the version read, so a review of an earlier
  version still reads against the work and still says which version it answered.
  The verdicts are `approve`, `changesRequested` and `comment`.

  The browser reader gains `changedPaths`, `readRange` and `listRange`, which
  answer for two commits what `readCommit` and `listCommits` answer for one and
  for a ref. A pull request written over a dozen commits is one thing to read,
  and the paths it touches are one tree walk from its merge base rather than a
  diff per commit.

  The repository browser reads all of it on a pull request list. The model, and
  what is still unbuilt, is in `docs/plans/2026-08-24-pull-requests.md`.

- 83083a5: Issues, as the model's one primitive: a `dev.pdsjs.git.issue` record in its
  filer's own repo names the repository, a record with `replyTo` answers one,
  and the repository owner's record with a `disposition` is what a reader shows
  as the issue's state. Nobody closes an issue; the owner states resolved,
  declined or reopened, attributed, and disagreement sits beside it. The latest
  word wins, so each of the three is answered by another one and none of them
  shuts a thread. The repository's own server lists the statements, reading
  the listed voices from their own servers and finding anybody else through
  its discovery index, and the repository browser lists threads, files, and
  replies with the session the reviews use. A thread reads its state as a pill, and a
  disposition reads as the event it is rather than as another comment. The
  list holds an Open tab and a Closed one, each a real address, and closed
  holds both of the words the owner settles a thread with, so the mark on a
  row still says which. Both lists draw through one row, so a size moves in
  one place.
- 32db640: The pull request and issue lists are served by the repository's own server:
  `dev.pdsjs.git.listPulls` and `dev.pdsjs.git.listIssues`. The owner's copy
  is read through the server's browser, every collaborator the config names
  through a browser over their server, and anybody else through a discovery
  port that answers which records about the repository exist in accounts the
  config does not name. The first provider is Constellation, a hosted reverse
  index over the public firehose, asked once per collection on the path
  `subject.uri`; a deployment may pass its own port to `createGitExtension`,
  or null to read the listed voices alone. Open and merged are computed from
  the object graph on every read and stored nowhere. The repository browser
  asks its server for the two lists, where it read five servers itself.

  The runner is CI only. Its pull request index, issue index and push log
  (`dev.pdsjs.git.pulls`, `.issues`, `.versions`) and `PDSJS_CI_PULL_SOURCES`
  are gone, since the discovery port answers what the indexes did and the
  version numbers the push log fed left the interface. A check or comment
  written against a commit the branch has since replaced still reads as
  outdated, from the tips the checks and reviews themselves name.

  A push into a fork writes `upstream` on the pushed record, the repository
  record the copy was taken from, when the checkout's remotes say which that
  is. The repository's server asks its discovery index which copies name it and
  reads every branch of each, so a bare push into a fork is listed before its
  author has written a pull request record.

  An author still writes their own words from the page: a title, a note, and
  open, draft or withdrawn, as a `dev.pdsjs.git.pull` record in their own
  repo. The form appears for the account holding the branch and nobody else.

- a56be28: A pull request is identified by the account whose copy holds the work and the
  ref that holds it, in place of the `Change-Id:` trailer. The pair costs nothing
  to compute, needs no hook in the author's push path, and survives the one case
  the trailer did not: a commit added on top of a branch gave the tip a new
  trailer, which detached every check and review keyed to the old one.

  `git-remote-atproto install-hook` and the `changeId` fields on the check,
  review and index records go with it. A `dev.pdsjs.git.review` record names
  `author` and `ref` instead, and its verdicts are `approve`, `changesRequested`
  and `comment`.

  A merged branch is read from the merge that brought it in: the merge commit's
  second parent is the tip merged and its first parents are main's trunk, so the
  branch's earliest commit outside that trunk is where the work began. A branch
  fast-forwarded into main leaves no such commit and opens at its tip alone.

  The vocabulary follows the concept where the concept matches. `contributors`
  becomes `collaborators` in the config record (`collaboratorsOf`), and
  `dev.pdsjs.git.offer` becomes `dev.pdsjs.git.pull`, which gains a `title`. Work
  from an account the repository has not named sorts into the one list, marked as
  coming from a fork.

  The repository browser serves the list at `/<repo>/pulls`, with open and merged
  tabs, and one pull request at `/<repo>/pull/<did>/<branch>` with its diffs
  under `/files`.

  None of these lexicons is published, so there is nothing to migrate.

- f27dcf7: A git repository's record key is minted at creation, and its name is an
  ordinary field. The name was the key, so it was the identity, and renaming a
  repository changed its AT-URI: every review, pull request, issue and check
  naming it, every fork naming it upstream, and the reverse index all pointed at
  an address that no longer existed.

  The rule is that the name is an address and the key is an identity. Every
  public surface still takes a name, `resolveRepo` is the one place that turns
  one into a key, and everything below it works in keys. `dev.pdsjs.git.repo`
  already declared `key: 'any'` and already required `name`, so no record's
  value changes, only its key.

  `dev.pdsjs.git.renameRepo` writes that one field. A repository in a space
  keeps the name it has: the space is what an address resolves to and is keyed
  by that name.

  The config record moves to the repository's key, which the write guard already
  assumed when it joins the two. A collaborator's copy is found by the name the
  two copies share rather than by assuming their key matches. Pull request keys,
  check request keys and latest-check keys all derive from the repository's own
  key, so a rename leaves them where they are.

  `@pdsjs/git-ci` reads a repository's name from its record rather than from the
  firehose write's key, which a minted key would have matched against nothing.
  Its two key derivations are duplicated in the server and must agree, so the
  runner is deployed with it. Secret grants keep naming repositories the way a
  person writes them and resolve to a record key at startup, where a grant
  naming a repository the account does not hold is reported.

  Existing repositories are moved by `scripts/migrate-git-repo-keys.mjs`. The
  resolver finds an unmigrated repository unchanged, so a deploy can precede the
  migration. See `docs/plans/2026-09-04-stable-repo-keys.md`.

- Updated dependencies [d66fcff]
- Updated dependencies [05a11b4]
- Updated dependencies [f79dd82]
- Updated dependencies [c68858b]
- Updated dependencies [04b15d0]
- Updated dependencies [288063a]
- Updated dependencies [c3c4caa]
- Updated dependencies [bcb5758]
- Updated dependencies [e0b38cd]
- Updated dependencies [4fb8f23]
- Updated dependencies [1cf113d]
- Updated dependencies [04b15d0]
- Updated dependencies [c4af198]
- Updated dependencies [f777a2c]
- Updated dependencies [a981627]
- Updated dependencies [3febe1c]
- Updated dependencies [ac5c8eb]
- Updated dependencies [00bd461]
- Updated dependencies [83083a5]
- Updated dependencies [2c68bdc]
- Updated dependencies [fe7ffe0]
- Updated dependencies [211c7c8]
- Updated dependencies [6cf84d5]
- Updated dependencies [35f794f]
- Updated dependencies [522071f]
- Updated dependencies [32db640]
- Updated dependencies [04b15d0]
- Updated dependencies [cc4577b]
- Updated dependencies [cc4577b]
- Updated dependencies [f5aae7c]
- Updated dependencies [cc4577b]
- Updated dependencies [fe3c9ac]
- Updated dependencies [b99acf8]
- Updated dependencies [c1ec3d6]
- Updated dependencies [04b15d0]
- Updated dependencies [7c06024]
- Updated dependencies [6935a55]
- Updated dependencies [15c69af]
- Updated dependencies [a56be28]
- Updated dependencies [673ec05]
- Updated dependencies [74819af]
- Updated dependencies [4dfdbfa]
- Updated dependencies [04b15d0]
- Updated dependencies [aeb61f9]
- Updated dependencies [04b15d0]
- Updated dependencies [04b15d0]
- Updated dependencies [f27dcf7]
- Updated dependencies [c9e3550]
- Updated dependencies [c01859b]
- Updated dependencies [41df38b]
- Updated dependencies [411b47b]
- Updated dependencies [ca47f96]
- Updated dependencies [861663f]
- Updated dependencies [617df4a]
- Updated dependencies [154e7d7]
- Updated dependencies [10c91f6]
- Updated dependencies [0e1bf66]
- Updated dependencies [77eb9db]
- Updated dependencies [76f5187]
- Updated dependencies [b51250e]
- Updated dependencies [799286b]
- Updated dependencies [4adc49e]
- Updated dependencies [e83838c]
- Updated dependencies [9149663]
- Updated dependencies [16ea1fe]
- Updated dependencies [fd401a4]
- Updated dependencies [93816a1]
- Updated dependencies [3d475f8]
- Updated dependencies [078c2df]
- Updated dependencies [d5f111c]
  - @pdsjs/core@2.5.0
  - @pdsjs/git@0.1.3

## 0.4.0

### Minor Changes

- d307f57: The daemon reads each watched repository's refs at startup when its state
  file says nothing about them. Without that, a daemon whose state was lost
  read every ref in the record as new on the next event and started a run for
  each, so every tag ran its release workflow again. The first run now comes
  from a ref that moves after startup, which is what starting at the live head
  means. A repository whose record cannot be read is still watched, and its
  first event still runs it.
- 2d0d653: The runner image carries the docker client and buildx, and the entrypoint
  puts the daemon's user in the group of a mounted docker socket. A deployment
  that mounts one can then run workflows that build, run and push container
  images, which previously needed a forge. The socket is the whole grant: a
  step commanding the host's daemon is root on that host, so mount it only
  where every contributor to every watched repository is trusted that far.
  Without the mount nothing changes and no step can reach a daemon.

### Patch Changes

- Updated dependencies [d307f57]
- Updated dependencies [2d0d653]
  - @pdsjs/core@2.4.3

## 0.3.0

### Minor Changes

- c235e96: Workflow files may be YAML. A step is a shell script, and a block scalar
  carries one as written where a JSON string carries it as a single line of
  escaped newlines. The parser is YAML 1.2, which subsumes JSON, so existing
  `.json` workflows and the `.pdsjs/ci.json` fallback read unchanged. The
  workflows directory now reads `.yml`, `.yaml` and `.json`, and passes over
  anything else, so a README can sit beside the workflows it describes.

### Patch Changes

- Updated dependencies [c235e96]
  - @pdsjs/core@2.4.2

## 0.2.0

### Minor Changes

- fa1558c: The runner reads one workflow per file from `.pdsjs/workflows/*.json`, falling
  back to `.pdsjs/ci.json` when the directory is absent. Every workflow naming
  the moved ref runs and publishes its own check; the latest-check record holds
  one entry per workflow under the unchanged key, and the account checks
  endpoint flattens the entries, reading records from before entries existed as
  one entry. Workflows declare secrets by name, and the daemon grants them per
  repository from the file `PDSJS_CI_SECRETS` names; the runner's own
  credentials no longer reach any step's environment. The runner image is based
  on trixie so a repository under test can load prebuilt native addons that
  need glibc 2.38.

### Patch Changes

- Updated dependencies [fa1558c]
  - @pdsjs/core@2.4.1

## 0.1.1

### Patch Changes

- 4895bc1: A repository's owner can ask for a check run. The daemon listens on no port,
  so the request is a record: `dev.pdsjs.git.checkRequest` in the owner's own
  repo, which the firehose connection the daemon already holds carries to it.
  The record's authority is the authorisation, since only the owner can write
  into that repo, and the runner acts on a request only for a repository it
  watches. The record key is derived from the repository and the ref, so asking
  twice replaces the record rather than leaving one per click, and the state
  file remembers the version acted on so a replayed event starts no second run.

  `sha` is optional: without it the run takes whatever the ref points at when
  the daemon reads the repository record.

- 0665ecc: Check record writes retry twice on a server error or a dropped connection
  before the run is abandoned. One transient failure on the outcome write
  used to leave the check `running` forever, indistinguishable from a
  runner that died mid-run. A client error, such as a failed swap, still
  throws at once.
- Updated dependencies [ee6d696]
- Updated dependencies [cb64c59]
- Updated dependencies [54bec84]
- Updated dependencies [922fb50]
- Updated dependencies [68ad18f]
- Updated dependencies [f716d9d]
- Updated dependencies [68ad18f]
- Updated dependencies [68ad18f]
- Updated dependencies [ae02630]
- Updated dependencies [68ad18f]
- Updated dependencies [4c334b3]
- Updated dependencies [86d8eb4]
- Updated dependencies [6b79149]
- Updated dependencies [8616855]
- Updated dependencies [af8b1fd]
- Updated dependencies [715c475]
  - @pdsjs/core@2.4.0
  - @pdsjs/git@0.1.2