chatgh 0.2.2__tar.gz → 0.2.4__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 (30) hide show
  1. {chatgh-0.2.2/src/chatgh.egg-info → chatgh-0.2.4}/PKG-INFO +29 -50
  2. {chatgh-0.2.2 → chatgh-0.2.4}/README.md +28 -49
  3. {chatgh-0.2.2 → chatgh-0.2.4}/src/chatgh/__init__.py +1 -1
  4. {chatgh-0.2.2 → chatgh-0.2.4}/src/chatgh/cli.py +2 -1
  5. {chatgh-0.2.2 → chatgh-0.2.4}/src/chatgh/github/api.py +32 -40
  6. chatgh-0.2.4/src/chatgh/github/cli.py +395 -0
  7. {chatgh-0.2.2 → chatgh-0.2.4}/src/chatgh/github/commands.py +52 -0
  8. {chatgh-0.2.2 → chatgh-0.2.4}/src/chatgh/github/requests.py +199 -0
  9. {chatgh-0.2.2 → chatgh-0.2.4/src/chatgh.egg-info}/PKG-INFO +29 -50
  10. {chatgh-0.2.2 → chatgh-0.2.4}/tests/test_version.py +1 -1
  11. chatgh-0.2.2/src/chatgh/github/cli.py +0 -158
  12. {chatgh-0.2.2 → chatgh-0.2.4}/LICENSE +0 -0
  13. {chatgh-0.2.2 → chatgh-0.2.4}/pyproject.toml +0 -0
  14. {chatgh-0.2.2 → chatgh-0.2.4}/setup.cfg +0 -0
  15. {chatgh-0.2.2 → chatgh-0.2.4}/src/chatgh/_generated/__init__.py +0 -0
  16. {chatgh-0.2.2 → chatgh-0.2.4}/src/chatgh/adapters/__init__.py +0 -0
  17. {chatgh-0.2.2 → chatgh-0.2.4}/src/chatgh/adapters/client.py +0 -0
  18. {chatgh-0.2.2 → chatgh-0.2.4}/src/chatgh/commands/__init__.py +0 -0
  19. {chatgh-0.2.2 → chatgh-0.2.4}/src/chatgh/commands/pr.py +0 -0
  20. {chatgh-0.2.2 → chatgh-0.2.4}/src/chatgh/config.py +0 -0
  21. {chatgh-0.2.2 → chatgh-0.2.4}/src/chatgh/github/__init__.py +0 -0
  22. {chatgh-0.2.2 → chatgh-0.2.4}/src/chatgh/github/client.py +0 -0
  23. {chatgh-0.2.2 → chatgh-0.2.4}/src/chatgh/github/render.py +0 -0
  24. {chatgh-0.2.2 → chatgh-0.2.4}/src/chatgh.egg-info/SOURCES.txt +0 -0
  25. {chatgh-0.2.2 → chatgh-0.2.4}/src/chatgh.egg-info/dependency_links.txt +0 -0
  26. {chatgh-0.2.2 → chatgh-0.2.4}/src/chatgh.egg-info/entry_points.txt +0 -0
  27. {chatgh-0.2.2 → chatgh-0.2.4}/src/chatgh.egg-info/requires.txt +0 -0
  28. {chatgh-0.2.2 → chatgh-0.2.4}/src/chatgh.egg-info/top_level.txt +0 -0
  29. {chatgh-0.2.2 → chatgh-0.2.4}/tests/test_adapter_client.py +0 -0
  30. {chatgh-0.2.2 → chatgh-0.2.4}/tests/test_cli.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: chatgh
3
- Version: 0.2.2
3
+ Version: 0.2.4
4
4
  Summary: GitHub CLI and Python helpers for ChatArch
5
5
  Author-email: ChatArch <1073853456@qq.com>
6
6
  License-Expression: MIT
@@ -43,7 +43,7 @@ pip install -e ".[dev]"
43
43
  默认行为:
44
44
 
45
45
  - `repo`:优先使用显式 `--repo owner/repo`,未传时从当前 git remote 推断。
46
- - `token`:优先使用显式 `--token`,其次读取当前仓库对应的 git credential,再回退 typed env 里的 `GITHUB_ACCESS_TOKEN`。
46
+ - `token`:优先使用显式 `--token`,其次读取当前仓库 `.git/config` 中 repo-local HTTPS auth header,再回退 typed env 里的 `GITHUB_ACCESS_TOKEN`。
47
47
  - 输出:默认是人类可读格式;支持 `--json-output` 的命令会输出稳定 JSON,适合脚本消费。
