code_healer 0.1.7 → 0.1.11

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: fb4a7ded404d0efca6e6e111b0186cc2bdeaef8a6eaf4041fd9799fcc447d044
4
- data.tar.gz: 95f4317a52fa36bc1aae2923d497a01c282486de0680548a5e80ff1f15ff6468
3
+ metadata.gz: 4be2602f991eaa2b9952ab40d9b582bb80482b7e1238dfa3b1019649d3a7c67a
4
+ data.tar.gz: c7762eeafe979d09f1620145f46357b822582770095a1ba7bb7be24645818715
5
5
  SHA512:
6
- metadata.gz: ad4af34d619b3d1361a61b5dd5e7a285bb9cdc399b72d200209a84ce565f2e7740917878684e4b094254ba3fbc858765e4dc2af2a3d425dd8d343a71e180477e
7
- data.tar.gz: 89b963d38d992791a738ff3ab91716939e39a1e8b84d056574bc6ffae504d66e6c192306ba28f5671efeec54967fa0eefca044e17121538055875a91875f4dbd
6
+ metadata.gz: 29e14dea885f980028dbe1105dd9d188ae547ecaba7a4e6e46332fe1c34af437bbf9351ca868fdbc7afb0d644e3d9a3c38ba38979d2206ca1eaa744a98bc451b
7
+ data.tar.gz: 7857192ea8f774737b3ed3093679a0cf46f8af3db7e10117aa414bce3e7163b64a247d4446b0fa835191cb58cb204fc405299082790f05bc7885d85fc96ed94b
data/CHANGELOG.md CHANGED
@@ -5,7 +5,33 @@ 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.7] - 2025-01-14
8
+ ## [0.1.11] - 2025-01-14
9
+
10
+ ### Fixed
11
+ - **Repository cloning** - Now clones from GitHub remote URL instead of local path
12
+ - **Git remote configuration** - Ensures workspace has correct GitHub remote for PR creation
13
+ - **Debug information** - Added Git remote and branch debugging in workspace operations
14
+
15
+ ## [0.1.10] - 2025-01-14
16
+
17
+ ### Changed
18
+ - **Complete workspace isolation** - All Git operations now happen in isolated workspace only
19
+ - **No file copying** - Removed file copying between workspace and main repo
20
+ - **Direct PR creation** - Pull requests are created directly from the isolated workspace
21
+ - **Main repo protection** - Main repository is never touched, only the isolated workspace
22
+
23
+ ### Fixed
24
+ - **Git commit workflow** - Added proper change detection before committing
25
+ - **Empty branch prevention** - Delete healing branches when no changes are detected
26
+ - **Enhanced debugging** - Added Git status and diff logging throughout the process
27
+
28
+ ## [0.1.8] - 2025-01-14
29
+
30
+ ### Changed
31
+ - **Production safety** - Healing workspace no longer modifies main directory directly
32
+ - **Git workflow** - Changes are applied to isolated healing branches only
33
+ - **Pull request automation** - Automatic PR creation when configured
34
+ - **Method renaming** - `merge_fixes_back` → `create_healing_branch` for clarity
9
35
 
10
36
  ### Fixed
11
37
  - **Git operations in isolated healing workspace** - Preserved .git directory during cloning for proper Git operations
@@ -22,7 +22,7 @@ class EvolutionJob
22
22
 
23
23
  if test_success
24
24
  # Merge back to main repo
