Skip to content

Commit 2832230

Browse files
committed
fix: Rakeタスクで行番号がずれるバグを修正
問題: - YAMLファイル更新中に yaml_lines.insert() で行が追加されると 次のDojoの行番号がずれて git blame が間違った行を参照していた 解決策: - Phase 1: 全Dojoの情報収集(YAMLを変更せずに) - Phase 2: 収集した情報を元にYAMLを一括更新 - これにより行番号のずれを防止
1 parent 884afec commit 2832230

File tree

1 file changed

+91
-42
lines changed

1 file changed

+91
-42
lines changed

lib/tasks/dojos_inactivated_at.rake

Lines changed: 91 additions & 42 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,5 @@
1+
require 'fileutils'
2+
13
namespace :dojos do
24
desc 'Git履歴からinactivated_at日付を抽出してYAMLファイルに反映(引数でDojo IDを指定可能)'
35
task :extract_inactivated_at_from_git, [:dojo_id] => :environment do |t, args|
@@ -21,7 +23,9 @@ namespace :dojos do
2123

2224
puts ""
2325
updated_count = 0
26+
updates_to_apply = [] # 更新情報を保存する配列
2427

28+
# Phase 1: 全てのDojoの情報を収集(YAMLを変更せずに)
2529
target_dojos.each do |dojo|
2630
puts "処理中: #{dojo.name} (ID: #{dojo.id})"
2731

@@ -40,11 +44,22 @@ namespace :dojos do
4044
# 該当Dojoブロック内で is_active: false を見つける
4145
if in_dojo_block && line.match?(/^\s*is_active: false/)
4246
target_line_number = index + 1 # git blameは1-indexedなので+1
47+
# デバッグ: 重要なDojoの行番号を確認
48+
if [203, 201, 125, 222, 25, 20].include?(dojo.id)
49+
puts " [DEBUG] ID #{dojo.id}: is_active:false は #{target_line_number} 行目"
50+
end
4351
break
4452
end
4553
end
4654

4755
if target_line_number
56+
# ファイルの行数チェック
57+
total_lines = yaml_lines.length
58+
if target_line_number > total_lines
59+
puts " ✗ エラー: 行番号 #{target_line_number} が範囲外です(ファイル行数: #{total_lines})"
60+
next
61+
end
62+
4863
# git blame を使って該当行の最新コミット情報を取得
4964
# --porcelain で解析しやすい形式で出力
5065
blame_cmd = "git blame #{yaml_path} -L #{target_line_number},+1 --porcelain 2>&1"
@@ -76,40 +91,17 @@ namespace :dojos do
7691
next
7792
end
7893