48
48
 
49
49
  ### Token 来源
@@ -51,7 +51,7 @@ pip install -e ".[dev]"
51
51
  Token 解析顺序稳定为:
52
52
 
53
53
  1. 显式 `--token`。
54
- 2. repo-scoped git credential,路径为规范化后的 `owner/repo`,不带 `.git` 后缀。
54
+ 2. 当前仓库 `.git/config` 中的 repo-local HTTPS auth header,路径为规范化后的 `https://github.com/owner/repo.git`。
55
55
  3. typed env 中的 `GITHUB_ACCESS_TOKEN`。
56
56
 
57
57
  可以用 `chatenv` 查看或配置 typed env:
@@ -72,13 +72,14 @@ chatenv cat -t gh
72
72
  - `git@github.com:octocat/Hello-World.git`
73
73
  - `ssh://git@github.com/octocat/Hello-World.git`
74
74
 
75
- 写入 repo-scoped credential 时,path 会规范化为 `octocat/Hello-World`。
75
+ 写入 repo-local HTTPS auth header 时,path 会规范化为 `https://github.com/octocat/Hello-World.git`。
76
76
 
77
77
  ## CLI 入口
78
78
 
79
79
  ```bash
80
80
  chatgh --help
81
81
  chatgh pr --help
82
+ chatgh repo --help
82
83
  chatgh run --help
83
84
  chatgh repo-perms --help
84
85
  chatgh set-token --help
@@ -89,7 +90,10 @@ chatgh set-token --help
89
90
  - `chatgh pr list`:generated-layer PR 列表。
90
91
  - `chatgh pr view NUMBER`:generated-layer PR 详情。
91
92
  - `chatgh pr checks NUMBER`:generated-layer PR head commit check runs。
92
- - `chatgh pr create/comment/merge/edit`:PR 创建、评论、合并和编辑操作。
93
+ - 当前公开 `chatgh pr` 命令面只包含 `list/view/checks`;PR 创建、评论、合并和编辑流程仍由内部 helper 支持,后续作为独立 CLI 命令恢复前不在帮助与文档中承诺。
94
+ - `chatgh repo list`:列出 user/org 下的仓库;默认 table,支持 `--json-output`、`--limit`、`--sort updated|created|pushed|name|stars|open-prs|open-issues`、`--direction asc|desc`,字段包含 visibility、stars、open PRs、open issues、created/updated time 等。
95
+ - `chatgh repo create`:创建仓库;默认 private,可用 `--public` 显式创建公开仓库。
96
+ - `chatgh repo protection`:查看单个仓库或 owner 下仓库的默认分支保护与 repository rulesets;治理/规则审计不挤进 `repo list` 默认表格。
93
97
  - `chatgh run view`:查看 workflow run 和 jobs。
94
98
  - `chatgh run logs`:查看 job 日志,支持 tail 和落盘。
95
99
  - `chatgh repo-perms`:查看 token 权限和派生 capabilities。
@@ -99,26 +103,7 @@ chatgh set-token --help
99
103
 
100
104
  ### 创建 PR
101
105
 
102
- 优先使用 `--body-file`,避免 shell 转义破坏 Markdown:
103
-
104
- ```bash
105
- cat > /tmp/pr_body.md <<'EOF'
106
- ## Summary
107
- - migrate GitHub helpers to chatgh
108
-
109
- ## Testing
110
- - python -m pytest -q
111
- EOF
112
-
113
- chatgh pr create \
114
- --repo octocat/Hello-World \
115
- --base main \
116
- --head feature-branch \
117
- --title "feat: migrate github helpers" \
118
- --body-file /tmp/pr_body.md
119
- ```
120
-
121
- 缺少 `base` / `head` / `title` 且终端可交互时,命令会自动补问;显式 `-I` 会禁用补问。
106
+ 当前版本未公开 `chatgh pr create` CLI 命令。需要创建 PR 时,请使用项目既有 GitHub 流程或直接调用 GitHub API;等写操作命令恢复为稳定 CLI surface 后再补回示例。
122
107
 
123
108
  ### 查看 PR
124
109
 
@@ -135,12 +120,10 @@ chatgh pr view 123 --repo octocat/Hello-World --json-output
135
120
  - `mergeable` 和 `mergeable_state`。
136
121
  - created/updated/merged timestamps。
137
122
 
138
- ### 查看和等待 CI
123
+ ### 查看 CI
139
124
 
140
125
  ```bash
