github-rest-api 0.47.2__tar.gz → 0.48.0__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (51) hide show
  1. {github_rest_api-0.47.2/github_rest_api/scripts/github → github_rest_api-0.48.0/.github}/workflows/auto_merge_pull_request.yaml +1 -0
  2. {github_rest_api-0.47.2 → github_rest_api-0.48.0}/.github/workflows/claude-code-review.yml +14 -9
  3. {github_rest_api-0.47.2 → github_rest_api-0.48.0}/PKG-INFO +1 -1
  4. {github_rest_api-0.47.2 → github_rest_api-0.48.0}/github_rest_api/github.py +11 -4
  5. {github_rest_api-0.47.2 → github_rest_api-0.48.0}/github_rest_api/scripts/github/create_github_repo.py +33 -15
  6. {github_rest_api-0.47.2 → github_rest_api-0.48.0}/pyproject.toml +1 -1
  7. {github_rest_api-0.47.2 → github_rest_api-0.48.0}/tests/test_github.py +3 -3
  8. {github_rest_api-0.47.2 → github_rest_api-0.48.0}/uv.lock +1 -1
  9. {github_rest_api-0.47.2 → github_rest_api-0.48.0}/.devcontainer/devcontainer.json +0 -0
  10. {github_rest_api-0.47.2 → github_rest_api-0.48.0}/.github/workflows/claude.yml +0 -0
  11. {github_rest_api-0.47.2 → github_rest_api-0.48.0}/.github/workflows/create_pr_to_main.yaml +0 -0
  12. {github_rest_api-0.47.2 → github_rest_api-0.48.0}/.github/workflows/lint.yaml +0 -0
  13. {github_rest_api-0.47.2 → github_rest_api-0.48.0}/.github/workflows/release.yaml +0 -0
  14. {github_rest_api-0.47.2 → github_rest_api-0.48.0}/.github/workflows/remove_branch.yaml +0 -0
  15. {github_rest_api-0.47.2 → github_rest_api-0.48.0}/.github/workflows/test.yaml +0 -0
  16. {github_rest_api-0.47.2 → github_rest_api-0.48.0}/.gitignore +0 -0
  17. {github_rest_api-0.47.2 → github_rest_api-0.48.0}/GEMINI.md +0 -0
  18. {github_rest_api-0.47.2 → github_rest_api-0.48.0}/README.md +0 -0
  19. {github_rest_api-0.47.2 → github_rest_api-0.48.0}/github_rest_api/__init__.py +0 -0
  20. {github_rest_api-0.47.2 → github_rest_api-0.48.0}/github_rest_api/pr_content.py +0 -0
  21. {github_rest_api-0.47.2 → github_rest_api-0.48.0}/github_rest_api/scripts/__init__.py +0 -0
  22. {github_rest_api-0.47.2 → github_rest_api-0.48.0}/github_rest_api/scripts/cargo/__init__.py +0 -0
  23. {github_rest_api-0.47.2 → github_rest_api-0.48.0}/github_rest_api/scripts/cargo/benchmark.py +0 -0
  24. {github_rest_api-0.47.2 → github_rest_api-0.48.0}/github_rest_api/scripts/cargo/profiling.py +0 -0
  25. {github_rest_api-0.47.2 → github_rest_api-0.48.0}/github_rest_api/scripts/cargo/utils.py +0 -0
  26. {github_rest_api-0.47.2 → github_rest_api-0.48.0}/github_rest_api/scripts/container/__init__.py +0 -0
  27. {github_rest_api-0.47.2 → github_rest_api-0.48.0}/github_rest_api/scripts/container/build_container_images.py +0 -0
  28. {github_rest_api-0.47.2 → github_rest_api-0.48.0}/github_rest_api/scripts/container/config_container.py +0 -0
  29. {github_rest_api-0.47.2 → github_rest_api-0.48.0}/github_rest_api/scripts/container/update_version_containerfile.py +0 -0
  30. {github_rest_api-0.47.2 → github_rest_api-0.48.0}/github_rest_api/scripts/github/__init__.py +0 -0
  31. {github_rest_api-0.47.2 → github_rest_api-0.48.0}/github_rest_api/scripts/github/auto_merge_pull_request.py +0 -0
  32. {github_rest_api-0.47.2 → github_rest_api-0.48.0}/github_rest_api/scripts/github/create_pull_request.py +0 -0
  33. {github_rest_api-0.47.2 → github_rest_api-0.48.0}/github_rest_api/scripts/github/release_on_github.py +0 -0
  34. {github_rest_api-0.47.2 → github_rest_api-0.48.0}/github_rest_api/scripts/github/remove_branch.py +0 -0
  35. {github_rest_api-0.47.2/.github → github_rest_api-0.48.0/github_rest_api/scripts/github}/workflows/auto_merge_pull_request.yaml +0 -0
  36. {github_rest_api-0.47.2 → github_rest_api-0.48.0}/github_rest_api/scripts/github/workflows/create_pr_dev_to_main.yaml +0 -0
  37. {github_rest_api-0.47.2 → github_rest_api-0.48.0}/github_rest_api/scripts/github/workflows/create_pr_to_dev.yaml +0 -0
  38. {github_rest_api-0.47.2 → github_rest_api-0.48.0}/github_rest_api/scripts/github/workflows/create_pr_to_main.yaml +0 -0
  39. {github_rest_api-0.47.2 → github_rest_api-0.48.0}/github_rest_api/scripts/github/workflows/python/lint.yaml +0 -0
  40. {github_rest_api-0.47.2 → github_rest_api-0.48.0}/github_rest_api/scripts/github/workflows/python/test.yaml +0 -0
  41. {github_rest_api-0.47.2 → github_rest_api-0.48.0}/github_rest_api/scripts/github/workflows/remove_branch.yaml +0 -0
  42. {github_rest_api-0.47.2 → github_rest_api-0.48.0}/github_rest_api/scripts/utils.py +0 -0
  43. {github_rest_api-0.47.2 → github_rest_api-0.48.0}/github_rest_api/utils.py +0 -0
  44. {github_rest_api-0.47.2 → github_rest_api-0.48.0}/memory/MEMORY.md +0 -0
  45. {github_rest_api-0.47.2 → github_rest_api-0.48.0}/memory/feedback_test_runner.md +0 -0
  46. {github_rest_api-0.47.2 → github_rest_api-0.48.0}/tests/__init__.py +0 -0
  47. {github_rest_api-0.47.2 → github_rest_api-0.48.0}/tests/test_build_container_images.py +0 -0
  48. {github_rest_api-0.47.2 → github_rest_api-0.48.0}/tests/test_create_pull_request.py +0 -0
  49. {github_rest_api-0.47.2 → github_rest_api-0.48.0}/tests/test_pr_content.py +0 -0
  50. {github_rest_api-0.47.2 → github_rest_api-0.48.0}/tests/test_release_on_github.py +0 -0
  51. {github_rest_api-0.47.2 → github_rest_api-0.48.0}/tests/test_utils.py +0 -0
