github2gerrit 2.2.0__tar.gz → 2.2.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.
Files changed (151) hide show
  1. {github2gerrit-2.2.0 → github2gerrit-2.2.2}/.pre-commit-config.yaml +32 -7
  2. {github2gerrit-2.2.0 → github2gerrit-2.2.2}/PKG-INFO +13 -12
  3. {github2gerrit-2.2.0 → github2gerrit-2.2.2}/README.md +12 -11
  4. {github2gerrit-2.2.0 → github2gerrit-2.2.2}/action.yaml +3 -3
  5. {github2gerrit-2.2.0 → github2gerrit-2.2.2}/docs/cli.md +35 -33
  6. {github2gerrit-2.2.0 → github2gerrit-2.2.2}/docs/features.md +86 -8
  7. {github2gerrit-2.2.0 → github2gerrit-2.2.2}/src/github2gerrit/cli.py +127 -30
  8. {github2gerrit-2.2.0 → github2gerrit-2.2.2}/src/github2gerrit/config.py +390 -461
  9. github2gerrit-2.2.2/src/github2gerrit/config_ini.py +355 -0
  10. {github2gerrit-2.2.0 → github2gerrit-2.2.2}/src/github2gerrit/core.py +251 -63
  11. {github2gerrit-2.2.0 → github2gerrit-2.2.2}/src/github2gerrit/duplicate_detection.py +7 -8
  12. {github2gerrit-2.2.0 → github2gerrit-2.2.2}/src/github2gerrit/gerrit_pr_closer.py +56 -45
  13. {github2gerrit-2.2.0 → github2gerrit-2.2.2}/src/github2gerrit/gerrit_query.py +6 -6
  14. {github2gerrit-2.2.0 → github2gerrit-2.2.2}/src/github2gerrit/gerrit_rest.py +8 -2
  15. {github2gerrit-2.2.0 → github2gerrit-2.2.2}/src/github2gerrit/gitreview.py +138 -0
  16. github2gerrit-2.2.2/src/github2gerrit/project_names.py +505 -0
  17. {github2gerrit-2.2.0 → github2gerrit-2.2.2}/src/github2gerrit/utils.py +33 -0
  18. {github2gerrit-2.2.0 → github2gerrit-2.2.2}/tests/conftest.py +32 -0
  19. {github2gerrit-2.2.0 → github2gerrit-2.2.2}/tests/test_action_environment_mapping.py +5 -2
  20. {github2gerrit-2.2.0 → github2gerrit-2.2.2}/tests/test_composite_action_coverage.py +2 -2
  21. {github2gerrit-2.2.0 → github2gerrit-2.2.2}/tests/test_config_helpers.py +1003 -15
  22. github2gerrit-2.2.2/tests/test_core_integration_fixture_repo.py +812 -0
  23. {github2gerrit-2.2.0 → github2gerrit-2.2.2}/tests/test_dns_validation_and_no_gerrit.py +16 -0
  24. {github2gerrit-2.2.0 → github2gerrit-2.2.2}/tests/test_duplicate_detection.py +42 -1
  25. {github2gerrit-2.2.0 → github2gerrit-2.2.2}/tests/test_fork_pr_hardening.py +131 -5
  26. {github2gerrit-2.2.0 → github2gerrit-2.2.2}/tests/test_gerrit_pr_closer.py +46 -13
  27. {github2gerrit-2.2.0 → github2gerrit-2.2.2}/tests/test_gitreview.py +3 -0
  28. {github2gerrit-2.2.0 → github2gerrit-2.2.2}/tests/test_issue_157_regressions.py +48 -10
  29. github2gerrit-2.2.2/tests/test_pr_closed_handling.py +263 -0
  30. {github2gerrit-2.2.0 → github2gerrit-2.2.2}/tests/test_precommit_mypy_pins.py +11 -69
  31. github2gerrit-2.2.2/tests/test_project_names.py +643 -0
  32. github2gerrit-2.2.2/tests/test_sync_mypy_pins.py +310 -0
  33. {github2gerrit-2.2.0 → github2gerrit-2.2.2}/tests/unit/test_config_integration.py +23 -16
  34. {github2gerrit-2.2.0 → github2gerrit-2.2.2}/uv.lock +19 -19
  35. github2gerrit-2.2.0/tests/test_core_integration_fixture_repo.py +0 -200
  36. {github2gerrit-2.2.0 → github2gerrit-2.2.2}/.aislop/config.yml +0 -0
  37. {github2gerrit-2.2.0 → github2gerrit-2.2.2}/.editorconfig +0 -0
  38. {github2gerrit-2.2.0 → github2gerrit-2.2.2}/.gitignore +0 -0
  39. {github2gerrit-2.2.0 → github2gerrit-2.2.2}/.gitlint +0 -0
  40. {github2gerrit-2.2.0 → github2gerrit-2.2.2}/.markdownlint.yaml +0 -0
  41. {github2gerrit-2.2.0 → github2gerrit-2.2.2}/.yamllint +0 -0
  42. {github2gerrit-2.2.0 → github2gerrit-2.2.2}/LICENSE +0 -0
  43. {github2gerrit-2.2.0 → github2gerrit-2.2.2}/LICENSES/Apache-2.0.txt +0 -0
  44. {github2gerrit-2.2.0 → github2gerrit-2.2.2}/REUSE.toml +0 -0
  45. {github2gerrit-2.2.0 → github2gerrit-2.2.2}/SECURITY.md +0 -0
  46. {github2gerrit-2.2.0 → github2gerrit-2.2.2}/docs/COMMIT_RULES.md +0 -0
  47. {github2gerrit-2.2.0 → github2gerrit-2.2.2}/docs/development.md +0 -0
  48. {github2gerrit-2.2.0 → github2gerrit-2.2.2}/docs/github2gerrit_token_permissions_classic.png +0 -0
  49. {github2gerrit-2.2.0 → github2gerrit-2.2.2}/pyproject.toml +0 -0
  50. {github2gerrit-2.2.0 → github2gerrit-2.2.2}/sitecustomize.py +0 -0
  51. {github2gerrit-2.2.0 → github2gerrit-2.2.2}/src/github2gerrit/__init__.py +0 -0
  52. {github2gerrit-2.2.0 → github2gerrit-2.2.2}/src/github2gerrit/approvers.py +0 -0
  53. {github2gerrit-2.2.0 → github2gerrit-2.2.2}/src/github2gerrit/commit_normalization.py +0 -0
  54. {github2gerrit-2.2.0 → github2gerrit-2.2.2}/src/github2gerrit/commit_rules.py +0 -0
  55. {github2gerrit-2.2.0 → github2gerrit-2.2.2}/src/github2gerrit/constants.py +0 -0
  56. {github2gerrit-2.2.0 → github2gerrit-2.2.2}/src/github2gerrit/error_codes.py +0 -0
  57. {github2gerrit-2.2.0 → github2gerrit-2.2.2}/src/github2gerrit/external_api.py +0 -0
  58. {github2gerrit-2.2.0 → github2gerrit-2.2.2}/src/github2gerrit/gerrit_ssh.py +0 -0
  59. {github2gerrit-2.2.0 → github2gerrit-2.2.2}/src/github2gerrit/gerrit_urls.py +0 -0
  60. {github2gerrit-2.2.0 → github2gerrit-2.2.2}/src/github2gerrit/github_api.py +0 -0
  61. {github2gerrit-2.2.0 → github2gerrit-2.2.2}/src/github2gerrit/gitutils.py +0 -0
  62. {github2gerrit-2.2.0 → github2gerrit-2.2.2}/src/github2gerrit/mapping_comment.py +0 -0
  63. {github2gerrit-2.2.0 → github2gerrit-2.2.2}/src/github2gerrit/models.py +0 -0
  64. {github2gerrit-2.2.0 → github2gerrit-2.2.2}/src/github2gerrit/netrc.py +0 -0
  65. {github2gerrit-2.2.0 → github2gerrit-2.2.2}/src/github2gerrit/orchestrator/__init__.py +0 -0
  66. {github2gerrit-2.2.0 → github2gerrit-2.2.2}/src/github2gerrit/orchestrator/reconciliation.py +0 -0
  67. {github2gerrit-2.2.0 → github2gerrit-2.2.2}/src/github2gerrit/pr_approval.py +0 -0
  68. {github2gerrit-2.2.0 → github2gerrit-2.2.2}/src/github2gerrit/pr_commands.py +0 -0
  69. {github2gerrit-2.2.0 → github2gerrit-2.2.2}/src/github2gerrit/pr_content_filter.py +0 -0
  70. {github2gerrit-2.2.0 → github2gerrit-2.2.2}/src/github2gerrit/pr_directives.py +0 -0
  71. {github2gerrit-2.2.0 → github2gerrit-2.2.2}/src/github2gerrit/reconcile_matcher.py +0 -0
  72. {github2gerrit-2.2.0 → github2gerrit-2.2.2}/src/github2gerrit/rich_display.py +0 -0
  73. {github2gerrit-2.2.0 → github2gerrit-2.2.2}/src/github2gerrit/rich_logging.py +0 -0
  74. {github2gerrit-2.2.0 → github2gerrit-2.2.2}/src/github2gerrit/similarity.py +0 -0
  75. {github2gerrit-2.2.0 → github2gerrit-2.2.2}/src/github2gerrit/ssh_agent_setup.py +0 -0
  76. {github2gerrit-2.2.0 → github2gerrit-2.2.2}/src/github2gerrit/ssh_common.py +0 -0
  77. {github2gerrit-2.2.0 → github2gerrit-2.2.2}/src/github2gerrit/ssh_config_parser.py +0 -0
  78. {github2gerrit-2.2.0 → github2gerrit-2.2.2}/src/github2gerrit/ssh_discovery.py +0 -0
  79. {github2gerrit-2.2.0 → github2gerrit-2.2.2}/src/github2gerrit/trailers.py +0 -0
  80. {github2gerrit-2.2.0 → github2gerrit-2.2.2}/src/github2gerrit/trust.py +0 -0
  81. {github2gerrit-2.2.0 → github2gerrit-2.2.2}/tests/fixtures/__init__.py +0 -0
  82. {github2gerrit-2.2.0 → github2gerrit-2.2.2}/tests/fixtures/make_repo.py +0 -0
  83. {github2gerrit-2.2.0 → github2gerrit-2.2.2}/tests/fixtures/ssh_config_samples.py +0 -0
  84. {github2gerrit-2.2.0 → github2gerrit-2.2.2}/tests/test_action_outputs.py +0 -0
  85. {github2gerrit-2.2.0 → github2gerrit-2.2.2}/tests/test_action_pr_number_handling.py +0 -0
  86. {github2gerrit-2.2.0 → github2gerrit-2.2.2}/tests/test_action_step_validation.py +0 -0
  87. {github2gerrit-2.2.0 → github2gerrit-2.2.2}/tests/test_approver_sources.py +0 -0
  88. {github2gerrit-2.2.0 → github2gerrit-2.2.2}/tests/test_automation_only.py +0 -0
  89. {github2gerrit-2.2.0 → github2gerrit-2.2.2}/tests/test_cache_isolation.py +0 -0
  90. {github2gerrit-2.2.0 → github2gerrit-2.2.2}/tests/test_change_id_deduplication.py +0 -0
  91. {github2gerrit-2.2.0 → github2gerrit-2.2.2}/tests/test_clean_squash_title.py +0 -0
  92. {github2gerrit-2.2.0 → github2gerrit-2.2.2}/tests/test_cli.py +0 -0
  93. {github2gerrit-2.2.0 → github2gerrit-2.2.2}/tests/test_cli_helpers.py +0 -0
  94. {github2gerrit-2.2.0 → github2gerrit-2.2.2}/tests/test_cli_netrc_options.py +0 -0
  95. {github2gerrit-2.2.0 → github2gerrit-2.2.2}/tests/test_cli_outputs_file.py +0 -0
  96. {github2gerrit-2.2.0 → github2gerrit-2.2.2}/tests/test_cli_url_and_dryrun.py +0 -0
  97. {github2gerrit-2.2.0 → github2gerrit-2.2.2}/tests/test_commit_normalization.py +0 -0
  98. {github2gerrit-2.2.0 → github2gerrit-2.2.2}/tests/test_commit_rules.py +0 -0
  99. {github2gerrit-2.2.0 → github2gerrit-2.2.2}/tests/test_config_and_reviewers.py +0 -0
  100. {github2gerrit-2.2.0 → github2gerrit-2.2.2}/tests/test_core_close_pr_policy.py +0 -0
  101. {github2gerrit-2.2.0 → github2gerrit-2.2.2}/tests/test_core_config_and_errors.py +0 -0
  102. {github2gerrit-2.2.0 → github2gerrit-2.2.2}/tests/test_core_gerrit_backref_comment.py +0 -0
  103. {github2gerrit-2.2.0 → github2gerrit-2.2.2}/tests/test_core_gerrit_push_errors.py +0 -0
  104. {github2gerrit-2.2.0 → github2gerrit-2.2.2}/tests/test_core_gerrit_rest_results.py +0 -0
  105. {github2gerrit-2.2.0 → github2gerrit-2.2.2}/tests/test_core_prepare_commits.py +0 -0
  106. {github2gerrit-2.2.0 → github2gerrit-2.2.2}/tests/test_core_shallow_clone.py +0 -0
  107. {github2gerrit-2.2.0 → github2gerrit-2.2.2}/tests/test_core_ssh_setup.py +0 -0
  108. {github2gerrit-2.2.0 → github2gerrit-2.2.2}/tests/test_core_ssrf_protection.py +0 -0
  109. {github2gerrit-2.2.0 → github2gerrit-2.2.2}/tests/test_dependency_supersession.py +0 -0
  110. {github2gerrit-2.2.0 → github2gerrit-2.2.2}/tests/test_email_case_normalization.py +0 -0
  111. {github2gerrit-2.2.0 → github2gerrit-2.2.2}/tests/test_error_codes.py +0 -0
  112. {github2gerrit-2.2.0 → github2gerrit-2.2.2}/tests/test_external_api_framework.py +0 -0
  113. {github2gerrit-2.2.0 → github2gerrit-2.2.2}/tests/test_final_state_reconciliation.py +0 -0
  114. {github2gerrit-2.2.0 → github2gerrit-2.2.2}/tests/test_force_flag_cli.py +0 -0
  115. {github2gerrit-2.2.0 → github2gerrit-2.2.2}/tests/test_fork_approval_gate.py +0 -0
  116. {github2gerrit-2.2.0 → github2gerrit-2.2.2}/tests/test_gerrit_change_id_footer.py +0 -0
  117. {github2gerrit-2.2.0 → github2gerrit-2.2.2}/tests/test_gerrit_change_status_checks.py +0 -0
  118. {github2gerrit-2.2.0 → github2gerrit-2.2.2}/tests/test_gerrit_rest_client.py +0 -0
  119. {github2gerrit-2.2.0 → github2gerrit-2.2.2}/tests/test_gerrit_ssh_abandon.py +0 -0
  120. {github2gerrit-2.2.0 → github2gerrit-2.2.2}/tests/test_gerrit_urls.py +0 -0
  121. {github2gerrit-2.2.0 → github2gerrit-2.2.2}/tests/test_gerrit_urls_more.py +0 -0
  122. {github2gerrit-2.2.0 → github2gerrit-2.2.2}/tests/test_ghe_and_gitreview_args.py +0 -0
  123. {github2gerrit-2.2.0 → github2gerrit-2.2.2}/tests/test_github_api_error_handling.py +0 -0
  124. {github2gerrit-2.2.0 → github2gerrit-2.2.2}/tests/test_github_api_helpers.py +0 -0
  125. {github2gerrit-2.2.0 → github2gerrit-2.2.2}/tests/test_github_api_retry_and_helpers.py +0 -0
  126. {github2gerrit-2.2.0 → github2gerrit-2.2.2}/tests/test_gitutils_helpers.py +0 -0
  127. {github2gerrit-2.2.0 → github2gerrit-2.2.2}/tests/test_mapping_comment_additional.py +0 -0
  128. {github2gerrit-2.2.0 → github2gerrit-2.2.2}/tests/test_mapping_comment_digest_and_backref.py +0 -0
  129. {github2gerrit-2.2.0 → github2gerrit-2.2.2}/tests/test_metadata_and_reconciliation.py +0 -0
  130. {github2gerrit-2.2.0 → github2gerrit-2.2.2}/tests/test_metadata_trailer_separation_bug.py +0 -0
  131. {github2gerrit-2.2.0 → github2gerrit-2.2.2}/tests/test_misc_small_coverage.py +0 -0
  132. {github2gerrit-2.2.0 → github2gerrit-2.2.2}/tests/test_netrc.py +0 -0
  133. {github2gerrit-2.2.0 → github2gerrit-2.2.2}/tests/test_orphan_rest_side_effects.py +0 -0
  134. {github2gerrit-2.2.0 → github2gerrit-2.2.2}/tests/test_pr_command_authorisation.py +0 -0
  135. {github2gerrit-2.2.0 → github2gerrit-2.2.2}/tests/test_pr_commands.py +0 -0
  136. {github2gerrit-2.2.0 → github2gerrit-2.2.2}/tests/test_pr_content_filter.py +0 -0
  137. {github2gerrit-2.2.0 → github2gerrit-2.2.2}/tests/test_pr_content_filter_integration.py +0 -0
  138. {github2gerrit-2.2.0 → github2gerrit-2.2.2}/tests/test_pr_update_detection.py +0 -0
  139. {github2gerrit-2.2.0 → github2gerrit-2.2.2}/tests/test_reconciliation_extracted_module.py +0 -0
  140. {github2gerrit-2.2.0 → github2gerrit-2.2.2}/tests/test_reconciliation_plan_and_orphans.py +0 -0
  141. {github2gerrit-2.2.0 → github2gerrit-2.2.2}/tests/test_reconciliation_scenarios.py +0 -0
  142. {github2gerrit-2.2.0 → github2gerrit-2.2.2}/tests/test_ssh_agent.py +0 -0
  143. {github2gerrit-2.2.0 → github2gerrit-2.2.2}/tests/test_ssh_agent_ownership.py +0 -0
  144. {github2gerrit-2.2.0 → github2gerrit-2.2.2}/tests/test_ssh_artifact_prevention.py +0 -0
  145. {github2gerrit-2.2.0 → github2gerrit-2.2.2}/tests/test_ssh_common.py +0 -0
  146. {github2gerrit-2.2.0 → github2gerrit-2.2.2}/tests/test_ssh_discovery.py +0 -0
  147. {github2gerrit-2.2.0 → github2gerrit-2.2.2}/tests/test_ssh_discovery_dry_run.py +0 -0
  148. {github2gerrit-2.2.0 → github2gerrit-2.2.2}/tests/test_trailers_additional.py +0 -0
  149. {github2gerrit-2.2.0 → github2gerrit-2.2.2}/tests/test_url_parser.py +0 -0
  150. {github2gerrit-2.2.0 → github2gerrit-2.2.2}/tests/test_utils.py +0 -0
  151. {github2gerrit-2.2.0 → github2gerrit-2.2.2}/tests/unit/test_ssh_config_parser.py +0 -0