25
- healing_branch = CodeHealer::HealingWorkspaceManager.merge_fixes_back(
25
+ healing_branch = CodeHealer::HealingWorkspaceManager.create_healing_branch(
26
26
  Rails.root.to_s,
27
27
  workspace_path,
28
28
  CodeHealer::ConfigManager.git_settings['pr_target_branch'] || 'main'
@@ -33,7 +33,7 @@ module CodeHealer
33
33
 
34
34
  if test_success
35
35
  # Merge back to main repo
36
- healing_branch = CodeHealer::HealingWorkspaceManager.merge_fixes_back(
36
+ healing_branch = CodeHealer::HealingWorkspaceManager.create_healing_branch(
37
37
  Rails.root.to_s,
38
38
  workspace_path,
39
39
  CodeHealer::ConfigManager.git_settings['pr_target_branch'] || 'main'
@@ -78,6 +78,14 @@ module CodeHealer
78
78
  apply_fix_to_file(file_path, fix[:new_code], class_name, method_name)
79
79
  end
80
80
 
81
+ # Show workspace Git status after applying fixes
82
+ Dir.chdir(workspace_path) do
83
+ puts "🔧 [WORKSPACE] Git status after fixes:"
84
+ system("git status --porcelain")
85
+ puts "🔧 [WORKSPACE] Git diff after fixes:"
86
+ system("git diff")
87
+ end
88
+
81
89
  puts "✅ Fixes applied successfully in workspace"
82
90
  true
83
91
  rescue => e
@@ -120,36 +128,75 @@ module CodeHealer
120
128
  end
121
129
  end
122
130
 
123
- def merge_fixes_back(repo_path, workspace_path, branch_name)
124
- puts "🔄 Merging fixes back to main repository"
131
+ def create_healing_branch(repo_path, workspace_path, branch_name)
132
+ puts "🔄 Creating healing branch and PR from isolated workspace"
125
133
 
126
134
  begin
127
- # Create healing branch in main repo
128
- Dir.chdir(repo_path) do
135
+ # All Git operations happen in the isolated workspace
136
+ Dir.chdir(workspace_path) do
137
+ puts "🌿 [WORKSPACE] Working in isolated workspace: #{workspace_path}"
138
+
139
+ # Debug Git configuration
140
+ puts "🌿 [WORKSPACE] Git remote origin: #{`git config --get remote.origin.url`.strip}"
141
+ puts "🌿 [WORKSPACE] Current branch: #{`git branch --show-current`.strip}"
142
+
129
143
  # Ensure we're on the target branch
130
144
  system("git checkout #{branch_name}")
131
145
  system("git pull origin #{branch_name}")
132
146
 
133
- # Create healing branch
147
+ # Create healing branch in the workspace
134
148
  healing_branch = "code-healer-fix-#{Time.now.to_i}"
135
149
  system("git checkout -b #{healing_branch}")
136
150
 
137
- # Copy fixed files from workspace
138
- copy_fixed_files(workspace_path, repo_path)
151
+ # Check Git status
152
+ puts "📊 [WORKSPACE] Git status in workspace:"
153
+ system("git status --porcelain")
139
154
 
140
- # Commit changes
155
+ # Add all changes (the fixes are already applied in the workspace)
141
156
  system("git add .")
142
- commit_message = "Fix applied by CodeHealer: #{Time.now.strftime('%Y-%m-%d %H:%M:%S')}"
143
- system("git commit -m '#{commit_message}'")
144
157
 
145
- # Push branch
146
- system("git push origin #{healing_branch}")
147
-
148
- puts " Healing branch created: #{healing_branch}"
149
- healing_branch
158
+ # Check if there are changes to commit
159
+ if system("git diff --cached --quiet") == false
160
+ puts "📝 [WORKSPACE] Changes detected, committing to healing branch..."
161
+ commit_message = "Fix applied by CodeHealer: #{Time.now.strftime('%Y-%m-%d %H:%M:%S')}"
162
+ system("git commit -m '#{commit_message}'")
163
+
164
+ # Push healing branch from workspace
165
+ puts "🚀 [WORKSPACE] Pushing healing branch from workspace..."
166
+ system("git push origin #{healing_branch}")
167
+
168
+ puts "✅ [WORKSPACE] Healing branch created and pushed: #{healing_branch}"
169
+ puts "🔒 Main repository (#{repo_path}) remains completely untouched"
170
+ puts "📝 All changes committed in isolated workspace"
171
+
172
+ # Create pull request if auto-create is enabled
173
+ if should_create_pull_request?
174
+ pr_url = create_pull_request(healing_branch, branch_name)
175
+ if pr_url
176
+ puts "🔗 [WORKSPACE] Pull request created: #{pr_url}"
177
+ else
178
+ puts "⚠️ [WORKSPACE] Failed to create pull request, but branch is ready"
179
+ end
180
+ else
181
+ puts "🔍 [WORKSPACE] Review the changes and create a pull request when ready"
182
+ end
183
+
184
+ healing_branch
185
+ else
186
+ puts "⚠️ [WORKSPACE] No changes detected in workspace"
187
+ puts "🔍 This might indicate that:"
188
+ puts " - The fixes were not applied to the workspace"
189
+ puts " - There was an issue with the healing process"
190
+
191
+ # Delete the empty branch
192
+ system("git checkout #{branch_name}")
193
+ system("git branch -D #{healing_branch}")
194
+ puts "🗑️ [WORKSPACE] Deleted empty healing branch: #{healing_branch}"
195
+ nil
196
+ end
150
197
  end
151
198
  rescue => e
152
- puts "❌ Failed to merge fixes back: #{e.message}"
199
+ puts "❌ Failed to create healing branch from workspace: #{e.message}"
153
200
  nil
154
201
  end
155
202
  end
@@ -197,6 +244,51 @@ module CodeHealer
197
244
 
198
245
  private
199
246
 
247
+ def should_create_pull_request?
248
+ config = CodeHealer::ConfigManager.config
249
+ auto_create = config.dig('pull_request', 'auto_create')
250
+ auto_create = config.dig(:pull_request, :auto_create) if auto_create.nil?
251
+ auto_create == true
252
+ end
253
+
254
+ def create_pull_request(healing_branch, target_branch)
255
+ puts "🔗 Creating pull request for #{healing_branch} → #{target_branch}"
256
+
257
+ begin
258
+ require 'octokit'
259
+
260
+ config = CodeHealer::ConfigManager.config
261
+ github_token = ENV['GITHUB_TOKEN']
262
+ repo_name = config['github_repo'] || config[:github_repo]
263
+
264
+ unless github_token && repo_name
265
+ puts "❌ Missing GitHub token or repository configuration"
266
+ return nil
267
+ end
268
+
269
+ # Parse repo name (owner/repo)
270
+ owner, repo = repo_name.split('/')
271
+
272
+ client = Octokit::Client.new(access_token: github_token)
273
+
274
+ # Create pull request
275
+ pr = client.create_pull_request(
276
+ repo_name,
277
+ target_branch,
278
+ healing_branch,
279
+ "CodeHealer: Automated Fix",
280
+ "This pull request contains automated fixes generated by CodeHealer.\n\n" \
281
+ "**Please review the changes before merging.**\n\n" \
282
+ "Generated at: #{Time.now.strftime('%Y-%m-%d %H:%M:%S')}"
283
+ )
284
+
285
+ pr.html_url
286
+ rescue => e
287
+ puts "❌ Failed to create pull request: #{e.message}"
288
+ nil
289
+ end
290
+ end
291
+
200
292
  def clone_strategy
201
293
  cfg = CodeHealer::ConfigManager.code_heal_directory_config
202
294
  cfg['clone_strategy'] || cfg[:clone_strategy] || "branch"
@@ -207,10 +299,20 @@ module CodeHealer
207
299
  Dir.chdir(repo_path) do
208
300
  current_branch = branch_name || `git branch --show-current`.strip
209
301
  puts "🌿 [WORKSPACE] Current branch: #{current_branch}"
210
- puts "🌿 [WORKSPACE] Executing: git clone --single-branch --branch #{current_branch} #{repo_path} #{workspace_path}"
211
302
 
212
- # Clone only the current branch
213
- result = system("git clone --single-branch --branch #{current_branch} #{repo_path} #{workspace_path}")
303
+ # Get the GitHub remote URL instead of local path
304
+ remote_url = `git config --get remote.origin.url`.strip
305
+ puts "🌿 [WORKSPACE] Remote origin URL: #{remote_url}"
306
+
307
+ if remote_url.empty?
308
+ puts "❌ [WORKSPACE] No remote origin found in #{repo_path}"
309
+ return false
310
+ end
311
+
312
+ puts "🌿 [WORKSPACE] Executing: git clone --single-branch --branch #{current_branch} #{remote_url} #{workspace_path}"
313
+
314
+ # Clone from GitHub remote URL, not local path
315
+ result = system("git clone --single-branch --branch #{current_branch} #{remote_url} #{workspace_path}")
214
316
  puts "🌿 [WORKSPACE] Clone result: #{result ? 'SUCCESS' : 'FAILED'}"
215
317
 
216
318
  if result
@@ -230,10 +332,20 @@ module CodeHealer
230
332
  Dir.chdir(repo_path) do
231
333
  current_branch = branch_name || `git branch --show-current`.strip
232
334
  puts "🌿 [WORKSPACE] Target branch: #{current_branch}"
233
- puts "🌿 [WORKSPACE] Executing: git clone #{repo_path} #{workspace_path}"
234
335
 
235
- # Clone full repo
236
- result = system("git clone #{repo_path} #{workspace_path}")
336
+ # Get the GitHub remote URL instead of local path
337
+ remote_url = `git config --get remote.origin.url`.strip
338
+ puts "🌿 [WORKSPACE] Remote origin URL: #{remote_url}"
339
+
340
+ if remote_url.empty?
341
+ puts "❌ [WORKSPACE] No remote origin found in #{repo_path}"
342
+ return false
343
+ end
344
+
345
+ puts "🌿 [WORKSPACE] Executing: git clone #{remote_url} #{workspace_path}"
346
+
347
+ # Clone from GitHub remote URL, not local path
348
+ result = system("git clone #{remote_url} #{workspace_path}")
237
349
  puts "🌿 [WORKSPACE] Clone result: #{result ? 'SUCCESS' : 'FAILED'}"
238
350
 
239
351
  if result
@@ -273,18 +385,10 @@ module CodeHealer
273
385
  Dir.glob("**/*.rb")
274
386
  end
275
387
 
276
- def copy_fixed_files(workspace_path, repo_path)
277
- # Copy all Ruby files from workspace to repo
278
- Dir.glob(File.join(workspace_path, "**/*.rb")).each do |workspace_file|
279
- relative_path = workspace_file.sub(workspace_path + "/", "")
280
- repo_file = File.join(repo_path, relative_path)
281
-
282
- if File.exist?(repo_file)
283
- FileUtils.cp(workspace_file, repo_file)
284
- puts "📁 Copied fixed file: #{relative_path}"
285
- end
286
- end
287
- end
388
+ # This method is no longer needed since we work entirely in the isolated workspace
389
+ # def copy_fixed_files(workspace_path, repo_path)
390
+ # # Removed - no longer copying files between directories
391
+ # end
288
392
 
289
393
  def workspace_expired?(workspace_path, hours)
290
394
  return false unless hours && hours > 0
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module CodeHealer
4
- VERSION = "0.1.7"
4
+ VERSION = "0.1.11"
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.7
4
+ version: 0.1.11
5
5
  platform: ruby
6
6
  authors:
7
7
  - Deepan Kumar