Coverage for scripts / list_pending_approvals.py: 19%

68 statements  

« prev     ^ index     » next       coverage.py v7.13.0, created at 2025-12-25 18:08 -0500

1#!/usr/bin/env python3 

2""" 

3List all pending approvals for current user (agent queue view). 

4 

5This script shows a queue of all pending approvals across requests where 

6the current user is an approver, providing an agent-level view of their 

7approval workload. 

8""" 

9 

10import sys 

11import argparse 

12import json 

13from pathlib import Path 

14from datetime import datetime 

15 

16# Add shared lib to path 

17sys.path.insert(0, str(Path(__file__).parent.parent.parent.parent / 'shared' / 'scripts' / 'lib')) 

18 

19from config_manager import get_jira_client 

20from error_handler import handle_errors 

21 

22 

23def get_jira_client(profile=None): 

24 """Get JIRA client (overridable for testing).""" 

25 from config_manager import get_jira_client as _get_client 

26 return _get_client(profile) 

27 

28 

29def format_pending_approvals_table(approvals: list, user_email: str = None) -> None: 

30 """Format pending approvals as table.""" 

31 if not approvals: 

32 print("No pending approvals found.") 

33 return 

34 

35 user_str = f" for {user_email}" if user_email else "" 

36 print(f"\nPending Approvals{user_str} ({len(approvals)} total):\n") 

37 

38 print(f"{'Request':<12} {'Summary':<35} {'Approval ID':<12} {'Approval Name':<25} {'Created':<20} {'Action'}") 

39 print("─" * 140) 

40 

41 for approval in approvals: 

42 request_key = approval.get('requestKey', 'Unknown') 

43 summary = approval.get('summary', '')[:34] 

44 approval_id = approval.get('approvalId', 'Unknown') 

45 approval_name = approval.get('approvalName', 'Unknown')[:24] 

46 created = approval.get('created', '') 

47 

48 # Format date 

49 try: 

50 created_dt = datetime.fromisoformat(created.replace('Z', '+00:00')) 

51 created_str = created_dt.strftime('%Y-%m-%d %H:%M') 

52 except: 

53 created_str = created[:16] if created else 'Unknown' 

54 

55 action = "Approve | Decline" 

56 

57 print(f"{request_key:<12} {summary:<35} {approval_id:<12} {approval_name:<25} {created_str:<20} {action}") 

58 

59 print("\nTo approve/decline:") 

60 print(" python approve_request.py <REQUEST-KEY> --approval-id <APPROVAL-ID>") 

61 print(" python decline_request.py <REQUEST-KEY> --approval-id <APPROVAL-ID>") 

62 

63 

64@handle_errors 

65def main(args=None): 

66 """Main function.""" 

67 parser = argparse.ArgumentParser( 

68 description='List all pending approvals (agent queue view)', 

69 formatter_class=argparse.RawDescriptionHelpFormatter, 

70 epilog=""" 

71Examples: 

72 # All pending approvals for current user 

73 %(prog)s 

74 

75 # Filter by project 

76 %(prog)s --project SD 

77 

78 # For specific user (admin only) 

79 %(prog)s --user alice@company.com 

80 

81 # JSON output 

82 %(prog)s --output json 

83 """ 

84 ) 

85 

86 parser.add_argument('--project', 

87 help='Filter by project key') 

88 parser.add_argument('--user', 

89 help='Show approvals for specific user (admin only)') 

90 parser.add_argument('--output', choices=['text', 'json'], default='text', 

91 help='Output format (default: text)') 

92 parser.add_argument('--profile', 

93 help='JIRA profile to use') 

94 

95 parsed_args = parser.parse_args(args) 

96 

97 # Get JIRA client 

98 jira = get_jira_client(parsed_args.profile) 

99 

100 # Build JQL to find requests with pending approvals 

101 jql_parts = ['status != Resolved'] 

102 

103 if parsed_args.project: 

104 jql_parts.append(f'project = {parsed_args.project}') 

105 

106 # Note: User filtering would require additional JQL or post-filtering 

107 # For now, we get all pending approvals and filter by canAnswerApproval 

108 

109 jql = ' AND '.join(jql_parts) 

110 

111 # Search for requests 

112 search_result = jira.search_issues(jql, max_results=100) 

113 

114 pending_approvals = [] 

115 

116 # For each request, check for pending approvals 

117 for issue in search_result.get('issues', []): 

118 issue_key = issue['key'] 

119 summary = issue.get('fields', {}).get('summary', '') 

120 

121 try: 

122 approvals_resp = jira.get_request_approvals(issue_key) 

123 approvals = approvals_resp.get('values', []) 

124 

125 for approval in approvals: 

126 if approval.get('finalDecision') == 'pending': 

127 # Check if current user can answer this approval 

128 if approval.get('canAnswerApproval', False): 

129 pending_approvals.append({ 

130 'requestKey': issue_key, 

131 'approvalId': approval.get('id'), 

132 'approvalName': approval.get('name'), 

133 'created': approval.get('createdDate'), 

134 'summary': summary 

135 }) 

136 except Exception: 

137 # Skip requests where we can't get approvals (e.g., permissions) 

138 continue 

139 

140 # Output 

141 if parsed_args.output == 'json': 

142 print(json.dumps(pending_approvals, indent=2)) 

143 else: 

144 format_pending_approvals_table(pending_approvals, parsed_args.user) 

145 

146 return 0 

147 

148 

149if __name__ == '__main__': 

150 sys.exit(main())