Add version checking that shows on the admin dashboard

This commit is contained in:
Neil Lalonde 2013-02-19 15:16:50 -05:00
parent bb1156cee1
commit c0371ff427
16 changed files with 195 additions and 48 deletions

View file

@ -10,6 +10,7 @@ gem 'simple_handlebars_rails', path: 'vendor/gems/simple_handlebars_rails'
gem 'activerecord-postgres-hstore'
gem 'acts_as_paranoid'
gem 'active_attr' # until we get ActiveModel::Model with Rails 4
gem 'airbrake', '3.1.2' # errbit is broken with 3.1.3 for now
gem 'clockwork', require: false
gem 'em-redis'

View file

@ -76,6 +76,9 @@ GEM
rack-cache (~> 1.2)
rack-test (~> 0.6.1)
sprockets (~> 2.2.1)
active_attr (0.7.0)
activemodel (>= 3.0.2, < 4.1)
activesupport (>= 3.0.2, < 4.1)
activemodel (3.2.12)
activesupport (= 3.2.12)
builder (~> 3.0.0)
@ -440,6 +443,7 @@ PLATFORMS
ruby
DEPENDENCIES
active_attr
active_model_serializers!
activerecord-postgres-hstore
acts_as_paranoid

View file

@ -0,0 +1,26 @@
window.Discourse.AdminDashboardController = Ember.Controller.extend
loading: true
versionCheck: null
upToDate: (->
if @versionCheck
@versionCheck.latest_version == @versionCheck.installed_version
else
true
).property('versionCheck')
updateIconClasses: (->
classes = "icon icon-warning-sign "
if @get('versionCheck.critical_updates')
classes += "critical-updates-available"
else
classes += "updates-available"
classes
).property('versionCheck')
priorityClass: (->
if @get('versionCheck.critical_updates')
'critical'
else
'normal'
).property('versionCheck')

View file

@ -0,0 +1,9 @@
window.Discourse.VersionCheck = Discourse.Model.extend({})
Discourse.VersionCheck.reopenClass
find: ->
$.ajax
url: '/admin/version_check'
dataType: 'json'
success: (json) =>
Discourse.VersionCheck.create(json)

View file

@ -0,0 +1,6 @@
Discourse.AdminDashboardRoute = Discourse.Route.extend
setupController: (c) ->
Discourse.VersionCheck.find().then (vc) ->
# Loading finished!
c.set('versionCheck', vc)
c.set('loading', false)

View file

