github2gerrit 1.0.7__tar.gz → 1.0.9__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.0.7 → github2gerrit-1.0.9}/.pre-commit-config.yaml +4 -4
- {github2gerrit-1.0.7 → github2gerrit-1.0.9}/PKG-INFO +119 -3
- {github2gerrit-1.0.7 → github2gerrit-1.0.9}/README.md +118 -1
- {github2gerrit-1.0.7 → github2gerrit-1.0.9}/action.yaml +15 -1
- github2gerrit-1.0.9/docs/COMMIT_RULES.md +255 -0
- {github2gerrit-1.0.7 → github2gerrit-1.0.9}/pyproject.toml +0 -2
- {github2gerrit-1.0.7 → github2gerrit-1.0.9}/src/github2gerrit/cli.py +99 -52
- github2gerrit-1.0.9/src/github2gerrit/commit_rules.py +518 -0
- {github2gerrit-1.0.7 → github2gerrit-1.0.9}/src/github2gerrit/config.py +44 -3
- {github2gerrit-1.0.7 → github2gerrit-1.0.9}/src/github2gerrit/core.py +368 -189
- {github2gerrit-1.0.7 → github2gerrit-1.0.9}/src/github2gerrit/duplicate_detection.py +26 -60
- {github2gerrit-1.0.7 → github2gerrit-1.0.9}/src/github2gerrit/error_codes.py +15 -11
- {github2gerrit-1.0.7 → github2gerrit-1.0.9}/src/github2gerrit/gerrit_pr_closer.py +13 -10
- github2gerrit-1.0.9/src/github2gerrit/gitreview.py +592 -0
- {github2gerrit-1.0.7 → github2gerrit-1.0.9}/src/github2gerrit/models.py +4 -0
- {github2gerrit-1.0.7 → github2gerrit-1.0.9}/src/github2gerrit/orchestrator/reconciliation.py +6 -12
- github2gerrit-1.0.9/src/github2gerrit/pr_commands.py +355 -0
- {github2gerrit-1.0.7 → github2gerrit-1.0.9}/src/github2gerrit/rich_display.py +12 -13
- {github2gerrit-1.0.7 → github2gerrit-1.0.9}/src/github2gerrit/rich_logging.py +2 -7
- {github2gerrit-1.0.7 → github2gerrit-1.0.9}/src/github2gerrit/ssh_discovery.py +12 -12
- {github2gerrit-1.0.7 → github2gerrit-1.0.9}/tests/conftest.py +4 -2
- {github2gerrit-1.0.7 → github2gerrit-1.0.9}/tests/test_change_id_deduplication.py +1 -0
- github2gerrit-1.0.9/tests/test_commit_rules.py +1029 -0
- {github2gerrit-1.0.7 → github2gerrit-1.0.9}/tests/test_core_config_and_errors.py +1 -0
- {github2gerrit-1.0.7 → github2gerrit-1.0.9}/tests/test_core_integration_fixture_repo.py +2 -0
- {github2gerrit-1.0.7 → github2gerrit-1.0.9}/tests/test_core_prepare_commits.py +1 -0
- {github2gerrit-1.0.7 → github2gerrit-1.0.9}/tests/test_core_ssh_setup.py +5 -0
- {github2gerrit-1.0.7 → github2gerrit-1.0.9}/tests/test_force_flag_cli.py +1 -0
- {github2gerrit-1.0.7 → github2gerrit-1.0.9}/tests/test_gerrit_change_id_footer.py +1 -0
- github2gerrit-1.0.9/tests/test_gitreview.py +1011 -0
- github2gerrit-1.0.9/tests/test_issue_157_regressions.py +512 -0
- {github2gerrit-1.0.7 → github2gerrit-1.0.9}/tests/test_metadata_trailer_separation_bug.py +1 -0
- github2gerrit-1.0.9/tests/test_pr_commands.py +959 -0
- {github2gerrit-1.0.7 → github2gerrit-1.0.9}/tests/test_pr_content_filter_integration.py +1 -0
- {github2gerrit-1.0.7 → github2gerrit-1.0.9}/tests/test_pr_update_detection.py +2 -0
- {github2gerrit-1.0.7 → github2gerrit-1.0.9}/uv.lock +24 -35
- {github2gerrit-1.0.7 → github2gerrit-1.0.9}/.editorconfig +0 -0
- {github2gerrit-1.0.7 → github2gerrit-1.0.9}/.gitignore +0 -0
- {github2gerrit-1.0.7 → github2gerrit-1.0.9}/.gitlint +0 -0
- {github2gerrit-1.0.7 → github2gerrit-1.0.9}/.markdownlint.yaml +0 -0
- {github2gerrit-1.0.7 → github2gerrit-1.0.9}/.readthedocs.yml +0 -0
- {github2gerrit-1.0.7 → github2gerrit-1.0.9}/.yamllint +0 -0
- {github2gerrit-1.0.7 → github2gerrit-1.0.9}/LICENSE +0 -0
- {github2gerrit-1.0.7 → github2gerrit-1.0.9}/LICENSES/Apache-2.0.txt +0 -0
- {github2gerrit-1.0.7 → github2gerrit-1.0.9}/REUSE.toml +0 -0
- {github2gerrit-1.0.7 → github2gerrit-1.0.9}/docs/COMPOSITE_ACTION_TESTING.md +0 -0
- {github2gerrit-1.0.7 → github2gerrit-1.0.9}/docs/PR_UPDATE_IMPLEMENTATION.md +0 -0
- {github2gerrit-1.0.7 → github2gerrit-1.0.9}/docs/RELEASE-v0.2.0.md +0 -0
- {github2gerrit-1.0.7 → github2gerrit-1.0.9}/docs/github2gerrit_token_permissions_classic.png +0 -0
- {github2gerrit-1.0.7 → github2gerrit-1.0.9}/sitecustomize.py +0 -0
- {github2gerrit-1.0.7 → github2gerrit-1.0.9}/src/github2gerrit/__init__.py +0 -0
- {github2gerrit-1.0.7 → github2gerrit-1.0.9}/src/github2gerrit/commit_normalization.py +0 -0
- {github2gerrit-1.0.7 → github2gerrit-1.0.9}/src/github2gerrit/constants.py +0 -0
- {github2gerrit-1.0.7 → github2gerrit-1.0.9}/src/github2gerrit/external_api.py +0 -0
- {github2gerrit-1.0.7 → github2gerrit-1.0.9}/src/github2gerrit/gerrit_query.py +0 -0
- {github2gerrit-1.0.7 → github2gerrit-1.0.9}/src/github2gerrit/gerrit_rest.py +0 -0
- {github2gerrit-1.0.7 → github2gerrit-1.0.9}/src/github2gerrit/gerrit_urls.py +0 -0
- {github2gerrit-1.0.7 → github2gerrit-1.0.9}/src/github2gerrit/github_api.py +0 -0
- {github2gerrit-1.0.7 → github2gerrit-1.0.9}/src/github2gerrit/gitutils.py +0 -0
- {github2gerrit-1.0.7 → github2gerrit-1.0.9}/src/github2gerrit/mapping_comment.py +0 -0
- {github2gerrit-1.0.7 → github2gerrit-1.0.9}/src/github2gerrit/netrc.py +0 -0
- {github2gerrit-1.0.7 → github2gerrit-1.0.9}/src/github2gerrit/orchestrator/__init__.py +0 -0
- {github2gerrit-1.0.7 → github2gerrit-1.0.9}/src/github2gerrit/pr_content_filter.py +0 -0
- {github2gerrit-1.0.7 → github2gerrit-1.0.9}/src/github2gerrit/reconcile_matcher.py +0 -0
- {github2gerrit-1.0.7 → github2gerrit-1.0.9}/src/github2gerrit/similarity.py +0 -0
- {github2gerrit-1.0.7 → github2gerrit-1.0.9}/src/github2gerrit/ssh_agent_setup.py +0 -0
- {github2gerrit-1.0.7 → github2gerrit-1.0.9}/src/github2gerrit/ssh_common.py +0 -0
- {github2gerrit-1.0.7 → github2gerrit-1.0.9}/src/github2gerrit/ssh_config_parser.py +0 -0
- {github2gerrit-1.0.7 → github2gerrit-1.0.9}/src/github2gerrit/trailers.py +0 -0
- {github2gerrit-1.0.7 → github2gerrit-1.0.9}/src/github2gerrit/utils.py +0 -0
- {github2gerrit-1.0.7 → github2gerrit-1.0.9}/tests/fixtures/__init__.py +0 -0
- {github2gerrit-1.0.7 → github2gerrit-1.0.9}/tests/fixtures/make_repo.py +0 -0
- {github2gerrit-1.0.7 → github2gerrit-1.0.9}/tests/fixtures/ssh_config_samples.py +0 -0
- {github2gerrit-1.0.7 → github2gerrit-1.0.9}/tests/test_action_environment_mapping.py +0 -0
- {github2gerrit-1.0.7 → github2gerrit-1.0.9}/tests/test_action_outputs.py +0 -0
- {github2gerrit-1.0.7 → github2gerrit-1.0.9}/tests/test_action_pr_number_handling.py +0 -0
- {github2gerrit-1.0.7 → github2gerrit-1.0.9}/tests/test_action_step_validation.py +0 -0
- {github2gerrit-1.0.7 → github2gerrit-1.0.9}/tests/test_automation_only.py +0 -0
- {github2gerrit-1.0.7 → github2gerrit-1.0.9}/tests/test_cli.py +0 -0
- {github2gerrit-1.0.7 → github2gerrit-1.0.9}/tests/test_cli_helpers.py +0 -0
- {github2gerrit-1.0.7 → github2gerrit-1.0.9}/tests/test_cli_netrc_options.py +0 -0
- {github2gerrit-1.0.7 → github2gerrit-1.0.9}/tests/test_cli_outputs_file.py +0 -0
- {github2gerrit-1.0.7 → github2gerrit-1.0.9}/tests/test_cli_url_and_dryrun.py +0 -0
- {github2gerrit-1.0.7 → github2gerrit-1.0.9}/tests/test_commit_normalization.py +0 -0
- {github2gerrit-1.0.7 → github2gerrit-1.0.9}/tests/test_composite_action_coverage.py +0 -0
- {github2gerrit-1.0.7 → github2gerrit-1.0.9}/tests/test_config_and_reviewers.py +0 -0
- {github2gerrit-1.0.7 → github2gerrit-1.0.9}/tests/test_config_helpers.py +0 -0
- {github2gerrit-1.0.7 → github2gerrit-1.0.9}/tests/test_core_close_pr_policy.py +0 -0
- {github2gerrit-1.0.7 → github2gerrit-1.0.9}/tests/test_core_gerrit_backref_comment.py +0 -0
- {github2gerrit-1.0.7 → github2gerrit-1.0.9}/tests/test_core_gerrit_push_errors.py +0 -0
- {github2gerrit-1.0.7 → github2gerrit-1.0.9}/tests/test_core_gerrit_rest_results.py +0 -0
- {github2gerrit-1.0.7 → github2gerrit-1.0.9}/tests/test_core_shallow_clone.py +0 -0
- {github2gerrit-1.0.7 → github2gerrit-1.0.9}/tests/test_core_ssrf_protection.py +0 -0
- {github2gerrit-1.0.7 → github2gerrit-1.0.9}/tests/test_duplicate_detection.py +0 -0
- {github2gerrit-1.0.7 → github2gerrit-1.0.9}/tests/test_email_case_normalization.py +0 -0
- {github2gerrit-1.0.7 → github2gerrit-1.0.9}/tests/test_error_codes.py +0 -0
- {github2gerrit-1.0.7 → github2gerrit-1.0.9}/tests/test_external_api_framework.py +0 -0
- {github2gerrit-1.0.7 → github2gerrit-1.0.9}/tests/test_gerrit_change_status_checks.py +0 -0
- {github2gerrit-1.0.7 → github2gerrit-1.0.9}/tests/test_gerrit_pr_closer.py +0 -0
- {github2gerrit-1.0.7 → github2gerrit-1.0.9}/tests/test_gerrit_rest_client.py +0 -0
- {github2gerrit-1.0.7 → github2gerrit-1.0.9}/tests/test_gerrit_urls.py +0 -0
- {github2gerrit-1.0.7 → github2gerrit-1.0.9}/tests/test_gerrit_urls_more.py +0 -0
- {github2gerrit-1.0.7 → github2gerrit-1.0.9}/tests/test_ghe_and_gitreview_args.py +0 -0
- {github2gerrit-1.0.7 → github2gerrit-1.0.9}/tests/test_github_api_error_handling.py +0 -0
- {github2gerrit-1.0.7 → github2gerrit-1.0.9}/tests/test_github_api_helpers.py +0 -0
- {github2gerrit-1.0.7 → github2gerrit-1.0.9}/tests/test_github_api_retry_and_helpers.py +0 -0
- {github2gerrit-1.0.7 → github2gerrit-1.0.9}/tests/test_gitutils_helpers.py +0 -0
- {github2gerrit-1.0.7 → github2gerrit-1.0.9}/tests/test_mapping_comment_additional.py +0 -0
- {github2gerrit-1.0.7 → github2gerrit-1.0.9}/tests/test_mapping_comment_digest_and_backref.py +0 -0
- {github2gerrit-1.0.7 → github2gerrit-1.0.9}/tests/test_metadata_and_reconciliation.py +0 -0
- {github2gerrit-1.0.7 → github2gerrit-1.0.9}/tests/test_misc_small_coverage.py +0 -0
- {github2gerrit-1.0.7 → github2gerrit-1.0.9}/tests/test_netrc.py +0 -0
- {github2gerrit-1.0.7 → github2gerrit-1.0.9}/tests/test_orphan_rest_side_effects.py +0 -0
- {github2gerrit-1.0.7 → github2gerrit-1.0.9}/tests/test_pr_content_filter.py +0 -0
- {github2gerrit-1.0.7 → github2gerrit-1.0.9}/tests/test_reconciliation_extracted_module.py +0 -0
- {github2gerrit-1.0.7 → github2gerrit-1.0.9}/tests/test_reconciliation_plan_and_orphans.py +0 -0
- {github2gerrit-1.0.7 → github2gerrit-1.0.9}/tests/test_reconciliation_scenarios.py +0 -0
- {github2gerrit-1.0.7 → github2gerrit-1.0.9}/tests/test_ssh_agent.py +0 -0
- {github2gerrit-1.0.7 → github2gerrit-1.0.9}/tests/test_ssh_agent_ownership.py +0 -0
- {github2gerrit-1.0.7 → github2gerrit-1.0.9}/tests/test_ssh_artifact_prevention.py +0 -0
- {github2gerrit-1.0.7 → github2gerrit-1.0.9}/tests/test_ssh_common.py +0 -0
- {github2gerrit-1.0.7 → github2gerrit-1.0.9}/tests/test_ssh_discovery.py +0 -0
- {github2gerrit-1.0.7 → github2gerrit-1.0.9}/tests/test_ssh_discovery_dry_run.py +0 -0
- {github2gerrit-1.0.7 → github2gerrit-1.0.9}/tests/test_trailers_additional.py +0 -0
- {github2gerrit-1.0.7 → github2gerrit-1.0.9}/tests/test_url_parser.py +0 -0
- {github2gerrit-1.0.7 → github2gerrit-1.0.9}/tests/test_utils.py +0 -0
- {github2gerrit-1.0.7 → github2gerrit-1.0.9}/tests/unit/test_config_integration.py +0 -0
- {github2gerrit-1.0.7 → github2gerrit-1.0.9}/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: b969e2851312ca2b24bbec879ba4954341d1bd12 # frozen: v0.15.5
|
|
63
63
|
hooks:
|
|
64
64
|
- id: ruff
|
|
65
65
|
files: ^(src|scripts|tests)/.+\.py$
|
|
@@ -96,7 +96,7 @@ repos:
|
|
|
96
96
|
- id: shellcheck
|
|
97
97
|
|
|
98
98
|
- repo: https://github.com/igorshubovych/markdownlint-cli
|
|
99
|
-
rev:
|
|
99
|
+
rev: e72a3ca1632f0b11a07d171449fe447a7ff6795e # frozen: v0.48.0
|
|
100
100
|
hooks:
|
|
101
101
|
- id: markdownlint
|
|
102
102
|
args: ["--fix", "--config", ".markdownlint.yaml"]
|
|
@@ -116,12 +116,12 @@ repos:
|
|
|
116
116
|
|
|
117
117
|
# Check for misspellings in documentation files
|
|
118
118
|
- repo: https://github.com/codespell-project/codespell
|
|
119
|
-
rev:
|
|
119
|
+
rev: 2ccb47ff45ad361a21071a7eedda4c37e6ae8c5a # frozen: v2.4.2
|
|
120
120
|
hooks:
|
|
121
121
|
- id: codespell
|
|
122
122
|
|
|
123
123
|
- repo: https://github.com/python-jsonschema/check-jsonschema
|
|
124
|
-
rev:
|
|
124
|
+
rev: 8db279a37c552206d2df62269ff6f9d31125815a # frozen: 0.37.0
|
|
125
125
|
hooks:
|
|
126
126
|
- id: check-github-actions
|
|
127
127
|
- id: check-github-workflows
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: github2gerrit
|
|
3
|
-
Version: 1.0.
|
|
3
|
+
Version: 1.0.9
|
|
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
|
|
@@ -39,7 +39,6 @@ Requires-Dist: pytest-mock>=3.15.1; extra == 'dev'
|
|
|
39
39
|
Requires-Dist: pytest>=9.0.2; extra == 'dev'
|
|
40
40
|
Requires-Dist: responses>=0.25.8; extra == 'dev'
|
|
41
41
|
Requires-Dist: ruff>=0.6.3; extra == 'dev'
|
|
42
|
-
Requires-Dist: types-click>=7.1.8; extra == 'dev'
|
|
43
42
|
Requires-Dist: types-requests>=2.31.0; extra == 'dev'
|
|
44
43
|
Requires-Dist: types-urllib3>=1.26.25.14; extra == 'dev'
|
|
45
44
|
Description-Content-Type: text/markdown
|
|
@@ -147,6 +146,117 @@ If UPDATE fails to find existing change:
|
|
|
147
146
|
To create a new change, trigger the 'opened' workflow action.
|
|
148
147
|
```
|
|
149
148
|
|
|
149
|
+
## PR Comment Commands
|
|
150
|
+
|
|
151
|
+
GitHub2Gerrit supports an extensible set of directives issued through
|
|
152
|
+
pull request comments. Add a comment containing `@github2gerrit`
|
|
153
|
+
followed by a command phrase and the tool will act on it during
|
|
154
|
+
the next workflow run.
|
|
155
|
+
|
|
156
|
+
### Command Format
|
|
157
|
+
|
|
158
|
+
<!-- markdownlint-disable MD013 -->
|
|
159
|
+
|
|
160
|
+
```text
|
|
161
|
+
@github2gerrit <command>
|
|
162
|
+
```
|
|
163
|
+
|
|
164
|
+
<!-- markdownlint-enable MD013 -->
|
|
165
|
+
|
|
166
|
+
- Commands are **case-insensitive** — `@github2gerrit Create Missing Change`
|
|
167
|
+
works the same as `@github2gerrit create missing change`.
|
|
168
|
+
- Only the **latest** occurrence of each command takes effect when the same
|
|
169
|
+
command appears in more than one comment.
|
|
170
|
+
- The tool logs unrecognised directives at debug level and ignores them.
|
|
171
|
+
|
|
172
|
+
### Available Commands
|
|
173
|
+
|
|
174
|
+
<!-- markdownlint-disable MD013 MD060 -->
|
|
175
|
+
|
|
176
|
+
| Command | Aliases | Description |
|
|
177
|
+
| --- | --- | --- |
|
|
178
|
+
| `create missing change` | `create-missing`, `create missing` | Create a Gerrit change when an UPDATE operation cannot find an existing one |
|
|
179
|
+
|
|
180
|
+
<!-- markdownlint-enable MD013 MD060 -->
|
|
181
|
+
|
|
182
|
+
### Create Missing Change
|
|
183
|
+
|
|
184
|
+
When a PR `synchronize` event fires, GitHub2Gerrit treats it as an
|
|
185
|
+
**UPDATE** operation and expects a Gerrit change to exist. If the
|
|
186
|
+
original `opened` event failed (for example due to a bug or transient
|
|
187
|
+
error), no Gerrit change exists and every following update fails with:
|
|
188
|
+
|
|
189
|
+
```text
|
|
190
|
+
❌ UPDATE FAILED: Cannot update non-existent Gerrit change
|
|
191
|
+
```
|
|
192
|
+
|
|
193
|
+
The **create missing change** command resolves this without manual
|
|
194
|
+
intervention in Gerrit. Two mechanisms trigger it:
|
|
195
|
+
|
|
196
|
+
#### 1. PR Comment Directive
|
|
197
|
+
|
|
198
|
+
Add a comment on the stuck pull request:
|
|
199
|
+
|
|
200
|
+
```text
|
|
201
|
+
@github2gerrit create missing change
|
|
202
|
+
```
|
|
203
|
+
|
|
204
|
+
Then re-trigger the workflow (push a trivial change or re-run the
|
|
205
|
+
workflow manually). GitHub2Gerrit detects the directive, switches
|
|
206
|
+
from UPDATE to CREATE mode, and pushes a new Gerrit change.
|
|
207
|
+
|
|
208
|
+
#### 2. CLI Flag
|
|
209
|
+
|
|
210
|
+
Outside GitHub Actions you can pass the flag directly:
|
|
211
|
+
|
|
212
|
+
```shell
|
|
213
|
+
github2gerrit \
|
|
214
|
+
--create-missing \
|
|
215
|
+
https://github.com/MyOrg/my-repo/pull/42
|
|
216
|
+
```
|
|
217
|
+
|
|
218
|
+
Or set the environment variable:
|
|
219
|
+
|
|
220
|
+
```shell
|
|
221
|
+
export CREATE_MISSING=true
|
|
222
|
+
github2gerrit https://github.com/MyOrg/my-repo/pull/42
|
|
223
|
+
```
|
|
224
|
+
|
|
225
|
+
#### What Happens During Fallback
|
|
226
|
+
|
|
227
|
+
1. The tool attempts the normal UPDATE flow and finds no existing
|
|
228
|
+
Gerrit change.
|
|
229
|
+
2. It checks for `--create-missing` **or** scans PR comments for the
|
|
230
|
+
`@github2gerrit create missing change` directive.
|
|
231
|
+
3. If authorised, the operation mode switches from UPDATE to CREATE.
|
|
232
|
+
4. The tool posts a notice on the PR:
|
|
233
|
+
|
|
234
|
+
```text
|
|
235
|
+
🔄 GitHub2Gerrit: No existing Gerrit change found for this PR.
|
|
236
|
+
Creating a new Gerrit change (fallback from UPDATE operation).
|
|
237
|
+
```
|
|
238
|
+
|
|
239
|
+
5. The pipeline continues as a normal CREATE — preparing commits,
|
|
240
|
+
pushing to Gerrit, posting the change URL back on the PR.
|
|
241
|
+
|
|
242
|
+
#### GitHub Actions Workflow Example
|
|
243
|
+
|
|
244
|
+
<!-- markdownlint-disable MD013 -->
|
|
245
|
+
|
|
246
|
+
```yaml
|
|
247
|
+
- name: Submit PR to Gerrit
|
|
248
|
+
uses: lfreleng-actions/github2gerrit-action@main
|
|
249
|
+
with:
|
|
250
|
+
GERRIT_SSH_PRIVKEY_G2G: ${{ secrets.GERRIT_SSH_PRIVKEY_G2G }}
|
|
251
|
+
CREATE_MISSING: "true" # always allow fallback
|
|
252
|
+
```
|
|
253
|
+
|
|
254
|
+
<!-- markdownlint-enable MD013 -->
|
|
255
|
+
|
|
256
|
+
> **Tip:** Setting `CREATE_MISSING` to `true` in your workflow means
|
|
257
|
+
> stuck PRs self-heal on the next `synchronize` event without requiring
|
|
258
|
+
> a comment directive.
|
|
259
|
+
|
|
150
260
|
## Close Merged PRs Feature
|
|
151
261
|
|
|
152
262
|
GitHub2Gerrit now includes **automatic PR closure** when Gerrit merges changes
|
|
@@ -1526,7 +1636,9 @@ requiring manual configuration per PR or user.
|
|
|
1526
1636
|
- `src/github2gerrit/gitutils.py` (subprocess and git helpers)
|
|
1527
1637
|
- Linting and type checking
|
|
1528
1638
|
- Ruff and MyPy use settings in `pyproject.toml`.
|
|
1529
|
-
- Run from
|
|
1639
|
+
- Run from [prek](https://github.com/j178/prek) hooks and CI.
|
|
1640
|
+
- prek is a faster, Rust-based drop-in replacement for pre-commit
|
|
1641
|
+
that reads the existing `.pre-commit-config.yaml` unchanged.
|
|
1530
1642
|
- Tests
|
|
1531
1643
|
- Pytest with coverage targets around 80%.
|
|
1532
1644
|
- Add unit and integration tests for each feature.
|
|
@@ -1536,6 +1648,10 @@ requiring manual configuration per PR or user.
|
|
|
1536
1648
|
- Install `uv` and run:
|
|
1537
1649
|
- `uv pip install --system .`
|
|
1538
1650
|
- `uv run github2gerrit --help`
|
|
1651
|
+
- Install prek hooks:
|
|
1652
|
+
- `uv tool install prek && prek install -f`
|
|
1653
|
+
- Run all checks (including tests) manually:
|
|
1654
|
+
- `prek run --all-files`
|
|
1539
1655
|
- Run tests:
|
|
1540
1656
|
- `uv run pytest -q`
|
|
1541
1657
|
- Lint and type check:
|
|
@@ -101,6 +101,117 @@ If UPDATE fails to find existing change:
|
|
|
101
101
|
To create a new change, trigger the 'opened' workflow action.
|
|
102
102
|
```
|
|
103
103
|
|
|
104
|
+
## PR Comment Commands
|
|
105
|
+
|
|
106
|
+
GitHub2Gerrit supports an extensible set of directives issued through
|
|
107
|
+
pull request comments. Add a comment containing `@github2gerrit`
|
|
108
|
+
followed by a command phrase and the tool will act on it during
|
|
109
|
+
the next workflow run.
|
|
110
|
+
|
|
111
|
+
### Command Format
|
|
112
|
+
|
|
113
|
+
<!-- markdownlint-disable MD013 -->
|
|
114
|
+
|
|
115
|
+
```text
|
|
116
|
+
@github2gerrit <command>
|
|
117
|
+
```
|
|
118
|
+
|
|
119
|
+
<!-- markdownlint-enable MD013 -->
|
|
120
|
+
|
|
121
|
+
- Commands are **case-insensitive** — `@github2gerrit Create Missing Change`
|
|
122
|
+
works the same as `@github2gerrit create missing change`.
|
|
123
|
+
- Only the **latest** occurrence of each command takes effect when the same
|
|
124
|
+
command appears in more than one comment.
|
|
125
|
+
- The tool logs unrecognised directives at debug level and ignores them.
|
|
126
|
+
|
|
127
|
+
### Available Commands
|
|
128
|
+
|
|
129
|
+
<!-- markdownlint-disable MD013 MD060 -->
|
|
130
|
+
|
|
131
|
+
| Command | Aliases | Description |
|
|
132
|
+
| --- | --- | --- |
|
|
133
|
+
| `create missing change` | `create-missing`, `create missing` | Create a Gerrit change when an UPDATE operation cannot find an existing one |
|
|
134
|
+
|
|
135
|
+
<!-- markdownlint-enable MD013 MD060 -->
|
|
136
|
+
|
|
137
|
+
### Create Missing Change
|
|
138
|
+
|
|
139
|
+
When a PR `synchronize` event fires, GitHub2Gerrit treats it as an
|
|
140
|
+
**UPDATE** operation and expects a Gerrit change to exist. If the
|
|
141
|
+
original `opened` event failed (for example due to a bug or transient
|
|
142
|
+
error), no Gerrit change exists and every following update fails with:
|
|
143
|
+
|
|
144
|
+
```text
|
|
145
|
+
❌ UPDATE FAILED: Cannot update non-existent Gerrit change
|
|
146
|
+
```
|
|
147
|
+
|
|
148
|
+
The **create missing change** command resolves this without manual
|
|
149
|
+
intervention in Gerrit. Two mechanisms trigger it:
|
|
150
|
+
|
|
151
|
+
#### 1. PR Comment Directive
|
|
152
|
+
|
|
153
|
+
Add a comment on the stuck pull request:
|
|
154
|
+
|
|
155
|
+
```text
|
|
156
|
+
@github2gerrit create missing change
|
|
157
|
+
```
|
|
158
|
+
|
|
159
|
+
Then re-trigger the workflow (push a trivial change or re-run the
|
|
160
|
+
workflow manually). GitHub2Gerrit detects the directive, switches
|
|
161
|
+
from UPDATE to CREATE mode, and pushes a new Gerrit change.
|
|
162
|
+
|
|
163
|
+
#### 2. CLI Flag
|
|
164
|
+
|
|
165
|
+
Outside GitHub Actions you can pass the flag directly:
|
|
166
|
+
|
|
167
|
+
```shell
|
|
168
|
+
github2gerrit \
|
|
169
|
+
--create-missing \
|
|
170
|
+
https://github.com/MyOrg/my-repo/pull/42
|
|
171
|
+
```
|
|
172
|
+
|
|
173
|
+
Or set the environment variable:
|
|
174
|
+
|
|
175
|
+
```shell
|
|
176
|
+
export CREATE_MISSING=true
|
|
177
|
+
github2gerrit https://github.com/MyOrg/my-repo/pull/42
|
|
178
|
+
```
|
|
179
|
+
|
|
180
|
+
#### What Happens During Fallback
|
|
181
|
+
|
|
182
|
+
1. The tool attempts the normal UPDATE flow and finds no existing
|
|
183
|
+
Gerrit change.
|
|
184
|
+
2. It checks for `--create-missing` **or** scans PR comments for the
|
|
185
|
+
`@github2gerrit create missing change` directive.
|
|
186
|
+
3. If authorised, the operation mode switches from UPDATE to CREATE.
|
|
187
|
+
4. The tool posts a notice on the PR:
|
|
188
|
+
|
|
189
|
+
```text
|
|
190
|
+
🔄 GitHub2Gerrit: No existing Gerrit change found for this PR.
|
|
191
|
+
Creating a new Gerrit change (fallback from UPDATE operation).
|
|
192
|
+
```
|
|
193
|
+
|
|
194
|
+
5. The pipeline continues as a normal CREATE — preparing commits,
|
|
195
|
+
pushing to Gerrit, posting the change URL back on the PR.
|
|
196
|
+
|
|
197
|
+
#### GitHub Actions Workflow Example
|
|
198
|
+
|
|
199
|
+
<!-- markdownlint-disable MD013 -->
|
|
200
|
+
|
|
201
|
+
```yaml
|
|
202
|
+
- name: Submit PR to Gerrit
|
|
203
|
+
uses: lfreleng-actions/github2gerrit-action@main
|
|
204
|
+
with:
|
|
205
|
+
GERRIT_SSH_PRIVKEY_G2G: ${{ secrets.GERRIT_SSH_PRIVKEY_G2G }}
|
|
206
|
+
CREATE_MISSING: "true" # always allow fallback
|
|
207
|
+
```
|
|
208
|
+
|
|
209
|
+
<!-- markdownlint-enable MD013 -->
|
|
210
|
+
|
|
211
|
+
> **Tip:** Setting `CREATE_MISSING` to `true` in your workflow means
|
|
212
|
+
> stuck PRs self-heal on the next `synchronize` event without requiring
|
|
213
|
+
> a comment directive.
|
|
214
|
+
|
|
104
215
|
## Close Merged PRs Feature
|
|
105
216
|
|
|
106
217
|
GitHub2Gerrit now includes **automatic PR closure** when Gerrit merges changes
|
|
@@ -1480,7 +1591,9 @@ requiring manual configuration per PR or user.
|
|
|
1480
1591
|
- `src/github2gerrit/gitutils.py` (subprocess and git helpers)
|
|
1481
1592
|
- Linting and type checking
|
|
1482
1593
|
- Ruff and MyPy use settings in `pyproject.toml`.
|
|
1483
|
-
- Run from
|
|
1594
|
+
- Run from [prek](https://github.com/j178/prek) hooks and CI.
|
|
1595
|
+
- prek is a faster, Rust-based drop-in replacement for pre-commit
|
|
1596
|
+
that reads the existing `.pre-commit-config.yaml` unchanged.
|
|
1484
1597
|
- Tests
|
|
1485
1598
|
- Pytest with coverage targets around 80%.
|
|
1486
1599
|
- Add unit and integration tests for each feature.
|
|
@@ -1490,6 +1603,10 @@ requiring manual configuration per PR or user.
|
|
|
1490
1603
|
- Install `uv` and run:
|
|
1491
1604
|
- `uv pip install --system .`
|
|
1492
1605
|
- `uv run github2gerrit --help`
|
|
1606
|
+
- Install prek hooks:
|
|
1607
|
+
- `uv tool install prek && prek install -f`
|
|
1608
|
+
- Run all checks (including tests) manually:
|
|
1609
|
+
- `prek run --all-files`
|
|
1493
1610
|
- Run tests:
|
|
1494
1611
|
- `uv run pytest -q`
|
|
1495
1612
|
- Lint and type check:
|
|
@@ -129,6 +129,14 @@ inputs:
|
|
|
129
129
|
(format: [{"key": "username", "value": "ISSUE-ID"}])
|
|
130
130
|
required: false
|
|
131
131
|
default: "[]"
|
|
132
|
+
COMMIT_RULES_JSON:
|
|
133
|
+
description: >-
|
|
134
|
+
JSON object defining commit message rules with per-project and
|
|
135
|
+
per-actor overrides. Supports arbitrary label-value pairs placed
|
|
136
|
+
in the commit body or trailer block.
|
|
137
|
+
(see: docs/COMMIT_RULES.md)
|
|
138
|
+
required: false
|
|
139
|
+
default: ""
|
|
132
140
|
AUTOMATION_ONLY:
|
|
133
141
|
description: "Only accept pull requests from known automation tools"
|
|
134
142
|
required: false
|
|
@@ -141,6 +149,10 @@ inputs:
|
|
|
141
149
|
description: "Abandon Gerrit changes when their GitHub PRs are closed"
|
|
142
150
|
required: false
|
|
143
151
|
default: "true"
|
|
152
|
+
CREATE_MISSING:
|
|
153
|
+
description: "Create a Gerrit change when an UPDATE operation cannot find an existing one"
|
|
154
|
+
required: false
|
|
155
|
+
default: "false"
|
|
144
156
|
|
|
145
157
|
outputs:
|
|
146
158
|
gerrit_change_request_url:
|
|
@@ -164,7 +176,7 @@ runs:
|
|
|
164
176
|
|
|
165
177
|
- name: "Setup uv"
|
|
166
178
|
# yamllint disable-line rule:line-length
|
|
167
|
-
uses: astral-sh/setup-uv@
|
|
179
|
+
uses: astral-sh/setup-uv@e06108dd0aef18192324c70427afc47652e63a82 # v7.5.0
|
|
168
180
|
with:
|
|
169
181
|
enable-cache: false
|
|
170
182
|
|
|
@@ -290,6 +302,7 @@ runs:
|
|
|
290
302
|
ALLOW_DUPLICATES: ${{ inputs.ALLOW_DUPLICATES }}
|
|
291
303
|
ISSUE_ID: ${{ inputs.ISSUE_ID }}
|
|
292
304
|
ISSUE_ID_LOOKUP_JSON: ${{ inputs.ISSUE_ID_LOOKUP_JSON }}
|
|
305
|
+
COMMIT_RULES_JSON: ${{ inputs.COMMIT_RULES_JSON }}
|
|
293
306
|
CI_TESTING: ${{ inputs.CI_TESTING }}
|
|
294
307
|
CLOSE_MERGED_PRS: ${{ inputs.CLOSE_MERGED_PRS }}
|
|
295
308
|
FORCE: ${{ inputs.FORCE }}
|
|
@@ -300,6 +313,7 @@ runs:
|
|
|
300
313
|
AUTOMATION_ONLY: ${{ inputs.AUTOMATION_ONLY }}
|
|
301
314
|
CLEANUP_ABANDONED: ${{ inputs.CLEANUP_ABANDONED }}
|
|
302
315
|
CLEANUP_GERRIT: ${{ inputs.CLEANUP_GERRIT }}
|
|
316
|
+
CREATE_MISSING: ${{ inputs.CREATE_MISSING }}
|
|
303
317
|
|
|
304
318
|
# Optional Gerrit overrides (when .gitreview is missing)
|
|
305
319
|
GERRIT_SERVER: ${{ inputs.GERRIT_SERVER }}
|
|
@@ -0,0 +1,255 @@
|
|
|
1
|
+
<!-- SPDX-License-Identifier: Apache-2.0 -->
|
|
2
|
+
<!-- SPDX-FileCopyrightText: 2025 The Linux Foundation -->
|
|
3
|
+
|
|
4
|
+
# Commit Rules (`COMMIT_RULES_JSON`)
|
|
5
|
+
|
|
6
|
+
The **commit rules** feature provides a flexible, JSON-driven mechanism for
|
|
7
|
+
injecting arbitrary lines into commit messages submitted to Gerrit. It
|
|
8
|
+
generalises the existing `ISSUE_ID` / `ISSUE_ID_LOOKUP_JSON` support to handle
|
|
9
|
+
per-project requirements such as FD.io VPP's mandatory `Type:` field.
|
|
10
|
+
|
|
11
|
+
## Quick Start
|
|
12
|
+
|
|
13
|
+
Set the `COMMIT_RULES_JSON` GitHub Actions variable (organisation or
|
|
14
|
+
repository level) to a JSON object describing the rules:
|
|
15
|
+
|
|
16
|
+
```yaml
|
|
17
|
+
# .github/workflows/g2g.yml
|
|
18
|
+
jobs:
|
|
19
|
+
submit:
|
|
20
|
+
steps:
|
|
21
|
+
- uses: lfreleng-actions/github2gerrit-action@main
|
|
22
|
+
with:
|
|
23
|
+
COMMIT_RULES_JSON: ${{ vars.COMMIT_RULES_JSON }}
|
|
24
|
+
# ... other inputs ...
|
|
25
|
+
```
|
|
26
|
+
|
|
27
|
+
## JSON Schema
|
|
28
|
+
|
|
29
|
+
The top-level object has three optional sections:
|
|
30
|
+
|
|
31
|
+
| Section | Type | Description |
|
|
32
|
+
|------------|-------------------------------|------------------------------------------------|
|
|
33
|
+
| `defaults` | `array` of rule objects | Baseline rules applied to every commit. |
|
|
34
|
+
| `projects` | `object` (project → rules[]) | Per-Gerrit-project overrides. |
|
|
35
|
+
| `actors` | `object` (actor → rules[]) | Per-GitHub-actor overrides (e.g. bots). |
|
|
36
|
+
|
|
37
|
+
### Rule Object
|
|
38
|
+
|
|
39
|
+
Each rule object describes a single line to insert into the commit message:
|
|
40
|
+
|
|
41
|
+
| Field | Type | Required | Default | Description |
|
|
42
|
+
|-------------|----------|----------|----------------|----------------------------------------------------------------------------|
|
|
43
|
+
| `key` | `string` | Yes | — | The label name (e.g. `Type`, `Issue-ID`, `Ticket`). |
|
|
44
|
+
| `value` | `string` | Yes | — | The value to insert. |
|
|
45
|
+
| `location` | `string` | No | `"trailer"` | Where to place the line — `"trailer"` or `"body"`. |
|
|
46
|
+
| `separator` | `string` | No | `"blank_line"` | Separation style when `location` is `"body"` — `"blank_line"` or `"none"`. |
|
|
47
|
+
|
|
48
|
+
### Locations
|
|
49
|
+
|
|
50
|
+
- **`trailer`** — places the line in the Git trailer block at the end of
|
|
51
|
+
the commit message, alongside `Change-Id`, `Signed-off-by`, etc.
|
|
52
|
+
- **`body`** — places the line in the commit body, before the trailer
|
|
53
|
+
block. Fields like VPP's `Type:` need this location because Gerrit
|
|
54
|
+
server-side hooks expect them in the body rather than the trailer section.
|
|
55
|
+
|
|
56
|
+
### Separators (body location only)
|
|
57
|
+
|
|
58
|
+
- **`blank_line`** (default) — inserts a blank line before the new
|
|
59
|
+
content, matching the conventional VPP commit style.
|
|
60
|
+
- **`none`** — appends the line directly after the existing body text
|
|
61
|
+
without extra blank lines.
|
|
62
|
+
|
|
63
|
+
## Resolution Precedence
|
|
64
|
+
|
|
65
|
+
The engine resolves rules in this order when building the commit message
|
|
66
|
+
(last writer wins for a given `key`):
|
|
67
|
+
|
|
68
|
+
1. **`defaults`** — baseline rules for all projects and actors.
|
|
69
|
+
2. **`projects[<gerrit_project>]`** — overrides defaults for the matching
|
|
70
|
+
Gerrit project (from `.gitreview` or `GERRIT_PROJECT`).
|
|
71
|
+
3. **`actors[<github_actor>]`** — overrides everything for the matching
|
|
72
|
+
GitHub actor (from `GITHUB_ACTOR`).
|
|
73
|
+
|
|
74
|
+
The existing `ISSUE_ID` input always takes priority over any `Issue-ID`
|
|
75
|
+
rule from commit rules. Both mechanisms can coexist safely.
|
|
76
|
+
|
|
77
|
+
## Examples
|
|
78
|
+
|
|
79
|
+
### FD.io (VPP + CSIT on the same Gerrit server)
|
|
80
|
+
|
|
81
|
+
VPP requires a `Type:` field in the commit body; CSIT does not.
|
|
82
|
+
Both projects need `Issue-ID` in the trailer block.
|
|
83
|
+
|
|
84
|
+
```json
|
|
85
|
+
{
|
|
86
|
+
"defaults": [
|
|
87
|
+
{
|
|
88
|
+
"key": "Issue-ID",
|
|
89
|
+
"value": "CIMAN-33",
|
|
90
|
+
"location": "trailer"
|
|
91
|
+
}
|
|
92
|
+
],
|
|
93
|
+
"projects": {
|
|
94
|
+
"vpp": [
|
|
95
|
+
{
|
|
96
|
+
"key": "Type",
|
|
97
|
+
"value": "ci",
|
|
98
|
+
"location": "body",
|
|
99
|
+
"separator": "blank_line"
|
|
100
|
+
},
|
|
101
|
+
{
|
|
102
|
+
"key": "Issue-ID",
|
|
103
|
+
"value": "CIMAN-33",
|
|
104
|
+
"location": "trailer"
|
|
105
|
+
}
|
|
106
|
+
],
|
|
107
|
+
"hicn": [
|
|
108
|
+
{
|
|
109
|
+
"key": "Type",
|
|
110
|
+
"value": "ci",
|
|
111
|
+
"location": "body",
|
|
112
|
+
"separator": "blank_line"
|
|
113
|
+
}
|
|
114
|
+
]
|
|
115
|
+
},
|
|
116
|
+
"actors": {
|
|
117
|
+
"dependabot[bot]": [
|
|
118
|
+
{
|
|
119
|
+
"key": "Type",
|
|
120
|
+
"value": "ci",
|
|
121
|
+
"location": "body"
|
|
122
|
+
},
|
|
123
|
+
{
|
|
124
|
+
"key": "Issue-ID",
|
|
125
|
+
"value": "CIMAN-33",
|
|
126
|
+
"location": "trailer"
|
|
127
|
+
}
|
|
128
|
+
],
|
|
129
|
+
"renovate[bot]": [
|
|
130
|
+
{
|
|
131
|
+
"key": "Issue-ID",
|
|
132
|
+
"value": "CIMAN-44",
|
|
133
|
+
"location": "trailer"
|
|
134
|
+
}
|
|
135
|
+
]
|
|
136
|
+
}
|
|
137
|
+
}
|
|
138
|
+
```
|
|
139
|
+
|
|
140
|
+
**Result for VPP + dependabot:**
|
|
141
|
+
|
|
142
|
+
```text
|
|
143
|
+
gha: update actions/checkout from v3 to v4
|
|
144
|
+
|
|
145
|
+
Type: ci
|
|
146
|
+
|
|
147
|
+
Issue-ID: CIMAN-33
|
|
148
|
+
Change-Id: I1234567890abcdef...
|
|
149
|
+
Signed-off-by: dependabot[bot] <support@github.com>
|
|
150
|
+
```
|
|
151
|
+
|
|
152
|
+
**Result for CSIT + human user:**
|
|
153
|
+
|
|
154
|
+
```text
|
|
155
|
+
fix: correct test assertion
|
|
156
|
+
|
|
157
|
+
Issue-ID: CIMAN-33
|
|
158
|
+
Change-Id: I1234567890abcdef...
|
|
159
|
+
Signed-off-by: Jane Doe <jane@example.com>
|
|
160
|
+
```
|
|
161
|
+
|
|
162
|
+
### ONAP (Issue-ID only)
|
|
163
|
+
|
|
164
|
+
ONAP projects only need `Issue-ID` in the trailer:
|
|
165
|
+
|
|
166
|
+
```json
|
|
167
|
+
{
|
|
168
|
+
"actors": {
|
|
169
|
+
"dependabot[bot]": [
|
|
170
|
+
{
|
|
171
|
+
"key": "Issue-ID",
|
|
172
|
+
"value": "CIMAN-33"
|
|
173
|
+
}
|
|
174
|
+
]
|
|
175
|
+
}
|
|
176
|
+
}
|
|
177
|
+
```
|
|
178
|
+
|
|
179
|
+
### Extra body fields
|
|
180
|
+
|
|
181
|
+
Some projects need more than one body field:
|
|
182
|
+
|
|
183
|
+
```json
|
|
184
|
+
{
|
|
185
|
+
"projects": {
|
|
186
|
+
"vpp": [
|
|
187
|
+
{
|
|
188
|
+
"key": "Type",
|
|
189
|
+
"value": "ci",
|
|
190
|
+
"location": "body",
|
|
191
|
+
"separator": "blank_line"
|
|
192
|
+
},
|
|
193
|
+
{
|
|
194
|
+
"key": "Ticket",
|
|
195
|
+
"value": "VPP-2088",
|
|
196
|
+
"location": "body",
|
|
197
|
+
"separator": "none"
|
|
198
|
+
}
|
|
199
|
+
]
|
|
200
|
+
}
|
|
201
|
+
}
|
|
202
|
+
```
|
|
203
|
+
|
|
204
|
+
**Result:**
|
|
205
|
+
|
|
206
|
+
```text
|
|
207
|
+
gha: update dependency versions
|
|
208
|
+
|
|
209
|
+
Type: ci
|
|
210
|
+
Ticket: VPP-2088
|
|
211
|
+
|
|
212
|
+
Change-Id: I1234567890abcdef...
|
|
213
|
+
Signed-off-by: bot <bot@example.com>
|
|
214
|
+
```
|
|
215
|
+
|
|
216
|
+
## CLI Usage
|
|
217
|
+
|
|
218
|
+
You can also pass the commit rules JSON via the command line:
|
|
219
|
+
|
|
220
|
+
```bash
|
|
221
|
+
github2gerrit --commit-rules '{"defaults": [...]}' \
|
|
222
|
+
https://github.com/org/repo/pull/123
|
|
223
|
+
```
|
|
224
|
+
|
|
225
|
+
Or via the environment variable:
|
|
226
|
+
|
|
227
|
+
```bash
|
|
228
|
+
export COMMIT_RULES_JSON='{"defaults": [...]}'
|
|
229
|
+
github2gerrit https://github.com/org/repo/pull/123
|
|
230
|
+
```
|
|
231
|
+
|
|
232
|
+
## Interaction with ISSUE_ID / ISSUE_ID_LOOKUP_JSON
|
|
233
|
+
|
|
234
|
+
The existing `ISSUE_ID` and `ISSUE_ID_LOOKUP_JSON` inputs continue to
|
|
235
|
+
work unchanged. When both mechanisms specify an `Issue-ID`:
|
|
236
|
+
|
|
237
|
+
1. An explicit `ISSUE_ID` input (or a value resolved from
|
|
238
|
+
`ISSUE_ID_LOOKUP_JSON`) **always wins**.
|
|
239
|
+
2. If `ISSUE_ID` is empty, the engine applies the `Issue-ID` rule from
|
|
240
|
+
`COMMIT_RULES_JSON` instead.
|
|
241
|
+
|
|
242
|
+
This means you can safely enable `COMMIT_RULES_JSON` for an organisation
|
|
243
|
+
without breaking workflows that already set `ISSUE_ID` directly.
|
|
244
|
+
|
|
245
|
+
## Validation and Error Handling
|
|
246
|
+
|
|
247
|
+
- Invalid JSON produces a warning but does **not** fail the workflow
|
|
248
|
+
(matching the existing `ISSUE_ID_LOOKUP_JSON` convention).
|
|
249
|
+
- Individual rule entries with missing or invalid `key`/`value` fields
|
|
250
|
+
produce a warning and the engine skips them; valid entries in the same
|
|
251
|
+
document still apply.
|
|
252
|
+
- Unknown `location` values default to `"trailer"` with a warning.
|
|
253
|
+
- Unknown `separator` values default to `"blank_line"` with a warning.
|
|
254
|
+
- Duplicate lines are automatically detected and skipped (both in body
|
|
255
|
+
and trailer locations).
|
|
@@ -102,7 +102,6 @@ dev = [
|
|
|
102
102
|
# Type checking helpers
|
|
103
103
|
"pytest-mock>=3.15.1",
|
|
104
104
|
"types-requests>=2.31.0",
|
|
105
|
-
"types-click>=7.1.8",
|
|
106
105
|
"types-urllib3>=1.26.25.14",
|
|
107
106
|
]
|
|
108
107
|
|
|
@@ -230,7 +229,6 @@ directory = "coverage_html_report"
|
|
|
230
229
|
minversion = "8.0"
|
|
231
230
|
addopts = "-ra -q --cov=github2gerrit --cov-report=term-missing --cov-report=html"
|
|
232
231
|
testpaths = ["tests"]
|
|
233
|
-
asyncio_default_fixture_loop_scope = "function"
|
|
234
232
|
markers = [
|
|
235
233
|
"integration: marks tests as integration tests (deselect with '-m \"not integration\"')",
|
|
236
234
|
]
|