79-
# YAMLファイルのDojoブロックを見つけて更新
80-
yaml_updated = false
81-
yaml_lines.each_with_index do |line, index|
82-
if line.match?(/^- id: #{dojo.id}$/)
83-
# 該当Dojoブロックの最後に inactivated_at を追加
84-
insert_index = index + 1
85-
while insert_index < yaml_lines.length && !yaml_lines[insert_index].match?(/^- id:/)
86-
# is_active: false の次の行に挿入したい
87-
if yaml_lines[insert_index - 1].match?(/is_active: false/)
88-
# 既に inactivated_at がある場合はスキップ(冪等性)
89-
if yaml_lines[insert_index].match?(/^\s*inactivated_at:/)
90-
puts " - inactivated_at は既に設定されています"
91-
yaml_updated = false
92-
break
93-
end
94-
95-
yaml_lines.insert(insert_index,
96-
" inactivated_at: '#{inactivated_date.strftime('%Y-%m-%d %H:%M:%S')}'\n")
97-
yaml_updated = true
98-
break
99-
end
100-
insert_index += 1
101-
end
102-
break
103-
end
104-
end
94+
# 更新情報を保存(実際の更新は後で一括実行)
95+
updates_to_apply << {
96+
dojo_id: dojo.id,
97+
dojo_name: dojo.name,
98+
date: inactivated_date,
99+
commit_id: commit_id,
100+
author_name: author_name
101+
}
105102

106-
if yaml_updated
107-
updated_count += 1
108-
puts " ✓ inactivated_at を追加: #{inactivated_date.strftime('%Y-%m-%d %H:%M:%S')}"
109-
puts " コミット: #{commit_id[0..7]} by #{author_name}"
110-
elsif !args[:dojo_id]
111-
puts " - スキップ(既に設定済みまたは更新失敗)"
112-
end
103+
puts " ✓ inactivated_at の日付を取得: #{inactivated_date.strftime('%Y-%m-%d %H:%M:%S')}"
104+
puts " コミット: #{commit_id[0..7]} by #{author_name}"
113105
else
114106
puts " ✗ コミット情報の取得に失敗"
115107
end
@@ -120,17 +112,74 @@ namespace :dojos do
120112
puts ""
121113
end
122114

115+
# Phase 2: 収集した情報を元にYAMLファイルを一括更新
116+
if !args[:dojo_id] && updates_to_apply.any?
117+
puts "\n=== Phase 2: YAMLファイルを更新 ==="
118+
puts "#{updates_to_apply.count} 個のDojoを更新します\n\n"
119+
120+
# 更新情報を日付順(ID順)にソート
121+
updates_to_apply.sort_by! { |u| u[:dojo_id] }
122+
123+
updates_to_apply.each do |update|
124+
puts "更新中: #{update[:dojo_name]} (ID: #{update[:dojo_id]})"
125+
126+
# YAMLファイルのDojoブロックを見つけて更新
127+
yaml_lines.each_with_index do |line, index|
128+
if line.match?(/^- id: #{update[:dojo_id]}$/)
129+
# 該当Dojoブロックの最後に inactivated_at を追加
130+
insert_index = index + 1
131+
while insert_index < yaml_lines.length && !yaml_lines[insert_index].match?(/^- id:/)
132+
# is_active: false の次の行に挿入したい
133+
if yaml_lines[insert_index - 1].match?(/is_active: false/)
134+
# 既に inactivated_at がある場合はスキップ(冪等性)
135+
if yaml_lines[insert_index].match?(/^\s*inactivated_at:/)
136+
puts " - inactivated_at は既に設定されています"
137+
break
138+
end
139+
140+
yaml_lines.insert(insert_index,
141+
" inactivated_at: '#{update[:date].strftime('%Y-%m-%d %H:%M:%S')}'\n")
142+
updated_count += 1
143+
puts " ✓ inactivated_at を追加: #{update[:date].strftime('%Y-%m-%d %H:%M:%S')}"
144+
break
145+
end
146+
insert_index += 1
147+
end
148+
break
149+
end
150+
end
151+
end
152+
end
153+
123154
# 全Dojoモードで更新があった場合のみYAMLファイルを書き戻す
124155
if !args[:dojo_id] && updated_count > 0
125-
File.write(yaml_path, yaml_lines.join)
126-
127-
puts "=== 完了 ==="
128-
puts "合計 #{updated_count} 個のDojoに inactivated_at を追加しました"
129-
puts ""
130-
puts "次のステップ:"
131-
puts "1. db/dojos.yaml の変更内容を確認"
132-
puts "2. rails dojos:update_db_by_yaml を実行してDBに反映"
133-
puts "3. 変更をコミット"
156+
begin
157+
# バックアップを作成(tmpディレクトリに)
158+
backup_path = Rails.root.join('tmp', "dojos.yaml.backup.#{Time.now.strftime('%Y%m%d_%H%M%S')}")
159+
FileUtils.cp(yaml_path, backup_path)
160+
puts "\n📦 バックアップ作成: #{backup_path}"
161+
162+
# YAMLファイルを更新
163+
File.write(yaml_path, yaml_lines.join)
164+
165+
# YAML構文チェック(DateとTimeクラスを許可)
166+
YAML.load_file(yaml_path, permitted_classes: [Date, Time])
167+
168+
puts "\n=== 完了 ==="
169+
puts "合計 #{updated_count} 個のDojoに inactivated_at を追加しました"
170+
puts ""
171+
puts "次のステップ:"
172+
puts "1. db/dojos.yaml の変更内容を確認"
173+
puts "2. rails dojos:update_db_by_yaml を実行してDBに反映"
174+
puts "3. 変更をコミット"
175+
rescue => e
176+
puts "\n❌ エラー: YAMLファイルの更新に失敗しました"
177+
puts " #{e.message}"
178+
puts "\n🔙 バックアップから復元中..."
179+
FileUtils.cp(backup_path, yaml_path) if File.exist?(backup_path)
180+
puts " 復元完了"
181+
raise e
182+
end
134183
elsif !args[:dojo_id]
135184
puts "=== 完了 ==="
136185
puts "更新対象のDojoはありませんでした(または既に設定済み)"

0 commit comments

Comments
 (0)