github2gerrit 0.1.9__tar.gz → 0.1.10__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 (90) hide show
  1. {github2gerrit-0.1.9 → github2gerrit-0.1.10}/.github/workflows/github2gerrit.yaml +22 -16
  2. {github2gerrit-0.1.9 → github2gerrit-0.1.10}/.pre-commit-config.yaml +1 -1
  3. {github2gerrit-0.1.9 → github2gerrit-0.1.10}/PKG-INFO +24 -2
  4. {github2gerrit-0.1.9 → github2gerrit-0.1.10}/README.md +23 -1
  5. {github2gerrit-0.1.9 → github2gerrit-0.1.10}/action.yaml +51 -42
  6. {github2gerrit-0.1.9 → github2gerrit-0.1.10}/src/github2gerrit/cli.py +10 -9
  7. {github2gerrit-0.1.9 → github2gerrit-0.1.10}/src/github2gerrit/config.py +1 -0
  8. {github2gerrit-0.1.9 → github2gerrit-0.1.10}/src/github2gerrit/core.py +12 -0
  9. {github2gerrit-0.1.9 → github2gerrit-0.1.10}/src/github2gerrit/duplicate_detection.py +2 -2
  10. {github2gerrit-0.1.9 → github2gerrit-0.1.10}/src/github2gerrit/similarity.py +2 -1
  11. {github2gerrit-0.1.9 → github2gerrit-0.1.10}/src/github2gerrit.egg-info/PKG-INFO +24 -2
  12. {github2gerrit-0.1.9 → github2gerrit-0.1.10}/tests/test_gerrit_change_id_footer.py +21 -8
  13. {github2gerrit-0.1.9 → github2gerrit-0.1.10}/tests/test_pr_content_filter_integration.py +6 -2
  14. {github2gerrit-0.1.9 → github2gerrit-0.1.10}/.editorconfig +0 -0
  15. {github2gerrit-0.1.9 → github2gerrit-0.1.10}/.github/actionlint.yaml +0 -0
  16. {github2gerrit-0.1.9 → github2gerrit-0.1.10}/.github/dependabot.yml +0 -0
  17. {github2gerrit-0.1.9 → github2gerrit-0.1.10}/.github/release-drafter.yml +0 -0
  18. {github2gerrit-0.1.9 → github2gerrit-0.1.10}/.github/workflows/build-test-release.yaml +0 -0
  19. {github2gerrit-0.1.9 → github2gerrit-0.1.10}/.github/workflows/build-test.yaml +0 -0
  20. {github2gerrit-0.1.9 → github2gerrit-0.1.10}/.github/workflows/dependencies.yaml +0 -0
  21. {github2gerrit-0.1.9 → github2gerrit-0.1.10}/.github/workflows/release-drafter.yaml +0 -0
  22. {github2gerrit-0.1.9 → github2gerrit-0.1.10}/.github/workflows/semantic-pull-request.yaml +0 -0
  23. {github2gerrit-0.1.9 → github2gerrit-0.1.10}/.github/workflows/sha-pinned-actions.yaml +0 -0
  24. {github2gerrit-0.1.9 → github2gerrit-0.1.10}/.github/workflows/testing.yaml +0 -0
  25. {github2gerrit-0.1.9 → github2gerrit-0.1.10}/.gitignore +0 -0
  26. {github2gerrit-0.1.9 → github2gerrit-0.1.10}/.gitlint +0 -0
  27. {github2gerrit-0.1.9 → github2gerrit-0.1.10}/.markdownlint.yaml +0 -0
  28. {github2gerrit-0.1.9 → github2gerrit-0.1.10}/.readthedocs.yml +0 -0
  29. {github2gerrit-0.1.9 → github2gerrit-0.1.10}/.yamllint +0 -0
  30. {github2gerrit-0.1.9 → github2gerrit-0.1.10}/LICENSE +0 -0
  31. {github2gerrit-0.1.9 → github2gerrit-0.1.10}/LICENSES/Apache-2.0.txt +0 -0
  32. {github2gerrit-0.1.9 → github2gerrit-0.1.10}/REUSE.toml +0 -0
  33. {github2gerrit-0.1.9 → github2gerrit-0.1.10}/docs/github2gerrit_token_permissions_classic.png +0 -0
  34. {github2gerrit-0.1.9 → github2gerrit-0.1.10}/pyproject.toml +0 -0
  35. {github2gerrit-0.1.9 → github2gerrit-0.1.10}/setup.cfg +0 -0
  36. {github2gerrit-0.1.9 → github2gerrit-0.1.10}/sitecustomize.py +0 -0
  37. {github2gerrit-0.1.9 → github2gerrit-0.1.10}/src/github2gerrit/__init__.py +0 -0
  38. {github2gerrit-0.1.9 → github2gerrit-0.1.10}/src/github2gerrit/commit_normalization.py +0 -0
  39. {github2gerrit-0.1.9 → github2gerrit-0.1.10}/src/github2gerrit/external_api.py +0 -0
  40. {github2gerrit-0.1.9 → github2gerrit-0.1.10}/src/github2gerrit/gerrit_rest.py +0 -0
  41. {github2gerrit-0.1.9 → github2gerrit-0.1.10}/src/github2gerrit/gerrit_urls.py +0 -0
  42. {github2gerrit-0.1.9 → github2gerrit-0.1.10}/src/github2gerrit/github_api.py +0 -0
  43. {github2gerrit-0.1.9 → github2gerrit-0.1.10}/src/github2gerrit/gitutils.py +0 -0
  44. {github2gerrit-0.1.9 → github2gerrit-0.1.10}/src/github2gerrit/models.py +0 -0
  45. {github2gerrit-0.1.9 → github2gerrit-0.1.10}/src/github2gerrit/pr_content_filter.py +0 -0
  46. {github2gerrit-0.1.9 → github2gerrit-0.1.10}/src/github2gerrit/ssh_agent_setup.py +0 -0
  47. {github2gerrit-0.1.9 → github2gerrit-0.1.10}/src/github2gerrit/ssh_common.py +0 -0
  48. {github2gerrit-0.1.9 → github2gerrit-0.1.10}/src/github2gerrit/ssh_discovery.py +0 -0
  49. {github2gerrit-0.1.9 → github2gerrit-0.1.10}/src/github2gerrit/utils.py +0 -0
  50. {github2gerrit-0.1.9 → github2gerrit-0.1.10}/src/github2gerrit.egg-info/SOURCES.txt +0 -0
  51. {github2gerrit-0.1.9 → github2gerrit-0.1.10}/src/github2gerrit.egg-info/dependency_links.txt +0 -0
  52. {github2gerrit-0.1.9 → github2gerrit-0.1.10}/src/github2gerrit.egg-info/entry_points.txt +0 -0
  53. {github2gerrit-0.1.9 → github2gerrit-0.1.10}/src/github2gerrit.egg-info/requires.txt +0 -0
  54. {github2gerrit-0.1.9 → github2gerrit-0.1.10}/src/github2gerrit.egg-info/top_level.txt +0 -0
  55. {github2gerrit-0.1.9 → github2gerrit-0.1.10}/tests/conftest.py +0 -0
  56. {github2gerrit-0.1.9 → github2gerrit-0.1.10}/tests/fixtures/__init__.py +0 -0
  57. {github2gerrit-0.1.9 → github2gerrit-0.1.10}/tests/fixtures/make_repo.py +0 -0
  58. {github2gerrit-0.1.9 → github2gerrit-0.1.10}/tests/test_change_id_deduplication.py +0 -0
  59. {github2gerrit-0.1.9 → github2gerrit-0.1.10}/tests/test_cli.py +0 -0
  60. {github2gerrit-0.1.9 → github2gerrit-0.1.10}/tests/test_cli_helpers.py +0 -0
  61. {github2gerrit-0.1.9 → github2gerrit-0.1.10}/tests/test_cli_outputs_file.py +0 -0
  62. {github2gerrit-0.1.9 → github2gerrit-0.1.10}/tests/test_cli_url_and_dryrun.py +0 -0
  63. {github2gerrit-0.1.9 → github2gerrit-0.1.10}/tests/test_commit_normalization.py +0 -0
  64. {github2gerrit-0.1.9 → github2gerrit-0.1.10}/tests/test_config_and_reviewers.py +0 -0
  65. {github2gerrit-0.1.9 → github2gerrit-0.1.10}/tests/test_config_helpers.py +0 -0
  66. {github2gerrit-0.1.9 → github2gerrit-0.1.10}/tests/test_core_close_pr_policy.py +0 -0
  67. {github2gerrit-0.1.9 → github2gerrit-0.1.10}/tests/test_core_config_and_errors.py +0 -0
  68. {github2gerrit-0.1.9 → github2gerrit-0.1.10}/tests/test_core_gerrit_backref_comment.py +0 -0
  69. {github2gerrit-0.1.9 → github2gerrit-0.1.10}/tests/test_core_gerrit_push_errors.py +0 -0
  70. {github2gerrit-0.1.9 → github2gerrit-0.1.10}/tests/test_core_gerrit_rest_results.py +0 -0
  71. {github2gerrit-0.1.9 → github2gerrit-0.1.10}/tests/test_core_integration_fixture_repo.py +0 -0
  72. {github2gerrit-0.1.9 → github2gerrit-0.1.10}/tests/test_core_prepare_commits.py +0 -0
  73. {github2gerrit-0.1.9 → github2gerrit-0.1.10}/tests/test_core_ssh_setup.py +0 -0
  74. {github2gerrit-0.1.9 → github2gerrit-0.1.10}/tests/test_duplicate_detection.py +0 -0
  75. {github2gerrit-0.1.9 → github2gerrit-0.1.10}/tests/test_external_api_framework.py +0 -0
  76. {github2gerrit-0.1.9 → github2gerrit-0.1.10}/tests/test_gerrit_rest_client.py +0 -0
  77. {github2gerrit-0.1.9 → github2gerrit-0.1.10}/tests/test_gerrit_urls.py +0 -0
  78. {github2gerrit-0.1.9 → github2gerrit-0.1.10}/tests/test_gerrit_urls_more.py +0 -0
  79. {github2gerrit-0.1.9 → github2gerrit-0.1.10}/tests/test_ghe_and_gitreview_args.py +0 -0
  80. {github2gerrit-0.1.9 → github2gerrit-0.1.10}/tests/test_github_api_helpers.py +0 -0
  81. {github2gerrit-0.1.9 → github2gerrit-0.1.10}/tests/test_github_api_retry_and_helpers.py +0 -0
  82. {github2gerrit-0.1.9 → github2gerrit-0.1.10}/tests/test_gitutils_helpers.py +0 -0
  83. {github2gerrit-0.1.9 → github2gerrit-0.1.10}/tests/test_misc_small_coverage.py +0 -0
  84. {github2gerrit-0.1.9 → github2gerrit-0.1.10}/tests/test_pr_content_filter.py +0 -0
  85. {github2gerrit-0.1.9 → github2gerrit-0.1.10}/tests/test_ssh_agent.py +0 -0
  86. {github2gerrit-0.1.9 → github2gerrit-0.1.10}/tests/test_ssh_common.py +0 -0
  87. {github2gerrit-0.1.9 → github2gerrit-0.1.10}/tests/test_ssh_discovery.py +0 -0
  88. {github2gerrit-0.1.9 → github2gerrit-0.1.10}/tests/test_url_parser.py +0 -0
  89. {github2gerrit-0.1.9 → github2gerrit-0.1.10}/tests/test_utils.py +0 -0
  90. {github2gerrit-0.1.9 → github2gerrit-0.1.10}/uv.lock +0 -0