@@ -27,4 +27,5 @@ jobs:
27
27
  uvx --from github-rest-api@latest auto_merge_pull_request \
28
28
  --authors dclong \
29
29
  --approvers dclong 'claude[bot]' 'gemini-code-assist[bot]' \
30
+ --marker 'AUTO_MERGE_APPROVED' \
30
31
  --token ${{ secrets.ACTIONS_TOKEN }}
@@ -21,8 +21,8 @@ jobs:
21
21
  runs-on: ubuntu-latest
22
22
  permissions:
23
23
  contents: read
24
- pull-requests: read
25
- issues: read
24
+ pull-requests: write
25
+ issues: write
26
26
  id-token: write
27
27
 
28
28
  steps:
@@ -36,6 +36,13 @@ jobs:
36
36
  uses: anthropics/claude-code-action@v1
37
37
  with:
38
38
  claude_code_oauth_token: ${{ secrets.CLAUDE_CODE_OAUTH_TOKEN }}
39
+ # Post the review comment with a token that has write access. Using the
40
+ # ACTIONS_TOKEN PAT also makes the comment (and its AUTO_MERGE_APPROVED
41
+ # marker) come from dclong, who is in the auto-merge approver allowlist.
42
+ github_token: ${{ secrets.ACTIONS_TOKEN }}
43
+ # Force tag mode so the action creates and updates a PR comment with the
44
+ # review; without this the code-review run posts nothing.
45
+ track_progress: true
39
46
  plugin_marketplaces: 'https://github.com/anthropics/claude-code.git'
40
47
  plugins: 'code-review@claude-code-plugins'
41
48
  prompt: |
@@ -45,12 +52,10 @@ jobs:
45
52
  When the review is finished, decide whether this PR is safe to merge
46
53
  automatically: it is safe only if the review surfaced no correctness bugs
