tayo 0.1.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.
@@ -0,0 +1,389 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "colorize"
4
+ require "json"
5
+ require "git"
6
+ require "yaml"
7
+ require "tty-prompt"
8
+
9
+ module Tayo
10
+ module Commands
11
+ class Gh
12
+ def execute
13
+ puts "๐Ÿš€ GitHub ์ €์žฅ์†Œ ๋ฐ ์ปจํ…Œ์ด๋„ˆ ๋ ˆ์ง€์ŠคํŠธ๋ฆฌ ์„ค์ •์„ ์‹œ์ž‘ํ•ฉ๋‹ˆ๋‹ค...".colorize(:green)
14
+
15
+ unless rails_project?
16
+ puts "โŒ Rails ํ”„๋กœ์ ํŠธ๊ฐ€ ์•„๋‹™๋‹ˆ๋‹ค. Rails ํ”„๋กœ์ ํŠธ ๋ฃจํŠธ์—์„œ ์‹คํ–‰ํ•ด์ฃผ์„ธ์š”.".colorize(:red)
17
+ return
18
+ end
19
+
20
+ puts "\n[1/7] GitHub CLI ์„ค์น˜ ํ™•์ธ".colorize(:blue)
21
+ check_github_cli
22
+
23
+ puts "\n[2/7] GitHub ๋กœ๊ทธ์ธ ํ™•์ธ".colorize(:blue)
24
+ check_github_auth
25
+
26
+ puts "\n[3/7] ์ปจํ…Œ์ด๋„ˆ ๋ ˆ์ง€์ŠคํŠธ๋ฆฌ ๊ถŒํ•œ ํ™•์ธ".colorize(:blue)
27
+ check_container_registry_permission
28
+
29
+ puts "\n[4/7] Git ์ €์žฅ์†Œ ์ดˆ๊ธฐํ™”".colorize(:blue)
30
+ init_git_repo
31
+
32
+ puts "\n[5/7] GitHub ์ €์žฅ์†Œ ์ƒ์„ฑ".colorize(:blue)
33
+ create_github_repository
34
+
35
+ puts "\n[6/7] ์ปจํ…Œ์ด๋„ˆ ๋ ˆ์ง€์ŠคํŠธ๋ฆฌ ์„ค์ •".colorize(:blue)
36
+ create_container_registry
37
+
38
+ puts "\n[7/7] ๋ฐฐํฌ ์„ค์ • ํŒŒ์ผ ์ƒ์„ฑ".colorize(:blue)
39
+ create_deploy_config
40
+
41
+ puts "\n๐ŸŽ‰ ๋ชจ๋“  ์„ค์ •์ด ์™„๋ฃŒ๋˜์—ˆ์Šต๋‹ˆ๋‹ค!".colorize(:green)
42
+ puts "\n๋‹ค์Œ ์ •๋ณด๊ฐ€ ์„ค์ •๋˜์—ˆ์Šต๋‹ˆ๋‹ค:".colorize(:yellow)
43
+ puts "โ€ข GitHub ์ €์žฅ์†Œ: https://github.com/#{@username}/#{@repo_name}".colorize(:cyan)
44
+ puts "โ€ข Container Registry: #{@registry_url}".colorize(:cyan)
45
+ puts "โ€ข ๋ฐฐํฌ ์„ค์ •: config/deploy.yml".colorize(:cyan)
46
+ end
47
+
48
+ private
49
+
50
+ def rails_project?
51
+ File.exist?("Gemfile") && File.exist?("config/application.rb")
52
+ end
53
+
54
+ def check_github_cli
55
+ if system("gh --version", out: File::NULL, err: File::NULL)
56
+ puts "โœ… GitHub CLI๊ฐ€ ์ด๋ฏธ ์„ค์น˜๋˜์–ด ์žˆ์Šต๋‹ˆ๋‹ค.".colorize(:green)
57
+ else
58
+ puts "๐Ÿ“ฆ GitHub CLI๋ฅผ ์„ค์น˜ํ•ฉ๋‹ˆ๋‹ค...".colorize(:yellow)
59
+ system("brew install gh")
60
+ puts "โœ… GitHub CLI ์„ค์น˜ ์™„๋ฃŒ.".colorize(:green)
61
+ end
62
+ end
63
+
64
+ def check_github_auth
65
+ auth_status = `gh auth status 2>&1`
66
+
67
+ unless $?.success?
68
+ puts "๐Ÿ”‘ GitHub ๋กœ๊ทธ์ธ์ด ํ•„์š”ํ•ฉ๋‹ˆ๋‹ค.".colorize(:yellow)
69
+ puts "๋‹ค์Œ ๋ช…๋ น์–ด๋ฅผ ์‹คํ–‰ํ•˜์—ฌ ๋กœ๊ทธ์ธํ•ด์ฃผ์„ธ์š”:".colorize(:yellow)
70
+ puts "gh auth login".colorize(:cyan)
71
+ exit 1
72
+ end
73
+
74
+ # ํ† ํฐ ๋งŒ๋ฃŒ ํ™•์ธ
75
+ if auth_status.include?("Token has expired") || auth_status.include?("authentication failed")
76
+ puts "โš ๏ธ GitHub ํ† ํฐ์ด ๋งŒ๋ฃŒ๋˜์—ˆ์Šต๋‹ˆ๋‹ค.".colorize(:yellow)
77
+ puts "๋‹ค์‹œ ๋กœ๊ทธ์ธํ•ด์ฃผ์„ธ์š”:".colorize(:yellow)
78
+ puts "gh auth login".colorize(:cyan)
79
+ exit 1
80
+ end
81
+
82
+ puts "โœ… GitHub์— ๋กœ๊ทธ์ธ๋˜์–ด ์žˆ์Šต๋‹ˆ๋‹ค.".colorize(:green)
83
+ end
84
+
85
+ def check_container_registry_permission
86
+ scopes = `gh auth status -t 2>&1`
87
+
88
+ # ํ† ํฐ ๋งŒ๋ฃŒ ํ™•์ธ (๊ถŒํ•œ ์ฒดํฌ ์‹œ์—๋„)
89
+ if scopes.include?("Token has expired") || scopes.include?("authentication failed")
90
+ puts "โš ๏ธ GitHub ํ† ํฐ์ด ๋งŒ๋ฃŒ๋˜์—ˆ์Šต๋‹ˆ๋‹ค.".colorize(:yellow)
91
+ puts "๋‹ค์‹œ ๋กœ๊ทธ์ธํ•ด์ฃผ์„ธ์š”:".colorize(:yellow)
92
+ puts "gh auth login".colorize(:cyan)
93
+ exit 1
94
+ end
95
+
96
+ unless scopes.include?("write:packages") || scopes.include?("admin:packages")
97
+ puts "โš ๏ธ ์ปจํ…Œ์ด๋„ˆ ๋ ˆ์ง€์ŠคํŠธ๋ฆฌ ๊ถŒํ•œ์ด ์—†์Šต๋‹ˆ๋‹ค.".colorize(:yellow)
98
+ puts "\nTayo๊ฐ€ ์ •์ƒ ์ž‘๋™ํ•˜๊ธฐ ์œ„ํ•ด ๋‹ค์Œ ๊ถŒํ•œ๋“ค์ด ํ•„์š”ํ•ฉ๋‹ˆ๋‹ค:".colorize(:yellow)
99
+ puts "โ€ข repo - GitHub ์ €์žฅ์†Œ ์ƒ์„ฑ ๋ฐ ๊ด€๋ฆฌ".colorize(:yellow)
100
+ puts "โ€ข read:org - ์กฐ์ง ์ •๋ณด ์ฝ๊ธฐ".colorize(:yellow)
101
+ puts "โ€ข write:packages - Docker ์ด๋ฏธ์ง€๋ฅผ Container Registry์— ํ‘ธ์‹œ".colorize(:yellow)
102
+ puts "\nํ† ํฐ ์ƒ์„ฑ ํŽ˜์ด์ง€๋ฅผ ์—ฝ๋‹ˆ๋‹ค...".colorize(:cyan)
103
+
104
+ project_name = File.basename(Dir.pwd)
105
+ token_description = "Tayo%20-%20#{project_name}"
106
+ token_url = "https://github.com/settings/tokens/new?scopes=repo,read:org,write:packages&description=#{token_description}"
107
+ system("open '#{token_url}'")
108
+
109
+ puts "\nโœ… ๋ธŒ๋ผ์šฐ์ €์—์„œ GitHub ํ† ํฐ ์ƒ์„ฑ ํŽ˜์ด์ง€๊ฐ€ ์—ด๋ ธ์Šต๋‹ˆ๋‹ค.".colorize(:green)
110
+ puts "๐Ÿ“Œ ํ•„์š”ํ•œ ๊ถŒํ•œ๋“ค์ด ์ด๋ฏธ ์ฒดํฌ๋˜์–ด ์žˆ์Šต๋‹ˆ๋‹ค:".colorize(:green)
111
+ puts " โ€ข repo - ์ €์žฅ์†Œ ์ƒ์„ฑ ๋ฐ ๊ด€๋ฆฌ".colorize(:gray)
112
+ puts " โ€ข read:org - ์กฐ์ง ์ •๋ณด ์ฝ๊ธฐ".colorize(:gray)
113
+ puts " โ€ข write:packages - Container Registry ์ ‘๊ทผ".colorize(:gray)
114
+
115
+ puts "\n๋‹ค์Œ ๋‹จ๊ณ„๋ฅผ ๋”ฐ๋ผ์ฃผ์„ธ์š”:".colorize(:yellow)
116
+ puts "1. ํŽ˜์ด์ง€ ํ•˜๋‹จ์˜ 'Generate token' ๋ฒ„ํŠผ์„ ํด๋ฆญํ•˜์„ธ์š”".colorize(:cyan)
117
+ puts "2. ์ƒ์„ฑ๋œ ํ† ํฐ์„ ๋ณต์‚ฌํ•˜์„ธ์š”".colorize(:cyan)
118
+ puts "3. ์•„๋ž˜์— ํ† ํฐ์„ ๋ถ™์—ฌ๋„ฃ์œผ์„ธ์š”:".colorize(:cyan)
119
+
120
+ print "\nํ† ํฐ ์ž…๋ ฅ: ".colorize(:yellow)
121
+ token = STDIN.gets.chomp
122
+
123
+ if token.empty?
124
+ puts "โŒ ํ† ํฐ์ด ์ž…๋ ฅ๋˜์ง€ ์•Š์•˜์Šต๋‹ˆ๋‹ค.".colorize(:red)
125
+ exit 1
126
+ end
127
+
128
+ # ํ† ํฐ์„ ์ž„์‹œ ํŒŒ์ผ์— ์ €์žฅํ•˜๊ณ  gh auth login ์‹คํ–‰
129
+ require 'tempfile'
130
+ Tempfile.create('github_token') do |f|
131
+ f.write(token)
132
+ f.flush
133
+
134
+ puts "\n๐Ÿ” GitHub์— ๋กœ๊ทธ์ธ ์ค‘...".colorize(:yellow)
135
+ if system("gh auth login --with-token < #{f.path}")
136
+ puts "โœ… GitHub ๋กœ๊ทธ์ธ์— ์„ฑ๊ณตํ–ˆ์Šต๋‹ˆ๋‹ค!".colorize(:green)
137
+ puts "\n๋‹ค์‹œ 'tayo gh' ๋ช…๋ น์„ ์‹คํ–‰ํ•ด์ฃผ์„ธ์š”.".colorize(:cyan)
138
+ else
139
+ puts "โŒ GitHub ๋กœ๊ทธ์ธ์— ์‹คํŒจํ–ˆ์Šต๋‹ˆ๋‹ค.".colorize(:red)
140
+ end
141
+ end
142
+
143
+ exit 0
144
+ end
145
+
146
+ puts "โœ… ์ปจํ…Œ์ด๋„ˆ ๋ ˆ์ง€์ŠคํŠธ๋ฆฌ ๊ถŒํ•œ์ด ํ™•์ธ๋˜์—ˆ์Šต๋‹ˆ๋‹ค.".colorize(:green)
147
+ end
148
+
149
+ def init_git_repo
150
+ unless Dir.exist?(".git")
151
+ Git.init(".")
152
+ puts "โœ… Git ์ €์žฅ์†Œ๋ฅผ ์ดˆ๊ธฐํ™”ํ–ˆ์Šต๋‹ˆ๋‹ค.".colorize(:green)
153
+ else
154
+ puts "โ„น๏ธ Git ์ €์žฅ์†Œ๊ฐ€ ์ด๋ฏธ ์ดˆ๊ธฐํ™”๋˜์–ด ์žˆ์Šต๋‹ˆ๋‹ค.".colorize(:yellow)
155
+ end
156
+
157
+ git = Git.open(".")
158
+
159
+ # HEAD ์ปค๋ฐ‹์ด ์žˆ๋Š”์ง€ ํ™•์ธ
160
+ has_commits = begin
161
+ git.log.count > 0
162
+ rescue Git::GitExecuteError
163
+ false
164
+ end
165
+
166
+ # git status๋กœ ๋ณ€๊ฒฝ์‚ฌํ•ญ ํ™•์ธ (HEAD๊ฐ€ ์—†์œผ๋ฉด ๋‹ค๋ฅธ ๋ฐฉ๋ฒ• ์‚ฌ์šฉ)
167
+ has_changes = if has_commits
168
+ git.status.untracked.any? || git.status.changed.any?
169
+ else
170
+ # HEAD๊ฐ€ ์—†์„ ๋•Œ๋Š” ์›Œํ‚น ๋””๋ ‰ํ† ๋ฆฌ์— ํŒŒ์ผ์ด ์žˆ๋Š”์ง€ ํ™•์ธ
171
+ Dir.glob("*", File::FNM_DOTMATCH).reject { |f| f == "." || f == ".." || f == ".git" }.any?
172
+ end
173
+
174
+ if has_changes
175
+ git.add(all: true)
176
+ git.commit("init")
177
+ puts "โœ… ์ดˆ๊ธฐ ์ปค๋ฐ‹์„ ์ƒ์„ฑํ–ˆ์Šต๋‹ˆ๋‹ค.".colorize(:green)
178
+ else
179
+ puts "โ„น๏ธ ์ปค๋ฐ‹ํ•  ๋ณ€๊ฒฝ์‚ฌํ•ญ์ด ์—†์Šต๋‹ˆ๋‹ค.".colorize(:yellow)
180
+ end
181
+ end
182
+
183
+ def create_github_repository
184
+ repo_name = File.basename(Dir.pwd)
185
+ username = `gh api user -q .login`.strip
186
+
187
+ # ์กฐ์ง ๋ชฉ๋ก ๊ฐ€์ ธ์˜ค๊ธฐ
188
+ orgs_json = `gh api user/orgs -q '.[].login' 2>/dev/null`
189
+ orgs = orgs_json.strip.split("\n").reject(&:empty?)
190
+
191
+ owner = username
192
+
193
+ if orgs.any?
194
+ prompt = TTY::Prompt.new
195
+ choices = ["#{username} (๊ฐœ์ธ ๊ณ„์ •)"] + orgs.map { |org| "#{org} (์กฐ์ง)" }
196
+
197
+ selection = prompt.select("๐Ÿข ์ €์žฅ์†Œ๋ฅผ ์ƒ์„ฑํ•  ์œ„์น˜๋ฅผ ์„ ํƒํ•˜์„ธ์š”:", choices)
198
+
199
+ if selection != "#{username} (๊ฐœ์ธ ๊ณ„์ •)"
200
+ owner = selection.split(" ").first
201
+ end
202
+ end
203
+
204
+ # ์ €์žฅ์†Œ ์กด์žฌ ์—ฌ๋ถ€ ํ™•์ธ
205
+ repo_exists = system("gh repo view #{owner}/#{repo_name}", out: File::NULL, err: File::NULL)
206
+
207
+ if repo_exists
208
+ puts "โ„น๏ธ GitHub ์ €์žฅ์†Œ๊ฐ€ ์ด๋ฏธ ์กด์žฌํ•ฉ๋‹ˆ๋‹ค: https://github.com/#{owner}/#{repo_name}".colorize(:yellow)
209
+ @repo_name = repo_name
210
+ @username = owner
211
+ else
212
+ create_cmd = if owner == username
213
+ "gh repo create #{repo_name} --private --source=. --remote=origin --push"
214
+ else
215
+ "gh repo create #{owner}/#{repo_name} --private --source=. --remote=origin --push"
216
+ end
217
+
218
+ result = system(create_cmd)
219
+
220
+ if result
221
+ puts "โœ… GitHub ์ €์žฅ์†Œ๋ฅผ ์ƒ์„ฑํ–ˆ์Šต๋‹ˆ๋‹ค: https://github.com/#{owner}/#{repo_name}".colorize(:green)
222
+ @repo_name = repo_name
223
+ @username = owner
224
+ else
225
+ puts "โŒ GitHub ์ €์žฅ์†Œ ์ƒ์„ฑ์— ์‹คํŒจํ–ˆ์Šต๋‹ˆ๋‹ค.".colorize(:red)
226
+ exit 1
227
+ end
228
+ end
229
+ end
230
+
231
+ def create_container_registry
232
+ # Docker ์ด๋ฏธ์ง€ ํƒœ๊ทธ๋Š” ์†Œ๋ฌธ์ž์—ฌ์•ผ ํ•จ
233
+ registry_url = "ghcr.io/#{@username.downcase}/#{@repo_name.downcase}"
234
+ @registry_url = registry_url
235
+
236
+ puts "โœ… ์ปจํ…Œ์ด๋„ˆ ๋ ˆ์ง€์ŠคํŠธ๋ฆฌ๊ฐ€ ์„ค์ •๋˜์—ˆ์Šต๋‹ˆ๋‹ค.".colorize(:green)
237
+ puts " URL: #{registry_url}".colorize(:gray)
238
+ puts " โ„น๏ธ ์ปจํ…Œ์ด๋„ˆ ๋ ˆ์ง€์ŠคํŠธ๋ฆฌ๋Š” ์ฒซ ์ด๋ฏธ์ง€ ํ‘ธ์‹œ ์‹œ ์ž๋™์œผ๋กœ ์ƒ์„ฑ๋ฉ๋‹ˆ๋‹ค.".colorize(:gray)
239
+
240
+ # Docker๋กœ GitHub Container Registry์— ๋กœ๊ทธ์ธ
241
+ puts "\n๐Ÿณ Docker๋กœ GitHub Container Registry์— ๋กœ๊ทธ์ธํ•ฉ๋‹ˆ๋‹ค...".colorize(:yellow)
242
+
243
+ # ํ˜„์žฌ GitHub ํ† ํฐ ๊ฐ€์ ธ์˜ค๊ธฐ
244
+ token = `gh auth token`.strip
245
+
246
+ if token.empty?
247
+ puts "โŒ GitHub ํ† ํฐ์„ ๊ฐ€์ ธ์˜ฌ ์ˆ˜ ์—†์Šต๋‹ˆ๋‹ค.".colorize(:red)
248
+ return
249
+ end
250
+
251
+ # Docker login ์‹คํ–‰
252
+ login_cmd = "echo #{token} | docker login ghcr.io -u #{@username} --password-stdin"
253
+
254
+ if system(login_cmd)
255
+ puts "โœ… Docker ๋กœ๊ทธ์ธ์— ์„ฑ๊ณตํ–ˆ์Šต๋‹ˆ๋‹ค!".colorize(:green)
256
+ puts " Registry: ghcr.io".colorize(:gray)
257
+ puts " Username: #{@username}".colorize(:gray)
258
+ else
259
+ puts "โŒ Docker ๋กœ๊ทธ์ธ์— ์‹คํŒจํ–ˆ์Šต๋‹ˆ๋‹ค.".colorize(:red)
260
+ puts " ์ˆ˜๋™์œผ๋กœ ๋‹ค์Œ ๋ช…๋ น์„ ์‹คํ–‰ํ•ด์ฃผ์„ธ์š”:".colorize(:yellow)
261
+ puts " docker login ghcr.io".colorize(:cyan)
262
+ end
263
+ end
264
+
265
+ def create_deploy_config
266
+ config_dir = "config"
267
+ Dir.mkdir(config_dir) unless Dir.exist?(config_dir)
268
+
269
+ if File.exist?("config/deploy.yml")
270
+ puts "โ„น๏ธ ๊ธฐ์กด config/deploy.yml ํŒŒ์ผ์„ ์—…๋ฐ์ดํŠธํ•ฉ๋‹ˆ๋‹ค.".colorize(:yellow)
271
+ update_kamal_config
272
+ else
273
+ puts "โœ… config/deploy.yml ํŒŒ์ผ์„ ์ƒ์„ฑํ–ˆ์Šต๋‹ˆ๋‹ค.".colorize(:green)
274
+ create_tayo_config
275
+ end
276
+ end
277
+
278
+ private
279
+
280
+ def update_kamal_config
281
+ content = File.read("config/deploy.yml")
282
+
283
+ # ์ด๋ฏธ์ง€ ์„ค์ • ์—…๋ฐ์ดํŠธ (ghcr.io ์ค‘๋ณต ์ œ๊ฑฐ)
284
+ # @registry_url์€ ์ด๋ฏธ ghcr.io๋ฅผ ํฌํ•จํ•˜๊ณ  ์žˆ์œผ๋ฏ€๋กœ, ๊ทธ๋Œ€๋กœ ์‚ฌ์šฉ
285
+ content.gsub!(/^image:\s+.*$/, "image: #{@registry_url}")
286
+
287
+ # registry ์„น์…˜ ์—…๋ฐ์ดํŠธ
288
+ if content.include?("registry:")
289
+ # ๊ธฐ์กด registry ์„น์…˜ ์ˆ˜์ •
290
+ # server ๋ผ์ธ์ด ์ฃผ์„์ฒ˜๋ฆฌ๋˜์–ด ์žˆ๋Š”์ง€ ํ™•์ธ
291
+ if content.match?(/^\s*#\s*server:/)
292
+ content.gsub!(/^\s*#\s*server:\s*.*$/, " server: ghcr.io")
293
+ elsif content.match?(/^\s*server:/)
294
+ content.gsub!(/^\s*server:\s*.*$/, " server: ghcr.io")
295
+ else
296
+ # server ๋ผ์ธ์ด ์—†์œผ๋ฉด username ์œ„์— ์ถ”๊ฐ€
297
+ content.gsub!(/(\s*username:\s+)/, " server: ghcr.io\n\\1")
298
+ end
299
+ # username๋„ ์†Œ๋ฌธ์ž๋กœ ๋ณ€ํ™˜
300
+ content.gsub!(/^\s*username:\s+.*$/, " username: #{@username.downcase}")
301
+ else
302
+ # registry ์„น์…˜ ์ถ”๊ฐ€
303
+ registry_config = "\n# Container registry configuration\nregistry:\n server: ghcr.io\n username: #{@username.downcase}\n password:\n - KAMAL_REGISTRY_PASSWORD\n"
304
+ content.gsub!(/^# Credentials for your image host\.\nregistry:.*?^$/m, registry_config)
305
+ end
306
+
307
+ File.write("config/deploy.yml", content)
308
+
309
+ # GitHub ํ† ํฐ์„ Kamal secrets ํŒŒ์ผ์— ์„ค์ •
310
+ setup_kamal_secrets
311
+
312
+ puts "โœ… Container Registry ์„ค์ •์ด ์—…๋ฐ์ดํŠธ๋˜์—ˆ์Šต๋‹ˆ๋‹ค:".colorize(:green)
313
+ puts " โ€ข ์ด๋ฏธ์ง€: #{@registry_url}".colorize(:gray)
314
+ puts " โ€ข ๋ ˆ์ง€์ŠคํŠธ๋ฆฌ ์„œ๋ฒ„: ghcr.io".colorize(:gray)
315
+ puts " โ€ข ์‚ฌ์šฉ์ž๋ช…: #{@username}".colorize(:gray)
316
+ end
317
+
318
+ def setup_kamal_secrets
319
+ # .kamal ๋””๋ ‰ํ† ๋ฆฌ ์ƒ์„ฑ
320
+ Dir.mkdir(".kamal") unless Dir.exist?(".kamal")
321
+
322
+ # ํ˜„์žฌ GitHub ํ† ํฐ ๊ฐ€์ ธ์˜ค๊ธฐ
323
+ token_output = `gh auth token 2>/dev/null`
324
+
325
+ if $?.success? && !token_output.strip.empty?
326
+ token = token_output.strip
327
+ secrets_file = ".kamal/secrets"
328
+
329
+ # ๊ธฐ์กด secrets ํŒŒ์ผ ์ฝ๊ธฐ (์žˆ๋‹ค๋ฉด)
330
+ existing_content = File.exist?(secrets_file) ? File.read(secrets_file) : ""
331
+
332
+ # KAMAL_REGISTRY_PASSWORD๊ฐ€ ์ด๋ฏธ ์žˆ๋Š”์ง€ ํ™•์ธ
333
+ if existing_content.include?("KAMAL_REGISTRY_PASSWORD")
334
+ # ๊ธฐ์กด ๊ฐ’ ์—…๋ฐ์ดํŠธ
335
+ updated_content = existing_content.gsub(/^KAMAL_REGISTRY_PASSWORD=.*$/, "KAMAL_REGISTRY_PASSWORD=#{token}")
336
+ else
337
+ # ์ƒˆ๋กœ ์ถ”๊ฐ€
338
+ updated_content = existing_content.empty? ? "KAMAL_REGISTRY_PASSWORD=#{token}\n" : "#{existing_content.chomp}\nKAMAL_REGISTRY_PASSWORD=#{token}\n"
339
+ end
340
+
341
+ File.write(secrets_file, updated_content)
342
+ puts "โœ… GitHub ํ† ํฐ์ด .kamal/secrets์— ์„ค์ •๋˜์—ˆ์Šต๋‹ˆ๋‹ค.".colorize(:green)
343
+
344
+ # .gitignore์— secrets ํŒŒ์ผ ์ถ”๊ฐ€
345
+ add_to_gitignore(".kamal/secrets")
346
+ else
347
+ puts "โš ๏ธ GitHub ํ† ํฐ์„ ๊ฐ€์ ธ์˜ฌ ์ˆ˜ ์—†์Šต๋‹ˆ๋‹ค. ์ˆ˜๋™์œผ๋กœ ์„ค์ •ํ•ด์ฃผ์„ธ์š”:".colorize(:yellow)
348
+ puts " echo 'KAMAL_REGISTRY_PASSWORD=your_github_token' >> .kamal/secrets".colorize(:cyan)
349
+ end
350
+ end
351
+
352
+ def add_to_gitignore(file_path)
353
+ gitignore_file = ".gitignore"
354
+
355
+ if File.exist?(gitignore_file)
356
+ content = File.read(gitignore_file)
357
+ unless content.include?(file_path)
358
+ File.write(gitignore_file, "#{content.chomp}\n#{file_path}\n")
359
+ puts "โœ… .gitignore์— #{file_path}๋ฅผ ์ถ”๊ฐ€ํ–ˆ์Šต๋‹ˆ๋‹ค.".colorize(:green)
360
+ end
361
+ else
362
+ File.write(gitignore_file, "#{file_path}\n")
363
+ puts "โœ… .gitignore ํŒŒ์ผ์„ ์ƒ์„ฑํ•˜๊ณ  #{file_path}๋ฅผ ์ถ”๊ฐ€ํ–ˆ์Šต๋‹ˆ๋‹ค.".colorize(:green)
364
+ end
365
+ end
366
+
367
+ def create_tayo_config
368
+ deploy_config = {
369
+ "production" => {
370
+ "registry" => @registry_url,
371
+ "repository" => "https://github.com/#{@username}/#{@repo_name}",
372
+ "server" => {
373
+ "host" => "your-home-server.local",
374
+ "user" => "deploy",
375
+ "port" => 22
376
+ },
377
+ "environment" => {
378
+ "RAILS_ENV" => "production",
379
+ "RAILS_MASTER_KEY" => "your-master-key"
380
+ }
381
+ }
382
+ }
383
+
384
+ File.write("config/deploy.yml", deploy_config.to_yaml)
385
+ puts " โš ๏ธ ์„œ๋ฒ„ ์ •๋ณด์™€ ํ™˜๊ฒฝ ๋ณ€์ˆ˜๋ฅผ ์„ค์ •ํ•ด์ฃผ์„ธ์š”.".colorize(:yellow)
386
+ end
387
+ end
388
+ end
389
+ end