@@ -64,7 +64,7 @@ repos:
64
64
  types: [yaml]
65
65
 
66
66
  - repo: https://github.com/astral-sh/ruff-pre-commit
67
- rev: e8f7d69b957a30acb2c875078d5fd012de24b64c # frozen: v0.16.7
67
+ rev: 2eeb5678de71a00c0902cbda7105d328432f72cb # frozen: v0.16.8
68
68
  hooks:
69
69
  - id: ruff
70
70
  files: ^(src|scripts|tests)/.+\.py$|^sitecustomize\.py$
@@ -72,6 +72,24 @@ repos:
72
72
  - id: ruff-format
73
73
  files: ^(src|scripts|tests)/.+\.py$|^sitecustomize\.py$
74
74
 
75
+ - repo: local
76
+ hooks:
77
+ - id: sync-mypy-pins
78
+ # Rewrites the mypy hook's exact pins below to the versions
79
+ # uv.lock records, so the two cannot drift. Ordered ahead of the
80
+ # mypy hook so the pins are corrected before mypy is reached,
81
+ # though pre-commit reads this file and builds hook environments
82
+ # before any hook runs: a rewrite fails this run, as any
83
+ # modifying hook does, and the corrected pins take effect on the
84
+ # rerun. Both files come from the same checkout, so the verdict
85
+ # is the same locally and in CI, and a Dependabot lockfile bump
86
+ # fails here on its own pull request rather than on main.
87
+ name: sync mypy hook pins with uv.lock
88
+ entry: python3 scripts/sync_mypy_pins.py
89
+ language: system
90
+ files: ^(\.pre-commit-config\.yaml|uv\.lock)$
91
+ pass_filenames: false
92
+
75
93
  - repo: https://github.com/pre-commit/mirrors-mypy
