code_healer 0.1.5 โ†’ 0.1.7

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 053ae42e7bf5fe56e20fefb00f6a5474bf2e4e74622738f81b45073bfe735da3
4
- data.tar.gz: e3349ed04f2cb27fec077f0003f5bde4b63b9a9a220158bbfb32b864ea1af75b
3
+ metadata.gz: fb4a7ded404d0efca6e6e111b0186cc2bdeaef8a6eaf4041fd9799fcc447d044
4
+ data.tar.gz: 95f4317a52fa36bc1aae2923d497a01c282486de0680548a5e80ff1f15ff6468
5
5
  SHA512:
6
- metadata.gz: 2bac061a4947215ba717645dccf034ebf1e130eb98f58861d4f88ad8249d17cd83380853b965a1b7f539a5c6af9bbeefd795eb45b521023f447ac99cc222f8e1
7
- data.tar.gz: da855be2022f1f6e1cd67dd48ea8a42985444b20895560fd34fe506734d2837fde99a374411c07f10622657b2acd5fc4ed329a5f04990aea6b30575ef0f3b5c2
6
+ metadata.gz: ad4af34d619b3d1361a61b5dd5e7a285bb9cdc399b72d200209a84ce565f2e7740917878684e4b094254ba3fbc858765e4dc2af2a3d425dd8d343a71e180477e
7
+ data.tar.gz: 89b963d38d992791a738ff3ab91716939e39a1e8b84d056574bc6ffae504d66e6c192306ba28f5671efeec54967fa0eefca044e17121538055875a91875f4dbd
data/CHANGELOG.md CHANGED
@@ -5,7 +5,21 @@ All notable changes to this project will be documented in this file.
5
5
  The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
6
6
  and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
7
7
 
8
- ## [0.1.5] - 2025-01-14
8
+ ## [0.1.7] - 2025-01-14
9
+
10
+ ### Fixed
11
+ - **Git operations in isolated healing workspace** - Preserved .git directory during cloning for proper Git operations
12
+ - **Branch creation and commit operations** now work correctly in the isolated workspace
13
+ - **Workspace cleanup** properly removes .git directory to prevent conflicts
14
+
15
+ ## [0.1.6] - 2025-01-14
16
+
17
+ ### Added
18
+ - **Code heal directory permission validation** during interactive setup
19
+ - **Repository access testing** to ensure the directory can clone and push to the target repo
20
+ - **Write permission verification** for the code heal directory
21
+ - **Automatic directory creation** if it doesn't exist
22
+ - **Comprehensive error messages** with troubleshooting tips for permission issues
9
23
 
10
24
  ### Fixed
11
25
  - **Duplicate HealingJob class definition** that was preventing isolated healing workspace system from working
@@ -161,6 +161,13 @@ module CodeHealer
161
161
 
162
162
  return unless Dir.exist?(workspace_path)
163
163
 
164
+ # Remove .git directory first to avoid conflicts
165
+ git_dir = File.join(workspace_path, '.git')
166
+ if Dir.exist?(git_dir)
167
+ puts "๐Ÿงน [WORKSPACE] Removing .git directory to prevent conflicts..."
168
+ FileUtils.rm_rf(git_dir)
169
+ end
170
+
164
171
  puts "๐Ÿงน [WORKSPACE] Removing workspace directory..."
165
172
  FileUtils.rm_rf(workspace_path)
166
173
  puts "๐Ÿงน [WORKSPACE] Workspace cleanup completed"
@@ -207,10 +214,9 @@ module CodeHealer
207
214
  puts "๐ŸŒฟ [WORKSPACE] Clone result: #{result ? 'SUCCESS' : 'FAILED'}"
208
215
 
209
216
  if result
210
- puts "๐ŸŒฟ [WORKSPACE] Removing .git to avoid conflicts..."
211
- # Remove .git to avoid conflicts
212
- FileUtils.rm_rf(File.join(workspace_path, '.git'))
213
- puts "๐ŸŒฟ [WORKSPACE] .git removed successfully"
217
+ puts "๐ŸŒฟ [WORKSPACE] Git repository preserved for healing operations"
218
+ # Keep .git for Git operations during healing
219
+ # We'll clean it up later in cleanup_workspace
214
220
  else
215
221
  puts "๐ŸŒฟ [WORKSPACE] Clone failed, checking workspace..."
216
222
  puts "๐ŸŒฟ [WORKSPACE] Workspace exists: #{Dir.exist?(workspace_path)}"