@@ -25,7 +25,7 @@ on:
25
25
  type: string
26
26
  GERRIT_KNOWN_HOSTS:
27
27
  description: "known hosts"
28
- required: true
28
+ required: false
29
29
  type: string
30
30
  GERRIT_SERVER:
31
31
  description: "Gerrit hostname ex: git.opendaylight.org"
@@ -44,11 +44,11 @@ on:
44
44
  type: string
45
45
  GERRIT_SSH_USER_G2G:
46
46
  description: "Gerrit user-id for SSH"
47
- required: true
47
+ required: false
48
48
  type: string
49
49
  GERRIT_SSH_USER_G2G_EMAIL:
50
50
  description: "Email of the SSH user"
51
- required: true
51
+ required: false
52
52
  type: string
53
53
  ORGANIZATION:
54
54
  description: "Organization name, e.g. opendaylight"
@@ -95,6 +95,11 @@ on:
95
95
  required: false
96
96
  default: ""
97
97
  type: string
98
+ ALLOW_DUPLICATES:
99
+ description: "Allow submitting duplicate changes without error"
100
+ required: false
101
+ default: false
102
+ type: boolean
98
103
  secrets:
99
104
  GERRIT_SSH_PRIVKEY_G2G:
100
105
  description: "SSH Private key"
