github2gerrit 1.4.0__tar.gz → 1.4.2__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.
- {github2gerrit-1.4.0 → github2gerrit-1.4.2}/.pre-commit-config.yaml +2 -2
- {github2gerrit-1.4.0 → github2gerrit-1.4.2}/PKG-INFO +6 -4
- {github2gerrit-1.4.0 → github2gerrit-1.4.2}/README.md +5 -3
- {github2gerrit-1.4.0 → github2gerrit-1.4.2}/action.yaml +13 -3
- {github2gerrit-1.4.0 → github2gerrit-1.4.2}/docs/cli.md +27 -20
- {github2gerrit-1.4.0 → github2gerrit-1.4.2}/docs/features.md +7 -8
- {github2gerrit-1.4.0 → github2gerrit-1.4.2}/pyproject.toml +6 -4
- {github2gerrit-1.4.0 → github2gerrit-1.4.2}/src/github2gerrit/cli.py +21 -50
- {github2gerrit-1.4.0 → github2gerrit-1.4.2}/src/github2gerrit/commit_normalization.py +0 -16
- {github2gerrit-1.4.0 → github2gerrit-1.4.2}/src/github2gerrit/commit_rules.py +0 -24
- {github2gerrit-1.4.0 → github2gerrit-1.4.2}/src/github2gerrit/config.py +36 -8
- {github2gerrit-1.4.0 → github2gerrit-1.4.2}/src/github2gerrit/core.py +252 -157
- {github2gerrit-1.4.0 → github2gerrit-1.4.2}/src/github2gerrit/duplicate_detection.py +0 -9
- {github2gerrit-1.4.0 → github2gerrit-1.4.2}/src/github2gerrit/error_codes.py +19 -7
- {github2gerrit-1.4.0 → github2gerrit-1.4.2}/src/github2gerrit/external_api.py +0 -7
- {github2gerrit-1.4.0 → github2gerrit-1.4.2}/src/github2gerrit/gerrit_pr_closer.py +4 -45
- {github2gerrit-1.4.0 → github2gerrit-1.4.2}/src/github2gerrit/gerrit_query.py +54 -15
- {github2gerrit-1.4.0 → github2gerrit-1.4.2}/src/github2gerrit/github_api.py +0 -1
- {github2gerrit-1.4.0 → github2gerrit-1.4.2}/src/github2gerrit/gitreview.py +0 -56
- {github2gerrit-1.4.0 → github2gerrit-1.4.2}/src/github2gerrit/gitutils.py +0 -5
- {github2gerrit-1.4.0 → github2gerrit-1.4.2}/src/github2gerrit/mapping_comment.py +0 -2
- {github2gerrit-1.4.0 → github2gerrit-1.4.2}/src/github2gerrit/netrc.py +12 -21
- {github2gerrit-1.4.0 → github2gerrit-1.4.2}/src/github2gerrit/orchestrator/reconciliation.py +13 -19
- {github2gerrit-1.4.0 → github2gerrit-1.4.2}/src/github2gerrit/pr_content_filter.py +0 -17
- {github2gerrit-1.4.0 → github2gerrit-1.4.2}/src/github2gerrit/reconcile_matcher.py +0 -6
- {github2gerrit-1.4.0 → github2gerrit-1.4.2}/src/github2gerrit/rich_display.py +5 -3
- {github2gerrit-1.4.0 → github2gerrit-1.4.2}/src/github2gerrit/rich_logging.py +5 -5
- {github2gerrit-1.4.0 → github2gerrit-1.4.2}/src/github2gerrit/similarity.py +0 -4
- {github2gerrit-1.4.0 → github2gerrit-1.4.2}/src/github2gerrit/ssh_agent_setup.py +0 -6
- {github2gerrit-1.4.0 → github2gerrit-1.4.2}/src/github2gerrit/ssh_common.py +0 -1
- {github2gerrit-1.4.0 → github2gerrit-1.4.2}/src/github2gerrit/ssh_config_parser.py +0 -3
- {github2gerrit-1.4.0 → github2gerrit-1.4.2}/src/github2gerrit/ssh_discovery.py +2 -7
- {github2gerrit-1.4.0 → github2gerrit-1.4.2}/src/github2gerrit/trailers.py +0 -7
- {github2gerrit-1.4.0 → github2gerrit-1.4.2}/tests/test_config_helpers.py +2 -2
- {github2gerrit-1.4.0 → github2gerrit-1.4.2}/tests/test_core_config_and_errors.py +143 -0
- github2gerrit-1.4.2/tests/test_final_state_reconciliation.py +333 -0
- {github2gerrit-1.4.0 → github2gerrit-1.4.2}/tests/test_pr_update_detection.py +2 -2
- {github2gerrit-1.4.0 → github2gerrit-1.4.2}/tests/test_reconciliation_extracted_module.py +43 -0
- {github2gerrit-1.4.0 → github2gerrit-1.4.2}/uv.lock +149 -143
- github2gerrit-1.4.0/.readthedocs.yml +0 -32
- {github2gerrit-1.4.0 → github2gerrit-1.4.2}/.editorconfig +0 -0
- {github2gerrit-1.4.0 → github2gerrit-1.4.2}/.gitignore +0 -0
- {github2gerrit-1.4.0 → github2gerrit-1.4.2}/.gitlint +0 -0
- {github2gerrit-1.4.0 → github2gerrit-1.4.2}/.markdownlint.yaml +0 -0
- {github2gerrit-1.4.0 → github2gerrit-1.4.2}/.yamllint +0 -0
- {github2gerrit-1.4.0 → github2gerrit-1.4.2}/LICENSE +0 -0
- {github2gerrit-1.4.0 → github2gerrit-1.4.2}/LICENSES/Apache-2.0.txt +0 -0
- {github2gerrit-1.4.0 → github2gerrit-1.4.2}/REUSE.toml +0 -0
- {github2gerrit-1.4.0 → github2gerrit-1.4.2}/SECURITY.md +0 -0
- {github2gerrit-1.4.0 → github2gerrit-1.4.2}/docs/COMMIT_RULES.md +0 -0
- {github2gerrit-1.4.0 → github2gerrit-1.4.2}/docs/development.md +0 -0
- {github2gerrit-1.4.0 → github2gerrit-1.4.2}/docs/github2gerrit_token_permissions_classic.png +0 -0
- {github2gerrit-1.4.0 → github2gerrit-1.4.2}/sitecustomize.py +0 -0
- {github2gerrit-1.4.0 → github2gerrit-1.4.2}/src/github2gerrit/__init__.py +0 -0
- {github2gerrit-1.4.0 → github2gerrit-1.4.2}/src/github2gerrit/constants.py +0 -0
- {github2gerrit-1.4.0 → github2gerrit-1.4.2}/src/github2gerrit/gerrit_rest.py +0 -0
- {github2gerrit-1.4.0 → github2gerrit-1.4.2}/src/github2gerrit/gerrit_ssh.py +0 -0
- {github2gerrit-1.4.0 → github2gerrit-1.4.2}/src/github2gerrit/gerrit_urls.py +0 -0
- {github2gerrit-1.4.0 → github2gerrit-1.4.2}/src/github2gerrit/models.py +0 -0
- {github2gerrit-1.4.0 → github2gerrit-1.4.2}/src/github2gerrit/orchestrator/__init__.py +0 -0
- {github2gerrit-1.4.0 → github2gerrit-1.4.2}/src/github2gerrit/pr_commands.py +0 -0
- {github2gerrit-1.4.0 → github2gerrit-1.4.2}/src/github2gerrit/utils.py +0 -0
- {github2gerrit-1.4.0 → github2gerrit-1.4.2}/tests/conftest.py +0 -0
- {github2gerrit-1.4.0 → github2gerrit-1.4.2}/tests/fixtures/__init__.py +0 -0
- {github2gerrit-1.4.0 → github2gerrit-1.4.2}/tests/fixtures/make_repo.py +0 -0
- {github2gerrit-1.4.0 → github2gerrit-1.4.2}/tests/fixtures/ssh_config_samples.py +0 -0
- {github2gerrit-1.4.0 → github2gerrit-1.4.2}/tests/test_action_environment_mapping.py +0 -0
- {github2gerrit-1.4.0 → github2gerrit-1.4.2}/tests/test_action_outputs.py +0 -0
- {github2gerrit-1.4.0 → github2gerrit-1.4.2}/tests/test_action_pr_number_handling.py +0 -0
- {github2gerrit-1.4.0 → github2gerrit-1.4.2}/tests/test_action_step_validation.py +0 -0
- {github2gerrit-1.4.0 → github2gerrit-1.4.2}/tests/test_automation_only.py +0 -0
- {github2gerrit-1.4.0 → github2gerrit-1.4.2}/tests/test_change_id_deduplication.py +0 -0
- {github2gerrit-1.4.0 → github2gerrit-1.4.2}/tests/test_clean_squash_title.py +0 -0
- {github2gerrit-1.4.0 → github2gerrit-1.4.2}/tests/test_cli.py +0 -0
- {github2gerrit-1.4.0 → github2gerrit-1.4.2}/tests/test_cli_helpers.py +0 -0
- {github2gerrit-1.4.0 → github2gerrit-1.4.2}/tests/test_cli_netrc_options.py +0 -0
- {github2gerrit-1.4.0 → github2gerrit-1.4.2}/tests/test_cli_outputs_file.py +0 -0
- {github2gerrit-1.4.0 → github2gerrit-1.4.2}/tests/test_cli_url_and_dryrun.py +0 -0
- {github2gerrit-1.4.0 → github2gerrit-1.4.2}/tests/test_commit_normalization.py +0 -0
- {github2gerrit-1.4.0 → github2gerrit-1.4.2}/tests/test_commit_rules.py +0 -0
- {github2gerrit-1.4.0 → github2gerrit-1.4.2}/tests/test_composite_action_coverage.py +0 -0
- {github2gerrit-1.4.0 → github2gerrit-1.4.2}/tests/test_config_and_reviewers.py +0 -0
- {github2gerrit-1.4.0 → github2gerrit-1.4.2}/tests/test_core_close_pr_policy.py +0 -0
- {github2gerrit-1.4.0 → github2gerrit-1.4.2}/tests/test_core_gerrit_backref_comment.py +0 -0
- {github2gerrit-1.4.0 → github2gerrit-1.4.2}/tests/test_core_gerrit_push_errors.py +0 -0
- {github2gerrit-1.4.0 → github2gerrit-1.4.2}/tests/test_core_gerrit_rest_results.py +0 -0
- {github2gerrit-1.4.0 → github2gerrit-1.4.2}/tests/test_core_integration_fixture_repo.py +0 -0
- {github2gerrit-1.4.0 → github2gerrit-1.4.2}/tests/test_core_prepare_commits.py +0 -0
- {github2gerrit-1.4.0 → github2gerrit-1.4.2}/tests/test_core_shallow_clone.py +0 -0
- {github2gerrit-1.4.0 → github2gerrit-1.4.2}/tests/test_core_ssh_setup.py +0 -0
- {github2gerrit-1.4.0 → github2gerrit-1.4.2}/tests/test_core_ssrf_protection.py +0 -0
- {github2gerrit-1.4.0 → github2gerrit-1.4.2}/tests/test_dependency_supersession.py +0 -0
- {github2gerrit-1.4.0 → github2gerrit-1.4.2}/tests/test_dns_validation_and_no_gerrit.py +0 -0
- {github2gerrit-1.4.0 → github2gerrit-1.4.2}/tests/test_duplicate_detection.py +0 -0
- {github2gerrit-1.4.0 → github2gerrit-1.4.2}/tests/test_email_case_normalization.py +0 -0
- {github2gerrit-1.4.0 → github2gerrit-1.4.2}/tests/test_error_codes.py +0 -0
- {github2gerrit-1.4.0 → github2gerrit-1.4.2}/tests/test_external_api_framework.py +0 -0
- {github2gerrit-1.4.0 → github2gerrit-1.4.2}/tests/test_force_flag_cli.py +0 -0
- {github2gerrit-1.4.0 → github2gerrit-1.4.2}/tests/test_gerrit_change_id_footer.py +0 -0
- {github2gerrit-1.4.0 → github2gerrit-1.4.2}/tests/test_gerrit_change_status_checks.py +0 -0
- {github2gerrit-1.4.0 → github2gerrit-1.4.2}/tests/test_gerrit_pr_closer.py +0 -0
- {github2gerrit-1.4.0 → github2gerrit-1.4.2}/tests/test_gerrit_rest_client.py +0 -0
- {github2gerrit-1.4.0 → github2gerrit-1.4.2}/tests/test_gerrit_ssh_abandon.py +0 -0
- {github2gerrit-1.4.0 → github2gerrit-1.4.2}/tests/test_gerrit_urls.py +0 -0
- {github2gerrit-1.4.0 → github2gerrit-1.4.2}/tests/test_gerrit_urls_more.py +0 -0
- {github2gerrit-1.4.0 → github2gerrit-1.4.2}/tests/test_ghe_and_gitreview_args.py +0 -0
- {github2gerrit-1.4.0 → github2gerrit-1.4.2}/tests/test_github_api_error_handling.py +0 -0
- {github2gerrit-1.4.0 → github2gerrit-1.4.2}/tests/test_github_api_helpers.py +0 -0
- {github2gerrit-1.4.0 → github2gerrit-1.4.2}/tests/test_github_api_retry_and_helpers.py +0 -0
- {github2gerrit-1.4.0 → github2gerrit-1.4.2}/tests/test_gitreview.py +0 -0
- {github2gerrit-1.4.0 → github2gerrit-1.4.2}/tests/test_gitutils_helpers.py +0 -0
- {github2gerrit-1.4.0 → github2gerrit-1.4.2}/tests/test_issue_157_regressions.py +0 -0
- {github2gerrit-1.4.0 → github2gerrit-1.4.2}/tests/test_mapping_comment_additional.py +0 -0
- {github2gerrit-1.4.0 → github2gerrit-1.4.2}/tests/test_mapping_comment_digest_and_backref.py +0 -0
- {github2gerrit-1.4.0 → github2gerrit-1.4.2}/tests/test_metadata_and_reconciliation.py +0 -0
- {github2gerrit-1.4.0 → github2gerrit-1.4.2}/tests/test_metadata_trailer_separation_bug.py +0 -0
- {github2gerrit-1.4.0 → github2gerrit-1.4.2}/tests/test_misc_small_coverage.py +0 -0
- {github2gerrit-1.4.0 → github2gerrit-1.4.2}/tests/test_netrc.py +0 -0
- {github2gerrit-1.4.0 → github2gerrit-1.4.2}/tests/test_orphan_rest_side_effects.py +0 -0
- {github2gerrit-1.4.0 → github2gerrit-1.4.2}/tests/test_pr_commands.py +0 -0
- {github2gerrit-1.4.0 → github2gerrit-1.4.2}/tests/test_pr_content_filter.py +0 -0
- {github2gerrit-1.4.0 → github2gerrit-1.4.2}/tests/test_pr_content_filter_integration.py +0 -0
- {github2gerrit-1.4.0 → github2gerrit-1.4.2}/tests/test_reconciliation_plan_and_orphans.py +0 -0
- {github2gerrit-1.4.0 → github2gerrit-1.4.2}/tests/test_reconciliation_scenarios.py +0 -0
- {github2gerrit-1.4.0 → github2gerrit-1.4.2}/tests/test_ssh_agent.py +0 -0
- {github2gerrit-1.4.0 → github2gerrit-1.4.2}/tests/test_ssh_agent_ownership.py +0 -0
- {github2gerrit-1.4.0 → github2gerrit-1.4.2}/tests/test_ssh_artifact_prevention.py +0 -0
- {github2gerrit-1.4.0 → github2gerrit-1.4.2}/tests/test_ssh_common.py +0 -0
- {github2gerrit-1.4.0 → github2gerrit-1.4.2}/tests/test_ssh_discovery.py +0 -0
- {github2gerrit-1.4.0 → github2gerrit-1.4.2}/tests/test_ssh_discovery_dry_run.py +0 -0
- {github2gerrit-1.4.0 → github2gerrit-1.4.2}/tests/test_trailers_additional.py +0 -0
- {github2gerrit-1.4.0 → github2gerrit-1.4.2}/tests/test_url_parser.py +0 -0
- {github2gerrit-1.4.0 → github2gerrit-1.4.2}/tests/test_utils.py +0 -0
- {github2gerrit-1.4.0 → github2gerrit-1.4.2}/tests/unit/test_config_integration.py +0 -0
- {github2gerrit-1.4.0 → github2gerrit-1.4.2}/tests/unit/test_ssh_config_parser.py +0 -0
|
@@ -59,7 +59,7 @@ repos:
|
|
|
59
59
|
types: [yaml]
|
|
60
60
|
|
|
61
61
|
- repo: https://github.com/astral-sh/ruff-pre-commit
|
|
62
|
-
rev:
|
|
62
|
+
rev: 01a675ea018f2fb714478a5ffb83fcea8374bb06 # frozen: v0.15.21
|
|
63
63
|
hooks:
|
|
64
64
|
- id: ruff
|
|
65
65
|
files: ^(src|scripts|tests)/.+\.py$
|
|
@@ -68,7 +68,7 @@ repos:
|
|
|
68
68
|
files: ^(src|scripts|tests)/.+\.py$
|
|
69
69
|
|
|
70
70
|
- repo: https://github.com/pre-commit/mirrors-mypy
|
|
71
|
-
rev:
|
|
71
|
+
rev: 41e691678310dfd3833f7ab4e180ddb014310356 # frozen: v2.3.0
|
|
72
72
|
hooks:
|
|
73
73
|
- id: mypy
|
|
74
74
|
files: ^src/.+\.py$
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: github2gerrit
|
|
3
|
-
Version: 1.4.
|
|
3
|
+
Version: 1.4.2
|
|
4
4
|
Summary: Submit a GitHub pull request to a Gerrit repository.
|
|
5
5
|
Project-URL: Homepage, https://github.com/lfreleng-actions/github2gerrit-action
|
|
6
6
|
Project-URL: Repository, https://github.com/lfreleng-actions/github2gerrit-action
|
|
@@ -353,9 +353,11 @@ dispatches the caller workflow to report a merged or abandoned
|
|
|
353
353
|
change, forward these dispatch inputs and the tool closes the source
|
|
354
354
|
GitHub PR instead of processing pull requests.
|
|
355
355
|
|
|
356
|
-
|
|
357
|
-
skip Gerrit interaction
|
|
358
|
-
`
|
|
356
|
+
Repository variables provide operational kill switches: set
|
|
357
|
+
`G2G_NO_GERRIT` to `true` to skip Gerrit interaction, or
|
|
358
|
+
`G2G_DISABLED` to `true` to exit immediately without processing.
|
|
359
|
+
Test-only settings (`CI_TESTING`, `USE_LOCAL_ACTION`) remain
|
|
360
|
+
composite-action-only by design.
|
|
359
361
|
|
|
360
362
|
## Documentation
|
|
361
363
|
|
|
@@ -307,9 +307,11 @@ dispatches the caller workflow to report a merged or abandoned
|
|
|
307
307
|
change, forward these dispatch inputs and the tool closes the source
|
|
308
308
|
GitHub PR instead of processing pull requests.
|
|
309
309
|
|
|
310
|
-
|
|
311
|
-
skip Gerrit interaction
|
|
312
|
-
`
|
|
310
|
+
Repository variables provide operational kill switches: set
|
|
311
|
+
`G2G_NO_GERRIT` to `true` to skip Gerrit interaction, or
|
|
312
|
+
`G2G_DISABLED` to `true` to exit immediately without processing.
|
|
313
|
+
Test-only settings (`CI_TESTING`, `USE_LOCAL_ACTION`) remain
|
|
314
|
+
composite-action-only by design.
|
|
313
315
|
|
|
314
316
|
## Documentation
|
|
315
317
|
|
|
@@ -22,6 +22,15 @@ inputs:
|
|
|
22
22
|
description: "Fetch depth for checkout"
|
|
23
23
|
required: false
|
|
24
24
|
default: "10"
|
|
25
|
+
SKIP_CHECKOUT:
|
|
26
|
+
description: >-
|
|
27
|
+
Skip the internal repository checkout. Set when the caller has
|
|
28
|
+
already checked out the target repository at the desired ref
|
|
29
|
+
(e.g. the bundled reusable workflow, which also checks out this
|
|
30
|
+
action into the workspace and must not have it deleted by a
|
|
31
|
+
nested checkout)
|
|
32
|
+
required: false
|
|
33
|
+
default: "false"
|
|
25
34
|
PR_NUMBER:
|
|
26
35
|
description: "Pull request number to process, use 0 to process all open"
|
|
27
36
|
required: false
|
|
@@ -108,7 +117,7 @@ inputs:
|
|
|
108
117
|
required: false
|
|
109
118
|
default: ""
|
|
110
119
|
GERRIT_SERVER_PORT:
|
|
111
|
-
description: "Gerrit
|
|
120
|
+
description: "Gerrit server SSH TCP port"
|
|
112
121
|
required: false
|
|
113
122
|
default: "29418"
|
|
114
123
|
GERRIT_PROJECT:
|
|
@@ -205,7 +214,8 @@ runs:
|
|
|
205
214
|
fi
|
|
206
215
|
|
|
207
216
|
- name: "Checkout repository"
|
|
208
|
-
|
|
217
|
+
# yamllint disable-line rule:line-length
|
|
218
|
+
if: steps.disabled-check.outputs.disabled != 'true' && inputs.SKIP_CHECKOUT != 'true'
|
|
209
219
|
# yamllint disable-line rule:line-length
|
|
210
220
|
uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0
|
|
211
221
|
with:
|
|
@@ -227,7 +237,7 @@ runs:
|
|
|
227
237
|
- name: "Setup uv"
|
|
228
238
|
if: steps.disabled-check.outputs.disabled != 'true'
|
|
229
239
|
# yamllint disable-line rule:line-length
|
|
230
|
-
uses: astral-sh/setup-uv@
|
|
240
|
+
uses: astral-sh/setup-uv@11f9893b081a58869d3b5fccaea48c9e9e46f990 # v8.3.2
|
|
231
241
|
with:
|
|
232
242
|
enable-cache: false
|
|
233
243
|
|
|
@@ -159,26 +159,33 @@ Some settings have no CLI flag and use environment variables:
|
|
|
159
159
|
|
|
160
160
|
<!-- markdownlint-disable MD013 -->
|
|
161
161
|
|
|
162
|
-
| Variable
|
|
163
|
-
|
|
|
164
|
-
| `G2G_CONFIG_PATH`
|
|
165
|
-
| `G2G_LOG_LEVEL`
|
|
166
|
-
| `G2G_TOPIC_PREFIX`
|
|
167
|
-
| `G2G_SKIP_GERRIT_COMMENTS`
|
|
168
|
-
| `G2G_ENABLE_DERIVATION`
|
|
169
|
-
| `G2G_AUTO_SAVE_CONFIG`
|
|
170
|
-
| `G2G_RESPECT_USER_SSH`
|
|
171
|
-
| `G2G_USE_SSH_AGENT`
|
|
172
|
-
| `G2G_NO_GERRIT`
|
|
173
|
-
| `G2G_DISABLED`
|
|
174
|
-
| `CLEANUP_ABANDONED`
|
|
175
|
-
| `CLEANUP_GERRIT`
|
|
176
|
-
| `PR_NUMBER`
|
|
177
|
-
| `SYNC_ALL_OPEN_PRS`
|
|
178
|
-
| `GERRIT_HTTP_USER`
|
|
179
|
-
| `GERRIT_HTTP_PASSWORD`
|
|
180
|
-
| `GERRIT_HTTP_BASE_PATH`
|
|
181
|
-
| `GITHUB_TOKEN`
|
|
162
|
+
| Variable | Default | Description |
|
|
163
|
+
| ----------------------------- | ------------------------------------------- | -------------------------------------------------------------------------------- |
|
|
164
|
+
| `G2G_CONFIG_PATH` | `~/.config/github2gerrit/configuration.txt` | Path to the per-organization configuration file |
|
|
165
|
+
| `G2G_LOG_LEVEL` | `WARNING` | Logging level; set `DEBUG` for verbose output |
|
|
166
|
+
| `G2G_TOPIC_PREFIX` | `GH` | Prefix used when generating Gerrit topics |
|
|
167
|
+
| `G2G_SKIP_GERRIT_COMMENTS` | `false` | Skip posting back-reference comments on Gerrit changes |
|
|
168
|
+
| `G2G_ENABLE_DERIVATION` | `true` | Enable automatic derivation of Gerrit parameters from organization defaults |
|
|
169
|
+
| `G2G_AUTO_SAVE_CONFIG` | context-dependent | Save derived parameters back to the configuration file |
|
|
170
|
+
| `G2G_RESPECT_USER_SSH` | `false` (`true` in direct URL mode) | Use the local user's SSH configuration and keys instead of provided key material |
|
|
171
|
+
| `G2G_USE_SSH_AGENT` | `true` | Use SSH agent authentication; set `false` to force file-based SSH keys |
|
|
172
|
+
| `G2G_NO_GERRIT` | `false` | Run the full pipeline without contacting Gerrit (forces dry-run behavior) |
|
|
173
|
+
| `G2G_DISABLED` | `false` | Exit immediately with success without processing anything |
|
|
174
|
+
| `CLEANUP_ABANDONED` | `true` | Close GitHub PRs whose Gerrit changes have status abandoned |
|
|
175
|
+
| `CLEANUP_GERRIT` | `true` | Abandon Gerrit changes for closed GitHub PRs |
|
|
176
|
+
| `PR_NUMBER` | unset | Pull request number to process in CI/CD mode (`0` means bulk mode) |
|
|
177
|
+
| `SYNC_ALL_OPEN_PRS` | `false` | Process all open PRs in the repository (bulk mode) |
|
|
178
|
+
| `GERRIT_HTTP_USER` | unset | Username for the Gerrit REST API (when required) |
|
|
179
|
+
| `GERRIT_HTTP_PASSWORD` | unset | HTTP password/token for the Gerrit REST API |
|
|
180
|
+
| `GERRIT_HTTP_BASE_PATH` | unset | Gerrit REST base path for non-standard deployments (e.g., `/r`) |
|
|
181
|
+
| `GITHUB_TOKEN` | unset | GitHub API token; required for PR queries, comments, and closing PRs |
|
|
182
|
+
| `GH_TOKEN` | unset | Fallback source for `GITHUB_TOKEN` when the latter is unset |
|
|
183
|
+
| `GERRIT_CHANGE_URL` | unset | Gerrit change URL for Gerrit-event dispatch mode (close the source PR) |
|
|
184
|
+
| `GERRIT_EVENT_TYPE` | unset | Gerrit event type for dispatch mode (`change-merged` or `change-abandoned`) |
|
|
185
|
+
| `GERRIT_BRANCH` | unset | Gerrit branch for dispatch mode change queries |
|
|
186
|
+
| `G2G_DRYRUN_DISABLE_NETWORK` | `false` | Skip DNS/network checks in dry-run; set automatically by `G2G_NO_GERRIT` |
|
|
187
|
+
| `G2G_ANON_SUPERSEDE_FALLBACK` | `true` | Allow anonymous supersession queries when Gerrit credentials are unavailable |
|
|
188
|
+
| `VERIFY_DIGEST_STRICT` | `true` | Fail (rather than warn) on reconciliation digest mismatch after push |
|
|
182
189
|
|
|
183
190
|
<!-- markdownlint-enable MD013 -->
|
|
184
191
|
|
|
@@ -44,8 +44,8 @@ When a PR updates (for example, Dependabot rebases or updates dependencies):
|
|
|
44
44
|
1. The `synchronize` event triggers UPDATE mode.
|
|
45
45
|
2. The tool recovers the existing Gerrit change using five strategies,
|
|
46
46
|
in order:
|
|
47
|
-
- Topic-based query (
|
|
48
|
-
the
|
|
47
|
+
- Topic-based query (`<prefix>-<project>-<pr-number>`, matching the
|
|
48
|
+
topic the tool pushed; see "Topic naming" under Behavior Details)
|
|
49
49
|
- `GitHub-Hash` trailer matching
|
|
50
50
|
- `GitHub-PR` trailer URL matching
|
|
51
51
|
- Mapping comment parsing from PR comments
|
|
@@ -702,12 +702,11 @@ Lookup logic:
|
|
|
702
702
|
|
|
703
703
|
- Branch resolution: uses `GITHUB_BASE_REF` as the target branch for Gerrit,
|
|
704
704
|
defaulting to `master` when unset.
|
|
705
|
-
- Topic naming: pushes
|
|
706
|
-
`<prefix>` comes from
|
|
707
|
-
|
|
708
|
-
|
|
709
|
-
|
|
710
|
-
repository name.
|
|
705
|
+
- Topic naming: pushes and change recovery queries use
|
|
706
|
+
`<prefix>-<project>-<pr-number>`, where `<prefix>` comes from
|
|
707
|
+
`G2G_TOPIC_PREFIX` (default `GH`) and `<project>` is the Gerrit
|
|
708
|
+
project path with `/` replaced by `-` (or the GitHub repository name
|
|
709
|
+
when `.gitreview` is unavailable).
|
|
711
710
|
- GitHub Enterprise support: direct URL mode accepts enterprise GitHub hosts
|
|
712
711
|
when explicitly enabled via `--allow-ghe-urls` or `ALLOW_GHE_URLS="true"`
|
|
713
712
|
(default: off). The tool determines the GitHub API base URL from
|
|
@@ -199,10 +199,6 @@ ignore_missing_imports = true
|
|
|
199
199
|
module = ["typer", "typer.*"]
|
|
200
200
|
ignore_missing_imports = true
|
|
201
201
|
|
|
202
|
-
[[tool.mypy.overrides]]
|
|
203
|
-
module = ["importlib_metadata"]
|
|
204
|
-
ignore_missing_imports = true
|
|
205
|
-
|
|
206
202
|
[[tool.mypy.overrides]]
|
|
207
203
|
module = ["pytest", "pytest.*"]
|
|
208
204
|
ignore_missing_imports = true
|
|
@@ -220,6 +216,12 @@ disallow_untyped_calls = false
|
|
|
220
216
|
|
|
221
217
|
[tool.coverage.run]
|
|
222
218
|
branch = true
|
|
219
|
+
# Keep transient coverage data out of the working tree so tests that
|
|
220
|
+
# inspect on-disk repository content never see .coverage* files.
|
|
221
|
+
# During pytest runs tests/conftest.py sets COVERAGE_FILE (env), which
|
|
222
|
+
# takes precedence; this value covers direct coverage invocations and
|
|
223
|
+
# satisfies python-test-action's data_file configuration check.
|
|
224
|
+
data_file = "${TMPDIR-/tmp}/.coverage.github2gerrit"
|
|
223
225
|
source = ["github2gerrit"]
|
|
224
226
|
omit = [
|
|
225
227
|
"tests/*",
|
|
@@ -88,15 +88,10 @@ from .utils import parse_bool_env
|
|
|
88
88
|
|
|
89
89
|
|
|
90
90
|
def get_version(package: str) -> str:
|
|
91
|
-
"""Get package version
|
|
92
|
-
|
|
93
|
-
from importlib.metadata import version as stdlib_version
|
|
94
|
-
|
|
95
|
-
return str(stdlib_version(package))
|
|
96
|
-
except ImportError:
|
|
97
|
-
from importlib_metadata import version as backport_version
|
|
91
|
+
"""Get the installed package version via importlib.metadata."""
|
|
92
|
+
from importlib.metadata import version
|
|
98
93
|
|
|
99
|
-
|
|
94
|
+
return str(version(package))
|
|
100
95
|
|
|
101
96
|
|
|
102
97
|
# Legacy error handling functions - now use centralized error_codes module
|
|
@@ -184,7 +179,6 @@ def _check_automation_only(
|
|
|
184
179
|
"pre-commit-ci",
|
|
185
180
|
]
|
|
186
181
|
|
|
187
|
-
# Get PR author
|
|
188
182
|
pr_author = getattr(getattr(pr_obj, "user", None), "login", "")
|
|
189
183
|
if not pr_author:
|
|
190
184
|
log.warning("Unable to determine PR author, allowing PR to proceed")
|
|
@@ -262,10 +256,8 @@ def _extract_and_display_pr_info(
|
|
|
262
256
|
# Check if automation_only is enabled and reject non-automation PRs
|
|
263
257
|
_check_automation_only(pr_obj, gh, progress_tracker)
|
|
264
258
|
|
|
265
|
-
# Extract PR information
|
|
266
259
|
title, _body = get_pr_title_body(pr_obj)
|
|
267
260
|
|
|
268
|
-
# Get additional PR details
|
|
269
261
|
pr_info = {
|
|
270
262
|
"Repository": gh.repository,
|
|
271
263
|
"PR Number": gh.pr_number,
|
|
@@ -364,7 +356,6 @@ def _parse_github_target(url: str) -> GitHubPRTarget | GitHubRepoTarget:
|
|
|
364
356
|
|
|
365
357
|
owner, repo = parts[0], parts[1]
|
|
366
358
|
|
|
367
|
-
# Check for PR URL
|
|
368
359
|
if len(parts) >= 4 and parts[2] in ("pull", "pulls"):
|
|
369
360
|
try:
|
|
370
361
|
pr_number = int(parts[3])
|
|
@@ -378,7 +369,6 @@ def _parse_github_target(url: str) -> GitHubPRTarget | GitHubRepoTarget:
|
|
|
378
369
|
|
|
379
370
|
APP_NAME = "github2gerrit"
|
|
380
371
|
|
|
381
|
-
|
|
382
372
|
if TYPE_CHECKING:
|
|
383
373
|
BaseGroup = object
|
|
384
374
|
else:
|
|
@@ -429,10 +419,8 @@ def _resolve_issue_id_from_json(json_str: str, github_actor: str) -> str:
|
|
|
429
419
|
return ""
|
|
430
420
|
|
|
431
421
|
try:
|
|
432
|
-
# Parse JSON
|
|
433
422
|
lookup_data = json.loads(json_str)
|
|
434
423
|
|
|
435
|
-
# Validate it's an array
|
|
436
424
|
if not isinstance(lookup_data, list):
|
|
437
425
|
log.warning(
|
|
438
426
|
"⚠️ Warning: Issue-ID JSON was not valid (expected array)"
|
|
@@ -484,8 +472,11 @@ def _print_version_banner() -> None:
|
|
|
484
472
|
try:
|
|
485
473
|
app_version = get_version("github2gerrit")
|
|
486
474
|
print(f"🏷️ github2gerrit version {app_version}")
|
|
487
|
-
|
|
488
|
-
|
|
475
|
+
# The banner is cosmetic: a missing or unreadable package version
|
|
476
|
+
# must never block CLI startup.
|
|
477
|
+
# aislop-ignore-next-line swallowed-exception
|
|
478
|
+
except Exception as exc:
|
|
479
|
+
print(f"⚠️ github2gerrit version information not available: {exc}")
|
|
489
480
|
|
|
490
481
|
|
|
491
482
|
# Show version information when --help is used or in GitHub Actions mode
|
|
@@ -531,7 +522,6 @@ def _save_derived_parameters_after_success(data: Inputs) -> None:
|
|
|
531
522
|
"""Save derived parameters to config file after successful Gerrit
|
|
532
523
|
submission."""
|
|
533
524
|
try:
|
|
534
|
-
# Get the organization used for derivation
|
|
535
525
|
org_for_cfg = (
|
|
536
526
|
data.organization
|
|
537
527
|
or os.getenv("ORGANIZATION")
|
|
@@ -756,8 +746,6 @@ def main(
|
|
|
756
746
|
envvar="G2G_SHOW_PROGRESS",
|
|
757
747
|
help="Show real-time progress updates with Rich formatting.",
|
|
758
748
|
),
|
|
759
|
-
# BREAKING CHANGE v0.2.0: Default changed from True to False
|
|
760
|
-
# for more flexible commit reconciliation
|
|
761
749
|
similarity_files: bool = typer.Option(
|
|
762
750
|
False,
|
|
763
751
|
"--similarity-files/--no-similarity-files",
|
|
@@ -852,7 +840,6 @@ def main(
|
|
|
852
840
|
- No arguments: environment variables determine behaviour (CI/CD mode)
|
|
853
841
|
"""
|
|
854
842
|
|
|
855
|
-
# Handle version flag first
|
|
856
843
|
if version_flag:
|
|
857
844
|
try:
|
|
858
845
|
app_version = get_version("github2gerrit")
|
|
@@ -931,7 +918,6 @@ def main(
|
|
|
931
918
|
|
|
932
919
|
# Handle netrc credential loading if enabled
|
|
933
920
|
if not no_netrc:
|
|
934
|
-
# Get the Gerrit server from environment or CLI
|
|
935
921
|
gerrit_host = gerrit_server or os.getenv("GERRIT_SERVER", "")
|
|
936
922
|
if gerrit_host:
|
|
937
923
|
try:
|
|
@@ -963,21 +949,18 @@ def main(
|
|
|
963
949
|
safe_typer_echo(f"❌ Failed to parse .netrc file: {e}")
|
|
964
950
|
sys.exit(int(ExitCode.CONFIGURATION_ERROR))
|
|
965
951
|
|
|
966
|
-
# Set up logging level based on verbose flag
|
|
967
952
|
if verbose:
|
|
968
953
|
os.environ["G2G_LOG_LEVEL"] = "DEBUG"
|
|
969
954
|
_reconfigure_logging()
|
|
970
955
|
|
|
971
|
-
# Initialize Rich-aware logging system
|
|
972
956
|
setup_rich_aware_logging()
|
|
973
957
|
|
|
974
|
-
# Log version to logs in GitHub Actions environment
|
|
975
958
|
if _is_github_actions_context():
|
|
976
959
|
try:
|
|
977
960
|
app_version = get_version("github2gerrit")
|
|
978
961
|
log.debug("github2gerrit version %s", app_version)
|
|
979
|
-
except Exception:
|
|
980
|
-
log.warning("Version information not available")
|
|
962
|
+
except Exception as exc:
|
|
963
|
+
log.warning("Version information not available: %s", exc)
|
|
981
964
|
|
|
982
965
|
# Show initial progress if Rich is available and progress is enabled
|
|
983
966
|
if show_progress and not RICH_AVAILABLE:
|
|
@@ -1041,7 +1024,6 @@ def main(
|
|
|
1041
1024
|
if reuse_strategy:
|
|
1042
1025
|
os.environ["REUSE_STRATEGY"] = reuse_strategy
|
|
1043
1026
|
|
|
1044
|
-
# Validate similarity parameters
|
|
1045
1027
|
if not (0.0 <= similarity_subject <= 1.0):
|
|
1046
1028
|
msg = (
|
|
1047
1029
|
f"similarity_subject must be between 0.0 and 1.0, "
|
|
@@ -1231,7 +1213,6 @@ def _build_inputs_from_env() -> Inputs:
|
|
|
1231
1213
|
|
|
1232
1214
|
|
|
1233
1215
|
def _process_bulk(data: Inputs, gh: GitHubContext) -> bool:
|
|
1234
|
-
# Initialize progress tracker for processing
|
|
1235
1216
|
show_progress = env_bool("G2G_SHOW_PROGRESS", True)
|
|
1236
1217
|
target = gh.repository
|
|
1237
1218
|
|
|
@@ -1303,7 +1284,6 @@ def _process_bulk(data: Inputs, gh: GitHubContext) -> bool:
|
|
|
1303
1284
|
gh.event_action,
|
|
1304
1285
|
)
|
|
1305
1286
|
|
|
1306
|
-
# Update progress tracker for this PR
|
|
1307
1287
|
progress_tracker.update_operation(f"Processing PR #{pr_number}...")
|
|
1308
1288
|
progress_tracker.pr_processed()
|
|
1309
1289
|
|
|
@@ -1391,7 +1371,6 @@ def _process_bulk(data: Inputs, gh: GitHubContext) -> bool:
|
|
|
1391
1371
|
)
|
|
1392
1372
|
pr_tasks.append((pr, per_ctx))
|
|
1393
1373
|
|
|
1394
|
-
# Process PRs in parallel
|
|
1395
1374
|
with ThreadPoolExecutor(max_workers=max_workers) as executor:
|
|
1396
1375
|
log.debug(
|
|
1397
1376
|
"Processing %d PRs with %d parallel workers",
|
|
@@ -1495,7 +1474,6 @@ def _process_bulk(data: Inputs, gh: GitHubContext) -> bool:
|
|
|
1495
1474
|
}
|
|
1496
1475
|
)
|
|
1497
1476
|
|
|
1498
|
-
# Stop progress tracker and show final results
|
|
1499
1477
|
if failed_count == 0:
|
|
1500
1478
|
progress_tracker.update_operation("Processing completed ✅")
|
|
1501
1479
|
else:
|
|
@@ -1544,7 +1522,6 @@ def _process_single(
|
|
|
1544
1522
|
gh: GitHubContext,
|
|
1545
1523
|
progress_tracker: G2GProgressTracker | DummyProgressTracker | None = None,
|
|
1546
1524
|
) -> tuple[bool, SubmissionResult]:
|
|
1547
|
-
# Create temporary directory for all git operations
|
|
1548
1525
|
with tempfile.TemporaryDirectory() as temp_dir:
|
|
1549
1526
|
workspace = Path(temp_dir)
|
|
1550
1527
|
|
|
@@ -1770,7 +1747,6 @@ def _process_single(
|
|
|
1770
1747
|
|
|
1771
1748
|
|
|
1772
1749
|
def _load_effective_inputs() -> Inputs:
|
|
1773
|
-
# Build inputs from environment (used by URL callback path)
|
|
1774
1750
|
data = _build_inputs_from_env()
|
|
1775
1751
|
|
|
1776
1752
|
# Detect GitHub CI mode and configure accordingly
|
|
@@ -1789,7 +1765,6 @@ def _load_effective_inputs() -> Inputs:
|
|
|
1789
1765
|
)
|
|
1790
1766
|
cfg = load_org_config(org_for_cfg)
|
|
1791
1767
|
|
|
1792
|
-
# Get repository for GERRIT_PROJECT derivation
|
|
1793
1768
|
repository = os.getenv("GITHUB_REPOSITORY", "")
|
|
1794
1769
|
|
|
1795
1770
|
# Apply dynamic parameter derivation for missing Gerrit parameters
|
|
@@ -1939,7 +1914,6 @@ def _process_close_gerrit_change(
|
|
|
1939
1914
|
# Check if close_merged_prs is enabled
|
|
1940
1915
|
close_merged_prs = env_bool("CLOSE_MERGED_PRS", True)
|
|
1941
1916
|
|
|
1942
|
-
# Check Gerrit change status
|
|
1943
1917
|
status = check_gerrit_change_status(gerrit_change_url)
|
|
1944
1918
|
|
|
1945
1919
|
# Validate status: without --force, reject MERGED/ABANDONED changes
|
|
@@ -1956,7 +1930,9 @@ def _process_close_gerrit_change(
|
|
|
1956
1930
|
error_msg,
|
|
1957
1931
|
)
|
|
1958
1932
|
|
|
1959
|
-
#
|
|
1933
|
+
# Branches vary in log level and nested close_merged_prs handling,
|
|
1934
|
+
# so a dispatch table would obscure this status logging.
|
|
1935
|
+
# aislop-ignore-next-line python-repetitive-dispatch
|
|
1960
1936
|
if status == "ABANDONED":
|
|
1961
1937
|
if close_merged_prs:
|
|
1962
1938
|
log.debug(
|
|
@@ -1983,7 +1959,6 @@ def _process_close_gerrit_change(
|
|
|
1983
1959
|
|
|
1984
1960
|
log.debug("Found GitHub PR URL: %s", pr_url)
|
|
1985
1961
|
|
|
1986
|
-
# Parse PR URL to get owner info for auto-discovery
|
|
1987
1962
|
parsed = parse_pr_url(pr_url)
|
|
1988
1963
|
if not parsed:
|
|
1989
1964
|
log.error("Failed to parse PR URL: %s", pr_url)
|
|
@@ -2007,6 +1982,9 @@ def _process_close_gerrit_change(
|
|
|
2007
1982
|
progress_tracker=None,
|
|
2008
1983
|
close_merged_prs=close_merged_prs,
|
|
2009
1984
|
)
|
|
1985
|
+
# log.exception records the caught error and traceback; keep
|
|
1986
|
+
# processing so one PR failure cannot abort the remaining closures.
|
|
1987
|
+
# aislop-ignore-next-line silent-recovery
|
|
2010
1988
|
except Exception:
|
|
2011
1989
|
log.exception("Failed to close GitHub PR #%d", pr_number)
|
|
2012
1990
|
|
|
@@ -2028,7 +2006,6 @@ def _process_close_merged_prs(data: Inputs, gh: GitHubContext) -> None:
|
|
|
2028
2006
|
"""
|
|
2029
2007
|
log.info("🔄 Processing merged Gerrit changes to close GitHub PRs")
|
|
2030
2008
|
|
|
2031
|
-
# Initialize progress tracker
|
|
2032
2009
|
show_progress = env_bool("G2G_SHOW_PROGRESS", True)
|
|
2033
2010
|
target = gh.repository
|
|
2034
2011
|
|
|
@@ -2054,7 +2031,6 @@ def _process_close_merged_prs(data: Inputs, gh: GitHubContext) -> None:
|
|
|
2054
2031
|
with gh.event_path.open() as f:
|
|
2055
2032
|
event_payload = json.load(f)
|
|
2056
2033
|
|
|
2057
|
-
# Extract commit SHAs from the push event
|
|
2058
2034
|
if "commits" in event_payload:
|
|
2059
2035
|
commit_shas = [
|
|
2060
2036
|
commit["id"]
|
|
@@ -2141,7 +2117,6 @@ def _process_close_merged_prs(data: Inputs, gh: GitHubContext) -> None:
|
|
|
2141
2117
|
def _process() -> None:
|
|
2142
2118
|
data = _load_effective_inputs()
|
|
2143
2119
|
|
|
2144
|
-
# Validate inputs
|
|
2145
2120
|
try:
|
|
2146
2121
|
_validate_inputs(data)
|
|
2147
2122
|
except ConfigurationError as exc:
|
|
@@ -2151,11 +2126,11 @@ def _process() -> None:
|
|
|
2151
2126
|
|
|
2152
2127
|
gh = _read_github_context()
|
|
2153
2128
|
|
|
2154
|
-
#
|
|
2155
|
-
#
|
|
2156
|
-
#
|
|
2157
|
-
#
|
|
2158
|
-
#
|
|
2129
|
+
# G2G_NO_GERRIT reuses the existing DRY_RUN +
|
|
2130
|
+
# G2G_DRYRUN_DISABLE_NETWORK code paths so that all tool logic runs
|
|
2131
|
+
# but Gerrit network operations are no-ops. Cleanup tasks
|
|
2132
|
+
# (abandoned-PR / Gerrit-change sweeps) are also suppressed because
|
|
2133
|
+
# they would hit a non-existent server.
|
|
2159
2134
|
no_gerrit = env_bool("G2G_NO_GERRIT", False)
|
|
2160
2135
|
|
|
2161
2136
|
if no_gerrit:
|
|
@@ -2336,7 +2311,6 @@ def _process() -> None:
|
|
|
2336
2311
|
# 2. Direct Gerrit change URL provided in CLI
|
|
2337
2312
|
# 3. Gerrit event dispatched via workflow_dispatch (GERRIT_CHANGE_URL set)
|
|
2338
2313
|
|
|
2339
|
-
# Check for Gerrit event inputs from workflow_dispatch
|
|
2340
2314
|
gerrit_event_change_url = os.getenv("GERRIT_CHANGE_URL")
|
|
2341
2315
|
gerrit_event_type = os.getenv("GERRIT_EVENT_TYPE")
|
|
2342
2316
|
|
|
@@ -2469,7 +2443,6 @@ def _process() -> None:
|
|
|
2469
2443
|
):
|
|
2470
2444
|
bulk_success = _process_bulk(data, gh)
|
|
2471
2445
|
|
|
2472
|
-
# Log external API metrics summary
|
|
2473
2446
|
try:
|
|
2474
2447
|
log_api_metrics_summary()
|
|
2475
2448
|
except Exception as exc:
|
|
@@ -2702,7 +2675,6 @@ def _process() -> None:
|
|
|
2702
2675
|
# Don't fail the whole pipeline if cleanup fails
|
|
2703
2676
|
log.warning("Gerrit cleanup failed: %s", exc)
|
|
2704
2677
|
|
|
2705
|
-
# Log external API metrics summary
|
|
2706
2678
|
try:
|
|
2707
2679
|
log_api_metrics_summary()
|
|
2708
2680
|
except Exception as exc:
|
|
@@ -2911,7 +2883,6 @@ def _validate_inputs(data: Inputs) -> None:
|
|
|
2911
2883
|
_MSG_MISSING_REQUIRED_INPUT.format(field_name=field_name)
|
|
2912
2884
|
)
|
|
2913
2885
|
|
|
2914
|
-
# Validate fetch depth is a positive integer
|
|
2915
2886
|
if data.fetch_depth <= 0:
|
|
2916
2887
|
log.error("Invalid FETCH_DEPTH: %s", data.fetch_depth)
|
|
2917
2888
|
raise ConfigurationError(_MSG_INVALID_FETCH_DEPTH)
|
|
@@ -149,7 +149,6 @@ class CommitNormalizer:
|
|
|
149
149
|
if self._is_conventional_commit(title):
|
|
150
150
|
return False
|
|
151
151
|
|
|
152
|
-
# Check for automation patterns
|
|
153
152
|
return self._is_automation_pr(title, author)
|
|
154
153
|
|
|
155
154
|
def normalize_commit_title(self, title: str, author: str) -> str:
|
|
@@ -165,7 +164,6 @@ class CommitNormalizer:
|
|
|
165
164
|
# Determine the appropriate conventional commit type
|
|
166
165
|
commit_type = self._determine_commit_type(title, author)
|
|
167
166
|
|
|
168
|
-
# Clean and normalize the title
|
|
169
167
|
normalized_title = self._clean_title(title)
|
|
170
168
|
|
|
171
169
|
# Apply conventional commit format
|
|
@@ -181,7 +179,6 @@ class CommitNormalizer:
|
|
|
181
179
|
|
|
182
180
|
def _is_automation_pr(self, title: str, author: str) -> bool:
|
|
183
181
|
"""Check if this is an automation PR that should be normalized."""
|
|
184
|
-
# Check for known automation authors
|
|
185
182
|
automation_authors = [
|
|
186
183
|
"dependabot[bot]",
|
|
187
184
|
"dependabot-preview[bot]",
|
|
@@ -195,7 +192,6 @@ class CommitNormalizer:
|
|
|
195
192
|
):
|
|
196
193
|
return True
|
|
197
194
|
|
|
198
|
-
# Check for automation patterns in title
|
|
199
195
|
automation_patterns = [
|
|
200
196
|
r"^bump\s+",
|
|
201
197
|
r"^update\s+.*\s+from\s+.*\s+to\s+",
|
|
@@ -216,10 +212,8 @@ class CommitNormalizer:
|
|
|
216
212
|
self.workspace,
|
|
217
213
|
)
|
|
218
214
|
|
|
219
|
-
# Check .pre-commit-config.yaml
|
|
220
215
|
self._check_precommit_config()
|
|
221
216
|
|
|
222
|
-
# Check .github/release-drafter.yml
|
|
223
217
|
self._check_release_drafter_config()
|
|
224
218
|
|
|
225
219
|
# Analyze git history
|
|
@@ -239,12 +233,10 @@ class CommitNormalizer:
|
|
|
239
233
|
|
|
240
234
|
ci_config = config.get("ci", {})
|
|
241
235
|
|
|
242
|
-
# Check autofix commit message
|
|
243
236
|
autofix_msg = ci_config.get("autofix_commit_msg", "")
|
|
244
237
|
if autofix_msg:
|
|
245
238
|
self._extract_preferences_from_message(autofix_msg)
|
|
246
239
|
|
|
247
|
-
# Check autoupdate commit message
|
|
248
240
|
autoupdate_msg = ci_config.get("autoupdate_commit_msg", "")
|
|
249
241
|
if autoupdate_msg:
|
|
250
242
|
self._extract_preferences_from_message(autoupdate_msg)
|
|
@@ -272,7 +264,6 @@ class CommitNormalizer:
|
|
|
272
264
|
titles = rule.get("title", [])
|
|
273
265
|
|
|
274
266
|
for title_pattern in titles:
|
|
275
|
-
# Extract conventional commit type from pattern
|
|
276
267
|
if title_pattern.startswith(
|
|
277
268
|
"/"
|
|
278
269
|
) and title_pattern.endswith("/i"):
|
|
@@ -292,7 +283,6 @@ class CommitNormalizer:
|
|
|
292
283
|
def _analyze_git_history(self) -> None:
|
|
293
284
|
"""Analyze recent git history for conventional commit patterns."""
|
|
294
285
|
try:
|
|
295
|
-
# Get recent commit messages
|
|
296
286
|
git_cmd = shutil.which("git")
|
|
297
287
|
if not git_cmd:
|
|
298
288
|
log.debug("git command not found in PATH")
|
|
@@ -332,7 +322,6 @@ class CommitNormalizer:
|
|
|
332
322
|
1
|
|
333
323
|
)
|
|
334
324
|
|
|
335
|
-
# Update preferences based on analysis
|
|
336
325
|
if type_counts:
|
|
337
326
|
# Determine most common capitalization
|
|
338
327
|
if capitalization_examples:
|
|
@@ -344,7 +333,6 @@ class CommitNormalizer:
|
|
|
344
333
|
else:
|
|
345
334
|
self.preferences.capitalization = "lower"
|
|
346
335
|
|
|
347
|
-
# Update preferred types
|
|
348
336
|
for commit_type in type_counts:
|
|
349
337
|
if commit_type in CONVENTIONAL_COMMIT_TYPES:
|
|
350
338
|
self.preferences.preferred_types[commit_type] = (
|
|
@@ -374,13 +362,11 @@ class CommitNormalizer:
|
|
|
374
362
|
"""Determine the appropriate conventional commit type."""
|
|
375
363
|
title_lower = title.lower()
|
|
376
364
|
|
|
377
|
-
# Check for dependabot patterns first
|
|
378
365
|
if "dependabot" in author.lower() or any(
|
|
379
366
|
re.search(pattern, title_lower) for pattern in DEPENDABOT_PATTERNS
|
|
380
367
|
):
|
|
381
368
|
return self.preferences.dependency_type
|
|
382
369
|
|
|
383
|
-
# Check for pre-commit.ci patterns
|
|
384
370
|
if "pre-commit" in author.lower() or "pre-commit" in title_lower:
|
|
385
371
|
return self.preferences.automation_type
|
|
386
372
|
|
|
@@ -395,10 +381,8 @@ class CommitNormalizer:
|
|
|
395
381
|
|
|
396
382
|
def _clean_title(self, title: str) -> str:
|
|
397
383
|
"""Clean and normalize the title text."""
|
|
398
|
-
# Remove markdown links
|
|
399
384
|
title = re.sub(r"\[([^\]]+)\]\([^)]+\)", r"\1", title)
|
|
400
385
|
|
|
401
|
-
# Remove trailing ellipsis
|
|
402
386
|
title = re.sub(r"\s*[.]{3,}.*$", "", title)
|
|
403
387
|
|
|
404
388
|
# Remove markdown bold/code formatting but preserve underscores
|