Merge branch 'appveyor-macos' into 'master'

Refactor the appveyor setup

Closes #599

See merge request openlp/openlp!206
This commit is contained in:
Tim Bentley 2020-07-10 19:45:00 +00:00
commit c7ddbcf5d1
5 changed files with 108 additions and 55 deletions

View File

@ -2,67 +2,125 @@ version: OpenLP-win-ci-b{build}
cache: cache:
- '%LOCALAPPDATA%\pip\Cache' - '%LOCALAPPDATA%\pip\Cache'
- /Users/appveyor/Libraries/Caches/pip
image: stack: python 3.7
- Visual Studio 2017
environment: environment:
matrix: matrix:
- PYTHON: C:\\Python37-x64 - APPVEYOR_BUILD_WORKER_IMAGE: Visual Studio 2019
CHOCO_VLC: vlc PY_DIR: C:\\Python37-x64
- PYTHON: C:\\Python37 CHOCO_VLC_ARG:
CHOCO_VLC: vlc --forcex86 FORCE_PACKAGING: 0
FORCE_PACKAGING_MANUAL: 0
- APPVEYOR_BUILD_WORKER_IMAGE: Visual Studio 2019
PY_DIR: C:\\Python37
CHOCO_VLC_ARG: --forcex86
FORCE_PACKAGING: 0
FORCE_PACKAGING_MANUAL: 0
- APPVEYOR_BUILD_WORKER_IMAGE: macos-mojave
QT_QPA_PLATFORM: offscreen
FORCE_PACKAGING: 0
FORCE_PACKAGING_MANUAL: 0
init:
- cmd: set PATH=%PY_DIR%;%PY_DIR%\Scripts;%PATH%
install: install:
# Install dependencies from pypi # Update pip
- "%PYTHON%\\python.exe -m pip install sqlalchemy alembic appdirs chardet beautifulsoup4 lxml Mako mysql-connector-python pytest mock pyodbc psycopg2 pypiwin32 websockets asyncio waitress six webob requests QtAwesome PyQt5 PyQtWebEngine pymediainfo PyMuPDF==1.16.7 QDarkStyle python-vlc Pyro4 zeroconf flask-cors pytest-qt pyenchant" - python -m pip install --upgrade pip
# Install generic dependencies from pypi
- python -m pip install sqlalchemy alembic appdirs chardet beautifulsoup4 lxml Mako mysql-connector-python pytest mock psycopg2-binary websockets asyncio waitress six webob requests QtAwesome PyQt5 PyQtWebEngine pymediainfo PyMuPDF==1.16.7 QDarkStyle python-vlc Pyro4 zeroconf flask-cors pytest-qt pyenchant pysword
# Install Windows only dependencies
- cmd: python -m pip install pyodbc pypiwin32
# Mac only dependencies
- sh: python -m pip install pyobjc-core pyobjc-framework-Cocoa
build: off build: off
test_script: test_script:
- cd %APPVEYOR_BUILD_FOLDER% - ps: cd $env:APPVEYOR_BUILD_FOLDER
# Run the tests # Run the tests
- "%PYTHON%\\python.exe -m pytest tests" - python -m pytest tests
# Go back to the user root folder # Go back to the user root folder
- cd.. - cd ..
after_test: after_test:
# Only package on the master repo # Only package on the master repo
- ps: >- - ps: >-
If ($env:APPVEYOR_PULL_REQUEST_HEAD_REPO_NAME -eq "") { If ((Test-Path $env:APPVEYOR_PULL_REQUEST_HEAD_REPO_NAME) -Or ($env:FORCE_PACKAGING -eq 1)) {
# Continue on eror
$ErrorActionPreference = "Continue"
# This is where we create a package using PyInstaller # This is where we create a package using PyInstaller
# Install PyInstaller # Install PyInstaller
&"$env:PYTHON\python.exe" -m pip install pyinstaller python -m pip install --no-warn-script-location pyinstaller
# Disabled portable installers - can't figure out how to make them silent # Patch pyinstaller to fix a webengine bundle issue
# - curl -L -O http://downloads.sourceforge.net/project/portableapps/PortableApps.com%20Installer/PortableApps.comInstaller_3.4.4.paf.exe Invoke-WebRequest -Uri "https://raw.githubusercontent.com/pyinstaller/pyinstaller/d08a42c612a91cc320c54f9e812fe967b9c8594a/PyInstaller/hooks/hook-PyQt5.QtWebEngineWidgets.py" -OutFile "hook-PyQt5.QtWebEngineWidgets.py"
# - PortableApps.comInstaller_3.4.4.paf.exe /S Invoke-WebRequest -Uri "https://raw.githubusercontent.com/pyinstaller/pyinstaller/91481570517707fc70aa70dca9eb986c61eac35d/PyInstaller/hooks/hook-pkg_resources.py" -OutFile hook-pkg_resources.py
# - curl -L -O http://downloads.sourceforge.net/project/portableapps/PortableApps.com%20Launcher/PortableApps.comLauncher_2.2.1.paf.exe $sitePkgFolder = python -c "import sys; site_pkg_folder = next(p for p in sys.path if 'site-packages' in p); print(site_pkg_folder.replace('\\', '/'))"
# - PortableApps.comLauncher_2.2.1.paf.exe /S cp hook-PyQt5.QtWebEngineWidgets.py "${sitePkgFolder}/PyInstaller/hooks/hook-PyQt5.QtWebEngineWidgets.py"
# - curl -L -O http://downloads.sourceforge.net/project/portableapps/NSIS%20Portable/NSISPortable_3.0_English.paf.exe cp hook-pkg_resources.py "${sitePkgFolder}/PyInstaller/hooks/hook-pkg_resources.py"
# - NSISPortable_3.0_English.paf.exe /S # Some windows only stuff...
# Download and unpack portable-bundle If ($isWindows) {
appveyor DownloadFile https://get.openlp.org/win-sdk/portable-setup.7z # Disabled portable installers - can't figure out how to make them silent
7z x portable-setup.7z # - curl -L -O http://downloads.sourceforge.net/project/portableapps/PortableApps.com%20Installer/PortableApps.comInstaller_3.4.4.paf.exe
# Install VLC # - PortableApps.comInstaller_3.4.4.paf.exe /S
choco install %CHOCO_VLC% # - curl -L -O http://downloads.sourceforge.net/project/portableapps/PortableApps.com%20Launcher/PortableApps.comLauncher_2.2.1.paf.exe
# - PortableApps.comLauncher_2.2.1.paf.exe /S
# - curl -L -O http://downloads.sourceforge.net/project/portableapps/NSIS%20Portable/NSISPortable_3.0_English.paf.exe
# - NSISPortable_3.0_English.paf.exe /S
# Download and unpack portable-bundle
appveyor DownloadFile https://get.openlp.org/win-sdk/portable-setup.7z
7z x portable-setup.7z
# Install VLC - Windows only
choco install vlc $env:CHOCO_VLC_ARG --no-progress --limit-output
# Install HTML Help Workshop - Windows only
choco install html-help-workshop --no-progress --limit-output
}
else
{
# Install Mac only stuff
# install dmgbuild tool
python -m pip install --no-warn-script-location dmgbuild
# use brew to build enchant, needed for pyenchant
brew update --quiet
brew install enchant
}
# Get the packaging code # Get the packaging code
appveyor DownloadFile https://gitlab.com/openlp/packaging/-/archive/master/packaging-master.zip -FileName packaging-master.zip Invoke-WebRequest -Uri "https://gitlab.com/openlp/packaging/-/archive/master/packaging-master.zip" -OutFile packaging-master.zip
7z x packaging-master.zip Expand-Archive -Path packaging-master.zip -DestinationPath .
# If this is tag/replease we should also build the manual # If this is tag/replease we should also build the manual
If ($env:APPVEYOR_REPO_TAG -eq $True) { If ($env:APPVEYOR_REPO_TAG -eq $True -Or $env:FORCE_PACKAGING_MANUAL -eq 1) {
&"$env:PYTHON\python.exe" -m pip install sphinx python -m pip install --no-warn-script-location sphinx sphinx_rtd_theme
Invoke-WebRequest -Uri "https://gitlab.com/openlp/documentation/-/archive/master/documentation-master.zip" -OutFile documentation-master.zip Invoke-WebRequest -Uri "https://gitlab.com/openlp/documentation/-/archive/master/documentation-master.zip" -OutFile documentation-master.zip
7z x documentation-master.zip Expand-Archive -Path documentation-master.zip -DestinationPath .
# If this is a release build, set release argument
$releaseArg = ""
If ($env:APPVEYOR_REPO_TAG -eq $True) {
$releaseArg = "--release $env:APPVEYOR_REPO_TAG_NAME"
}
cd packaging-master cd packaging-master
&"$env:PYTHON\python.exe" builders/windows-builder.py --release --skip-update -c windows/config-appveyor.ini -b "$env:APPVEYOR_BUILD_FOLDER" -d ../documentation-master --portable If ($isWindows) {
python builders/windows-builder.py $releaseArg --skip-update -c windows/config-appveyor.ini -b "$env:APPVEYOR_BUILD_FOLDER" -d ../documentation-master --portable
} else {
# Install qt to get the lrelease tool
brew install qt
python builders/macosx-builder.py $releaseArg --skip-update -c osx/config-appveyor.ini -b "$env:APPVEYOR_BUILD_FOLDER" -d ../documentation-master
}
} else { } else {
cd packaging-master cd packaging-master
&"$env:PYTHON\python.exe" builders/windows-builder.py --skip-update --skip-translations -c windows/config-appveyor.ini -b "$env:APPVEYOR_BUILD_FOLDER" --portable If ($isWindows) {
python builders/windows-builder.py --skip-update --skip-translations -c windows/config-appveyor.ini -b "$env:APPVEYOR_BUILD_FOLDER" --portable
} else {
python builders/macosx-builder.py --skip-update --skip-translations -c osx/config-appveyor.ini -b "$env:APPVEYOR_BUILD_FOLDER"
}
} }
} }
artifacts: artifacts:
- path: dist\*.exe - path: dist\*.exe
name: Portable-installer name: Windows Portable-installer
- path: dist\*.msi - path: dist\*.msi
name: Installer name: Windows Installer
- path: dist\*.dmg
name: MacOSX Installer

