1+ require 'fileutils'
2+
13namespace :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