47
54
  and no other blocking issues (non-blocking style or cleanup suggestions do
48
- not disqualify it). If and only if it is safe, post a single new comment on
49
- the pull request whose body includes, on its own line, this exact marker
50
- (a short note such as "Approved for auto-merge." above it is fine):
51
- <!-- auto-merge: approved -->
52
- If you found any blocking issue, do NOT post the marker. Always post a fresh
53
- comment rather than editing an existing one, so the marker's timestamp
54
- follows the latest commit.
55
+ not disqualify it). If and only if it is safe, end your review with this
56
+ token alone on its own final line, exactly and verbatim:
57
+ AUTO_MERGE_APPROVED
58
+ Do not write this token anywhere else in your review, and do not write it
59
+ at all if you found any blocking issue.
55
60
  # See https://github.com/anthropics/claude-code-action/blob/main/docs/usage.md
56
61
  # or https://code.claude.com/docs/en/cli-reference for available options
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: github-rest-api
3
- Version: 0.47.2
3
+ Version: 0.48.0
4
4
  Summary: Simple wrapper of GitHub REST APIs.
5
5
  Author-email: Ben Du <longendu@yahoo.com>
6
6
  Classifier: Programming Language :: Python :: 3 :: Only
@@ -31,9 +31,9 @@ DEFAULT_PR_MODEL = "anthropic/claude-haiku-4-5-20251001"
31
31
  # Defaults for automatic pull request merging (see Repository.auto_merge_pull_requests).
32
32
  # A marker comment from an allowlisted approver is accepted as an approval signal
33
33
  # for AI reviewers that only comment instead of submitting a formal review.
34
- DEFAULT_AUTO_MERGE_MARKER = "<!-- auto-merge: approved -->"
34
+ DEFAULT_AUTO_MERGE_MARKER = "AUTO_MERGE_APPROVED"
35
35
  # Conventional-commit title types eligible for auto-merge.
36
- DEFAULT_AUTO_MERGE_TYPES = ("chore", "docs", "deps")
36
+ DEFAULT_AUTO_MERGE_TYPES = ("build", "chore", "ci", "docs", "deps")
37
37
  # A PR is only auto-merged once its head commit is at least this old, an anti-race
38
38
  # guard so a PR that momentarily reads `clean` before CI registers is not merged.
39
39
  # A just-created PR is simply deferred to the next run, never dropped, so a small
