Skip to content

Commit

Permalink
FEATURE: Rake themes installer (#7848)
Browse files Browse the repository at this point in the history
* Delete remote_theme when deleting the theme

* Install themes and theme components through rake

* Removed unnecessary test
  • Loading branch information
rrooding authored and eviltrout committed Jul 4, 2019
1 parent 72bac61 commit 1318e0b
Show file tree
Hide file tree
Showing 4 changed files with 181 additions and 1 deletion.
2 changes: 1 addition & 1 deletion app/models/theme.rb
Expand Up @@ -22,7 +22,7 @@ class Theme < ActiveRecord::Base
has_many :child_themes, -> { order(:name) }, through: :child_theme_relation, source: :child_theme
has_many :parent_themes, -> { order(:name) }, through: :parent_theme_relation, source: :parent_theme
has_many :color_schemes
belongs_to :remote_theme, autosave: true
belongs_to :remote_theme, autosave: true, dependent: :destroy

has_one :settings_field, -> { where(target_id: Theme.targets[:settings], name: "yaml") }, class_name: 'ThemeField'
has_one :javascript_cache, dependent: :destroy
Expand Down
54 changes: 54 additions & 0 deletions app/services/themes_install_task.rb
@@ -0,0 +1,54 @@
# frozen_string_literal: true

class ThemesInstallTask
def self.install(yml)
counts = { installed: 0, updated: 0, skipped: 0, errors: 0 }
log = []
themes = YAML::load(yml)
themes.each do |theme|
name = theme[0]
val = theme[1]
installer = new(val)

if installer.theme_exists?
log << "#{name}: is already installed"
counts[:skipped] += 1
else
begin
installer.install
log << "#{name}: installed from #{installer.url}"
counts[:installed] += 1
rescue RemoteTheme::ImportError, Discourse::InvalidParameters => err
log << "#{name}: #{err.message}"
counts[:errors] += 1
end
end
end

return log, counts
end

attr_reader :url, :options

def initialize(url_or_options = nil)
if url_or_options.is_a?(Hash)
@url = url_or_options.fetch("url")
@options = url_or_options
else
@url = url_or_options
@options = {}
end
end

def theme_exists?
RemoteTheme
.where(remote_url: url)
.where(branch: options.fetch("branch", nil))
.exists?
end

def install
theme = RemoteTheme.import_theme(url, Discourse.system_user, private_key: options["private_key"], branch: options["branch"])
theme.set_default! if options.fetch("default", false)
end
end
43 changes: 43 additions & 0 deletions lib/tasks/themes.rake
@@ -0,0 +1,43 @@
# frozen_string_literal: true

require 'yaml'

# == YAML file format
#
# 2 different formats are accepted:
#
# theme_name: https://github.com/example/theme.git
#
# theme_name:
# url: https://github.com/example/theme.git
# branch: abc
# private_key: ...
# default: true
#
# In the second form, only the url is required.
#
desc "Install themes & theme components"
task "themes:install" => :environment do
yml = (STDIN.tty?) ? '' : STDIN.read
if yml == ''
puts
puts "Please specify a themes yml file"
puts "Example: rake themes:install < themes.yml"
exit 1
end

log, counts = ThemesInstallTask.install(yml)

puts log

puts
puts "Results:"
puts " Installed: #{counts[:installed]}"
puts " Updated: #{counts[:updated]}"
puts " Skipped: #{counts[:skipped]}"
puts " Errors: #{counts[:errors]}"

if counts[:errors] > 0
exit 1
end
end
83 changes: 83 additions & 0 deletions spec/services/themes_spec.rb
@@ -0,0 +1,83 @@
# frozen_string_literal: true

require 'rails_helper'

describe ThemesInstallTask do

before do
Discourse::Application.load_tasks
end

let(:github_repo) { 'https://github.com/example/theme.git' }
let(:branch) { 'master' }

describe '.new' do
context 'with url' do
subject { described_class.new(github_repo) }

it 'configures the url' do
expect(subject.url).to eq github_repo
end

it 'initializes without options' do
expect(subject.options).to eq({})
end
end

context 'with options' do
subject { described_class.new(options) }
let(:options) { { 'url' => github_repo, 'branch' => branch } }

it 'configures the url' do
expect(subject.url).to eq github_repo
end

it 'initializes options' do
expect(subject.options).to eq("url" => github_repo, "branch" => branch)
end
end
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

it 'returns false when the url exists but with a branch' do
theme.create_remote_theme(remote_url: github_repo, branch: branch)
expect(subject.theme_exists?).to be false
end

it 'returns false when it doesnt exist' do
theme.create_remote_theme(remote_url: 'https://github.com/example/different_theme.git')
expect(subject.theme_exists?).to be false
end
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

it 'returns true when the url exists with a branch' do
theme.create_remote_theme(remote_url: github_repo, branch: branch)
expect(subject.theme_exists?).to be true
end

it 'returns false when it doesnt exist' do
theme.create_remote_theme(remote_url: 'https://github.com/example/different_theme.git')
expect(subject.theme_exists?).to be false
end
end
end
end

0 comments on commit 1318e0b

Please sign in to comment.