From b9bb17dd6976119773396848dda5598f20775096 Mon Sep 17 00:00:00 2001 From: Manuel Cortez Date: Wed, 26 Dec 2018 12:24:12 -0600 Subject: [PATCH 1/7] Added new update data --- src/application.py | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) diff --git a/src/application.py b/src/application.py index 101d147..c8be988 100644 --- a/src/application.py +++ b/src/application.py @@ -6,11 +6,18 @@ authorEmail = "manuel@manuelcortez.net" copyright = u"Copyright (C) 2016-2018, Manuel Cortez" description = unicode(name+" Is an accessible VK client for Windows.") url = "https://manuelcortez.net/socializer" -update_url = "https://code.manuelcortez.net/manuelcortez/socializer/raw/master/update-files/socializer.json" # The short name will be used for detecting translation files. See languageHandler for more details. short_name = "socializer" translators = [u"Darya Ratnikova (Russian)", u"Manuel Cortez (Spanish)"] bts_name = "socializer" bts_access_token = "U29jaWFsaXplcg" bts_url = "https://issues.manuelcortez.net" -bts_project_id = 4 \ No newline at end of file +bts_project_id = 4 +### Update information +# URL to retrieve the latest updates for the stable branch. +update_stable_url = "https://code.manuelcortez.net/manuelcortez/socializer/raw/master/update-files/socializer.json" +# URL to retrieve update information for the "next" branch. This is a channel made for alpha versions. +# Every commit will trigger an update, so users wanting to have the bleeding edge code will get it as soon as it is committed here and build by a runner. +update_next_url = "https://code.manuelcortez.net/api/v4/projects/4/repository/commits/master" +# Short_id of the last commit, this is set to none here because it will be set manually by the building tools. +update_next_version = "03286a44" \ No newline at end of file From 729b410d63cd68810c59d4fc9db765e3f9bb249d Mon Sep 17 00:00:00 2001 From: Manuel Cortez Date: Wed, 26 Dec 2018 12:27:44 -0600 Subject: [PATCH 2/7] Updater now accepts updates from the gitlab repo URL --- src/update/update.py | 34 +++++++++++++++++++++++++++------- src/update/updater.py | 10 ++++++++-- 2 files changed, 35 insertions(+), 9 deletions(-) diff --git a/src/update/update.py b/src/update/update.py index b756cc9..275a515 100644 --- a/src/update/update.py +++ b/src/update/update.py @@ -16,18 +16,15 @@ except ImportError: from platform_utils import paths -def perform_update(endpoint, current_version, app_name='', password=None, update_available_callback=None, progress_callback=None, update_complete_callback=None): +def perform_update(endpoint, current_version, update_type="stable", app_name='', password=None, update_available_callback=None, progress_callback=None, update_complete_callback=None): requests_session = create_requests_session(app_name=app_name, version=current_version) available_update = find_update(endpoint, requests_session=requests_session) if not available_update: logger.debug("No update available") return False - available_version = float(available_update['current_version']) - if not float(available_version) > float(current_version) or platform.system()+platform.architecture()[0][:2] not in available_update['downloads']: - logger.debug("No update for this architecture") - return False - available_description = available_update.get('description', None) - update_url = available_update ['downloads'][platform.system()+platform.architecture()[0][:2]] + available_version, available_description, update_url = find_version_data(update_type, current_version, available_update) + if available_version == False: + return logger.info("A new update is available. Version %s" % available_version) if callable(update_available_callback) and not update_available_callback(version=available_version, description=available_description): #update_available_callback should return a falsy value to stop the process logger.info("User canceled update.") @@ -57,6 +54,29 @@ def find_update(endpoint, requests_session): content = response.json() return content +def find_version_data(update_type, current_version, available_update): + if update_type == "stable": + available_version = float(available_update['current_version']) + if not float(available_version) > float(current_version) or platform.system()+platform.architecture()[0][:2] not in available_update['downloads']: + logger.debug("No update for this architecture") + return (False, False, False) + available_description = available_update.get('description', None) + update_url = available_update ['downloads'][platform.system()+platform.architecture()[0][:2]] + return (available_version, available_description, update_url) + else: # Unstable versions, based in commits instead of version numbers. + # A condition for this to work is a successful ran of a pipeline. + if "status" not in available_update: + return (False, False, False) + if "status" in available_update and available_update["status"] != "success": + return (False, False, False) + available_version = available_update["short_id"] + if available_version == current_version: + return (False, False, False) + available_description = available_update["message"] + # ToDo: simplify this so it can be reused in other projects. + update_url = "https://code.manuelcortez.net/manuelcortez/socializer/-/jobs/artifacts/master/raw/socializer.zip?job=production" + return (available_version, available_description, update_url) + def download_update(update_url, update_destination, requests_session, progress_callback=None, chunk_size=io.DEFAULT_BUFFER_SIZE): total_downloaded = total_size = 0 with io.open(update_destination, 'w+b') as outfile: diff --git a/src/update/updater.py b/src/update/updater.py index 86ee7e7..a50211b 100644 --- a/src/update/updater.py +++ b/src/update/updater.py @@ -8,9 +8,15 @@ from requests.exceptions import ConnectionError from wxUpdater import * logger = logging.getLogger("updater") -def do_update(endpoint=application.update_url): +def do_update(update_type="stable"): + if update_type == "stable": + endpoint = application.update_stable_url + version = application.version + else: + endpoint = application.update_next_url + version = application.update_next_version try: - return update.perform_update(endpoint=endpoint, current_version=application.version, app_name=application.name, update_available_callback=available_update_dialog, progress_callback=progress_callback, update_complete_callback=update_finished) + return update.perform_update(endpoint=endpoint, current_version=version, app_name=application.name, update_type=update_type, update_available_callback=available_update_dialog, progress_callback=progress_callback, update_complete_callback=update_finished) except ConnectionError: logger.exception("Update failed.") output.speak("An exception occurred while attempting to update " + application.name + ". If this message persists, contact the " + application.name + " developers. More information about the exception has been written to the error log.",True) \ No newline at end of file From fae791ff7123256b48476e9756b8a923685a4aab Mon Sep 17 00:00:00 2001 From: Manuel Cortez Date: Thu, 27 Dec 2018 08:30:51 -0600 Subject: [PATCH 3/7] Added update channel settings to general tab --- src/controller/configuration.py | 29 +++++++++++++++++++++++++++++ src/session.defaults | 1 + src/wxUI/dialogs/configuration.py | 11 +++++++++++ 3 files changed, 41 insertions(+) diff --git a/src/controller/configuration.py b/src/controller/configuration.py index 1b0807e..d2d1183 100644 --- a/src/controller/configuration.py +++ b/src/controller/configuration.py @@ -16,6 +16,22 @@ class configuration(object): else: return _(u"Custom") + def get_update_channel_type(self, value): + if value == _(u"Stable"): + return "stable" + elif value == _(u"Weekly"): + return "weekly" + else: + return "alpha" + + def get_update_channel_label(self, value): + if value == "stable": + return _(u"Stable") + elif value == "weekly": + return _(u"Weekly") + else: + return _(u"Alpha") + def __init__(self, session): self.session = session self.dialog = configurationUI.configurationDialog(_(u"Preferences")) @@ -26,6 +42,7 @@ class configuration(object): self.dialog.set_value("general", "wall_buffer_count", self.session.settings["buffers"]["count_for_wall_buffers"]) self.dialog.set_value("general", "video_buffers_count", self.session.settings["buffers"]["count_for_video_buffers"]) self.dialog.set_value("general", "load_images", self.session.settings["general"]["load_images"]) + self.dialog.set_value("general", "update_channel", self.get_update_channel_label(self.session.settings["general"]["update_channel"])) self.dialog.create_chat() self.dialog.set_value("chat", "notify_online", self.session.settings["chat"]["notify_online"]) self.dialog.set_value("chat", "notify_offline", self.session.settings["chat"]["notify_offline"]) @@ -38,6 +55,18 @@ class configuration(object): def save_configuration(self): self.session.settings["buffers"]["count_for_video_buffers"] = self.dialog.get_value("general", "video_buffers_count") self.session.settings["general"]["load_images"] = self.dialog.get_value("general", "load_images") + update_channel = self.get_update_channel_type(self.dialog.get_value("general", "update_channel")) + if update_channel != self.session.settings["general"]["update_channel"]: + if update_channel == "stable": + self.session.settings["general"]["update_channel"] = update_channel + elif update_channel == "weekly": + dialog = configurationUI.weekly_channel() + if dialog == widgetUtils.YES: + self.session.settings["general"]["update_channel"] = update_channel + elif update_channel == "alpha": + dialog = configurationUI.alpha_channel() + if dialog == widgetUtils.YES: + self.session.settings["general"]["update_channel"] = update_channel self.session.settings["chat"]["notify_online"] = self.dialog.get_value("chat", "notify_online") self.session.settings["chat"]["notify_offline"] = self.dialog.get_value("chat", "notify_offline") self.session.settings["chat"]["open_unread_conversations"] = self.dialog.get_value("chat", "open_unread_conversations") diff --git a/src/session.defaults b/src/session.defaults index 0ecf69e..c2d3216 100644 --- a/src/session.defaults +++ b/src/session.defaults @@ -7,6 +7,7 @@ use_alternative_tokens = boolean(default=False) [general] reverse_timelines = boolean(default=False) load_images = boolean(default=True) +update_channel = string(default="stable") [buffers] count_for_wall_buffers = integer(default=100) diff --git a/src/wxUI/dialogs/configuration.py b/src/wxUI/dialogs/configuration.py index abb2ec2..494a759 100644 --- a/src/wxUI/dialogs/configuration.py +++ b/src/wxUI/dialogs/configuration.py @@ -22,6 +22,12 @@ class general(wx.Panel, widgetUtils.BaseDialog): sizer.Add(box3, 0, wx.ALL, 5) self.load_images = wx.CheckBox(self, wx.NewId(), _(u"Load images in posts")) sizer.Add(self.load_images, 0, wx.ALL, 5) + lbl4 = wx.StaticText(self, wx.NewId(), _(u"Update channel")) + self.update_channel = wx.ComboBox(self, wx.NewId(), choices=[_(u"Stable"), _(u"Weekly"), _(u"Alpha")], value=_(u"Native"), style=wx.CB_READONLY) + box4 = wx.BoxSizer(wx.HORIZONTAL) + box4.Add(lbl4, 0, wx.ALL, 5) + box4.Add(self.update_channel, 0, wx.ALL, 5) + sizer.Add(box4, 0, wx.ALL, 5) self.SetSizer(sizer) class chat(wx.Panel, widgetUtils.BaseDialog): @@ -84,3 +90,8 @@ class configurationDialog(widgetUtils.BaseDialog): control = getattr(p, key) getattr(control, "SetValue")(value) +def alpha_channel(): + return wx.MessageDialog(None, _(u"The alpha channel contains bleeding edge changes introduced to Socializer. A new alpha update is generated every time there are new changes in the project. Take into account that updates are generated automatically and may fail at any time due to errors in the build process. Use alpha channels when you are sure you want to try the latest changes and contribute with reports to fix bugs. Never use alpha channel updates for everyday use. Do you want to continue?"), _(u"Attention"), style=wx.ICON_QUESTION|wx.YES_NO).ShowModal() + +def weekly_channel(): + return wx.MessageDialog(None, _(u"The weekly channel generates an update automatically every week by building the source code present in the project. This version is used to test features added to the next stable version. Do you want to continue?"), _(u"Attention"), style=wx.ICON_QUESTION|wx.YES_NO).ShowModal() \ No newline at end of file From a410c2a2f65ebbbcdae693889e6a23b53284761f Mon Sep 17 00:00:00 2001 From: Manuel Cortez Date: Thu, 27 Dec 2018 09:01:07 -0600 Subject: [PATCH 4/7] Removed weekly channel for now as there are no idea on how to track updates, yet --- src/wxUI/dialogs/configuration.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/wxUI/dialogs/configuration.py b/src/wxUI/dialogs/configuration.py index 494a759..52844cf 100644 --- a/src/wxUI/dialogs/configuration.py +++ b/src/wxUI/dialogs/configuration.py @@ -23,7 +23,7 @@ class general(wx.Panel, widgetUtils.BaseDialog): self.load_images = wx.CheckBox(self, wx.NewId(), _(u"Load images in posts")) sizer.Add(self.load_images, 0, wx.ALL, 5) lbl4 = wx.StaticText(self, wx.NewId(), _(u"Update channel")) - self.update_channel = wx.ComboBox(self, wx.NewId(), choices=[_(u"Stable"), _(u"Weekly"), _(u"Alpha")], value=_(u"Native"), style=wx.CB_READONLY) + self.update_channel = wx.ComboBox(self, wx.NewId(), choices=[_(u"Stable"), _(u"Alpha")], value=_(u"Native"), style=wx.CB_READONLY) box4 = wx.BoxSizer(wx.HORIZONTAL) box4.Add(lbl4, 0, wx.ALL, 5) box4.Add(self.update_channel, 0, wx.ALL, 5) From 833c089a2767be0fc84dd7134bca36379a6d3ccf Mon Sep 17 00:00:00 2001 From: Manuel Cortez Date: Thu, 27 Dec 2018 09:15:32 -0600 Subject: [PATCH 5/7] Added script to write data for versions in the alpha channel --- src/write_version_data.py | 19 +++++++++++++++++++ 1 file changed, 19 insertions(+) create mode 100644 src/write_version_data.py diff --git a/src/write_version_data.py b/src/write_version_data.py new file mode 100644 index 0000000..b4a646d --- /dev/null +++ b/src/write_version_data.py @@ -0,0 +1,19 @@ +#! /usr/bin/env python# -*- coding: iso-8859-1 -*- +""" Write version info (taken from the last commit) to application.py. This method has been implemented this way for running the alpha channel updates. +This file is not intended to be called by the user. It will be used only by the Gitlab CI runner.""" +import requests +from codecs import open + +print("Writing version data for alpha update...") +commit_info = requests.get("https://code.manuelcortez.net/api/v4/projects/4/repository/commits/master") +commit_info = commit_info.json() +commit = commit_info["short_id"] +print("Got new version info: {commit}".format(commit=commit,)) +file = open("application.py", "r", encoding="utf-8") +lines = file.readlines() +lines[-1] = 'update_next_version = "{commit}"'.format(commit=commit,) +file.close() +file2 = open("application.py", "w", encoding="utf-8") +file2.writelines(lines) +file2.close() +print("Wrote application.py with the new version info.") \ No newline at end of file From 2e025ebf20d8a47d8bd3538a991572657c950d3e Mon Sep 17 00:00:00 2001 From: Manuel Cortez Date: Thu, 27 Dec 2018 09:19:28 -0600 Subject: [PATCH 6/7] Modify gitlab CI configuration to generate both alpha and stable versions --- .gitlab-ci.yml | 33 ++++++++++++++++++++++++++++++--- 1 file changed, 30 insertions(+), 3 deletions(-) diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml index 96948e0..8b7c5b1 100644 --- a/.gitlab-ci.yml +++ b/.gitlab-ci.yml @@ -1,4 +1,32 @@ -production: +# Jobs to build the two channels in Socializer. +alpha: + type: deploy + tags: + - windows + script: + - pip install --upgrade pip + - pip install --upgrade -r requirements.txt + - copy changelog.md doc\changelog.md + - cd doc + - python documentation_importer.py + - cd ..\src + - python ..\doc\generator.py + - python write_version_data.py + - python setup.py py2exe + - cd .. + - cd scripts + - python prepare_zipversion.py + - cd .. + - move src\socializer.zip socializer.zip + only: + - master + artifacts: + paths: + - socializer.zip + name: socializer + expire_in: 1 week + +stable: type: deploy tags: - windows @@ -17,10 +45,9 @@ production: - cd .. - move src\socializer.zip socializer.zip only: - - schedules - tags artifacts: paths: - socializer.zip name: socializer - expire_in: 1 week \ No newline at end of file + expire_in: 1 month \ No newline at end of file From 8f52ae6f0c05b7535f267cafacf3e02a910fb57f Mon Sep 17 00:00:00 2001 From: Manuel Cortez Date: Thu, 27 Dec 2018 11:11:30 -0600 Subject: [PATCH 7/7] Updated calls to autoupdate feature for alpha channel --- src/controller/mainController.py | 4 ++-- src/update/update.py | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/src/controller/mainController.py b/src/controller/mainController.py index 7b7e594..50e803f 100644 --- a/src/controller/mainController.py +++ b/src/controller/mainController.py @@ -56,7 +56,7 @@ class Controller(object): self.create_controls() self.window.Show() self.connect_events() - call_threaded(updater.do_update) + call_threaded(updater.do_update, update_type=self.session.settings["general"]["update_channel"]) def create_controls(self): log.debug("Creating controls for the window...") @@ -266,7 +266,7 @@ class Controller(object): b.get_more_items() def check_for_updates(self, *args, **kwargs): - update = updater.do_update() + update = updater.do_update(update_type=self.session.settings["general"]["update_channel"]) if update == False: commonMessages.no_update_available() diff --git a/src/update/update.py b/src/update/update.py index 275a515..22fa4bf 100644 --- a/src/update/update.py +++ b/src/update/update.py @@ -24,7 +24,7 @@ def perform_update(endpoint, current_version, update_type="stable", app_name='', return False available_version, available_description, update_url = find_version_data(update_type, current_version, available_update) if available_version == False: - return + return False logger.info("A new update is available. Version %s" % available_version) if callable(update_available_callback) and not update_available_callback(version=available_version, description=available_description): #update_available_callback should return a falsy value to stop the process logger.info("User canceled update.")