@@ -237,6 +243,7 @@ module CodeHealer
237
243
  checkout_result = system("git checkout #{current_branch}")
238
244
  puts "๐ŸŒฟ [WORKSPACE] Checkout result: #{checkout_result ? 'SUCCESS' : 'FAILED'}"
239
245
  end
246
+ puts "๐ŸŒฟ [WORKSPACE] Git repository preserved for healing operations"
240
247
  else
241
248
  puts "๐ŸŒฟ [WORKSPACE] Full repo clone failed"
242
249
  end
@@ -7,6 +7,7 @@
7
7
  require 'fileutils'
8
8
  require 'yaml'
9
9
  require 'optparse'
10
+ require 'octokit'
10
11
 
11
12
  # Parse command line options
12
13
  options = {}
@@ -88,6 +89,109 @@ def read_file_content(file_path)
88
89
  File.read(file_path) if file_exists?(file_path)
89
90
  end
90
91
 
92
+ def normalize_repository_url(repository_input, github_token = nil)
93
+ return nil if repository_input.nil?
94
+ input = repository_input.strip
95
+ return nil if input.empty?
96
+
97
+ # If it's already a URL, return as-is
98
+ if input.include?('://')
99
+ return input
100
+ end
101
+
102
+ # Build HTTPS URL from owner/repo
103
+ base = "https://github.com/#{input}.git"
104
+ return base if github_token.nil? || github_token.strip.empty?
105
+
106
+ # Embed token for validation clone only (do not log the token)
107
+ "https://#{github_token}@github.com/#{input}.git"
108
+ end
109
+
110
+ # Permission validation method
111
+ def validate_code_heal_directory_permissions(directory_path, repository_url, github_token = nil)
112
+ puts " ๐Ÿ“ Checking directory: #{directory_path}"
113
+
114
+ # Check if directory exists or can be created
115
+ begin
116
+ if Dir.exist?(directory_path)
117
+ puts " โœ… Directory exists"
118
+ else
119
+ puts " ๐Ÿ”จ Creating directory..."
120
+ Dir.mkdir(directory_path)
121
+ puts " โœ… Directory created successfully"
122
+ end
123
+ rescue => e
124
+ puts " โŒ Cannot create directory: #{e.message}"
125
+ return false
126
+ end
127
+
128
+ # Check write permissions
129
+ begin
130
+ test_file = File.join(directory_path, '.permission_test')
131
+ File.write(test_file, 'test')
132
+ File.delete(test_file)
133
+ puts " โœ… Write permissions verified"
134
+ rescue => e
135
+ puts " โŒ Write permission failed: #{e.message}"
136
+ return false
137
+ end
138
+
139
+ # If we have a token and a repo, verify push permissions via GitHub API
140
+ if github_token && !github_token.strip.empty? && repository_url && !repository_url.strip.empty?
141
+ begin
142
+ client = Octokit::Client.new(access_token: github_token)
143
+ repo_full_name = if repository_url.include?('github.com')
144
+ path = repository_url.split('github.com/').last.to_s
145
+ path.sub(/\.git\z/, '')
146
+ else
147
+ repository_url
148
+ end
149
+ repo = client.repository(repo_full_name)
150
+ perms = (repo.respond_to?(:permissions) ? repo.permissions : repo[:permissions]) || {}
151
+ can_push = perms[:push] == true || perms['push'] == true
152
+ if can_push
153
+ puts " โœ… GitHub token has push permission to #{repo_full_name}"
154
+ else
155
+ puts " โš ๏ธ GitHub token does not have push permission to #{repo_full_name}"
156
+ end
157
+ rescue => e
158
+ puts " โš ๏ธ Could not verify push permission via GitHub API: #{e.message}"
159
+ end
160
+ else
161
+ puts " โš ๏ธ Skipping GitHub push-permission check (missing token or repository)"
162
+ end
163
+
164
+ # Check if we can clone the repository (read access)
165
+ puts " ๐Ÿ” Testing repository access..."
166
+ begin
167
+ require 'git'
168
+ require 'fileutils'
169
+
170
+ # Create a temporary test directory
171
+ test_dir = File.join(directory_path, 'test_clone_' + Time.now.to_i.to_s)
172
+
173
+ # Try to clone the repository
174
+ puts " ๐Ÿ“ฅ Attempting to clone repository..."
175
+ # Avoid printing token in logs
176
+ safe_url = repository_url.to_s.gsub(/:\/\/[A-Za-z0-9_\-]+@/, '://***@')
177
+ # Perform clone
178
+ Git.clone(repository_url, test_dir, depth: 1)
179
+
180
+ # Clean up test clone
181
+ FileUtils.rm_rf(test_dir)
182
+ puts " โœ… Repository access verified (#{safe_url})"
183
+
184
+ return true
185
+ rescue => e
186
+ puts " โŒ Repository access failed: #{e.message}"
187
+ puts " ๐Ÿ’ก Make sure:"
188
+ puts " - Your GitHub token has repo access"
189
+ puts " - The repository URL is correct (e.g., https://github.com/owner/repo.git or owner/repo)"
190
+ puts " - You have network access to GitHub"
191
+ return false
192
+ end
193
+ end
194
+
91
195
  # Main setup logic