76
94
  rev: 7ff8d35ae36a7d2b968f2f90b4c723e292e594ee # frozen: v2.3.1
77
95
  hooks:
@@ -100,10 +118,16 @@ repos:
100
118
  # nobody runs locally. That drift is not theoretical: CI once
101
119
  # resolved typer 0.27.2 against a lockfile holding 0.27.1, and the
102
120
  # two disagreed about which module typer.Exit lives in.
103
- # Every version here must equal the one uv.lock records for that
104
- # package, so update both together (after `uv lock --upgrade`, for
105
- # instance). tests/test_precommit_mypy_pins.py compares the two
106
- # files and fails if they diverge in either direction.
121
+ # The versions are not maintained by hand: the sync-mypy-pins hook
122
+ # above rewrites them from uv.lock, so after `uv lock --upgrade` a
123
+ # `prek run sync-mypy-pins --all-files` brings them into step
124
+ # (--all-files, because neither file is staged at that point and
125
+ # the hook would otherwise not be selected). The tests in
126
+ # tests/test_precommit_mypy_pins.py check the list is exact and
127
+ # complete against the imports; they deliberately do not compare
128
+ # versions to the lockfile, since a pull request is tested as
129
+ # merged into main and would otherwise fail for a dependency that
130
+ # moved there, not for anything on the branch.
107
131
  #
