Skip to content

Commit ed95798

Browse files
Update usage and usage documentation.
1 parent a8b64c8 commit ed95798

File tree

6 files changed

+72
-41
lines changed

6 files changed

+72
-41
lines changed

README.md

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,30 @@ This project uses [GitPython](https://github.com/gitpython-developers/GitPython)
1111
local commit and recreate it remotely using [PyGitHub](https://github.com/PyGithub/PyGithub).
1212

1313

14+
## Usage
15+
16+
### Prerequisites
17+
18+
It is assumed that you have an authorized GitHub app with permissions to write to the contents
19+
of your target GitHub repository. You will need the `app id` and `private key` of this app
20+
(and should be sure to keep the `private key` secret throughout any operations using this tool).
21+
22+
It is also assumed that you have a created a single, non-merge commit locally and wish to
23+
recreate this commit remotely using the bot.
24+
25+
### Invocation
26+
27+
```sh
28+
write-commit \
29+
--app-id <github-app-id> \
30+
--private-key <github-app-private-key> \
31+
--repo /path/to/repo \
32+
--ref <some-local-ref>
33+
--branch <some-remote-branch>
34+
```
35+
36+
Note that the `GITHUB_APP_PRIVATE_KEY` environment variable can be used to pass the private
37+
key without passing it as a commmand line argument.
1438

1539
## Docker
1640

pyproject.toml

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -42,8 +42,8 @@ types = [
4242

4343
[project.scripts]
4444

45-
read-commit = "bot.cli.main:read"
46-
write-commit = "bot.cli.main:write"
45+
read-commit = "bot.cli:read"
46+
write-commit = "bot.cli:write"
4747

4848
[build-system]
4949

src/bot/cli/main.py renamed to src/bot/cli.py

Lines changed: 33 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -5,9 +5,9 @@
55
from click import Path as PathType
66
from click import command, option, secho
77

8-
from ..dtos import Tree
9-
from ..local import extract_repo_name, read_commit, read_repo
10-
from ..remote import authenticate_app, write_commit
8+
from .dtos import Tree
9+
from .local import extract_repo_name, read_commit, read_repo
10+
from .remote import authenticate_app, write_commit
1111

1212

1313
def print_tree(tree: Tree, parent: Path, depth: int = 0) -> None:
@@ -29,6 +29,7 @@ def print_tree(tree: Tree, parent: Path, depth: int = 0) -> None:
2929
@option(
3030
"--repo-path",
3131
"--repo",
32+
help="The path to the local git repository.",
3233
type=PathType(
3334
exists=True,
3435
file_okay=False,
@@ -39,37 +40,26 @@ def print_tree(tree: Tree, parent: Path, depth: int = 0) -> None:
3940
)
4041
@option(
4142
"--ref",
43+
help="The local ref to read.",
4244
required=True,
4345
)
4446
def read(
4547
*,
4648
repo_path: Path,
47-
ref: str,
49+
sha: str,
4850
) -> None:
4951
repo = read_repo(repo_path)
50-
commit = read_commit(repo, ref)
52+
commit = read_commit(repo, sha)
5153

5254
secho(f"Commit: {commit.message}", fg="green")
5355
print_tree(commit.tree, Path())
5456

5557

5658
@command()
57-
@option(
58-
"--application-id",
59-
"--app-id",
60-
envvar="GITHUB_APP_ID",
61-
required=True,
62-
type=int,
63-
)
64-
@option(
65-
"--private-key",
66-
hidden=True,
67-
envvar="GITHUB_APP_PRIVATE_KEY",
68-
required=True,
69-
)
7059
@option(
7160
"--repo-path",
7261
"--repo",
62+
help="The path to the local git repository.",
7363
type=PathType(
7464
exists=True,
7565
file_okay=False,
@@ -78,13 +68,34 @@ def read(
7868
),
7969
required=True,
8070
)
71+
@option(
72+
"--branch",
73+
help="The remote branch on which to add the generated commit.",
74+
required=True,
75+
)
8176
@option(
8277
"--ref",
78+
help="The local ref to recreate remotely.",
79+
required=True,
80+
)
81+
@option(
82+
"--app-id",
83+
envvar="GITHUB_APP_ID",
84+
help="The GitHub App's app id.",
85+
required=True,
86+
type=int,
87+
)
88+
@option(
89+
"--private-key",
90+
hidden=True,
91+
help="The GitHub App's private key",
92+
envvar="GITHUB_APP_PRIVATE_KEY",
8393
required=True,
8494
)
8595
def write(
8696
*,
87-
application_id: int,
97+
app_id: int,
98+
branch: str,
8899
private_key: str,
89100
repo_path: Path,
90101
ref: str,
@@ -94,10 +105,10 @@ def write(
94105
repo = read_repo(repo_path)
95106
repo_name = extract_repo_name(repo)
96107

97-
github = authenticate_app(application_id, private_key)
108+
github = authenticate_app(app_id, private_key)
98109
repository = github.get_repo(repo_name)
110+
git_ref = repository.get_git_ref(f"heads/{branch}")
99111

100112
commit = read_commit(repo, ref)
101113
git_commit = write_commit(repository, commit)
102-
103-
secho(f"Created git commit: {git_commit.sha}", fg="green")
114+
git_ref.edit(git_commit.sha)

src/bot/cli/__init__.py

Whitespace-only changes.

src/bot/local.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -80,6 +80,7 @@ def iter_blobs(item: Diff) -> Generator[BlobDTO, None, None]:
8080

8181

8282
def build_trees(blobs: list[BlobDTO]) -> TreeDTO:
83+
"""Build the tree structure from a list of blobs."""
8384
trees: dict[Path, TreeDTO] = {}
8485

8586
# Create the root tree

src/bot/remote.py

Lines changed: 12 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
from logging import getLogger as get_logger
2+
from typing import Generator
23

34
from github import Github, GithubIntegration
45
from github.Auth import AppAuth
@@ -11,8 +12,8 @@
1112
from .enums import Mode, Type
1213

1314

14-
def authenticate_app(application_id: int, private_key: str) -> Github:
15-
auth = AppAuth(application_id, private_key)
15+
def authenticate_app(app_id: int, private_key: str) -> Github:
16+
auth = AppAuth(app_id, private_key)
1617
integration = GithubIntegration(auth=auth)
1718
installation = integration.get_installations()[0]
1819
return installation.get_github_for_installation() # type: ignore
@@ -36,28 +37,22 @@ def make_tree_blob_element(blob: Blob) -> InputGitTreeElement:
3637
)
3738

3839

39-
def make_tree_tree_element(tree: Tree, git_tree: GitTree) -> InputGitTreeElement:
40-
return InputGitTreeElement(
41-
path=str(tree.path),
42-
mode=Mode.SUBDIRECTORY.value,
43-
type=Type.TREE.value,
44-
sha=git_tree.sha,
45-
)
40+
def iter_tree_blob_element(tree: Tree) -> Generator[InputGitTreeElement, None, None]:
41+
for child in tree.trees:
42+
yield from iter_tree_blob_element(child)
43+
44+
for blob in tree.blobs:
45+
yield make_tree_blob_element(blob)
4646

4747

4848
def write_tree(repo: Repository, tree: Tree, base_tree: GitTree) -> GitTree:
4949
logger = get_logger("GitTree")
5050

51-
child_git_trees = [write_tree(repo, child, base_tree) for child in tree.trees]
52-
53-
tree_items = [make_tree_blob_element(blob) for blob in tree.blobs] + [
54-
make_tree_tree_element(child, child_git_tree)
55-
for child, child_git_tree in zip(tree.trees, child_git_trees)
56-
]
51+
tree_blob_elements = list(iter_tree_blob_element(tree))
5752

58-
logger.info(f"Creating git tree with {len(tree_items)} items from: {base_tree}")
53+
logger.info("Creating git tree")
5954
git_tree = repo.create_git_tree(
60-
tree=tree_items,
55+
tree=tree_blob_elements,
6156
base_tree=base_tree,
6257
)
6358
logger.info(f"Created git tree: {git_tree.sha}")

0 commit comments

Comments
 (0)