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

chadtmiller.com/pds.js

An atproto PDS in JavaScript, for Cloudflare Workers and Node

0
0
main
55 lines · 2.1 KB Raw History
// Merging a pull request, which is the one act in this model that moves the
// repository's canonical branch.
//
// Everything else the page writes goes into the visitor's own repo. This
// writes the repository record, so it runs as the owner, on the owner's own
// PDS, under the owner's OAuth session. The server accepts it only from a
// token whose account is the repository's, so nobody else's session merges,
// and the grant reaches no repository but the owner's own.

import { XrpcError } from '@pdsjs/git/client';
import { account } from '#/lib/git.js';
import { authedFetch } from '#/lib/oauth.js';

/**
 * Put a pull request's work on the canonical branch.
 *
 * A squash is the change, so it takes the change's title. A merge is a record
 * of taking the change rather than the change itself, so it names the branch
 * the way `git merge` does and the title is not its subject.
 * @param {import('#/lib/oauth.js').Session} session - the owner's own
 * @param {string} repo - repository name on this site
 * @param {{author: {did: string, handle: string}, branch: string, title: string}} pull
 * @param {'merge'|'squash'} mode
 * @returns {Promise<{sha: string, ref: string, objects: number}>}
 */
export async function mergePull(session, repo, pull, mode) {
  const response = await authedFetch(
    session,
    `${account.pds}/xrpc/dev.pdsjs.git.mergePull`,
    {
      method: 'POST',
      headers: { 'content-type': 'application/json' },
      body: JSON.stringify({
        name: repo,
        did: pull.author.did,
        ref: `refs/heads/${pull.branch}`,
        mode,
        handle: pull.author.handle,
        ...(mode === 'squash' && pull.title ? { subject: pull.title } : {}),
      }),
    },
  );
  const body = await response.json().catch(() => ({}));
  if (!response.ok) {
    // A grant made before the scope named the repository record cannot
    // merge; the session provider sends such a session back through consent,
    // so this reports only what a fresh grant still could not do.
    throw new XrpcError(
      response.status,
      body.error ?? 'Unknown',
      body.message ?? `The merge failed (${response.status}).`,
    );
  }
  return body;
}