108
132
  # These pins do not freeze the whole resolved closure: pip still
109
133
  # picks transitive versions at build time, and listing every
@@ -119,8 +143,9 @@ repos:
119
143
  # runs, and nothing otherwise ties it to the locked one, so an
120
144
  # autoupdate of the mirror or a lockfile-only mypy upgrade would
121
145
  # leave the hook running a different checker in silence. With the
122
- # pin present, the test compares it against uv.lock, and a mirror
123
- # whose rev disagrees fails to install rather than quietly winning.
146
+ # pin present, the sync hook keeps it at the locked version, and a
147
+ # mirror whose rev disagrees fails to install rather than quietly
148
+ # winning.
124
149
  additional_dependencies:
125
150
  - mypy==2.3.1
126
151
  - click==8.5.0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.5
2
2
  Name: github2gerrit
3
- Version: 2.2.0
3
+ Version: 2.2.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
@@ -276,9 +276,9 @@ uvx github2gerrit https://github.com/onap/portal-ng-bff/pull/33
276
276
  | `GERRIT_KNOWN_HOSTS` | No | — | Known hosts entries for Gerrit SSH (auto-populated when empty) |
277
277
  | `GERRIT_SSH_USER_G2G` | No | `""` | Gerrit SSH username; derived when not supplied |
278
278
  | `GERRIT_SSH_USER_G2G_EMAIL` | No | `""` | Gerrit user email address; derived when not supplied |
279
- | `GERRIT_SERVER` | No | `""` | Gerrit server hostname; `.gitreview` preferred |
280
- | `GERRIT_SERVER_PORT` | No | `"29418"` | Gerrit SSH port |
281
- | `GERRIT_PROJECT` | No | `""` | Gerrit project name; `.gitreview` preferred |
279
+ | `GERRIT_SERVER` | No | `""` | Gerrit server hostname; overrides `.gitreview` when set |
280
+ | `GERRIT_SERVER_PORT` | No | `""` | Gerrit SSH port; `.gitreview`'s when unset, else 29418 |
281
+ | `GERRIT_PROJECT` | No | `""` | Gerrit project name; overrides `.gitreview` when set |
282
282
  | `GERRIT_HTTP_BASE_PATH` | No | `""` | HTTP base path for Gerrit REST API (e.g. `/r`) |
283
283
  | `GERRIT_HTTP_USER` | No | `""` | Gerrit HTTP user for REST queries |
284
284
  | `GERRIT_HTTP_PASSWORD` | No | `""` | Gerrit HTTP password/token for REST queries |
@@ -326,14 +326,15 @@ environment variables do not cross the `workflow_call` boundary. See
326
326
  [docs/cli.md](docs/cli.md) for the full option reference and
327
327
  [docs/features.md](docs/features.md) for feature-specific settings.
328
328
 
329
- Nine `G2G_`-prefixed settings can come from repository or organisation
329
+ Ten `G2G_`-prefixed settings can come from repository or organisation
330
330
  **variables**, which the reusable workflow reads and passes to the
