DEV: Add options to theme install rake task - more options (#9394)
This commit is contained in:
parent
2aaf5cb2b8
commit
f07c4a781c
|
@ -1,18 +1,17 @@
|
||||||
# frozen_string_literal: true
|
# frozen_string_literal: true
|
||||||
|
|
||||||
class ThemesInstallTask
|
class ThemesInstallTask
|
||||||
def self.install(yml)
|
def self.install(themes)
|
||||||
counts = { installed: 0, updated: 0, skipped: 0, errors: 0 }
|
counts = { installed: 0, updated: 0, errors: 0 }
|
||||||
log = []
|
log = []
|
||||||
themes = YAML::load(yml)
|
themes.each do |name, val|
|
||||||
themes.each do |theme|
|
|
||||||
name = theme[0]
|
|
||||||
val = theme[1]
|
|
||||||
installer = new(val)
|
installer = new(val)
|
||||||
|
next if installer.url.nil?
|
||||||
|
|
||||||
if installer.theme_exists?
|
if installer.theme_exists?
|
||||||
log << "#{name}: is already installed"
|
installer.update
|
||||||
counts[:skipped] += 1
|
log << "#{name}: is already installed. Updating from remote."
|
||||||
|
counts[:updated] += 1
|
||||||
else
|
else
|
||||||
begin
|
begin
|
||||||
installer.install
|
installer.install
|
||||||
|
@ -32,7 +31,8 @@ class ThemesInstallTask
|
||||||
|
|
||||||
def initialize(url_or_options = nil)
|
def initialize(url_or_options = nil)
|
||||||
if url_or_options.is_a?(Hash)
|
if url_or_options.is_a?(Hash)
|
||||||
@url = url_or_options.fetch("url")
|
url_or_options.deep_symbolize_keys!
|
||||||
|
@url = url_or_options.fetch(:url, nil)
|
||||||
@options = url_or_options
|
@options = url_or_options
|
||||||
else
|
else
|
||||||
@url = url_or_options
|
@url = url_or_options
|
||||||
|
@ -41,14 +41,28 @@ class ThemesInstallTask
|
||||||
end
|
end
|
||||||
|
|
||||||
def theme_exists?
|
def theme_exists?
|
||||||
RemoteTheme
|
@remote_theme = RemoteTheme.find_by(remote_url: @url, branch: @options.fetch(:branch, nil))
|
||||||
.where(remote_url: url)
|
@theme = @remote_theme&.theme
|
||||||
.where(branch: options.fetch("branch", nil))
|
@theme.present?
|
||||||
.exists?
|
|
||||||
end
|
end
|
||||||
|
|
||||||
def install
|
def install
|
||||||
theme = RemoteTheme.import_theme(url, Discourse.system_user, private_key: options["private_key"], branch: options["branch"])
|
@theme = RemoteTheme.import_theme(@url, Discourse.system_user, private_key: @options[:private_key], branch: @options[:branch])
|
||||||
theme.set_default! if options.fetch("default", false)
|
@theme.set_default! if @options.fetch(:default, false)
|
||||||
|
add_component_to_all_themes
|
||||||
|
end
|
||||||
|
|
||||||
|
def update
|
||||||
|
@remote_theme.update_from_remote
|
||||||
|
add_component_to_all_themes
|
||||||
|
end
|
||||||
|
|
||||||
|
def add_component_to_all_themes
|
||||||
|
return if (!@options.fetch(:add_to_all_themes, false) || !@theme.component)
|
||||||
|
|
||||||
|
Theme.where(component: false).each do |parent_theme|
|
||||||
|
next if ChildTheme.where(parent_theme_id: parent_theme.id, child_theme_id: @theme.id).exists?
|
||||||
|
parent_theme.add_relative_theme!(:child, @theme)
|
||||||
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
|
@ -2,31 +2,41 @@
|
||||||
|
|
||||||
require 'yaml'
|
require 'yaml'
|
||||||
|
|
||||||
# == YAML file format
|
|
||||||
#
|
#
|
||||||
# 2 different formats are accepted:
|
# 2 different formats are accepted:
|
||||||
#
|
#
|
||||||
|
# == JSON format
|
||||||
|
#
|
||||||
|
# bin/rake themes:install -- '--{"discourse-something": "https://github.com/discourse/discourse-something"}'
|
||||||
|
# OR
|
||||||
|
# bin/rake themes:install -- '--{"discourse-something": {"url": "https://github.com/discourse/discourse-something", default: true}}'
|
||||||
|
#
|
||||||
|
# == YAML file formats
|
||||||
|
#
|
||||||
# theme_name: https://github.com/example/theme.git
|
# theme_name: https://github.com/example/theme.git
|
||||||
#
|
# OR
|
||||||
# theme_name:
|
# theme_name:
|
||||||
# url: https://github.com/example/theme.git
|
# url: https://github.com/example/theme_name.git
|
||||||
# branch: abc
|
# branch: "master"
|
||||||
# private_key: ...
|
# private_key: ""
|
||||||
# default: true
|
# default: false
|
||||||
|
# add_to_all_themes: false # only for components - install on every theme
|
||||||
#
|
#
|
||||||
# In the second form, only the url is required.
|
# In the first form, only the url is required.
|
||||||
#
|
#
|
||||||
desc "Install themes & theme components"
|
desc "Install themes & theme components"
|
||||||
task "themes:install" => :environment do
|
task "themes:install" => :environment do |task, args|
|
||||||
yml = (STDIN.tty?) ? '' : STDIN.read
|
theme_args = (STDIN.tty?) ? '' : STDIN.read
|
||||||
if yml == ''
|
use_json = theme_args == ''
|
||||||
puts
|
|
||||||
puts "Please specify a themes yml file"
|
|
||||||
puts "Example: rake themes:install < themes.yml"
|
|
||||||
exit 1
|
|
||||||
end
|
|
||||||
|
|
||||||
log, counts = ThemesInstallTask.install(yml)
|
theme_args = begin
|
||||||
|
use_json ? JSON.parse(ARGV.last.gsub('--', '')) : YAML::load(theme_args)
|
||||||
|
rescue
|
||||||
|
puts use_json ? "Invalid JSON input. \n#{ARGV.last}" : "Invalid YML: \n#{theme_args}"
|
||||||
|
exit 1
|
||||||
|
end
|
||||||
|
|
||||||
|
log, counts = ThemesInstallTask.install(theme_args)
|
||||||
|
|
||||||
puts log
|
puts log
|
||||||
|
|
||||||
|
@ -34,7 +44,6 @@ task "themes:install" => :environment do
|
||||||
puts "Results:"
|
puts "Results:"
|
||||||
puts " Installed: #{counts[:installed]}"
|
puts " Installed: #{counts[:installed]}"
|
||||||
puts " Updated: #{counts[:updated]}"
|
puts " Updated: #{counts[:updated]}"
|
||||||
puts " Skipped: #{counts[:skipped]}"
|
|
||||||
puts " Errors: #{counts[:errors]}"
|
puts " Errors: #{counts[:errors]}"
|
||||||
|
|
||||||
if counts[:errors] > 0
|
if counts[:errors] > 0
|
||||||
|
|
|
@ -8,75 +8,136 @@ describe ThemesInstallTask do
|
||||||
Discourse::Application.load_tasks
|
Discourse::Application.load_tasks
|
||||||
end
|
end
|
||||||
|
|
||||||
let(:github_repo) { 'https://github.com/example/theme.git' }
|
|
||||||
let(:branch) { 'master' }
|
|
||||||
|
|
||||||
describe '.new' do
|
describe '.new' do
|
||||||
context 'with url' do
|
def setup_git_repo(files)
|
||||||
subject { described_class.new(github_repo) }
|
dir = Dir.tmpdir
|
||||||
|
repo_dir = "#{dir}/#{SecureRandom.hex}"
|
||||||
it 'configures the url' do
|
`mkdir #{repo_dir}`
|
||||||
expect(subject.url).to eq github_repo
|
`cd #{repo_dir} && git init . `
|
||||||
|
`cd #{repo_dir} && git config user.email 'someone@cool.com'`
|
||||||
|
`cd #{repo_dir} && git config user.name 'The Cool One'`
|
||||||
|
`cd #{repo_dir} && git config commit.gpgsign 'false'`
|
||||||
|
files.each do |name, data|
|
||||||
|
FileUtils.mkdir_p(Pathname.new("#{repo_dir}/#{name}").dirname)
|
||||||
|
File.write("#{repo_dir}/#{name}", data)
|
||||||
|
`cd #{repo_dir} && git add #{name}`
|
||||||
end
|
end
|
||||||
|
`cd #{repo_dir} && git commit -am 'first commit'`
|
||||||
|
repo_dir
|
||||||
|
end
|
||||||
|
|
||||||
it 'initializes without options' do
|
THEME_NAME = "awesome theme"
|
||||||
expect(subject.options).to eq({})
|
|
||||||
|
def about_json(love_color: "FAFAFA", tertiary_low_color: "FFFFFF", color_scheme_name: "Amazing", about_url: "https://www.site.com/about", component: false)
|
||||||
|
<<~JSON
|
||||||
|
{
|
||||||
|
"name": "#{THEME_NAME}",
|
||||||
|
"about_url": "#{about_url}",
|
||||||
|
"license_url": "https://www.site.com/license",
|
||||||
|
"theme_version": "1.0",
|
||||||
|
"minimum_discourse_version": "1.0.0",
|
||||||
|
"assets": {
|
||||||
|
"font": "assets/font.woff2"
|
||||||
|
},
|
||||||
|
"component": "#{component}",
|
||||||
|
"color_schemes": {
|
||||||
|
"#{color_scheme_name}": {
|
||||||
|
"love": "#{love_color}",
|
||||||
|
"tertiary-low": "#{tertiary_low_color}"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"modifiers": {
|
||||||
|
"serialize_topic_excerpts": true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
JSON
|
||||||
|
end
|
||||||
|
|
||||||
|
let :scss_data do
|
||||||
|
"@font-face { font-family: magic; src: url($font)}; body {color: $color; content: $name;}"
|
||||||
|
end
|
||||||
|
|
||||||
|
let :theme_repo do
|
||||||
|
setup_git_repo(
|
||||||
|
"about.json" => about_json,
|
||||||
|
"desktop/desktop.scss" => scss_data,
|
||||||
|
"scss/oldpath.scss" => ".class2{color:blue}",
|
||||||
|
"stylesheets/file.scss" => ".class1{color:red}",
|
||||||
|
"stylesheets/empty.scss" => "",
|
||||||
|
"javascripts/discourse/controllers/test.js.es6" => "console.log('test');",
|
||||||
|
"common/header.html" => "I AM HEADER",
|
||||||
|
"common/random.html" => "I AM SILLY",
|
||||||
|
"common/embedded.scss" => "EMBED",
|
||||||
|
"assets/font.woff2" => "FAKE FONT",
|
||||||
|
"settings.yaml" => "boolean_setting: true",
|
||||||
|
"locales/en.yml" => "sometranslations"
|
||||||
|
)
|
||||||
|
end
|
||||||
|
|
||||||
|
let :component_repo do
|
||||||
|
setup_git_repo(
|
||||||
|
"about.json" => about_json(component: true),
|
||||||
|
"desktop/desktop.scss" => scss_data,
|
||||||
|
"scss/oldpath.scss" => ".class2{color:blue}",
|
||||||
|
"stylesheets/file.scss" => ".class1{color:red}",
|
||||||
|
"stylesheets/empty.scss" => "",
|
||||||
|
"javascripts/discourse/controllers/test.js.es6" => "console.log('test');",
|
||||||
|
"common/header.html" => "I AM HEADER",
|
||||||
|
"common/random.html" => "I AM SILLY",
|
||||||
|
"common/embedded.scss" => "EMBED",
|
||||||
|
"assets/font.woff2" => "FAKE FONT",
|
||||||
|
"settings.yaml" => "boolean_setting: true",
|
||||||
|
"locales/en.yml" => "sometranslations"
|
||||||
|
)
|
||||||
|
end
|
||||||
|
|
||||||
|
after do
|
||||||
|
`rm -fr #{theme_repo}`
|
||||||
|
`rm -fr #{component_repo}`
|
||||||
|
end
|
||||||
|
|
||||||
|
it 'gracefully fails' do
|
||||||
|
ThemesInstallTask.install("nothing": "fail!")
|
||||||
|
expect(Theme.where(name: "fail!").exists?).to eq(false)
|
||||||
|
end
|
||||||
|
|
||||||
|
describe "no options" do
|
||||||
|
it 'installs a theme' do
|
||||||
|
ThemesInstallTask.install("some_theme": theme_repo)
|
||||||
|
expect(Theme.where(name: THEME_NAME).exists?).to eq(true)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
context 'with options' do
|
describe "with options" do
|
||||||
subject { described_class.new(options) }
|
it 'installs a theme from only a url' do
|
||||||
let(:options) { { 'url' => github_repo, 'branch' => branch } }
|
ThemesInstallTask.install({ "some_theme": { "url": theme_repo } })
|
||||||
|
expect(Theme.where(name: THEME_NAME).exists?).to eq(true)
|
||||||
it 'configures the url' do
|
|
||||||
expect(subject.url).to eq github_repo
|
|
||||||
end
|
end
|
||||||
|
|
||||||
it 'initializes options' do
|
it 'does not set the theme to default if the key/value is not present' do
|
||||||
expect(subject.options).to eq("url" => github_repo, "branch" => branch)
|
ThemesInstallTask.install({ "some_theme": { "url": theme_repo } })
|
||||||
end
|
theme = Theme.find_by(name: THEME_NAME)
|
||||||
end
|
expect(theme.default?).to eq(false)
|
||||||
end
|
|
||||||
|
|
||||||
describe '#theme_exists?' do
|
|
||||||
let(:theme) { Fabricate(:theme) }
|
|
||||||
subject { described_class.new(options) }
|
|
||||||
|
|
||||||
context 'without branch' do
|
|
||||||
let(:options) { github_repo }
|
|
||||||
|
|
||||||
it 'returns true when a branchless theme exists' do
|
|
||||||
theme.create_remote_theme(remote_url: github_repo)
|
|
||||||
expect(subject.theme_exists?).to be true
|
|
||||||
end
|
end
|
||||||
|
|
||||||
it 'returns false when the url exists but with a branch' do
|
it 'sets the theme to default if the key/value is true' do
|
||||||
theme.create_remote_theme(remote_url: github_repo, branch: branch)
|
ThemesInstallTask.install({ "some_theme": { "url": theme_repo, default: true } })
|
||||||
expect(subject.theme_exists?).to be false
|
theme = Theme.find_by(name: THEME_NAME)
|
||||||
|
expect(theme.default?).to eq(true)
|
||||||
end
|
end
|
||||||
|
|
||||||
it 'returns false when it doesnt exist' do
|
it 'installs theme components, but does not add them to themes' do
|
||||||
theme.create_remote_theme(remote_url: 'https://github.com/example/different_theme.git')
|
ThemesInstallTask.install({ "some_theme": { "url": component_repo } })
|
||||||
expect(subject.theme_exists?).to be false
|
theme = Theme.find_by(name: THEME_NAME)
|
||||||
end
|
expect(theme.component).to eq(true)
|
||||||
end
|
|
||||||
|
|
||||||
context 'with branch' do
|
|
||||||
let(:options) { { 'url' => github_repo, 'branch' => branch } }
|
|
||||||
|
|
||||||
it 'returns false when a branchless theme exists' do
|
|
||||||
theme.create_remote_theme(remote_url: github_repo)
|
|
||||||
expect(subject.theme_exists?).to be false
|
|
||||||
end
|
end
|
||||||
|
|
||||||
it 'returns true when the url exists with a branch' do
|
it 'adds component to all themes if "add_to_all_themes" is true' do
|
||||||
theme.create_remote_theme(remote_url: github_repo, branch: branch)
|
ThemesInstallTask.install({ "some_theme": { "url": component_repo, add_to_all_themes: true } })
|
||||||
expect(subject.theme_exists?).to be true
|
theme = Theme.find_by(name: THEME_NAME)
|
||||||
end
|
Theme.where(component: false).each do |parent_theme|
|
||||||
|
expect(ChildTheme.find_by(parent_theme_id: parent_theme.id, child_theme_id: theme.id).nil?).to eq(false)
|
||||||
it 'returns false when it doesnt exist' do
|
end
|
||||||
theme.create_remote_theme(remote_url: 'https://github.com/example/different_theme.git')
|
|
||||||
expect(subject.theme_exists?).to be false
|
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
Loading…
Reference in New Issue