@ -1,4 +1,23 @@
<h3>Welcome to the admin section.</h3>
<p>Not much to see here right now. Why not try the Site Settings?</p>
<p class="version-check">
{{#if loading }}
Loading...
{{else}}
<p {{bindAttr class="priorityClass"}}>
Discourse version: <span class="version-number">{{ versionCheck.installed_version }}</span>
<span class="version-notes">
{{#if upToDate }}
<i class='icon icon-ok update-to-date'></i> You are running the latest version of Discourse.
{{else}}
<i {{bindAttr class="updateIconClasses"}}></i>
<span class="critical-note">A critical update is available.</span>
<span class="normal-note">Updates are available.</span>
Please upgrade!
Latest version: <span class="version-number">{{ versionCheck.latest_version }}</span>
{{/if}}
</span>
</p>
{{/if}}
</p>

View file

@ -77,6 +77,38 @@
}
}
.version-check {
.version-number {
font-size: 18px;
font-weight: bold
}
.version-notes {
margin-left: 24px;
}
.critical .version-notes .normal-note {
display: none;
}
.normal .version-notes .critical-note {
display: none;
}
i.icon {
font-size: 20px;
}
i.update-to-date {
color: green;
}
i.updates-available {
color: orange;
}
i.critical-updates-available {
color: red;
}
}
.settings {
.setting {
padding-bottom: 20px;

View file

@ -1,15 +1,7 @@
require_dependency 'discourse_hub'
require_dependency 'version'
require_dependency 'discourse_updates'
class Admin::VersionsController < Admin::AdminController
def show
if SiteSetting.discourse_org_access_key.present?
render json: success_json.merge( latest_version: DiscourseHub.current_discourse_version, installed_version: Discourse::VERSION::STRING )
else
# Don't contact discourse.org
render json: success_json.merge( latest_version: Discourse::VERSION::STRING, installed_version: Discourse::VERSION::STRING )
end
rescue RestClient::Forbidden
render json: {errors: [I18n.t("discourse_hub.access_token_problem")]}
render json: DiscourseUpdates.check_version
end
end

View file

@ -0,0 +1,14 @@
class DiscourseVersionCheck
# include ActiveModel::Model <-- If we were using Rails 4, we could use this instead of active_attr
include ActiveAttr::Attributes
include ActiveAttr::MassAssignment
include ActiveModel::Serialization
attr_accessor :latest_version, :installed_version, :critical_updates
def active_model_serializer
DiscourseVersionCheckSerializer
end
end

View file

@ -0,0 +1,5 @@
class DiscourseVersionCheckSerializer < ApplicationSerializer
attributes :latest_version, :installed_version, :critical_updates
self.root = false
end

View file

@ -16,4 +16,5 @@ module Clockwork
every(10.minutes, 'feature_topics')
every(1.minute, 'calculate_score')
every(20.minutes, 'calculate_view_counts')
every(1.day, 'version_check')
end

View file

@ -1,4 +1,5 @@
require_dependency 'rest_client'
require_dependency 'version'
module DiscourseHub
@ -33,8 +34,8 @@ module DiscourseHub
end
def self.current_discourse_version
get('/current_version')['version']
def self.discourse_version_check
get('/version_check', {installed_version: Discourse::VERSION::STRING})
end

41
lib/discourse_updates.rb Normal file
View file

@ -0,0 +1,41 @@
module DiscourseUpdates
class << self
def check_version
DiscourseVersionCheck.new(
latest_version: latest_version || Discourse::VERSION::STRING,
installed_version: Discourse::VERSION::STRING,
critical_updates: critical_update_available?
# TODO: more info, like links and release messages
)
end
def latest_version=(arg)
$redis.set latest_version_key, arg
end
def latest_version
$redis.get latest_version_key
end
def critical_update_available=(arg)
$redis.set critical_updates_available_key, arg
end
def critical_update_available?
($redis.get(critical_updates_available_key) || false) == 'true'
end
private
def latest_version_key
'discourse_latest_version'
end
def critical_updates_available_key
'critical_updates_available'
end
end
end

15
lib/jobs/version_check.rb Normal file
View file

@ -0,0 +1,15 @@
require_dependency 'discourse_hub'
require_dependency 'discourse_updates'
module Jobs
class VersionCheck < Jobs::Base
def execute(args)
json = DiscourseHub.discourse_version_check
DiscourseUpdates.latest_version = json['latestVersion']
DiscourseUpdates.critical_update_available = json['criticalUpdates']
true
end
end
end

View file

@ -55,10 +55,11 @@ describe DiscourseHub do
end
end
describe '#current_discourse_version' do
it 'should return the latest version of discourse' do
RestClient.stubs(:get).returns( {success: 'OK', version: 1.0}.to_json )
DiscourseHub.current_discourse_version().should == 1.0
describe '#discourse_version_check' do
it 'should return just return the json that the hub returns' do
hub_response = {'success' => 'OK', 'latest_version' => '0.8.1', 'critical_updates' => false}
RestClient.stubs(:get).returns( hub_response.to_json )
DiscourseHub.discourse_version_check.should == hub_response
end
end

View file

@ -4,7 +4,8 @@ require_dependency 'version'
describe Admin::VersionsController do
before do
RestClient.stubs(:get).returns( {success: 'OK', version: '1.2.33'}.to_json )
DiscourseUpdates.stubs(:latest_version).returns('1.2.33')
DiscourseUpdates.stubs(:critical_update_available?).returns(false)
end
it "is a subclass of AdminController" do
@ -17,38 +18,17 @@ describe Admin::VersionsController do
end
describe 'show' do
context 'when discourse_org_access_key is set' do
before do
SiteSetting.stubs(:discourse_org_access_key).returns('asdf')
end
subject { xhr :get, :show }
it { should be_success }
subject { xhr :get, :show }
it { should be_success }
it 'should return the currently available version' do
json = JSON.parse(subject.body)
json['latest_version'].should == '1.2.33'
end
it "should return the installed version" do
json = JSON.parse(subject.body)
json['installed_version'].should == Discourse::VERSION::STRING
end
it 'should return the currently available version' do
json = JSON.parse(subject.body)
json['latest_version'].should == '1.2.33'
end
context 'when discourse_org_access_key is blank' do
subject { xhr :get, :show }
it { should be_success }
it 'should return the installed version as the currently available version' do
json = JSON.parse(subject.body)
json['latest_version'].should == Discourse::VERSION::STRING
end
it "should return the installed version" do
json = JSON.parse(subject.body)
json['installed_version'].should == Discourse::VERSION::STRING
end
it "should return the installed version" do
json = JSON.parse(subject.body)
json['installed_version'].should == Discourse::VERSION::STRING
end
end
end