331
- action — among them `G2G_TRUSTED_ASSOCIATIONS`, `G2G_TOPIC_PREFIX`
332
- and `G2G_ENABLE_DERIVATION`, plus the `G2G_NO_GERRIT` and
333
- `G2G_DISABLED` kill switches. An organisation can set one once for
334
- every repository beneath it. A workflow calling the composite action
335
- directly does not inherit those variables; map them in with `env:`
336
- yourself. See [docs/cli.md](docs/cli.md) for the full list.
331
+ action — among them `G2G_TRUSTED_ASSOCIATIONS`, `G2G_TOPIC_PREFIX`,
332
+ `G2G_ENABLE_DERIVATION` and the `G2G_RESOLVE_PROJECT_VIA_GERRIT`
333
+ opt-in, plus the `G2G_NO_GERRIT` and `G2G_DISABLED` kill switches. An
334
+ organisation can set one once for every repository beneath it. A
335
+ workflow calling the composite action directly does not inherit those
336
+ variables; map them in with `env:` yourself. See
337
+ [docs/cli.md](docs/cli.md) for the full list.
337
338
 
338
339
  The three `G2G_APPROVER*` inputs widen who may clear the fork approval
339
340
  gate, and each defaults to off. `G2G_INFO_YAML_MATCH_LFID` carries a
@@ -376,7 +377,7 @@ Input defaults match the composite action defaults.
376
377
  | `GERRIT_SSH_USER_G2G` | string | `""` | Gerrit SSH username |
377
378
  | `GERRIT_SSH_USER_G2G_EMAIL` | string | `""` | Gerrit user email address |
378
379
  | `GERRIT_SERVER` | string | `""` | Gerrit server hostname |
379
- | `GERRIT_SERVER_PORT` | string | `"29418"` | Gerrit SSH port |
380
+ | `GERRIT_SERVER_PORT` | string | `""` | Gerrit SSH port; `.gitreview`'s when unset |
380
381
  | `GERRIT_PROJECT` | string | `""` | Gerrit project name |
381
382
  | `GERRIT_HTTP_BASE_PATH` | string | `""` | HTTP base path for Gerrit REST |
382
383
  | `GERRIT_HTTP_USER` | string | `""` | Gerrit HTTP user for REST queries |
@@ -229,9 +229,9 @@ uvx github2gerrit https://github.com/onap/portal-ng-bff/pull/33
229
229
  | `GERRIT_KNOWN_HOSTS` | No | — | Known hosts entries for Gerrit SSH (auto-populated when empty) |
230
230
  | `GERRIT_SSH_USER_G2G` | No | `""` | Gerrit SSH username; derived when not supplied |
231
231
  | `GERRIT_SSH_USER_G2G_EMAIL` | No | `""` | Gerrit user email address; derived when not supplied |
232
- | `GERRIT_SERVER` | No | `""` | Gerrit server hostname; `.gitreview` preferred |
233
- | `GERRIT_SERVER_PORT` | No | `"29418"` | Gerrit SSH port |
234
- | `GERRIT_PROJECT` | No | `""` | Gerrit project name; `.gitreview` preferred |
232
+ | `GERRIT_SERVER` | No | `""` | Gerrit server hostname; overrides `.gitreview` when set |
233
+ | `GERRIT_SERVER_PORT` | No | `""` | Gerrit SSH port; `.gitreview`'s when unset, else 29418 |
234
+ | `GERRIT_PROJECT` | No | `""` | Gerrit project name; overrides `.gitreview` when set |
235
235
  | `GERRIT_HTTP_BASE_PATH` | No | `""` | HTTP base path for Gerrit REST API (e.g. `/r`) |
236
236
  | `GERRIT_HTTP_USER` | No | `""` | Gerrit HTTP user for REST queries |
237
237
  | `GERRIT_HTTP_PASSWORD` | No | `""` | Gerrit HTTP password/token for REST queries |
@@ -279,14 +279,15 @@ environment variables do not cross the `workflow_call` boundary. See
279
279
  [docs/cli.md](docs/cli.md) for the full option reference and
280
280
  [docs/features.md](docs/features.md) for feature-specific settings.
281
281
 
282
- Nine `G2G_`-prefixed settings can come from repository or organisation
282
+ Ten `G2G_`-prefixed settings can come from repository or organisation
283
283
  **variables**, which the reusable workflow reads and passes to the
284
- action — among them `G2G_TRUSTED_ASSOCIATIONS`, `G2G_TOPIC_PREFIX`
285
- and `G2G_ENABLE_DERIVATION`, plus the `G2G_NO_GERRIT` and
286
- `G2G_DISABLED` kill switches. An organisation can set one once for
287
- every repository beneath it. A workflow calling the composite action
288
- directly does not inherit those variables; map them in with `env:`
289
- yourself. See [docs/cli.md](docs/cli.md) for the full list.
284
+ action — among them `G2G_TRUSTED_ASSOCIATIONS`, `G2G_TOPIC_PREFIX`,
285
+ `G2G_ENABLE_DERIVATION` and the `G2G_RESOLVE_PROJECT_VIA_GERRIT`
286
+ opt-in, plus the `G2G_NO_GERRIT` and `G2G_DISABLED` kill switches. An
287
+ organisation can set one once for every repository beneath it. A
288
+ workflow calling the composite action directly does not inherit those
289
+ variables; map them in with `env:` yourself. See
290
+ [docs/cli.md](docs/cli.md) for the full list.
290
291
 
291
292
  The three `G2G_APPROVER*` inputs widen who may clear the fork approval
292
293
  gate, and each defaults to off. `G2G_INFO_YAML_MATCH_LFID` carries a
@@ -329,7 +330,7 @@ Input defaults match the composite action defaults.
329
330
  | `GERRIT_SSH_USER_G2G` | string | `""` | Gerrit SSH username |
330
331
  | `GERRIT_SSH_USER_G2G_EMAIL` | string | `""` | Gerrit user email address |
331
332
  | `GERRIT_SERVER` | string | `""` | Gerrit server hostname |
332
- | `GERRIT_SERVER_PORT` | string | `"29418"` | Gerrit SSH port |
333
+ | `GERRIT_SERVER_PORT` | string | `""` | Gerrit SSH port; `.gitreview`'s when unset |
333
334
  | `GERRIT_PROJECT` | string | `""` | Gerrit project name |
334
335
  | `GERRIT_HTTP_BASE_PATH` | string | `""` | HTTP base path for Gerrit REST |
335
336
  | `GERRIT_HTTP_USER` | string | `""` | Gerrit HTTP user for REST queries |
@@ -133,9 +133,9 @@ inputs:
133
133
  required: false
