Coverage for src / gh_secrets_and_vars_async / status.py: 93%

55 statements  

« prev     ^ index     » next       coverage.py v7.13.5, created at 2026-04-16 17:56 +0000

1"""Informational status dump for a GitHub repository. 

2 

3``ai-gh status`` is intentionally opinion-free: it reports current 

4auto-merge state, any non-default repo configuration, all current 

5rulesets (including org-inherited ones), and whether a pipeline file 

6exists on disk. It no longer compares anything to an in-tool template. 

7""" 

8 

9from pathlib import Path 

10 

11import click 

12from rich import print 

13from rich.table import Table 

14 

15from .common import get_github_repo, load_env_config 

16from .config import get_auto_merge_status, has_dev_branch 

17from .rulesets import display_rulesets, get_rulesets 

18 

19# GitHub repo default values. A setting is reported in the "non-default" 

20# section only if its current value differs from what's listed here. 

21REPO_SETTING_DEFAULTS: dict[str, object] = { 

22 "allow_merge_commit": True, 

23 "allow_squash_merge": True, 

24 "allow_rebase_merge": True, 

25 "allow_auto_merge": False, 

26 "delete_branch_on_merge": False, 

27 "allow_update_branch": False, 

28 "web_commit_signoff_required": False, 

29 "has_issues": True, 

30 "has_projects": True, 

31 "has_wiki": True, 

32 "merge_commit_title": "MERGE_MESSAGE", 

33 "merge_commit_message": "PR_TITLE", 

34 "squash_merge_commit_title": "COMMIT_OR_PR_TITLE", 

35 "squash_merge_commit_message": "COMMIT_MESSAGES", 

36} 

37 

38 

39def _get_repo_attr(repo: object, name: str) -> object | None: 

40 """Read an attribute from a PyGithub Repository, returning None on failure.""" 

41 try: 

42 value: object = getattr(repo, name) 

43 except Exception: 

44 return None 

45 return value 

46 

47 

48def check_auto_merge(repo) -> str: 

49 """Return a human-readable line describing the auto-merge state.""" 

50 if get_auto_merge_status(repo): 

51 return "[green]enabled[/green]" 

52 return "[red]disabled[/red]" 

53 

54 

55def check_repo_settings(repo) -> list[tuple[str, str]]: 

56 """Return (setting, current_value) rows for any non-default repo setting. 

57 

58 Skips settings that match GitHub's defaults. ``allow_auto_merge`` is 

59 intentionally reported here too even though it's also shown above, so 

60 users see the full merge policy in one table. 

61 """ 

62 rows: list[tuple[str, str]] = [] 

63 for name, default in REPO_SETTING_DEFAULTS.items(): 

64 value = _get_repo_attr(repo, name) 

65 if value is None: 

66 continue 

67 if value != default: 

68 rows.append((name, str(value))) 

69 

70 if has_dev_branch(repo): 

71 rows.append(("dev branch", "present")) 

72 

73 return rows 

74 

75 

76def check_pipeline_file() -> str: 

77 """Return a human-readable line describing the pipeline file state.""" 

78 if Path(".github/workflows/pipeline.yaml").exists(): 

79 return "[green].github/workflows/pipeline.yaml exists[/green]" 

80 return ( 

81 "[yellow].github/workflows/pipeline.yaml not found " 

82 "(run /ai-standardize-pipeline in augint-shell)[/yellow]" 

83 ) 

84 

85 

86@click.command("status") 

87@click.option("--verbose", "-v", is_flag=True, help="Show additional detail.") 

88def status_command(verbose: bool) -> None: 

89 """Show repository configuration: auto-merge, non-default settings, rulesets, pipeline file.""" 

90 gh_repo, gh_account, _ = load_env_config() 

91 if not gh_repo or not gh_account: 

92 raise click.ClickException("GH_REPO and GH_ACCOUNT must be set in .env or environment.") 

93 

94 repo = get_github_repo(gh_account, gh_repo) 

95 

96 print(f"\n[bold]Status: {gh_account}/{gh_repo}[/bold]\n") 

97 

98 # 1. Auto-merge 

99 print(f"[bold]Auto-merge:[/bold] {check_auto_merge(repo)}") 

100 

101 # 2. Non-default repo configuration 

102 non_default = check_repo_settings(repo) 

103 if non_default: 

104 table = Table(show_header=True, header_style="bold", title="Non-default settings") 

105 table.add_column("Setting") 

106 table.add_column("Value") 

107 for name, value in non_default: 

108 table.add_row(name, value) 

109 print(table) 

110 else: 

111 print("[dim]All repo settings are at GitHub defaults.[/dim]") 

112 

113 # 3. Rulesets 

114 print("\n[bold]Rulesets[/bold]") 

115 rulesets = get_rulesets(repo) 

116 display_rulesets(rulesets) 

117 

118 # 4. Pipeline file 

119 print(f"\n[bold]Pipeline:[/bold] {check_pipeline_file()}")