gitwebhooks 2.1.3__tar.gz → 2.2.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.
- {gitwebhooks-2.1.3 → gitwebhooks-2.2.0}/CLAUDE.md +22 -13
- {gitwebhooks-2.1.3 → gitwebhooks-2.2.0}/PKG-INFO +45 -7
- {gitwebhooks-2.1.3 → gitwebhooks-2.2.0}/README.md +40 -2
- {gitwebhooks-2.1.3 → gitwebhooks-2.2.0}/README.zh.md +40 -2
- {gitwebhooks-2.1.3 → gitwebhooks-2.2.0}/gitwebhooks/__init__.py +1 -1
- {gitwebhooks-2.1.3 → gitwebhooks-2.2.0}/gitwebhooks/cli/init_wizard.py +3 -3
- {gitwebhooks-2.1.3 → gitwebhooks-2.2.0}/gitwebhooks/cli/service.py +7 -7
- {gitwebhooks-2.1.3 → gitwebhooks-2.2.0}/gitwebhooks/config/loader.py +9 -3
- {gitwebhooks-2.1.3 → gitwebhooks-2.2.0}/gitwebhooks/handlers/request.py +16 -11
- {gitwebhooks-2.1.3 → gitwebhooks-2.2.0}/gitwebhooks/logging/setup.py +17 -6
- gitwebhooks-2.2.0/gitwebhooks/main/__init__.py +182 -0
- {gitwebhooks-2.1.3 → gitwebhooks-2.2.0}/gitwebhooks/utils/systemd.py +3 -3
- {gitwebhooks-2.1.3 → gitwebhooks-2.2.0}/gitwebhooks.egg-info/PKG-INFO +45 -7
- {gitwebhooks-2.1.3 → gitwebhooks-2.2.0}/gitwebhooks.egg-info/SOURCES.txt +3 -1
- gitwebhooks-2.1.3/git-webhooks-server.ini.sample → gitwebhooks-2.2.0/gitwebhooks.ini.sample +1 -1
- {gitwebhooks-2.1.3 → gitwebhooks-2.2.0}/pyproject.toml +5 -5
- {gitwebhooks-2.1.3 → gitwebhooks-2.2.0}/tests/__init__.py +2 -2
- {gitwebhooks-2.1.3 → gitwebhooks-2.2.0}/tests/__main__.py +2 -2
- {gitwebhooks-2.1.3 → gitwebhooks-2.2.0}/tests/conftest.py +1 -1
- gitwebhooks-2.2.0/tests/integration/__init__.py +3 -0
- gitwebhooks-2.2.0/tests/integration/test_config_discovery.py +328 -0
- {gitwebhooks-2.1.3 → gitwebhooks-2.2.0}/tests/integration/test_config_view_integration.py +1 -1
- {gitwebhooks-2.1.3 → gitwebhooks-2.2.0}/tests/integration/test_custom_webhook.py +1 -1
- {gitwebhooks-2.1.3 → gitwebhooks-2.2.0}/tests/integration/test_edge_cases.py +6 -2
- gitwebhooks-2.2.0/tests/unit/__init__.py +3 -0
- {gitwebhooks-2.1.3 → gitwebhooks-2.2.0}/tests/unit/test_config_loading.py +4 -11
- gitwebhooks-2.2.0/tests/unit/test_main.py +341 -0
- {gitwebhooks-2.1.3 → gitwebhooks-2.2.0}/tests/unit/test_signature_verification.py +6 -9
- {gitwebhooks-2.1.3 → gitwebhooks-2.2.0}/tests/utils/certificate_generator.py +1 -1
- {gitwebhooks-2.1.3 → gitwebhooks-2.2.0}/tests/utils/coverage_runner.py +2 -2
- {gitwebhooks-2.1.3 → gitwebhooks-2.2.0}/tests/utils/http_client.py +1 -1
- {gitwebhooks-2.1.3 → gitwebhooks-2.2.0}/tests/utils/server_manager.py +3 -3
- gitwebhooks-2.1.3/gitwebhooks/main/__init__.py +0 -117
- gitwebhooks-2.1.3/tests/integration/__init__.py +0 -3
- gitwebhooks-2.1.3/tests/unit/__init__.py +0 -3
- {gitwebhooks-2.1.3 → gitwebhooks-2.2.0}/.editorconfig +0 -0
- {gitwebhooks-2.1.3 → gitwebhooks-2.2.0}/LICENSE +0 -0
- {gitwebhooks-2.1.3 → gitwebhooks-2.2.0}/MANIFEST.in +0 -0
- {gitwebhooks-2.1.3 → gitwebhooks-2.2.0}/doc/custom-body.png +0 -0
- {gitwebhooks-2.1.3 → gitwebhooks-2.2.0}/doc/custom-header.png +0 -0
- {gitwebhooks-2.1.3 → gitwebhooks-2.2.0}/doc/custom-response.png +0 -0
- {gitwebhooks-2.1.3 → gitwebhooks-2.2.0}/doc/gitee-success.png +0 -0
- {gitwebhooks-2.1.3 → gitwebhooks-2.2.0}/doc/gitee.png +0 -0
- {gitwebhooks-2.1.3 → gitwebhooks-2.2.0}/doc/github-success.png +0 -0
- {gitwebhooks-2.1.3 → gitwebhooks-2.2.0}/doc/github.png +0 -0
- {gitwebhooks-2.1.3 → gitwebhooks-2.2.0}/doc/gitlab-success.png +0 -0
- {gitwebhooks-2.1.3 → gitwebhooks-2.2.0}/doc/gitlab.png +0 -0
- {gitwebhooks-2.1.3 → gitwebhooks-2.2.0}/doc/install.png +0 -0
- {gitwebhooks-2.1.3 → gitwebhooks-2.2.0}/doc/uninstall.png +0 -0
- {gitwebhooks-2.1.3 → gitwebhooks-2.2.0}/gitwebhooks/__main__.py +0 -0
- {gitwebhooks-2.1.3 → gitwebhooks-2.2.0}/gitwebhooks/auth/__init__.py +0 -0
- {gitwebhooks-2.1.3 → gitwebhooks-2.2.0}/gitwebhooks/auth/custom.py +0 -0
- {gitwebhooks-2.1.3 → gitwebhooks-2.2.0}/gitwebhooks/auth/factory.py +0 -0
- {gitwebhooks-2.1.3 → gitwebhooks-2.2.0}/gitwebhooks/auth/gitee.py +0 -0
- {gitwebhooks-2.1.3 → gitwebhooks-2.2.0}/gitwebhooks/auth/github.py +0 -0
- {gitwebhooks-2.1.3 → gitwebhooks-2.2.0}/gitwebhooks/auth/gitlab.py +0 -0
- {gitwebhooks-2.1.3 → gitwebhooks-2.2.0}/gitwebhooks/auth/verifier.py +0 -0
- {gitwebhooks-2.1.3 → gitwebhooks-2.2.0}/gitwebhooks/cli/__init__.py +0 -0
- {gitwebhooks-2.1.3 → gitwebhooks-2.2.0}/gitwebhooks/cli/config.py +0 -0
- {gitwebhooks-2.1.3 → gitwebhooks-2.2.0}/gitwebhooks/cli/prompts.py +0 -0
- {gitwebhooks-2.1.3 → gitwebhooks-2.2.0}/gitwebhooks/config/__init__.py +0 -0
- {gitwebhooks-2.1.3 → gitwebhooks-2.2.0}/gitwebhooks/config/models.py +0 -0
- {gitwebhooks-2.1.3 → gitwebhooks-2.2.0}/gitwebhooks/config/registry.py +0 -0
- {gitwebhooks-2.1.3 → gitwebhooks-2.2.0}/gitwebhooks/config/server.py +0 -0
- {gitwebhooks-2.1.3 → gitwebhooks-2.2.0}/gitwebhooks/handlers/__init__.py +0 -0
- {gitwebhooks-2.1.3 → gitwebhooks-2.2.0}/gitwebhooks/handlers/base.py +0 -0
- {gitwebhooks-2.1.3 → gitwebhooks-2.2.0}/gitwebhooks/handlers/custom.py +0 -0
- {gitwebhooks-2.1.3 → gitwebhooks-2.2.0}/gitwebhooks/handlers/factory.py +0 -0
- {gitwebhooks-2.1.3 → gitwebhooks-2.2.0}/gitwebhooks/handlers/gitee.py +0 -0
- {gitwebhooks-2.1.3 → gitwebhooks-2.2.0}/gitwebhooks/handlers/github.py +0 -0
- {gitwebhooks-2.1.3 → gitwebhooks-2.2.0}/gitwebhooks/handlers/gitlab.py +0 -0
- {gitwebhooks-2.1.3 → gitwebhooks-2.2.0}/gitwebhooks/logging/__init__.py +0 -0
- {gitwebhooks-2.1.3 → gitwebhooks-2.2.0}/gitwebhooks/main/__main__.py +0 -0
- {gitwebhooks-2.1.3 → gitwebhooks-2.2.0}/gitwebhooks/models/__init__.py +0 -0
- {gitwebhooks-2.1.3 → gitwebhooks-2.2.0}/gitwebhooks/models/provider.py +0 -0
- {gitwebhooks-2.1.3 → gitwebhooks-2.2.0}/gitwebhooks/models/request.py +0 -0
- {gitwebhooks-2.1.3 → gitwebhooks-2.2.0}/gitwebhooks/models/result.py +0 -0
- {gitwebhooks-2.1.3 → gitwebhooks-2.2.0}/gitwebhooks/server.py +0 -0
- {gitwebhooks-2.1.3 → gitwebhooks-2.2.0}/gitwebhooks/utils/__init__.py +0 -0
- {gitwebhooks-2.1.3 → gitwebhooks-2.2.0}/gitwebhooks/utils/constants.py +0 -0
- {gitwebhooks-2.1.3 → gitwebhooks-2.2.0}/gitwebhooks/utils/exceptions.py +0 -0
- {gitwebhooks-2.1.3 → gitwebhooks-2.2.0}/gitwebhooks/utils/executor.py +0 -0
- {gitwebhooks-2.1.3 → gitwebhooks-2.2.0}/gitwebhooks.egg-info/dependency_links.txt +0 -0
- {gitwebhooks-2.1.3 → gitwebhooks-2.2.0}/gitwebhooks.egg-info/entry_points.txt +0 -0
- {gitwebhooks-2.1.3 → gitwebhooks-2.2.0}/gitwebhooks.egg-info/requires.txt +0 -0
- {gitwebhooks-2.1.3 → gitwebhooks-2.2.0}/gitwebhooks.egg-info/top_level.txt +0 -0
- {gitwebhooks-2.1.3 → gitwebhooks-2.2.0}/setup.cfg +0 -0
- {gitwebhooks-2.1.3 → gitwebhooks-2.2.0}/tests/fixtures/__init__.py +0 -0
- {gitwebhooks-2.1.3 → gitwebhooks-2.2.0}/tests/fixtures/custom_payloads.py +0 -0
- {gitwebhooks-2.1.3 → gitwebhooks-2.2.0}/tests/fixtures/gitee_payloads.py +0 -0
- {gitwebhooks-2.1.3 → gitwebhooks-2.2.0}/tests/fixtures/github_payloads.py +0 -0
- {gitwebhooks-2.1.3 → gitwebhooks-2.2.0}/tests/fixtures/gitlab_payloads.py +0 -0
- {gitwebhooks-2.1.3 → gitwebhooks-2.2.0}/tests/fixtures/signature_builder.py +0 -0
- {gitwebhooks-2.1.3 → gitwebhooks-2.2.0}/tests/integration/test_command_execution.py +0 -0
- {gitwebhooks-2.1.3 → gitwebhooks-2.2.0}/tests/integration/test_gitee_webhook.py +0 -0
- {gitwebhooks-2.1.3 → gitwebhooks-2.2.0}/tests/integration/test_github_webhook.py +0 -0
- {gitwebhooks-2.1.3 → gitwebhooks-2.2.0}/tests/integration/test_gitlab_webhook.py +0 -0
- {gitwebhooks-2.1.3 → gitwebhooks-2.2.0}/tests/test_auth/__init__.py +0 -0
- {gitwebhooks-2.1.3 → gitwebhooks-2.2.0}/tests/test_config/__init__.py +0 -0
- {gitwebhooks-2.1.3 → gitwebhooks-2.2.0}/tests/test_handlers/__init__.py +0 -0
- {gitwebhooks-2.1.3 → gitwebhooks-2.2.0}/tests/test_integration/__init__.py +0 -0
- {gitwebhooks-2.1.3 → gitwebhooks-2.2.0}/tests/unit/cli/__init__.py +0 -0
- {gitwebhooks-2.1.3 → gitwebhooks-2.2.0}/tests/unit/cli/test_config_view.py +0 -0
- {gitwebhooks-2.1.3 → gitwebhooks-2.2.0}/tests/unit/cli/test_init_wizard.py +0 -0
- {gitwebhooks-2.1.3 → gitwebhooks-2.2.0}/tests/unit/test_data_parsing.py +0 -0
- {gitwebhooks-2.1.3 → gitwebhooks-2.2.0}/tests/unit/test_provider_detection.py +0 -0
- {gitwebhooks-2.1.3 → gitwebhooks-2.2.0}/tests/unit/test_request_handler.py +0 -0
- {gitwebhooks-2.1.3 → gitwebhooks-2.2.0}/tests/utils/__init__.py +0 -0
|
@@ -42,26 +42,34 @@ sudo gitwebhooks-cli service uninstall
|
|
|
42
42
|
# 方式1: 使用模块入口
|
|
43
43
|
python3 -m gitwebhooks.cli -c /path/to/config.ini
|
|
44
44
|
|
|
45
|
-
# 方式2: 使用 CLI
|
|
45
|
+
# 方式2: 使用 CLI 工具(自动查找配置文件)
|
|
46
46
|
gitwebhooks-cli
|
|
47
47
|
|
|
48
48
|
# 方式3: 指定配置文件
|
|
49
49
|
gitwebhooks-cli -c /path/to/config.ini
|
|
50
50
|
|
|
51
51
|
# systemd 服务管理
|
|
52
|
-
systemctl start
|
|
53
|
-
systemctl stop
|
|
54
|
-
systemctl restart
|
|
55
|
-
systemctl status
|
|
52
|
+
systemctl start gitwebhooks
|
|
53
|
+
systemctl stop gitwebhooks
|
|
54
|
+
systemctl restart gitwebhooks
|
|
55
|
+
systemctl status gitwebhooks
|
|
56
56
|
```
|
|
57
57
|
|
|
58
|
+
**配置文件自动查找**:
|
|
59
|
+
- 不指定 `-c` 参数时,系统按优先级自动查找配置文件:
|
|
60
|
+
1. `~/.gitwebhooks.ini`(用户级,最高优先级)
|
|
61
|
+
2. `/usr/local/etc/gitwebhooks.ini`(本地级)
|
|
62
|
+
3. `/etc/gitwebhooks.ini`(系统级)
|
|
63
|
+
- 启动时会显示正在使用的配置文件路径
|
|
64
|
+
- 找不到配置文件时显示友好的错误消息
|
|
65
|
+
|
|
58
66
|
### 测试开发
|
|
59
67
|
```bash
|
|
60
68
|
# 直接运行(开发模式)
|
|
61
|
-
./gitwebhooks-cli -c
|
|
69
|
+
./gitwebhooks-cli -c gitwebhooks.ini.sample
|
|
62
70
|
|
|
63
71
|
# 或使用模块方式
|
|
64
|
-
python3 -m gitwebhooks.cli -c
|
|
72
|
+
python3 -m gitwebhooks.cli -c gitwebhooks.ini.sample
|
|
65
73
|
|
|
66
74
|
# 运行测试套件
|
|
67
75
|
python3 -m pytest tests/
|
|
@@ -204,7 +212,7 @@ python3 -m pytest tests/
|
|
|
204
212
|
## 文件结构
|
|
205
213
|
|
|
206
214
|
```
|
|
207
|
-
|
|
215
|
+
gitwebhooks/
|
|
208
216
|
├── gitwebhooks-cli # CLI 命令行工具
|
|
209
217
|
├── gitwebhooks/ # 主包目录
|
|
210
218
|
│ ├── __init__.py # 包入口
|
|
@@ -250,8 +258,8 @@ git-webhooks-server/
|
|
|
250
258
|
│ ├── integration/ # 集成测试
|
|
251
259
|
│ ├── utils/ # 测试工具
|
|
252
260
|
│ └── conftest.py # pytest 配置
|
|
253
|
-
├──
|
|
254
|
-
├──
|
|
261
|
+
├── gitwebhooks.ini.sample # 配置文件模板
|
|
262
|
+
├── gitwebhooks.service.sample # systemd 服务模板
|
|
255
263
|
├── install.sh # 安装/卸载脚本
|
|
256
264
|
├── message.sh # 颜色输出辅助脚本
|
|
257
265
|
├── README.md # 项目说明(英文)
|
|
@@ -268,10 +276,10 @@ git-webhooks-server/
|
|
|
268
276
|
|
|
269
277
|
## 配置文件位置
|
|
270
278
|
|
|
271
|
-
- 默认配置路径: `/usr/local/etc/
|
|
272
|
-
- 日志文件: `/var/log/
|
|
279
|
+
- 默认配置路径: `/usr/local/etc/gitwebhooks.ini`
|
|
280
|
+
- 日志文件: `/var/log/gitwebhooks.log`
|
|
273
281
|
- 安装后的 CLI: `/usr/local/bin/gitwebhooks-cli`
|
|
274
|
-
- systemd 服务: `/usr/lib/systemd/system/
|
|
282
|
+
- systemd 服务: `/usr/lib/systemd/system/gitwebhooks.service`
|
|
275
283
|
|
|
276
284
|
## Active Technologies
|
|
277
285
|
- Python 3.6+ + Python 标准库(无外部依赖)
|
|
@@ -292,6 +300,7 @@ git-webhooks-server/
|
|
|
292
300
|
- INI 配置文件,systemd 服务单元文件 (001-install-method-guidance)
|
|
293
301
|
- Python 3.7+ (项目要求) + Python 标准库仅(无外部依赖) (001-fix-config-init-bug)
|
|
294
302
|
- INI 配置文件 (configparser) (001-fix-config-init-bug)
|
|
303
|
+
- Python 3.7+ (项目要求) + Python 标准库(pathlib, configparser, argparse) (001-config-priority)
|
|
295
304
|
|
|
296
305
|
## Recent Changes
|
|
297
306
|
- 001-config-init-wizard: 添加 `config init` 交互式向导,支持配置级别选择、平台配置和仓库配置
|
|
@@ -1,14 +1,14 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: gitwebhooks
|
|
3
|
-
Version: 2.
|
|
3
|
+
Version: 2.2.0
|
|
4
4
|
Summary: A lightweight Git webhook server for automated deployment supporting GitHub, Gitee, GitLab, and custom webhooks
|
|
5
5
|
Author-email: Troy Tse <troy@holyhi.net>
|
|
6
6
|
Maintainer-email: Troy Tse <troy@holyhi.net>
|
|
7
7
|
License-Expression: MIT
|
|
8
|
-
Project-URL: Homepage, https://github.com/troytse/
|
|
9
|
-
Project-URL: Documentation, https://github.com/troytse/
|
|
10
|
-
Project-URL: Repository, https://github.com/troytse/
|
|
11
|
-
Project-URL: Issues, https://github.com/troytse/
|
|
8
|
+
Project-URL: Homepage, https://github.com/troytse/gitwebhooks
|
|
9
|
+
Project-URL: Documentation, https://github.com/troytse/gitwebhooks#readme
|
|
10
|
+
Project-URL: Repository, https://github.com/troytse/gitwebhooks.git
|
|
11
|
+
Project-URL: Issues, https://github.com/troytse/gitwebhooks/issues
|
|
12
12
|
Keywords: webhook,git,github,gitee,gitlab,deployment,automation,server,devops
|
|
13
13
|
Classifier: Development Status :: 5 - Production/Stable
|
|
14
14
|
Classifier: Environment :: No Input/Output (Daemon)
|
|
@@ -291,9 +291,47 @@ pip uninstall gitwebhooks
|
|
|
291
291
|
|
|
292
292
|
## Usage
|
|
293
293
|
|
|
294
|
+
### Configuration File Auto-Discovery
|
|
295
|
+
|
|
296
|
+
The `gitwebhooks-cli` automatically searches for configuration files in the following order (priority):
|
|
297
|
+
|
|
298
|
+
1. **User level**: `~/.gitwebhooks.ini` (highest priority)
|
|
299
|
+
2. **Local level**: `/usr/local/etc/gitwebhooks.ini`
|
|
300
|
+
3. **System level**: `/etc/gitwebhooks.ini` (lowest priority)
|
|
301
|
+
|
|
302
|
+
You can run `gitwebhooks-cli` without specifying `-c` parameter, and it will automatically use the first existing configuration file.
|
|
303
|
+
|
|
304
|
+
```bash
|
|
305
|
+
# Auto-discover and use configuration file
|
|
306
|
+
gitwebhooks-cli
|
|
307
|
+
|
|
308
|
+
# The server will display which config file is being used
|
|
309
|
+
# Using configuration file: /home/user/.gitwebhooks.ini
|
|
310
|
+
```
|
|
311
|
+
|
|
312
|
+
If you want to use a specific configuration file, use the `-c` parameter:
|
|
313
|
+
|
|
314
|
+
```bash
|
|
315
|
+
# Use a specific configuration file
|
|
316
|
+
gitwebhooks-cli -c /path/to/custom.ini
|
|
317
|
+
```
|
|
318
|
+
|
|
319
|
+
If no configuration file is found, a friendly error message will display all searched paths:
|
|
320
|
+
|
|
321
|
+
```
|
|
322
|
+
Error: Configuration file not found.
|
|
323
|
+
Searched paths:
|
|
324
|
+
1. /home/user/.gitwebhooks.ini
|
|
325
|
+
2. /usr/local/etc/gitwebhooks.ini
|
|
326
|
+
3. /etc/gitwebhooks.ini
|
|
327
|
+
|
|
328
|
+
You can create a configuration file using:
|
|
329
|
+
gitwebhooks-cli config init
|
|
330
|
+
```
|
|
331
|
+
|
|
294
332
|
### 1. Configure Repository
|
|
295
333
|
|
|
296
|
-
Edit `~/.
|
|
334
|
+
Edit your configuration file (e.g., `~/.gitwebhooks.ini`):
|
|
297
335
|
|
|
298
336
|
```ini
|
|
299
337
|
[your_name/repository]
|
|
@@ -307,7 +345,7 @@ cmd=git fetch --all && git reset --hard origin/master && git pull
|
|
|
307
345
|
# If running as a service
|
|
308
346
|
systemctl restart gitwebhooks
|
|
309
347
|
|
|
310
|
-
# Or run directly:
|
|
348
|
+
# Or run directly (auto-discovers config file):
|
|
311
349
|
gitwebhooks-cli
|
|
312
350
|
```
|
|
313
351
|
|
|
@@ -251,9 +251,47 @@ pip uninstall gitwebhooks
|
|
|
251
251
|
|
|
252
252
|
## Usage
|
|
253
253
|
|
|
254
|
+
### Configuration File Auto-Discovery
|
|
255
|
+
|
|
256
|
+
The `gitwebhooks-cli` automatically searches for configuration files in the following order (priority):
|
|
257
|
+
|
|
258
|
+
1. **User level**: `~/.gitwebhooks.ini` (highest priority)
|
|
259
|
+
2. **Local level**: `/usr/local/etc/gitwebhooks.ini`
|
|
260
|
+
3. **System level**: `/etc/gitwebhooks.ini` (lowest priority)
|
|
261
|
+
|
|
262
|
+
You can run `gitwebhooks-cli` without specifying `-c` parameter, and it will automatically use the first existing configuration file.
|
|
263
|
+
|
|
264
|
+
```bash
|
|
265
|
+
# Auto-discover and use configuration file
|
|
266
|
+
gitwebhooks-cli
|
|
267
|
+
|
|
268
|
+
# The server will display which config file is being used
|
|
269
|
+
# Using configuration file: /home/user/.gitwebhooks.ini
|
|
270
|
+
```
|
|
271
|
+
|
|
272
|
+
If you want to use a specific configuration file, use the `-c` parameter:
|
|
273
|
+
|
|
274
|
+
```bash
|
|
275
|
+
# Use a specific configuration file
|
|
276
|
+
gitwebhooks-cli -c /path/to/custom.ini
|
|
277
|
+
```
|
|
278
|
+
|
|
279
|
+
If no configuration file is found, a friendly error message will display all searched paths:
|
|
280
|
+
|
|
281
|
+
```
|
|
282
|
+
Error: Configuration file not found.
|
|
283
|
+
Searched paths:
|
|
284
|
+
1. /home/user/.gitwebhooks.ini
|
|
285
|
+
2. /usr/local/etc/gitwebhooks.ini
|
|
286
|
+
3. /etc/gitwebhooks.ini
|
|
287
|
+
|
|
288
|
+
You can create a configuration file using:
|
|
289
|
+
gitwebhooks-cli config init
|
|
290
|
+
```
|
|
291
|
+
|
|
254
292
|
### 1. Configure Repository
|
|
255
293
|
|
|
256
|
-
Edit `~/.
|
|
294
|
+
Edit your configuration file (e.g., `~/.gitwebhooks.ini`):
|
|
257
295
|
|
|
258
296
|
```ini
|
|
259
297
|
[your_name/repository]
|
|
@@ -267,7 +305,7 @@ cmd=git fetch --all && git reset --hard origin/master && git pull
|
|
|
267
305
|
# If running as a service
|
|
268
306
|
systemctl restart gitwebhooks
|
|
269
307
|
|
|
270
|
-
# Or run directly:
|
|
308
|
+
# Or run directly (auto-discovers config file):
|
|
271
309
|
gitwebhooks-cli
|
|
272
310
|
```
|
|
273
311
|
|
|
@@ -251,9 +251,47 @@ pip uninstall gitwebhooks
|
|
|
251
251
|
|
|
252
252
|
## 使用
|
|
253
253
|
|
|
254
|
+
### 配置文件自动查找
|
|
255
|
+
|
|
256
|
+
`gitwebhooks-cli` 会自动按以下顺序(优先级)搜索配置文件:
|
|
257
|
+
|
|
258
|
+
1. **用户级**:`~/.gitwebhooks.ini`(最高优先级)
|
|
259
|
+
2. **本地级**:`/usr/local/etc/gitwebhooks.ini`
|
|
260
|
+
3. **系统级**:`/etc/gitwebhooks.ini`(最低优先级)
|
|
261
|
+
|
|
262
|
+
您可以直接运行 `gitwebhooks-cli` 而无需指定 `-c` 参数,系统会自动使用第一个存在的配置文件。
|
|
263
|
+
|
|
264
|
+
```bash
|
|
265
|
+
# 自动查找并使用配置文件
|
|
266
|
+
gitwebhooks-cli
|
|
267
|
+
|
|
268
|
+
# 服务器会显示正在使用的配置文件
|
|
269
|
+
# Using configuration file: /home/user/.gitwebhooks.ini
|
|
270
|
+
```
|
|
271
|
+
|
|
272
|
+
如果需要使用特定的配置文件,可以使用 `-c` 参数:
|
|
273
|
+
|
|
274
|
+
```bash
|
|
275
|
+
# 使用指定的配置文件
|
|
276
|
+
gitwebhooks-cli -c /path/to/custom.ini
|
|
277
|
+
```
|
|
278
|
+
|
|
279
|
+
如果找不到配置文件,会显示友好的错误消息并列出所有搜索路径:
|
|
280
|
+
|
|
281
|
+
```
|
|
282
|
+
Error: Configuration file not found.
|
|
283
|
+
Searched paths:
|
|
284
|
+
1. /home/user/.gitwebhooks.ini
|
|
285
|
+
2. /usr/local/etc/gitwebhooks.ini
|
|
286
|
+
3. /etc/gitwebhooks.ini
|
|
287
|
+
|
|
288
|
+
You can create a configuration file using:
|
|
289
|
+
gitwebhooks-cli config init
|
|
290
|
+
```
|
|
291
|
+
|
|
254
292
|
### 1. 配置仓库
|
|
255
293
|
|
|
256
|
-
|
|
294
|
+
编辑您的配置文件(例如 `~/.gitwebhooks.ini`):
|
|
257
295
|
|
|
258
296
|
```ini
|
|
259
297
|
[your_name/repository]
|
|
@@ -267,7 +305,7 @@ cmd=git fetch --all && git reset --hard origin/master && git pull
|
|
|
267
305
|
# 如果作为服务运行
|
|
268
306
|
systemctl restart gitwebhooks
|
|
269
307
|
|
|
270
|
-
#
|
|
308
|
+
# 或直接运行(自动查找配置文件):
|
|
271
309
|
gitwebhooks-cli
|
|
272
310
|
```
|
|
273
311
|
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
"""
|
|
2
2
|
Interactive configuration initialization wizard.
|
|
3
3
|
|
|
4
|
-
This module provides a user-friendly wizard for creating
|
|
4
|
+
This module provides a user-friendly wizard for creating gitwebhooks
|
|
5
5
|
configuration files through an interactive command-line interface.
|
|
6
6
|
|
|
7
7
|
Features:
|
|
@@ -310,7 +310,7 @@ class Wizard:
|
|
|
310
310
|
"""
|
|
311
311
|
Interactive configuration wizard.
|
|
312
312
|
|
|
313
|
-
Guides users through creating a
|
|
313
|
+
Guides users through creating a gitwebhooks configuration file
|
|
314
314
|
by collecting server, platform, and repository configuration parameters.
|
|
315
315
|
"""
|
|
316
316
|
|
|
@@ -487,7 +487,7 @@ class Wizard:
|
|
|
487
487
|
print("端口号必须在 1-65535 之间")
|
|
488
488
|
|
|
489
489
|
# Log file
|
|
490
|
-
default_log = "/var/log/
|
|
490
|
+
default_log = "/var/log/gitwebhooks.log"
|
|
491
491
|
log_file = input(f"日志文件路径 [默认: {default_log}]: ").strip()
|
|
492
492
|
if not log_file:
|
|
493
493
|
log_file = default_log
|
|
@@ -111,7 +111,7 @@ def install_service(force: bool = False, verbose: int = 0, dry_run: bool = False
|
|
|
111
111
|
print()
|
|
112
112
|
print('For migration from conda:', file=sys.stderr)
|
|
113
113
|
print(' 1. Deactivate your conda environment: conda deactivate', file=sys.stderr)
|
|
114
|
-
print(' 2. Install using pipx: pipx install
|
|
114
|
+
print(' 2. Install using pipx: pipx install gitwebhooks', file=sys.stderr)
|
|
115
115
|
print(' OR create a venv: python3 -m venv ~/venv/gitwebhooks', file=sys.stderr)
|
|
116
116
|
return 1
|
|
117
117
|
|
|
@@ -205,14 +205,14 @@ def enable_and_start_service() -> int:
|
|
|
205
205
|
# Ask if user wants to enable and start
|
|
206
206
|
if not ask_yes_no('Enable and start service? (Y/n) ', default=True):
|
|
207
207
|
print('Service installed but not started')
|
|
208
|
-
print('Start manually: sudo systemctl start
|
|
208
|
+
print('Start manually: sudo systemctl start gitwebhooks')
|
|
209
209
|
return 0
|
|
210
210
|
|
|
211
211
|
# Enable service
|
|
212
212
|
print('Enabling service...')
|
|
213
213
|
try:
|
|
214
214
|
subprocess.run(
|
|
215
|
-
['systemctl', 'enable', '
|
|
215
|
+
['systemctl', 'enable', 'gitwebhooks'],
|
|
216
216
|
check=True,
|
|
217
217
|
capture_output=True
|
|
218
218
|
)
|
|
@@ -224,7 +224,7 @@ def enable_and_start_service() -> int:
|
|
|
224
224
|
print('Starting service...')
|
|
225
225
|
try:
|
|
226
226
|
subprocess.run(
|
|
227
|
-
['systemctl', 'start', '
|
|
227
|
+
['systemctl', 'start', 'gitwebhooks'],
|
|
228
228
|
check=True,
|
|
229
229
|
capture_output=True
|
|
230
230
|
)
|
|
@@ -234,7 +234,7 @@ def enable_and_start_service() -> int:
|
|
|
234
234
|
|
|
235
235
|
print()
|
|
236
236
|
print('Installation complete!')
|
|
237
|
-
print('Service status: systemctl status
|
|
237
|
+
print('Service status: systemctl status gitwebhooks')
|
|
238
238
|
|
|
239
239
|
return 0
|
|
240
240
|
|
|
@@ -302,7 +302,7 @@ def stop_and_disable_service() -> None:
|
|
|
302
302
|
print('Stopping service...')
|
|
303
303
|
try:
|
|
304
304
|
subprocess.run(
|
|
305
|
-
['systemctl', 'stop', '
|
|
305
|
+
['systemctl', 'stop', 'gitwebhooks'],
|
|
306
306
|
check=False,
|
|
307
307
|
capture_output=True
|
|
308
308
|
)
|
|
@@ -314,7 +314,7 @@ def stop_and_disable_service() -> None:
|
|
|
314
314
|
print('Disabling service...')
|
|
315
315
|
try:
|
|
316
316
|
subprocess.run(
|
|
317
|
-
['systemctl', 'disable', '
|
|
317
|
+
['systemctl', 'disable', 'gitwebhooks'],
|
|
318
318
|
check=False,
|
|
319
319
|
capture_output=True
|
|
320
320
|
)
|
|
@@ -98,15 +98,21 @@ class ConfigLoader:
|
|
|
98
98
|
|
|
99
99
|
Note:
|
|
100
100
|
Skips reserved section names: server, ssl, github, gitee, gitlab, custom
|
|
101
|
+
Skips repository sections with missing required options (logs warning)
|
|
101
102
|
"""
|
|
102
103
|
configs = {}
|
|
103
104
|
reserved_sections = self._get_reserved_sections()
|
|
104
105
|
|
|
105
106
|
for section in self.parser.sections():
|
|
106
107
|
if section not in reserved_sections:
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
108
|
+
try:
|
|
109
|
+
repo_config = self.load_repository_config(section)
|
|
110
|
+
if repo_config is not None:
|
|
111
|
+
configs[section] = repo_config
|
|
112
|
+
except (configparser.NoOptionError, ConfigurationError) as e:
|
|
113
|
+
# Skip incomplete repository configurations
|
|
114
|
+
import logging
|
|
115
|
+
logging.warning('跳过不完整的仓库配置 [%s]: %s', section, e)
|
|
110
116
|
|
|
111
117
|
return configs
|
|
112
118
|
|
|
@@ -185,27 +185,32 @@ class WebhookRequestHandler(BaseHTTPRequestHandler):
|
|
|
185
185
|
|
|
186
186
|
Returns:
|
|
187
187
|
Tuple of (provider, event)
|
|
188
|
-
"""
|
|
189
|
-
headers_dict = dict(self.headers)
|
|
190
188
|
|
|
189
|
+
Note:
|
|
190
|
+
HTTP headers are case-insensitive per RFC 2616.
|
|
191
|
+
Uses get() method which is case-insensitive for HTTPMessage.
|
|
192
|
+
"""
|
|
191
193
|
# GitHub
|
|
192
|
-
|
|
193
|
-
|
|
194
|
+
github_event = self.headers.get(HEADER_GITHUB_EVENT)
|
|
195
|
+
if github_event is not None:
|
|
196
|
+
return Provider.GITHUB, github_event
|
|
194
197
|
|
|
195
198
|
# Gitee
|
|
196
|
-
|
|
197
|
-
|
|
199
|
+
gitee_event = self.headers.get(HEADER_GITEE_EVENT)
|
|
200
|
+
if gitee_event is not None:
|
|
201
|
+
return Provider.GITEE, gitee_event
|
|
198
202
|
|
|
199
203
|
# GitLab
|
|
200
|
-
|
|
201
|
-
|
|
204
|
+
gitlab_event = self.headers.get(HEADER_GITLAB_EVENT)
|
|
205
|
+
if gitlab_event is not None:
|
|
206
|
+
return Provider.GITLAB, gitlab_event
|
|
202
207
|
|
|
203
208
|
# Custom
|
|
204
209
|
custom_config = self._provider_configs.get(Provider.CUSTOM)
|
|
205
210
|
if custom_config and custom_config.header_name:
|
|
206
|
-
header_value =
|
|
207
|
-
if header_value.startswith(custom_config.header_value):
|
|
208
|
-
event =
|
|
211
|
+
header_value = self.headers.get(custom_config.header_name, '')
|
|
212
|
+
if header_value and header_value.startswith(custom_config.header_value):
|
|
213
|
+
event = self.headers.get(custom_config.header_event) if custom_config.header_event else None
|
|
209
214
|
return Provider.CUSTOM, event
|
|
210
215
|
|
|
211
216
|
# Unable to identify
|
|
@@ -5,6 +5,7 @@
|
|
|
5
5
|
|
|
6
6
|
import logging
|
|
7
7
|
import sys
|
|
8
|
+
from pathlib import Path
|
|
8
9
|
|
|
9
10
|
|
|
10
11
|
def setup_logging(log_file: str = None):
|
|
@@ -16,6 +17,7 @@ def setup_logging(log_file: str = None):
|
|
|
16
17
|
根据配置设置日志记录:
|
|
17
18
|
- 如果 log_file 为空,只输出到 stdout
|
|
18
19
|
- 如果 log_file 非空,同时输出到文件和 stdout
|
|
20
|
+
- 如果日志目录不存在,只输出到 stdout(记录警告)
|
|
19
21
|
|
|
20
22
|
Note:
|
|
21
23
|
Python 3.8+ 使用 force 参数确保重新配置,
|
|
@@ -25,12 +27,21 @@ def setup_logging(log_file: str = None):
|
|
|
25
27
|
|
|
26
28
|
# 文件处理器
|
|
27
29
|
if log_file:
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
30
|
+
try:
|
|
31
|
+
log_path = Path(log_file)
|
|
32
|
+
# 确保日志目录存在
|
|
33
|
+
log_path.parent.mkdir(parents=True, exist_ok=True)
|
|
34
|
+
|
|
35
|
+
file_handler = logging.FileHandler(log_file, encoding='utf-8')
|
|
36
|
+
file_handler.setFormatter(logging.Formatter(
|
|
37
|
+
'%(asctime)s %(message)s',
|
|
38
|
+
datefmt='%Y-%m-%d %H:%M:%S'
|
|
39
|
+
))
|
|
40
|
+
handlers.append(file_handler)
|
|
41
|
+
except (OSError, IOError) as e:
|
|
42
|
+
# 如果无法创建日志文件,回退到仅控制台输出
|
|
43
|
+
import warnings
|
|
44
|
+
warnings.warn(f'无法创建日志文件 {log_file}: {e},将仅输出到控制台')
|
|
34
45
|
|
|
35
46
|
# 控制台处理器
|
|
36
47
|
console_handler = logging.StreamHandler(sys.stdout)
|
|
@@ -0,0 +1,182 @@
|
|
|
1
|
+
"""CLI main function
|
|
2
|
+
|
|
3
|
+
Command-line interface module providing compatibility with the original gitwebhooks.py.
|
|
4
|
+
"""
|
|
5
|
+
|
|
6
|
+
import argparse
|
|
7
|
+
import sys
|
|
8
|
+
from pathlib import Path
|
|
9
|
+
from typing import List, Optional
|
|
10
|
+
|
|
11
|
+
from gitwebhooks.server import WebhookServer
|
|
12
|
+
from gitwebhooks.utils.exceptions import ConfigurationError
|
|
13
|
+
from gitwebhooks.utils.constants import CONFIG_SEARCH_PATHS
|
|
14
|
+
|
|
15
|
+
# Try to import subcommands, may not be available in older versions
|
|
16
|
+
try:
|
|
17
|
+
from gitwebhooks.cli import register_subparsers
|
|
18
|
+
HAS_SUBCOMMANDS = True
|
|
19
|
+
except ImportError:
|
|
20
|
+
HAS_SUBCOMMANDS = False
|
|
21
|
+
|
|
22
|
+
|
|
23
|
+
def find_config_file() -> Optional[str]:
|
|
24
|
+
"""Find configuration file by priority order.
|
|
25
|
+
|
|
26
|
+
Searches for configuration files in the following order:
|
|
27
|
+
1. User level: ~/.gitwebhooks.ini
|
|
28
|
+
2. Local level: /usr/local/etc/gitwebhooks.ini
|
|
29
|
+
3. System level: /etc/gitwebhooks.ini
|
|
30
|
+
|
|
31
|
+
Returns:
|
|
32
|
+
Path string of the first existing configuration file, or None if not found.
|
|
33
|
+
|
|
34
|
+
Examples:
|
|
35
|
+
>>> find_config_file() # doctest: +SKIP
|
|
36
|
+
'/home/user/.gitwebhooks.ini'
|
|
37
|
+
>>> find_config_file() # doctest: +SKIP
|
|
38
|
+
None
|
|
39
|
+
"""
|
|
40
|
+
for config_path in CONFIG_SEARCH_PATHS:
|
|
41
|
+
expanded_path = Path(config_path).expanduser().resolve()
|
|
42
|
+
if expanded_path.exists():
|
|
43
|
+
return str(expanded_path)
|
|
44
|
+
return None
|
|
45
|
+
|
|
46
|
+
|
|
47
|
+
def format_config_error(searched_paths: List[Path]) -> str:
|
|
48
|
+
"""Format user-friendly error message for missing configuration file.
|
|
49
|
+
|
|
50
|
+
Args:
|
|
51
|
+
searched_paths: List of paths that were searched.
|
|
52
|
+
|
|
53
|
+
Returns:
|
|
54
|
+
Formatted error message string.
|
|
55
|
+
|
|
56
|
+
Examples:
|
|
57
|
+
>>> paths = [Path('/home/user/.gitwebhooks.ini')]
|
|
58
|
+
>>> format_config_error(paths) # doctest: +SKIP
|
|
59
|
+
'Error: Configuration file not found.\\nSearched paths:\\n 1. /home/user/.gitwebhooks.ini\\n\\nYou can create a configuration file using:\\n gitwebhooks-cli config init'
|
|
60
|
+
"""
|
|
61
|
+
lines = [
|
|
62
|
+
'Error: Configuration file not found.',
|
|
63
|
+
'Searched paths:'
|
|
64
|
+
]
|
|
65
|
+
for i, path in enumerate(searched_paths, 1):
|
|
66
|
+
lines.append(f' {i}. {path}')
|
|
67
|
+
lines.append('')
|
|
68
|
+
lines.append('You can create a configuration file using:')
|
|
69
|
+
lines.append(' gitwebhooks-cli config init')
|
|
70
|
+
return '\n'.join(lines)
|
|
71
|
+
|
|
72
|
+
|
|
73
|
+
def main(argv: List[str] = None) -> int:
|
|
74
|
+
"""Main entry point
|
|
75
|
+
|
|
76
|
+
Args:
|
|
77
|
+
argv: Command-line argument list (defaults to sys.argv[1:])
|
|
78
|
+
|
|
79
|
+
Returns:
|
|
80
|
+
Exit code (0 = success, 1 = error)
|
|
81
|
+
|
|
82
|
+
Raises:
|
|
83
|
+
SystemExit: Exit on error
|
|
84
|
+
|
|
85
|
+
Command Line Arguments:
|
|
86
|
+
-h, --help Show help message and exit
|
|
87
|
+
-c, --config Specify configuration file path (optional)
|
|
88
|
+
service Service management subcommands
|
|
89
|
+
config Configuration management subcommands
|
|
90
|
+
|
|
91
|
+
Config Discovery:
|
|
92
|
+
When -c is not specified, searches in order:
|
|
93
|
+
1. ~/.gitwebhooks.ini (user level)
|
|
94
|
+
2. /usr/local/etc/gitwebhooks.ini (local level)
|
|
95
|
+
3. /etc/gitwebhooks.ini (system level)
|
|
96
|
+
|
|
97
|
+
Examples:
|
|
98
|
+
python3 -m gitwebhooks.main
|
|
99
|
+
python3 -m gitwebhooks.main -c /path/to/config.ini
|
|
100
|
+
gitwebhooks-cli --config /etc/webhooks.ini
|
|
101
|
+
gitwebhooks-cli service install
|
|
102
|
+
gitwebhooks-cli config init
|
|
103
|
+
"""
|
|
104
|
+
if argv is None:
|
|
105
|
+
argv = sys.argv[1:]
|
|
106
|
+
|
|
107
|
+
# Create main argument parser
|
|
108
|
+
parser = argparse.ArgumentParser(
|
|
109
|
+
prog='gitwebhooks-cli',
|
|
110
|
+
description='Git Webhooks Server - Automated deployment webhook handler',
|
|
111
|
+
add_help=True
|
|
112
|
+
)
|
|
113
|
+
parser.add_argument(
|
|
114
|
+
'-c', '--config',
|
|
115
|
+
default=None,
|
|
116
|
+
help='Path to INI configuration file (default: auto-discover)'
|
|
117
|
+
)
|
|
118
|
+
|
|
119
|
+
# Add subcommands if available
|
|
120
|
+
if HAS_SUBCOMMANDS:
|
|
121
|
+
subparsers = parser.add_subparsers(dest='command', help='Subcommands')
|
|
122
|
+
register_subparsers(subparsers)
|
|
123
|
+
|
|
124
|
+
# Parse arguments
|
|
125
|
+
args = parser.parse_args(argv)
|
|
126
|
+
|
|
127
|
+
# If no subcommand, run server (backward compatible behavior)
|
|
128
|
+
if not hasattr(args, 'func'):
|
|
129
|
+
return run_server(args.config)
|
|
130
|
+
|
|
131
|
+
# Execute subcommand
|
|
132
|
+
return args.func(args)
|
|
133
|
+
|
|
134
|
+
|
|
135
|
+
def run_server(config_file: Optional[str]) -> int:
|
|
136
|
+
"""Run the webhook server
|
|
137
|
+
|
|
138
|
+
Args:
|
|
139
|
+
config_file: Path to configuration file, or None to auto-discover
|
|
140
|
+
|
|
141
|
+
Returns:
|
|
142
|
+
Exit code (0 = success, 1 = error)
|
|
143
|
+
"""
|
|
144
|
+
# Auto-discover config file if not specified
|
|
145
|
+
if config_file is None:
|
|
146
|
+
config_file = find_config_file()
|
|
147
|
+
if config_file is None:
|
|
148
|
+
# No config found - format error with all search paths
|
|
149
|
+
searched_paths = [Path(p).expanduser().resolve() for p in CONFIG_SEARCH_PATHS]
|
|
150
|
+
error_msg = format_config_error(searched_paths)
|
|
151
|
+
print(error_msg, file=sys.stderr)
|
|
152
|
+
return 1
|
|
153
|
+
|
|
154
|
+
# Expand user path
|
|
155
|
+
config_path = Path(config_file).expanduser()
|
|
156
|
+
|
|
157
|
+
# Check configuration file exists
|
|
158
|
+
if not config_path.exists():
|
|
159
|
+
print(f'Error: Configuration file not found: {config_path}', file=sys.stderr)
|
|
160
|
+
return 1
|
|
161
|
+
|
|
162
|
+
# Print configuration file being used
|
|
163
|
+
print(f'Using configuration file: {config_path}')
|
|
164
|
+
|
|
165
|
+
# Create and run server
|
|
166
|
+
try:
|
|
167
|
+
server = WebhookServer(config_path=str(config_path))
|
|
168
|
+
server.run()
|
|
169
|
+
return 0
|
|
170
|
+
except ConfigurationError as e:
|
|
171
|
+
print(f'Configuration error: {e}', file=sys.stderr)
|
|
172
|
+
return 1
|
|
173
|
+
except KeyboardInterrupt:
|
|
174
|
+
print('\nServer stopped by user')
|
|
175
|
+
return 0
|
|
176
|
+
except Exception as e:
|
|
177
|
+
print(f'Error: {e}', file=sys.stderr)
|
|
178
|
+
return 1
|
|
179
|
+
|
|
180
|
+
|
|
181
|
+
if __name__ == '__main__':
|
|
182
|
+
sys.exit(main())
|