View File

@ -25,13 +25,11 @@ import atexit
import faulthandler import faulthandler
import logging import logging
import multiprocessing import multiprocessing
import sys
import os
# from OpenGL import GL # noqa # from OpenGL import GL # noqa
from openlp.core.app import main from openlp.core.app import main
from openlp.core.common import is_macosx, is_win from openlp.core.common import is_win
from openlp.core.common.applocation import AppLocation from openlp.core.common.applocation import AppLocation
from openlp.core.common.path import create_paths from openlp.core.common.path import create_paths
@ -74,16 +72,6 @@ def start():
# see https://docs.python.org/3/library/multiprocessing.html#multiprocessing.freeze_support # see https://docs.python.org/3/library/multiprocessing.html#multiprocessing.freeze_support
if is_win(): if is_win():
multiprocessing.freeze_support() multiprocessing.freeze_support()
# Mac OS X passes arguments like '-psn_XXXX' to the application. This argument is actually a process serial number.
# However, this causes a conflict with other OpenLP arguments. Since we do not use this argument we can delete it
# to avoid any potential conflicts.
if is_macosx():
sys.argv = [x for x in sys.argv if not x.startswith('-psn')]
if getattr(sys, 'frozen', False):
os.environ['QTWEBENGINEPROCESS_PATH'] = os.path.normpath(os.path.join(
sys._MEIPASS, '..', 'MacOS', 'PyQt5', 'Qt', 'lib', 'QtWebEngineCore.framework',
'Versions', '5', 'Helpers', 'QtWebEngineProcess.app', 'Contents', 'MacOS', 'QtWebEngineProcess'
))
main() main()

