49 lines · 1.8 KB
import { all } from "./db";
import { ZERO_SHA } from "./git/store";
import type { RepoRow } from "~/lib/types";

const RECENT_WINDOW_MS = 2 * 60 * 60 * 1000;
const MAX_SUGGESTIONS = 3;
const HEADS_PREFIX = "refs/heads/";

export type RecentBranchPush = { branch: string; pushedAt: number };

type PushRow = { ref: string; after_sha: string; created_at: number };

/**
 * Branches the viewer pushed recently that have no open pull request yet, newest first. Only the latest
 * push per ref counts, so a branch that was pushed and then deleted does not get suggested.
 */
export async function recentBranchPushesFor(
  repo: Pick<RepoRow, "id" | "default_branch">,
  viewerId: string,
  now = Date.now(),
) {
  const rows = await all<PushRow>(
    `SELECT p.ref, p.after_sha, p.created_at FROM push_events p
     WHERE p.repo_id = ?1 AND p.pusher_id = ?2 AND p.created_at >= ?3 AND p.ref LIKE 'refs/heads/%'
       AND p.created_at = (
         SELECT MAX(q.created_at) FROM push_events q WHERE q.repo_id = ?1 AND q.ref = p.ref
       )
       AND NOT EXISTS (
         SELECT 1 FROM pull_requests pr JOIN issues i ON i.id = pr.issue_id
         WHERE pr.head_repo_id = ?1 AND pr.head_ref = substr(p.ref, ?4) AND i.state = 'open'
       )
     ORDER BY p.created_at DESC`,
    repo.id,
    viewerId,
    now - RECENT_WINDOW_MS,
    HEADS_PREFIX.length + 1,
  );
  const suggestions: RecentBranchPush[] = [];
  for (const row of rows) {
    if (row.after_sha === ZERO_SHA) continue;