github2gerrit 2.2.0__py3-none-any.whl → 2.2.2__py3-none-any.whl

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/cli.py CHANGED
@@ -120,6 +120,46 @@ def _exit_for_pr_state_error(pr_number: int, pr_state: str) -> None:
120
120
  exit_for_pr_state_error(pr_number, pr_state)
121
121
 
122
122
 
123
+ def _stop_for_pr_state(
124
+ gh: GitHubContext, pr_state: str, progress_tracker: Any = None
125
+ ) -> NoReturn:
126
+ """Stop because the pull request is not open.
127
+
128
+ On a pull request event this is not an error. GitHub delivers
129
+ several events around a close — Dependabot edits the body before
130
+ closing, for instance — and any of them may land after the
131
+ ``closed`` event whose handler already ran. Such a run has nothing
132
+ to do, and a red check on the contributor's pull request would
133
+ misreport that. The report behind #441 cited exactly this run and
134
+ took it for the close handler failing.
135
+
136
+ A dispatch or direct invocation naming a closed pull request is
137
+ different: somebody asked for that one specifically, and being told
138
+ it cannot be processed is the useful answer.
139
+ """
140
+ if gh.event_name in ("pull_request", "pull_request_target"):
141
+ log.info(
142
+ "Pull request #%s is %s; nothing to do for a '%s' event. Cleanup "
143
+ "for a closed pull request runs on the 'closed' event itself.",
144
+ gh.pr_number,
145
+ pr_state,
146
+ gh.event_action or gh.event_name,
147
+ )
148
+ safe_console_print(
149
+ f"⏩ Pull request #{gh.pr_number} is {pr_state}; nothing to do",
150
+ style="yellow",
151
+ progress_tracker=progress_tracker,
152
+ )
153
+ # The caller's own stop() is downstream of this raise, and
154
+ # safe_console_print only suspends and resumes the display, so
155
+ # an in-process caller catching the exit would otherwise be
156
+ # left with an active Rich context.
157
+ if progress_tracker is not None:
158
+ progress_tracker.stop()
159
+ raise typer.Exit(int(ExitCode.SUCCESS))
160
+ exit_for_pr_state_error(gh.pr_number or 0, pr_state)
161
+
162
+
123
163
  def _exit_for_pr_not_found(pr_number: int, repository: str) -> None:
124
164
  """Exit with error message for PR not found."""
125
165
  exit_for_pr_not_found(pr_number, repository)