141
126
  chatgh pr checks 123 --repo octocat/Hello-World
142
- chatgh pr checks --repo octocat/Hello-World --number 123 --wait
143
- chatgh pr checks --repo octocat/Hello-World --number 123 --wait --interval 10 --timeout 600
144
127
  chatgh pr checks 123 --repo octocat/Hello-World --json-output
145
128
  ```
146
129
 
@@ -150,11 +133,7 @@ chatgh pr checks 123 --repo octocat/Hello-World --json-output
150
133
  - check runs
151
134
  - workflow runs
152
135
 
153
- `--wait` 会持续轮询直到 statuses、check runs 和 workflow runs 都结束:
154
-
155
- - 默认不设超时,会一直等。
156
- - `--interval <seconds>` 控制轮询间隔。
157
- - 只有显式传 `--timeout <seconds>` 时才会超时报错。
136
+ 当前公开 CLI 不提供 `--wait` / `--interval` / `--timeout` 参数;需要等待终态时,在外层流程中轮询 `chatgh pr checks`。
158
137
 
159
138
  如果 GitHub token 无权读取 check-runs API,命令会把 check-runs 错误放进 payload,同时仍尽量展示 combined status 和 workflow runs。
160
139
 
@@ -173,25 +152,18 @@ chatgh run logs --repo octocat/Hello-World --job-id 987654321 --tail 200 --outpu
173
152
 
174
153
  ### 评论、合并和编辑 PR
175
154
 
176
- ```bash
177
- chatgh pr comment --repo octocat/Hello-World --number 123 --body "Looks good"
155
+ 当前版本未公开 `chatgh pr comment/merge/edit` CLI 命令。相关业务函数已保留在 `chatgh.github.commands` 中,后续恢复为稳定 CLI surface 前,建议通过项目既有流程或 GitHub API 执行写操作。
178
156
 
179
- chatgh pr merge --repo octocat/Hello-World --number 123 --method squash
180
- chatgh pr merge --repo octocat/Hello-World --number 123 --method squash --check
157
+ ### 查看仓库保护规则
181
158
 
182
- chatgh pr edit --repo octocat/Hello-World --number 123 --title "New title"
183
- chatgh pr edit --repo octocat/Hello-World --number 123 --body-file /tmp/pr_body.md
184
- chatgh pr edit --repo octocat/Hello-World --number 123 --state closed
185
- chatgh pr edit --repo octocat/Hello-World --number 123 --base main
159
+ ```bash
160
+ chatgh repo protection --repo octocat/Hello-World
161
+ chatgh repo protection --repo octocat/Hello-World --json-output
162
+ chatgh repo protection --owner octocat --limit 50 --jobs 8
163
+ chatgh repo protection --owner octocat --limit 50 --jobs 8 --json-output
186
164
  ```
187
165
 
188
- `pr merge --check` 会在合并前拒绝以下情况:
189
-
190
- - PR 当前 `mergeable=False`。
191
- - `mergeable_state` 为 `dirty`、`blocked`、`behind`、`draft` 或 `unknown`。
192
- - combined status、check runs 或 workflow runs 存在失败、取消或未完成项。
193
-
194
- 不带 `--check` 时,命令保持直接调用 GitHub merge API 的行为。
166
+ `repo protection` 会展示默认分支、是否 protected、classic branch protection 细节(例如是否要求 PR、review 数量、是否允许 force push / deletion),以及 GitHub 可读取时的 repository ruleset 摘要。部分 private 仓库可能因为 GitHub plan/visibility 限制读取 rulesets 返回错误;命令会在 JSON 里保留该错误,同时尽量展示 branch protection 状态。owner inventory 模式会先列仓库,再用 `--jobs` 并发检查每个仓库,输出顺序保持稳定。
195
167
 
196
168
  ### 配置和检查 token
197
169
 
@@ -209,7 +181,14 @@ chatgh set-token --token "$GITHUB_ACCESS_TOKEN" --save-env
209
181
  - GitHub 返回的 `permissions`。
210
182
  - 派生 capabilities:`can_read_pr`、`can_comment_pr`、`can_merge_pr`、`can_view_checks`、`can_view_actions`。
211
183
 
