diff --git a/rhodecode/apps/admin/tests/test_admin_settings.py b/rhodecode/apps/admin/tests/test_admin_settings.py
--- a/rhodecode/apps/admin/tests/test_admin_settings.py
+++ b/rhodecode/apps/admin/tests/test_admin_settings.py
@@ -31,8 +31,7 @@ from rhodecode.tests import assert_sessi
from rhodecode.tests.utils import AssertResponse
-UPDATE_DATA_QUALNAME = (
- 'rhodecode.apps.admin.views.system_info.AdminSystemInfoSettingsView.get_update_data')
+UPDATE_DATA_QUALNAME = 'rhodecode.model.update.UpdateModel.get_update_data'
def route_path(name, params=None, **kwargs):
@@ -586,7 +585,7 @@ class TestAdminSystemInfo(object):
with mock.patch(UPDATE_DATA_QUALNAME, return_value=update_data):
response = self.app.get(route_path('admin_settings_system_update'))
response.mustcontain(
- 'You already have the latest stable version.')
+ 'This instance is already running the latest stable version')
def test_system_update_bad_response(self, autologin_user):
with mock.patch(UPDATE_DATA_QUALNAME, side_effect=ValueError('foo')):
diff --git a/rhodecode/apps/admin/views/system_info.py b/rhodecode/apps/admin/views/system_info.py
--- a/rhodecode/apps/admin/views/system_info.py
+++ b/rhodecode/apps/admin/views/system_info.py
@@ -20,7 +20,6 @@
import logging
import urllib2
-import packaging.version
from pyramid.view import view_config
@@ -31,8 +30,7 @@ from rhodecode.lib import helpers as h
from rhodecode.lib.auth import (LoginRequired, HasPermissionAllDecorator)
from rhodecode.lib.utils2 import str2bool
from rhodecode.lib import system_info
-from rhodecode.lib.ext_json import json
-from rhodecode.model.settings import SettingsModel
+from rhodecode.model.update import UpdateModel
log = logging.getLogger(__name__)
@@ -40,26 +38,8 @@ log = logging.getLogger(__name__)
class AdminSystemInfoSettingsView(BaseAppView):
def load_default_context(self):
c = self._get_local_tmpl_context()
-
return c
- @staticmethod
- def get_update_data(update_url):
- """Return the JSON update data."""
- ver = rhodecode.__version__
- log.debug('Checking for upgrade on `%s` server', update_url)
- opener = urllib2.build_opener()
- opener.addheaders = [('User-agent', 'RhodeCode-SCM/%s' % ver)]
- response = opener.open(update_url)
- response_data = response.read()
- data = json.loads(response_data)
-
- return data
-
- def get_update_url(self):
- settings = SettingsModel().get_all_settings()
- return settings.get('rhodecode_update_url')
-
@LoginRequired()
@HasPermissionAllDecorator('hg.admin')
@view_config(
@@ -77,7 +57,7 @@ class AdminSystemInfoSettingsView(BaseAp
snapshot = str2bool(self.request.params.get('snapshot'))
- c.rhodecode_update_url = self.get_update_url()
+ c.rhodecode_update_url = UpdateModel().get_update_url()
server_info = system_info.get_system_info(self.request.environ)
for key, val in server_info.items():
@@ -97,6 +77,14 @@ class AdminSystemInfoSettingsView(BaseAp
update_info_msg = _('Note: please make sure this server can '
'access `${url}` for the update link to work',
mapping=dict(url=c.rhodecode_update_url))
+ version = UpdateModel().get_stored_version()
+ is_outdated = UpdateModel().is_outdated(
+ rhodecode.__version__, version)
+ update_state = {
+ 'type': 'warning',
+ 'message': 'New version available: {}'.format(version)
+ } \
+ if is_outdated else {}
c.data_items = [
# update info
(_('Update info'), h.literal(
@@ -107,6 +95,7 @@ class AdminSystemInfoSettingsView(BaseAp
# RhodeCode specific
(_('RhodeCode Version'), val('rhodecode_app')['text'], state('rhodecode_app')),
+ (_('Latest version'), version, update_state),
(_('RhodeCode Server IP'), val('server')['server_ip'], state('server')),
(_('RhodeCode Server ID'), val('server')['server_id'], state('server')),
(_('RhodeCode Configuration'), val('rhodecode_config')['path'], state('rhodecode_config')),
@@ -178,11 +167,11 @@ class AdminSystemInfoSettingsView(BaseAp
_ = self.request.translate
c = self.load_default_context()
- update_url = self.get_update_url()
+ update_url = UpdateModel().get_update_url()
_err = lambda s: '
{}
'.format(s)
try:
- data = self.get_update_data(update_url)
+ data = UpdateModel().get_update_data(update_url)
except urllib2.URLError as e:
log.exception("Exception contacting upgrade server")
self.request.override_renderer = 'string'
@@ -200,9 +189,9 @@ class AdminSystemInfoSettingsView(BaseAp
c.cur_ver = rhodecode.__version__
c.should_upgrade = False
- if (packaging.version.Version(c.latest_ver) >
- packaging.version.Version(c.cur_ver)):
+ is_oudated = UpdateModel().is_outdated(c.cur_ver, c.latest_ver)
+ if is_oudated:
c.should_upgrade = True
c.important_notices = latest['general']
-
+ UpdateModel().store_version(latest['version'])
return self._get_template_context(c)
diff --git a/rhodecode/lib/celerylib/tasks.py b/rhodecode/lib/celerylib/tasks.py
--- a/rhodecode/lib/celerylib/tasks.py
+++ b/rhodecode/lib/celerylib/tasks.py
@@ -278,6 +278,20 @@ def sync_repo(*args, **kwargs):
log.debug('Repo `%s` not found or without a clone_url', repo_name)
+@async_task(ignore_result=True)
+def check_for_update():
+ from rhodecode.model.update import UpdateModel
+ update_url = UpdateModel().get_update_url()
+ cur_ver = rhodecode.__version__
+
+ try:
+ data = UpdateModel().get_update_data(update_url)
+ latest = data['versions'][0]
+ UpdateModel().store_version(latest['version'])
+ except Exception:
+ pass
+
+
@async_task(ignore_result=False)
def beat_check(*args, **kwargs):
log = get_logger(beat_check)
diff --git a/rhodecode/model/update.py b/rhodecode/model/update.py
new file mode 100644
--- /dev/null
+++ b/rhodecode/model/update.py
@@ -0,0 +1,71 @@
+# -*- coding: utf-8 -*-
+
+# Copyright (C) 2013-2017 RhodeCode GmbH
+#
+# This program is free software: you can redistribute it and/or modify
+# it under the terms of the GNU Affero General Public License, version 3
+# (only), as published by the Free Software Foundation.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU Affero General Public License
+# along with this program. If not, see .
+#
+# This program is dual-licensed. If you wish to learn more about the
+# RhodeCode Enterprise Edition, including its added features, Support services,
+# and proprietary license terms, please see https://rhodecode.com/licenses/
+
+import logging
+import urllib2
+from packaging import version
+
+import rhodecode
+from rhodecode.lib.ext_json import json
+from rhodecode.model import BaseModel
+from rhodecode.model.meta import Session
+from rhodecode.model.settings import SettingsModel
+
+
+log = logging.getLogger(__name__)
+
+
+class UpdateModel(BaseModel):
+ UPDATE_SETTINGS_KEY = 'update_version'
+ UPDATE_URL_SETTINGS_KEY = 'rhodecode_update_url'
+
+ @staticmethod
+ def get_update_data(update_url):
+ """Return the JSON update data."""
+ ver = rhodecode.__version__
+ log.debug('Checking for upgrade on `%s` server', update_url)
+ opener = urllib2.build_opener()
+ opener.addheaders = [('User-agent', 'RhodeCode-SCM/%s' % ver)]
+ response = opener.open(update_url)
+ response_data = response.read()
+ data = json.loads(response_data)
+ log.debug('update server returned data')
+ return data
+
+ def get_update_url(self):
+ settings = SettingsModel().get_all_settings()
+ return settings.get(self.UPDATE_URL_SETTINGS_KEY)
+
+ def store_version(self, version):
+ log.debug('Storing version %s into settings', version)
+ setting = SettingsModel().create_or_update_setting(
+ self.UPDATE_SETTINGS_KEY, version)
+ Session().add(setting)
+ Session().commit()
+
+ def get_stored_version(self):
+ obj = SettingsModel().get_setting_by_name(self.UPDATE_SETTINGS_KEY)
+ if obj:
+ return obj.app_settings_value
+ return '0.0.0'
+
+ def is_outdated(self, cur_version, latest_version=None):
+ latest_version = latest_version or self.get_stored_version()
+ return version.Version(latest_version) > version.Version(cur_version)
diff --git a/rhodecode/templates/admin/settings/settings_system_update.mako b/rhodecode/templates/admin/settings/settings_system_update.mako
--- a/rhodecode/templates/admin/settings/settings_system_update.mako
+++ b/rhodecode/templates/admin/settings/settings_system_update.mako
@@ -2,8 +2,7 @@
## upgrade block rendered afte on-click check
-
-
+
%if c.should_upgrade:
A new version is available:
%if c.latest_data.get('title'):
@@ -12,7 +11,7 @@
${c.latest_ver}
%endif
%else:
- You already have the latest stable version.
+ This instance is already running the latest stable version ${c.latest_ver}.
%endif