Merge branch 'next' into 'master'

Modifications to release process. Closes #14

Closes #14

See merge request manuelcortez/socializer!1
This commit is contained in:
Manuel Cortez 2018-12-27 18:29:46 +03:00
commit 54247b8b90
8 changed files with 134 additions and 14 deletions

View File

@ -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 type: deploy
tags: tags:
- windows - windows
@ -17,10 +45,9 @@ production:
- cd .. - cd ..
- move src\socializer.zip socializer.zip - move src\socializer.zip socializer.zip
only: only:
- schedules
- tags - tags
artifacts: artifacts:
paths: paths:
- socializer.zip - socializer.zip
name: socializer name: socializer
expire_in: 1 week expire_in: 1 month

View File

@ -6,7 +6,6 @@ authorEmail = "manuel@manuelcortez.net"
copyright = u"Copyright (C) 2016-2018, Manuel Cortez" copyright = u"Copyright (C) 2016-2018, Manuel Cortez"
description = unicode(name+" Is an accessible VK client for Windows.") description = unicode(name+" Is an accessible VK client for Windows.")
url = "https://manuelcortez.net/socializer" 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. # The short name will be used for detecting translation files. See languageHandler for more details.
short_name = "socializer" short_name = "socializer"
translators = [u"Darya Ratnikova (Russian)", u"Manuel Cortez (Spanish)"] translators = [u"Darya Ratnikova (Russian)", u"Manuel Cortez (Spanish)"]
@ -14,3 +13,11 @@ bts_name = "socializer"
bts_access_token = "U29jaWFsaXplcg" bts_access_token = "U29jaWFsaXplcg"
bts_url = "https://issues.manuelcortez.net" bts_url = "https://issues.manuelcortez.net"
bts_project_id = 4 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"

View File

@ -16,6 +16,22 @@ class configuration(object):
else: else:
return _(u"Custom") 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): def __init__(self, session):
self.session = session self.session = session
self.dialog = configurationUI.configurationDialog(_(u"Preferences")) 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", "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", "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", "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.create_chat()
self.dialog.set_value("chat", "notify_online", self.session.settings["chat"]["notify_online"]) 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"]) self.dialog.set_value("chat", "notify_offline", self.session.settings["chat"]["notify_offline"])
@ -38,6 +55,18 @@ class configuration(object):
def save_configuration(self): def save_configuration(self):
self.session.settings["buffers"]["count_for_video_buffers"] = self.dialog.get_value("general", "video_buffers_count") 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") 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_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"]["notify_offline"] = self.dialog.get_value("chat", "notify_offline")
self.session.settings["chat"]["open_unread_conversations"] = self.dialog.get_value("chat", "open_unread_conversations") self.session.settings["chat"]["open_unread_conversations"] = self.dialog.get_value("chat", "open_unread_conversations")

View File

@ -7,6 +7,7 @@ use_alternative_tokens = boolean(default=False)
[general] [general]
reverse_timelines = boolean(default=False) reverse_timelines = boolean(default=False)
load_images = boolean(default=True) load_images = boolean(default=True)
update_channel = string(default="stable")
[buffers] [buffers]
count_for_wall_buffers = integer(default=100) count_for_wall_buffers = integer(default=100)

View File

@ -16,18 +16,15 @@ except ImportError:
from platform_utils import paths 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) requests_session = create_requests_session(app_name=app_name, version=current_version)
available_update = find_update(endpoint, requests_session=requests_session) available_update = find_update(endpoint, requests_session=requests_session)
if not available_update: if not available_update:
logger.debug("No update available") logger.debug("No update available")
return False return False
available_version = float(available_update['current_version']) available_version, available_description, update_url = find_version_data(update_type, current_version, available_update)
if not float(available_version) > float(current_version) or platform.system()+platform.architecture()[0][:2] not in available_update['downloads']: if available_version == False:
logger.debug("No update for this architecture") return
return False
available_description = available_update.get('description', None)
update_url = available_update ['downloads'][platform.system()+platform.architecture()[0][:2]]
logger.info("A new update is available. Version %s" % available_version) 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 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.") logger.info("User canceled update.")
@ -57,6 +54,29 @@ def find_update(endpoint, requests_session):
content = response.json() content = response.json()
return content 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): def download_update(update_url, update_destination, requests_session, progress_callback=None, chunk_size=io.DEFAULT_BUFFER_SIZE):
total_downloaded = total_size = 0 total_downloaded = total_size = 0
with io.open(update_destination, 'w+b') as outfile: with io.open(update_destination, 'w+b') as outfile:

View File

@ -8,9 +8,15 @@ from requests.exceptions import ConnectionError
from wxUpdater import * from wxUpdater import *
logger = logging.getLogger("updater") 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: 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: except ConnectionError:
logger.exception("Update failed.") 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) 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)

19
src/write_version_data.py Normal file
View File

@ -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.")

View File

@ -22,6 +22,12 @@ class general(wx.Panel, widgetUtils.BaseDialog):
sizer.Add(box3, 0, wx.ALL, 5) sizer.Add(box3, 0, wx.ALL, 5)
self.load_images = wx.CheckBox(self, wx.NewId(), _(u"Load images in posts")) self.load_images = wx.CheckBox(self, wx.NewId(), _(u"Load images in posts"))
sizer.Add(self.load_images, 0, wx.ALL, 5) 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"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) self.SetSizer(sizer)
class chat(wx.Panel, widgetUtils.BaseDialog): class chat(wx.Panel, widgetUtils.BaseDialog):
@ -84,3 +90,8 @@ class configurationDialog(widgetUtils.BaseDialog):
control = getattr(p, key) control = getattr(p, key)
getattr(control, "SetValue")(value) 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()