212
- `set-token` 只在当前目录能识别 GitHub remote 时生效。默认只写入 repo-scoped git credential;传 `--save-env` 时会同步写入 typed env 的 `GITHUB_ACCESS_TOKEN`。
184
+ `set-token` 只在当前目录能识别 GitHub remote 时生效。默认只写入当前仓库自己的 `.git/config`:
185
+
186
+ ```ini
187
+ [http "https://github.com/octocat/Hello-World.git"]
188
+ extraHeader = Authorization: Basic <base64(x-access-token:TOKEN)>
189
+ ```
190
+
191
+ 不要把 token 写进 remote URL,也不要把 raw `extraHeader` 输出到日志。传 `--save-env` 时会同步写入 typed env 的 `GITHUB_ACCESS_TOKEN`。
213
192
 
214
193
  ## 交互模式
215
194
 
@@ -233,7 +212,7 @@ git fetch origin main
233
212
 
234
213
  - `chatgh pr view` / `chatgh pr checks` 显示 `mergeable` 不是 `False`,`mergeable_state` 不是 `dirty`。
235
214
  - 本地基于最新 base 做过 merge 或 rebase 演练,并在该结果上跑过最相关测试。
236
- - CI 需要终态时用 `chatgh pr checks --wait`,不要只看一次快照。
215
+ - CI 需要终态时,在外层流程中轮询 `chatgh pr checks`,不要只看一次快照。
237
216
 
238
217
  ## Python API
239
218
 
@@ -15,7 +15,7 @@ pip install -e ".[dev]"
15
15
  默认行为:
16
16
 
17
17
  - `repo`:优先使用显式 `--repo owner/repo`,未传时从当前 git remote 推断。
18
- - `token`:优先使用显式 `--token`,其次读取当前仓库对应的 git credential,再回退 typed env 里的 `GITHUB_ACCESS_TOKEN`。
18
+ - `token`:优先使用显式 `--token`,其次读取当前仓库 `.git/config` 中 repo-local HTTPS auth header,再回退 typed env 里的 `GITHUB_ACCESS_TOKEN`。
19
19
  - 输出:默认是人类可读格式;支持 `--json-output` 的命令会输出稳定 JSON,适合脚本消费。
20
20
 
21
21
  ### Token 来源
@@ -23,7 +23,7 @@ pip install -e ".[dev]"
23
23
  Token 解析顺序稳定为:
24
24
 
25
25
  1. 显式 `--token`。
26
- 2. repo-scoped git credential,路径为规范化后的 `owner/repo`,不带 `.git` 后缀。
26
+ 2. 当前仓库 `.git/config` 中的 repo-local HTTPS auth header,路径为规范化后的 `https://github.com/owner/repo.git`。
27
27
  3. typed env 中的 `GITHUB_ACCESS_TOKEN`。
28
28
 
29
29
  可以用 `chatenv` 查看或配置 typed env:
@@ -44,13 +44,14 @@ chatenv cat -t gh
44
44
  - `git@github.com:octocat/Hello-World.git`
45
45
  - `ssh://git@github.com/octocat/Hello-World.git`
46
46
 
47
- 写入 repo-scoped credential 时,path 会规范化为 `octocat/Hello-World`。
47
+ 写入 repo-local HTTPS auth header 时,path 会规范化为 `https://github.com/octocat/Hello-World.git`。
48
48
 
49
49
  ## CLI 入口
50
50
 