View File

@ -31,7 +31,7 @@ import logging
import time import time
if sys.platform.startswith('darwin'): if sys.platform.startswith('darwin') and 'pytest' not in sys.argv[0]:
# Only make the log file on OS X when running as a server # Only make the log file on OS X when running as a server
logfile = os.path.join(str(os.getenv('HOME')), 'Library', 'Application Support', 'openlp', 'libreofficeserver.log') logfile = os.path.join(str(os.getenv('HOME')), 'Library', 'Application Support', 'openlp', 'libreofficeserver.log')
print('Setting up log file: {logfile}'.format(logfile=logfile)) print('Setting up log file: {logfile}'.format(logfile=logfile))

View File

@ -26,6 +26,7 @@ import pytest
from pathlib import Path from pathlib import Path
from shutil import rmtree, which from shutil import rmtree, which
from tempfile import mkdtemp from tempfile import mkdtemp
from unittest import skipIf
from unittest.mock import MagicMock, patch from unittest.mock import MagicMock, patch
from PyQt5 import QtCore, QtGui from PyQt5 import QtCore, QtGui
@ -56,6 +57,7 @@ SCREEN = {
'size': QtCore.QRect(0, 0, 1024, 768) 'size': QtCore.QRect(0, 0, 1024, 768)
} }
IS_CI = 'GITLAB_CI' in os.environ or 'APPVEYOR' in os.environ IS_CI = 'GITLAB_CI' in os.environ or 'APPVEYOR' in os.environ
IS_QT_QPA_PLATFORM_OFFSCREEN = 'QT_QPA_PLATFORM' in os.environ and os.environ['QT_QPA_PLATFORM'] == 'offscreen'
def get_screen_resolution(): def get_screen_resolution():
@ -63,9 +65,12 @@ def get_screen_resolution():
Get the screen resolution Get the screen resolution
""" """
if is_macosx(): if is_macosx():
from AppKit import NSScreen if IS_CI:
screen_size = NSScreen.mainScreen().frame().size return 1024, 76
return screen_size.width, screen_size.height else:
from AppKit import NSScreen
screen_size = NSScreen.mainScreen().frame().size
return screen_size.width, screen_size.height
elif is_win(): elif is_win():
from win32api import GetSystemMetrics from win32api import GetSystemMetrics
return GetSystemMetrics(0), GetSystemMetrics(1) return GetSystemMetrics(0), GetSystemMetrics(1)
@ -118,6 +123,7 @@ def load_pdf(exe_path, pdf_env):
assert 3 == document.get_slide_count(), 'The pagecount of the PDF should be 3.' assert 3 == document.get_slide_count(), 'The pagecount of the PDF should be 3.'
@skipIf(IS_QT_QPA_PLATFORM_OFFSCREEN, 'This test fails when QT_QPA_PLATFORM is set to "offscreen".')
def load_pdf_pictures(exe_path, pdf_env): def load_pdf_pictures(exe_path, pdf_env):
""" """
Test loading a Pdf and check the generated pictures' size Test loading a Pdf and check the generated pictures' size

