FIX: issue 1538. After upgrading and before a new version check request has been made, dashboard might still say that an update is available.

This commit is contained in:
Neil Lalonde 2013-11-04 12:51:01 -05:00
parent 5e69b277ea
commit ede59a4386
10 changed files with 133 additions and 75 deletions

View File

@ -13,7 +13,7 @@ Discourse.VersionCheck = Discourse.Model.extend({
}.property('updated_at'),
dataIsOld: function() {
return moment().diff(moment(this.get('updated_at')), 'hours') >= 48;
return this.get('version_check_pending') || moment().diff(moment(this.get('updated_at')), 'hours') >= 48;
}.property('updated_at'),
staleData: function() {

View File

@ -62,16 +62,26 @@
{{#if versionCheck.staleData}}
<td class="version-number">&nbsp;</td>
<td class="face">
<span class="icon critical-updates-available">☹</span>
{{#if versionCheck.version_check_pending}}
<span class='icon up-to-date'>☻</span>
{{else}}
<span class="icon critical-updates-available">☹</span>
{{/if}}
</td>
<td class="version-notes">
<span class="normal-note">{{i18n admin.dashboard.stale_data}}</span>
<span class="normal-note">
{{#if versionCheck.version_check_pending}}
{{i18n admin.dashboard.version_check_pending}}
{{else}}
{{i18n admin.dashboard.stale_data}}
{{/if}}
</span>
</td>
{{else}}
<td class="version-number">{{ versionCheck.latest_version }}</td>
<td class="face">
{{#if versionCheck.upToDate }}
<span class='icon update-to-date'>☻</span>
<span class='icon up-to-date'>☻</span>
{{else}}
<span {{bindAttr class=":icon versionCheck.critical_updates:critical-updates-available:updates-available"}}>
{{#if versionCheck.behindByOneVersion}}

View File

@ -382,7 +382,7 @@ table {
font-size: 26px;
}
.update-to-date {
.up-to-date {
color: green;
}
.updates-available {

View File

@ -11,6 +11,7 @@ module Jobs
should_send_email = (SiteSetting.new_version_emails and DiscourseUpdates.missing_versions_count and DiscourseUpdates.missing_versions_count == 0)
json = DiscourseHub.discourse_version_check
DiscourseUpdates.last_installed_version = Discourse::VERSION::STRING
DiscourseUpdates.latest_version = json['latestVersion']
DiscourseUpdates.critical_updates_available = json['criticalUpdates']
DiscourseUpdates.missing_versions_count = json['missingVersionsCount']

View File

@ -7,7 +7,7 @@ class DiscourseVersionCheck
include ActiveModel::Serialization
end
attr_accessor :latest_version, :critical_updates, :installed_version, :installed_sha, :missing_versions_count, :updated_at
attr_accessor :latest_version, :critical_updates, :installed_version, :installed_sha, :missing_versions_count, :updated_at, :version_check_pending
unless rails4?
def active_model_serializer

View File

@ -1090,6 +1090,7 @@ en:
please_upgrade: "Please upgrade!"
no_check_performed: "A check for updates has not been performed. Ensure sidekiq is running."
stale_data: "A check for updates has not been performed lately. Ensure sidekiq is running."
version_check_pending: "Looks like you upgraded recently. Fantastic!"
installed_version: "Installed"
latest_version: "Latest"
problems_found: "Some problems have been found with your installation of Discourse:"

View File

@ -24,20 +24,27 @@ module DiscourseUpdates
# Handle cases when version check data is old so we report something that makes sense
if (version_info.updated_at.nil? or
(version_info.missing_versions_count == 0 and version_info.latest_version != version_info.installed_version) or
(version_info.missing_versions_count != 0 and version_info.latest_version == version_info.installed_version))
if (version_info.updated_at.nil? or # never performed a version check
last_installed_version != Discourse::VERSION::STRING or # upgraded since the last version check
(version_info.missing_versions_count == 0 and version_info.latest_version != version_info.installed_version) or # old data
(version_info.missing_versions_count != 0 and version_info.latest_version == version_info.installed_version)) # old data
Jobs.enqueue(:version_check, all_sites: true)
end
if !version_info.updated_at.nil? and version_info.latest_version == version_info.installed_version
version_info.missing_versions_count = 0
version_info.version_check_pending = true
unless version_info.updated_at.nil?
version_info.missing_versions_count = 0
version_info.critical_updates = false
end
end
end
version_info
end
# last_installed_version is the installed version at the time of the last version check
def last_installed_version
$redis.get last_installed_version_key
end
def latest_version
$redis.get latest_version_key
end
@ -59,7 +66,7 @@ module DiscourseUpdates
$redis.set updated_at_key, time_with_zone.as_json
end
['latest_version', 'missing_versions_count', 'critical_updates_available'].each do |name|
['last_installed_version', 'latest_version', 'missing_versions_count', 'critical_updates_available'].each do |name|
eval "define_method :#{name}= do |arg|
$redis.set #{name}_key, arg
end"
@ -68,6 +75,10 @@ module DiscourseUpdates
private
def last_installed_version_key
'last_installed_version'
end
def latest_version_key
'discourse_latest_version'
end

View File

@ -16,75 +16,103 @@ describe DiscourseUpdates do
subject { DiscourseUpdates.check_version.as_json }
context 'a good version check request happened recently' do
context 'and server is up-to-date' do
before { stub_data(Discourse::VERSION::STRING, 0, false, 12.hours.ago) }
context 'version check was done at the current installed version' do
before do
DiscourseUpdates.stubs(:last_installed_version).returns(Discourse::VERSION::STRING)
end
it 'returns all the version fields' do
subject['latest_version'].should == Discourse::VERSION::STRING
subject['missing_versions_count'].should == 0
subject['critical_updates'].should == false
context 'a good version check request happened recently' do
context 'and server is up-to-date' do
before { stub_data(Discourse::VERSION::STRING, 0, false, 12.hours.ago) }
it 'returns all the version fields' do
subject['latest_version'].should == Discourse::VERSION::STRING
subject['missing_versions_count'].should == 0
subject['critical_updates'].should == false
subject['installed_version'].should == Discourse::VERSION::STRING
end
it 'returns the timestamp of the last version check' do
subject['updated_at'].should be_within_one_second_of(12.hours.ago)
end
end
context 'and server is not up-to-date' do
before { stub_data('0.9.0', 2, false, 12.hours.ago) }
it 'returns all the version fields' do
subject['latest_version'].should == '0.9.0'
subject['missing_versions_count'].should == 2
subject['critical_updates'].should == false
subject['installed_version'].should == Discourse::VERSION::STRING
end
it 'returns the timestamp of the last version check' do
subject['updated_at'].should be_within_one_second_of(12.hours.ago)
end
end
end
context 'a version check has never been performed' do
before { stub_data(nil, nil, false, nil) }
it 'returns the installed version' do
subject['installed_version'].should == Discourse::VERSION::STRING
end
it 'returns the timestamp of the last version check' do
subject['updated_at'].should be_within_one_second_of(12.hours.ago)
it 'indicates that version check has not been performed' do
subject.should have_key('updated_at')
subject['updated_at'].should == nil
end
it 'does not return latest version info' do
subject.should_not have_key('latest_version')
subject.should_not have_key('missing_versions_count')
subject.should_not have_key('critical_updates')
end
it 'queues a version check' do
Jobs.expects(:enqueue).with(:version_check, anything)
subject
end
end
context 'and server is not up-to-date' do
before { stub_data('0.9.0', 2, false, 12.hours.ago) }
# These cases should never happen anymore, but keep the specs to be sure
# they're handled in a sane way.
context 'old version check data' do
shared_examples "queue version check and report that version is ok" do
it 'queues a version check' do
Jobs.expects(:enqueue).with(:version_check, anything)
subject
end
it 'returns all the version fields' do
subject['latest_version'].should == '0.9.0'
subject['missing_versions_count'].should == 2
subject['critical_updates'].should == false
subject['installed_version'].should == Discourse::VERSION::STRING
it 'reports 0 missing versions' do
subject['missing_versions_count'].should == 0
end
it 'reports that a version check will be run soon' do
subject['version_check_pending'].should == true
end
end
it 'returns the timestamp of the last version check' do
subject['updated_at'].should be_within_one_second_of(12.hours.ago)
context 'installed is latest' do
before { stub_data(Discourse::VERSION::STRING, 1, false, 8.hours.ago) }
include_examples "queue version check and report that version is ok"
end
context 'installed does not match latest version, but missing_versions_count is 0' do
before { stub_data('0.10.10.123', 0, false, 8.hours.ago) }
include_examples "queue version check and report that version is ok"
end
end
end
context 'a version check has never been performed' do
before { stub_data(nil, nil, false, nil) }
it 'returns the installed version' do
subject['installed_version'].should == Discourse::VERSION::STRING
context 'version check was done at a different installed version' do
before do
DiscourseUpdates.stubs(:last_installed_version).returns('0.9.1')
end
it 'indicates that version check has not been performed' do
subject.should have_key('updated_at')
subject['updated_at'].should == nil
end
it 'does not return latest version info' do
subject.should_not have_key('latest_version')
subject.should_not have_key('missing_versions_count')
subject.should_not have_key('critical_updates')
end
it 'queues a version check' do
Jobs.expects(:enqueue).with(:version_check, anything)
subject
end
end
context 'installed version is newer' do
before { stub_data('0.9.3', 0, false, 28.hours.ago) }
it 'queues a version check' do
Jobs.expects(:enqueue).with(:version_check, anything)
subject
end
end
context 'old version check data' do
context 'installed is latest' do
before { stub_data(Discourse::VERSION::STRING, 1, false, 8.hours.ago) }
shared_examples "when last_installed_version is old" do
it 'queues a version check' do
Jobs.expects(:enqueue).with(:version_check, anything)
subject
@ -93,16 +121,20 @@ describe DiscourseUpdates do
it 'reports 0 missing versions' do
subject['missing_versions_count'].should == 0
end
end
context 'installed is not latest' do
before { stub_data('0.9.1', 0, false, 8.hours.ago) }
it 'queues a version check' do
Jobs.expects(:enqueue).with(:version_check, anything)
subject
it 'reports that a version check will be run soon' do
subject['version_check_pending'].should == true
end
end
end
context 'missing_versions_count is 0' do
before { stub_data('0.9.7', 0, false, 8.hours.ago) }
include_examples "when last_installed_version is old"
end
context 'missing_versions_count is not 0' do
before { stub_data('0.9.7', 1, false, 8.hours.ago) }
include_examples "when last_installed_version is old"
end
end
end

View File

@ -4,6 +4,7 @@ require_dependency 'version'
describe Admin::VersionsController do
before do
Jobs::VersionCheck.any_instance.stubs(:execute).returns(true)
DiscourseUpdates.stubs(:updated_at).returns(2.hours.ago)
DiscourseUpdates.stubs(:latest_version).returns('1.2.33')
DiscourseUpdates.stubs(:critical_updates_available?).returns(false)

View File

@ -7,6 +7,7 @@ test('dataIsOld', function() {
dataIsOld({updated_at: moment().subtract('hours', 2).toJSON()}, false, '2 hours ago');
dataIsOld({updated_at: moment().subtract('hours', 49).toJSON()}, true, '49 hours ago');
dataIsOld({updated_at: moment().subtract('hours', 2).toJSON(), version_check_pending: true}, true, 'version check pending');
});
test('staleData', function() {
@ -21,4 +22,5 @@ test('staleData', function() {
staleData({missing_versions_count: 0, installed_version: '0.9.4', latest_version: '0.9.3', updated_at: updatedAt(2)}, true, 'installed and latest do not match, but missing_versions_count is 0');
staleData({missing_versions_count: 1, installed_version: '0.9.3', latest_version: '0.9.3', updated_at: updatedAt(2)}, true, 'installed and latest match, but missing_versions_count is not 0');
staleData({missing_versions_count: 0, installed_version: '0.9.3', latest_version: '0.9.3', updated_at: updatedAt(50)}, true, 'old version check data');
staleData({version_check_pending: true, missing_versions_count: 0, installed_version: '0.9.4', latest_version: '0.9.3', updated_at: updatedAt(2)}, true, 'version was upgraded, but no version check has been done since the upgrade');
});