Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions .pre-commit-config.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -140,8 +140,8 @@ repos:
hooks:
- id: pytest
name: pytest
entry: uv
args: [run, pytest, --tb=short, -q, -v, --strict-markers, --maxfail=5]
entry: env
args: [-u, VIRTUAL_ENV, uv, run, pytest, --tb=short, -q, -v, --strict-markers, --maxfail=5]
language: system
Comment on lines +143 to 145
pass_filenames: false
always_run: true
Expand Down
2 changes: 0 additions & 2 deletions pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -102,7 +102,6 @@ dev = [
# Type checking helpers
"pytest-mock>=3.15.1",
"types-requests>=2.31.0",
"types-click>=7.1.8",
"types-urllib3>=1.26.25.14",
]

Expand Down Expand Up @@ -230,7 +229,6 @@ directory = "coverage_html_report"
minversion = "8.0"
addopts = "-ra -q --cov=github2gerrit --cov-report=term-missing --cov-report=html"
testpaths = ["tests"]
asyncio_default_fixture_loop_scope = "function"
markers = [
"integration: marks tests as integration tests (deselect with '-m \"not integration\"')",
]
Expand Down
10 changes: 6 additions & 4 deletions src/github2gerrit/cli.py
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@
from urllib.parse import urlparse

import click
import click.core
import typer

from . import models
Expand Down Expand Up @@ -845,8 +846,8 @@ def _env_bool_override(
param_name: str, env_var: str, current: bool
) -> bool:
"""Return *current* if the CLI flag was explicit, else parse env."""
source = ctx.get_parameter_source(param_name)
if source == click.core.ParameterSource.COMMANDLINE:
source = ctx.get_parameter_source(param_name) # pyright: ignore[reportAttributeAccessIssue]
if source == click.core.ParameterSource.COMMANDLINE: # pyright: ignore[reportAttributeAccessIssue]
return current
env_val = os.getenv(env_var)
if env_val is not None:
Expand Down Expand Up @@ -1620,8 +1621,9 @@ def _process_single(
progress_tracker=progress_tracker,
)
safe_console_print(
" To create a new change, trigger the 'opened' "
"workflow action.",
" To create a new change, set CREATE_MISSING=true "
"or add a '@github2gerrit create missing change' "
"comment on the PR.",
style="yellow",
progress_tracker=progress_tracker,
)
Expand Down
47 changes: 44 additions & 3 deletions src/github2gerrit/config.py
Original file line number Diff line number Diff line change
Expand Up @@ -454,11 +454,38 @@ def _is_local_cli_context() -> bool:
return not _is_github_actions_context()


def _read_gitreview_host(repository: str | None = None) -> str | None:
"""Read the Gerrit host from the .gitreview file.

Delegates to the shared :mod:`github2gerrit.gitreview` module which
consolidates all ``.gitreview`` parsing and fetching logic.

Checks the local workspace first (available after actions/checkout),
then falls back to fetching via raw.githubusercontent.com when a
GITHUB_REPOSITORY is set.

Args:
repository: GitHub repository in owner/repo format (optional).
Falls back to GITHUB_REPOSITORY env var.

Returns:
The host string from .gitreview, or None if unavailable.
"""
from .gitreview import read_gitreview_host

return read_gitreview_host(repository)


def derive_gerrit_parameters(
organization: str | None, repository: str | None = None
) -> dict[str, str]:
"""Derive Gerrit parameters using SSH config, git config, and org fallback.

Priority order for server derivation:
1. Per-org configuration file entry (GERRIT_SERVER)
2. .gitreview host field (local file or fetched from GitHub)
3. Heuristic fallback: gerrit.[org].org

Priority order for credential derivation:
1. SSH config user for gerrit.* hosts (checks generic and specific patterns)
2. Git user email from local git configuration
Expand All @@ -472,7 +499,7 @@ def derive_gerrit_parameters(
Dict with derived parameter values:
- GERRIT_SSH_USER_G2G: From SSH config or [org].gh2gerrit
- GERRIT_SSH_USER_G2G_EMAIL: From git config or fallback email
- GERRIT_SERVER: Resolved from config or gerrit.[org].org
- GERRIT_SERVER: Resolved from config, .gitreview, or gerrit.[org].org
- GERRIT_PROJECT: Derived from repository name if provided
"""
if not organization:
Expand All @@ -484,8 +511,22 @@ def derive_gerrit_parameters(
config = load_org_config(org)
configured_server = config.get("GERRIT_SERVER", "").strip()

# Determine the gerrit server to use for SSH config lookup
gerrit_host = configured_server or f"gerrit.{org}.org"
# Read .gitreview host only when no config file entry
# (avoid unnecessary I/O)
gitreview_host = (
_read_gitreview_host(repository) if not configured_server else None
)

# Priority: config file > .gitreview > heuristic fallback
gerrit_host = configured_server or gitreview_host or f"gerrit.{org}.org"

if gitreview_host and not configured_server:
log.debug(
"Using Gerrit host from .gitreview: %s (instead of heuristic "
"gerrit.%s.org)",
gitreview_host,
org,
)

# Derive GERRIT_PROJECT from repository if provided
gerrit_project = ""
Expand Down
Loading
Loading