@@ -177,8 +177,15 @@ def _field_gate_failure(
177
177
  return "it is a draft"
178
178
  if not _in_allowlist(_login(pr), _normalized_logins(authors)):
179
179
  return "its author is not in the allowlist"
180
- if not _title_type_allowed(pr.get("title") or "", allowed_types):
181
- return "its title type is not auto-merge eligible"
180
+ title = pr.get("title") or ""
181
+ if not _title_type_allowed(title, allowed_types):
182
+ type_ = _conventional_type(title)
183
+ current = f"'{type_}'" if type_ is not None else "missing/unrecognized"
184
+ eligible = ", ".join(allowed_types) or "none"
185
+ return (
186
+ f"its title type ({current}) is not auto-merge eligible "
187
+ f"(eligible types: {eligible})"
188
+ )
182
189
  return None
183
190
 
184
191
 
@@ -67,8 +67,12 @@ def _init_local_repo(
67
67
  dir_: str,
68
68
  token: str,
69
69
  protocol: str,
70
+ push: bool,
70
71
  branches: Sequence[str] = ("main",),
71
72
  ) -> None:
73
+ branches = list(dict.fromkeys(branches))
74
+ if not branches:
75
+ raise ValueError("At least one branch must be specified.")
72
76
  repo_name = repo.split("/")[-1]
73
77
  path = Path(dir_) if dir_ else Path(repo_name)
74
78
  path.mkdir(parents=True, exist_ok=True)
@@ -94,21 +98,26 @@ def _init_local_repo(
94
98
  if initial_branch not in branches:
95
99
  porcelain.branch_delete(repo=path, name=initial_branch)
96
100
  logger.info("Deleted initial branch '%s'", initial_branch)
101
+ else:
102
+ existing_branches = {b.decode() for b in porcelain.branch_list(path)}
103
+ for branch in branches:
104
+ if branch not in existing_branches:
105
+ porcelain.branch_create(repo=path, name=branch)
106
+ logger.info("Created branch '%s' from HEAD", branch)
97
107
  _ensure_remote(path, repo, protocol)
98
- local_branches = {b.decode() for b in porcelain.branch_list(path)}
99
- branches_to_push = [branch for branch in branches if branch in local_branches]
100
- if not branches_to_push:
101
- branches_to_push = [_active_branch(path)]
102
- for branch in branches_to_push:
103
- logger.info("Pushing branch '%s' to remote '%s'...", branch, repo)
104
- porcelain.push(
105
- repo=path,
106
- remote_location=_remote_url(repo, "https"),
107
- refspecs=[branch.encode()],
108
- username="x-access-token",
109
- password=token,
110
- )
111
- logger.info("Successfully pushed branch '%s'.", branch)
108
+ if push:
109
+ for branch in branches:
110
+ logger.info("Pushing branch '%s' to remote '%s'...", branch, repo)
111
+ porcelain.push(
112
+ repo=path,
113
+ remote_location=_remote_url(repo, "https"),
114
+ refspecs=[branch.encode()],
115
+ username="x-access-token",
116
+ password=token,
117
+ )
118
+ logger.info("Successfully pushed branch '%s'.", branch)
119
+ else:
120
+ logger.info("Skipping push (pass --push to push branches to the remote).")
112
121
  _add_workflow(path, language)
113
122
 
114
123
 
@@ -120,6 +129,7 @@ def create_github_repo(
120
129
  dir_: str,
121
130
  token: str,
122
131
  protocol: str,
132
+ push: bool,
123
133
  branches: Sequence[str] = ("main",),
124
134
  ) -> None:
125
135
  token = token or os.getenv("GITHUB_TOKEN", "")
@@ -141,6 +151,7 @@ def create_github_repo(
141
151
  token=token,
142
152
  branches=branches,
143
153
  protocol=protocol,
154
+ push=push,
144
155
  )
145
156
 
146
157
 
@@ -223,7 +234,7 @@ def parse_args(args=None, namespace=None):
223
234
  nargs="+",
224
235
  default=["main"],
225
236
  metavar="BRANCH",
226
- help="Branches to create and push to remote (default: main).",
237
+ help="Branches to create (and push if --push is set) (default: main).",
227
238
  )
228
239
  parser.add_argument(
229
240
  "--https",
@@ -233,6 +244,12 @@ def parse_args(args=None, namespace=None):
233
244
  default="git",
234
245
  help="Use the HTTPS protocol for the remote URL.",
235
246
  )
247
+ parser.add_argument(
248
+ "--push",
249
+ dest="push",
250
+ action="store_true",
251
+ help="Push branches to the remote (by default, nothing is pushed).",
252
+ )
236
253
  parser.add_argument(
237
254
  "-v",
238
255
  "--verbose",
@@ -256,6 +273,7 @@ def main() -> int:
256
273
  token=args.token,
257
274
  branches=args.branches,
258
275
  protocol=args.protocol,
276
+ push=args.push,
259
277
  )
260
278
  except Exception as e:
261
279
  logger.error("Failed to create GitHub repo: %s", e, exc_info=args.verbose)
@@ -4,7 +4,7 @@ requires = [ "hatchling" ]
4
4
 
5
5
  [project]
6
6
  name = "github-rest-api"
7
- version = "0.47.2"
7
+ version = "0.48.0"
8
8
  description = "Simple wrapper of GitHub REST APIs."
9
9
  readme = "README.md"
10
10
  authors = [ { name = "Ben Du", email = "longendu@yahoo.com" } ]
@@ -525,7 +525,7 @@ def test_should_auto_merge_marker_comment_path():
525
525
  comments=[
526
526
  {
527
527
  "user": {"login": "bot"},
528
- "body": "<!-- auto-merge: approved -->",
528
+ "body": "AUTO_MERGE_APPROVED",
529
529
  # Posted after the head commit (which _auto_merge_repo dates 30 min ago).
530
530
  "created_at": datetime.now(timezone.utc).isoformat(),
531
531
  }
@@ -543,7 +543,7 @@ def test_should_auto_merge_skips_marker_comment_before_head_commit():
543
543
  comments=[
544
544
  {
545
545
  "user": {"login": "bot"},
546
- "body": "<!-- auto-merge: approved -->",
546
+ "body": "AUTO_MERGE_APPROVED",
547
547
  "created_at": (
548
548
  datetime.now(timezone.utc) - timedelta(hours=1)
549
549
  ).isoformat(),
@@ -593,7 +593,7 @@ def test_should_auto_merge_changes_requested_vetoes_marker_comment():
593
593
  # left an approving marker comment.
594
594
  repo, patches = _auto_merge_repo(
595
595
  reviews=[_review("bot", "CHANGES_REQUESTED")],
596
- comments=[{"user": {"login": "bot"}, "body": "<!-- auto-merge: approved -->"}],
596
+ comments=[{"user": {"login": "bot"}, "body": "AUTO_MERGE_APPROVED"}],
597
597
  )
598
598
  assert _run_should_auto_merge(repo, patches) is None
599
599
 
@@ -542,7 +542,7 @@ wheels = [
542
542
 
543
543
  [[package]]
544
544
  name = "github-rest-api"
545
- version = "0.47.2"
545
+ version = "0.48.0"
546
546
  source = { editable = "." }
547
547
  dependencies = [
548
548
  { name = "dulwich" },