@@ -116,22 +121,18 @@ on:
116
121
  required: false
117
122
  default: false
118
123
  type: boolean
119
- FETCH_DEPTH:
120
- description: "fetch-depth for the clone. (Default: 10)"
121
- required: false
122
- default: "10"
123
- type: string
124
+
124
125
  GERRIT_KNOWN_HOSTS:
125
126
  description: "known hosts"
126
- required: true
127
+ required: false
127
128
  type: string
128
129
  GERRIT_SSH_USER_G2G:
129
130
  description: "Gerrit user-id for SSH"
130
- required: true
131
+ required: false
131
132
  type: string
132
133
  GERRIT_SSH_USER_G2G_EMAIL:
133
134
  description: "Email of the SSH user"
134
- required: true
135
+ required: false
135
136
  type: string
136
137
 
137
138
  PRESERVE_GITHUB_PRS:
@@ -149,6 +150,11 @@ on:
149
150
  required: false
150
151
  default: ""
151
152
  type: string
153
+ ALLOW_DUPLICATES:
154
+ description: "Allow submitting duplicate changes without error"
155
+ required: false
156
+ default: false
157
+ type: boolean
152
158
 
153
159
  concurrency:
154
160
  group: reusable-${{ github.workflow }}-${{ github.run_id }}
@@ -159,7 +165,7 @@ jobs:
159
165
  # Manual run: allow optional PR_NUMBER (0 => process all PRs)
160
166
  if: ${{ github.event_name == 'workflow_dispatch' }}
161
167
  runs-on: ubuntu-latest
162
- timeout-minutes: 6
168
+ timeout-minutes: 12
163
169
  steps:
164
170
  # yamllint disable rule:line-length
165
171
  # PR_NUMBER normalization is handled by the composite action
@@ -169,13 +175,12 @@ jobs:
169
175
  with:
170
176
  SUBMIT_SINGLE_COMMITS: ${{ inputs.SUBMIT_SINGLE_COMMITS }}
171
177
  USE_PR_AS_COMMIT: ${{ inputs.USE_PR_AS_COMMIT }}
172
- FETCH_DEPTH: ${{ inputs.FETCH_DEPTH }}
178
+
173
179
  GERRIT_KNOWN_HOSTS: ${{ inputs.GERRIT_KNOWN_HOSTS }}
174
180
  GERRIT_SSH_PRIVKEY_G2G: ${{ secrets.GERRIT_SSH_PRIVKEY_G2G }}
175
181
  GERRIT_SSH_USER_G2G: ${{ inputs.GERRIT_SSH_USER_G2G }}
176
182
  GERRIT_SSH_USER_G2G_EMAIL: ${{ inputs.GERRIT_SSH_USER_G2G_EMAIL }}
177
- ORGANIZATION: ${{ inputs.ORGANIZATION }}
178
- ALLOW_GHE_URLS: ${{ inputs.ALLOW_GHE_URLS }}
183
+ ALLOW_DUPLICATES: ${{ inputs.ALLOW_DUPLICATES }}
179
184
  PRESERVE_GITHUB_PRS: ${{ inputs.PRESERVE_GITHUB_PRS }}
180
185
  DRY_RUN: ${{ inputs.DRY_RUN }}
181
186
  ISSUE_ID: ${{ inputs.ISSUE_ID }}
@@ -185,7 +190,7 @@ jobs:
185
190
  # Only run if we have a proper pull request context
186
191
  if: ${{ github.event.pull_request.number || github.event.issue.number }}
187
192
  runs-on: ubuntu-latest
188
- timeout-minutes: 15
193
+ timeout-minutes: 12
189
194
  permissions:
190
195
  contents: read
191
196
  pull-requests: write
@@ -206,6 +211,7 @@ jobs:
206
211
  ALLOW_GHE_URLS: ${{ inputs.ALLOW_GHE_URLS }}
207
212
  PRESERVE_GITHUB_PRS: ${{ inputs.PRESERVE_GITHUB_PRS }}
208
213
  DRY_RUN: ${{ inputs.DRY_RUN }}
214
+ ALLOW_DUPLICATES: ${{ inputs.ALLOW_DUPLICATES }}
209
215
  ISSUE_ID: ${{ inputs.ISSUE_ID }}
210
216
  GERRIT_SERVER: ${{ inputs.GERRIT_SERVER }}
211
217
  GERRIT_SERVER_PORT: ${{ inputs.GERRIT_SERVER_PORT }}
@@ -58,7 +58,7 @@ repos:
58
58
  types: [yaml]
59
59
 
60
60
  - repo: https://github.com/astral-sh/ruff-pre-commit
61
- rev: 54a455f7ce629598b7535ff828fd5fb796f4b83f # frozen: v0.12.9
61
+ rev: 0acff885bcb16381b67930fefb91e460202f172c # frozen: v0.12.10
62
62
  hooks:
63
63
  - id: ruff
64
64
  files: ^(src|scripts|tests)/.+\.py$
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: github2gerrit
3
- Version: 0.1.9
3
+ Version: 0.1.10
4
4
  Summary: Submit a GitHub pull request to a Gerrit repository.
5
5
  Author-email: Matthew Watkins <mwatkins@linuxfoundation.org>