51
51
  ```bash
52
52
  chatgh --help
53
53
  chatgh pr --help
54
+ chatgh repo --help
54
55
  chatgh run --help
55
56
  chatgh repo-perms --help
56
57
  chatgh set-token --help
@@ -61,7 +62,10 @@ chatgh set-token --help
61
62
  - `chatgh pr list`:generated-layer PR 列表。
62
63
  - `chatgh pr view NUMBER`:generated-layer PR 详情。
63
64
  - `chatgh pr checks NUMBER`:generated-layer PR head commit check runs。
64
- - `chatgh pr create/comment/merge/edit`:PR 创建、评论、合并和编辑操作。
65
+ - 当前公开 `chatgh pr` 命令面只包含 `list/view/checks`;PR 创建、评论、合并和编辑流程仍由内部 helper 支持,后续作为独立 CLI 命令恢复前不在帮助与文档中承诺。
66
+ - `chatgh repo list`:列出 user/org 下的仓库;默认 table,支持 `--json-output`、`--limit`、`--sort updated|created|pushed|name|stars|open-prs|open-issues`、`--direction asc|desc`,字段包含 visibility、stars、open PRs、open issues、created/updated time 等。
67
+ - `chatgh repo create`:创建仓库;默认 private,可用 `--public` 显式创建公开仓库。
68
+ - `chatgh repo protection`:查看单个仓库或 owner 下仓库的默认分支保护与 repository rulesets;治理/规则审计不挤进 `repo list` 默认表格。
65
69
  - `chatgh run view`:查看 workflow run 和 jobs。
66
70
  - `chatgh run logs`:查看 job 日志,支持 tail 和落盘。
67
71
  - `chatgh repo-perms`:查看 token 权限和派生 capabilities。
@@ -71,26 +75,7 @@ chatgh set-token --help
71
75
 
72
76
  ### 创建 PR
73
77
 
74
- 优先使用 `--body-file`,避免 shell 转义破坏 Markdown:
75
-
76
- ```bash
77
- cat > /tmp/pr_body.md <<'EOF'
78
- ## Summary
79
- - migrate GitHub helpers to chatgh
80
-
81
- ## Testing
82
- - python -m pytest -q
83
- EOF
84
-
85
- chatgh pr create \
86
- --repo octocat/Hello-World \
87
- --base main \
88
- --head feature-branch \
89
- --title "feat: migrate github helpers" \
90
- --body-file /tmp/pr_body.md
91
- ```
92
-
93
- 缺少 `base` / `head` / `title` 且终端可交互时,命令会自动补问;显式 `-I` 会禁用补问。
78
+ 当前版本未公开 `chatgh pr create` CLI 命令。需要创建 PR 时,请使用项目既有 GitHub 流程或直接调用 GitHub API;等写操作命令恢复为稳定 CLI surface 后再补回示例。
94
79
 
95
80
  ### 查看 PR
96
81
 
@@ -107,12 +92,10 @@ chatgh pr view 123 --repo octocat/Hello-World --json-output
107
92
  - `mergeable` 和 `mergeable_state`。
108
93
  - created/updated/merged timestamps。
109
94
 
110
- ### 查看和等待 CI
95
+ ### 查看 CI
111
96
 
112
97
  ```bash
113
98
  chatgh pr checks 123 --repo octocat/Hello-World
114
- chatgh pr checks --repo octocat/Hello-World --number 123 --wait
115
- chatgh pr checks --repo octocat/Hello-World --number 123 --wait --interval 10 --timeout 600
116
99
  chatgh pr checks 123 --repo octocat/Hello-World --json-output
117
100
  ```
118
101
 
@@ -122,11 +105,7 @@ chatgh pr checks 123 --repo octocat/Hello-World --json-output
122
105
  - check runs
123
106
  - workflow runs
124
107
 
125
- `--wait` 会持续轮询直到 statuses、check runs 和 workflow runs 都结束:
126
-
127
- - 默认不设超时,会一直等。
128
- - `--interval <seconds>` 控制轮询间隔。
129
- - 只有显式传 `--timeout <seconds>` 时才会超时报错。
108
+ 当前公开 CLI 不提供 `--wait` / `--interval` / `--timeout` 参数;需要等待终态时,在外层流程中轮询 `chatgh pr checks`。
130
109
 
131
110
  如果 GitHub token 无权读取 check-runs API,命令会把 check-runs 错误放进 payload,同时仍尽量展示 combined status 和 workflow runs。
132
111
 
@@ -145,25 +124,18 @@ chatgh run logs --repo octocat/Hello-World --job-id 987654321 --tail 200 --outpu
145
124
 
146
125
  ### 评论、合并和编辑 PR
147
126
 
148
- ```bash
149
- chatgh pr comment --repo octocat/Hello-World --number 123 --body "Looks good"
127
+ 当前版本未公开 `chatgh pr comment/merge/edit` CLI 命令。相关业务函数已保留在 `chatgh.github.commands` 中,后续恢复为稳定 CLI surface 前,建议通过项目既有流程或 GitHub API 执行写操作。
150
128
 
151
- chatgh pr merge --repo octocat/Hello-World --number 123 --method squash
152
- chatgh pr merge --repo octocat/Hello-World --number 123 --method squash --check
129
+ ### 查看仓库保护规则
153
130
 