92
196
  puts "๐Ÿฅ Welcome to CodeHealer Setup! ๐Ÿš€"
93
197
  puts "=" * 50
@@ -119,7 +223,7 @@ else
119
223
  puts "๐Ÿ“ Would add 'code_healer' to Gemfile"
120
224
  else
121
225
  File.write(gemfile_path, new_gemfile_content)
122
- puts "โœ… Added 'code_healer' to Gemfile"
226
+ puts "โœ… Added 'code_healer' to Gemfile"
123
227
  end
124
228
  end
125
229
 
@@ -145,7 +249,8 @@ puts "Get one at: https://github.com/settings/tokens"
145
249
  puts
146
250
 
147
251
  github_token = ask_for_input("Enter your GitHub personal access token (or press Enter to skip for now):")
148
- github_repo = ask_for_input("Enter your GitHub repository (username/repo):")
252
+ github_repo = ask_for_input("Enter your GitHub repository (username/repo or full URL):")
253
+ github_repo_url = normalize_repository_url(github_repo, github_token)
149
254
 
150
255
  # Git Branch Configuration
151
256
  puts
@@ -161,6 +266,29 @@ puts "CodeHealer will clone your current branch here before making fixes."
161
266
  puts
162
267
 
163
268
  code_heal_directory = ask_for_input("Enter code heal directory path (default: /tmp/code_healer_workspaces):", default: "/tmp/code_healer_workspaces")
269
+
270
+ # Validate code heal directory permissions
271
+ puts "๐Ÿ” Validating code heal directory permissions..."
272
+ if github_repo_url && !github_repo_url.strip.empty?
273
+ if validate_code_heal_directory_permissions(code_heal_directory, github_repo_url, github_token)
274
+ puts "โœ… Code heal directory permissions validated successfully!"
275
+ else
276
+ puts "โŒ Code heal directory permission validation failed!"
277
+ puts "Please ensure the directory has proper write permissions and can access the repository."
278
+ code_heal_directory = ask_for_input("Enter a different code heal directory path:", default: "/tmp/code_healer_workspaces")
279
+
280
+ # Retry validation
281
+ if validate_code_heal_directory_permissions(code_heal_directory, github_repo_url, github_token)
282
+ puts "โœ… Code heal directory permissions validated successfully!"
283
+ else
284
+ puts "โš ๏ธ Permission validation failed again. You may need to fix permissions manually."
285
+ end
286
+ end
287
+ else
288
+ puts "โš ๏ธ Skipping repository access validation (no repository URL provided)"
289
+ puts " Directory permissions will be validated when you run the actual setup"
290
+ end
291
+
164
292
  auto_cleanup = ask_for_yes_no("Automatically clean up healing workspaces after use?", default: true)
165
293
  cleanup_after_hours = ask_for_input("Clean up workspaces after how many hours? (default: 24):", default: "24")
166
294
 
@@ -198,12 +326,12 @@ puts "๐Ÿ“ Step 3: Creating Configuration Files"
198
326
  puts
199
327
 
200
328
  # Create actual .env file (will be ignored by git)
201
- env_content = <<~ENV
329
+ env_content = <<~ENV
202
330
  # CodeHealer Configuration
203
- # OpenAI Configuration
331
+ # OpenAI Configuration
204
332
  OPENAI_API_KEY=#{openai_key}
205
-
206
- # GitHub Configuration
333
+
334
+ # GitHub Configuration
207
335
  GITHUB_TOKEN=#{github_token}
208
336
  GITHUB_REPOSITORY=#{github_repo}
209
337
 
@@ -214,81 +342,81 @@ ENV
214
342
  create_file_with_content('.env', env_content, dry_run: options[:dry_run])
215
343
 
216
344
  # Create code_healer.yml
