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 +4 -4
- data/CHANGELOG.md +27 -1
- data/lib/code_healer/evolution_job.rb +1 -1
- data/lib/code_healer/healing_job.rb +1 -1
- data/lib/code_healer/healing_workspace_manager.rb +138 -34
- data/lib/code_healer/version.rb +1 -1
- metadata +1 -1
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 4be2602f991eaa2b9952ab40d9b582bb80482b7e1238dfa3b1019649d3a7c67a
|
4
|
+
data.tar.gz: c7762eeafe979d09f1620145f46357b822582770095a1ba7bb7be24645818715
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
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.
|
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.
|
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.
|
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
|
124
|
-
puts "🔄
|
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
|
-
#
|
128
|
-
Dir.chdir(
|
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
|
-
#
|
138
|
-
|
151
|
+
# Check Git status
|
152
|
+
puts "📊 [WORKSPACE] Git status in workspace:"
|
153
|
+
system("git status --porcelain")
|
139
154
|
|
140
|
-
#
|
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
|
-
#
|
146
|
-
system("git
|
147
|
-
|
148
|
-
|
149
|
-
|
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
|
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
|
-
#
|
213
|
-
|
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
|
-
#
|
236
|
-
|
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
|
-
|
277
|
-
|
278
|
-
|
279
|
-
|
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
|
data/lib/code_healer/version.rb
CHANGED