1
- use anyhow:: { Context , Result } ;
1
+ use anyhow:: { Context as _ , Result } ;
2
2
use octocrab:: Octocrab ;
3
+ use serde_json:: Value ;
3
4
use std:: env;
5
+ use std:: fs;
6
+ use clap:: Parser ;
7
+
8
+ #[ derive( Parser , Debug ) ]
9
+ #[ command( name = "clippy-annotation-reporter" ) ]
10
+ #[ command( about = "Reports changes in clippy annotations for panic rules" ) ]
11
+ struct Args {
12
+ /// GitHub token for API access
13
+ #[ arg( long, env = "GITHUB_TOKEN" ) ]
14
+ token : String ,
15
+
16
+ /// Comma-separated list of panic-related Clippy rules to track
17
+ #[ arg( long, default_value = "unwrap_used,expect_used,todo,unimplemented,panic,unreachable" ) ]
18
+ rules : String ,
19
+
20
+ /// GitHub repository (owner/repo) - defaults to current repository
21
+ #[ arg( long) ]
22
+ repo : Option < String > ,
23
+
24
+ /// Pull request number - defaults to PR from event context
25
+ #[ arg( long) ]
26
+ pr : Option < u64 > ,
27
+ }
28
+
29
+ /// GitHub event context extracted from environment
30
+ struct GitHubContext {
31
+ repository : String ,
32
+ pr_number : u64 ,
33
+ event_name : String ,
34
+ }
35
+
36
+ impl GitHubContext {
37
+ /// Try to extract GitHub context from environment variables and event file
38
+ fn from_env ( ) -> Result < Self > {
39
+ // Get repository from env or args
40
+ let repository = env:: var ( "GITHUB_REPOSITORY" )
41
+ . context ( "GITHUB_REPOSITORY environment variable not set" ) ?;
42
+
43
+ // Get event name (pull_request, push, etc.)
44
+ let event_name = env:: var ( "GITHUB_EVENT_NAME" )
45
+ . context ( "GITHUB_EVENT_NAME environment variable not set" ) ?;
46
+
47
+ // For PR events, get PR number from event payload
48
+ let event_path = env:: var ( "GITHUB_EVENT_PATH" )
49
+ . context ( "GITHUB_EVENT_PATH environment variable not set" ) ?;
50
+
51
+ println ! ( "Event name: {}" , event_name) ;
52
+ println ! ( "Event path: {}" , event_path) ;
53
+
54
+ let event_data = fs:: read_to_string ( event_path)
55
+ . context ( "Failed to read GitHub event file" ) ?;
56
+
57
+ let event_json: Value = serde_json:: from_str ( & event_data)
58
+ . context ( "Failed to parse GitHub event JSON" ) ?;
59
+
60
+ // Print the event JSON for debugging
61
+ println ! ( "Event JSON structure (top level): {:?}" ,
62
+ event_json. as_object( ) . map( |o| o. keys( ) . collect:: <Vec <_>>( ) ) ) ;
63
+
64
+ // Extract PR number using different strategies based on event type
65
+ let pr_number = match event_name. as_str ( ) {
66
+ "pull_request" | "pull_request_target" => {
67
+ event_json[ "pull_request" ] [ "number" ] . as_u64 ( )
68
+ . context ( "Could not find pull_request.number in event data" ) ?
69
+ } ,
70
+ "issue_comment" => {
71
+ event_json[ "issue" ] [ "number" ] . as_u64 ( )
72
+ . context ( "Could not find issue.number in event data" ) ?
73
+ } ,
74
+ _ => {
75
+ // For other events, PR number must be provided as an argument
76
+ 0 // Will be overridden by required argument check below
77
+ }
78
+ } ;
79
+
80
+ Ok ( GitHubContext {
81
+ repository,
82
+ pr_number,
83
+ event_name,
84
+ } )
85
+ }
86
+ }
4
87
5
88
#[ tokio:: main]
6
89
async fn main ( ) -> Result < ( ) > {
7
- println ! ( "Hello World from clippy-annotation-checker!" ) ;
8
- println ! ( "Action is running successfully!" ) ;
90
+ // Initialize logger
91
+ env_logger :: init ( ) ;
9
92
10
- // Get required environment variables
11
- let github_token = env:: var ( "GITHUB_TOKEN" )
12
- . context ( "GITHUB_TOKEN environment variable not set" ) ?;
93
+ // Parse command line arguments
94
+ let args = Args :: parse ( ) ;
13
95
14
- let github_repository = env:: var ( "GITHUB_REPOSITORY" )
15
- . context ( "GITHUB_REPOSITORY environment variable not set" ) ?;
96
+ println ! ( "Clippy Annotation Reporter starting..." ) ;
16
97
17
- let event_path = env :: var ( "GITHUB_EVENT_PATH" )
18
- . context ( "GITHUB_EVENT_PATH environment variable not set" ) ?;
98
+ // Try to get GitHub context from environment
99
+ let github_ctx = GitHubContext :: from_env ( ) ?;
19
100
20
- // Parse event data to get PR number
21
- let event_data = std:: fs:: read_to_string ( event_path)
22
- . context ( "Failed to read event file" ) ?;
101
+ // Use provided values from args if available, otherwise use context
102
+ let repository = args. repo . unwrap_or ( github_ctx. repository ) ;
103
+ let pr_number = match args. pr {
104
+ Some ( pr) => pr,
105
+ None => {
106
+ if github_ctx. pr_number == 0 {
107
+ anyhow:: bail!( "No PR number found in event context. Please provide --pr argument." ) ;
108
+ }
109
+ github_ctx. pr_number
110
+ }
111
+ } ;
23
112
24
- let event_json: serde_json:: Value = serde_json:: from_str ( & event_data)
25
- . context ( "Failed to parse event JSON" ) ?;
113
+ println ! ( "Repository: {}" , repository) ;
114
+ println ! ( "PR Number: {}" , pr_number) ;
115
+ println ! ( "Event Type: {}" , github_ctx. event_name) ;
116
+ println ! ( "Checking for rules: {}" , args. rules) ;
26
117
27
- let pr_number = event_json[ "pull_request" ] [ "number" ]
28
- . as_u64 ( )
29
- . context ( "Could not find PR number in event data" ) ?;
118
+ // Initialize GitHub API client with token
119
+ let octocrab = Octocrab :: builder ( )
120
+ . personal_token ( args. token )
121
+ . build ( )
122
+ . context ( "Failed to build GitHub API client" ) ?;
30
123
31
124
// Split repository into owner and name
32
- let repo_parts: Vec < & str > = github_repository . split ( '/' ) . collect ( ) ;
125
+ let repo_parts: Vec < & str > = repository . split ( '/' ) . collect ( ) ;
33
126
if repo_parts. len ( ) != 2 {
34
- anyhow:: bail!( "Invalid repository format: {} " , github_repository ) ;
127
+ anyhow:: bail!( "Invalid repository format. Expected 'owner/repo', got '{}' " , repository ) ;
35
128
}
36
-
37
129
let owner = repo_parts[ 0 ] ;
38
130
let repo = repo_parts[ 1 ] ;
39
131
40
- println ! ( "Posting Hello World comment to PR #{} in {}/{}" , pr_number, owner, repo) ;
132
+ // This is just a "Hello World" example that posts a comment to verify everything works
133
+ println ! ( "Posting a test comment to PR #{} in {}/{}" , pr_number, owner, repo) ;
41
134
42
- // Initialize GitHub client
43
- let octocrab = Octocrab :: builder ( )
44
- . personal_token ( github_token)
45
- . build ( )
46
- . context ( "Failed to build GitHub client" ) ?;
47
-
48
- // Post a simple comment
49
135
octocrab
50
136
. issues ( owner, repo)
51
- . create_comment ( pr_number, "## Hello World from clippy-annotation-checker!\n \n This action is running successfully and can post comments to PRs." )
137
+ . create_comment (
138
+ pr_number,
139
+ format ! ( "## Clippy Annotation Reporter Test\n \n Successfully connected to PR #{} in {}/{}.\n \n Will scan for the following rules: `{}`" ,
140
+ pr_number, owner, repo, args. rules)
141
+ )
52
142
. await
53
- . context ( "Failed to post comment" ) ?;
143
+ . context ( "Failed to post comment to PR " ) ?;
54
144
55
145
println ! ( "Comment posted successfully!" ) ;
56
146
147
+ // TODO: Add actual clippy annotation checking logic here
148
+
57
149
Ok ( ( ) )
58
- }
150
+ }
0 commit comments