this repo has no description
1#!/usr/bin/env ruby
2
3require 'optparse'
4require 'octokit'
5require 'fileutils'
6require 'open3'
7require 'haikunator'
8require 'yaml'
9require 'replicate' # Try just the namespace
10require 'down'
11
12class RepoInitializer
13 def initialize
14 @options = {
15 verbose: false,
16 name: nil,
17 template: nil
18 }
19 load_config
20 end
21
22 def run(args)
23 parse_options(args)
24 # Make sure we have a template repo before proceeding
25 if !@options[:template] && config_exists?
26 config = YAML.load_file(File.expand_path('~/.github-init-config.yml'))
27 @options[:template] = config['template_repo']
28 end
29
30 if !@options[:template]
31 puts "Error: No template repository specified. Please provide it in config file or via --template parameter"
32 exit 1
33 end
34
35 create_and_setup_repo
36 rescue StandardError => e
37 puts "Error: #{e.message}"
38 exit 1
39 end
40
41 def config_exists?
42 File.exist?(File.expand_path('~/.github-init-config.yml'))
43 end
44
45 private
46
47 def load_config
48 config_path = File.expand_path('~/.github-init-config.yml')
49 return unless File.exist?(config_path)
50
51 config = YAML.load_file(config_path)
52 @github_token = config['github_token']
53 @bot_git_email = config['bot_git_email']
54 @bot_git_name = config['bot_git_name']
55 @github_username = config['github_username']
56 @replicate_token = config['replicate_token']
57
58 # Configure Replicate with the token
59 Replicate.configure do |config|
60 config.api_token = @replicate_token
61 end
62 end
63
64 def parse_options(args)
65 OptionParser.new do |opts|
66 opts.banner = "Usage: #{File.basename($PROGRAM_NAME)} [options]"
67
68 # Repository options
69 opts.on("-n", "--name NAME", "Repository name") do |name|
70 @options[:name] = name
71 end
72
73 opts.on("-t", "--template REPO", "Template repository (e.g., username/repo)") do |repo|
74 @options[:template] = repo
75 end
76
77 # GitHub configuration
78 opts.on("--github-token TOKEN", "GitHub API token") do |token|
79 @github_token = token
80 end
81
82 opts.on("--github-username USERNAME", "GitHub username") do |username|
83 @github_username = username
84 end
85
86 # Git configuration
87 opts.on("--git-email EMAIL", "Git email for commit signing") do |email|
88 @bot_git_email = email
89 end
90
91 opts.on("--git-name NAME", "Git name for commit signing") do |name|
92 @bot_git_name = name
93 end
94
95 # Image generation
96 opts.on("--replicate-token TOKEN", "Replicate API token for image generation") do |token|
97 @replicate_token = token
98 end
99
100 # Other options
101 opts.on("-v", "--verbose", "Enable verbose output") do
102 @options[:verbose] = true
103 end
104
105 opts.on("-g", "--generate", "Generate a new name (can be used multiple times)") do
106 generate_and_show_name
107 exit
108 end
109
110 opts.on("-h", "--help", "Show this message") do
111 puts opts
112 exit
113 end
114 end.parse!(args)
115
116 validate_configuration
117 end
118
119 def validate_configuration
120 # Only validate if arguments were provided
121 return unless ARGV.any?
122
123 missing = []
124 missing << "GitHub token" unless @github_token
125 missing << "GitHub username" unless @github_username
126 missing << "Git email" unless @bot_git_email
127 missing << "Git name" unless @bot_git_name
128 missing << "Template repository" unless @options[:template]
129 missing << "Replicate token" unless @replicate_token
130
131 unless missing.empty?
132 puts "Missing required configuration. Please provide either in config file or as parameters:"
133 missing.each { |m| puts "- #{m}" }
134 exit 1
135 end
136 end
137
138 def generate_and_show_name
139 5.times do
140 puts "Generated name option: #{Haikunator.haikunate(0)}"
141 end
142 end
143
144 def prompt_for_name
145 loop do
146 suggested_name = Haikunator.haikunate(0)
147 print "Suggested repository name: #{suggested_name}\nUse this name? (y/n/q to quit) "
148
149 case gets.chomp.downcase
150 when 'y'
151 return suggested_name
152 when 'q'
153 exit
154 end
155 end
156 end
157
158 def create_and_setup_repo
159 @repo_name = @options[:name] || prompt_for_name
160
161 puts "Creating repository: #{@repo_name}"
162
163 # Create GitHub repository
164 client = Octokit::Client.new(access_token: @github_token)
165 repo = client.create_repository(
166 @repo_name,
167 private: true,
168 auto_init: false
169 )
170
171 # Clone template repository
172 clone_and_setup_repo(repo.ssh_url)
173
174 puts "Repository successfully created and initialized!"
175 puts "GitHub URL: #{repo.html_url}"
176 end
177
178 def generate_readme_image
179 puts "Generating project banner image..."
180
181 # Create a prompt based on the repository name
182 prompt = "A modern, minimalist logo for a software project called #{@repo_name}, " \
183 "digital art style, clean design, white background"
184
185 # Use the model
186 model = Replicate.client.retrieve_model("stability-ai/sdxl")
187 version = model.latest_version
188
189 # Run prediction
190 prediction = version.predict(
191 prompt: prompt,
192 negative_prompt: "text, words, letters, blurry, low quality",
193 width: 1200,
194 height: 400,
195 num_outputs: 1,
196 scheduler: "K_EULER",
197 num_inference_steps: 50,
198 guidance_scale: 7.5
199 )
200
201 # Download the generated image
202 image_url = prediction.output # Changed from prediction[0]
203 tempfile = Down.download(image_url)
204
205 # Move the image to the assets directory
206 FileUtils.mkdir_p('assets')
207 FileUtils.mv(tempfile.path, 'assets/banner.png')
208
209 puts "Banner image generated successfully!"
210 end
211
212 def update_readme_with_banner
213 readme_path = 'README.md'
214 return unless File.exist?(readme_path)
215
216 content = File.read(readme_path)
217 banner_markdown = "\n\n"
218
219 # Add banner at the top of the README
220 if content.include?('![Project Banner]')
221 content.sub!(/!\[Project Banner\].*$\n\n/m, banner_markdown)
222 else
223 content = banner_markdown + content
224 end
225
226 File.write(readme_path, content)
227 end
228
229 def clone_and_setup_repo(ssh_url)
230 puts "Debug: Using template repository: #{@options[:template]}" if @options[:verbose]
231
232 # Create directory and initialize git
233 FileUtils.mkdir_p(@repo_name)
234 Dir.chdir(@repo_name) do
235 # First initialize a new git repository
236 run_command('git init')
237
238 # Configure bot user for signing commits
239 run_command("git config user.email \"#{@bot_git_email}\"")
240 run_command("git config user.name \"#{@bot_git_name}\"")
241
242 # Clone template repository contents
243 clone_cmd = "git pull git@github.com:#{@options[:template]}.git main"
244 puts "Debug: Running clone command: #{clone_cmd}" if @options[:verbose]
245 run_command(clone_cmd)
246
247 # Generate and add banner image
248 generate_readme_image
249 update_readme_with_banner
250
251 # Add remote and push
252 run_command("git remote add origin #{ssh_url}")
253 run_command('git add .')
254 run_command('git commit -S -m "Initial commit"')
255 run_command('git branch -M main')
256 run_command('git push -u origin main')
257 end
258 end
259
260 def run_command(command)
261 puts "> #{command}" if @options[:verbose]
262
263 output, status = Open3.capture2e(command)
264 if status.success?
265 puts output if @options[:verbose]
266 else
267 raise "Command failed: #{output}"
268 end
269 end
270end
271
272# Handle interrupt gracefully
273Signal.trap("INT") do
274 puts "\nInterrupted by user"
275 exit 1
276end
277
278if __FILE__ == $PROGRAM_NAME
279 RepoInitializer.new.run(ARGV)
280end