github2gerrit 0.1.6__py3-none-any.whl → 0.1.8__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 +458 -192
- github2gerrit/commit_normalization.py +471 -0
- github2gerrit/core.py +822 -252
- github2gerrit/duplicate_detection.py +1 -69
- github2gerrit/external_api.py +517 -0
- github2gerrit/gerrit_rest.py +298 -0
- github2gerrit/gerrit_urls.py +149 -52
- github2gerrit/github_api.py +12 -79
- github2gerrit/gitutils.py +208 -49
- github2gerrit/models.py +2 -0
- github2gerrit/pr_content_filter.py +476 -0
- github2gerrit/similarity.py +2 -2
- github2gerrit/ssh_agent_setup.py +351 -0
- github2gerrit/ssh_common.py +244 -0
- github2gerrit/ssh_discovery.py +4 -0
- github2gerrit/utils.py +113 -0
- github2gerrit-0.1.8.dist-info/METADATA +798 -0
- github2gerrit-0.1.8.dist-info/RECORD +24 -0
- github2gerrit-0.1.6.dist-info/METADATA +0 -552
- github2gerrit-0.1.6.dist-info/RECORD +0 -17
- {github2gerrit-0.1.6.dist-info → github2gerrit-0.1.8.dist-info}/WHEEL +0 -0
- {github2gerrit-0.1.6.dist-info → github2gerrit-0.1.8.dist-info}/entry_points.txt +0 -0
- {github2gerrit-0.1.6.dist-info → github2gerrit-0.1.8.dist-info}/licenses/LICENSE +0 -0
- {github2gerrit-0.1.6.dist-info → github2gerrit-0.1.8.dist-info}/top_level.txt +0 -0
github2gerrit/cli.py
CHANGED
@@ -3,11 +3,16 @@
|
|
3
3
|
|
4
4
|
from __future__ import annotations
|
5
5
|
|
6
|
+
import io
|
6
7
|
import json
|
7
8
|
import logging
|
8
9
|
import os
|
10
|
+
import shutil
|
9
11
|
import tempfile
|
12
|
+
import zipfile
|
10
13
|
from collections.abc import Callable
|
14
|
+
from concurrent.futures import ThreadPoolExecutor
|
15
|
+
from concurrent.futures import as_completed
|
11
16
|
from pathlib import Path
|
12
17
|
from typing import TYPE_CHECKING
|
13
18
|
from typing import Any
|
@@ -15,6 +20,8 @@ from typing import Protocol
|
|
15
20
|
from typing import TypeVar
|
16
21
|
from typing import cast
|
17
22
|
from urllib.parse import urlparse
|
23
|
+
from urllib.request import Request
|
24
|
+
from urllib.request import urlopen
|
18
25
|
|
19
26
|
import click
|
20
27
|
import typer
|
@@ -35,19 +42,13 @@ from .github_api import iter_open_pulls
|
|
35
42
|
from .gitutils import run_cmd
|
36
43
|
from .models import GitHubContext
|
37
44
|
from .models import Inputs
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
|
44
|
-
|
45
|
-
def _log_exception_conditionally(logger: logging.Logger, message: str, *args: Any) -> None:
|
46
|
-
"""Log exception with traceback only if verbose mode is enabled."""
|
47
|
-
if _is_verbose_mode():
|
48
|
-
logger.exception(message, *args)
|
49
|
-
else:
|
50
|
-
logger.error(message, *args)
|
45
|
+
from .ssh_common import build_git_ssh_command
|
46
|
+
from .ssh_common import build_non_interactive_ssh_env
|
47
|
+
from .utils import append_github_output
|
48
|
+
from .utils import env_bool
|
49
|
+
from .utils import env_str
|
50
|
+
from .utils import log_exception_conditionally
|
51
|
+
from .utils import parse_bool_env
|
51
52
|
|
52
53
|
|
53
54
|
class ConfigurationError(Exception):
|
@@ -72,7 +73,7 @@ def _parse_github_target(url: str) -> tuple[str | None, str | None, int | None]:
|
|
72
73
|
except Exception:
|
73
74
|
return None, None, None
|
74
75
|
|
75
|
-
allow_ghe =
|
76
|
+
allow_ghe = env_bool("ALLOW_GHE_URLS", False)
|
76
77
|
bad_hosts = {
|
77
78
|
"gitlab.com",
|
78
79
|
"www.gitlab.com",
|
@@ -164,36 +165,38 @@ def main(
|
|
164
165
|
submit_single_commits: bool = typer.Option(
|
165
166
|
False,
|
166
167
|
"--submit-single-commits",
|
168
|
+
envvar="SUBMIT_SINGLE_COMMITS",
|
167
169
|
help="Submit one commit at a time to the Gerrit repository.",
|
168
170
|
),
|
169
171
|
use_pr_as_commit: bool = typer.Option(
|
170
172
|
False,
|
171
173
|
"--use-pr-as-commit",
|
174
|
+
envvar="USE_PR_AS_COMMIT",
|
172
175
|
help="Use PR title and body as the commit message.",
|
173
176
|
),
|
174
177
|
fetch_depth: int = typer.Option(
|
175
178
|
10,
|
176
179
|
"--fetch-depth",
|
177
180
|
envvar="FETCH_DEPTH",
|
178
|
-
help="Fetch
|
181
|
+
help="Fetch depth for checkout.",
|
179
182
|
),
|
180
183
|
gerrit_known_hosts: str = typer.Option(
|
181
184
|
"",
|
182
185
|
"--gerrit-known-hosts",
|
183
186
|
envvar="GERRIT_KNOWN_HOSTS",
|
184
|
-
help="Known hosts entries for Gerrit SSH.",
|
187
|
+
help="Known hosts entries for Gerrit SSH (single or multi-line).",
|
185
188
|
),
|
186
189
|
gerrit_ssh_privkey_g2g: str = typer.Option(
|
187
190
|
"",
|
188
191
|
"--gerrit-ssh-privkey-g2g",
|
189
192
|
envvar="GERRIT_SSH_PRIVKEY_G2G",
|
190
|
-
help="SSH private key
|
193
|
+
help="SSH private key content used to authenticate to Gerrit.",
|
191
194
|
),
|
192
195
|
gerrit_ssh_user_g2g: str = typer.Option(
|
193
196
|
"",
|
194
197
|
"--gerrit-ssh-user-g2g",
|
195
198
|
envvar="GERRIT_SSH_USER_G2G",
|
196
|
-
help="Gerrit SSH
|
199
|
+
help="Gerrit SSH username (e.g. automation bot account).",
|
197
200
|
),
|
198
201
|
gerrit_ssh_user_g2g_email: str = typer.Option(
|
199
202
|
"",
|
@@ -261,6 +264,12 @@ def main(
|
|
261
264
|
envvar="ALLOW_DUPLICATES",
|
262
265
|
help="Allow submitting duplicate changes without error.",
|
263
266
|
),
|
267
|
+
ci_testing: bool = typer.Option(
|
268
|
+
False,
|
269
|
+
"--ci-testing/--no-ci-testing",
|
270
|
+
envvar="CI_TESTING",
|
271
|
+
help="Enable CI testing mode (overrides .gitreview, handles unrelated repos).",
|
272
|
+
),
|
264
273
|
duplicates: str = typer.Option(
|
265
274
|
"open",
|
266
275
|
"--duplicates",
|
@@ -269,36 +278,56 @@ def main(
|
|
269
278
|
'Gerrit statuses for duplicate detection (comma-separated). E.g. "open,merged,abandoned". Default: "open".'
|
270
279
|
),
|
271
280
|
),
|
281
|
+
normalise_commit: bool = typer.Option(
|
282
|
+
True,
|
283
|
+
"--normalise-commit/--no-normalise-commit",
|
284
|
+
envvar="NORMALISE_COMMIT",
|
285
|
+
help="Normalize commit messages to conventional commit format.",
|
286
|
+
),
|
272
287
|
verbose: bool = typer.Option(
|
273
288
|
False,
|
274
289
|
"--verbose",
|
275
290
|
"-v",
|
276
291
|
envvar="G2G_VERBOSE",
|
277
|
-
help="
|
292
|
+
help="Verbose output (sets loglevel to DEBUG).",
|
278
293
|
),
|
279
294
|
) -> None:
|
280
295
|
"""
|
281
296
|
Tool to convert GitHub pull requests into Gerrit changes
|
282
297
|
|
283
|
-
- Providing a URL to a pull request: converts that pull request
|
284
|
-
into a Gerrit change
|
298
|
+
- Providing a URL to a pull request: converts that pull request into a Gerrit change
|
285
299
|
|
286
|
-
- Providing a URL to a GitHub repository converts all open pull
|
287
|
-
requests into Gerrit changes
|
300
|
+
- Providing a URL to a GitHub repository converts all open pull requests into Gerrit changes
|
288
301
|
|
289
|
-
- No arguments for CI/CD environment; reads parameters from
|
290
|
-
environment variables
|
302
|
+
- No arguments for CI/CD environment; reads parameters from environment variables
|
291
303
|
"""
|
304
|
+
# Override boolean parameters with properly parsed environment variables
|
305
|
+
# This ensures that string "false" from GitHub Actions is handled correctly
|
306
|
+
if os.getenv("SUBMIT_SINGLE_COMMITS"):
|
307
|
+
submit_single_commits = parse_bool_env(os.getenv("SUBMIT_SINGLE_COMMITS"))
|
308
|
+
|
309
|
+
if os.getenv("USE_PR_AS_COMMIT"):
|
310
|
+
use_pr_as_commit = parse_bool_env(os.getenv("USE_PR_AS_COMMIT"))
|
311
|
+
|
312
|
+
if os.getenv("PRESERVE_GITHUB_PRS"):
|
313
|
+
preserve_github_prs = parse_bool_env(os.getenv("PRESERVE_GITHUB_PRS"))
|
314
|
+
|
315
|
+
if os.getenv("DRY_RUN"):
|
316
|
+
dry_run = parse_bool_env(os.getenv("DRY_RUN"))
|
317
|
+
|
318
|
+
if os.getenv("ALLOW_DUPLICATES"):
|
319
|
+
allow_duplicates = parse_bool_env(os.getenv("ALLOW_DUPLICATES"))
|
320
|
+
|
321
|
+
if os.getenv("CI_TESTING"):
|
322
|
+
ci_testing = parse_bool_env(os.getenv("CI_TESTING"))
|
292
323
|
# Set up logging level based on verbose flag
|
293
324
|
if verbose:
|
294
325
|
os.environ["G2G_LOG_LEVEL"] = "DEBUG"
|
295
326
|
_reconfigure_logging()
|
296
327
|
# Normalize CLI options into environment for unified processing.
|
297
|
-
#
|
298
|
-
if submit_single_commits
|
299
|
-
|
300
|
-
if use_pr_as_commit:
|
301
|
-
os.environ["USE_PR_AS_COMMIT"] = "true"
|
328
|
+
# Explicitly set all boolean flags to ensure consistent behavior
|
329
|
+
os.environ["SUBMIT_SINGLE_COMMITS"] = "true" if submit_single_commits else "false"
|
330
|
+
os.environ["USE_PR_AS_COMMIT"] = "true" if use_pr_as_commit else "false"
|
302
331
|
os.environ["FETCH_DEPTH"] = str(fetch_depth)
|
303
332
|
if gerrit_known_hosts:
|
304
333
|
os.environ["GERRIT_KNOWN_HOSTS"] = gerrit_known_hosts
|
@@ -313,10 +342,9 @@ def main(
|
|
313
342
|
os.environ["ORGANIZATION"] = resolved_org
|
314
343
|
if reviewers_email:
|
315
344
|
os.environ["REVIEWERS_EMAIL"] = reviewers_email
|
316
|
-
if preserve_github_prs
|
317
|
-
|
318
|
-
if
|
319
|
-
os.environ["DRY_RUN"] = "true"
|
345
|
+
os.environ["PRESERVE_GITHUB_PRS"] = "true" if preserve_github_prs else "false"
|
346
|
+
os.environ["DRY_RUN"] = "true" if dry_run else "false"
|
347
|
+
os.environ["NORMALISE_COMMIT"] = "true" if normalise_commit else "false"
|
320
348
|
os.environ["ALLOW_GHE_URLS"] = "true" if allow_ghe_urls else "false"
|
321
349
|
if gerrit_server:
|
322
350
|
os.environ["GERRIT_SERVER"] = gerrit_server
|
@@ -326,8 +354,8 @@ def main(
|
|
326
354
|
os.environ["GERRIT_PROJECT"] = gerrit_project
|
327
355
|
if issue_id:
|
328
356
|
os.environ["ISSUE_ID"] = issue_id
|
329
|
-
if allow_duplicates
|
330
|
-
|
357
|
+
os.environ["ALLOW_DUPLICATES"] = "true" if allow_duplicates else "false"
|
358
|
+
os.environ["CI_TESTING"] = "true" if ci_testing else "false"
|
331
359
|
if duplicates:
|
332
360
|
os.environ["DUPLICATES"] = duplicates
|
333
361
|
# URL mode handling
|
@@ -343,6 +371,12 @@ def main(
|
|
343
371
|
else:
|
344
372
|
os.environ["SYNC_ALL_OPEN_PRS"] = "true"
|
345
373
|
os.environ["G2G_TARGET_URL"] = "1"
|
374
|
+
# Debug: Show environment at CLI startup
|
375
|
+
log.debug("CLI startup environment check:")
|
376
|
+
for key in ["DRY_RUN", "CI_TESTING", "GERRIT_SERVER", "GERRIT_PROJECT"]:
|
377
|
+
value = os.environ.get(key, "NOT_SET")
|
378
|
+
log.debug(" %s = %s", key, value)
|
379
|
+
|
346
380
|
# Delegate to common processing path
|
347
381
|
try:
|
348
382
|
_process()
|
@@ -351,7 +385,7 @@ def main(
|
|
351
385
|
raise
|
352
386
|
except Exception as exc:
|
353
387
|
log.debug("main(): _process failed: %s", exc)
|
354
|
-
|
388
|
+
raise typer.Exit(code=1) from exc
|
355
389
|
|
356
390
|
|
357
391
|
def _setup_logging() -> logging.Logger:
|
@@ -374,68 +408,59 @@ def _reconfigure_logging() -> None:
|
|
374
408
|
log = _setup_logging()
|
375
409
|
|
376
410
|
|
377
|
-
def _env_str(name: str, default: str = "") -> str:
|
378
|
-
val = os.getenv(name)
|
379
|
-
return val if val is not None else default
|
380
|
-
|
381
|
-
|
382
|
-
def _env_bool(name: str, default: bool = False) -> bool:
|
383
|
-
val = os.getenv(name)
|
384
|
-
if val is None:
|
385
|
-
return default
|
386
|
-
s = val.strip().lower()
|
387
|
-
return s in ("1", "true", "yes", "on")
|
388
|
-
|
389
|
-
|
390
411
|
def _build_inputs_from_env() -> Inputs:
|
391
412
|
return Inputs(
|
392
|
-
submit_single_commits=
|
393
|
-
use_pr_as_commit=
|
394
|
-
fetch_depth=int(
|
395
|
-
gerrit_known_hosts=
|
396
|
-
gerrit_ssh_privkey_g2g=
|
397
|
-
gerrit_ssh_user_g2g=
|
398
|
-
gerrit_ssh_user_g2g_email=
|
399
|
-
organization=
|
400
|
-
reviewers_email=
|
401
|
-
preserve_github_prs=
|
402
|
-
dry_run=
|
403
|
-
|
404
|
-
|
405
|
-
|
406
|
-
|
407
|
-
|
408
|
-
|
413
|
+
submit_single_commits=env_bool("SUBMIT_SINGLE_COMMITS", False),
|
414
|
+
use_pr_as_commit=env_bool("USE_PR_AS_COMMIT", False),
|
415
|
+
fetch_depth=int(env_str("FETCH_DEPTH", "10") or "10"),
|
416
|
+
gerrit_known_hosts=env_str("GERRIT_KNOWN_HOSTS"),
|
417
|
+
gerrit_ssh_privkey_g2g=env_str("GERRIT_SSH_PRIVKEY_G2G"),
|
418
|
+
gerrit_ssh_user_g2g=env_str("GERRIT_SSH_USER_G2G"),
|
419
|
+
gerrit_ssh_user_g2g_email=env_str("GERRIT_SSH_USER_G2G_EMAIL"),
|
420
|
+
organization=env_str("ORGANIZATION", env_str("GITHUB_REPOSITORY_OWNER")),
|
421
|
+
reviewers_email=env_str("REVIEWERS_EMAIL", ""),
|
422
|
+
preserve_github_prs=env_bool("PRESERVE_GITHUB_PRS", False),
|
423
|
+
dry_run=env_bool("DRY_RUN", False),
|
424
|
+
normalise_commit=env_bool("NORMALISE_COMMIT", True),
|
425
|
+
gerrit_server=env_str("GERRIT_SERVER", ""),
|
426
|
+
gerrit_server_port=env_str("GERRIT_SERVER_PORT", "29418"),
|
427
|
+
gerrit_project=env_str("GERRIT_PROJECT"),
|
428
|
+
issue_id=env_str("ISSUE_ID", ""),
|
429
|
+
allow_duplicates=env_bool("ALLOW_DUPLICATES", False),
|
430
|
+
ci_testing=env_bool("CI_TESTING", False),
|
431
|
+
duplicates_filter=env_str("DUPLICATES", "open"),
|
409
432
|
)
|
410
433
|
|
411
434
|
|
412
|
-
def _process_bulk(data: Inputs, gh: GitHubContext) ->
|
435
|
+
def _process_bulk(data: Inputs, gh: GitHubContext) -> bool:
|
413
436
|
client = build_client()
|
414
437
|
repo = get_repo_from_env(client)
|
415
438
|
|
416
439
|
all_urls: list[str] = []
|
417
440
|
all_nums: list[str] = []
|
441
|
+
all_shas: list[str] = []
|
418
442
|
|
419
443
|
prs_list = list(iter_open_pulls(repo))
|
420
444
|
log.info("Found %d open PRs to process", len(prs_list))
|
421
|
-
|
445
|
+
|
446
|
+
# Result tracking for summary
|
447
|
+
processed_count = 0
|
448
|
+
succeeded_count = 0
|
449
|
+
skipped_count = 0
|
450
|
+
failed_count = 0
|
451
|
+
|
452
|
+
# Use bounded parallel processing with shared clients
|
453
|
+
max_workers = min(4, max(1, len(prs_list))) # Cap at 4 workers
|
454
|
+
|
455
|
+
def process_single_pr(
|
456
|
+
pr_data: tuple[Any, models.GitHubContext],
|
457
|
+
) -> tuple[str, SubmissionResult | None, Exception | None]:
|
458
|
+
"""Process a single PR and return (status, result, exception)."""
|
459
|
+
pr, per_ctx = pr_data
|
422
460
|
pr_number = int(getattr(pr, "number", 0) or 0)
|
423
|
-
if pr_number <= 0:
|
424
|
-
continue
|
425
461
|
|
426
|
-
|
427
|
-
|
428
|
-
event_action=gh.event_action,
|
429
|
-
event_path=gh.event_path,
|
430
|
-
repository=gh.repository,
|
431
|
-
repository_owner=gh.repository_owner,
|
432
|
-
server_url=gh.server_url,
|
433
|
-
run_id=gh.run_id,
|
434
|
-
sha=gh.sha,
|
435
|
-
base_ref=gh.base_ref,
|
436
|
-
head_ref=gh.head_ref,
|
437
|
-
pr_number=pr_number,
|
438
|
-
)
|
462
|
+
if pr_number <= 0:
|
463
|
+
return "invalid", None, None
|
439
464
|
|
440
465
|
log.info("Starting processing of PR #%d", pr_number)
|
441
466
|
log.debug(
|
@@ -450,58 +475,123 @@ def _process_bulk(data: Inputs, gh: GitHubContext) -> None:
|
|
450
475
|
os.environ["DUPLICATES"] = data.duplicates_filter
|
451
476
|
check_for_duplicates(per_ctx, allow_duplicates=data.allow_duplicates)
|
452
477
|
except DuplicateChangeError as exc:
|
453
|
-
|
478
|
+
log_exception_conditionally(log, "Skipping PR #%d", pr_number)
|
454
479
|
log.warning(
|
455
480
|
"Skipping PR #%d due to duplicate detection: %s. Use --allow-duplicates to override this check.",
|
456
481
|
pr_number,
|
457
482
|
exc,
|
458
483
|
)
|
459
|
-
|
484
|
+
return "skipped", None, exc
|
460
485
|
|
461
486
|
try:
|
462
487
|
with tempfile.TemporaryDirectory() as temp_dir:
|
463
488
|
workspace = Path(temp_dir)
|
464
489
|
orch = Orchestrator(workspace=workspace)
|
465
490
|
result_multi = orch.execute(inputs=data, gh=per_ctx)
|
466
|
-
|
467
|
-
all_urls.extend(result_multi.change_urls)
|
468
|
-
for url in result_multi.change_urls:
|
469
|
-
log.info("Gerrit change URL: %s", url)
|
470
|
-
log.info(
|
471
|
-
"PR #%d created Gerrit change: %s",
|
472
|
-
pr_number,
|
473
|
-
url,
|
474
|
-
)
|
475
|
-
if result_multi.change_numbers:
|
476
|
-
all_nums.extend(result_multi.change_numbers)
|
477
|
-
log.info(
|
478
|
-
"PR #%d change numbers: %s",
|
479
|
-
pr_number,
|
480
|
-
result_multi.change_numbers,
|
481
|
-
)
|
491
|
+
return "success", result_multi, None
|
482
492
|
except Exception as exc:
|
483
|
-
|
484
|
-
|
485
|
-
|
493
|
+
log_exception_conditionally(log, "Failed to process PR #%d", pr_number)
|
494
|
+
return "failed", None, exc
|
495
|
+
|
496
|
+
# Prepare PR processing tasks
|
497
|
+
pr_tasks = []
|
498
|
+
for pr in prs_list:
|
499
|
+
pr_number = int(getattr(pr, "number", 0) or 0)
|
500
|
+
if pr_number <= 0:
|
486
501
|
continue
|
487
502
|
|
503
|
+
per_ctx = models.GitHubContext(
|
504
|
+
event_name=gh.event_name,
|
505
|
+
event_action=gh.event_action,
|
506
|
+
event_path=gh.event_path,
|
507
|
+
repository=gh.repository,
|
508
|
+
repository_owner=gh.repository_owner,
|
509
|
+
server_url=gh.server_url,
|
510
|
+
run_id=gh.run_id,
|
511
|
+
sha=gh.sha,
|
512
|
+
base_ref=gh.base_ref,
|
513
|
+
head_ref=gh.head_ref,
|
514
|
+
pr_number=pr_number,
|
515
|
+
)
|
516
|
+
pr_tasks.append((pr, per_ctx))
|
517
|
+
|
518
|
+
# Process PRs in parallel
|
519
|
+
with ThreadPoolExecutor(max_workers=max_workers) as executor:
|
520
|
+
log.info("Processing %d PRs with %d parallel workers", len(pr_tasks), max_workers)
|
521
|
+
|
522
|
+
# Submit all tasks
|
523
|
+
future_to_pr = {
|
524
|
+
executor.submit(process_single_pr, pr_task): pr_task[1].pr_number
|
525
|
+
for pr_task in pr_tasks
|
526
|
+
if pr_task[1].pr_number is not None
|
527
|
+
}
|
528
|
+
|
529
|
+
# Collect results as they complete
|
530
|
+
for future in as_completed(future_to_pr):
|
531
|
+
pr_number = future_to_pr[future]
|
532
|
+
processed_count += 1
|
533
|
+
|
534
|
+
try:
|
535
|
+
status, result_multi, exc = future.result()
|
536
|
+
|
537
|
+
if status == "success" and result_multi:
|
538
|
+
succeeded_count += 1
|
539
|
+
if result_multi.change_urls:
|
540
|
+
all_urls.extend(result_multi.change_urls)
|
541
|
+
for url in result_multi.change_urls:
|
542
|
+
log.info("Gerrit change URL: %s", url)
|
543
|
+
log.info("PR #%d created Gerrit change: %s", pr_number, url)
|
544
|
+
if result_multi.change_numbers:
|
545
|
+
all_nums.extend(result_multi.change_numbers)
|
546
|
+
log.info("PR #%d change numbers: %s", pr_number, result_multi.change_numbers)
|
547
|
+
if result_multi.commit_shas:
|
548
|
+
all_shas.extend(result_multi.commit_shas)
|
549
|
+
elif status == "skipped":
|
550
|
+
skipped_count += 1
|
551
|
+
elif status == "failed":
|
552
|
+
failed_count += 1
|
553
|
+
typer.echo(f"Failed to process PR #{pr_number}: {exc}")
|
554
|
+
log.info("Continuing to next PR despite failure")
|
555
|
+
else:
|
556
|
+
failed_count += 1
|
557
|
+
|
558
|
+
except Exception as exc:
|
559
|
+
failed_count += 1
|
560
|
+
log_exception_conditionally(log, "Failed to process PR #%d", pr_number)
|
561
|
+
typer.echo(f"Failed to process PR #{pr_number}: {exc}")
|
562
|
+
log.info("Continuing to next PR despite failure")
|
563
|
+
|
564
|
+
# Aggregate results and provide summary
|
488
565
|
if all_urls:
|
489
566
|
os.environ["GERRIT_CHANGE_REQUEST_URL"] = "\n".join(all_urls)
|
490
567
|
if all_nums:
|
491
568
|
os.environ["GERRIT_CHANGE_REQUEST_NUM"] = "\n".join(all_nums)
|
569
|
+
if all_shas:
|
570
|
+
os.environ["GERRIT_COMMIT_SHA"] = "\n".join(all_shas)
|
492
571
|
|
493
|
-
|
572
|
+
append_github_output(
|
494
573
|
{
|
495
|
-
"gerrit_change_request_url":
|
496
|
-
"gerrit_change_request_num":
|
574
|
+
"gerrit_change_request_url": "\n".join(all_urls) if all_urls else "",
|
575
|
+
"gerrit_change_request_num": "\n".join(all_nums) if all_nums else "",
|
576
|
+
"gerrit_commit_sha": "\n".join(all_shas) if all_shas else "",
|
497
577
|
}
|
498
578
|
)
|
499
579
|
|
500
|
-
|
501
|
-
|
580
|
+
# Summary block
|
581
|
+
log.info("=" * 60)
|
582
|
+
log.info("BULK PROCESSING SUMMARY:")
|
583
|
+
log.info(" Total PRs processed: %d", processed_count)
|
584
|
+
log.info(" Succeeded: %d", succeeded_count)
|
585
|
+
log.info(" Skipped (duplicates): %d", skipped_count)
|
586
|
+
log.info(" Failed: %d", failed_count)
|
587
|
+
log.info(" Gerrit changes created: %d", len(all_urls))
|
588
|
+
log.info("=" * 60)
|
502
589
|
|
590
|
+
# Return True if no failures occurred
|
591
|
+
return failed_count == 0
|
503
592
|
|
504
|
-
|
593
|
+
|
594
|
+
def _process_single(data: Inputs, gh: GitHubContext) -> bool:
|
505
595
|
# Create temporary directory for all git operations
|
506
596
|
with tempfile.TemporaryDirectory() as temp_dir:
|
507
597
|
workspace = Path(temp_dir)
|
@@ -527,21 +617,19 @@ def _process_single(data: Inputs, gh: GitHubContext) -> None:
|
|
527
617
|
log.info("Gerrit change URL: %s", url)
|
528
618
|
if result.change_numbers:
|
529
619
|
os.environ["GERRIT_CHANGE_REQUEST_NUM"] = "\n".join(result.change_numbers)
|
620
|
+
if result.commit_shas:
|
621
|
+
os.environ["GERRIT_COMMIT_SHA"] = "\n".join(result.commit_shas)
|
530
622
|
|
531
623
|
# Also write outputs to GITHUB_OUTPUT if available
|
532
|
-
|
624
|
+
append_github_output(
|
533
625
|
{
|
534
|
-
"gerrit_change_request_url":
|
535
|
-
"gerrit_change_request_num":
|
536
|
-
"gerrit_commit_sha":
|
626
|
+
"gerrit_change_request_url": "\n".join(result.change_urls) if result.change_urls else "",
|
627
|
+
"gerrit_change_request_num": "\n".join(result.change_numbers) if result.change_numbers else "",
|
628
|
+
"gerrit_commit_sha": "\n".join(result.commit_shas) if result.commit_shas else "",
|
537
629
|
}
|
538
630
|
)
|
539
631
|
|
540
|
-
|
541
|
-
log.info("Submission pipeline completed SUCCESSFULLY ✅")
|
542
|
-
else:
|
543
|
-
log.error("Submission pipeline FAILED ❌")
|
544
|
-
return
|
632
|
+
return pipeline_success
|
545
633
|
|
546
634
|
|
547
635
|
def _prepare_local_checkout(workspace: Path, gh: GitHubContext, data: Inputs) -> None:
|
@@ -554,31 +642,52 @@ def _prepare_local_checkout(workspace: Path, gh: GitHubContext, data: Inputs) ->
|
|
554
642
|
if not repo_full:
|
555
643
|
return
|
556
644
|
|
557
|
-
|
645
|
+
# Try SSH first for private repos if available, then fall back to HTTPS/API
|
646
|
+
repo_ssh_url = f"git@{server_url.replace('https://', '').replace('http://', '')}:{repo_full}.git"
|
647
|
+
repo_https_url = f"{server_url}/{repo_full}.git"
|
648
|
+
|
558
649
|
run_cmd(["git", "init"], cwd=workspace)
|
650
|
+
|
651
|
+
# Determine which URL to use and set up authentication
|
652
|
+
env: dict[str, str] = {}
|
653
|
+
repo_url = repo_https_url # Default to HTTPS
|
654
|
+
|
655
|
+
# Check if we should try SSH for private repos
|
656
|
+
use_ssh = False
|
657
|
+
respect_user_ssh = os.getenv("G2G_RESPECT_USER_SSH", "false").lower() in ("true", "1", "yes")
|
658
|
+
gerrit_ssh_privkey = os.getenv("GERRIT_SSH_PRIVKEY_G2G")
|
659
|
+
|
660
|
+
log.debug(
|
661
|
+
"GitHub repo access decision: SSH URL available=%s, G2G_RESPECT_USER_SSH=%s, GERRIT_SSH_PRIVKEY_G2G=%s",
|
662
|
+
repo_ssh_url.startswith("git@"),
|
663
|
+
respect_user_ssh,
|
664
|
+
bool(gerrit_ssh_privkey),
|
665
|
+
)
|
666
|
+
|
667
|
+
if repo_ssh_url.startswith("git@"):
|
668
|
+
# For private repos, only try SSH if G2G_RESPECT_USER_SSH is explicitly enabled
|
669
|
+
# Don't use SSH just because GERRIT_SSH_PRIVKEY_G2G is set (that's for Gerrit, not GitHub)
|
670
|
+
if respect_user_ssh:
|
671
|
+
use_ssh = True
|
672
|
+
repo_url = repo_ssh_url
|
673
|
+
log.debug("Using SSH for GitHub repo access due to G2G_RESPECT_USER_SSH=true")
|
674
|
+
else:
|
675
|
+
log.debug("Not using SSH for GitHub repo access - G2G_RESPECT_USER_SSH not enabled")
|
676
|
+
|
677
|
+
if use_ssh:
|
678
|
+
env = {
|
679
|
+
"GIT_SSH_COMMAND": build_git_ssh_command(),
|
680
|
+
**build_non_interactive_ssh_env(),
|
681
|
+
}
|
682
|
+
log.debug("Using SSH URL for private repo: %s", repo_url)
|
683
|
+
else:
|
684
|
+
log.debug("Using HTTPS URL: %s", repo_url)
|
685
|
+
|
559
686
|
run_cmd(["git", "remote", "add", "origin", repo_url], cwd=workspace)
|
560
687
|
|
561
|
-
#
|
562
|
-
|
563
|
-
"GIT_SSH_COMMAND": (
|
564
|
-
"ssh -F /dev/null "
|
565
|
-
"-o IdentitiesOnly=yes "
|
566
|
-
"-o IdentityAgent=none "
|
567
|
-
"-o BatchMode=yes "
|
568
|
-
"-o PreferredAuthentications=publickey "
|
569
|
-
"-o StrictHostKeyChecking=yes "
|
570
|
-
"-o PasswordAuthentication=no "
|
571
|
-
"-o PubkeyAcceptedKeyTypes=+ssh-rsa "
|
572
|
-
"-o ConnectTimeout=10"
|
573
|
-
),
|
574
|
-
"SSH_AUTH_SOCK": "",
|
575
|
-
"SSH_AGENT_PID": "",
|
576
|
-
"SSH_ASKPASS": "/usr/bin/false",
|
577
|
-
"DISPLAY": "",
|
578
|
-
"SSH_ASKPASS_REQUIRE": "never",
|
579
|
-
}
|
688
|
+
# Fetch base branch and PR head with fallback to API archive
|
689
|
+
fetch_success = False
|
580
690
|
|
581
|
-
# Fetch base branch and PR head
|
582
691
|
if base_ref:
|
583
692
|
try:
|
584
693
|
branch_ref = f"refs/heads/{base_ref}:refs/remotes/origin/{base_ref}"
|
@@ -597,29 +706,161 @@ def _prepare_local_checkout(workspace: Path, gh: GitHubContext, data: Inputs) ->
|
|
597
706
|
log.debug("Base branch fetch failed for %s: %s", base_ref, exc)
|
598
707
|
|
599
708
|
if pr_num_str:
|
600
|
-
|
601
|
-
|
602
|
-
|
603
|
-
|
604
|
-
|
605
|
-
|
606
|
-
|
607
|
-
|
608
|
-
|
609
|
-
|
610
|
-
|
611
|
-
|
612
|
-
|
613
|
-
|
614
|
-
|
615
|
-
|
616
|
-
|
617
|
-
|
618
|
-
|
619
|
-
|
620
|
-
|
621
|
-
|
622
|
-
|
709
|
+
try:
|
710
|
+
pr_ref = f"refs/pull/{pr_num_str}/head:refs/remotes/origin/pr/{pr_num_str}/head"
|
711
|
+
run_cmd(
|
712
|
+
[
|
713
|
+
"git",
|
714
|
+
"fetch",
|
715
|
+
f"--depth={data.fetch_depth}",
|
716
|
+
"origin",
|
717
|
+
pr_ref,
|
718
|
+
],
|
719
|
+
cwd=workspace,
|
720
|
+
env=env,
|
721
|
+
)
|
722
|
+
run_cmd(
|
723
|
+
[
|
724
|
+
"git",
|
725
|
+
"checkout",
|
726
|
+
"-B",
|
727
|
+
"g2g_pr_head",
|
728
|
+
f"refs/remotes/origin/pr/{pr_num_str}/head",
|
729
|
+
],
|
730
|
+
cwd=workspace,
|
731
|
+
env=env,
|
732
|
+
)
|
733
|
+
fetch_success = True
|
734
|
+
except Exception as exc:
|
735
|
+
log.warning("Git fetch failed, attempting API archive fallback: %s", exc)
|
736
|
+
# Try API archive fallback for private repos
|
737
|
+
try:
|
738
|
+
_fallback_to_api_archive(workspace, gh, data, pr_num_str)
|
739
|
+
fetch_success = True
|
740
|
+
except Exception as api_exc:
|
741
|
+
log.exception("API archive fallback also failed")
|
742
|
+
raise exc from api_exc
|
743
|
+
|
744
|
+
if not fetch_success and pr_num_str:
|
745
|
+
msg = f"Failed to prepare checkout for PR #{pr_num_str}"
|
746
|
+
raise RuntimeError(msg)
|
747
|
+
|
748
|
+
|
749
|
+
def _fallback_to_api_archive(workspace: Path, gh: GitHubContext, data: Inputs, pr_num_str: str) -> None:
|
750
|
+
"""Fallback to GitHub API archive download for private repos."""
|
751
|
+
log.info("Attempting API archive fallback for PR #%s", pr_num_str)
|
752
|
+
|
753
|
+
# Get GitHub token for authenticated requests
|
754
|
+
token = os.getenv("GITHUB_TOKEN")
|
755
|
+
if not token:
|
756
|
+
msg = "GITHUB_TOKEN required for API archive fallback"
|
757
|
+
raise RuntimeError(msg)
|
758
|
+
|
759
|
+
# Build API URLs
|
760
|
+
repo_full = gh.repository
|
761
|
+
server_url = gh.server_url or "https://github.com"
|
762
|
+
|
763
|
+
# Construct GitHub API base URL properly
|
764
|
+
if "github.com" in server_url:
|
765
|
+
# For github.com, use api.github.com
|
766
|
+
api_base = "https://api.github.com"
|
767
|
+
elif server_url.startswith("https://"):
|
768
|
+
# For GitHub Enterprise, append /api/v3
|
769
|
+
api_base = server_url.rstrip("/") + "/api/v3"
|
770
|
+
else:
|
771
|
+
# Fallback for unexpected formats
|
772
|
+
api_base = "https://api.github.com"
|
773
|
+
|
774
|
+
# Get PR details to find head SHA
|
775
|
+
pr_api_url = f"{api_base}/repos/{repo_full}/pulls/{pr_num_str}"
|
776
|
+
log.debug("GitHub API PR URL: %s", pr_api_url)
|
777
|
+
|
778
|
+
headers = {
|
779
|
+
"Authorization": f"token {token}",
|
780
|
+
"Accept": "application/vnd.github.v3+json",
|
781
|
+
"User-Agent": "github2gerrit",
|
782
|
+
}
|
783
|
+
|
784
|
+
try:
|
785
|
+
req = Request(pr_api_url, headers=headers) # noqa: S310
|
786
|
+
with urlopen(req, timeout=30) as response: # noqa: S310
|
787
|
+
pr_data = json.loads(response.read().decode())
|
788
|
+
except Exception:
|
789
|
+
log.exception("Failed to fetch PR data from GitHub API")
|
790
|
+
log.debug("PR API URL was: %s", pr_api_url)
|
791
|
+
raise
|
792
|
+
|
793
|
+
head_sha = pr_data["head"]["sha"]
|
794
|
+
|
795
|
+
# Download archive
|
796
|
+
archive_url = f"{api_base}/repos/{repo_full}/zipball/{head_sha}"
|
797
|
+
log.debug("GitHub API archive URL: %s", archive_url)
|
798
|
+
|
799
|
+
try:
|
800
|
+
req = Request(archive_url, headers=headers) # noqa: S310
|
801
|
+
with urlopen(req, timeout=120) as response: # noqa: S310
|
802
|
+
archive_data = response.read()
|
803
|
+
except Exception:
|
804
|
+
log.exception("Failed to download archive from GitHub API")
|
805
|
+
log.debug("Archive URL was: %s", archive_url)
|
806
|
+
raise
|
807
|
+
|
808
|
+
# Extract archive
|
809
|
+
with zipfile.ZipFile(io.BytesIO(archive_data)) as zf:
|
810
|
+
# Find the root directory in the archive (usually repo-sha format)
|
811
|
+
members = zf.namelist()
|
812
|
+
root_dir = None
|
813
|
+
for member in members:
|
814
|
+
if "/" in member:
|
815
|
+
root_dir = member.split("/")[0]
|
816
|
+
break
|
817
|
+
|
818
|
+
if not root_dir:
|
819
|
+
msg = "Could not find root directory in archive"
|
820
|
+
raise RuntimeError(msg)
|
821
|
+
|
822
|
+
# Extract to temporary location then move contents
|
823
|
+
extract_path = workspace / "archive_temp"
|
824
|
+
zf.extractall(extract_path)
|
825
|
+
|
826
|
+
# Move contents from extracted root to workspace
|
827
|
+
extracted_root = extract_path / root_dir
|
828
|
+
for item in extracted_root.iterdir():
|
829
|
+
if item.name == ".git":
|
830
|
+
continue # Skip .git if present
|
831
|
+
dest = workspace / item.name
|
832
|
+
if dest.exists():
|
833
|
+
if dest.is_dir():
|
834
|
+
shutil.rmtree(dest)
|
835
|
+
else:
|
836
|
+
dest.unlink()
|
837
|
+
item.rename(dest)
|
838
|
+
|
839
|
+
# Clean up
|
840
|
+
shutil.rmtree(extract_path)
|
841
|
+
|
842
|
+
# Set up git for the extracted content
|
843
|
+
if not (workspace / ".git").exists():
|
844
|
+
run_cmd(["git", "init"], cwd=workspace)
|
845
|
+
|
846
|
+
# Create a commit for the PR content
|
847
|
+
run_cmd(["git", "add", "."], cwd=workspace)
|
848
|
+
run_cmd(
|
849
|
+
[
|
850
|
+
"git",
|
851
|
+
"commit",
|
852
|
+
"-m",
|
853
|
+
f"PR #{pr_num_str} content from API archive",
|
854
|
+
"--author",
|
855
|
+
"GitHub API <noreply@github.com>",
|
856
|
+
],
|
857
|
+
cwd=workspace,
|
858
|
+
)
|
859
|
+
|
860
|
+
# Create the expected branch
|
861
|
+
run_cmd(["git", "checkout", "-B", "g2g_pr_head"], cwd=workspace)
|
862
|
+
|
863
|
+
log.info("Successfully extracted PR #%s content via API archive", pr_num_str)
|
623
864
|
|
624
865
|
|
625
866
|
def _load_effective_inputs() -> Inputs:
|
@@ -633,6 +874,15 @@ def _load_effective_inputs() -> Inputs:
|
|
633
874
|
# Apply dynamic parameter derivation for missing Gerrit parameters
|
634
875
|
cfg = apply_parameter_derivation(cfg, org_for_cfg, save_to_config=True)
|
635
876
|
|
877
|
+
# Debug: Show what configuration would be applied
|
878
|
+
log.debug("Configuration to apply: %s", cfg)
|
879
|
+
if "DRY_RUN" in cfg:
|
880
|
+
log.warning(
|
881
|
+
"Configuration contains DRY_RUN=%s, this may override environment DRY_RUN=%s",
|
882
|
+
cfg["DRY_RUN"],
|
883
|
+
os.getenv("DRY_RUN"),
|
884
|
+
)
|
885
|
+
|
636
886
|
apply_config_to_env(cfg)
|
637
887
|
|
638
888
|
# Refresh inputs after applying configuration to environment
|
@@ -658,11 +908,13 @@ def _load_effective_inputs() -> Inputs:
|
|
658
908
|
reviewers_email=os.environ["REVIEWERS_EMAIL"],
|
659
909
|
preserve_github_prs=data.preserve_github_prs,
|
660
910
|
dry_run=data.dry_run,
|
911
|
+
normalise_commit=data.normalise_commit,
|
661
912
|
gerrit_server=data.gerrit_server,
|
662
913
|
gerrit_server_port=data.gerrit_server_port,
|
663
914
|
gerrit_project=data.gerrit_project,
|
664
915
|
issue_id=data.issue_id,
|
665
916
|
allow_duplicates=data.allow_duplicates,
|
917
|
+
ci_testing=data.ci_testing,
|
666
918
|
duplicates_filter=data.duplicates_filter,
|
667
919
|
)
|
668
920
|
log.info("Derived reviewers: %s", data.reviewers_email)
|
@@ -672,25 +924,6 @@ def _load_effective_inputs() -> Inputs:
|
|
672
924
|
return data
|
673
925
|
|
674
926
|
|
675
|
-
def _append_github_output(outputs: dict[str, str]) -> None:
|
676
|
-
gh_out = os.getenv("GITHUB_OUTPUT")
|
677
|
-
if not gh_out:
|
678
|
-
return
|
679
|
-
try:
|
680
|
-
with open(gh_out, "a", encoding="utf-8") as fh:
|
681
|
-
for key, val in outputs.items():
|
682
|
-
if not val:
|
683
|
-
continue
|
684
|
-
if "\n" in val:
|
685
|
-
fh.write(f"{key}<<G2G\n")
|
686
|
-
fh.write(f"{val}\n")
|
687
|
-
fh.write("G2G\n")
|
688
|
-
else:
|
689
|
-
fh.write(f"{key}={val}\n")
|
690
|
-
except Exception as exc:
|
691
|
-
log.debug("Failed to write GITHUB_OUTPUT: %s", exc)
|
692
|
-
|
693
|
-
|
694
927
|
def _augment_pr_refs_if_needed(gh: GitHubContext) -> GitHubContext:
|
695
928
|
if os.getenv("G2G_TARGET_URL") and gh.pr_number and (not gh.head_ref or not gh.base_ref):
|
696
929
|
try:
|
@@ -722,7 +955,7 @@ def _process() -> None:
|
|
722
955
|
try:
|
723
956
|
_validate_inputs(data)
|
724
957
|
except ConfigurationError as exc:
|
725
|
-
|
958
|
+
log_exception_conditionally(log, "Configuration validation failed")
|
726
959
|
typer.echo(f"Configuration validation failed: {exc}", err=True)
|
727
960
|
raise typer.Exit(code=2) from exc
|
728
961
|
|
@@ -730,15 +963,31 @@ def _process() -> None:
|
|
730
963
|
_log_effective_config(data, gh)
|
731
964
|
|
732
965
|
# Test mode: short-circuit after validation
|
733
|
-
if
|
966
|
+
if env_bool("G2G_TEST_MODE", False):
|
734
967
|
log.info("Validation complete. Ready to execute submission pipeline.")
|
735
968
|
typer.echo("Validation complete. Ready to execute submission pipeline.")
|
736
969
|
return
|
737
970
|
|
738
971
|
# Bulk mode for URL/workflow_dispatch
|
739
|
-
sync_all =
|
972
|
+
sync_all = env_bool("SYNC_ALL_OPEN_PRS", False)
|
740
973
|
if sync_all and (gh.event_name == "workflow_dispatch" or os.getenv("G2G_TARGET_URL")):
|
741
|
-
_process_bulk(data, gh)
|
974
|
+
bulk_success = _process_bulk(data, gh)
|
975
|
+
|
976
|
+
# Log external API metrics summary
|
977
|
+
try:
|
978
|
+
from .external_api import log_api_metrics_summary
|
979
|
+
|
980
|
+
log_api_metrics_summary()
|
981
|
+
except Exception as exc:
|
982
|
+
log.debug("Failed to log API metrics summary: %s", exc)
|
983
|
+
|
984
|
+
# Final success/failure message for bulk processing
|
985
|
+
if bulk_success:
|
986
|
+
log.info("Bulk processing completed SUCCESSFULLY ✅")
|
987
|
+
else:
|
988
|
+
log.error("Bulk processing FAILED ❌")
|
989
|
+
raise typer.Exit(code=1)
|
990
|
+
|
742
991
|
return
|
743
992
|
|
744
993
|
if not gh.pr_number:
|
@@ -759,13 +1008,13 @@ def _process() -> None:
|
|
759
1008
|
gh = _augment_pr_refs_if_needed(gh)
|
760
1009
|
|
761
1010
|
# Check for duplicates in single-PR mode (before workspace setup)
|
762
|
-
if gh.pr_number and not
|
1011
|
+
if gh.pr_number and not env_bool("SYNC_ALL_OPEN_PRS", False):
|
763
1012
|
try:
|
764
1013
|
if data.duplicates_filter:
|
765
1014
|
os.environ["DUPLICATES"] = data.duplicates_filter
|
766
1015
|
check_for_duplicates(gh, allow_duplicates=data.allow_duplicates)
|
767
1016
|
except DuplicateChangeError as exc:
|
768
|
-
|
1017
|
+
log_exception_conditionally(
|
769
1018
|
log,
|
770
1019
|
"Duplicate detection blocked submission for PR #%d",
|
771
1020
|
gh.pr_number,
|
@@ -773,7 +1022,23 @@ def _process() -> None:
|
|
773
1022
|
log.info("Use --allow-duplicates to override this check.")
|
774
1023
|
raise typer.Exit(code=3) from exc
|
775
1024
|
|
776
|
-
_process_single(data, gh)
|
1025
|
+
pipeline_success = _process_single(data, gh)
|
1026
|
+
|
1027
|
+
# Log external API metrics summary
|
1028
|
+
try:
|
1029
|
+
from .external_api import log_api_metrics_summary
|
1030
|
+
|
1031
|
+
log_api_metrics_summary()
|
1032
|
+
except Exception as exc:
|
1033
|
+
log.debug("Failed to log API metrics summary: %s", exc)
|
1034
|
+
|
1035
|
+
# Final success/failure message after all cleanup
|
1036
|
+
if pipeline_success:
|
1037
|
+
log.info("Submission pipeline completed SUCCESSFULLY ✅")
|
1038
|
+
else:
|
1039
|
+
log.error("Submission pipeline FAILED ❌")
|
1040
|
+
raise typer.Exit(code=1)
|
1041
|
+
|
777
1042
|
return
|
778
1043
|
|
779
1044
|
|
@@ -892,7 +1157,7 @@ def _validate_inputs(data: Inputs) -> None:
|
|
892
1157
|
", ".join(missing_gerrit_params),
|
893
1158
|
)
|
894
1159
|
# Allow derivation in local mode only if explicitly enabled
|
895
|
-
if not
|
1160
|
+
if not env_bool("G2G_ENABLE_DERIVATION", False):
|
896
1161
|
required_fields.extend(missing_gerrit_params)
|
897
1162
|
else:
|
898
1163
|
required_fields.extend(missing_gerrit_params)
|
@@ -947,7 +1212,8 @@ def _log_effective_config(data: Inputs, gh: GitHubContext) -> None:
|
|
947
1212
|
log.info(" REVIEWERS_EMAIL: %s", data.reviewers_email or "")
|
948
1213
|
log.info(" PRESERVE_GITHUB_PRS: %s", data.preserve_github_prs)
|
949
1214
|
log.info(" DRY_RUN: %s", data.dry_run)
|
950
|
-
log.info("
|
1215
|
+
log.info(" CI_TESTING: %s", data.ci_testing)
|
1216
|
+
log.info(" GERRIT_SERVER: %s", data.gerrit_server)
|
951
1217
|
log.info(" GERRIT_SERVER_PORT: %s", data.gerrit_server_port or "")
|
952
1218
|
log.info(" GERRIT_PROJECT: %s", data.gerrit_project or "")
|
953
1219
|
log.info("GitHub context:")
|