154
- chatgh pr edit --repo octocat/Hello-World --number 123 --title "New title"
155
- chatgh pr edit --repo octocat/Hello-World --number 123 --body-file /tmp/pr_body.md
156
- chatgh pr edit --repo octocat/Hello-World --number 123 --state closed
157
- chatgh pr edit --repo octocat/Hello-World --number 123 --base main
131
+ ```bash
132
+ chatgh repo protection --repo octocat/Hello-World
133
+ chatgh repo protection --repo octocat/Hello-World --json-output
134
+ chatgh repo protection --owner octocat --limit 50 --jobs 8
135
+ chatgh repo protection --owner octocat --limit 50 --jobs 8 --json-output
158
136
  ```
159
137
 
160
- `pr merge --check` 会在合并前拒绝以下情况:
161
-
162
- - PR 当前 `mergeable=False`。
163
- - `mergeable_state` 为 `dirty`、`blocked`、`behind`、`draft` 或 `unknown`。
164
- - combined status、check runs 或 workflow runs 存在失败、取消或未完成项。
165
-
166
- 不带 `--check` 时,命令保持直接调用 GitHub merge API 的行为。
138
+ `repo protection` 会展示默认分支、是否 protected、classic branch protection 细节(例如是否要求 PR、review 数量、是否允许 force push / deletion),以及 GitHub 可读取时的 repository ruleset 摘要。部分 private 仓库可能因为 GitHub plan/visibility 限制读取 rulesets 返回错误;命令会在 JSON 里保留该错误,同时尽量展示 branch protection 状态。owner inventory 模式会先列仓库,再用 `--jobs` 并发检查每个仓库,输出顺序保持稳定。
167
139
 
168
140
  ### 配置和检查 token
169
141
 
@@ -181,7 +153,14 @@ chatgh set-token --token "$GITHUB_ACCESS_TOKEN" --save-env
181
153
  - GitHub 返回的 `permissions`。
182
154
  - 派生 capabilities:`can_read_pr`、`can_comment_pr`、`can_merge_pr`、`can_view_checks`、`can_view_actions`。
183
155
 
184
- `set-token` 只在当前目录能识别 GitHub remote 时生效。默认只写入 repo-scoped git credential;传 `--save-env` 时会同步写入 typed env 的 `GITHUB_ACCESS_TOKEN`。
156
+ `set-token` 只在当前目录能识别 GitHub remote 时生效。默认只写入当前仓库自己的 `.git/config`:
157
+
158
+ ```ini
159
+ [http "https://github.com/octocat/Hello-World.git"]
160
+ extraHeader = Authorization: Basic <base64(x-access-token:TOKEN)>
161
+ ```
162
+
163
+ 不要把 token 写进 remote URL,也不要把 raw `extraHeader` 输出到日志。传 `--save-env` 时会同步写入 typed env 的 `GITHUB_ACCESS_TOKEN`。
185
164
 
186
165
  ## 交互模式
187
166
 
@@ -205,7 +184,7 @@ git fetch origin main
205
184
 
206
185
  - `chatgh pr view` / `chatgh pr checks` 显示 `mergeable` 不是 `False`,`mergeable_state` 不是 `dirty`。
207
186
  - 本地基于最新 base 做过 merge 或 rebase 演练,并在该结果上跑过最相关测试。
208
- - CI 需要终态时用 `chatgh pr checks --wait`,不要只看一次快照。
187
+ - CI 需要终态时,在外层流程中轮询 `chatgh pr checks`,不要只看一次快照。
209
188
 
210
189
  ## Python API
211
190
 
@@ -2,4 +2,4 @@
2
2
 
3
3
  __all__ = ["__version__"]
4
4
 
5
- __version__ = "0.2.2"
5
+ __version__ = "0.2.4"
@@ -3,7 +3,7 @@
3
3
  import click
4
4
 
5
5
  from chatgh.commands.pr import pr_group
6
- from chatgh.github.cli import repo_permissions, run_group, set_repo_token
6
+ from chatgh.github.cli import repo_group, repo_permissions, run_group, set_repo_token
7
7
 
8
8
 
9
9
  @click.group()
@@ -12,6 +12,7 @@ def main() -> None:
12
12
 
13
13
 
14
14
  main.add_command(pr_group, name="pr")
15
+ main.add_command(repo_group, name="repo")
15
16
  main.add_command(run_group, name="run")
16
17
  main.add_command(repo_permissions, name="repo-perms")
