github2gerrit 1.4.4__tar.gz → 2.0.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.4.4 → github2gerrit-2.0.0}/.pre-commit-config.yaml +7 -6
- {github2gerrit-1.4.4 → github2gerrit-2.0.0}/PKG-INFO +4 -4
- {github2gerrit-1.4.4 → github2gerrit-2.0.0}/README.md +2 -2
- {github2gerrit-1.4.4 → github2gerrit-2.0.0}/action.yaml +32 -19
- {github2gerrit-1.4.4 → github2gerrit-2.0.0}/docs/cli.md +1 -1
- {github2gerrit-1.4.4 → github2gerrit-2.0.0}/docs/features.md +69 -0
- {github2gerrit-1.4.4 → github2gerrit-2.0.0}/pyproject.toml +5 -0
- {github2gerrit-1.4.4 → github2gerrit-2.0.0}/src/github2gerrit/cli.py +103 -37
- {github2gerrit-1.4.4 → github2gerrit-2.0.0}/src/github2gerrit/config.py +40 -5
- {github2gerrit-1.4.4 → github2gerrit-2.0.0}/src/github2gerrit/core.py +129 -46
- {github2gerrit-1.4.4 → github2gerrit-2.0.0}/src/github2gerrit/duplicate_detection.py +13 -2
- {github2gerrit-1.4.4 → github2gerrit-2.0.0}/src/github2gerrit/gitreview.py +18 -2
- {github2gerrit-1.4.4 → github2gerrit-2.0.0}/src/github2gerrit/models.py +61 -1
- {github2gerrit-1.4.4 → github2gerrit-2.0.0}/tests/conftest.py +29 -0
- {github2gerrit-1.4.4 → github2gerrit-2.0.0}/tests/test_action_environment_mapping.py +6 -0
- {github2gerrit-1.4.4 → github2gerrit-2.0.0}/tests/test_action_step_validation.py +131 -17
- {github2gerrit-1.4.4 → github2gerrit-2.0.0}/tests/test_cli_netrc_options.py +25 -10
- {github2gerrit-1.4.4 → github2gerrit-2.0.0}/tests/test_composite_action_coverage.py +24 -16
- {github2gerrit-1.4.4 → github2gerrit-2.0.0}/tests/test_core_ssh_setup.py +6 -2
- github2gerrit-2.0.0/tests/test_fork_pr_hardening.py +580 -0
- {github2gerrit-1.4.4 → github2gerrit-2.0.0}/tests/test_issue_157_regressions.py +19 -15
- {github2gerrit-1.4.4 → github2gerrit-2.0.0}/uv.lock +129 -111
- {github2gerrit-1.4.4 → github2gerrit-2.0.0}/.aislop/config.yml +0 -0
- {github2gerrit-1.4.4 → github2gerrit-2.0.0}/.editorconfig +0 -0
- {github2gerrit-1.4.4 → github2gerrit-2.0.0}/.gitignore +0 -0
- {github2gerrit-1.4.4 → github2gerrit-2.0.0}/.gitlint +0 -0
- {github2gerrit-1.4.4 → github2gerrit-2.0.0}/.markdownlint.yaml +0 -0
- {github2gerrit-1.4.4 → github2gerrit-2.0.0}/.yamllint +0 -0
- {github2gerrit-1.4.4 → github2gerrit-2.0.0}/LICENSE +0 -0
- {github2gerrit-1.4.4 → github2gerrit-2.0.0}/LICENSES/Apache-2.0.txt +0 -0
- {github2gerrit-1.4.4 → github2gerrit-2.0.0}/REUSE.toml +0 -0
- {github2gerrit-1.4.4 → github2gerrit-2.0.0}/SECURITY.md +0 -0
- {github2gerrit-1.4.4 → github2gerrit-2.0.0}/docs/COMMIT_RULES.md +0 -0
- {github2gerrit-1.4.4 → github2gerrit-2.0.0}/docs/development.md +0 -0
- {github2gerrit-1.4.4 → github2gerrit-2.0.0}/docs/github2gerrit_token_permissions_classic.png +0 -0
- {github2gerrit-1.4.4 → github2gerrit-2.0.0}/sitecustomize.py +0 -0
- {github2gerrit-1.4.4 → github2gerrit-2.0.0}/src/github2gerrit/__init__.py +0 -0
- {github2gerrit-1.4.4 → github2gerrit-2.0.0}/src/github2gerrit/commit_normalization.py +0 -0
- {github2gerrit-1.4.4 → github2gerrit-2.0.0}/src/github2gerrit/commit_rules.py +0 -0
- {github2gerrit-1.4.4 → github2gerrit-2.0.0}/src/github2gerrit/constants.py +0 -0
- {github2gerrit-1.4.4 → github2gerrit-2.0.0}/src/github2gerrit/error_codes.py +0 -0
- {github2gerrit-1.4.4 → github2gerrit-2.0.0}/src/github2gerrit/external_api.py +0 -0
- {github2gerrit-1.4.4 → github2gerrit-2.0.0}/src/github2gerrit/gerrit_pr_closer.py +0 -0
- {github2gerrit-1.4.4 → github2gerrit-2.0.0}/src/github2gerrit/gerrit_query.py +0 -0
- {github2gerrit-1.4.4 → github2gerrit-2.0.0}/src/github2gerrit/gerrit_rest.py +0 -0
- {github2gerrit-1.4.4 → github2gerrit-2.0.0}/src/github2gerrit/gerrit_ssh.py +0 -0
- {github2gerrit-1.4.4 → github2gerrit-2.0.0}/src/github2gerrit/gerrit_urls.py +0 -0
- {github2gerrit-1.4.4 → github2gerrit-2.0.0}/src/github2gerrit/github_api.py +0 -0
- {github2gerrit-1.4.4 → github2gerrit-2.0.0}/src/github2gerrit/gitutils.py +0 -0
- {github2gerrit-1.4.4 → github2gerrit-2.0.0}/src/github2gerrit/mapping_comment.py +0 -0
- {github2gerrit-1.4.4 → github2gerrit-2.0.0}/src/github2gerrit/netrc.py +0 -0
- {github2gerrit-1.4.4 → github2gerrit-2.0.0}/src/github2gerrit/orchestrator/__init__.py +0 -0
- {github2gerrit-1.4.4 → github2gerrit-2.0.0}/src/github2gerrit/orchestrator/reconciliation.py +0 -0
- {github2gerrit-1.4.4 → github2gerrit-2.0.0}/src/github2gerrit/pr_commands.py +0 -0
- {github2gerrit-1.4.4 → github2gerrit-2.0.0}/src/github2gerrit/pr_content_filter.py +0 -0
- {github2gerrit-1.4.4 → github2gerrit-2.0.0}/src/github2gerrit/reconcile_matcher.py +0 -0
- {github2gerrit-1.4.4 → github2gerrit-2.0.0}/src/github2gerrit/rich_display.py +0 -0
- {github2gerrit-1.4.4 → github2gerrit-2.0.0}/src/github2gerrit/rich_logging.py +0 -0
- {github2gerrit-1.4.4 → github2gerrit-2.0.0}/src/github2gerrit/similarity.py +0 -0
- {github2gerrit-1.4.4 → github2gerrit-2.0.0}/src/github2gerrit/ssh_agent_setup.py +0 -0
- {github2gerrit-1.4.4 → github2gerrit-2.0.0}/src/github2gerrit/ssh_common.py +0 -0
- {github2gerrit-1.4.4 → github2gerrit-2.0.0}/src/github2gerrit/ssh_config_parser.py +0 -0
- {github2gerrit-1.4.4 → github2gerrit-2.0.0}/src/github2gerrit/ssh_discovery.py +0 -0
- {github2gerrit-1.4.4 → github2gerrit-2.0.0}/src/github2gerrit/trailers.py +0 -0
- {github2gerrit-1.4.4 → github2gerrit-2.0.0}/src/github2gerrit/utils.py +0 -0
- {github2gerrit-1.4.4 → github2gerrit-2.0.0}/tests/fixtures/__init__.py +0 -0
- {github2gerrit-1.4.4 → github2gerrit-2.0.0}/tests/fixtures/make_repo.py +0 -0
- {github2gerrit-1.4.4 → github2gerrit-2.0.0}/tests/fixtures/ssh_config_samples.py +0 -0
- {github2gerrit-1.4.4 → github2gerrit-2.0.0}/tests/test_action_outputs.py +0 -0
- {github2gerrit-1.4.4 → github2gerrit-2.0.0}/tests/test_action_pr_number_handling.py +0 -0
- {github2gerrit-1.4.4 → github2gerrit-2.0.0}/tests/test_automation_only.py +0 -0
- {github2gerrit-1.4.4 → github2gerrit-2.0.0}/tests/test_change_id_deduplication.py +0 -0
- {github2gerrit-1.4.4 → github2gerrit-2.0.0}/tests/test_clean_squash_title.py +0 -0
- {github2gerrit-1.4.4 → github2gerrit-2.0.0}/tests/test_cli.py +0 -0
- {github2gerrit-1.4.4 → github2gerrit-2.0.0}/tests/test_cli_helpers.py +0 -0
- {github2gerrit-1.4.4 → github2gerrit-2.0.0}/tests/test_cli_outputs_file.py +0 -0
- {github2gerrit-1.4.4 → github2gerrit-2.0.0}/tests/test_cli_url_and_dryrun.py +0 -0
- {github2gerrit-1.4.4 → github2gerrit-2.0.0}/tests/test_commit_normalization.py +0 -0
- {github2gerrit-1.4.4 → github2gerrit-2.0.0}/tests/test_commit_rules.py +0 -0
- {github2gerrit-1.4.4 → github2gerrit-2.0.0}/tests/test_config_and_reviewers.py +0 -0
- {github2gerrit-1.4.4 → github2gerrit-2.0.0}/tests/test_config_helpers.py +0 -0
- {github2gerrit-1.4.4 → github2gerrit-2.0.0}/tests/test_core_close_pr_policy.py +0 -0
- {github2gerrit-1.4.4 → github2gerrit-2.0.0}/tests/test_core_config_and_errors.py +0 -0
- {github2gerrit-1.4.4 → github2gerrit-2.0.0}/tests/test_core_gerrit_backref_comment.py +0 -0
- {github2gerrit-1.4.4 → github2gerrit-2.0.0}/tests/test_core_gerrit_push_errors.py +0 -0
- {github2gerrit-1.4.4 → github2gerrit-2.0.0}/tests/test_core_gerrit_rest_results.py +0 -0
- {github2gerrit-1.4.4 → github2gerrit-2.0.0}/tests/test_core_integration_fixture_repo.py +0 -0
- {github2gerrit-1.4.4 → github2gerrit-2.0.0}/tests/test_core_prepare_commits.py +0 -0
- {github2gerrit-1.4.4 → github2gerrit-2.0.0}/tests/test_core_shallow_clone.py +0 -0
- {github2gerrit-1.4.4 → github2gerrit-2.0.0}/tests/test_core_ssrf_protection.py +0 -0
- {github2gerrit-1.4.4 → github2gerrit-2.0.0}/tests/test_dependency_supersession.py +0 -0
- {github2gerrit-1.4.4 → github2gerrit-2.0.0}/tests/test_dns_validation_and_no_gerrit.py +0 -0
- {github2gerrit-1.4.4 → github2gerrit-2.0.0}/tests/test_duplicate_detection.py +0 -0
- {github2gerrit-1.4.4 → github2gerrit-2.0.0}/tests/test_email_case_normalization.py +0 -0
- {github2gerrit-1.4.4 → github2gerrit-2.0.0}/tests/test_error_codes.py +0 -0
- {github2gerrit-1.4.4 → github2gerrit-2.0.0}/tests/test_external_api_framework.py +0 -0
- {github2gerrit-1.4.4 → github2gerrit-2.0.0}/tests/test_final_state_reconciliation.py +0 -0
- {github2gerrit-1.4.4 → github2gerrit-2.0.0}/tests/test_force_flag_cli.py +0 -0
- {github2gerrit-1.4.4 → github2gerrit-2.0.0}/tests/test_gerrit_change_id_footer.py +0 -0
- {github2gerrit-1.4.4 → github2gerrit-2.0.0}/tests/test_gerrit_change_status_checks.py +0 -0
- {github2gerrit-1.4.4 → github2gerrit-2.0.0}/tests/test_gerrit_pr_closer.py +0 -0
- {github2gerrit-1.4.4 → github2gerrit-2.0.0}/tests/test_gerrit_rest_client.py +0 -0
- {github2gerrit-1.4.4 → github2gerrit-2.0.0}/tests/test_gerrit_ssh_abandon.py +0 -0
- {github2gerrit-1.4.4 → github2gerrit-2.0.0}/tests/test_gerrit_urls.py +0 -0
- {github2gerrit-1.4.4 → github2gerrit-2.0.0}/tests/test_gerrit_urls_more.py +0 -0
- {github2gerrit-1.4.4 → github2gerrit-2.0.0}/tests/test_ghe_and_gitreview_args.py +0 -0
- {github2gerrit-1.4.4 → github2gerrit-2.0.0}/tests/test_github_api_error_handling.py +0 -0
- {github2gerrit-1.4.4 → github2gerrit-2.0.0}/tests/test_github_api_helpers.py +0 -0
- {github2gerrit-1.4.4 → github2gerrit-2.0.0}/tests/test_github_api_retry_and_helpers.py +0 -0
- {github2gerrit-1.4.4 → github2gerrit-2.0.0}/tests/test_gitreview.py +0 -0
- {github2gerrit-1.4.4 → github2gerrit-2.0.0}/tests/test_gitutils_helpers.py +0 -0
- {github2gerrit-1.4.4 → github2gerrit-2.0.0}/tests/test_mapping_comment_additional.py +0 -0
- {github2gerrit-1.4.4 → github2gerrit-2.0.0}/tests/test_mapping_comment_digest_and_backref.py +0 -0
- {github2gerrit-1.4.4 → github2gerrit-2.0.0}/tests/test_metadata_and_reconciliation.py +0 -0
- {github2gerrit-1.4.4 → github2gerrit-2.0.0}/tests/test_metadata_trailer_separation_bug.py +0 -0
- {github2gerrit-1.4.4 → github2gerrit-2.0.0}/tests/test_misc_small_coverage.py +0 -0
- {github2gerrit-1.4.4 → github2gerrit-2.0.0}/tests/test_netrc.py +0 -0
- {github2gerrit-1.4.4 → github2gerrit-2.0.0}/tests/test_orphan_rest_side_effects.py +0 -0
- {github2gerrit-1.4.4 → github2gerrit-2.0.0}/tests/test_pr_commands.py +0 -0
- {github2gerrit-1.4.4 → github2gerrit-2.0.0}/tests/test_pr_content_filter.py +0 -0
- {github2gerrit-1.4.4 → github2gerrit-2.0.0}/tests/test_pr_content_filter_integration.py +0 -0
- {github2gerrit-1.4.4 → github2gerrit-2.0.0}/tests/test_pr_update_detection.py +0 -0
- {github2gerrit-1.4.4 → github2gerrit-2.0.0}/tests/test_reconciliation_extracted_module.py +0 -0
- {github2gerrit-1.4.4 → github2gerrit-2.0.0}/tests/test_reconciliation_plan_and_orphans.py +0 -0
- {github2gerrit-1.4.4 → github2gerrit-2.0.0}/tests/test_reconciliation_scenarios.py +0 -0
- {github2gerrit-1.4.4 → github2gerrit-2.0.0}/tests/test_ssh_agent.py +0 -0
- {github2gerrit-1.4.4 → github2gerrit-2.0.0}/tests/test_ssh_agent_ownership.py +0 -0
- {github2gerrit-1.4.4 → github2gerrit-2.0.0}/tests/test_ssh_artifact_prevention.py +0 -0
- {github2gerrit-1.4.4 → github2gerrit-2.0.0}/tests/test_ssh_common.py +0 -0
- {github2gerrit-1.4.4 → github2gerrit-2.0.0}/tests/test_ssh_discovery.py +0 -0
- {github2gerrit-1.4.4 → github2gerrit-2.0.0}/tests/test_ssh_discovery_dry_run.py +0 -0
- {github2gerrit-1.4.4 → github2gerrit-2.0.0}/tests/test_trailers_additional.py +0 -0
- {github2gerrit-1.4.4 → github2gerrit-2.0.0}/tests/test_url_parser.py +0 -0
- {github2gerrit-1.4.4 → github2gerrit-2.0.0}/tests/test_utils.py +0 -0
- {github2gerrit-1.4.4 → github2gerrit-2.0.0}/tests/unit/test_config_integration.py +0 -0
- {github2gerrit-1.4.4 → github2gerrit-2.0.0}/tests/unit/test_ssh_config_parser.py +0 -0
|
@@ -3,6 +3,7 @@
|
|
|
3
3
|
# SPDX-FileCopyrightText: 2025 The Linux Foundation
|
|
4
4
|
|
|
5
5
|
ci:
|
|
6
|
+
autofix_prs: false
|
|
6
7
|
# pre-commit.ci sandbox prevents network calls; aislop runs engines
|
|
7
8
|
# that can call the network at scan time, so it cannot run there
|
|
8
9
|
# either. gha-workflow-linter validates action calls over the
|
|
@@ -63,7 +64,7 @@ repos:
|
|
|
63
64
|
types: [yaml]
|
|
64
65
|
|
|
65
66
|
- repo: https://github.com/astral-sh/ruff-pre-commit
|
|
66
|
-
rev:
|
|
67
|
+
rev: 65dbdb59d2f2d9c3bdc343c566821ad3319ddaa3 # frozen: v0.16.3
|
|
67
68
|
hooks:
|
|
68
69
|
- id: ruff
|
|
69
70
|
files: ^(src|scripts|tests)/.+\.py$
|
|
@@ -72,7 +73,7 @@ repos:
|
|
|
72
73
|
files: ^(src|scripts|tests)/.+\.py$
|
|
73
74
|
|
|
74
75
|
- repo: https://github.com/pre-commit/mirrors-mypy
|
|
75
|
-
rev:
|
|
76
|
+
rev: 7ff8d35ae36a7d2b968f2f90b4c723e292e594ee # frozen: v2.3.1
|
|
76
77
|
hooks:
|
|
77
78
|
- id: mypy
|
|
78
79
|
files: ^src/.+\.py$
|
|
@@ -119,13 +120,13 @@ repos:
|
|
|
119
120
|
|
|
120
121
|
# Requires a mirror, primary repo lacks .pre-commit-hooks.yaml
|
|
121
122
|
- repo: https://github.com/DetachHead/basedpyright-prek-mirror
|
|
122
|
-
rev:
|
|
123
|
+
rev: 3c94d276aa3005fa1f5a977946c9dc106135c083 # frozen: 1.39.10
|
|
123
124
|
hooks:
|
|
124
125
|
- id: basedpyright
|
|
125
126
|
files: ^src/.+\.py$
|
|
126
127
|
|
|
127
128
|
- repo: https://github.com/lfreleng-actions/gha-workflow-linter
|
|
128
|
-
rev:
|
|
129
|
+
rev: 7f11ad46be1cd2b3d778428d40fcb09309bb3be5 # frozen: v1.4.1
|
|
129
130
|
hooks:
|
|
130
131
|
- id: gha-workflow-linter
|
|
131
132
|
|
|
@@ -141,12 +142,12 @@ repos:
|
|
|
141
142
|
name: aislop
|
|
142
143
|
entry: aislop ci --human
|
|
143
144
|
language: node
|
|
144
|
-
additional_dependencies: ["aislop@0.
|
|
145
|
+
additional_dependencies: ["aislop@0.14.1"]
|
|
145
146
|
pass_filenames: false
|
|
146
147
|
always_run: true
|
|
147
148
|
|
|
148
149
|
- repo: https://github.com/python-jsonschema/check-jsonschema
|
|
149
|
-
rev:
|
|
150
|
+
rev: c4654a7e007c9619a5eb63c39a456572a0fa1851 # frozen: 0.38.0
|
|
150
151
|
hooks:
|
|
151
152
|
- id: check-github-actions
|
|
152
153
|
- id: check-github-workflows
|
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
Metadata-Version: 2.
|
|
1
|
+
Metadata-Version: 2.5
|
|
2
2
|
Name: github2gerrit
|
|
3
|
-
Version:
|
|
3
|
+
Version: 2.0.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
|
|
@@ -235,7 +235,7 @@ uvx github2gerrit https://github.com/onap/portal-ng-bff/pull/33
|
|
|
235
235
|
| `GERRIT_HTTP_PASSWORD` | No | `""` | Gerrit HTTP password/token for REST queries |
|
|
236
236
|
| `ORGANIZATION` | No | repository owner | GitHub organization/owner used for credential derivation |
|
|
237
237
|
| `PR_NUMBER` | No | `"0"` | PR number to process; `0` processes all open PRs (dispatch) |
|
|
238
|
-
| `FETCH_DEPTH` | No | `"10"` |
|
|
238
|
+
| `FETCH_DEPTH` | No | `"10"` | Git history depth: PR fetch, push checkout, reconciliation |
|
|
239
239
|
| `SUBMIT_SINGLE_COMMITS` | No | `"false"` | Submit one commit at a time to Gerrit |
|
|
240
240
|
| `USE_PR_AS_COMMIT` | No | `"false"` | Use PR title and body as the commit message |
|
|
241
241
|
| `PRESERVE_GITHUB_PRS` | No | `"true"` | Do not close GitHub PRs after pushing to Gerrit |
|
|
@@ -312,7 +312,7 @@ Input defaults match the composite action defaults.
|
|
|
312
312
|
| `G2G_USE_SSH_AGENT` | boolean | `true` | Use SSH agent instead of file-based keys |
|
|
313
313
|
| `ORGANIZATION` | string | repository owner | GitHub organization/owner |
|
|
314
314
|
| `PR_NUMBER` | string | `"0"` | PR to process on dispatch; `0` processes all |
|
|
315
|
-
| `FETCH_DEPTH` | string | `"10"` |
|
|
315
|
+
| `FETCH_DEPTH` | string | `"10"` | Git depth: PR, push, reconciliation |
|
|
316
316
|
| `SUBMIT_SINGLE_COMMITS` | boolean | `false` | Submit one commit at a time |
|
|
317
317
|
| `USE_PR_AS_COMMIT` | boolean | `false` | Use PR title and body as the commit message |
|
|
318
318
|
| `PRESERVE_GITHUB_PRS` | boolean | `true` | Do not close GitHub PRs after pushing |
|
|
@@ -189,7 +189,7 @@ uvx github2gerrit https://github.com/onap/portal-ng-bff/pull/33
|
|
|
189
189
|
| `GERRIT_HTTP_PASSWORD` | No | `""` | Gerrit HTTP password/token for REST queries |
|
|
190
190
|
| `ORGANIZATION` | No | repository owner | GitHub organization/owner used for credential derivation |
|
|
191
191
|
| `PR_NUMBER` | No | `"0"` | PR number to process; `0` processes all open PRs (dispatch) |
|
|
192
|
-
| `FETCH_DEPTH` | No | `"10"` |
|
|
192
|
+
| `FETCH_DEPTH` | No | `"10"` | Git history depth: PR fetch, push checkout, reconciliation |
|
|
193
193
|
| `SUBMIT_SINGLE_COMMITS` | No | `"false"` | Submit one commit at a time to Gerrit |
|
|
194
194
|
| `USE_PR_AS_COMMIT` | No | `"false"` | Use PR title and body as the commit message |
|
|
195
195
|
| `PRESERVE_GITHUB_PRS` | No | `"true"` | Do not close GitHub PRs after pushing to Gerrit |
|
|
@@ -266,7 +266,7 @@ Input defaults match the composite action defaults.
|
|
|
266
266
|
| `G2G_USE_SSH_AGENT` | boolean | `true` | Use SSH agent instead of file-based keys |
|
|
267
267
|
| `ORGANIZATION` | string | repository owner | GitHub organization/owner |
|
|
268
268
|
| `PR_NUMBER` | string | `"0"` | PR to process on dispatch; `0` processes all |
|
|
269
|
-
| `FETCH_DEPTH` | string | `"10"` |
|
|
269
|
+
| `FETCH_DEPTH` | string | `"10"` | Git depth: PR, push, reconciliation |
|
|
270
270
|
| `SUBMIT_SINGLE_COMMITS` | boolean | `false` | Submit one commit at a time |
|
|
271
271
|
| `USE_PR_AS_COMMIT` | boolean | `false` | Use PR title and body as the commit message |
|
|
272
272
|
| `PRESERVE_GITHUB_PRS` | boolean | `true` | Do not close GitHub PRs after pushing |
|
|
@@ -19,18 +19,13 @@ inputs:
|
|
|
19
19
|
required: false
|
|
20
20
|
default: "false"
|
|
21
21
|
FETCH_DEPTH:
|
|
22
|
-
description: "Fetch depth for checkout"
|
|
23
|
-
required: false
|
|
24
|
-
default: "10"
|
|
25
|
-
SKIP_CHECKOUT:
|
|
26
22
|
description: >-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
nested checkout)
|
|
23
|
+
Depth of git history fetched. Applied to the tool's own fetch of
|
|
24
|
+
refs/pull/<N>/head, to the push-event checkout, and as the git log
|
|
25
|
+
window used to find merged commits during PR reconciliation, so
|
|
26
|
+
raising it widens how far back a merged change is matched
|
|
32
27
|
required: false
|
|
33
|
-
default: "
|
|
28
|
+
default: "10"
|
|
34
29
|
PR_NUMBER:
|
|
35
30
|
description: "Pull request number to process, use 0 to process all open"
|
|
36
31
|
required: false
|
|
@@ -213,19 +208,32 @@ runs:
|
|
|
213
208
|
echo "disabled=false" >> "$GITHUB_OUTPUT"
|
|
214
209
|
fi
|
|
215
210
|
|
|
216
|
-
- name: "Checkout repository"
|
|
217
|
-
#
|
|
218
|
-
|
|
211
|
+
- name: "Checkout repository (push events)"
|
|
212
|
+
# Push runs reconcile merged Gerrit changes back to their GitHub
|
|
213
|
+
# PRs, which reads commit trailers with a local `git show` in the
|
|
214
|
+
# working directory. Pull request runs need no checkout: the tool
|
|
215
|
+
# fetches refs/pull/<N>/head into its own temporary directory, and
|
|
216
|
+
# checking a fork head out here would both fail under
|
|
217
|
+
# pull_request_target and expose a fork-controlled .gitreview.
|
|
218
|
+
if: >-
|
|
219
|
+
steps.disabled-check.outputs.disabled != 'true'
|
|
220
|
+
&& github.event_name == 'push'
|
|
219
221
|
# yamllint disable-line rule:line-length
|
|
220
222
|
uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
|
|
221
223
|
with:
|
|
222
224
|
fetch-depth: ${{ inputs.FETCH_DEPTH }}
|
|
223
|
-
#
|
|
224
|
-
|
|
225
|
-
#
|
|
226
|
-
# explicit GITHUB_TOKEN env var, so the checkout token does not need
|
|
227
|
-
# to be persisted into the local git config.
|
|
225
|
+
# The action authenticates to Gerrit over SSH and to GitHub via
|
|
226
|
+
# an explicit GITHUB_TOKEN env var, so the checkout token does
|
|
227
|
+
# not need to be persisted into the local git config.
|
|
228
228
|
persist-credentials: false
|
|
229
|
+
# Callers may place files in the workspace that this action
|
|
230
|
+
# depends on. The bundled reusable workflow checks the action
|
|
231
|
+
# itself out to .g2g-action and then runs it from there, so a
|
|
232
|
+
# cleaning checkout would delete the action mid-run. That
|
|
233
|
+
# workflow also seeds the workspace root with the target
|
|
234
|
+
# repository first, because actions/checkout wipes a directory
|
|
235
|
+
# that is not already a git repository whatever `clean` says.
|
|
236
|
+
clean: false
|
|
229
237
|
|
|
230
238
|
- name: "Setup Python"
|
|
231
239
|
if: steps.disabled-check.outputs.disabled != 'true'
|
|
@@ -237,7 +245,7 @@ runs:
|
|
|
237
245
|
- name: "Setup uv"
|
|
238
246
|
if: steps.disabled-check.outputs.disabled != 'true'
|
|
239
247
|
# yamllint disable-line rule:line-length
|
|
240
|
-
uses: astral-sh/setup-uv@
|
|
248
|
+
uses: astral-sh/setup-uv@20cfd1bf945f4377ade1205e4dbc17946fc9a30d # v10.0.1
|
|
241
249
|
with:
|
|
242
250
|
enable-cache: false
|
|
243
251
|
|
|
@@ -396,6 +404,11 @@ runs:
|
|
|
396
404
|
GITHUB_SHA: ${{ github.sha }}
|
|
397
405
|
GITHUB_BASE_REF: ${{ github.base_ref }}
|
|
398
406
|
GITHUB_HEAD_REF: ${{ github.head_ref }}
|
|
407
|
+
# Full owner/repo of the PR head. Differs from GITHUB_REPOSITORY
|
|
408
|
+
# for fork pull requests, whose tree must not influence Gerrit
|
|
409
|
+
# target resolution.
|
|
410
|
+
# yamllint disable-line rule:line-length
|
|
411
|
+
PR_HEAD_REPO: ${{ github.event.pull_request.head.repo.full_name }}
|
|
399
412
|
GITHUB_ACTOR: ${{ github.actor }}
|
|
400
413
|
SYNC_ALL_OPEN_PRS: ${{ steps.extract.outputs.sync_all }}
|
|
401
414
|
PR_NUMBER: ${{ steps.extract.outputs.pr_number }}
|
|
@@ -84,7 +84,7 @@ set by GitHub Actions) and undergo proper boolean parsing.
|
|
|
84
84
|
| `--preserve-github-prs/--no-preserve-github-prs` | `PRESERVE_GITHUB_PRS` | `true` | Do not close GitHub PRs after pushing to Gerrit |
|
|
85
85
|
| `--close-merged-prs/--no-close-merged-prs` | `CLOSE_MERGED_PRS` | `true` | Close GitHub PRs when corresponding Gerrit changes merge |
|
|
86
86
|
| `--force` | `FORCE` | `false` | Force PR closure regardless of Gerrit change status (abandoned, etc.) |
|
|
87
|
-
| `--fetch-depth INTEGER` | `FETCH_DEPTH` | `10` |
|
|
87
|
+
| `--fetch-depth INTEGER` | `FETCH_DEPTH` | `10` | Git history depth: PR fetch, push checkout, reconciliation window |
|
|
88
88
|
| `--reviewers-email TEXT` | `REVIEWERS_EMAIL` | `""` | Email address(es) of reviewers (comma-separated) |
|
|
89
89
|
| `--organization TEXT` | `ORGANIZATION` | unset | Organization (defaults to `GITHUB_REPOSITORY_OWNER` when unset) |
|
|
90
90
|
| `--github-actor TEXT` | `GITHUB_ACTOR` | `""` | GitHub actor (username) who triggered the workflow |
|
|
@@ -16,6 +16,7 @@ action in detail. For a quick start and the full inputs table, see the
|
|
|
16
16
|
- [Closing Merged PRs](#closing-merged-prs)
|
|
17
17
|
- [Automatic Cleanup](#automatic-cleanup)
|
|
18
18
|
- [Restricting PRs to Automation Tools](#restricting-prs-to-automation-tools)
|
|
19
|
+
- [Fork Pull Requests](#fork-pull-requests)
|
|
19
20
|
- [Duplicate Detection](#duplicate-detection)
|
|
20
21
|
- [Commit Message Normalization](#commit-message-normalization)
|
|
21
22
|
- [Change-ID Reconciliation](#change-id-reconciliation)
|
|
@@ -284,6 +285,74 @@ Set `AUTOMATION_ONLY: "false"` to accept PRs from all users:
|
|
|
284
285
|
GERRIT_SSH_PRIVKEY_G2G: ${{ secrets.GERRIT_SSH_PRIVKEY_G2G }}
|
|
285
286
|
```
|
|
286
287
|
|
|
288
|
+
## Fork Pull Requests
|
|
289
|
+
|
|
290
|
+
A pull request raised from a fork carries a tree that someone without write
|
|
291
|
+
access to the base repository wrote. The tool treats that tree as untrusted
|
|
292
|
+
input.
|
|
293
|
+
|
|
294
|
+
### No runner checkout for pull requests
|
|
295
|
+
|
|
296
|
+
The action does not check the target repository out into the runner workspace
|
|
297
|
+
for pull request events. It fetches `refs/pull/<N>/head` into a private
|
|
298
|
+
temporary directory instead. That ref lives on the base repository and resolves
|
|
299
|
+
fork pull request heads, so the tool never contacts the fork directly.
|
|
300
|
+
|
|
301
|
+
This sidesteps the `pull_request_target` checkout restriction that
|
|
302
|
+
`actions/checkout` enforces, and keeps fork content out of the working
|
|
303
|
+
directory, where the tool might otherwise read it as configuration.
|
|
304
|
+
|
|
305
|
+
Push events still check the repository out. Those runs reconcile merged Gerrit
|
|
306
|
+
changes back to their GitHub pull requests, which reads commit trailers from
|
|
307
|
+
the working directory. A push carries no fork content, so the checkout is safe
|
|
308
|
+
there.
|
|
309
|
+
|
|
310
|
+
### Gerrit target resolution
|
|
311
|
+
|
|
312
|
+
For fork pull requests the tool ignores any `.gitreview` in the pull request
|
|
313
|
+
tree and resolves against the **base repository** instead. A fork could
|
|
314
|
+
otherwise redirect the push to a different Gerrit project simply by editing
|
|
315
|
+
`.gitreview`.
|
|
316
|
+
|
|
317
|
+
The tool applies the same treatment when it cannot establish where the pull
|
|
318
|
+
request head lives. Specific-PR `workflow_dispatch` runs and direct URL
|
|
319
|
+
invocations carry no pull request payload, and GitHub reports a null head
|
|
320
|
+
repository for a deleted fork. The tool resolves provenance through the API
|
|
321
|
+
where it can, and treats whatever remains unresolved as untrusted, so a missing
|
|
322
|
+
signal never earns a fork unwarranted trust.
|
|
323
|
+
|
|
324
|
+
Resolution order for a fork pull request:
|
|
325
|
+
|
|
326
|
+
1. `.gitreview` from the base repository at the pull request's base branch,
|
|
327
|
+
via the GitHub API or `raw.githubusercontent.com`
|
|
328
|
+
2. Explicit `GERRIT_SERVER` / `GERRIT_SERVER_PORT` / `GERRIT_PROJECT` inputs
|
|
329
|
+
3. Per-organization configuration file
|
|
330
|
+
4. Derivation from the organization name (`gerrit.[org].org`)
|
|
331
|
+
|
|
332
|
+
The lookup stops at the base branch. It does not fall back to the repository
|
|
333
|
+
default branch, and it does not read `.gitreview` through the API without an
|
|
334
|
+
authoritative base ref, because either would answer for a branch the pull
|
|
335
|
+
request does not target — and `.gitreview` outranks the explicit inputs.
|
|
336
|
+
|
|
337
|
+
The base repository's copy carries the same authority and lies outside an
|
|
338
|
+
attacker's reach, so this costs no accuracy. Skipping straight to derivation
|
|
339
|
+
would instead guess the Gerrit project name, and that guess goes wrong for
|
|
340
|
+
repositories whose name contains a hyphen that does not mark a path separator.
|
|
341
|
+
|
|
342
|
+
For the same reason, the tool drops branch names that originate in the fork
|
|
343
|
+
(`GITHUB_HEAD_REF` and the pull request head ref) from base-repository
|
|
344
|
+
lookups. Duplicate detection, which resolves `.gitreview` independently and
|
|
345
|
+
earlier, applies the same rule.
|
|
346
|
+
|
|
347
|
+
Same-repository pull requests keep their previous behaviour and still read
|
|
348
|
+
`.gitreview` from the pull request tree.
|
|
349
|
+
|
|
350
|
+
### Approval gating
|
|
351
|
+
|
|
352
|
+
The tool does not yet require a maintainer approval before it transfers a fork
|
|
353
|
+
pull request to Gerrit. Until it does, use `AUTOMATION_ONLY` (see above) to
|
|
354
|
+
control which pull requests the tool accepts.
|
|
355
|
+
|
|
287
356
|
## Duplicate Detection
|
|
288
357
|
|
|
289
358
|
Duplicate detection uses a scoring-based approach. The detector compares the
|
|
@@ -139,6 +139,11 @@ ignore = [
|
|
|
139
139
|
"sitecustomize.py" = ["S110", "SIM103", "SIM105", "PLW2901"]
|
|
140
140
|
"src/github2gerrit/duplicate_detection.py" = ["S310"]
|
|
141
141
|
"src/github2gerrit/gerrit_rest.py" = ["S310", "TRY301"]
|
|
142
|
+
# S310 audits urlopen for non-HTTP schemes such as file:. This module
|
|
143
|
+
# builds the URL from a literal https://raw.githubusercontent.com/ prefix
|
|
144
|
+
# and passes it through _validate_raw_url, which requires scheme https and
|
|
145
|
+
# host raw.githubusercontent.com before the fetch runs.
|
|
146
|
+
"src/github2gerrit/gitreview.py" = ["S310"]
|
|
142
147
|
|
|
143
148
|
[tool.ruff.lint.isort]
|
|
144
149
|
known-first-party = ["github2gerrit"]
|
|
@@ -961,7 +961,11 @@ def main(
|
|
|
961
961
|
10,
|
|
962
962
|
"--fetch-depth",
|
|
963
963
|
envvar="FETCH_DEPTH",
|
|
964
|
-
help=
|
|
964
|
+
help=(
|
|
965
|
+
"Git history depth. Also the git log window for merged-PR "
|
|
966
|
+
"reconciliation, so lowering it narrows how far back a "
|
|
967
|
+
"merged change is matched."
|
|
968
|
+
),
|
|
965
969
|
),
|
|
966
970
|
gerrit_known_hosts: str = typer.Option(
|
|
967
971
|
"",
|
|
@@ -1429,6 +1433,25 @@ def _finish_bulk_no_prs(
|
|
|
1429
1433
|
return True # Success (no failures because no work)
|
|
1430
1434
|
|
|
1431
1435
|
|
|
1436
|
+
def _head_repo_for_pr(pr: Any) -> str:
|
|
1437
|
+
"""Return the ``owner/repo`` of a PyGithub pull request's head.
|
|
1438
|
+
|
|
1439
|
+
Used in bulk mode, where each pull request carries its own
|
|
1440
|
+
provenance rather than inheriting it from the triggering event.
|
|
1441
|
+
Returns an empty string when unavailable.
|
|
1442
|
+
"""
|
|
1443
|
+
head = getattr(pr, "head", None)
|
|
1444
|
+
repo = getattr(head, "repo", None)
|
|
1445
|
+
full_name = getattr(repo, "full_name", "")
|
|
1446
|
+
return str(full_name or "").strip()
|
|
1447
|
+
|
|
1448
|
+
|
|
1449
|
+
def _ref_for_pr(pr: Any, side: str) -> str:
|
|
1450
|
+
"""Return ``pr.<side>.ref`` as a string, or empty when unavailable."""
|
|
1451
|
+
end = getattr(pr, side, None)
|
|
1452
|
+
return str(getattr(end, "ref", "") or "").strip()
|
|
1453
|
+
|
|
1454
|
+
|
|
1432
1455
|
def _build_bulk_pr_tasks(
|
|
1433
1456
|
gh: GitHubContext, prs_list: list[Any]
|
|
1434
1457
|
) -> list[tuple[Any, models.GitHubContext]]:
|
|
@@ -1439,6 +1462,10 @@ def _build_bulk_pr_tasks(
|
|
|
1439
1462
|
if pr_number <= 0:
|
|
1440
1463
|
continue
|
|
1441
1464
|
|
|
1465
|
+
# Bulk runs are triggered by workflow_dispatch or a repository
|
|
1466
|
+
# URL, so the outer context carries no PR refs. Take each pull
|
|
1467
|
+
# request's own refs so .gitreview resolves against the branch
|
|
1468
|
+
# the PR actually targets.
|
|
1442
1469
|
per_ctx = models.GitHubContext(
|
|
1443
1470
|
event_name=gh.event_name,
|
|
1444
1471
|
event_action=gh.event_action,
|
|
@@ -1448,9 +1475,10 @@ def _build_bulk_pr_tasks(
|
|
|
1448
1475
|
server_url=gh.server_url,
|
|
1449
1476
|
run_id=gh.run_id,
|
|
1450
1477
|
sha=gh.sha,
|
|
1451
|
-
base_ref=gh.base_ref,
|
|
1452
|
-
head_ref=gh.head_ref,
|
|
1478
|
+
base_ref=_ref_for_pr(pr, "base") or gh.base_ref,
|
|
1479
|
+
head_ref=_ref_for_pr(pr, "head") or gh.head_ref,
|
|
1453
1480
|
pr_number=pr_number,
|
|
1481
|
+
head_repo=_head_repo_for_pr(pr),
|
|
1454
1482
|
)
|
|
1455
1483
|
pr_tasks.append((pr, per_ctx))
|
|
1456
1484
|
return pr_tasks
|
|
@@ -2154,40 +2182,51 @@ def _load_effective_inputs() -> Inputs:
|
|
|
2154
2182
|
|
|
2155
2183
|
|
|
2156
2184
|
def _augment_pr_refs_if_needed(gh: GitHubContext) -> GitHubContext:
|
|
2157
|
-
|
|
2158
|
-
|
|
2159
|
-
|
|
2160
|
-
|
|
2161
|
-
|
|
2162
|
-
|
|
2163
|
-
|
|
2164
|
-
|
|
2165
|
-
|
|
2166
|
-
|
|
2167
|
-
|
|
2168
|
-
|
|
2169
|
-
|
|
2170
|
-
|
|
2171
|
-
|
|
2172
|
-
|
|
2173
|
-
|
|
2174
|
-
|
|
2175
|
-
|
|
2176
|
-
|
|
2177
|
-
|
|
2178
|
-
|
|
2179
|
-
|
|
2180
|
-
|
|
2181
|
-
|
|
2182
|
-
|
|
2183
|
-
|
|
2184
|
-
|
|
2185
|
-
|
|
2186
|
-
|
|
2187
|
-
|
|
2188
|
-
|
|
2189
|
-
|
|
2190
|
-
|
|
2185
|
+
"""Fill in PR refs and provenance that the event context lacks.
|
|
2186
|
+
|
|
2187
|
+
Direct URL invocations and specific-PR ``workflow_dispatch`` runs
|
|
2188
|
+
carry no pull request payload, so ``base_ref``, ``head_ref`` and
|
|
2189
|
+
``head_repo`` all arrive empty. Provenance in particular must not
|
|
2190
|
+
stay unknown: ``_read_gitreview`` treats an unresolved head
|
|
2191
|
+
repository as untrusted, so leaving it blank needlessly forfeits the
|
|
2192
|
+
PR tree's own ``.gitreview`` on same-repository pull requests.
|
|
2193
|
+
"""
|
|
2194
|
+
needs_refs = not gh.head_ref or not gh.base_ref
|
|
2195
|
+
needs_provenance = not gh.head_repo
|
|
2196
|
+
if not gh.pr_number or not (needs_refs or needs_provenance):
|
|
2197
|
+
return gh
|
|
2198
|
+
|
|
2199
|
+
# Deliberately not gated on event name. Pull request events populate
|
|
2200
|
+
# both refs and provenance from the payload and so return above;
|
|
2201
|
+
# anything still missing them here (workflow_dispatch, issue_comment,
|
|
2202
|
+
# direct URL) needs the API regardless of how it was triggered.
|
|
2203
|
+
try:
|
|
2204
|
+
client = build_client()
|
|
2205
|
+
repo = get_repo_from_env(client)
|
|
2206
|
+
pr_obj = get_pull(repo, int(gh.pr_number))
|
|
2207
|
+
base_ref = _ref_for_pr(pr_obj, "base")
|
|
2208
|
+
head_ref = _ref_for_pr(pr_obj, "head")
|
|
2209
|
+
head_repo = _head_repo_for_pr(pr_obj)
|
|
2210
|
+
head_sha = str(
|
|
2211
|
+
getattr(getattr(pr_obj, "head", object()), "sha", "") or ""
|
|
2212
|
+
)
|
|
2213
|
+
if base_ref:
|
|
2214
|
+
os.environ["GITHUB_BASE_REF"] = base_ref
|
|
2215
|
+
log.debug("Resolved base_ref via GitHub API: %s", base_ref)
|
|
2216
|
+
if head_ref:
|
|
2217
|
+
os.environ["GITHUB_HEAD_REF"] = head_ref
|
|
2218
|
+
log.debug("Resolved head_ref via GitHub API: %s", head_ref)
|
|
2219
|
+
if head_repo:
|
|
2220
|
+
os.environ["PR_HEAD_REPO"] = head_repo
|
|
2221
|
+
log.debug("Resolved head repository via GitHub API: %s", head_repo)
|
|
2222
|
+
if head_sha:
|
|
2223
|
+
os.environ["GITHUB_SHA"] = head_sha
|
|
2224
|
+
log.debug("Resolved head sha via GitHub API: %s", head_sha)
|
|
2225
|
+
except Exception as exc:
|
|
2226
|
+
log.debug("Could not resolve PR refs via GitHub API: %s", exc)
|
|
2227
|
+
return gh
|
|
2228
|
+
else:
|
|
2229
|
+
return _read_github_context()
|
|
2191
2230
|
|
|
2192
2231
|
|
|
2193
2232
|
def _process_close_gerrit_change(
|
|
@@ -3019,6 +3058,31 @@ def _extract_pr_number(evt: dict[str, Any]) -> int | None:
|
|
|
3019
3058
|
return None
|
|
3020
3059
|
|
|
3021
3060
|
|
|
3061
|
+
def _read_head_repo(evt: dict[str, Any]) -> str:
|
|
3062
|
+
"""Return the ``owner/repo`` of the pull request head repository.
|
|
3063
|
+
|
|
3064
|
+
Prefers the ``PR_HEAD_REPO`` environment variable supplied by the
|
|
3065
|
+
composite action, falling back to the raw event payload so the CLI
|
|
3066
|
+
behaves identically when invoked outside that wrapper.
|
|
3067
|
+
|
|
3068
|
+
Returns an empty string when the provenance cannot be established.
|
|
3069
|
+
"""
|
|
3070
|
+
env_value = os.getenv("PR_HEAD_REPO", "").strip()
|
|
3071
|
+
if env_value:
|
|
3072
|
+
return env_value
|
|
3073
|
+
|
|
3074
|
+
pr = evt.get("pull_request")
|
|
3075
|
+
if isinstance(pr, dict):
|
|
3076
|
+
head = pr.get("head")
|
|
3077
|
+
if isinstance(head, dict):
|
|
3078
|
+
repo = head.get("repo")
|
|
3079
|
+
if isinstance(repo, dict):
|
|
3080
|
+
full_name = repo.get("full_name")
|
|
3081
|
+
if isinstance(full_name, str):
|
|
3082
|
+
return full_name.strip()
|
|
3083
|
+
return ""
|
|
3084
|
+
|
|
3085
|
+
|
|
3022
3086
|
def _read_github_context() -> GitHubContext:
|
|
3023
3087
|
event_name = os.getenv("GITHUB_EVENT_NAME", "")
|
|
3024
3088
|
event_action = ""
|
|
@@ -3037,6 +3101,7 @@ def _read_github_context() -> GitHubContext:
|
|
|
3037
3101
|
|
|
3038
3102
|
base_ref = os.getenv("GITHUB_BASE_REF", "")
|
|
3039
3103
|
head_ref = os.getenv("GITHUB_HEAD_REF", "")
|
|
3104
|
+
head_repo = _read_head_repo(evt)
|
|
3040
3105
|
|
|
3041
3106
|
pr_number = _extract_pr_number(evt)
|
|
3042
3107
|
if pr_number is None:
|
|
@@ -3056,6 +3121,7 @@ def _read_github_context() -> GitHubContext:
|
|
|
3056
3121
|
base_ref=base_ref,
|
|
3057
3122
|
head_ref=head_ref,
|
|
3058
3123
|
pr_number=pr_number,
|
|
3124
|
+
head_repo=head_repo,
|
|
3059
3125
|
)
|
|
3060
3126
|
return ctx
|
|
3061
3127
|
|
|
@@ -520,9 +520,26 @@ def _read_gitreview_host(repository: str | None = None) -> str | None:
|
|
|
520
520
|
Delegates to the shared :mod:`github2gerrit.gitreview` module which
|
|
521
521
|
consolidates all ``.gitreview`` parsing and fetching logic.
|
|
522
522
|
|
|
523
|
-
|
|
524
|
-
|
|
525
|
-
|
|
523
|
+
This runs during parameter derivation, before the pull request
|
|
524
|
+
context is read, so provenance comes from ``PR_HEAD_REPO`` as the
|
|
525
|
+
composite action exports it.
|
|
526
|
+
|
|
527
|
+
``GITHUB_HEAD_REF`` is consulted only when the head is known to live
|
|
528
|
+
in the base repository. A fork chooses its own branch name, and one
|
|
529
|
+
matching a real base-repository branch would otherwise select that
|
|
530
|
+
branch's host. Keeping the head ref for a *trusted* head matters
|
|
531
|
+
too: :meth:`Orchestrator._read_gitreview` reads the head tree in
|
|
532
|
+
that case, and dropping it here would let derivation record one host
|
|
533
|
+
while the pipeline pushes to another.
|
|
534
|
+
|
|
535
|
+
Provenance that cannot be established counts as untrusted, so the
|
|
536
|
+
absent-signal case falls back to the base ref alone.
|
|
537
|
+
|
|
538
|
+
The local working-directory file is still read. This layer cannot
|
|
539
|
+
tell a pull request the *tool* is processing from one the *workflow*
|
|
540
|
+
merely runs inside, so any attempt to skip it here also breaks
|
|
541
|
+
legitimate local reads. See issue #386: the fix belongs with the
|
|
542
|
+
wider question of tracking where a configuration value came from.
|
|
526
543
|
|
|
527
544
|
Args:
|
|
528
545
|
repository: GitHub repository in owner/repo format (optional).
|
|
@@ -532,8 +549,26 @@ def _read_gitreview_host(repository: str | None = None) -> str | None:
|
|
|
532
549
|
The host string from .gitreview, or None if unavailable.
|
|
533
550
|
"""
|
|
534
551
|
from .gitreview import read_gitreview_host
|
|
535
|
-
|
|
536
|
-
|
|
552
|
+
from .models import head_repo_is_trusted
|
|
553
|
+
|
|
554
|
+
repo_full = (repository or os.getenv("GITHUB_REPOSITORY") or "").strip()
|
|
555
|
+
head_repo = os.getenv("PR_HEAD_REPO", "").strip()
|
|
556
|
+
trusted_head = head_repo_is_trusted(repo_full, head_repo)
|
|
557
|
+
|
|
558
|
+
branches: list[str] = []
|
|
559
|
+
if trusted_head:
|
|
560
|
+
head_ref = os.getenv("GITHUB_HEAD_REF", "").strip()
|
|
561
|
+
if head_ref:
|
|
562
|
+
branches.append(head_ref)
|
|
563
|
+
base_ref = os.getenv("GITHUB_BASE_REF", "").strip()
|
|
564
|
+
if base_ref:
|
|
565
|
+
branches.append(base_ref)
|
|
566
|
+
|
|
567
|
+
return read_gitreview_host(
|
|
568
|
+
repository,
|
|
569
|
+
branches=tuple(branches),
|
|
570
|
+
include_env_refs=False,
|
|
571
|
+
)
|
|
537
572
|
|
|
538
573
|
|
|
539
574
|
def derive_gerrit_parameters(
|