134
134
  default: ""
135
135
  GERRIT_SERVER_PORT:
136
- description: "Gerrit server SSH TCP port"
136
+ description: "Gerrit server SSH TCP port; .gitreview's when unset, else 29418"
137
137
  required: false
138
- default: "29418"
138
+ default: ""
139
139
  GERRIT_PROJECT:
140
140
  description: "Gerrit project; optional if .gitreview exists"
141
141
  required: false
@@ -266,7 +266,7 @@ runs:
266
266
  - name: "Setup uv"
267
267
  if: steps.disabled-check.outputs.disabled != 'true'
268
268
  # yamllint disable-line rule:line-length
269
- uses: astral-sh/setup-uv@20cfd1bf945f4377ade1205e4dbc17946fc9a30d # v10.0.1
269
+ uses: astral-sh/setup-uv@bec219d24cd3e171d82865faccec33120bb574f4 # v10.1.0
270
270
  with:
271
271
  enable-cache: false
272
272
 
@@ -100,9 +100,9 @@ set by GitHub Actions) and undergo proper boolean parsing.
100
100
 
101
101
  | Flag(s) | Env var | Default | Description |
102
102
  | ------------------------------------ | --------------------------- | ------- | ------------------------------------------------------------ |
103
- | `--gerrit-server TEXT` | `GERRIT_SERVER` | `""` | Gerrit server hostname (optional; `.gitreview` preferred) |
104
- | `--gerrit-server-port INTEGER` | `GERRIT_SERVER_PORT` | `29418` | Gerrit SSH port |
105
- | `--gerrit-project TEXT` | `GERRIT_PROJECT` | `""` | Gerrit project (optional; `.gitreview` preferred) |
103
+ | `--gerrit-server TEXT` | `GERRIT_SERVER` | `""` | Gerrit server hostname (optional; overrides `.gitreview`) |
104
+ | `--gerrit-server-port INTEGER` | `GERRIT_SERVER_PORT` | unset | Gerrit SSH port; `.gitreview`'s when unset, else 29418 |
105
+ | `--gerrit-project TEXT` | `GERRIT_PROJECT` | `""` | Gerrit project (optional; overrides `.gitreview` when set) |
106
106
  | `--gerrit-ssh-user-g2g TEXT` | `GERRIT_SSH_USER_G2G` | `""` | Gerrit SSH username (e.g., automation bot account) |
107
107
  | `--gerrit-ssh-user-g2g-email TEXT` | `GERRIT_SSH_USER_G2G_EMAIL` | `""` | Email address for the Gerrit SSH user |
108
108
  | `--gerrit-ssh-privkey-g2g TEXT` | `GERRIT_SSH_PRIVKEY_G2G` | `""` | SSH private key content used to authenticate to Gerrit |
@@ -160,11 +160,12 @@ Some settings have no CLI flag and use environment variables.
160
160
  When running the tool as a GitHub Action, how you set one depends on the
161
161
  integration:
162
162
 
163
- - **Reusable workflow** — the workflow reads these nine names from repository
163
+ - **Reusable workflow** — the workflow reads these ten names from repository
164
164
  or organisation **variables**:
165
165
  `G2G_TRUSTED_ASSOCIATIONS`, `G2G_TOPIC_PREFIX`, `G2G_SKIP_GERRIT_COMMENTS`,
166
166
  `G2G_ENABLE_DERIVATION`, `G2G_ANON_SUPERSEDE_FALLBACK`, `G2G_SHOW_PROGRESS`,
167
- `G2G_LOG_LEVEL`, `G2G_NO_GERRIT` and `G2G_DISABLED`.
167
+ `G2G_LOG_LEVEL`, `G2G_RESOLVE_PROJECT_VIA_GERRIT`, `G2G_NO_GERRIT` and
168
+ `G2G_DISABLED`.
168
169
 
169
170
  The last two predate the rest and behave differently: `G2G_NO_GERRIT` is
170
171
  also a workflow input, taking the input first and falling back to the
@@ -187,34 +188,35 @@ forwarded setting treats blank as unset and keeps its documented default.
187
188
 
188
189
  <!-- markdownlint-disable MD013 -->
189
190
 
