Metadata-Version: 2.4
Name: patch-via-github
Version: 1.0.0
Summary: Tool used to modify a local 'repo sync' with changes from GitHub pull requests
Requires-Python: ==3.14.*
Description-Content-Type: text/markdown
License-File: LICENSE
Requires-Dist: requests==2.34.2
Requires-Dist: urllib3==2.8.0

# patch\_via\_github

`patch_via_github` is a command-line tool for applying GitHub pull request
changes to a [`repo sync`](https://source.android.com/docs/setup/download/downloading)
workspace. It automates the process of fetching and cherry-picking (or checking
out) PRs from GitHub, with manifest-aware project resolution.

This is the GitHub counterpart to
[`patch_via_gerrit`](https://github.com/couchbase/patch_via_gerrit). The two
tools can be used together on the same `repo sync` workspace — each targets
its own set of PRs/reviews independently.

## Installation

The easiest way to run `patch_via_github` is with `uvx`, which needs no
separate install step:

```bash
uvx patch_via_github -p couchbase/tlm#42
```

Alternatively, install it persistently with `uv`:

```bash
uv tool install patch-via-github
```

This will install `patch_via_github` to `~/.local/bin/`. Make sure this
directory is on your `PATH`.

## Configuration

Before using `patch_via_github`, create a configuration file with your GitHub
credentials. By default, the tool looks for `~/.ssh/patch_via_github.ini`:

```ini
[main]
token = ghp_xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
default_org = couchbase
```

| Key | Required | Description |
|---|---|---|
| `token` | Yes | GitHub personal access token (see below) |
| `default_org` | No | Default GitHub org for short-form PR references (`repo#123`) |
| `ssh` | No | Fetch over SSH (default `true`); `--no-ssh` on the command line takes precedence |

An example config is provided in
[`patch_via_github.ini.example`](patch_via_github.ini.example).

You can also specify a custom config file location with the `-c/--config`
option.

### Creating a GitHub Personal Access Token

Use a classic token: a single build can involve private repositories in more
than one organization (e.g. `couchbase` and `couchbaselabs`), and a
fine-grained token can only access one. To create one:

1. Go to **GitHub → Settings → Developer settings →
   [Personal access tokens → Tokens (classic)](https://github.com/settings/tokens/new)**
2. Give the token a descriptive name (e.g. `patch_via_github`)
3. Set the **Expiration** as appropriate for your use case
4. Select the **`repo`** scope (needed to read pull requests on private
   repositories)
5. Click **Generate token** and copy the value into your config file
6. Authorize the token for single sign-on: in the
   [list of classic tokens](https://github.com/settings/tokens), click
   **Configure SSO** next to it and **Authorize** each organization you'll be
   patching from

Without step 6, GitHub refuses requests for repositories in SSO-protected
organizations.

## Usage

By default, `patch_via_github` operates on the current directory. You can either
navigate to your `repo sync` workspace first, or use the `-s/--source` option to
specify the workspace location.

### Apply Patches by PR Reference

Apply one or more specific pull requests:

```bash
patch_via_github -p couchbase/tlm#42
patch_via_github -p couchbase/tlm#42,couchbase/ns_server#108
patch_via_github --pull-request couchbase/tlm#42 couchbase/server-ui#7
```

Short-form references use the `default_org` from your config (or `-o`):

```bash
patch_via_github -o couchbase -p tlm#42,ns_server#108
```

### Apply Patches by Label

Apply all open PRs matching a label on a given repo:

```bash
patch_via_github -l couchbase/tlm:backport
patch_via_github -l couchbase/tlm:backport,couchbase/ns_server:ci-test
```

### Checkout vs Cherry-Pick

By default, each PR's commits are cherry-picked in order onto the project's
current checkout. This requires linear PR history: a PR containing merge
commits is rejected, and should be rebased or applied with `-C/--checkout`,
which checks out the PR head instead:

```bash
patch_via_github -C -p couchbase/tlm#42
```

### Debug Output

```bash
patch_via_github -d -p couchbase/tlm#42
```

## How It Works

`patch_via_github` automates several tasks:

1. **PR Resolution:** When you specify PRs by reference or label, the tool
   fetches their metadata from the GitHub API and filters based on state and
   branch.

2. **Branch Filtering:** PRs found by label are only applied if they are open
   and their target branch matches the manifest's revision for that project
   (unless the manifest revision is a SHA). PRs requested by reference are
   applied whatever their state or target branch.

3. **Ordering:** PRs are applied in the order given on the command line. PRs
   found by label are applied label by label in the order the labels were
   given, and in PR number order (oldest first) within each label. A PR that
   appears more than once is applied once, at its first position.

4. **Verification:** The tool verifies that all explicitly-requested PRs were
   successfully applied.

5. **Rollback:** If anything fails, every project the run touched is returned
   to the commit (and branch) it was on beforehand; uncommitted local changes
   are kept.

Changes to the `manifest` repository are reviewed on Gerrit, so apply those
with [`patch_via_gerrit`](https://github.com/couchbase/patch_via_gerrit).

GitHub API requests are retried on transient errors (HTTP 429/5xx), and `git
fetch` times out after 10 minutes.

## Command-Line Options

```
patch_via_github [options]

Required (mutually exclusive):
  -p, --pull-request PR [PR ...]  PR references to apply (comma-separated)
                                  Format: org/repo#number or repo#number
  -l, --label LABEL [LABEL ...]   Labels to search for open PRs (comma-separated)
                                  Format: org/repo:label

Options:
  -d, --debug                     Enable debugging output
  -c, --config FILE               Configuration file (default: ~/.ssh/patch_via_github.ini)
  -s, --source DIR                Location of repo sync checkout (default: current directory)
  -o, --default-org ORG           Default GitHub org for short-form PR references
  -C, --checkout                  Checkout PR head instead of cherry-picking
  --no-ssh                        Fetch over HTTPS instead of SSH
  -V, --version                   Display version information
```

## Troubleshooting

**"Configuration file missing":**
- Create `~/.ssh/patch_via_github.ini` with your GitHub credentials
- Or specify a custom location with `-c/--config`

**"Project missing on disk":**
- Ensure you've run `repo sync` before applying patches
- The PR may reference a project not in your manifest groups

**"Failed to apply all explicitly-requested PRs":**
- The PR's project is not in the manifest, or is excluded by your manifest
  groups (look for "ignoring PR" earlier in the output)
- Try running with `--debug` to see more details

## Running Tests

```bash
uv run pytest
```

