Skip to content
Merged
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
38 changes: 32 additions & 6 deletions cli/python/base_dev/engine.py
Original file line number Diff line number Diff line change
Expand Up @@ -86,9 +86,7 @@ def check_dev_artifacts(
definitions: tuple[ArtifactDefinition, ...],
output_format: str,
) -> int:
checks = tuple(
check_homebrew_artifact(artifact, definition) for artifact, definition in zip(artifacts, definitions)
)
checks = dev_checks(artifacts, definitions)
if output_format == "json":
print(json.dumps([check_to_json(check) for check in checks], indent=2))
elif output_format == "text":
Expand All @@ -109,9 +107,7 @@ def doctor_dev_artifacts(
definitions: tuple[ArtifactDefinition, ...],
output_format: str,
) -> int:
checks = tuple(
check_homebrew_artifact(artifact, definition) for artifact, definition in zip(artifacts, definitions)
)
checks = dev_checks(artifacts, definitions)
if output_format == "json":
print(json.dumps([check_to_doctor_json(check) for check in checks], indent=2))
return min(sum(1 for check in checks if doctor_status(check) == "error"), 125)
Expand All @@ -130,6 +126,19 @@ def doctor_dev_artifacts(
return min(error_count, 125)


def dev_checks(
artifacts: tuple[ArtifactRequest, ...],
definitions: tuple[ArtifactDefinition, ...],
) -> tuple[DevCheck, ...]:
checks: list[DevCheck] = []
for artifact, definition in zip(artifacts, definitions):
check = check_homebrew_artifact(artifact, definition)
checks.append(check)
if artifact.name == "gh" and check.ok:
checks.append(check_github_cli_auth())
return tuple(checks)


def check_homebrew_artifact(artifact: ArtifactRequest, definition: ArtifactDefinition) -> DevCheck:
if definition.manager != "homebrew":
return DevCheck(
Expand Down Expand Up @@ -164,6 +173,23 @@ def check_homebrew_artifact(artifact: ArtifactRequest, definition: ArtifactDefin
)


def check_github_cli_auth() -> DevCheck:
ok = run_check(["gh", "auth", "status"])
if ok:
return DevCheck(
name="gh-auth",
ok=True,
message="GitHub CLI authentication is ready.",
fix="",
)
return DevCheck(
name="gh-auth",
ok=False,
message="GitHub CLI authentication is not ready.",
fix="gh auth login -h github.com",
)


def check_to_json(check: DevCheck) -> dict[str, str | bool]:
return {
"name": check.name,
Expand Down
50 changes: 50 additions & 0 deletions cli/python/base_dev/tests/test_engine.py
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,33 @@ def test_check_json_reports_manifest_artifacts(self) -> None:
self.assertIn('"name": "gh"', stdout)
self.assertEqual(stderr, "")

@unittest.skipUnless(importlib.util.find_spec("click"), "Click is not installed")
def test_check_json_reports_invalid_github_auth_when_gh_is_installed(self) -> None:
def fake_run_check(command: list[str]) -> bool:
if command == ["brew", "list", "bats-core"]:
return True
if command == ["brew", "list", "gh"]:
return True
if command == ["gh", "auth", "status"]:
return False
raise AssertionError(f"Unexpected command: {command}")

with mock.patch("base_dev.engine.run_check", side_effect=fake_run_check):
status, stdout, stderr = run_engine(["check", "--format", "json"])

findings = json.loads(stdout)
self.assertEqual(status, 1)
self.assertEqual(stderr, "")
self.assertIn(
{
"name": "gh-auth",
"ok": False,
"message": "GitHub CLI authentication is not ready.",
"fix": "gh auth login -h github.com",
},
findings,
)

@unittest.skipUnless(importlib.util.find_spec("click"), "Click is not installed")
def test_setup_dry_run_uses_homebrew_registry_definitions(self) -> None:
status, _stdout, stderr = run_engine(["setup", "--dry-run"])
Expand All @@ -64,6 +91,29 @@ def test_doctor_returns_number_of_failed_manifest_artifacts(self) -> None:
self.assertIn("error", stdout.getvalue())
self.assertIn("Fix: basectl setup --dev", stdout.getvalue())

def test_doctor_reports_invalid_github_auth(self) -> None:
manifest = engine.read_manifest(Path(__file__).resolve().parents[4] / "lib" / "base" / "dev_manifest.yaml")
definitions = engine.resolve_artifact_definitions(manifest.artifacts)

def fake_run_check(command: list[str]) -> bool:
if command == ["brew", "list", "bats-core"]:
return True
if command == ["brew", "list", "gh"]:
return True
if command == ["gh", "auth", "status"]:
return False
raise AssertionError(f"Unexpected command: {command}")

with mock.patch("base_dev.engine.run_check", side_effect=fake_run_check):
stdout = io.StringIO()
with redirect_stdout(stdout):
status = engine.doctor_dev_artifacts(manifest.artifacts, definitions, output_format="text")

self.assertEqual(status, 1)
self.assertIn("gh-auth", stdout.getvalue())
self.assertIn("GitHub CLI authentication is not ready.", stdout.getvalue())
self.assertIn("Fix: gh auth login -h github.com", stdout.getvalue())

def test_doctor_supports_json_output(self) -> None:
manifest = engine.read_manifest(Path(__file__).resolve().parents[4] / "lib" / "base" / "dev_manifest.yaml")
definitions = engine.resolve_artifact_definitions(manifest.artifacts)
Expand Down
Loading