discourse/script/theme-watcher
2018-03-13 17:39:53 +11:00

136 lines
3.0 KiB
Ruby
Executable File

#!/usr/bin/env ruby
require 'fileutils'
require 'pathname'
require 'tempfile'
require 'securerandom'
require 'minitar'
require 'zlib'
require 'find'
require 'net/http'
require 'net/http/post/multipart'
require 'uri'
require 'listen'
require 'json'
# Work in progress theme watcher for Discourse
#
# Monitor a theme directory locally and automatically keep it in sync with Discourse
def usage
puts "Usage: theme-watcher DIR SITE"
exit 1
end
WATCHER_SETTINGS_FILE = File.expand_path("~/.discourse-theme-watcher")
$api_key = ENV['DISCOURSE_API_KEY']
$dir = ARGV[0]
$site = ARGV[1]
if $site !~ /https?:\/\//i
$site = "http://#{$site}"
end
puts "Watching #{$dir} and uploading changes to #{$site}"
if !$api_key && File.exist?(WATCHER_SETTINGS_FILE)
$api_key = File.read(WATCHER_SETTINGS_FILE).strip
puts "Using previously stored api key in #{WATCHER_SETTINGS_FILE}"
end
if !$api_key
puts "No API key found in DISCOURSE_API_KEY env var enter your API key: "
$api_key = STDIN.gets.strip
puts "Would you like me to store this API key in #{WATCHER_SETTINGS_FILE}? (Yes|No)"
answer = STDIN.gets.strip
if answer =~ /y(es)?/i
File.write WATCHER_SETTINGS_FILE, $api_key
end
end
if !File.exist?("#{$dir}/about.json")
puts "No about.json file found in #{dir}!"
puts
usage
end
def compress_dir(gzip, dir)
sgz = Zlib::GzipWriter.new(File.open(gzip, 'wb'))
tar = Archive::Tar::Minitar::Output.new(sgz)
Dir.chdir(dir + "/../") do
Find.find(File.basename(dir)) do |x|
Find.prune if File.basename(x)[0] == ?.
next if File.directory?(x)
Minitar.pack_file(x, tar)
end
end
ensure
tar.close
sgz.close
end
def diagnose_errors(text)
count = 0
json = JSON.parse(text)
json["theme"]["theme_fields"].each do |row|
if (error = row["error"]) && error.length > 0
if count == 0
puts
end
count += 1
puts
puts "Error in #{row["target"]} #{row["name"]}} : #{row["error"]}"
puts
end
end
count
end
def upload_full_theme(dir, site)
filename = "#{Pathname.new(Dir.tmpdir).realpath}/bundle_#{SecureRandom.hex}.tar.gz"
compress_dir(filename, dir)
# new full upload endpoint
uri = URI.parse(site + "/admin/themes/import.json?api_key=#{$api_key}")
http = Net::HTTP.new(uri.host, uri.port)
File.open(filename) do |tgz|
request = Net::HTTP::Post::Multipart.new(
uri.request_uri,
"bundle" => UploadIO.new(tgz, "application/tar+gzip", "bundle.tar.gz"),
)
response = http.request(request)
if response.code.to_i == 201
if diagnose_errors(response.body) == 0
puts "(done)"
end
end
end
ensure
FileUtils.rm_f filename
end
upload_full_theme($dir, $site)
def resolve_file(path)
end
listener = Listen.to($dir) do |modified, added, removed|
if modified.length == 1 &&
added.length == 0 &&
removed.length == 0 &&
(target, name = resolve_file(modified[0]))
print "Updating #{target} #{name}"
else
print "Full re-sync is required, re-uploading theme"
upload_full_theme($dir, $site)
end
end
listener.start
sleep