6
6
  License-Expression: Apache-2.0
@@ -140,6 +140,27 @@ with:
140
140
  When allowed, duplicates generate warnings but processing continues.
141
141
  The tool exits with code 3 when it detects duplicates and they are not allowed.
142
142
 
143
+ ### Configuring duplicate detection scope
144
+
145
+ By default, the duplicate detector considers changes with status `open` when searching for potential duplicates.
146
+ You can customize which Gerrit change states to check using `--duplicate-types` or setting `DUPLICATE_TYPES`:
147
+
148
+ ```bash
149
+ # CLI usage - check against open and merged changes
150
+ github2gerrit --duplicate-types=open,merged https://github.com/org/repo
151
+
152
+ # Environment variable
153
+ DUPLICATE_TYPES=open,merged,abandoned github2gerrit https://github.com/org/repo
154
+
155
+ # GitHub Actions
156
+ uses: onap/github2gerrit@main
157
+ with:
158
+ DUPLICATE_TYPES: 'open,merged'
159
+ ```
160
+
161
+ Valid change states include `open`, `merged`, and `abandoned`. This setting determines which existing changes
162
+ to check when evaluating whether a new change would be a duplicate.
163
+
143
164
  ## Commit Message Normalization
144
165
 
145
166
  The tool includes intelligent commit message normalization that automatically
@@ -368,6 +389,7 @@ Key options include:
368
389
  - `--use-pr-as-commit`: Use PR title/body as commit message (`USE_PR_AS_COMMIT`)
369
390
  - `--issue-id`: Add an Issue-ID trailer (e.g., "Issue-ID: ABC-123") to the commit message (`ISSUE_ID`)
370
391
  - `--preserve-github-prs`: Don't close GitHub PRs after submission (`PRESERVE_GITHUB_PRS`)
392
+ - `--duplicate-types`: Configure which Gerrit change states to check for duplicates (`DUPLICATE_TYPES`)
371
393
 
