tayo 0.1.13 β†’ 0.2.0

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.
@@ -1,413 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- require 'tayo/commands/base'
4
- require 'git'
5
- require 'colorize'
6
- require 'tty-prompt'
7
-
8
- module Tayo
9
- module Commands
10
- class Sqlite < Base
11
- def execute
12
- puts "\nπŸ—„οΈ SQLite ν”„λ‘œλ•μ…˜ μ΅œμ ν™” 섀정을 μ‹œμž‘ν•©λ‹ˆλ‹€...".colorize(:yellow)
13
- puts "Tayo #{Tayo::VERSION}".colorize(:light_black)
14
-
15
- unless in_rails_project?
16
- puts "❌ Rails ν”„λ‘œμ νŠΈκ°€ μ•„λ‹™λ‹ˆλ‹€. Rails ν”„λ‘œμ νŠΈ λ£¨νŠΈμ—μ„œ μ‹€ν–‰ν•΄μ£Όμ„Έμš”.".colorize(:red)
17
- exit 1
18
- end
19
-
20
- puts "\n이 λͺ…령은 λ‹€μŒ μž‘μ—…μ„ μˆ˜ν–‰ν•©λ‹ˆλ‹€:".colorize(:light_black)
21
- puts " β€’ database.yml에 SQLite ν”„λ‘œλ•μ…˜ μ΅œμ ν™” μ„€μ • μΆ”κ°€"
22
- puts " β€’ SQLite pragma μ΄ˆκΈ°ν™” 파일 생성"
23
- puts " β€’ SQLite μ„€μ • 검증 rake task 생성"
24
- puts " β€’ SQLite ν”„λ‘œλ•μ…˜ κ°€μ΄λ“œ λ¬Έμ„œ 생성"
25
-
26
- prompt = TTY::Prompt.new
27
- continue = prompt.yes?("\nκ³„μ†ν•˜μ‹œκ² μŠ΅λ‹ˆκΉŒ?")
28
-
29
- unless continue
30
- puts "μ·¨μ†Œλ˜μ—ˆμŠ΅λ‹ˆλ‹€.".colorize(:yellow)
31
- exit 0
32
- end
33
-
34
- # Git μƒνƒœ 체크
35
- git = Git.open('.')
36
- unless git.status.changed.empty? && git.status.added.empty? && git.status.deleted.empty?
37
- puts "\n⚠️ μ»€λ°‹λ˜μ§€ μ•Šμ€ 변경사항이 μžˆμŠ΅λ‹ˆλ‹€.".colorize(:yellow)
38
- puts "SQLite 섀정을 μ μš©ν•˜κΈ° 전에 ν˜„μž¬ μƒνƒœλ₯Ό μ»€λ°‹ν•˜λŠ” 것을 ꢌμž₯ν•©λ‹ˆλ‹€.".colorize(:light_black)
39
-
40
- commit_now = prompt.yes?("\nμ§€κΈˆ μ»€λ°‹ν•˜μ‹œκ² μŠ΅λ‹ˆκΉŒ?")
41
- if commit_now
42
- git.add(all: true)
43
- git.commit("ν˜„μž¬ μƒνƒœ μ €μž₯ (tayo sqlite μ‹€ν–‰ μ „)")
44
- puts "βœ“ ν˜„μž¬ μƒνƒœλ₯Ό μ»€λ°‹ν–ˆμŠ΅λ‹ˆλ‹€.".colorize(:green)
45
- end
46
- end
47
-
48
- # database.yml μ—…λ°μ΄νŠΈ
49
- update_database_yml
50
-
51
- # SQLite pragma μ΄ˆκΈ°ν™” 파일 생성
52
- create_sqlite_pragma_initializer
53
-
54
- # SQLite 검증 rake task 생성
55
- create_sqlite_check_rake_task
56
-
57
- # SQLite κ°€μ΄λ“œ λ¬Έμ„œ 생성
58
- create_sqlite_guide
59
-
60
- # Git 컀밋
61
- begin
62
- git.add('config/database.yml')
63
- git.add('config/initializers/sqlite3_pragmas.rb')
64
- git.add('lib/tasks/sqlite_check.rake')
65
- git.add('sqlite_guide.md')
66
-
67
- commit_message = <<~MSG
68
- SQLite ν”„λ‘œλ•μ…˜ μ΅œμ ν™” μ„€μ • μΆ”κ°€
69
-
70
- - WAL λͺ¨λ“œμ™€ IMMEDIATE νŠΈλžœμž­μ…˜μœΌλ‘œ λ™μ‹œμ„± 문제 ν•΄κ²°
71
- - busy_timeout 5초 μ„€μ •μœΌλ‘œ SQLITE_BUSY μ—λŸ¬ λ°©μ§€
72
- - μΊμ‹œ 및 λ©”λͺ¨λ¦¬ μ΅œμ ν™”λ‘œ μ„±λŠ₯ ν–₯상
73
- - μ„€μ • 검증을 μœ„ν•œ rake task μΆ”κ°€
74
- - 상세 κ°€μ΄λ“œ λ¬Έμ„œ 포함
75
- MSG
76
-
77
- git.commit(commit_message)
78
- puts "\nβœ“ 변경사항을 Git에 μ»€λ°‹ν–ˆμŠ΅λ‹ˆλ‹€.".colorize(:green)
79
- rescue => e
80
- puts "\n⚠️ Git 컀밋 μ‹€νŒ¨: #{e.message}".colorize(:yellow)
81
- puts "μˆ˜λ™μœΌλ‘œ μ»€λ°‹ν•΄μ£Όμ„Έμš”.".colorize(:light_black)
82
- end
83
-
84
- puts "\nβœ… SQLite ν”„λ‘œλ•μ…˜ μ΅œμ ν™” 섀정이 μ™„λ£Œλ˜μ—ˆμŠ΅λ‹ˆλ‹€!".colorize(:green)
85
- puts "\nλ‹€μŒ λͺ…λ ΉμœΌλ‘œ 섀정을 검증할 수 μžˆμŠ΅λ‹ˆλ‹€:".colorize(:light_black)
86
- puts " rails db:sqlite_check".colorize(:cyan)
87
- puts " rails db:sqlite_stats".colorize(:cyan)
88
- puts "\nμžμ„Έν•œ λ‚΄μš©μ€ sqlite_guide.md νŒŒμΌμ„ μ°Έκ³ ν•˜μ„Έμš”.".colorize(:light_black)
89
- end
90
-
91
- private
92
-
93
- def update_database_yml
94
- puts "\nπŸ“ database.yml μ—…λ°μ΄νŠΈ 쀑...".colorize(:blue)
95
-
96
- database_yml_path = 'config/database.yml'
97
- unless File.exist?(database_yml_path)
98
- puts "❌ config/database.yml νŒŒμΌμ„ 찾을 수 μ—†μŠ΅λ‹ˆλ‹€.".colorize(:red)
99
- exit 1
100
- end
101
-
102
- # λ°±μ—… 생성
103
- backup_path = "#{database_yml_path}.backup"
104
- FileUtils.cp(database_yml_path, backup_path)
105
- puts " λ°±μ—… 생성: #{backup_path}".colorize(:light_black)
106
-
107
- content = File.read(database_yml_path)
108
-
109
- # SQLite μ΅œμ ν™” μ„€μ • μΆ”κ°€
110
- optimized_content = add_sqlite_optimizations(content)
111
-
112
- File.write(database_yml_path, optimized_content)
113
- puts "βœ“ database.yml이 μ—…λ°μ΄νŠΈλ˜μ—ˆμŠ΅λ‹ˆλ‹€.".colorize(:green)
114
- end
115
-
116
- def add_sqlite_optimizations(content)
117
- # 이미 μ΅œμ ν™” 섀정이 μžˆλŠ”μ§€ 확인
118
- if content.include?('transaction_mode: IMMEDIATE')
119
- puts " 이미 SQLite μ΅œμ ν™” 섀정이 μ μš©λ˜μ–΄ μžˆμŠ΅λ‹ˆλ‹€.".colorize(:yellow)
120
- return content
121
- end
122
-
123
- # production μ„Ήμ…˜ μ°ΎκΈ°
124
- if content =~ /^production:\s*$/
125
- # κΈ°μ‘΄ production 섀정이 λ‹¨μˆœν•œ 경우
126
- if content =~ /^production:\s*\n\s+<<:\s*\*default/
127
- # μƒˆλ‘œμš΄ production μ„€μ •μœΌλ‘œ ꡐ체
128
- new_production = <<~YAML
129
- production:
130
- primary:
131
- <<: *default
132
- database: storage/production.sqlite3
133
- transaction_mode: IMMEDIATE
134
- pragmas:
135
- journal_mode: WAL
136
- synchronous: NORMAL
137
- cache_size: 2000
138
- journal_size_limit: 27103364
139
- foreign_keys: ON
140
- mmap_size: 134217728
141
- busy_timeout: 5000
142
- cache:
143
- <<: *default
144
- database: storage/production_cache.sqlite3
145
- migrations_paths: db/cache_migrate
146
- transaction_mode: IMMEDIATE
147
- pragmas:
148
- journal_mode: WAL
149
- synchronous: NORMAL
150
- cache_size: 2000
151
- journal_size_limit: 27103364
152
- foreign_keys: ON
153
- mmap_size: 134217728
154
- busy_timeout: 5000
155
- queue:
156
- <<: *default
157
- database: storage/production_queue.sqlite3
158
- migrations_paths: db/queue_migrate
159
- transaction_mode: IMMEDIATE
160
- pragmas:
161
- journal_mode: WAL
162
- synchronous: NORMAL
163
- cache_size: 2000
164
- journal_size_limit: 27103364
165
- foreign_keys: ON
166
- mmap_size: 134217728
167
- busy_timeout: 5000
168
- cable:
169
- <<: *default
170
- database: storage/production_cable.sqlite3
171
- migrations_paths: db/cable_migrate
172
- transaction_mode: IMMEDIATE
173
- pragmas:
174
- journal_mode: WAL
175
- synchronous: NORMAL
176
- cache_size: 2000
177
- journal_size_limit: 27103364
178
- foreign_keys: ON
179
- mmap_size: 134217728
180
- busy_timeout: 5000
181
- YAML
182
-
183
- content.sub!(/^production:\s*\n\s+<<:\s*\*default\s*\n\s+database:\s+storage\/production\.sqlite3/, new_production.chomp)
184
- end
185
- end
186
-
187
- # default μ„Ήμ…˜μ— busy_timeout μΆ”κ°€
188
- unless content.include?('pragmas:')
189
- content.sub!(/^(\s+timeout:\s+5000)/, "\\1\n pragmas:\n busy_timeout: 5000")
190
- end
191
-
192
- content
193
- end
194
-
195
- def create_sqlite_pragma_initializer
196
- puts "\nπŸ“ SQLite pragma μ΄ˆκΈ°ν™” 파일 생성 쀑...".colorize(:blue)
197
-
198
- initializer_path = 'config/initializers/sqlite3_pragmas.rb'
199
-
200
- # consulteam의 sqlite3_pragmas.rb λ‚΄μš©
201
- initializer_content = <<~RUBY
202
- # SQLite3 ν”„λ‘œλ•μ…˜ μ΅œμ ν™” μ„€μ •
203
- # database.yml의 pragma 섀정을 λ³΄μ™„ν•˜λŠ” μΆ”κ°€ μ„€μ •
204
-
205
- # ActiveRecordκ°€ 연결을 μ„€μ •ν•  λ•Œλ§ˆλ‹€ μ‹€ν–‰λ˜λ„λ‘ μ„€μ •
206
- ActiveSupport.on_load(:active_record) do
207
- if defined?(ActiveRecord::ConnectionAdapters::SQLite3Adapter)
208
- # SQLite3Adapter의 configure_connection λ©”μ„œλ“œ μ˜€λ²„λΌμ΄λ“œ
209
- module SQLite3BusyTimeoutPatch
210
- def configure_connection
211
- super
212
- # busy_timeout을 ν™•μ‹€ν•˜κ²Œ μ„€μ • (λ°€λ¦¬μ΄ˆ λ‹¨μœ„)
213
- if @raw_connection.respond_to?(:busy_timeout)
214
- @raw_connection.busy_timeout(5000)
215
- end
216
- raw_execute("PRAGMA busy_timeout = 5000", "SCHEMA")
217
- raw_execute("PRAGMA journal_size_limit = 27103364", "SCHEMA")
218
- end
219
- end
220
-
221
- ActiveRecord::ConnectionAdapters::SQLite3Adapter.prepend(SQLite3BusyTimeoutPatch)
222
- end
223
- end
224
-
225
- Rails.application.config.after_initialize do
226
- ActiveRecord::Base.connection_pool.with_connection do |connection|
227
- if connection.adapter_name == 'SQLite'
228
- # 개발 ν™˜κ²½μ—μ„œλ„ μ€‘μš”ν•œ 섀정은 적용
229
- # SQLite3 gem의 busy_timeout λ©”μ„œλ“œλ₯Ό 직접 호좜
230
- if connection.raw_connection.respond_to?(:busy_timeout)
231
- connection.raw_connection.busy_timeout(5000)
232
- else
233
- connection.execute("PRAGMA busy_timeout = 5000")
234
- end
235
- connection.execute("PRAGMA journal_size_limit = 27103364")
236
-
237
- if Rails.env.production?
238
- # WAL λͺ¨λ“œ 확인 (database.ymlμ—μ„œ 이미 μ„€μ •λ˜μ–΄ μžˆμ–΄μ•Ό 함)
239
- result = connection.execute("PRAGMA journal_mode")
240
- journal_mode = result.first["journal_mode"] rescue result.first.values.first
241
-
242
- unless journal_mode.upcase == "WAL"
243
- Rails.logger.warn "WARNING: SQLite is not in WAL mode. Production performance may be severely impacted."
244
- end
245
-
246
- # busy_timeout 확인
247
- result = connection.execute("PRAGMA busy_timeout")
248
- busy_timeout = result.first["busy_timeout"] rescue result.first.values.first
249
-
250
- if busy_timeout.to_i < 5000
251
- Rails.logger.warn "WARNING: SQLite busy_timeout is less than 5000ms. This may cause SQLITE_BUSY errors under load."
252
- end
253
-
254
- # μΆ”κ°€ μ΅œμ ν™” μ„€μ •
255
- connection.execute("PRAGMA temp_store = MEMORY")
256
- connection.execute("PRAGMA optimize")
257
-
258
- Rails.logger.info "SQLite production optimizations applied successfully"
259
- Rails.logger.info "Journal mode: \#{journal_mode}, Busy timeout: \#{busy_timeout}ms"
260
- end
261
- end
262
- end
263
- end
264
-
265
- # 주기적인 μ΅œμ ν™” μ‹€ν–‰ (선택사항)
266
- if Rails.env.production? && defined?(ActiveRecord::Base)
267
- Thread.new do
268
- loop do
269
- sleep(4.hours)
270
- begin
271
- ActiveRecord::Base.connection_pool.with_connection do |connection|
272
- if connection.adapter_name == 'SQLite'
273
- connection.execute("PRAGMA optimize")
274
- Rails.logger.info "SQLite PRAGMA optimize executed"
275
- end
276
- end
277
- rescue => e
278
- Rails.logger.error "Failed to run SQLite optimization: \#{e.message}"
279
- end
280
- end
281
- end
282
- end
283
- RUBY
284
-
285
- File.write(initializer_path, initializer_content)
286
- puts "βœ“ #{initializer_path} 파일이 μƒμ„±λ˜μ—ˆμŠ΅λ‹ˆλ‹€.".colorize(:green)
287
- end
288
-
289
- def create_sqlite_check_rake_task
290
- puts "\nπŸ“ SQLite 검증 rake task 생성 쀑...".colorize(:blue)
291
-
292
- # lib/tasks 디렉토리 생성
293
- FileUtils.mkdir_p('lib/tasks')
294
-
295
- rake_task_path = 'lib/tasks/sqlite_check.rake'
296
-
297
- # consulteam의 sqlite_check.rake λ‚΄μš©
298
- rake_task_content = <<~RUBY
299
- namespace :db do
300
- desc "SQLite ν”„λ‘œλ•μ…˜ μ„€μ • 검증"
301
- task sqlite_check: :environment do
302
- if ActiveRecord::Base.connection.adapter_name == 'SQLite'
303
- puts "\\n=== SQLite ν”„λ‘œλ•μ…˜ μ„€μ • 검증 ==="
304
-
305
- connection = ActiveRecord::Base.connection
306
-
307
- # 각 pragma μ„€μ • 확인
308
- pragmas = {
309
- 'journal_mode' => 'WAL',
310
- 'synchronous' => 'NORMAL',
311
- 'cache_size' => '2000',
312
- 'journal_size_limit' => '27103364',
313
- 'foreign_keys' => '1',
314
- 'mmap_size' => '134217728',
315
- 'busy_timeout' => '5000'
316
- }
317
-
318
- all_good = true
319
-
320
- pragmas.each do |pragma, expected|
321
- result = connection.execute("PRAGMA \#{pragma}")
322
- actual = result.first[pragma] rescue result.first.values.first
323
-
324
- if pragma == 'foreign_keys'
325
- status = actual.to_s == expected ? "βœ“" : "βœ—"
326
- elsif pragma == 'journal_mode'
327
- status = actual.to_s.upcase == expected ? "βœ“" : "βœ—"
328
- elsif pragma == 'synchronous'
329
- # NORMAL = 1 in SQLite
330
- status = (actual.to_s == '1' || actual.to_s.upcase == expected) ? "βœ“" : "βœ—"
331
- else
332
- status = actual.to_s == expected ? "βœ“" : "βœ—"
333
- end
334
-
335
- puts "\#{status} \#{pragma.ljust(20)}: \#{actual} \#{status == 'βœ—' ? "(μ˜ˆμƒκ°’: \#{expected})" : ""}"
336
- all_good = false if status == "βœ—"
337
- end
338
-
339
- # transaction_mode 확인 (Rails λ‘œκ·Έμ—μ„œλ§Œ 확인 κ°€λŠ₯)
340
- puts "\\nμ°Έκ³ : transaction_mode=IMMEDIATE 섀정은 λŸ°νƒ€μž„μ—μ„œλ§Œ 확인 κ°€λŠ₯ν•©λ‹ˆλ‹€."
341
-
342
- if all_good
343
- puts "\\nβœ… λͺ¨λ“  SQLite ν”„λ‘œλ•μ…˜ 섀정이 μ˜¬λ°”λ₯΄κ²Œ κ΅¬μ„±λ˜μ—ˆμŠ΅λ‹ˆλ‹€!"
344
- else
345
- puts "\\n⚠️ 일뢀 섀정이 ꢌμž₯κ°’κ³Ό λ‹€λ¦…λ‹ˆλ‹€. database.yml을 ν™•μΈν•˜μ„Έμš”."
346
- end
347
- else
348
- puts "이 νƒœμŠ€ν¬λŠ” SQLite λ°μ΄ν„°λ² μ΄μŠ€μ—μ„œλ§Œ μ‚¬μš© κ°€λŠ₯ν•©λ‹ˆλ‹€."
349
- end
350
- end
351
-
352
- desc "SQLite μ„±λŠ₯ 톡계 확인"
353
- task sqlite_stats: :environment do
354
- if ActiveRecord::Base.connection.adapter_name == 'SQLite'
355
- puts "\\n=== SQLite μ„±λŠ₯ 톡계 ==="
356
-
357
- connection = ActiveRecord::Base.connection
358
-
359
- # λ°μ΄ν„°λ² μ΄μŠ€ 파일 크기
360
- db_path = connection.instance_variable_get(:@config)[:database]
361
- if File.exist?(db_path)
362
- size_mb = File.size(db_path) / 1024.0 / 1024.0
363
- puts "λ°μ΄ν„°λ² μ΄μŠ€ 크기: \#{'%.2f' % size_mb} MB"
364
-
365
- # WAL 파일 크기 확인
366
- wal_path = "\#{db_path}-wal"
367
- if File.exist?(wal_path)
368
- wal_size_mb = File.size(wal_path) / 1024.0 / 1024.0
369
- puts "WAL 파일 크기: \#{'%.2f' % wal_size_mb} MB"
370
- end
371
- end
372
-
373
- # νŽ˜μ΄μ§€ 정보
374
- result = connection.execute("PRAGMA page_count")
375
- page_count = result.first.values.first
376
-
377
- result = connection.execute("PRAGMA page_size")
378
- page_size = result.first.values.first
379
-
380
- puts "νŽ˜μ΄μ§€ 수: \#{page_count}"
381
- puts "νŽ˜μ΄μ§€ 크기: \#{page_size} bytes"
382
-
383
- # μΊμ‹œ 히트율 (λŒ€λž΅μ μΈ μΆ”μ •)
384
- result = connection.execute("PRAGMA cache_size")
385
- cache_size = result.first.values.first
386
- puts "μΊμ‹œ 크기: \#{cache_size} pages"
387
-
388
- puts "\\nμ‹€μ‹œκ°„ μ„±λŠ₯ λͺ¨λ‹ˆν„°λ§μ„ μœ„ν•΄μ„œλŠ” μ• ν”Œλ¦¬μΌ€μ΄μ…˜ 둜그λ₯Ό ν™•μΈν•˜μ„Έμš”."
389
- else
390
- puts "이 νƒœμŠ€ν¬λŠ” SQLite λ°μ΄ν„°λ² μ΄μŠ€μ—μ„œλ§Œ μ‚¬μš© κ°€λŠ₯ν•©λ‹ˆλ‹€."
391
- end
392
- end
393
- end
394
- RUBY
395
-
396
- File.write(rake_task_path, rake_task_content)
397
- puts "βœ“ #{rake_task_path} 파일이 μƒμ„±λ˜μ—ˆμŠ΅λ‹ˆλ‹€.".colorize(:green)
398
- end
399
-
400
- def create_sqlite_guide
401
- puts "\nπŸ“ SQLite κ°€μ΄λ“œ λ¬Έμ„œ 생성 쀑...".colorize(:blue)
402
-
403
- guide_path = 'sqlite_guide.md'
404
-
405
- # consulteam의 sqlite_guide.md λ‚΄μš©
406
- guide_content = File.read('/Users/alfonso/projects/consulteam/sqlite_guide.md')
407
-
408
- File.write(guide_path, guide_content)
409
- puts "βœ“ #{guide_path} 파일이 μƒμ„±λ˜μ—ˆμŠ΅λ‹ˆλ‹€.".colorize(:green)
410
- end
411
- end
412
- end
413
- end
@@ -1,60 +0,0 @@
1
- #!/bin/bash
2
-
3
- # RubyGems API ν‚€ μ„€μ • 슀크립트
4
-
5
- echo "πŸ”‘ RubyGems API ν‚€ μ„€μ • λ„μš°λ―Έ"
6
- echo "================================"
7
- echo ""
8
- echo "이 μŠ€ν¬λ¦½νŠΈλŠ” RubyGems API ν‚€λ₯Ό μ•ˆμ „ν•˜κ²Œ μ €μž₯ν•©λ‹ˆλ‹€."
9
- echo ""
10
-
11
- # μ˜΅μ…˜ 선택
12
- echo "μ €μž₯ 방법을 μ„ νƒν•˜μ„Έμš”:"
13
- echo "1) ~/.gem/credentials (ν‘œμ€€ 방법)"
14
- echo "2) macOS Keychain (κ°€μž₯ μ•ˆμ „)"
15
- echo "3) λ‘˜ λ‹€"
16
- echo ""
17
- read -p "선택 (1-3): " choice
18
-
19
- # API ν‚€ μž…λ ₯
20
- echo ""
21
- read -s -p "RubyGems API ν‚€λ₯Ό μž…λ ₯ν•˜μ„Έμš”: " api_key
22
- echo ""
23
-
24
- case $choice in
25
- 1)
26
- # credentials νŒŒμΌμ— μ €μž₯
27
- mkdir -p ~/.gem
28
- echo "---" > ~/.gem/credentials
29
- echo ":rubygems_api_key: $api_key" >> ~/.gem/credentials
30
- chmod 0600 ~/.gem/credentials
31
- echo "βœ… ~/.gem/credentials에 μ €μž₯λ˜μ—ˆμŠ΅λ‹ˆλ‹€."
32
- ;;
33
- 2)
34
- # Keychain에 μ €μž₯
35
- security add-generic-password -a "$USER" -s "rubygems-api-key" -w "$api_key" -U
36
- echo "βœ… macOS Keychain에 μ €μž₯λ˜μ—ˆμŠ΅λ‹ˆλ‹€."
37
- ;;
38
- 3)
39
- # λ‘˜ λ‹€
40
- mkdir -p ~/.gem
41
- echo "---" > ~/.gem/credentials
42
- echo ":rubygems_api_key: $api_key" >> ~/.gem/credentials
43
- chmod 0600 ~/.gem/credentials
44
- security add-generic-password -a "$USER" -s "rubygems-api-key" -w "$api_key" -U
45
- echo "βœ… 두 κ³³ λͺ¨λ‘μ— μ €μž₯λ˜μ—ˆμŠ΅λ‹ˆλ‹€."
46
- ;;
47
- *)
48
- echo "❌ 잘λͺ»λœ μ„ νƒμž…λ‹ˆλ‹€."
49
- exit 1
50
- ;;
51
- esac
52
-
53
- echo ""
54
- echo "πŸŽ‰ 섀정이 μ™„λ£Œλ˜μ—ˆμŠ΅λ‹ˆλ‹€!"
55
- echo ""
56
- echo "이제 λ‹€μŒ λͺ…λ ΉμœΌλ‘œ gem을 배포할 수 μžˆμŠ΅λ‹ˆλ‹€:"
57
- echo " rake release"
58
- echo ""
59
- echo "λ˜λŠ” Keychainμ—μ„œ ν‚€λ₯Ό μ‚¬μš©ν•˜λ €λ©΄:"
60
- echo " GEM_HOST_API_KEY=\$(security find-generic-password -a \"$USER\" -s \"rubygems-api-key\" -w) rake release"