mirror of
https://github.com/jellyfin/jellyfin-kodi.git
synced 2024-11-10 04:06:11 +00:00
migrate from generate_xml to build a full bundle zip
This commit is contained in:
parent
1bd73881cb
commit
632fac7809
6 changed files with 162 additions and 112 deletions
|
@ -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)
|
|
|
@ -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'
|
|
|
@ -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'
|
|
14
.github/workflows/build-publish.yaml
vendored
14
.github/workflows/build-publish.yaml
vendored
|
@ -28,19 +28,15 @@ jobs:
|
||||||
python -m pip install pyyaml
|
python -m pip install pyyaml
|
||||||
|
|
||||||
- name: Create ${{ matrix.py_version }} addon.xml
|
- 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
|
uses: actions/upload-artifact@v2
|
||||||
with:
|
with:
|
||||||
retention-days: 14
|
retention-days: 14
|
||||||
name: ${{ matrix.py_version }}-build-artifact
|
name: ${{ matrix.py_version }}-build-artifact
|
||||||
path: |
|
path: |
|
||||||
**/*
|
*.zip
|
||||||
!.ci/*
|
|
||||||
!.config/*
|
|
||||||
!.git/**/*
|
|
||||||
!.github/*
|
|
||||||
|
|
||||||
publish:
|
publish:
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
|
@ -53,10 +49,6 @@ jobs:
|
||||||
- uses: actions/download-artifact@v2
|
- uses: actions/download-artifact@v2
|
||||||
with:
|
with:
|
||||||
name: ${{ matrix.py_version }}-build-artifact
|
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
|
- name: Upload to repo server
|
||||||
uses: burnett01/rsync-deployments@4.1
|
uses: burnett01/rsync-deployments@4.1
|
||||||
|
|
125
build.py
Normal file
125
build.py
Normal file
|
@ -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)
|
33
release.yaml
33
release.yaml
|
@ -3,3 +3,36 @@ changelog: |
|
||||||
- #508 Use jellyfin's DisplayTitle for audio and subtitle streams
|
- #508 Use jellyfin's DisplayTitle for audio and subtitle streams
|
||||||
- #513 Fix subsequent syncs from the addon menu better
|
- #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'
|
||||||
|
|
Loading…
Reference in a new issue