190
- | Variable | Default | Description |
191
- | ----------------------------- | ------------------------------------------- | -------------------------------------------------------------------------------- |
192
- | `G2G_CONFIG_PATH` | `~/.config/github2gerrit/configuration.txt` | Path to the per-organization configuration file |
193
- | `G2G_LOG_LEVEL` | `WARNING` | Logging level; set `DEBUG` for verbose output |
194
- | `G2G_TOPIC_PREFIX` | `GH` | Prefix used when generating Gerrit topics |
195
- | `G2G_SKIP_GERRIT_COMMENTS` | `false` | Skip posting back-reference comments on Gerrit changes |
196
- | `G2G_TRUSTED_ASSOCIATIONS` | `OWNER,MEMBER,COLLABORATOR` | Author associations trusted to issue `@github2gerrit` comment directives |
197
- | `G2G_ENABLE_DERIVATION` | `true` | Enable automatic derivation of Gerrit parameters from organization defaults |
198
- | `G2G_AUTO_SAVE_CONFIG` | context-dependent | Save derived parameters back to the configuration file |
199
- | `G2G_RESPECT_USER_SSH` | `false` (`true` in direct URL mode) | Use the local user's SSH configuration and keys instead of provided key material |
200
- | `G2G_USE_SSH_AGENT` | `true` | Use SSH agent authentication; set `false` to force file-based SSH keys |
201
- | `G2G_NO_GERRIT` | `false` | Run the full pipeline without contacting Gerrit (forces dry-run behavior) |
202
- | `G2G_DISABLED` | `false` | Exit immediately with success without processing anything |
203
- | `CLEANUP_ABANDONED` | `true` | Close GitHub PRs whose Gerrit changes have status abandoned |
204
- | `CLEANUP_GERRIT` | `true` | Abandon Gerrit changes for closed GitHub PRs |
205
- | `PR_NUMBER` | unset | Pull request number to process in CI/CD mode (`0` means bulk mode) |
206
- | `SYNC_ALL_OPEN_PRS` | `false` | Process all open PRs in the repository (bulk mode) |
207
- | `GERRIT_HTTP_USER` | unset | Username for the Gerrit REST API (when required) |
208
- | `GERRIT_HTTP_PASSWORD` | unset | HTTP password/token for the Gerrit REST API |
209
- | `GERRIT_HTTP_BASE_PATH` | unset | Gerrit REST base path for non-standard deployments (e.g., `/r`) |
210
- | `GITHUB_TOKEN` | unset | GitHub API token; required for PR queries, comments, and closing PRs |
211
- | `GH_TOKEN` | unset | Fallback source for `GITHUB_TOKEN` when the latter is unset |
212
- | `GERRIT_CHANGE_URL` | unset | Gerrit change URL for Gerrit-event dispatch mode (close the source PR) |
213
- | `GERRIT_EVENT_TYPE` | unset | Gerrit event type for dispatch mode (`change-merged` or `change-abandoned`) |
214
- | `GERRIT_BRANCH` | unset | Gerrit branch for dispatch mode change queries |
215
- | `G2G_DRYRUN_DISABLE_NETWORK` | `false` | Skip DNS/network checks in dry-run; set automatically by `G2G_NO_GERRIT` |
216
- | `G2G_ANON_SUPERSEDE_FALLBACK` | `true` | Allow anonymous supersession queries when Gerrit credentials are unavailable |
217
- | `VERIFY_DIGEST_STRICT` | `true` | Fail (rather than warn) on reconciliation digest mismatch after push |
191
+ | Variable | Default | Description |
192
+ | -------------------------------- | ------------------------------------------- | --------------------------------------------------------------------------------- |
193
+ | `G2G_CONFIG_PATH` | `~/.config/github2gerrit/configuration.txt` | Path to the per-organization configuration file |
194
+ | `G2G_LOG_LEVEL` | `WARNING` | Logging level; set `DEBUG` for verbose output |
195
+ | `G2G_TOPIC_PREFIX` | `GH` | Prefix used when generating Gerrit topics |
196
+ | `G2G_RESOLVE_PROJECT_VIA_GERRIT` | `false` | Without a `.gitreview`, ask Gerrit which project a hyphenated GitHub name maps to |
197
+ | `G2G_SKIP_GERRIT_COMMENTS` | `false` | Skip posting back-reference comments on Gerrit changes |
198
+ | `G2G_TRUSTED_ASSOCIATIONS` | `OWNER,MEMBER,COLLABORATOR` | Author associations trusted to issue `@github2gerrit` comment directives |
199
+ | `G2G_ENABLE_DERIVATION` | `true` | Enable automatic derivation of Gerrit parameters from organization defaults |
200
+ | `G2G_AUTO_SAVE_CONFIG` | context-dependent | Save derived parameters back to the configuration file |
201
+ | `G2G_RESPECT_USER_SSH` | `false` (`true` in direct URL mode) | Use the local user's SSH configuration and keys instead of provided key material |
202
+ | `G2G_USE_SSH_AGENT` | `true` | Use SSH agent authentication; set `false` to force file-based SSH keys |
203
+ | `G2G_NO_GERRIT` | `false` | Run the full pipeline without contacting Gerrit (forces dry-run behavior) |
204
+ | `G2G_DISABLED` | `false` | Exit immediately with success without processing anything |
205
+ | `CLEANUP_ABANDONED` | `true` | Close GitHub PRs whose Gerrit changes have status abandoned |
206
+ | `CLEANUP_GERRIT` | `true` | Abandon Gerrit changes for closed GitHub PRs |
207
+ | `PR_NUMBER` | unset | Pull request number to process in CI/CD mode (`0` means bulk mode) |
208
+ | `SYNC_ALL_OPEN_PRS` | `false` | Process all open PRs in the repository (bulk mode) |
209
+ | `GERRIT_HTTP_USER` | unset | Username for the Gerrit REST API (when required) |
210
+ | `GERRIT_HTTP_PASSWORD` | unset | HTTP password/token for the Gerrit REST API |
211
+ | `GERRIT_HTTP_BASE_PATH` | unset | Gerrit REST base path for non-standard deployments (e.g., `/r`) |
212
+ | `GITHUB_TOKEN` | unset | GitHub API token; required for PR queries, comments, and closing PRs |
213
+ | `GH_TOKEN` | unset | Fallback source for `GITHUB_TOKEN` when the latter is unset |
214
+ | `GERRIT_CHANGE_URL` | unset | Gerrit change URL for Gerrit-event dispatch mode (close the source PR) |
215
+ | `GERRIT_EVENT_TYPE` | unset | Gerrit event type for dispatch mode (`change-merged` or `change-abandoned`) |
216
+ | `GERRIT_BRANCH` | unset | Gerrit branch for dispatch mode change queries |
217
+ | `G2G_DRYRUN_DISABLE_NETWORK` | `false` | Skip DNS/network checks in dry-run; set automatically by `G2G_NO_GERRIT` |
218
+ | `G2G_ANON_SUPERSEDE_FALLBACK` | `true` | Allow anonymous supersession queries when Gerrit credentials are unavailable |
219
+ | `VERIFY_DIGEST_STRICT` | `true` | Fail (rather than warn) on reconciliation digest mismatch after push |
218
220
 
219
221
  <!-- markdownlint-enable MD013 -->
220
222
 
