github2gerrit 1.0.9__tar.gz → 1.2.0__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- {github2gerrit-1.0.9 → github2gerrit-1.2.0}/.pre-commit-config.yaml +14 -9
- {github2gerrit-1.0.9 → github2gerrit-1.2.0}/PKG-INFO +1 -1
- {github2gerrit-1.0.9 → github2gerrit-1.2.0}/action.yaml +53 -11
- {github2gerrit-1.0.9 → github2gerrit-1.2.0}/pyproject.toml +1 -13
- {github2gerrit-1.0.9 → github2gerrit-1.2.0}/src/github2gerrit/cli.py +110 -27
- {github2gerrit-1.0.9 → github2gerrit-1.2.0}/src/github2gerrit/core.py +65 -11
- {github2gerrit-1.0.9 → github2gerrit-1.2.0}/tests/test_cli.py +58 -0
- {github2gerrit-1.0.9 → github2gerrit-1.2.0}/tests/test_cli_outputs_file.py +5 -0
- {github2gerrit-1.0.9 → github2gerrit-1.2.0}/tests/test_cli_url_and_dryrun.py +3 -0
- {github2gerrit-1.0.9 → github2gerrit-1.2.0}/tests/test_core_config_and_errors.py +1 -1
- {github2gerrit-1.0.9 → github2gerrit-1.2.0}/tests/test_core_integration_fixture_repo.py +8 -2
- {github2gerrit-1.0.9 → github2gerrit-1.2.0}/tests/test_core_ssrf_protection.py +32 -12
- github2gerrit-1.2.0/tests/test_dns_validation_and_no_gerrit.py +475 -0
- {github2gerrit-1.0.9 → github2gerrit-1.2.0}/uv.lock +81 -81
- {github2gerrit-1.0.9 → github2gerrit-1.2.0}/.editorconfig +0 -0
- {github2gerrit-1.0.9 → github2gerrit-1.2.0}/.gitignore +0 -0
- {github2gerrit-1.0.9 → github2gerrit-1.2.0}/.gitlint +0 -0
- {github2gerrit-1.0.9 → github2gerrit-1.2.0}/.markdownlint.yaml +0 -0
- {github2gerrit-1.0.9 → github2gerrit-1.2.0}/.readthedocs.yml +0 -0
- {github2gerrit-1.0.9 → github2gerrit-1.2.0}/.yamllint +0 -0
- {github2gerrit-1.0.9 → github2gerrit-1.2.0}/LICENSE +0 -0
- {github2gerrit-1.0.9 → github2gerrit-1.2.0}/LICENSES/Apache-2.0.txt +0 -0
- {github2gerrit-1.0.9 → github2gerrit-1.2.0}/README.md +0 -0
- {github2gerrit-1.0.9 → github2gerrit-1.2.0}/REUSE.toml +0 -0
- {github2gerrit-1.0.9 → github2gerrit-1.2.0}/docs/COMMIT_RULES.md +0 -0
- {github2gerrit-1.0.9 → github2gerrit-1.2.0}/docs/COMPOSITE_ACTION_TESTING.md +0 -0
- {github2gerrit-1.0.9 → github2gerrit-1.2.0}/docs/PR_UPDATE_IMPLEMENTATION.md +0 -0
- {github2gerrit-1.0.9 → github2gerrit-1.2.0}/docs/RELEASE-v0.2.0.md +0 -0
- {github2gerrit-1.0.9 → github2gerrit-1.2.0}/docs/github2gerrit_token_permissions_classic.png +0 -0
- {github2gerrit-1.0.9 → github2gerrit-1.2.0}/sitecustomize.py +0 -0
- {github2gerrit-1.0.9 → github2gerrit-1.2.0}/src/github2gerrit/__init__.py +0 -0
- {github2gerrit-1.0.9 → github2gerrit-1.2.0}/src/github2gerrit/commit_normalization.py +0 -0
- {github2gerrit-1.0.9 → github2gerrit-1.2.0}/src/github2gerrit/commit_rules.py +0 -0
- {github2gerrit-1.0.9 → github2gerrit-1.2.0}/src/github2gerrit/config.py +0 -0
- {github2gerrit-1.0.9 → github2gerrit-1.2.0}/src/github2gerrit/constants.py +0 -0
- {github2gerrit-1.0.9 → github2gerrit-1.2.0}/src/github2gerrit/duplicate_detection.py +0 -0
- {github2gerrit-1.0.9 → github2gerrit-1.2.0}/src/github2gerrit/error_codes.py +0 -0
- {github2gerrit-1.0.9 → github2gerrit-1.2.0}/src/github2gerrit/external_api.py +0 -0
- {github2gerrit-1.0.9 → github2gerrit-1.2.0}/src/github2gerrit/gerrit_pr_closer.py +0 -0
- {github2gerrit-1.0.9 → github2gerrit-1.2.0}/src/github2gerrit/gerrit_query.py +0 -0
- {github2gerrit-1.0.9 → github2gerrit-1.2.0}/src/github2gerrit/gerrit_rest.py +0 -0
- {github2gerrit-1.0.9 → github2gerrit-1.2.0}/src/github2gerrit/gerrit_urls.py +0 -0
- {github2gerrit-1.0.9 → github2gerrit-1.2.0}/src/github2gerrit/github_api.py +0 -0
- {github2gerrit-1.0.9 → github2gerrit-1.2.0}/src/github2gerrit/gitreview.py +0 -0
- {github2gerrit-1.0.9 → github2gerrit-1.2.0}/src/github2gerrit/gitutils.py +0 -0
- {github2gerrit-1.0.9 → github2gerrit-1.2.0}/src/github2gerrit/mapping_comment.py +0 -0
- {github2gerrit-1.0.9 → github2gerrit-1.2.0}/src/github2gerrit/models.py +0 -0
- {github2gerrit-1.0.9 → github2gerrit-1.2.0}/src/github2gerrit/netrc.py +0 -0
- {github2gerrit-1.0.9 → github2gerrit-1.2.0}/src/github2gerrit/orchestrator/__init__.py +0 -0
- {github2gerrit-1.0.9 → github2gerrit-1.2.0}/src/github2gerrit/orchestrator/reconciliation.py +0 -0
- {github2gerrit-1.0.9 → github2gerrit-1.2.0}/src/github2gerrit/pr_commands.py +0 -0
- {github2gerrit-1.0.9 → github2gerrit-1.2.0}/src/github2gerrit/pr_content_filter.py +0 -0
- {github2gerrit-1.0.9 → github2gerrit-1.2.0}/src/github2gerrit/reconcile_matcher.py +0 -0
- {github2gerrit-1.0.9 → github2gerrit-1.2.0}/src/github2gerrit/rich_display.py +0 -0
- {github2gerrit-1.0.9 → github2gerrit-1.2.0}/src/github2gerrit/rich_logging.py +0 -0
- {github2gerrit-1.0.9 → github2gerrit-1.2.0}/src/github2gerrit/similarity.py +0 -0
- {github2gerrit-1.0.9 → github2gerrit-1.2.0}/src/github2gerrit/ssh_agent_setup.py +0 -0
- {github2gerrit-1.0.9 → github2gerrit-1.2.0}/src/github2gerrit/ssh_common.py +0 -0
- {github2gerrit-1.0.9 → github2gerrit-1.2.0}/src/github2gerrit/ssh_config_parser.py +0 -0
- {github2gerrit-1.0.9 → github2gerrit-1.2.0}/src/github2gerrit/ssh_discovery.py +0 -0
- {github2gerrit-1.0.9 → github2gerrit-1.2.0}/src/github2gerrit/trailers.py +0 -0
- {github2gerrit-1.0.9 → github2gerrit-1.2.0}/src/github2gerrit/utils.py +0 -0
- {github2gerrit-1.0.9 → github2gerrit-1.2.0}/tests/conftest.py +0 -0
- {github2gerrit-1.0.9 → github2gerrit-1.2.0}/tests/fixtures/__init__.py +0 -0
- {github2gerrit-1.0.9 → github2gerrit-1.2.0}/tests/fixtures/make_repo.py +0 -0
- {github2gerrit-1.0.9 → github2gerrit-1.2.0}/tests/fixtures/ssh_config_samples.py +0 -0
- {github2gerrit-1.0.9 → github2gerrit-1.2.0}/tests/test_action_environment_mapping.py +0 -0
- {github2gerrit-1.0.9 → github2gerrit-1.2.0}/tests/test_action_outputs.py +0 -0
- {github2gerrit-1.0.9 → github2gerrit-1.2.0}/tests/test_action_pr_number_handling.py +0 -0
- {github2gerrit-1.0.9 → github2gerrit-1.2.0}/tests/test_action_step_validation.py +0 -0
- {github2gerrit-1.0.9 → github2gerrit-1.2.0}/tests/test_automation_only.py +0 -0
- {github2gerrit-1.0.9 → github2gerrit-1.2.0}/tests/test_change_id_deduplication.py +0 -0
- {github2gerrit-1.0.9 → github2gerrit-1.2.0}/tests/test_cli_helpers.py +0 -0
- {github2gerrit-1.0.9 → github2gerrit-1.2.0}/tests/test_cli_netrc_options.py +0 -0
- {github2gerrit-1.0.9 → github2gerrit-1.2.0}/tests/test_commit_normalization.py +0 -0
- {github2gerrit-1.0.9 → github2gerrit-1.2.0}/tests/test_commit_rules.py +0 -0
- {github2gerrit-1.0.9 → github2gerrit-1.2.0}/tests/test_composite_action_coverage.py +0 -0
- {github2gerrit-1.0.9 → github2gerrit-1.2.0}/tests/test_config_and_reviewers.py +0 -0
- {github2gerrit-1.0.9 → github2gerrit-1.2.0}/tests/test_config_helpers.py +0 -0
- {github2gerrit-1.0.9 → github2gerrit-1.2.0}/tests/test_core_close_pr_policy.py +0 -0
- {github2gerrit-1.0.9 → github2gerrit-1.2.0}/tests/test_core_gerrit_backref_comment.py +0 -0
- {github2gerrit-1.0.9 → github2gerrit-1.2.0}/tests/test_core_gerrit_push_errors.py +0 -0
- {github2gerrit-1.0.9 → github2gerrit-1.2.0}/tests/test_core_gerrit_rest_results.py +0 -0
- {github2gerrit-1.0.9 → github2gerrit-1.2.0}/tests/test_core_prepare_commits.py +0 -0
- {github2gerrit-1.0.9 → github2gerrit-1.2.0}/tests/test_core_shallow_clone.py +0 -0
- {github2gerrit-1.0.9 → github2gerrit-1.2.0}/tests/test_core_ssh_setup.py +0 -0
- {github2gerrit-1.0.9 → github2gerrit-1.2.0}/tests/test_duplicate_detection.py +0 -0
- {github2gerrit-1.0.9 → github2gerrit-1.2.0}/tests/test_email_case_normalization.py +0 -0
- {github2gerrit-1.0.9 → github2gerrit-1.2.0}/tests/test_error_codes.py +0 -0
- {github2gerrit-1.0.9 → github2gerrit-1.2.0}/tests/test_external_api_framework.py +0 -0
- {github2gerrit-1.0.9 → github2gerrit-1.2.0}/tests/test_force_flag_cli.py +0 -0
- {github2gerrit-1.0.9 → github2gerrit-1.2.0}/tests/test_gerrit_change_id_footer.py +0 -0
- {github2gerrit-1.0.9 → github2gerrit-1.2.0}/tests/test_gerrit_change_status_checks.py +0 -0
- {github2gerrit-1.0.9 → github2gerrit-1.2.0}/tests/test_gerrit_pr_closer.py +0 -0
- {github2gerrit-1.0.9 → github2gerrit-1.2.0}/tests/test_gerrit_rest_client.py +0 -0
- {github2gerrit-1.0.9 → github2gerrit-1.2.0}/tests/test_gerrit_urls.py +0 -0
- {github2gerrit-1.0.9 → github2gerrit-1.2.0}/tests/test_gerrit_urls_more.py +0 -0
- {github2gerrit-1.0.9 → github2gerrit-1.2.0}/tests/test_ghe_and_gitreview_args.py +0 -0
- {github2gerrit-1.0.9 → github2gerrit-1.2.0}/tests/test_github_api_error_handling.py +0 -0
- {github2gerrit-1.0.9 → github2gerrit-1.2.0}/tests/test_github_api_helpers.py +0 -0
- {github2gerrit-1.0.9 → github2gerrit-1.2.0}/tests/test_github_api_retry_and_helpers.py +0 -0
- {github2gerrit-1.0.9 → github2gerrit-1.2.0}/tests/test_gitreview.py +0 -0
- {github2gerrit-1.0.9 → github2gerrit-1.2.0}/tests/test_gitutils_helpers.py +0 -0
- {github2gerrit-1.0.9 → github2gerrit-1.2.0}/tests/test_issue_157_regressions.py +0 -0
- {github2gerrit-1.0.9 → github2gerrit-1.2.0}/tests/test_mapping_comment_additional.py +0 -0
- {github2gerrit-1.0.9 → github2gerrit-1.2.0}/tests/test_mapping_comment_digest_and_backref.py +0 -0
- {github2gerrit-1.0.9 → github2gerrit-1.2.0}/tests/test_metadata_and_reconciliation.py +0 -0
- {github2gerrit-1.0.9 → github2gerrit-1.2.0}/tests/test_metadata_trailer_separation_bug.py +0 -0
- {github2gerrit-1.0.9 → github2gerrit-1.2.0}/tests/test_misc_small_coverage.py +0 -0
- {github2gerrit-1.0.9 → github2gerrit-1.2.0}/tests/test_netrc.py +0 -0
- {github2gerrit-1.0.9 → github2gerrit-1.2.0}/tests/test_orphan_rest_side_effects.py +0 -0
- {github2gerrit-1.0.9 → github2gerrit-1.2.0}/tests/test_pr_commands.py +0 -0
- {github2gerrit-1.0.9 → github2gerrit-1.2.0}/tests/test_pr_content_filter.py +0 -0
- {github2gerrit-1.0.9 → github2gerrit-1.2.0}/tests/test_pr_content_filter_integration.py +0 -0
- {github2gerrit-1.0.9 → github2gerrit-1.2.0}/tests/test_pr_update_detection.py +0 -0
- {github2gerrit-1.0.9 → github2gerrit-1.2.0}/tests/test_reconciliation_extracted_module.py +0 -0
- {github2gerrit-1.0.9 → github2gerrit-1.2.0}/tests/test_reconciliation_plan_and_orphans.py +0 -0
- {github2gerrit-1.0.9 → github2gerrit-1.2.0}/tests/test_reconciliation_scenarios.py +0 -0
- {github2gerrit-1.0.9 → github2gerrit-1.2.0}/tests/test_ssh_agent.py +0 -0
- {github2gerrit-1.0.9 → github2gerrit-1.2.0}/tests/test_ssh_agent_ownership.py +0 -0
- {github2gerrit-1.0.9 → github2gerrit-1.2.0}/tests/test_ssh_artifact_prevention.py +0 -0
- {github2gerrit-1.0.9 → github2gerrit-1.2.0}/tests/test_ssh_common.py +0 -0
- {github2gerrit-1.0.9 → github2gerrit-1.2.0}/tests/test_ssh_discovery.py +0 -0
- {github2gerrit-1.0.9 → github2gerrit-1.2.0}/tests/test_ssh_discovery_dry_run.py +0 -0
- {github2gerrit-1.0.9 → github2gerrit-1.2.0}/tests/test_trailers_additional.py +0 -0
- {github2gerrit-1.0.9 → github2gerrit-1.2.0}/tests/test_url_parser.py +0 -0
- {github2gerrit-1.0.9 → github2gerrit-1.2.0}/tests/test_utils.py +0 -0
- {github2gerrit-1.0.9 → github2gerrit-1.2.0}/tests/unit/test_config_integration.py +0 -0
- {github2gerrit-1.0.9 → github2gerrit-1.2.0}/tests/unit/test_ssh_config_parser.py +0 -0
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
# SPDX-FileCopyrightText: 2025 The Linux Foundation
|
|
4
4
|
|
|
5
5
|
ci:
|
|
6
|
-
skip: [pytest]
|
|
6
|
+
skip: [pytest, gha-workflow-linter]
|
|
7
7
|
autofix_commit_msg: |
|
|
8
8
|
Chore: pre-commit autofixes
|
|
9
9
|
|
|
@@ -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: e05c5c0818279e5ac248ac9e954431ba58865e61 # frozen: v0.15.7
|
|
63
63
|
hooks:
|
|
64
64
|
- id: ruff
|
|
65
65
|
files: ^(src|scripts|tests)/.+\.py$
|
|
@@ -76,13 +76,6 @@ repos:
|
|
|
76
76
|
- types-PyYAML
|
|
77
77
|
- types-requests
|
|
78
78
|
|
|
79
|
-
# Doesn't seem to run reliably inside pre-commit.ci
|
|
80
|
-
# - repo: https://github.com/RobertCraigie/pyright-python
|
|
81
|
-
# rev: d393df1703a808473b84bd14a2702f4793014031 # frozen: v1.1.404
|
|
82
|
-
# hooks:
|
|
83
|
-
# - id: pyright
|
|
84
|
-
# files: ^(src|scripts|tests)/.+\.py$
|
|
85
|
-
|
|
86
79
|
- repo: https://github.com/btford/write-good
|
|
87
80
|
rev: ab66ce10136dfad5146e69e70f82a3efac8842c1 # frozen: v1.0.8
|
|
88
81
|
hooks:
|
|
@@ -120,6 +113,18 @@ repos:
|
|
|
120
113
|
hooks:
|
|
121
114
|
- id: codespell
|
|
122
115
|
|
|
116
|
+
# Requires a mirror, primary repo lacks .pre-commit-hooks.yaml
|
|
117
|
+
- repo: https://github.com/DetachHead/basedpyright-prek-mirror
|
|
118
|
+
rev: d58fe7fc44458fa7e41e2d38c04598a3c87833f2 # frozen: 1.38.3
|
|
119
|
+
hooks:
|
|
120
|
+
- id: basedpyright
|
|
121
|
+
files: ^src/.+\.py$
|
|
122
|
+
|
|
123
|
+
- repo: https://github.com/lfreleng-actions/gha-workflow-linter
|
|
124
|
+
rev: a7caf8f3a1a05688d1cee46615ff94def617e5a3 # frozen: v1.0.2
|
|
125
|
+
hooks:
|
|
126
|
+
- id: gha-workflow-linter
|
|
127
|
+
|
|
123
128
|
- repo: https://github.com/python-jsonschema/check-jsonschema
|
|
124
129
|
rev: 8db279a37c552206d2df62269ff6f9d31125815a # frozen: 0.37.0
|
|
125
130
|
hooks:
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: github2gerrit
|
|
3
|
-
Version: 1.0
|
|
3
|
+
Version: 1.2.0
|
|
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
|
|
@@ -69,6 +69,10 @@ inputs:
|
|
|
69
69
|
description: "Enable CI testing mode; overrides .gitreview, creates orphan commits"
|
|
70
70
|
required: false
|
|
71
71
|
default: "false"
|
|
72
|
+
G2G_NO_GERRIT:
|
|
73
|
+
description: "Run full pipeline without contacting Gerrit (forces DRY_RUN, suppresses cleanup)"
|
|
74
|
+
required: false
|
|
75
|
+
default: "false"
|
|
72
76
|
FORCE:
|
|
73
77
|
description: "Force PR closure regardless of Gerrit change status (abandoned, etc)"
|
|
74
78
|
required: false
|
|
@@ -153,6 +157,10 @@ inputs:
|
|
|
153
157
|
description: "Create a Gerrit change when an UPDATE operation cannot find an existing one"
|
|
154
158
|
required: false
|
|
155
159
|
default: "false"
|
|
160
|
+
G2G_DISABLED:
|
|
161
|
+
description: "Set to 'true' to disable the action entirely (exits successfully with a message)"
|
|
162
|
+
required: false
|
|
163
|
+
default: ""
|
|
156
164
|
|
|
157
165
|
outputs:
|
|
158
166
|
gerrit_change_request_url:
|
|
@@ -168,27 +176,57 @@ outputs:
|
|
|
168
176
|
runs:
|
|
169
177
|
using: "composite"
|
|
170
178
|
steps:
|
|
179
|
+
- name: "Check if GitHub2Gerrit is disabled"
|
|
180
|
+
id: disabled-check
|
|
181
|
+
shell: bash
|
|
182
|
+
run: |
|
|
183
|
+
# Check if GitHub2Gerrit is disabled
|
|
184
|
+
set -euo pipefail
|
|
185
|
+
DISABLED_ENV="${G2G_DISABLED:-}"
|
|
186
|
+
DISABLED_INPUT="${{ inputs.G2G_DISABLED }}"
|
|
187
|
+
# Normalize: accept the same truthy set as env_bool()
|
|
188
|
+
# (1/true/yes/on, case-insensitive, trimmed)
|
|
189
|
+
_normalize() {
|
|
190
|
+
printf '%s' "$1" | tr '[:upper:]' '[:lower:]' | xargs
|
|
191
|
+
}
|
|
192
|
+
_is_truthy() {
|
|
193
|
+
case "$(_normalize "$1")" in
|
|
194
|
+
1|true|yes|on) return 0 ;;
|
|
195
|
+
*) return 1 ;;
|
|
196
|
+
esac
|
|
197
|
+
}
|
|
198
|
+
if _is_truthy "${DISABLED_ENV}" || _is_truthy "${DISABLED_INPUT}"; then
|
|
199
|
+
echo "🛑 GitHub2Gerrit is disabled by check of G2G_DISABLED variable or input"
|
|
200
|
+
echo "disabled=true" >> "$GITHUB_OUTPUT"
|
|
201
|
+
else
|
|
202
|
+
echo "disabled=false" >> "$GITHUB_OUTPUT"
|
|
203
|
+
fi
|
|
204
|
+
|
|
205
|
+
- name: "Checkout repository"
|
|
206
|
+
if: steps.disabled-check.outputs.disabled != 'true'
|
|
207
|
+
# yamllint disable-line rule:line-length
|
|
208
|
+
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
|
|
209
|
+
with:
|
|
210
|
+
fetch-depth: ${{ inputs.FETCH_DEPTH }}
|
|
211
|
+
# Ensure we are on the PR's head SHA when triggered by PR events
|
|
212
|
+
ref: ${{ github.event.pull_request.head.sha || github.sha }}
|
|
213
|
+
|
|
171
214
|
- name: "Setup Python"
|
|
215
|
+
if: steps.disabled-check.outputs.disabled != 'true'
|
|
172
216
|
# yamllint disable-line rule:line-length
|
|
173
217
|
uses: actions/setup-python@a309ff8b426b58ec0e2a45f0f869d46889d02405 # v6.2.0
|
|
174
218
|
with:
|
|
175
219
|
python-version-file: '${{ github.action_path }}/pyproject.toml'
|
|
176
220
|
|
|
177
221
|
- name: "Setup uv"
|
|
222
|
+
if: steps.disabled-check.outputs.disabled != 'true'
|
|
178
223
|
# yamllint disable-line rule:line-length
|
|
179
|
-
uses: astral-sh/setup-uv@
|
|
224
|
+
uses: astral-sh/setup-uv@37802adc94f370d6bfd71619e3f0bf239e1f3b78 # v7.6.0
|
|
180
225
|
with:
|
|
181
226
|
enable-cache: false
|
|
182
227
|
|
|
183
|
-
- name: "Checkout repository"
|
|
184
|
-
# yamllint disable-line rule:line-length
|
|
185
|
-
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
|
|
186
|
-
with:
|
|
187
|
-
fetch-depth: ${{ inputs.FETCH_DEPTH }}
|
|
188
|
-
# Ensure we are on the PR's head SHA when triggered by PR events
|
|
189
|
-
ref: ${{ github.event.pull_request.head.sha || github.sha }}
|
|
190
|
-
|
|
191
228
|
- name: "Setup github2gerrit"
|
|
229
|
+
if: steps.disabled-check.outputs.disabled != 'true'
|
|
192
230
|
shell: bash
|
|
193
231
|
env:
|
|
194
232
|
# Provide version for hatch-vcs (via setuptools-scm)
|
|
@@ -210,7 +248,7 @@ runs:
|
|
|
210
248
|
|
|
211
249
|
- name: "Validate PR_NUMBER usage"
|
|
212
250
|
# yamllint disable-line rule:line-length
|
|
213
|
-
if: ${{ github.event_name != 'workflow_dispatch' && inputs.PR_NUMBER != '' && inputs.PR_NUMBER != '0' }}
|
|
251
|
+
if: ${{ steps.disabled-check.outputs.disabled != 'true' && github.event_name != 'workflow_dispatch' && inputs.PR_NUMBER != '' && inputs.PR_NUMBER != '0' }}
|
|
214
252
|
shell: bash
|
|
215
253
|
run: |
|
|
216
254
|
# Validate PR_NUMBER usage
|
|
@@ -219,7 +257,7 @@ runs:
|
|
|
219
257
|
exit 2
|
|
220
258
|
|
|
221
259
|
- name: "Normalize PR_NUMBER"
|
|
222
|
-
if: ${{ github.event_name == 'workflow_dispatch' }}
|
|
260
|
+
if: ${{ steps.disabled-check.outputs.disabled != 'true' && github.event_name == 'workflow_dispatch' }}
|
|
223
261
|
shell: bash
|
|
224
262
|
run: |
|
|
225
263
|
# Normalize PR_NUMBER
|
|
@@ -239,6 +277,7 @@ runs:
|
|
|
239
277
|
fi
|
|
240
278
|
|
|
241
279
|
- name: "Extract PR number, validate context"
|
|
280
|
+
if: steps.disabled-check.outputs.disabled != 'true'
|
|
242
281
|
shell: bash
|
|
243
282
|
run: |
|
|
244
283
|
# Extract PR number, validate context
|
|
@@ -280,6 +319,7 @@ runs:
|
|
|
280
319
|
fi
|
|
281
320
|
|
|
282
321
|
- name: "Run github2gerrit Python CLI"
|
|
322
|
+
if: steps.disabled-check.outputs.disabled != 'true'
|
|
283
323
|
id: run-cli
|
|
284
324
|
shell: bash
|
|
285
325
|
env:
|
|
@@ -338,6 +378,7 @@ runs:
|
|
|
338
378
|
SYNC_ALL_OPEN_PRS: ${{ env.SYNC_ALL_OPEN_PRS }}
|
|
339
379
|
PR_NUMBER: ${{ env.PR_NUMBER }}
|
|
340
380
|
G2G_TEST_MODE: "false"
|
|
381
|
+
G2G_NO_GERRIT: ${{ inputs.G2G_NO_GERRIT }}
|
|
341
382
|
run: |
|
|
342
383
|
# Run github2gerrit Python CLI
|
|
343
384
|
set -euo pipefail
|
|
@@ -352,6 +393,7 @@ runs:
|
|
|
352
393
|
fi
|
|
353
394
|
|
|
354
395
|
- name: "Capture outputs"
|
|
396
|
+
if: steps.disabled-check.outputs.disabled != 'true'
|
|
355
397
|
id: capture-outputs
|
|
356
398
|
shell: bash
|
|
357
399
|
# yamllint disable rule:line-length
|
|
@@ -235,19 +235,7 @@ markers = [
|
|
|
235
235
|
|
|
236
236
|
[tool.pyright]
|
|
237
237
|
pythonVersion = "3.11"
|
|
238
|
-
include = ["src"
|
|
239
|
-
exclude = [
|
|
240
|
-
"build/",
|
|
241
|
-
"dist/",
|
|
242
|
-
"docs/",
|
|
243
|
-
"scripts/",
|
|
244
|
-
"tests/fixtures/",
|
|
245
|
-
".venv/",
|
|
246
|
-
".mypy_cache/",
|
|
247
|
-
".pytest_cache/",
|
|
248
|
-
".ruff_cache/",
|
|
249
|
-
"coverage_html_report/",
|
|
250
|
-
]
|
|
238
|
+
include = ["src"]
|
|
251
239
|
typeCheckingMode = "strict"
|
|
252
240
|
reportMissingImports = "none"
|
|
253
241
|
reportMissingTypeStubs = "none"
|
|
@@ -845,6 +845,14 @@ def main(
|
|
|
845
845
|
typer.echo("Version information not available")
|
|
846
846
|
sys.exit(int(ExitCode.SUCCESS))
|
|
847
847
|
|
|
848
|
+
# Check if GitHub2Gerrit is disabled via environment variable
|
|
849
|
+
if env_bool("G2G_DISABLED"):
|
|
850
|
+
typer.echo(
|
|
851
|
+
"\U0001f6d1 GitHub2Gerrit is disabled by check of "
|
|
852
|
+
"G2G_DISABLED variable"
|
|
853
|
+
)
|
|
854
|
+
sys.exit(int(ExitCode.SUCCESS))
|
|
855
|
+
|
|
848
856
|
# Override boolean parameters with properly parsed environment variables.
|
|
849
857
|
# This ensures that string "false" from GitHub Actions is handled
|
|
850
858
|
# correctly (Typer/Click treats any non-empty string as truthy).
|
|
@@ -2126,8 +2134,40 @@ def _process() -> None:
|
|
|
2126
2134
|
raise converted_error from exc
|
|
2127
2135
|
|
|
2128
2136
|
gh = _read_github_context()
|
|
2137
|
+
|
|
2138
|
+
# --- G2G_NO_GERRIT: leverage DRY_RUN infrastructure ---
|
|
2139
|
+
# G2G_NO_GERRIT reuses the existing DRY_RUN + G2G_DRYRUN_DISABLE_NETWORK
|
|
2140
|
+
# code paths so that all tool logic runs but Gerrit network operations
|
|
2141
|
+
# are no-ops. Cleanup tasks (abandoned-PR / Gerrit-change sweeps) are
|
|
2142
|
+
# also suppressed because they would hit a non-existent server.
|
|
2143
|
+
no_gerrit = env_bool("G2G_NO_GERRIT", False)
|
|
2144
|
+
|
|
2145
|
+
if no_gerrit:
|
|
2146
|
+
log.info(
|
|
2147
|
+
"🧪 G2G_NO_GERRIT enabled: forcing DRY_RUN=true and "
|
|
2148
|
+
"G2G_DRYRUN_DISABLE_NETWORK=true"
|
|
2149
|
+
)
|
|
2150
|
+
os.environ["DRY_RUN"] = "true"
|
|
2151
|
+
os.environ["G2G_DRYRUN_DISABLE_NETWORK"] = "true"
|
|
2152
|
+
# Rebuild inputs so the rest of the pipeline sees dry_run=True
|
|
2153
|
+
data = _load_effective_inputs()
|
|
2154
|
+
|
|
2155
|
+
# Display config AFTER G2G_NO_GERRIT evaluation so the table
|
|
2156
|
+
# reflects the actual runtime values (e.g. DRY_RUN forced true).
|
|
2129
2157
|
_display_effective_config(data, gh)
|
|
2130
2158
|
|
|
2159
|
+
# Log configured Gerrit server if present. DNS validation is
|
|
2160
|
+
# handled by Orchestrator._resolve_gerrit_info() which covers
|
|
2161
|
+
# both explicit GERRIT_SERVER and .gitreview-derived hosts in
|
|
2162
|
+
# a single, consolidated code path.
|
|
2163
|
+
gerrit_host = data.gerrit_server or ""
|
|
2164
|
+
if gerrit_host:
|
|
2165
|
+
log.debug(
|
|
2166
|
+
"Gerrit server '%s' configured; DNS validation "
|
|
2167
|
+
"deferred to Orchestrator",
|
|
2168
|
+
gerrit_host.strip(),
|
|
2169
|
+
)
|
|
2170
|
+
|
|
2131
2171
|
# Detect PR operation mode for routing
|
|
2132
2172
|
operation_mode = gh.get_operation_mode()
|
|
2133
2173
|
if operation_mode != models.PROperationMode.UNKNOWN:
|
|
@@ -2145,13 +2185,25 @@ def _process() -> None:
|
|
|
2145
2185
|
log.debug("✏️ PR edit event - will sync metadata to Gerrit change")
|
|
2146
2186
|
elif operation_mode == models.PROperationMode.CLOSE:
|
|
2147
2187
|
pr_num = gh.pr_number or "unknown"
|
|
2148
|
-
|
|
2149
|
-
|
|
2150
|
-
|
|
2151
|
-
|
|
2152
|
-
|
|
2153
|
-
|
|
2154
|
-
|
|
2188
|
+
if no_gerrit:
|
|
2189
|
+
log.debug(
|
|
2190
|
+
"🚪 Pull request #%s closed; Gerrit cleanup skipped "
|
|
2191
|
+
"(G2G_NO_GERRIT)",
|
|
2192
|
+
pr_num,
|
|
2193
|
+
)
|
|
2194
|
+
safe_console_print(
|
|
2195
|
+
f"🚪 Pull request #{pr_num} closed; "
|
|
2196
|
+
"Gerrit cleanup skipped (G2G_NO_GERRIT)"
|
|
2197
|
+
)
|
|
2198
|
+
else:
|
|
2199
|
+
log.debug(
|
|
2200
|
+
"🚪 Pull request #%s closed; performing Gerrit cleanup",
|
|
2201
|
+
pr_num,
|
|
2202
|
+
)
|
|
2203
|
+
safe_console_print(
|
|
2204
|
+
f"🚪 Pull request #{pr_num} closed; "
|
|
2205
|
+
"performing Gerrit cleanup"
|
|
2206
|
+
)
|
|
2155
2207
|
|
|
2156
2208
|
# Debug log prerequisites for abandoning Gerrit change
|
|
2157
2209
|
log.debug(
|
|
@@ -2164,8 +2216,10 @@ def _process() -> None:
|
|
|
2164
2216
|
)
|
|
2165
2217
|
|
|
2166
2218
|
# First, abandon the specific Gerrit change for this closed PR
|
|
2219
|
+
# Skip in G2G_NO_GERRIT: no Gerrit server to query
|
|
2167
2220
|
if (
|
|
2168
|
-
|
|
2221
|
+
not no_gerrit
|
|
2222
|
+
and gh.pr_number
|
|
2169
2223
|
and data.gerrit_server
|
|
2170
2224
|
and data.gerrit_project
|
|
2171
2225
|
and gh.repository
|
|
@@ -2209,7 +2263,8 @@ def _process() -> None:
|
|
|
2209
2263
|
)
|
|
2210
2264
|
|
|
2211
2265
|
# Run abandoned PR cleanup if enabled
|
|
2212
|
-
|
|
2266
|
+
# Skip in G2G_NO_GERRIT: no Gerrit server to query
|
|
2267
|
+
if FORCE_ABANDONED_CLEANUP and not no_gerrit:
|
|
2213
2268
|
try:
|
|
2214
2269
|
log.debug("Running abandoned PR cleanup...")
|
|
2215
2270
|
if gh.repository and "/" in gh.repository:
|
|
@@ -2225,7 +2280,8 @@ def _process() -> None:
|
|
|
2225
2280
|
log.warning("Abandoned PR cleanup failed: %s", exc)
|
|
2226
2281
|
|
|
2227
2282
|
# Run Gerrit cleanup if enabled
|
|
2228
|
-
|
|
2283
|
+
# Skip in G2G_NO_GERRIT: no Gerrit server to query
|
|
2284
|
+
if FORCE_GERRIT_CLEANUP and not no_gerrit:
|
|
2229
2285
|
try:
|
|
2230
2286
|
log.debug("Running Gerrit cleanup for closed GitHub PRs...")
|
|
2231
2287
|
if data.gerrit_server and data.gerrit_project:
|
|
@@ -2264,10 +2320,14 @@ def _process() -> None:
|
|
|
2264
2320
|
log.debug(merge_message)
|
|
2265
2321
|
safe_console_print(merge_message)
|
|
2266
2322
|
|
|
2267
|
-
|
|
2268
|
-
|
|
2269
|
-
|
|
2270
|
-
|
|
2323
|
+
# Skip in G2G_NO_GERRIT: Gerrit REST calls are not possible
|
|
2324
|
+
if no_gerrit:
|
|
2325
|
+
log.info("G2G_NO_GERRIT: skipping Gerrit change processing")
|
|
2326
|
+
else:
|
|
2327
|
+
force = env_bool("FORCE", False)
|
|
2328
|
+
_process_close_gerrit_change(
|
|
2329
|
+
data, gh, gerrit_event_change_url, force=force
|
|
2330
|
+
)
|
|
2271
2331
|
|
|
2272
2332
|
# Continue with cleanup tasks even if no PR was found/closed
|
|
2273
2333
|
# (Gerrit change might not have originated from GitHub)
|
|
@@ -2276,16 +2336,23 @@ def _process() -> None:
|
|
|
2276
2336
|
gerrit_change_url = os.getenv("G2G_GERRIT_CHANGE_URL") or ""
|
|
2277
2337
|
if gerrit_change_url and not gerrit_event_change_url:
|
|
2278
2338
|
log.info("🔄 Gerrit change URL provided: %s", gerrit_change_url)
|
|
2279
|
-
|
|
2280
|
-
|
|
2281
|
-
|
|
2339
|
+
# Skip in G2G_NO_GERRIT: Gerrit REST calls are not possible
|
|
2340
|
+
if no_gerrit:
|
|
2341
|
+
log.info("G2G_NO_GERRIT: skipping Gerrit change processing")
|
|
2342
|
+
else:
|
|
2343
|
+
log.info("Finding and closing source GitHub pull request")
|
|
2344
|
+
force = env_bool("FORCE", False)
|
|
2345
|
+
_process_close_gerrit_change(
|
|
2346
|
+
data, gh, gerrit_change_url, force=force
|
|
2347
|
+
)
|
|
2282
2348
|
|
|
2283
2349
|
# Continue with cleanup tasks
|
|
2284
2350
|
|
|
2285
2351
|
# Run cleanup tasks for Gerrit events and legacy G2G_GERRIT_CHANGE_URL
|
|
2286
2352
|
if gerrit_event_change_url or gerrit_change_url:
|
|
2287
2353
|
# Run abandoned PR cleanup if enabled
|
|
2288
|
-
|
|
2354
|
+
# Skip in G2G_NO_GERRIT: no Gerrit server to query
|
|
2355
|
+
if FORCE_ABANDONED_CLEANUP and not no_gerrit:
|
|
2289
2356
|
try:
|
|
2290
2357
|
log.debug("Running abandoned PR cleanup...")
|
|
2291
2358
|
if gh.repository and "/" in gh.repository:
|
|
@@ -2301,7 +2368,8 @@ def _process() -> None:
|
|
|
2301
2368
|
log.warning("Abandoned PR cleanup failed: %s", exc)
|
|
2302
2369
|
|
|
2303
2370
|
# Run Gerrit cleanup if enabled
|
|
2304
|
-
|
|
2371
|
+
# Skip in G2G_NO_GERRIT: no Gerrit server to query
|
|
2372
|
+
if FORCE_GERRIT_CLEANUP and not no_gerrit:
|
|
2305
2373
|
try:
|
|
2306
2374
|
log.debug("Running Gerrit cleanup for closed GitHub PRs...")
|
|
2307
2375
|
if data.gerrit_server and data.gerrit_project:
|
|
@@ -2322,7 +2390,8 @@ def _process() -> None:
|
|
|
2322
2390
|
_process_close_merged_prs(data, gh)
|
|
2323
2391
|
|
|
2324
2392
|
# Run abandoned PR cleanup if enabled
|
|
2325
|
-
|
|
2393
|
+
# Skip in G2G_NO_GERRIT: no Gerrit server to query
|
|
2394
|
+
if FORCE_ABANDONED_CLEANUP and not no_gerrit:
|
|
2326
2395
|
try:
|
|
2327
2396
|
log.debug("Running abandoned PR cleanup...")
|
|
2328
2397
|
if gh.repository and "/" in gh.repository:
|
|
@@ -2338,7 +2407,8 @@ def _process() -> None:
|
|
|
2338
2407
|
log.warning("Abandoned PR cleanup failed: %s", exc)
|
|
2339
2408
|
|
|
2340
2409
|
# Run Gerrit cleanup if enabled
|
|
2341
|
-
|
|
2410
|
+
# Skip in G2G_NO_GERRIT: no Gerrit server to query
|
|
2411
|
+
if FORCE_GERRIT_CLEANUP and not no_gerrit:
|
|
2342
2412
|
try:
|
|
2343
2413
|
log.info("Running Gerrit cleanup for closed GitHub PRs...")
|
|
2344
2414
|
if data.gerrit_server and data.gerrit_project:
|
|
@@ -2383,7 +2453,8 @@ def _process() -> None:
|
|
|
2383
2453
|
log.debug("Processing completed ✅")
|
|
2384
2454
|
|
|
2385
2455
|
# Run abandoned PR cleanup if enabled
|
|
2386
|
-
|
|
2456
|
+
# Skip in G2G_NO_GERRIT: no Gerrit server to query
|
|
2457
|
+
if FORCE_ABANDONED_CLEANUP and not no_gerrit:
|
|
2387
2458
|
try:
|
|
2388
2459
|
log.debug("Running abandoned PR cleanup...")
|
|
2389
2460
|
if gh.repository and "/" in gh.repository:
|
|
@@ -2399,7 +2470,8 @@ def _process() -> None:
|
|
|
2399
2470
|
log.warning("Abandoned PR cleanup failed: %s", exc)
|
|
2400
2471
|
|
|
2401
2472
|
# Run Gerrit cleanup if enabled
|
|
2402
|
-
|
|
2473
|
+
# Skip in G2G_NO_GERRIT: no Gerrit server to query
|
|
2474
|
+
if FORCE_GERRIT_CLEANUP and not no_gerrit:
|
|
2403
2475
|
try:
|
|
2404
2476
|
log.info("Running Gerrit cleanup for closed GitHub PRs...")
|
|
2405
2477
|
if data.gerrit_server and data.gerrit_project:
|
|
@@ -2567,7 +2639,8 @@ def _process() -> None:
|
|
|
2567
2639
|
pipeline_success, result = _process_single(data, gh, progress_tracker)
|
|
2568
2640
|
|
|
2569
2641
|
# Run abandoned PR cleanup if enabled and pipeline was successful
|
|
2570
|
-
|
|
2642
|
+
# Skip in G2G_NO_GERRIT: no Gerrit server to query
|
|
2643
|
+
if pipeline_success and FORCE_ABANDONED_CLEANUP and not no_gerrit:
|
|
2571
2644
|
try:
|
|
2572
2645
|
log.debug("Running abandoned PR cleanup...")
|
|
2573
2646
|
# Extract owner and repo from gh.repository (format: "owner/repo")
|
|
@@ -2585,7 +2658,8 @@ def _process() -> None:
|
|
|
2585
2658
|
log.warning("Abandoned PR cleanup failed: %s", exc)
|
|
2586
2659
|
|
|
2587
2660
|
# Run Gerrit cleanup if enabled and pipeline was successful
|
|
2588
|
-
|
|
2661
|
+
# Skip in G2G_NO_GERRIT: no Gerrit server to query
|
|
2662
|
+
if pipeline_success and FORCE_GERRIT_CLEANUP and not no_gerrit:
|
|
2589
2663
|
try:
|
|
2590
2664
|
log.debug("Running Gerrit cleanup for closed GitHub PRs...")
|
|
2591
2665
|
if data.gerrit_server and data.gerrit_project:
|
|
@@ -2612,10 +2686,11 @@ def _process() -> None:
|
|
|
2612
2686
|
# Show summary after progress tracker is stopped
|
|
2613
2687
|
if show_progress and RICH_AVAILABLE:
|
|
2614
2688
|
summary = progress_tracker.get_summary() if progress_tracker else {}
|
|
2689
|
+
safe_console_print("")
|
|
2615
2690
|
safe_console_print(
|
|
2616
|
-
"
|
|
2691
|
+
"✅ Operation completed!"
|
|
2617
2692
|
if pipeline_success
|
|
2618
|
-
else "
|
|
2693
|
+
else "❌ Operation failed!",
|
|
2619
2694
|
style="green" if pipeline_success else "red",
|
|
2620
2695
|
)
|
|
2621
2696
|
safe_console_print(
|
|
@@ -2864,6 +2939,9 @@ def _get_ssh_agent_status() -> str:
|
|
|
2864
2939
|
|
|
2865
2940
|
def _display_effective_config(data: Inputs, gh: GitHubContext) -> None:
|
|
2866
2941
|
"""Display effective configuration in a formatted table."""
|
|
2942
|
+
# Use env_bool for consistent boolean parsing across the codebase
|
|
2943
|
+
no_gerrit_enabled = env_bool("G2G_NO_GERRIT", False)
|
|
2944
|
+
|
|
2867
2945
|
# Detect mode and display prominently
|
|
2868
2946
|
github_mode = _is_github_mode()
|
|
2869
2947
|
mode_label = "GITHUB_MODE" if github_mode else "CLI_MODE"
|
|
@@ -2924,6 +3002,11 @@ def _display_effective_config(data: Inputs, gh: GitHubContext) -> None:
|
|
|
2924
3002
|
# Mode first - always show
|
|
2925
3003
|
config_info[mode_label] = mode_description
|
|
2926
3004
|
|
|
3005
|
+
# Show G2G_NO_GERRIT regardless of operation mode so logs always
|
|
3006
|
+
# indicate when the run is using test infrastructure.
|
|
3007
|
+
if no_gerrit_enabled:
|
|
3008
|
+
config_info["G2G_NO_GERRIT"] = "🧪"
|
|
3009
|
+
|
|
2927
3010
|
if is_closing_pr_mode:
|
|
2928
3011
|
# In PR closing mode, only show minimal relevant config
|
|
2929
3012
|
if data.dry_run:
|
|
@@ -116,12 +116,16 @@ log = logging.getLogger("github2gerrit.core")
|
|
|
116
116
|
_MSG_ISSUE_ID_MULTILINE = "Issue ID must be single line"
|
|
117
117
|
_MSG_MISSING_PR_CONTEXT = "missing PR context"
|
|
118
118
|
_MSG_BAD_REPOSITORY_CONTEXT = "bad repository context"
|
|
119
|
-
_MSG_MISSING_GERRIT_SERVER =
|
|
119
|
+
_MSG_MISSING_GERRIT_SERVER = (
|
|
120
|
+
"Missing Gerrit host. Provide it via the GERRIT_SERVER "
|
|
121
|
+
"input/environment variable, .gitreview file, or action configuration."
|
|
122
|
+
)
|
|
120
123
|
_MSG_MISSING_GERRIT_PROJECT = "missing GERRIT_PROJECT"
|
|
121
124
|
_MSG_PYGERRIT2_REQUIRED_REST = "pygerrit2 is required to query Gerrit REST API"
|
|
122
125
|
_MSG_PYGERRIT2_REQUIRED_AUTH = "pygerrit2 is required for HTTP authentication"
|
|
123
126
|
_MSG_PYGERRIT2_MISSING = "pygerrit2 missing"
|
|
124
127
|
_MSG_PYGERRIT2_AUTH_MISSING = "pygerrit2 auth missing"
|
|
128
|
+
_MSG_DNS_RESOLUTION_FAILED = "DNS resolution failed for '%s'"
|
|
125
129
|
|
|
126
130
|
|
|
127
131
|
# Removed _insert_issue_id_into_commit_message - dead code
|
|
@@ -1658,6 +1662,38 @@ class Orchestrator:
|
|
|
1658
1662
|
# Public API
|
|
1659
1663
|
# ---------------
|
|
1660
1664
|
|
|
1665
|
+
def validate_gerrit_server(self, gerrit_host: str | None) -> None:
|
|
1666
|
+
"""Validate that the Gerrit server hostname can be resolved via DNS.
|
|
1667
|
+
|
|
1668
|
+
This provides a fast-fail mechanism to catch invalid or
|
|
1669
|
+
unresolvable Gerrit server hostnames early, before any work is done.
|
|
1670
|
+
|
|
1671
|
+
Args:
|
|
1672
|
+
gerrit_host: The Gerrit server hostname to validate.
|
|
1673
|
+
May be ``None`` or empty, in which case an error is raised.
|
|
1674
|
+
|
|
1675
|
+
Raises:
|
|
1676
|
+
OrchestratorError: If the hostname is empty/None or cannot
|
|
1677
|
+
be resolved.
|
|
1678
|
+
"""
|
|
1679
|
+
if not gerrit_host or not gerrit_host.strip():
|
|
1680
|
+
raise OrchestratorError(_MSG_MISSING_GERRIT_SERVER)
|
|
1681
|
+
|
|
1682
|
+
host = gerrit_host.strip()
|
|
1683
|
+
try:
|
|
1684
|
+
socket.getaddrinfo(host, None)
|
|
1685
|
+
log.debug("DNS resolution for Gerrit host '%s' succeeded", host)
|
|
1686
|
+
except (OSError, UnicodeError) as exc:
|
|
1687
|
+
log.debug(
|
|
1688
|
+
"Gerrit server '%s' could not be resolved via DNS. "
|
|
1689
|
+
"This typically means either the server hostname is "
|
|
1690
|
+
"incorrect or there is no Gerrit server associated "
|
|
1691
|
+
"with this repository.",
|
|
1692
|
+
host,
|
|
1693
|
+
exc_info=True,
|
|
1694
|
+
)
|
|
1695
|
+
raise OrchestratorError(_MSG_DNS_RESOLUTION_FAILED % host) from exc
|
|
1696
|
+
|
|
1661
1697
|
def execute(
|
|
1662
1698
|
self,
|
|
1663
1699
|
inputs: Inputs,
|
|
@@ -2058,7 +2094,15 @@ class Orchestrator:
|
|
|
2058
2094
|
inputs: Inputs,
|
|
2059
2095
|
repo: RepoNames,
|
|
2060
2096
|
) -> GerritInfo:
|
|
2061
|
-
"""Resolve Gerrit connection info from .gitreview or inputs.
|
|
2097
|
+
"""Resolve Gerrit connection info from .gitreview or inputs.
|
|
2098
|
+
|
|
2099
|
+
After resolution, the Gerrit host is validated via DNS to
|
|
2100
|
+
catch bogus hostnames early — regardless of whether the host
|
|
2101
|
+
came from ``.gitreview`` or explicit ``GERRIT_SERVER`` input.
|
|
2102
|
+
|
|
2103
|
+
DNS validation is skipped when ``G2G_DRYRUN_DISABLE_NETWORK``
|
|
2104
|
+
is set, consistent with the preflight and CLI-level guards.
|
|
2105
|
+
"""
|
|
2062
2106
|
log.debug(
|
|
2063
2107
|
"_resolve_gerrit_info: inputs.ci_testing=%s", inputs.ci_testing
|
|
2064
2108
|
)
|
|
@@ -2071,6 +2115,7 @@ class Orchestrator:
|
|
|
2071
2115
|
|
|
2072
2116
|
if gitreview:
|
|
2073
2117
|
log.debug("Using .gitreview settings: %s", gitreview)
|
|
2118
|
+
self._validate_resolved_gerrit_host(gitreview.host)
|
|
2074
2119
|
return gitreview
|
|
2075
2120
|
|
|
2076
2121
|
host = inputs.gerrit_server.strip()
|
|
@@ -2101,8 +2146,24 @@ class Orchestrator:
|
|
|
2101
2146
|
|
|
2102
2147
|
info = make_gitreview_info(host=host, port=port, project=project)
|
|
2103
2148
|
log.debug("Resolved Gerrit info: %s", info)
|
|
2149
|
+
self._validate_resolved_gerrit_host(info.host)
|
|
2104
2150
|
return info
|
|
2105
2151
|
|
|
2152
|
+
def _validate_resolved_gerrit_host(self, host: str | None) -> None:
|
|
2153
|
+
"""Validate a resolved Gerrit host via DNS unless network is disabled.
|
|
2154
|
+
|
|
2155
|
+
Delegates to :meth:`validate_gerrit_server` for the actual DNS
|
|
2156
|
+
check. Skipped when ``G2G_DRYRUN_DISABLE_NETWORK`` is set so
|
|
2157
|
+
that offline / test scenarios are not penalised.
|
|
2158
|
+
"""
|
|
2159
|
+
if env_bool("G2G_DRYRUN_DISABLE_NETWORK", False):
|
|
2160
|
+
log.debug(
|
|
2161
|
+
"Skipping DNS validation for '%s' (G2G_DRYRUN_DISABLE_NETWORK)",
|
|
2162
|
+
host,
|
|
2163
|
+
)
|
|
2164
|
+
return
|
|
2165
|
+
self.validate_gerrit_server(host)
|
|
2166
|
+
|
|
2106
2167
|
def _setup_ssh(self, inputs: Inputs, gerrit: GerritInfo) -> None:
|
|
2107
2168
|
"""Set up temporary SSH configuration for Gerrit access.
|
|
2108
2169
|
|
|
@@ -5772,15 +5833,8 @@ class Orchestrator:
|
|
|
5772
5833
|
)
|
|
5773
5834
|
return
|
|
5774
5835
|
|
|
5775
|
-
# DNS resolution for Gerrit host
|
|
5776
|
-
|
|
5777
|
-
socket.getaddrinfo(gerrit.host, None)
|
|
5778
|
-
log.debug(
|
|
5779
|
-
"DNS resolution for Gerrit host '%s' succeeded", gerrit.host
|
|
5780
|
-
)
|
|
5781
|
-
except Exception as exc:
|
|
5782
|
-
msg = "DNS resolution failed"
|
|
5783
|
-
raise OrchestratorError(msg) from exc
|
|
5836
|
+
# DNS resolution for Gerrit host (reuses validate_gerrit_server)
|
|
5837
|
+
self.validate_gerrit_server(gerrit.host)
|
|
5784
5838
|
|
|
5785
5839
|
# SSH (TCP) reachability on Gerrit port
|
|
5786
5840
|
try:
|