Skip to content

Internal PR Gate: Block upstream push until internal fork PR is approved #11

@coopernetes

Description

@coopernetes

Depends on: #10 (Mirror Sync) — the internal fork must exist before this gate can function.

Problem

Once an internal mirror exists, teams want to do collaborative work — code review, security scanning, licence compliance — on that fork before changes are pushed upstream through jgit-proxy. Today jgit-proxy has no way to verify that an internal review has happened and passed.

Missing: a push-time gate that looks up the corresponding internal fork PR and blocks the push if the PR is not approved or required status checks have not passed.

Proposed Design

Core interface: InternalPRGateCheck

Shared service in jgit-proxy-core with thin adapters for each execution path:

  • InternalPRGateHook (store-and-forward) — implements PreReceiveHook, streams result live via rp.sendMessage()
  • InternalPRGateFilter (transparent proxy) — implements GitProxyFilter at order 200, accumulates result and calls sendGitError

GitHubPRGateCheck (initial implementation)

GitHub REST API v3 / GHE 3.x compatible. Logic per push:

  1. Resolve internal fork coordinates from push destination URL
  2. Find open PR: GET /repos/{owner}/{repo}/pulls?head={org}:{branch}&state=open — fail if none
  3. Check approvals: GET /repos/{owner}/{repo}/pulls/{pull_number}/reviews — fail if approved count < min
  4. Check status checks: GET /repos/{owner}/{repo}/commits/{sha}/check-runs — fail if required check not completed/success

Steps 2–4 can run in parallel; gate result is their conjunction.

Tasks

  • Define InternalPRGateCheck interface and PRGateResult record in jgit-proxy-core
  • Implement InternalPRGateHook (PreReceiveHook adapter — streams messages to git client on failure)
  • Implement InternalPRGateFilter (GitProxyFilter at order 200)
  • Implement GitHubPRGateCheck with parallelised PR lookup, approval check, and status-check queries
  • Add YAML config block (git-proxy.mirror.pr-gate.*: enabled, min-approvals, required-app-slug, block-if-no-pr, block-if-app-not-installed)
  • Add short-TTL cache (10–30 s) on PR and check-run responses to stay within GitHub API rate limits
  • Unit tests for pass/fail cases: missing PR, insufficient approvals, failing checks

Open Questions

  • Branch name mapping: push branch may not match internal PR head branch 1:1; need configurable lookup strategy (by branch name, commit SHA, or PR label)
  • Multiple internal forks: all mirrors need an approved PR, or just one?
  • GitLab / Bitbucket variants: InternalPRGateCheck is provider-agnostic; additional implementations can be added without touching the adapters

Metadata

Metadata

Assignees

No one assigned

    Type

    No type
    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions