1010
1111
1212def lint_for_dev_import_violations (codebase : Codebase , event : PullRequestLabeledEvent ):
13+ # Next.js codemod to detect imports of the react-dev-overlay module in production code
14+
1315 patch , commit_shas , modified_symbols = codebase .get_modified_symbols_in_pr (event .pull_request .number )
1416 modified_files = set (commit_shas .keys ())
17+ from codegen .sdk .core .statements .if_block_statement import IfBlockStatement
1518
16- DIR_NAME = " packages/next/src/client/components/react-dev-overlay"
19+ DIR_NAME = ' packages/next/src/client/components/react-dev-overlay'
1720 directory = codebase .get_directory (DIR_NAME )
1821
19- # Initialize a list to store all violations
2022 violations = []
2123
22- print ("modified_files" , modified_files )
23-
24- # Check if directory exists before proceeding
25- if directory is not None and hasattr (directory , "files" ):
26- for file in directory .files :
27- print ("checking file" , file .filepath )
28- for imp in file .inbound_imports :
29- print ("file" , imp .file .filepath )
30- print ("checking import" , imp .import_statement )
31- # Check if the import is from outside the directory and is in the modified files
32- if imp .file not in directory and imp .file .filepath in modified_files :
33- # Skip require statements
34- if "require" in imp .import_statement :
35- continue
36- violation = f"- Violation in `{ file .filepath } `: Importing from `{ imp .file .filepath } ` ([link]({ imp .github_url } ))"
37- violations .append (violation )
38- logger .info (f"Found violation: { violation } " )
39-
40- # Only create a PR comment if violations are found
41- if violations :
42- review_attention_message = "## Dev Import Violations Found\n \n "
43- review_attention_message += "The following files have imports that violate development overlay rules:\n \n "
44- review_attention_message += "\n " .join (violations )
45- review_attention_message += "\n \n Please ensure that development imports are not imported in production code."
46-
47- # Create PR comment with the formatted message
48- codebase ._op .create_pr_comment (event .pull_request .number , review_attention_message )
49-
50-
51- def review_with_codegen_agent (codebase : Codebase , event : PullRequestLabeledEvent ):
52- review_initial_message = "CodegenBot is starting to review the PR please wait..."
53- comment = codebase ._op .create_pr_comment (event .number , review_initial_message )
54- # Define tools first
55- pr_tools = [
56- GithubViewPRTool (codebase ),
57- GithubCreatePRCommentTool (codebase ),
58- GithubCreatePRReviewCommentTool (codebase ),
59- ]
60-
61- # Create agent with the defined tools
62- agent = CodeAgent (codebase = codebase , tools = pr_tools )
63-
64- # Using a prompt from SWE Bench
65- prompt = f"""
66- Hey CodegenBot!
67-
68- Here's a SWE task for you. Please Review this pull request!
69- { event .pull_request .url }
70- Do not terminate until have reviewed the pull request and are satisfied with your review.
71-
72- Review this Pull request like the señor ingenier you are
73- be explicit about the changes, produce a short summary, and point out possible improvements where pressent dont be self congratulatory stick to the facts
74- use the tools at your disposal to create propper pr reviews include code snippets if needed, and suggest improvements if feel its necesary
75- """
76- # Run the agent
77- agent .run (prompt )
78- comment .delete ()
24+
25+ false_operators = ["!=" , "!==" ]
26+ true_operators = ["===" , "==" ]
27+
28+
29+
30+ def is_valid_block_expression (if_block : IfBlockStatement ) -> bool :
31+ """Check if the if block has a valid environment check condition.
32+
33+ Valid conditions are:
34+ - process.env.NODE_ENV !== 'production'
35+ - process.env.NODE_ENV != 'production'
36+ - process.env.NODE_ENV === 'development'
37+ - process.env.NODE_ENV == 'development'
38+ """
39+ if not if_block .is_if_statement :
40+ return False
41+
42+ condition = if_block .condition
43+ # Get the operator without any whitespace
44+ operator = condition .operator [- 1 ].source
45+
46+ # Check for non-production conditions
47+ if operator in false_operators and condition .source == f"process.env.NODE_ENV { operator } 'production'" :
48+ return True
49+
50+ # Check for explicit development conditions
51+ if operator in true_operators and condition .source == f"process.env.NODE_ENV { operator } 'development'" :
52+ return True
53+
54+ return False
55+
56+
57+ def process_else_block_expression (else_block : IfBlockStatement ) -> bool :
58+ """Check if the else block is valid by checking its parent if block.
59+
60+ Valid when the parent if block checks for production environment:
61+ - if (process.env.NODE_ENV === 'production') { ... } else { <our import> }
62+ - if (process.env.NODE_ENV == 'production') { ... } else { <our import> }
63+ """
64+ if not else_block .is_else_statement :
65+ return False
66+
67+ main_if = else_block ._main_if_block
68+ if not main_if or not main_if .condition :
69+ return False
70+
71+ condition = main_if .condition
72+ operator = condition .operator [- 1 ].source
73+
74+ # Valid if the main if block checks for production
75+ return operator in true_operators and condition .source == f"process.env.NODE_ENV { operator } 'production'"
76+
77+
78+ for file in directory .files (recursive = True ):
79+ for imp in file .inbound_imports :
80+
81+ if imp .file .filepath not in modified_files :
82+ # skip if the import is not in the pull request's modified files
83+ continue
84+ # Skip if the import is from within the target directory
85+ if directory .dirpath in imp .file .filepath :
86+ # "✅ Valid import" if the import is within the target directory
87+ continue
88+
89+ parent_if_block = imp .parent_of_type (IfBlockStatement )
90+
91+ # Check if import is in a valid environment check block
92+ if_block_valid = parent_if_block and is_valid_block_expression (parent_if_block )
93+ else_block_valid = parent_if_block and process_else_block_expression (parent_if_block )
94+
95+ # Skip if the import is properly guarded by environment checks
96+ if if_block_valid or else_block_valid :
97+ # "✅ Valid import" these are guarded by non prod checks
98+ continue
99+
100+ # Report invalid imports that aren't properly guarded
101+ violation = f"- Violation in `{ file .filepath } `: Importing from `{ imp .file .filepath } ` ([link]({ imp .github_url } ))"
102+ violations .append (violation )
103+ logger .info (f"Found violation: { violation } " )
104+
105+
106+ if violations :
107+ # Comment on PR with violations
108+ review_attention_message = "## Dev Import Violations Found\n \n "
109+ review_attention_message += "The following files have imports that violate development overlay rules:\n \n "
110+ review_attention_message += "\n " .join (violations )
111+ review_attention_message += "\n \n Please ensure that development imports are not imported in production code."
112+
113+ # Create PR comment with the formatted message
114+ codebase ._op .create_pr_comment (event .pull_request .number , review_attention_message )
0 commit comments