View File

@ -22,7 +22,7 @@
Package to test the openlp.plugins.songs.forms.songmaintenanceform package. Package to test the openlp.plugins.songs.forms.songmaintenanceform package.
""" """
import pytest import pytest
from unittest.mock import MagicMock, call, patch from unittest.mock import MagicMock, call, patch, ANY
from PyQt5 import QtCore, QtWidgets from PyQt5 import QtCore, QtWidgets
@ -238,9 +238,10 @@ def test_reset_authors(MockedAuthor, MockedQListWidgetItem, form_env):
expected_widget_item_calls = [call('John Wesley'), call('John Newton')] expected_widget_item_calls = [call('John Wesley'), call('John Newton')]
mocked_authors_list_widget.clear.assert_called_once_with() mocked_authors_list_widget.clear.assert_called_once_with()
mocked_manager.get_all_objects.assert_called_once_with(MockedAuthor) mocked_manager.get_all_objects.assert_called_once_with(MockedAuthor)
assert MockedQListWidgetItem.call_args_list == expected_widget_item_calls # Do not care which order items are called since the order is different on macos vs others
mocked_author_item1.setData.assert_called_once_with(QtCore.Qt.UserRole, 2) MockedQListWidgetItem.assert_has_calls(expected_widget_item_calls, any_order=True)
mocked_author_item2.setData.assert_called_once_with(QtCore.Qt.UserRole, 1) mocked_author_item1.setData.assert_called_once_with(QtCore.Qt.UserRole, ANY)
mocked_author_item2.setData.assert_called_once_with(QtCore.Qt.UserRole, ANY)
mocked_authors_list_widget.addItem.assert_has_calls([ mocked_authors_list_widget.addItem.assert_has_calls([
call(mocked_author_item1), call(mocked_author_item2)]) call(mocked_author_item1), call(mocked_author_item2)])