17
18
  main.add_command(set_repo_token, name="set-token")
@@ -1,5 +1,6 @@
1
1
  from __future__ import annotations
2
2
 
3
+ import base64
3
4
  from urllib.parse import urlparse
4
5
  import subprocess
5
6
  from typing import Optional, TypedDict
@@ -74,7 +75,7 @@ def resolve_token_with_source(
74
75
  credential_path, exact_only=exact_only
75
76
  )
76
77
  if credential_token:
77
- return {"token": credential_token, "source": "git credential"}
78
+ return {"token": credential_token, "source": "repo git config"}
78
79
  credential_token = read_github_token_from_credentials(
79
80
  credential_path, exact_only=exact_only
80
81
  )
@@ -212,20 +213,22 @@ def read_github_token_from_git(
212
213
  ) -> Optional[str]:
213
214
  if not credential_path:
214
215
  return None
215
- return _git_credential_fill(credential_path)
216
+ return _read_repo_local_extraheader(credential_path)
216
217
 
217
218
 
218
- def _git_credential_fill(credential: CredentialQuery) -> Optional[str]:
219
- credential_input = (
220
- f"protocol={credential['protocol']}\n"
221
- f"host={credential['host']}\n"
222
- f"path={credential['path']}\n"
223
- )
224
- credential_input += "\n"
219
+ def _github_https_url(credential: CredentialQuery) -> str:
220
+ path = credential["path"].strip().removeprefix("/").removesuffix(".git")
221
+ return f"https://{credential['host']}/{path}.git"
222
+
223
+
224
+ def _extraheader_config_key(credential: CredentialQuery) -> str:
225
+ return f"http.{_github_https_url(credential)}.extraHeader"
226
+
227
+
228
+ def _read_repo_local_extraheader(credential: CredentialQuery) -> Optional[str]:
225
229
  try:
226
230
  result = subprocess.run(
227
- ["git", "credential", "fill"],
228
- input=credential_input,
231
+ ["git", "config", "--local", "--get", _extraheader_config_key(credential)],
229
232
  check=False,
230
233
  capture_output=True,
231
234
  text=True,
@@ -234,41 +237,30 @@ def _git_credential_fill(credential: CredentialQuery) -> Optional[str]:
234
237
  return None
235
238
  if result.returncode != 0:
236
239
  return None
237
- values: dict[str, str] = {}
238
- for line in result.stdout.splitlines():
239
- if "=" not in line:
240
- continue
241
- key, value = line.split("=", 1)
242
- values[key] = value
243
- if values.get("host") != credential["host"]:
240
+ return _token_from_extraheader(result.stdout.strip())
241
+
242
+
243
+ def _token_from_extraheader(header: str) -> Optional[str]:
244
+ prefix = "Authorization: Basic "
245
+ if not header.startswith(prefix):
246
+ return None
247
+ encoded = header[len(prefix) :].strip()
248
+ try:
249
+ decoded = base64.b64decode(encoded).decode("utf-8")
250
+ except Exception:
251
+ return None
252
+ username, sep, password = decoded.partition(":")
253
+ if sep != ":" or username != "x-access-token" or not password:
244
254
  return None
245
- return values.get("password") or None
255
+ return password
246
256
 
247
257
 
248
258
  def configure_github_https_token(credential: CredentialQuery, token: str) -> None:
249
259
  try:
260
+ raw = f"x-access-token:{token}".encode("utf-8")
261
+ header = "Authorization: Basic " + base64.b64encode(raw).decode("ascii")
250
262
  subprocess.run(
251
- ["git", "config", "--global", "credential.helper", "store"],
252
- check=True,
253
- capture_output=True,
254
- text=True,
255
- )
256
- subprocess.run(
257
- ["git", "config", "--global", "credential.useHttpPath", "true"],
258
- check=True,
259
- capture_output=True,
260
- text=True,
261
- )
262
- credential_input = (
263
- f"protocol={credential['protocol']}\n"
264
- f"host={credential['host']}\n"
265
- f"path={credential['path']}\n"
266
- "username=x-access-token\n"
267
- f"password={token}\n\n"
268
- )
269
- subprocess.run(
270
- ["git", "credential", "approve"],
271
- input=credential_input,
263
+ ["git", "config", "--local", _extraheader_config_key(credential), header],
272
264
  check=True,
273
265
  capture_output=True,
274
266
  text=True,