217
- config_content = <<~YAML
218
- # CodeHealer Configuration
219
- enabled: true
220
-
345
+ config_content = <<~YAML
346
+ # CodeHealer Configuration
347
+ enabled: true
348
+
221
349
  # Allowed classes for healing (customize as needed)
222
- allowed_classes:
223
- - User
224
- - Order
225
- - PaymentProcessor
350
+ allowed_classes:
351
+ - User
352
+ - Order
353
+ - PaymentProcessor
226
354
  - OrderProcessor
227
-
355
+
228
356
  # Excluded classes (never touch these)
229
- excluded_classes:
230
- - ApplicationController
231
- - ApplicationRecord
232
- - ApplicationJob
233
- - ApplicationMailer
357
+ excluded_classes:
358
+ - ApplicationController
359
+ - ApplicationRecord
360
+ - ApplicationJob
361
+ - ApplicationMailer
234
362
  - ApplicationHelper
235
-
236
- # Allowed error types for healing
237
- allowed_error_types:
363
+
364
+ # Allowed error types for healing
365
+ allowed_error_types:
238
366
  - ZeroDivisionError
239
367
  - NoMethodError
240
- - ArgumentError
368
+ - ArgumentError
241
369
  - TypeError
242
- - NameError
243
- - ValidationError
244
-
370
+ - NameError
371
+ - ValidationError
372
+
245
373
  # Evolution Strategy Configuration
246
- evolution_strategy:
374
+ evolution_strategy:
247
375
  method: #{evolution_method} # Options: api, claude_code_terminal, hybrid
248
376
  fallback_to_api: #{fallback_to_api} # If Claude Code fails, fall back to API
249
-
377
+
250
378
  # Claude Code Terminal Configuration
251
- claude_code:
379
+ claude_code:
252
380
  enabled: #{evolution_method == 'claude_code_terminal' || evolution_method == 'hybrid'}
253
381
  timeout: 300 # Timeout in seconds
254
- max_file_changes: 10
255
- include_tests: true
382
+ max_file_changes: 10
383
+ include_tests: true
256
384
  command_template: "claude --print '{prompt}' --output-format text --permission-mode acceptEdits --allowedTools Edit"
257
- business_context_sources:
258
- - "config/business_rules.yml"
259
- - "docs/business_logic.md"
260
- - "spec/business_context_specs.rb"
261
-
385
+ business_context_sources:
386
+ - "config/business_rules.yml"
387
+ - "docs/business_logic.md"
388
+ - "spec/business_context_specs.rb"
389
+
262
390
  # Business Context Configuration
263
- business_context:
264
- enabled: true
391
+ business_context:
392
+ enabled: true
265
393
  sources:
266
394
  - "docs/business_rules.md"
267
-
268
- # OpenAI API configuration
269
- api:
270
- provider: openai
395
+
396
+ # OpenAI API configuration
397
+ api:
398
+ provider: openai
271
399
  model: gpt-4
272
- max_tokens: 2000
273
- temperature: 0.1
274
-
275
- # Git operations
276
- git:
277
- auto_commit: true
278
- auto_push: true
400
+ max_tokens: 2000
401
+ temperature: 0.1
402
+
403
+ # Git operations
404
+ git:
405
+ auto_commit: true
406
+ auto_push: true
279
407
  branch_prefix: "#{branch_prefix}"
280
408
  commit_message_template: 'Fix {{class_name}}\#\#{{method_name}}: {{error_type}}'
281
409
  pr_target_branch: "#{pr_target_branch}"
282
410
 
283
411
  # Pull Request Configuration
284
- pull_request:
285
- enabled: true
286
- auto_create: true
287
- labels:
288
- - "auto-fix"
412
+ pull_request:
413
+ enabled: true
414
+ auto_create: true
415
+ labels:
416
+ - "auto-fix"
289
417
  - "self-evolving"
290
- - "bug-fix"
291
-
418
+ - "bug-fix"
419
+
292
420
  # Safety Configuration
293
421
  safety:
294
422
  backup_before_evolution: true
@@ -369,6 +497,8 @@ YAML
369
497
 
370
498
  create_file_with_content('config/sidekiq.yml', sidekiq_config_content, dry_run: options[:dry_run])
371
499
 
500
+ # Permission validation method moved to top of file
501
+
372
502
  # Final instructions
373
503
  puts
374
504
  if options[:dry_run]
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module CodeHealer
4
- VERSION = "0.1.5"
4
+ VERSION = "0.1.7"
5
5
  end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: code_healer
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.5
4
+ version: 0.1.7
5
5
  platform: ruby
6
6
  authors:
7
7
  - Deepan Kumar