From 632fac78093758911a1d00700809085f24ff489d Mon Sep 17 00:00:00 2001 From: h1dden-da3m0n <33120068+h1dden-da3m0n@users.noreply.github.com> Date: Sun, 23 May 2021 20:17:06 +0200 Subject: [PATCH] migrate from generate_xml to build a full bundle zip --- .config/generate_xml.py | 70 --------------- .config/py2.yaml | 16 ---- .config/py3.yaml | 14 --- .github/workflows/build-publish.yaml | 14 +-- build.py | 125 +++++++++++++++++++++++++++ release.yaml | 35 +++++++- 6 files changed, 162 insertions(+), 112 deletions(-) delete mode 100644 .config/generate_xml.py delete mode 100644 .config/py2.yaml delete mode 100644 .config/py3.yaml create mode 100644 build.py diff --git a/.config/generate_xml.py b/.config/generate_xml.py deleted file mode 100644 index 025e8f74..00000000 --- a/.config/generate_xml.py +++ /dev/null @@ -1,70 +0,0 @@ -import xml.etree.ElementTree as ET -import sys -import os -from datetime import datetime - -import yaml - - -def indent(elem, level=0): - ''' - Nicely formats output xml with newlines and spaces - https://stackoverflow.com/a/33956544 - ''' - i = "\n" + level*" " - if len(elem): - if not elem.text or not elem.text.strip(): - elem.text = i + " " - if not elem.tail or not elem.tail.strip(): - elem.tail = i - for elem in elem: - indent(elem, level+1) - if not elem.tail or not elem.tail.strip(): - elem.tail = i - else: - if level and (not elem.tail or not elem.tail.strip()): - elem.tail = i - - -try: - py_version = sys.argv[1] -except IndexError: - print('No version specified') - sys.exit(1) - -dir_path = os.path.dirname(os.path.realpath(__file__)) - -# Load template file -with open('{dir_path}/template.xml'.format(**locals()), 'r') as f: - tree = ET.parse(f) - root = tree.getroot() - -# Load version dependencies -with open('{dir_path}/{py_version}.yaml'.format(**locals()), 'r') as f: - deps = yaml.safe_load(f) - -# Load version and changelog -with open('release.yaml', 'r') as f: - data = yaml.safe_load(f) - -# Populate xml template -for dep in deps: - ET.SubElement(root.find('requires'), 'import', attrib=dep) - -# Update version string -addon_version = data.get('version') -root.attrib['version'] = '{addon_version}+{py_version}'.format(**locals()) - -# Changelog -date = datetime.today().strftime('%Y-%m-%d') -changelog = data.get('changelog') -for section in root.findall('extension'): - news = section.findall('news') - if news: - news[0].text = 'v{addon_version} ({date}):\n{changelog}'.format(**locals()) - -# Format xml tree -indent(root) - -# Write addon.xml -tree.write('addon.xml', encoding='utf-8', xml_declaration=True) diff --git a/.config/py2.yaml b/.config/py2.yaml deleted file mode 100644 index 244f1c64..00000000 --- a/.config/py2.yaml +++ /dev/null @@ -1,16 +0,0 @@ -- addon: 'xbmc.python' - version: '2.25.0' -- addon: 'script.module.requests' - version: '2.22.0' -- addon: 'script.module.dateutil' - version: '2.8.1' -- addon: 'script.module.six' - version: '1.13.0' -- addon: 'script.module.kodi-six' - version: '0.0.7' -- addon: 'script.module.addon.signals' - version: '0.0.5' -- addon: 'script.module.futures' - version: '2.2.0' -- addon: 'script.module.websocket' - version: '0.57.0' diff --git a/.config/py3.yaml b/.config/py3.yaml deleted file mode 100644 index c8a12418..00000000 --- a/.config/py3.yaml +++ /dev/null @@ -1,14 +0,0 @@ -- addon: 'xbmc.python' - version: '3.0.0' -- addon: 'script.module.requests' - version: '2.22.0+matrix.1' -- addon: 'script.module.dateutil' - version: '2.8.1+matrix.1' -- addon: 'script.module.six' - version: '1.14.0+matrix.2' -- addon: 'script.module.kodi-six' - version: '0.1.3+1' -- addon: 'script.module.addon.signals' - version: '0.0.5+matrix.1' -- addon: 'script.module.websocket' - version: '0.58.0+matrix.1' diff --git a/.github/workflows/build-publish.yaml b/.github/workflows/build-publish.yaml index d858df07..6680830f 100644 --- a/.github/workflows/build-publish.yaml +++ b/.github/workflows/build-publish.yaml @@ -28,19 +28,15 @@ jobs: python -m pip install pyyaml - name: Create ${{ matrix.py_version }} addon.xml - run: python .config/generate_xml.py ${{ matrix.py_version }} + run: python build.py --version ${{ matrix.py_version }} - - name: Publish Build Atrifact + - name: Publish Build Artifact uses: actions/upload-artifact@v2 with: retention-days: 14 name: ${{ matrix.py_version }}-build-artifact path: | - **/* - !.ci/* - !.config/* - !.git/**/* - !.github/* + *.zip publish: runs-on: ubuntu-latest @@ -53,10 +49,6 @@ jobs: - uses: actions/download-artifact@v2 with: name: ${{ matrix.py_version }}-build-artifact - path: plugin.video.jellyfin-${{ matrix.py_version }} - - - name: Create release Zip - run: zip -rq plugin.video.jellyfin-${{ matrix.py_version }}.zip plugin.video.jellyfin-${{ matrix.py_version }} - name: Upload to repo server uses: burnett01/rsync-deployments@4.1 diff --git a/build.py b/build.py new file mode 100644 index 00000000..762d14ea --- /dev/null +++ b/build.py @@ -0,0 +1,125 @@ +#!/usr/bin/env python + +import argparse +import os +import xml.etree.ElementTree as ET +import zipfile +from datetime import datetime +from pathlib import Path + +import yaml + + +def indent(elem: ET.Element, level: int = 0) -> None: + """ + Nicely formats output xml with newlines and spaces + https://stackoverflow.com/a/33956544 + """ + i = "\n" + level * " " + if len(elem): + if not elem.text or not elem.text.strip(): + elem.text = i + " " + if not elem.tail or not elem.tail.strip(): + elem.tail = i + for elem in elem: + indent(elem, level + 1) + if not elem.tail or not elem.tail.strip(): + elem.tail = i + else: + if level and (not elem.tail or not elem.tail.strip()): + elem.tail = i + + +def create_addon_xml(config: dict, source: str, py_version: str) -> None: + """ + Create addon.xml from template file + """ + # Load template file + with open('{}/.config/template.xml'.format(source), 'r') as f: + tree = ET.parse(f) + root = tree.getroot() + + # Populate dependencies in template + dependencies = config['dependencies'].get(py_version) + for dep in dependencies: + ET.SubElement(root.find('requires'), 'import', attrib=dep) + + # Populate version string + addon_version = config.get('version') + root.attrib['version'] = '{}+{}'.format(addon_version, py_version) + + # Populate Changelog + date = datetime.today().strftime('%Y-%m-%d') + changelog = config.get('changelog') + for section in root.findall('extension'): + news = section.findall('news') + if news: + news[0].text = 'v{} ({}):\n{}'.format(addon_version, date, changelog) + + # Format xml tree + indent(root) + + # Write addon.xml + tree.write('{}/addon.xml'.format(source), encoding='utf-8', xml_declaration=True) + + +def zip_files(py_version: str, source: str, target: str) -> None: + """ + Create installable addon zip archive + """ + archive_name = 'plugin.video.jellyfin+{}.zip'.format(py_version) + + with zipfile.ZipFile('{}/{}'.format(target, archive_name), 'w') as z: + for root, dirs, files in os.walk(args.source): + for filename in filter(file_filter, files): + file_path = os.path.join(root, filename) + if folder_filter(file_path): + relative_path = os.path.join('plugin.video.jellyfin', os.path.relpath(file_path, source)) + z.write(file_path, relative_path) + + +def file_filter(file_name: str) -> bool: + """ + True if file_name is meant to be included + """ + return 'plugin.video.jellyfin' not in file_name and 'pyo' not in file_name + + +def folder_filter(folder_name: str) -> bool: + """ + True if folder_name is meant to be included + """ + return ('.ci' not in folder_name + and '.git' not in folder_name + and '.github' not in folder_name + and '.config' not in folder_name) + + +if __name__ == '__main__': + parser = argparse.ArgumentParser(description='Build flags:') + parser.add_argument( + '--version', + type=str, + choices=('py2', 'py3'), + default='py3') + + parser.add_argument( + '--source', + type=Path, + default=Path(__file__).absolute().parent) + + parser.add_argument( + '--target', + type=Path, + default=Path(__file__).absolute().parent) + + args = parser.parse_args() + + # Load config file + config_path = os.path.join(args.source, 'release.yaml') + with open(config_path, 'r') as fh: + release_config = yaml.safe_load(fh) + + create_addon_xml(release_config, args.source, args.version) + + zip_files(args.version, args.source, args.target) diff --git a/release.yaml b/release.yaml index fa4c7ada..cfb8cd95 100644 --- a/release.yaml +++ b/release.yaml @@ -2,4 +2,37 @@ version: '0.7.3' changelog: | - #508 Use jellyfin's DisplayTitle for audio and subtitle streams - #513 Fix subsequent syncs from the addon menu better - - #515 Allow multiple subtitles with identical names + - #515 Allow multiple subtitles with identical names +dependencies: + py2: + - addon: 'xbmc.python' + version: '2.25.0' + - addon: 'script.module.requests' + version: '2.22.0' + - addon: 'script.module.dateutil' + version: '2.8.1' + - addon: 'script.module.six' + version: '1.13.0' + - addon: 'script.module.kodi-six' + version: '0.0.7' + - addon: 'script.module.addon.signals' + version: '0.0.5' + - addon: 'script.module.futures' + version: '2.2.0' + - addon: 'script.module.websocket' + version: '0.57.0' + py3: + - addon: 'xbmc.python' + version: '3.0.0' + - addon: 'script.module.requests' + version: '2.22.0+matrix.1' + - addon: 'script.module.dateutil' + version: '2.8.1+matrix.1' + - addon: 'script.module.six' + version: '1.14.0+matrix.2' + - addon: 'script.module.kodi-six' + version: '0.1.3+1' + - addon: 'script.module.addon.signals' + version: '0.0.5+matrix.1' + - addon: 'script.module.websocket' + version: '0.58.0+matrix.1'