@@ -20,6 +20,7 @@ action in detail. For a quick start and the full inputs table, see the
20
20
  - [Duplicate Detection](#duplicate-detection)
21
21
  - [Commit Message Normalization](#commit-message-normalization)
22
22
  - [Change-ID Reconciliation](#change-id-reconciliation)
23
+ - [Repository and Project Names](#repository-and-project-names)
23
24
  - [Configuration](#configuration)
24
25
  - [Behavior Details](#behavior-details)
25
26
 
@@ -402,16 +403,23 @@ signal never earns a fork unwarranted trust.
402
403
 
403
404
  Resolution order for a fork pull request:
404
405
 
405
- 1. `.gitreview` from the base repository at the pull request's base branch,
406
+ 1. Explicit `GERRIT_SERVER` / `GERRIT_SERVER_PORT` / `GERRIT_PROJECT`
407
+ inputs, each for its own field — an operator configured them for this
408
+ run. The port input has no default: the action and the CLI pass none
409
+ when the caller gave none, so a set port is distinguishable from an
410
+ unset one. 29418 applies only when neither an input nor `.gitreview`
411
+ names a port.
412
+ 2. `.gitreview` from the base repository at the pull request's base branch,
406
413
  via the GitHub API or `raw.githubusercontent.com`
407
- 2. Explicit `GERRIT_SERVER` / `GERRIT_SERVER_PORT` / `GERRIT_PROJECT` inputs
408
414
  3. Per-organization configuration file
409
415
  4. Derivation from the organization name (`gerrit.[org].org`)
410
416
 
411
- The lookup stops at the base branch. It does not fall back to the repository
412
- default branch, and it does not read `.gitreview` through the API without an
413
- authoritative base ref, because either would answer for a branch the pull
414
- request does not target — and `.gitreview` outranks the explicit inputs.
417
+ A value the tool's own derivation exported through those same variables does
418
+ not count as explicit; the tool tracks which is which. The lookup stops at the
419
+ base branch. It does not fall back to the repository default branch, and it
420
+ does not read `.gitreview` through the API without an authoritative base ref,
421
+ because either would answer for a branch the pull request does not target —
422
+ and `.gitreview` outranks everything but an explicit input.
415
423
 
416
424
  The base repository's copy carries the same authority and lies outside an
417
425
  attacker's reach, so this costs no accuracy. Skipping straight to derivation
@@ -421,7 +429,9 @@ repositories whose name contains a hyphen that does not mark a path separator.
421
429
  For the same reason, the tool drops branch names that originate in the fork
422
430
  (`GITHUB_HEAD_REF` and the pull request head ref) from base-repository
423
431
  lookups. Duplicate detection, which resolves `.gitreview` independently and
424
- earlier, applies the same rule.
432
+ earlier, applies the same rule, and so does parameter derivation: for an
433
+ untrusted pull request it declines the workspace copy of `.gitreview` and the
434
+ `master`/`main` fallbacks alike, reading the base branch only.
425
435
 
426
436
  Same-repository pull requests keep their previous behaviour and still read
427
437
  `.gitreview` from the pull request tree.
@@ -828,6 +838,69 @@ github2gerrit \
828
838
  https://github.com/owner/repo/pull/123
829
839
  ```
830
840
 
841
+ ## Repository and Project Names
842
+
843
+ Gerrit projects are paths, such as `multicloud/openstack`; GitHub repository
844
+ names are flat, such as `multicloud-openstack`. Linux Foundation mirrors
845
+ flatten a path by replacing every `/` with `-`. One module, `project_names`,
846
+ handles that mapping for the whole tool, so every part of it agrees on what a
847
+ name means.
848
+
849
+ ### One direction is exact, the other is not
850
+
851
+ Gerrit to GitHub is deterministic. GitHub to Gerrit is **ambiguous**: a hyphen
852
+ is both the flattened separator and an ordinary character inside a segment.
853
+ On gerrit.onap.org, `aai-aai-common` is `aai/aai-common`, not
854
+ `aai/aai/common`, and nothing in the name can tell you which.
855
+
856
+ So the tool resolves the Gerrit project from the best source it has, in this
857
+ order:
858
+
859
+ 1. An explicit `GERRIT_PROJECT` input — an operator said so. A value the
860
+ tool's own parameter derivation exported through the same variable does
861
+ not count; the tool tracks which is which.
862
+ 2. The repository's `.gitreview` — the repository says so. For a pull request
863
+ the tool reads this from the **base** repository at the base ref, never
864
+ from a fork; see [Gerrit target resolution](#gerrit-target-resolution).
865
+ 3. Gerrit's own project list, when you enable
866
+ `G2G_RESOLVE_PROJECT_VIA_GERRIT` — the server says so. The tool checks
867
+ every reading of the hyphens against `GET /projects/?p=<first segment>`;
868
+ exactly one match resolves it, and on two matches the tool refuses to
869
+ choose.
870
+ 4. A project from the per-organization configuration file, or one an earlier
871
+ derivation pass exported — somebody wrote it down, but nothing confirms
872
+ it for this repository.
873
+ 5. A guess that every hyphen is a separator, logged as a guess. A name with
874
+ no hyphens has only one reading and is not a guess.
875
+
876
+ The tool resolves the project once per run and uses the result both for the
877
+ Gerrit topic and for the push target, so the two cannot disagree. A real run
878
+ refuses to push to a guess: with no `.gitreview`, no `GERRIT_PROJECT`, and a
879
+ hyphenated name, it stops with an error naming the ambiguity and the three
880
+ ways to settle it. This holds for direct URL invocations too, since a URL
881
+ names the GitHub side and says nothing about the Gerrit project. Dry runs
882
+ proceed on the guess, since they push nothing. Queries — the close handler,
883
+ the sweeps — still use the guess, because a wrong query costs nothing.
884
+
885
+ Every Linux Foundation repository carries a `.gitreview`, so in practice step
886
+ 2 answers. Step 3 is off by default because it adds a network call to name
887
+ resolution; enable it for repositories that have no `.gitreview` and whose
888
+ names contain hyphens inside segments. It applies wherever the tool resolves a
889
+ project, including the closed-pull-request handler and the cleanup sweeps,
890
+ reads the opt-in from the configuration file as well as the environment, asks
891
+ each server once per prefix per run, and stays off under `G2G_NO_GERRIT`, which
892
+ promises no Gerrit calls at all.
893
+
894
+ ### Why this matters for cleanup
895
+
896
+ The close handler, the bulk sweep and duplicate detection all query Gerrit
897
+ with `project:<name>`. A wrong name matches nothing and the tool reports
898
+ "no change found" rather than an error — which is how 239 changes across 43
899
+ ONAP projects stayed open after their pull requests closed (#441). The tool
900
+ now resolves the project from `.gitreview` before any of those paths run,
901
+ reports at INFO level when it finds no change, naming the project it asked
902
+ about, and reports a failed lookup as a failure rather than as "no change".
903
+
831
904
  ## Configuration
832
905
 
833
906
  ### Configuration Precedence
@@ -940,7 +1013,12 @@ provided, the tool derives them from these sources, in priority order:
940
1013
 
941
1014
  Organization-based pattern, from the `ORGANIZATION` value:
942
1015
 
943
- - Gerrit server: `gerrit.{organization}.org` (or from config file)
1016
+ - Gerrit server: the repository's `.gitreview` host when the file exists,
1017
+ else the configuration file's `GERRIT_SERVER`, else
1018
+ `gerrit.{organization}.org`. The derived host travels with the derived
1019
+ project as one target, because the closed-pull-request handler queries
1020
+ them together and the pipeline pushes to the `.gitreview` host whenever
1021
+ the file exists.
944
1022
  - SSH username: `{organization}.gh2gerrit`
945
1023
  - Email: `releng+{organization}-gh2gerrit@linuxfoundation.org`
946
1024