372
394
  For a complete list of all available options, see the [Inputs](#inputs) section.
373
395
 
@@ -593,7 +615,7 @@ alignment between action inputs, environment variables, and CLI flags:
593
615
  | `CI_TESTING` | `CI_TESTING` | `--ci-testing` | No | `"false"` | Enable CI testing mode (overrides .gitreview) |
594
616
  | `ISSUE_ID` | `ISSUE_ID` | `--issue-id` | No | `""` | Issue ID to include (e.g., ABC-123) |
595
617
  | `G2G_USE_SSH_AGENT` | `G2G_USE_SSH_AGENT` | N/A | No | `"true"` | Use SSH agent for authentication |
596
- | `DUPLICATES` | `DUPLICATES` | `--duplicates` | No | `"open"` | Comma-separated Gerrit statuses for duplicate detection |
618
+ | `DUPLICATE_TYPES` | `DUPLICATE_TYPES` | `--duplicate-types` | No | `"open"` | Comma-separated Gerrit change states to check for duplicate detection |
597
619
  | `GERRIT_SERVER` | `GERRIT_SERVER` | `--gerrit-server` | No² | `""` | Gerrit server hostname (auto-derived if enabled) |
598
620
  | `GERRIT_SERVER_PORT` | `GERRIT_SERVER_PORT` | `--gerrit-server-port` | No | `"29418"` | Gerrit SSH port |
599
621
  | `GERRIT_PROJECT` | `GERRIT_PROJECT` | `--gerrit-project` | No² | `""` | Gerrit project name |
@@ -100,6 +100,27 @@ with:
100
100
  When allowed, duplicates generate warnings but processing continues.
101
101
  The tool exits with code 3 when it detects duplicates and they are not allowed.
102
102
 
103
+ ### Configuring duplicate detection scope
104
+
105
+ By default, the duplicate detector considers changes with status `open` when searching for potential duplicates.
106
+ You can customize which Gerrit change states to check using `--duplicate-types` or setting `DUPLICATE_TYPES`:
107
+
108
+ ```bash
109
+ # CLI usage - check against open and merged changes
110
+ github2gerrit --duplicate-types=open,merged https://github.com/org/repo
111
+
112
+ # Environment variable
113
+ DUPLICATE_TYPES=open,merged,abandoned github2gerrit https://github.com/org/repo
114
+
115
+ # GitHub Actions
116
+ uses: onap/github2gerrit@main
117
+ with:
118
+ DUPLICATE_TYPES: 'open,merged'
119
+ ```
120
+
121
+ Valid change states include `open`, `merged`, and `abandoned`. This setting determines which existing changes
122
+ to check when evaluating whether a new change would be a duplicate.
123
+
103
124
  ## Commit Message Normalization
104
125
 
105
126
  The tool includes intelligent commit message normalization that automatically
@@ -328,6 +349,7 @@ Key options include:
328
349
  - `--use-pr-as-commit`: Use PR title/body as commit message (`USE_PR_AS_COMMIT`)
329
350
  - `--issue-id`: Add an Issue-ID trailer (e.g., "Issue-ID: ABC-123") to the commit message (`ISSUE_ID`)
330
351
  - `--preserve-github-prs`: Don't close GitHub PRs after submission (`PRESERVE_GITHUB_PRS`)
352
+ - `--duplicate-types`: Configure which Gerrit change states to check for duplicates (`DUPLICATE_TYPES`)
331
353
 
332
354
  For a complete list of all available options, see the [Inputs](#inputs) section.
333
355
 
@@ -553,7 +575,7 @@ alignment between action inputs, environment variables, and CLI flags:
553
575
  | `CI_TESTING` | `CI_TESTING` | `--ci-testing` | No | `"false"` | Enable CI testing mode (overrides .gitreview) |
554
576
  | `ISSUE_ID` | `ISSUE_ID` | `--issue-id` | No | `""` | Issue ID to include (e.g., ABC-123) |
555
577
  | `G2G_USE_SSH_AGENT` | `G2G_USE_SSH_AGENT` | N/A | No | `"true"` | Use SSH agent for authentication |
556
- | `DUPLICATES` | `DUPLICATES` | `--duplicates` | No | `"open"` | Comma-separated Gerrit statuses for duplicate detection |
578
+ | `DUPLICATE_TYPES` | `DUPLICATE_TYPES` | `--duplicate-types` | No | `"open"` | Comma-separated Gerrit change states to check for duplicate detection |
557
579
  | `GERRIT_SERVER` | `GERRIT_SERVER` | `--gerrit-server` | No² | `""` | Gerrit server hostname (auto-derived if enabled) |
558
580
  | `GERRIT_SERVER_PORT` | `GERRIT_SERVER_PORT` | `--gerrit-server-port` | No | `"29418"` | Gerrit SSH port |
559
581
  | `GERRIT_PROJECT` | `GERRIT_PROJECT` | `--gerrit-project` | No² | `""` | Gerrit project name |
@@ -6,6 +6,10 @@ name: github2gerrit
6
6
  description: "Creates Gerrit changes from GitHub pull requests"
7
7
 
8
8
  inputs:
9
+ # Optional
10
+ GERRIT_SSH_PRIVKEY_G2G:
11
+ description: "SSH private key content used to authenticate to Gerrit"
12
+ required: true
9
13
  SUBMIT_SINGLE_COMMITS:
10
14
  description: "Submit one commit at a time to the Gerrit repository"
11
15
  required: false
@@ -22,35 +26,17 @@ inputs:
22
26
  description: "Pull request number to process, use 0 to process all open"
23
27
  required: false
24
28
  default: "0"
25
-
26
- # SSH and identity
27
29
  GERRIT_KNOWN_HOSTS:
28
30
  description: "Known hosts entries for Gerrit SSH (single or multi-line)"
29
- required: true
30
- GERRIT_SSH_PRIVKEY_G2G:
31
- description: "SSH private key content used to authenticate to Gerrit"
32
- required: true
31
+ required: false
33
32
  GERRIT_SSH_USER_G2G:
34
- description: >
35
- Gerrit SSH username (e.g. automation bot account). In GitHub Actions,
36
- automatically derived as [ORGANIZATION].gh2gerrit when not provided if
37
- G2G_ENABLE_DERIVATION=true (default: false). For local CLI usage,
38
- derivation is enabled by default; set
39
- G2G_ENABLE_DERIVATION=false to disable.
33
+ description: "Gerrit SSH username; derived if not supplied explicitly"
40
34
  required: false
41
35
  default: ""
42
36
  GERRIT_SSH_USER_G2G_EMAIL:
43
- description: >
44
- Email address associated to the Gerrit SSH user. In GitHub Actions,
45
- automatically derived as
46
- releng+[ORGANIZATION]-gh2gerrit@linuxfoundation.org when not provided if
47
- G2G_ENABLE_DERIVATION=true (default: false). For local CLI usage,
48
- derivation is enabled by default; set
49
- G2G_ENABLE_DERIVATION=false to disable.
37
+ description: "Gerrit user email address; derived if not supplied explicitly"
50
38
  required: false
51
39
  default: ""
52
-
53
- # Behavior and metadata
54
40
  ORGANIZATION:
55
41
  description: "GitHub organization/owner (defaults to repo owner)"
56
42
  required: false
@@ -76,7 +62,7 @@ inputs:
76
62
  required: false
77
63
  default: "false"
78
64
  CI_TESTING:
79
- description: "Enable CI testing mode (overrides .gitreview, handles unrelated repos)"
65
+ description: "Enable CI testing mode; overrides .gitreview, creates orphan commits"
80
66
  required: false
81
67
  default: "false"
82
68
  ISSUE_ID:
@@ -87,38 +73,26 @@ inputs:
87
73
  description: "Use SSH agent for authentication instead of file-based keys (recommended)"
88
74
  required: false
89
75
  default: "true"
90
-
91
- DUPLICATES:
92
- description: >
93
- Comma-separated Gerrit statuses to consider for duplicate
94
- detection (e.g., open,merged,abandoned)
76
+ DUPLICATE_TYPES:
77
+ description: "Comma-separated Gerrit states for evaluating duplicates"
95
78
  required: false
96
79
  default: "open"
97
80
  NORMALISE_COMMIT:
98
81
  description: "Normalize commit messages to conventional commit format"
99
82
  required: false
100
- default: "true"
101
-
102
- # Optional Gerrit overrides (used when .gitreview is missing)
83
+ default: "false"
103
84
  GERRIT_SERVER:
104
- description: >
105
- Gerrit server hostname (optional; use .gitreview if present). In GitHub
106
- Actions, automatically derived as gerrit.[ORGANIZATION].org when not
107
- provided if G2G_ENABLE_DERIVATION=true (default: false). For local CLI
108
- usage, derivation is enabled by default; set G2G_ENABLE_DERIVATION=false
109
- to disable.
85
+ description: "Gerrit server hostname; derived if not supplied explicitly"
110
86
  required: false
111
87
  default: ""
112
88
  GERRIT_SERVER_PORT:
113
- description: "Gerrit SSH port (default: 29418)"
89
+ description: "Gerrit serverSSH TCP/port"
114
90
  required: false
115
91
  default: "29418"
116
92
  GERRIT_PROJECT:
117
- description: "Gerrit project, optional if .gitreview exists"
93
+ description: "Gerrit project; optional if .gitreview exists"
118
94
  required: false
119
95
  default: ""
120
-
121
- # Optional Gerrit REST-related settings
122
96
  GERRIT_HTTP_BASE_PATH:
123
97
  description: "Optional HTTP base path for Gerrit REST (e.g. /r)"
124
98
  required: false
@@ -165,6 +139,41 @@ runs:
165
139
  # Ensure we are on the PR's head SHA when triggered by PR events
166
140
  ref: ${{ github.event.pull_request.head.sha || github.sha }}
167
141
 
142
+ - name: "Set key to use for JSON lookup"
143
+ if: ${{ inputs.ISSUE_ID == '' && vars.ISSUE_ID_LOOKUP == 'true' }}
144
+ shell: bash
145
+ run: |
146
+ # Set key to use for JSON lookup
147
+ ACTOR="${{ github.actor }}"
148
+ ACTOR_ID="${{ github.actor_id }}"
149
+ echo "Using GitHub actor as lookup key: $ACTOR [$ACTOR_ID]"
150
+ echo "key=$ACTOR" >> "$GITHUB_ENV"
151
+
152
+ - name: "Get ticket from JSON lookup table"
153
+ if: ${{ inputs.ISSUE_ID == '' && vars.ISSUE_ID_LOOKUP == 'true' }}
154
+ id: json-lookup
155
+ uses: lfit/releng-reusable-workflows/.github/actions/json-key-value-lookup-action@main
156
+ with:
157
+ json: ${{ vars.ISSUE_ID_LOOKUP_JSON }}
158
+ key: ${{ env.key }}
159
+
160
+ - name: "Set IssueID in GITHUB_ENV"
161
+ if: ${{ inputs.ISSUE_ID == '' && vars.ISSUE_ID_LOOKUP == 'true' }}
162
+ shell: bash
163
+ # yamllint disable rule:line-length
164
+ run: |
165
+ set -euo pipefail
166
+ val="${{ steps.json-lookup.outputs.value }}"
167
+ if [ -z "$val" ]; then
168
+ alt="${{ env.value }}"
169
+ if [ -n "$alt" ]; then
170
+ val="$alt"
171
+ fi
172
+ fi
173
+ if [ -n "$val" ]; then
174
+ echo "RESOLVED_ISSUE_ID=$val" >> "$GITHUB_ENV"
175
+ fi
176
+
168
177
  - name: Install required dependencies
169
178
  shell: bash
170
179
  run: |
@@ -253,9 +262,9 @@ runs:
253
262
  PRESERVE_GITHUB_PRS: ${{ inputs.PRESERVE_GITHUB_PRS }}
254
263
  DRY_RUN: ${{ inputs.DRY_RUN }}
255
264
  ALLOW_DUPLICATES: ${{ inputs.ALLOW_DUPLICATES }}
256
- ISSUE_ID: ${{ inputs.ISSUE_ID }}
265
+ ISSUE_ID: ${{ inputs.ISSUE_ID != '' && inputs.ISSUE_ID || env.RESOLVED_ISSUE_ID }}
257
266
  CI_TESTING: ${{ inputs.CI_TESTING }}
258
- DUPLICATES: ${{ inputs.DUPLICATES }}
267
+ DUPLICATE_TYPES: ${{ inputs.DUPLICATE_TYPES }}
259
268
  NORMALISE_COMMIT: ${{ inputs.NORMALISE_COMMIT }}
260
269
  G2G_USE_SSH_AGENT: ${{ inputs.G2G_USE_SSH_AGENT }}
261
270
 
@@ -265,12 +265,13 @@ def main(
265
265
  envvar="CI_TESTING",
266
266
  help="Enable CI testing mode (overrides .gitreview, handles unrelated repos).",
267
267
  ),
268
- duplicates: str = typer.Option(
268
+ duplicate_types: str = typer.Option(
269
269
  "open",
270
- "--duplicates",
271
- envvar="DUPLICATES",
270
+ "--duplicate-types",
271
+ envvar="DUPLICATE_TYPES",
272
272
  help=(
273
- 'Gerrit statuses for duplicate detection (comma-separated). E.g. "open,merged,abandoned". Default: "open".'
273
+ "Gerrit change states to evaluate when determining if a change should be considered a duplicate "
274
+ '(comma-separated). E.g. "open,merged,abandoned". Default: "open".'
274
275
  ),
275
276
  ),
276
277
  normalise_commit: bool = typer.Option(
@@ -354,8 +355,8 @@ def main(
354
355
  os.environ["ISSUE_ID"] = issue_id
355
356
  os.environ["ALLOW_DUPLICATES"] = "true" if allow_duplicates else "false"
356
357
  os.environ["CI_TESTING"] = "true" if ci_testing else "false"
357
- if duplicates:
358
- os.environ["DUPLICATES"] = duplicates
358
+ if duplicate_types:
359
+ os.environ["DUPLICATE_TYPES"] = duplicate_types
359
360
  # URL mode handling
360
361
  if target_url:
361
362
  org, repo, pr = _parse_github_target(target_url)
@@ -432,7 +433,7 @@ def _build_inputs_from_env() -> Inputs:
432
433
  issue_id=env_str("ISSUE_ID", ""),
433
434
  allow_duplicates=env_bool("ALLOW_DUPLICATES", False),
434
435
  ci_testing=env_bool("CI_TESTING", False),
435
- duplicates_filter=env_str("DUPLICATES", "open"),
436
+ duplicates_filter=env_str("DUPLICATE_TYPES", "open"),
436
437
  )
437
438
 
438
439
 
@@ -476,7 +477,7 @@ def _process_bulk(data: Inputs, gh: GitHubContext) -> bool:
476
477
 
477
478
  try:
478
479
  if data.duplicates_filter:
479
- os.environ["DUPLICATES"] = data.duplicates_filter
480
+ os.environ["DUPLICATE_TYPES"] = data.duplicates_filter
480
481
  check_for_duplicates(per_ctx, allow_duplicates=data.allow_duplicates)
481
482
  except DuplicateChangeError as exc:
482
483
  log_exception_conditionally(log, "Skipping PR #%d", pr_number)
@@ -1022,7 +1023,7 @@ def _process() -> None:
1022
1023
  if gh.pr_number and not env_bool("SYNC_ALL_OPEN_PRS", False):
1023
1024
  try:
1024
1025
  if data.duplicates_filter:
1025
- os.environ["DUPLICATES"] = data.duplicates_filter
1026
+ os.environ["DUPLICATE_TYPES"] = data.duplicates_filter
1026
1027
  check_for_duplicates(gh, allow_duplicates=data.allow_duplicates)
1027
1028
  except DuplicateChangeError as exc:
1028
1029
  log_exception_conditionally(
@@ -77,6 +77,7 @@ KNOWN_KEYS: set[str] = {
77
77
  "ALLOW_GHE_URLS",
78
78
  "DRY_RUN",
79
79
  "ALLOW_DUPLICATES",
80
+ "DUPLICATE_TYPES",
80
81
  "ISSUE_ID",
81
82
  "G2G_VERBOSE",
82
83
  "G2G_SKIP_GERRIT_COMMENTS",
@@ -1417,6 +1417,7 @@ class Orchestrator:
1417
1417
  signed_lines = [ln for ln in lines_cur if ln.startswith("Signed-off-by:")]
1418
1418
  change_id_lines = [ln for ln in lines_cur if ln.startswith("Change-Id:")]
1419
1419
  github_hash_lines = [ln for ln in lines_cur if ln.startswith("GitHub-Hash:")]
1420
+ github_pr_lines = [ln for ln in lines_cur if ln.startswith("GitHub-PR:")]
1420
1421
 
1421
1422
  msg_parts = [title, "", body] if title or body else [current_body]
1422
1423
  commit_message = "\n".join(msg_parts).strip()
@@ -1446,8 +1447,19 @@ class Orchestrator:
1446
1447
  seen_so.add(ln)
1447
1448
  if change_id_lines:
1448
1449
  trailers_out.append(change_id_lines[-1])
1450
+
1451
+ # GitHub-PR trailer (must appear after Change-Id)
1452
+ if github_pr_lines:
1453
+ pr_line = github_pr_lines[-1]
1454
+ else:
1455
+ pr_line = f"GitHub-PR: {gh.server_url}/{gh.repository}/pull/{gh.pr_number}" if gh.pr_number else ""
1456
+
1449
1457
  if trailers_out:
1450
1458
  commit_message += "\n\n" + "\n".join(trailers_out)
1459
+ if pr_line:
1460
+ commit_message += "\n" + pr_line
1461
+ elif pr_line:
1462
+ commit_message += "\n\n" + pr_line
1451
1463
 
1452
1464
  author = run_cmd(
1453
1465
  ["git", "show", "-s", "--pretty=format:%an <%ae>", "HEAD"],
@@ -373,7 +373,7 @@ class DuplicateDetector:
373
373
  q_parts = []
374
374
  if gerrit_project:
375
375
  q_parts.append(f"project:{gerrit_project}")
376
- # Build status clause from DUPLICATES filter (default: open)
376
+ # Build status clause from DUPLICATE_TYPES filter (default: open)
377
377
  dup_filter = (self.duplicates_filter or "open").strip().lower()
378
378
  selected = [s.strip() for s in dup_filter.split(",") if s.strip()]
379
379
  valid = {
@@ -644,7 +644,7 @@ def check_for_duplicates(
644
644
  detector = DuplicateDetector(
645
645
  repo,
646
646
  lookback_days=lookback_days,
647
- duplicates_filter=os.getenv("DUPLICATES", "open"),
647
+ duplicates_filter=os.getenv("DUPLICATE_TYPES", "open"),
648
648
  )
649
649
  detector.check_for_duplicates(target_pr, allow_duplicates=allow_duplicates, gh=gh)
650
650
 
@@ -163,6 +163,7 @@ def remove_commit_trailers(message: str) -> str:
163
163
  - Signed-off-by: Name <email>
164
164
  - Issue-ID: ABC-123
165
165
  - GitHub-Hash: deadbeefcafebabe
166
+ - GitHub-PR: https://github.com/org/repo/pull/123
166
167
  - Co-authored-by: ...
167
168
 
168
169
  Args:
@@ -173,7 +174,7 @@ def remove_commit_trailers(message: str) -> str:
173
174
  """
174
175
  lines = (message or "").splitlines()
175
176
  out: list[str] = []
176
- trailer_re = re.compile(r"(?i)^(change-id|signed-off-by|issue-id|github-hash|co-authored-by):")
177
+ trailer_re = re.compile(r"(?i)^(change-id|signed-off-by|issue-id|github-hash|github-pr|co-authored-by):")
177
178
  for ln in lines:
178
179
  if trailer_re.match(ln.strip()):
179
180
  continue
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: github2gerrit
3
- Version: 0.1.9
3
+ Version: 0.1.10
4
4
  Summary: Submit a GitHub pull request to a Gerrit repository.
5
5
  Author-email: Matthew Watkins <mwatkins@linuxfoundation.org>
6
6
  License-Expression: Apache-2.0
@@ -140,6 +140,27 @@ with:
140
140
  When allowed, duplicates generate warnings but processing continues.
141
141
  The tool exits with code 3 when it detects duplicates and they are not allowed.
142
142
 
143
+ ### Configuring duplicate detection scope
144
+
145
+ By default, the duplicate detector considers changes with status `open` when searching for potential duplicates.
146
+ You can customize which Gerrit change states to check using `--duplicate-types` or setting `DUPLICATE_TYPES`:
147
+
148
+ ```bash
149
+ # CLI usage - check against open and merged changes
150
+ github2gerrit --duplicate-types=open,merged https://github.com/org/repo
151
+
152
+ # Environment variable
153
+ DUPLICATE_TYPES=open,merged,abandoned github2gerrit https://github.com/org/repo
154
+
155
+ # GitHub Actions
156
+ uses: onap/github2gerrit@main
157
+ with:
158
+ DUPLICATE_TYPES: 'open,merged'
159
+ ```
160
+
161
+ Valid change states include `open`, `merged`, and `abandoned`. This setting determines which existing changes
162
+ to check when evaluating whether a new change would be a duplicate.
163
+
143
164
  ## Commit Message Normalization
144
165
 
145
166
  The tool includes intelligent commit message normalization that automatically
@@ -368,6 +389,7 @@ Key options include:
368
389
  - `--use-pr-as-commit`: Use PR title/body as commit message (`USE_PR_AS_COMMIT`)
369
390
  - `--issue-id`: Add an Issue-ID trailer (e.g., "Issue-ID: ABC-123") to the commit message (`ISSUE_ID`)
370
391
  - `--preserve-github-prs`: Don't close GitHub PRs after submission (`PRESERVE_GITHUB_PRS`)
392
+ - `--duplicate-types`: Configure which Gerrit change states to check for duplicates (`DUPLICATE_TYPES`)
371
393
 
372
394
  For a complete list of all available options, see the [Inputs](#inputs) section.
373
395
 
@@ -593,7 +615,7 @@ alignment between action inputs, environment variables, and CLI flags:
593
615
  | `CI_TESTING` | `CI_TESTING` | `--ci-testing` | No | `"false"` | Enable CI testing mode (overrides .gitreview) |
594
616
  | `ISSUE_ID` | `ISSUE_ID` | `--issue-id` | No | `""` | Issue ID to include (e.g., ABC-123) |
595
617
  | `G2G_USE_SSH_AGENT` | `G2G_USE_SSH_AGENT` | N/A | No | `"true"` | Use SSH agent for authentication |
596
- | `DUPLICATES` | `DUPLICATES` | `--duplicates` | No | `"open"` | Comma-separated Gerrit statuses for duplicate detection |
618
+ | `DUPLICATE_TYPES` | `DUPLICATE_TYPES` | `--duplicate-types` | No | `"open"` | Comma-separated Gerrit change states to check for duplicate detection |
597
619
  | `GERRIT_SERVER` | `GERRIT_SERVER` | `--gerrit-server` | No² | `""` | Gerrit server hostname (auto-derived if enabled) |
598
620
  | `GERRIT_SERVER_PORT` | `GERRIT_SERVER_PORT` | `--gerrit-server-port` | No | `"29418"` | Gerrit SSH port |
599
621
  | `GERRIT_PROJECT` | `GERRIT_PROJECT` | `--gerrit-project` | No² | `""` | Gerrit project name |
@@ -67,7 +67,7 @@ def _inputs(*, use_pr_as_commit: bool = True) -> Inputs:
67
67
  def test_apply_pr_title_body_preserves_change_id_footer(tmp_path: Path, monkeypatch: pytest.MonkeyPatch) -> None:
68
68
  """
69
69
  When applying PR title/body to the commit, the Change-Id trailer must
70
- remain in the message footer (last trailer line) to satisfy Gerrit.
70
+ remain in the message footer before the GitHub-PR trailer.
71
71
  """
72
72
  # Arrange
73
73
  orch = Orchestrator(workspace=tmp_path)
@@ -132,22 +132,35 @@ def test_apply_pr_title_body_preserves_change_id_footer(tmp_path: Path, monkeypa
132
132
  new_msg = amended_messages[-1]
133
133
  lines = new_msg.strip().splitlines()
134
134
 
135
- # Ensure Change-Id is present and at the footer (last non-empty line)
135
+ # Ensure Change-Id is present and appears before GitHub-PR
136
136
  assert any(ln.startswith("Change-Id: ") for ln in lines), "Change-Id trailer missing after amend"
137
- assert lines[-1].startswith("Change-Id: "), "Change-Id must be the last trailer line in the footer"
138
- assert existing_change_id in lines[-1], "Original Change-Id value should be preserved"
137
+ assert any(ln.startswith("GitHub-PR: ") for ln in lines), "GitHub-PR trailer missing after amend"
138
+ assert lines[-1].startswith("GitHub-PR: "), "GitHub-PR must be the last trailer line in the footer"
139
139
 
140
- # Ensure Signed-off-by is preserved and appears before Change-Id
140
+ # Find Change-Id line and verify it contains the original value
141
+ change_id_line = next((ln for ln in lines if ln.startswith("Change-Id: ")), "")
142
+ assert existing_change_id in change_id_line, "Original Change-Id value should be preserved"
143
+
144
+ # Ensure proper trailer ordering: Signed-off-by, Change-Id, GitHub-PR
141
145
  signed_idx = None
142
146
  change_idx = None
147
+ github_pr_idx = None
143
148
  for i, ln in enumerate(lines):
144
149
  if ln.startswith("Signed-off-by: "):
145
150
  signed_idx = i
146
- if ln.startswith("Change-Id: "):
151
+ elif ln.startswith("Change-Id: "):
147
152
  change_idx = i
148
- break
153
+ elif ln.startswith("GitHub-PR: "):
154
+ github_pr_idx = i
155
+
149
156
  assert signed_idx is not None, "Signed-off-by trailer should be preserved"
150
- assert change_idx is not None and change_idx > signed_idx, "Change-Id should follow Signed-off-by in the footer"
157
+ assert change_idx is not None, "Change-Id trailer should be present"
158
+ assert github_pr_idx is not None, "GitHub-PR trailer should be present"
159
+ assert signed_idx < change_idx < github_pr_idx, "Trailer order should be: Signed-off-by, Change-Id, GitHub-PR"
160
+
161
+ # Verify GitHub-PR contains the correct URL
162
+ github_pr_line = lines[github_pr_idx]
163
+ assert "https://github.com/acme/widget/pull/99" in github_pr_line, "GitHub-PR should contain correct PR URL"
151
164
 
152
165
  # Ensure there's a blank line separating body and trailers
153
166
  # Find the first trailer index and verify the previous non-empty line is blank-separated
@@ -142,8 +142,12 @@ Dependabot will resolve any conflicts with this PR as long as you don't alter it
142
142
  assert "Bug fix #123" in commit_message # Content preserved
143
143
  assert "abc123: Fix issue" in commit_message # Content preserved
144
144
 
145
- # Verify unwanted content was removed
146
- assert "github.com" not in commit_message # Links removed
145
+ # Verify unwanted content was removed from body (but GitHub-PR trailer is OK)
146
+ # Check that github.com links are removed from body content, but allow GitHub-PR trailer
147
+ lines = commit_message.split("\n")
148
+ body_lines = [line for line in lines if not line.startswith("GitHub-PR:")]
149
+ body_content = "\n".join(body_lines)
150
+ assert "github.com" not in body_content # Links removed from body
147
151
  assert "camo.githubusercontent.com" not in commit_message # Image removed
148
152
  assert "Dependabot will resolve" not in commit_message # Commands removed
149
153
  assert "@dependabot rebase" not in commit_message # Commands removed
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes