Coverage for src / documint_mcp / check_runs.py: 0%

30 statements  

« prev     ^ index     » next       coverage.py v7.13.5, created at 2026-03-30 22:30 -0400

1""" 

2GitHub Check Runs API integration for Documint. 

3Posts non-blocking drift annotations on PRs (neutral conclusion — the Codecov model). 

4""" 

5 

6from __future__ import annotations 

7 

8from dataclasses import dataclass, field 

9 

10from .github import _github_request, get_installation_access_token 

11 

12 

13@dataclass 

14class DriftAnnotation: 

15 path: str # "docs/API_REFERENCE.md" 

16 start_line: int # line in the doc that mentions the changed symbol 

17 end_line: int 

18 annotation_level: str # "warning" (non-blocking) 

19 message: str # "add_memory() gained parameter session_id: str — review §3.2" 

20 title: str # "Documint: Documentation drift detected" 

21 raw_details: str = field(default="") # full diff context (optional) 

22 

23 

24class CheckRunManager: 

25 """ 

26 Manages GitHub Check Runs for drift detection. 

27 

28 Flow: 

29 1. create_check_run() — called when PR is opened (status=in_progress) 

30 2. complete_check_run() — called when drift analysis finishes (conclusion=neutral) 

31 

32 The existing GitHub client in github.py uses synchronous httpx calls via the 

33 module-level _github_request() helper and get_installation_access_token(). 

34 This class wraps those helpers directly. 

35 """ 

36 

37 def create_check_run( 

38 self, 

39 owner: str, 

40 repo: str, 

41 head_sha: str, 

42 installation_id: str, 

43 ) -> int: 

44 """ 

45 Create a check run in 'in_progress' state. 

46 Returns the check run ID. 

47 """ 

48 token = get_installation_access_token(installation_id) 

49 resp = _github_request( 

50 "POST", 

51 f"/repos/{owner}/{repo}/check-runs", 

52 token=token, 

53 json_body={ 

54 "name": "Documint", 

55 "head_sha": head_sha, 

56 "status": "in_progress", 

57 "output": { 

58 "title": "Checking documentation drift...", 

59 "summary": "Documint is analyzing your changes for documentation drift.", 

60 }, 

61 }, 

62 ) 

63 return int(resp.json()["id"]) 

64 

65 def complete_check_run( 

66 self, 

67 owner: str, 

68 repo: str, 

69 check_run_id: int, 

70 installation_id: str, 

71 findings_count: int, 

72 annotations: list[DriftAnnotation], 

73 ) -> None: 

74 """ 

75 Update check run with results. 

76 

77 Always uses conclusion="neutral" (non-blocking — informational only). 

78 Annotation level is "warning" (not "failure"). 

79 """ 

80 if findings_count == 0: 

81 title = "No documentation drift detected" 

82 summary = "All documentation artifacts are synchronized with their source files." 

83 else: 

84 plural = "s" if findings_count > 1 else "" 

85 title = f"{findings_count} documentation artifact{plural} may be outdated" 

86 summary = ( 

87 f"Documint detected structural changes in {findings_count} artifact definition(s). " 

88 "Review and update documentation to keep your agent context accurate.\n\n" 

89 "This check is informational and does not block merging." 

90 ) 

91 

92 # GitHub API limits: max 50 annotations per update 

93 annotation_payload = [ 

94 { 

95 "path": a.path, 

96 "start_line": a.start_line, 

97 "end_line": a.end_line, 

98 "annotation_level": a.annotation_level, 

99 "message": a.message, 

100 "title": a.title, 

101 "raw_details": a.raw_details, 

102 } 

103 for a in annotations[:50] 

104 ] 

105 

106 token = get_installation_access_token(installation_id) 

107 _github_request( 

108 "PATCH", 

109 f"/repos/{owner}/{repo}/check-runs/{check_run_id}", 

110 token=token, 

111 json_body={ 

112 "status": "completed", 

113 "conclusion": "neutral", 

114 "output": { 

115 "title": title, 

116 "summary": summary, 

117 "annotations": annotation_payload, 

118 }, 

119 }, 

120 ) 

121 

122 def fail_check_run( 

123 self, 

124 owner: str, 

125 repo: str, 

126 check_run_id: int, 

127 installation_id: str, 

128 error_message: str, 

129 ) -> None: 

130 """Mark check run as failed (internal error, not drift).""" 

131 token = get_installation_access_token(installation_id) 

132 _github_request( 

133 "PATCH", 

134 f"/repos/{owner}/{repo}/check-runs/{check_run_id}", 

135 token=token, 

136 json_body={ 

137 "status": "completed", 

138 "conclusion": "neutral", # still neutral — don't block for our own errors 

139 "output": { 

140 "title": "Documint check encountered an error", 

141 "summary": f"Internal error during drift analysis: {error_message}", 

142 }, 

143 }, 

144 )