@@ -756,10 +796,10 @@ def _extract_and_display_pr_info(
756
796
  repo = get_repo_from_env(client)
757
797
  pr_obj = get_pull(repo, int(gh.pr_number))
758
798
 
759
- # Check PR state and exit if not processable
799
+ # Check PR state and stop if not processable
760
800
  pr_state = getattr(pr_obj, "state", "unknown")
761
801
  if pr_state != "open":
762
- _exit_for_pr_state_error(gh.pr_number, pr_state)
802
+ _stop_for_pr_state(gh, str(pr_state), progress_tracker)
763
803
 
764
804
  # Check if automation_only is enabled and reject non-automation PRs
765
805
  _check_automation_only(pr_obj, gh, progress_tracker)
@@ -792,6 +832,12 @@ def _extract_and_display_pr_info(
792
832
  except GitHub2GerritError:
793
833
  # Let our structured errors propagate
794
834
  raise
835
+ except typer.Exit:
836
+ # display_and_exit and the clean stop above both raise this.
837
+ # It derives from Exception through click, so without this
838
+ # clause the handler below would swallow a deliberate exit 8
839
+ # and report "Failed to fetch PR details: 8" with exit 1.
840
+ raise
795
841
  except Exception as exc:
796
842
  log.debug("Failed to display PR info: %s", exc)
797
843
  if "404" in str(exc) or "Not Found" in str(exc):
@@ -1468,19 +1514,19 @@ def main(
1468
1514
  "",
1469
1515
  "--gerrit-project",
1470
1516
  envvar="GERRIT_PROJECT",
1471
- help="Gerrit project (optional; .gitreview preferred).",
1517
+ help="Gerrit project (optional; overrides .gitreview when set).",
1472
1518
  ),
1473
1519
  gerrit_server: str = typer.Option(
1474
1520
  "",
1475
1521
  "--gerrit-server",
1476
1522
  envvar="GERRIT_SERVER",
1477
- help="Gerrit server hostname (optional; .gitreview preferred).",
1523
+ help="Gerrit server hostname (optional; overrides .gitreview).",
1478
1524
  ),
1479
1525
  gerrit_server_port: int = typer.Option(
1480
- 29418,
1526
+ 0,
1481
1527
  "--gerrit-server-port",
1482
1528
  envvar="GERRIT_SERVER_PORT",
1483
- help="Gerrit SSH port (default: 29418).",
1529
+ help="Gerrit SSH port; .gitreview's when unset, else 29418.",
1484
1530
  ),
1485
1531
  gerrit_ssh_privkey_g2g: str = typer.Option(
1486
1532
  "",
@@ -1853,9 +1899,10 @@ def _build_inputs_from_env() -> Inputs:
1853
1899
  dry_run=env_bool("DRY_RUN", False),
1854
1900
  normalise_commit=env_bool("NORMALISE_COMMIT", True),
1855
1901
  gerrit_server=env_str("GERRIT_SERVER", ""),
1856
- gerrit_server_port=int(
1857
- env_str("GERRIT_SERVER_PORT", "29418") or "29418"
1858
- ),
1902
+ # 0 means unset. A blank value is what the action passes when the
1903
+ # caller gave none, and the distinction matters: an explicit
1904
+ # port outranks .gitreview's, a defaulted one must not.
1905
+ gerrit_server_port=int(env_str("GERRIT_SERVER_PORT", "").strip() or 0),
1859
1906
  gerrit_project=env_str("GERRIT_PROJECT"),
1860
1907
  issue_id=env_str("ISSUE_ID", ""),
1861
1908
  issue_id_lookup_json=env_str("ISSUE_ID_LOOKUP_JSON", ""),
@@ -3036,14 +3083,23 @@ def _log_abandoned_change_url(
3036
3083
 
3037
3084
 
3038
3085
  def _abandon_change_for_closed_pr(data: Inputs, gh: GitHubContext) -> None:
3039
- """Abandon the Gerrit change associated with a closed pull request."""
3086
+ """Abandon the Gerrit change associated with a closed pull request.
3087
+
3088
+ Three outcomes, reported distinctly: a change was abandoned, no
3089
+ open change carries this pull request's trailer, or the lookup or
3090
+ abandon itself failed. The last two used to share one message, and
3091
+ a failed query read as a clean "nothing to do". A failure does not
3092
+ say which side of the abandon it happened on -- Gerrit may have
3093
+ applied it and the response been lost -- so the report says the
3094
+ state is unconfirmed rather than claiming the change is open.
3095
+ """
3040
3096
  if gh.pr_number is None:
3041
3097
  return
3098
+ log.debug(
3099
+ "Checking for Gerrit change to abandon for PR #%s",
3100
+ gh.pr_number,
3101
+ )
3042
3102
  try:
3043
- log.debug(
3044
- "Checking for Gerrit change to abandon for PR #%s",
3045
- gh.pr_number,
3046
- )
3047
3103
  change_number = abandon_gerrit_change_for_closed_pr(
3048
3104
  pr_number=gh.pr_number,
3049
3105
  gerrit_server=data.gerrit_server,
@@ -3052,21 +3108,46 @@ def _abandon_change_for_closed_pr(data: Inputs, gh: GitHubContext) -> None:
3052
3108
  dry_run=data.dry_run,
3053
3109
  progress_tracker=None,
3054
3110
  )
3055
- if change_number:
3056
- _log_abandoned_change_url(data, gh, change_number)
3057
- # Console output already done by
3058
- # abandon_gerrit_change_for_closed_pr
3059
- else:
3060
- log.debug(
3061
- "No open Gerrit change found for pull request #%s",
3062
- gh.pr_number,
3063
- )
3064
3111
  except Exception as exc:
3065
3112
  log.warning(
3066
- "Failed to abandon Gerrit change for PR #%s: %s",
3113
+ "Failed to look up or abandon the Gerrit change for pull "
3114
+ "request #%s in project %r on %s: %s. Its state could not be "
3115
+ "confirmed; check Gerrit.",
3067
3116
  gh.pr_number,
3117
+ data.gerrit_project,
3118
+ data.gerrit_server,
3068
3119
  exc,
3069
3120
  )
3121
+ log.debug("Cleanup failure detail", exc_info=True)
3122
+ safe_console_print(
3123
+ f"⚠️ Could not confirm the Gerrit change state for PR "
3124
+ f"#{gh.pr_number}: {exc}",
3125
+ style="yellow",
3126
+ )
3127
+ return
3128
+
3129
+ if change_number:
3130
+ _log_abandoned_change_url(data, gh, change_number)
3131
+ # Console output already done by
3132
+ # abandon_gerrit_change_for_closed_pr
3133
+ return
3134
+
3135
+ # Audible on purpose. This is the outcome when the project name is
3136
+ # wrong, and at debug level it hid 239 stranded changes on one
3137
+ # server for six months (#441). Naming the project queried is what
3138
+ # lets a reader spot the mismatch.
3139
+ log.info(
3140
+ "No open Gerrit change found for pull request #%s in "
3141
+ "project %r on %s; nothing to abandon",
3142
+ gh.pr_number,
3143
+ data.gerrit_project,
3144
+ data.gerrit_server,
3145
+ )
3146
+ safe_console_print(
3147
+ f"⏩ No open Gerrit change for PR #{gh.pr_number} in "
3148
+ f"project '{data.gerrit_project}'",
3149
+ style="dim",
3150
+ )
3070
3151
 
3071
3152
 
3072
3153
  def _handle_pr_closed(
@@ -3104,13 +3185,28 @@ def _handle_pr_closed(
3104
3185
 
3105
3186
  # First, abandon the specific Gerrit change for this closed PR
3106
3187
  # Skip in G2G_NO_GERRIT: no Gerrit server to query
3107
- if (
3108
- not no_gerrit
3109
- and gh.pr_number
3188
+ if no_gerrit:
3189
+ pass
3190
+ elif not (
3191
+ gh.pr_number
3192
+ and gh.repository
3110
3193
  and data.gerrit_server
3111
3194
  and data.gerrit_project
3112
- and gh.repository
3113
3195
  ):
3196
+ # Say so. Silently skipping here is indistinguishable from a
3197
+ # successful cleanup that found nothing, and the change stays
3198
+ # open with no trace of why.
3199
+ log.warning(
3200
+ "Cannot look for a Gerrit change to abandon for PR #%s: "
3201
+ "repository=%r server=%r project=%r. Set GERRIT_SERVER and "
3202
+ "GERRIT_PROJECT, or add a .gitreview so they can be derived; "
3203
+ "the repository comes from GITHUB_REPOSITORY.",
3204
+ gh.pr_number,
3205
+ gh.repository,
3206
+ data.gerrit_server,
3207
+ data.gerrit_project,
3208
+ )
3209
+ else:
3114
3210
  _abandon_change_for_closed_pr(data, gh)
3115
3211
 
3116
3212
  _run_gerrit_cleanup_tasks(data, gh, no_gerrit=no_gerrit)
@@ -3935,8 +4031,9 @@ def _add_full_config(
3935
4031
  # Show Gerrit settings if they have values
3936
4032
  if data.gerrit_server:
3937
4033
  config_info["GERRIT_SERVER"] = data.gerrit_server
3938
- # Only show non-default port (29418 is default)
3939
- if data.gerrit_server_port and data.gerrit_server_port != 29418:
4034
+ # Any set port is shown: 0 is the unset sentinel, and an explicit
4035
+ # 29418 is a real override of whatever .gitreview names.
4036
+ if data.gerrit_server_port:
3940
4037
  config_info["GERRIT_SERVER_PORT"] = str(data.gerrit_server_port)
3941
4038
  if data.gerrit_project:
3942
4039
  config_info["GERRIT_PROJECT"] = data.gerrit_project