diff --git a/.ci/azure-pipelines.yml b/.ci/azure-pipelines.yml
new file mode 100644
index 00000000..754303a7
--- /dev/null
+++ b/.ci/azure-pipelines.yml
@@ -0,0 +1,9 @@
+# Starter pipeline
+# Start with a minimal pipeline that you can customize to build and deploy your code.
+# Add steps that build, run tests, deploy, and more:
+# https://aka.ms/yaml
+
+steps:
+  - template: build.yml
+    parameters:
+      py_versions: [ 'py2', 'py3' ]
diff --git a/.ci/build.yml b/.ci/build.yml
new file mode 100644
index 00000000..cc8f60a0
--- /dev/null
+++ b/.ci/build.yml
@@ -0,0 +1,43 @@
+parameters:
+  python_versions : []
+
+steps:
+  - ${{ each py_version in parameters.py_versions }}:
+    - task: usePythonVersion@0
+      inputs:
+        versionSpec: '3.6'
+
+    - checkout: self
+      clean: true
+
+    - script: python3 -m pip install --user pyyaml
+      displayName: 'Install PyYaml'
+
+    - script: python3 jellyfin-kodi/.config/generate_xml.py ${{ py_version }}
+      displayName: 'Create ${{ py_version }} addon.xml'
+
+    - task: ArchiveFiles@2
+      displayName: 'Create ${{ py_version }} zip file'
+      inputs:
+        rootFolderOrFile: jellyfin-kodi
+        includeRootFolder: False
+        archiveType: 'zip'
+        tarCompression: 'none'
+        archiveFile: 'plugin.video.jellyfin-${{ py_version }}.zip'
+
+    - task: CopyFilesOverSSH@0
+      displayName: 'Upload to repo server'
+      inputs:
+        sshEndpoint: repository
+        sourceFolder: '${Agent.BuildDirectory}'
+        contents: 'plugin.video.jellyfin-${{ py-version }}.zip'
+        targetFolder: '/srv/repository/incoming/kodi'
+      condition: startsWith(variables['Build.SourceBranch'], 'refs/tags')
+
+    - task: SSH@0
+      displayName: 'Add to Kodi repo'
+      inputs:
+        sshEndpoint: repository
+        runOptions: 'commands'
+        commands: 'sudo -n python3 /usr/local/bin/kodirepo add /srv/repository/incoming/kodi/plugin.video.jellyfin-${{ py_version }} --datadir /srv/repository/releases/client/kodi/${{ py_version }}'
+      condition: startsWith(variables['Build.SourceBranch'], 'refs/tags')
diff --git a/.config/generate_xml.py b/.config/generate_xml.py
new file mode 100644
index 00000000..a35b995e
--- /dev/null
+++ b/.config/generate_xml.py
@@ -0,0 +1,67 @@
+import xml.etree.ElementTree as ET
+import yaml
+import sys
+import os
+from datetime import datetime
+
+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(f'{dir_path}/template.xml', 'r') as f:
+    tree = ET.parse(f)
+    root = tree.getroot()
+
+# Load version dependencies
+with open(f'{dir_path}/{py_version}.yaml', 'r') as f:
+    deps = yaml.safe_load(f)
+
+# Load version and changelog
+with open('jellyfin-kodi/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'] = f'{addon_version}+{py_version}'
+
+# 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 = f'v{addon_version} ({date}):\n{changelog}'
+
+# Format xml tree
+indent(root)
+
+# Write addon.xml
+tree.write('jellyfin-kodi/addon.xml', encoding='utf-8', xml_declaration=True)
diff --git a/.config/py2.yaml b/.config/py2.yaml
new file mode 100644
index 00000000..f673c810
--- /dev/null
+++ b/.config/py2.yaml
@@ -0,0 +1,14 @@
+- 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'
diff --git a/.config/py3.yaml b/.config/py3.yaml
new file mode 100644
index 00000000..83d2d87f
--- /dev/null
+++ b/.config/py3.yaml
@@ -0,0 +1,12 @@
+- 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'
diff --git a/addon.xml b/.config/template.xml
similarity index 81%
rename from addon.xml
rename to .config/template.xml
index a5deaed0..ee6bb514 100644
--- a/addon.xml
+++ b/.config/template.xml
@@ -1,16 +1,9 @@
 <?xml version="1.0" encoding="UTF-8" standalone="yes"?>
 <addon  id="plugin.video.jellyfin"
         name="Jellyfin"
-        version="0.5.8"
+        version=""
         provider-name="Jellyfin Contributors, angelblue05">
   <requires>
-    <import addon="xbmc.python" version="2.25.0"/>
-    <import addon="script.module.requests" version="2.22.0"/>
-    <import addon="script.module.dateutil" version="2.7.3"/>
-    <import addon="script.module.six" version="1.13.0"/>
-    <import addon="script.module.kodi-six" />
-    <import addon="script.module.addon.signals" version="0.0.1"/>
-    <import addon="script.module.futures" version="2.2.0"/>
   </requires>
   <extension    point="xbmc.python.pluginsource"
                 library="default.py">
@@ -35,13 +28,11 @@
     <language>en</language>
     <license>GNU GENERAL PUBLIC LICENSE. Version 3, 29 June 2007</license>
     <forum>https://forum.jellyfin.org</forum>
-    <website>https://jellyfin.media/</website>
+    <website>https://jellyfin.org/</website>
     <source>https://github.com/jellyfin/jellyfin-kodi</source>
     <summary lang="en"></summary>
     <description lang="en">Welcome to Jellyfin for Kodi!&#10;A whole new way to manage and view your media library. The Jellyfin addon for Kodi combines the best of Kodi - ultra smooth navigation, beautiful UIs and playback of any file under the sun, and Jellyfin - the most powerful fully open source multi-client media metadata indexer and server.&#10;&#10;Jellyfin for Kodi is the absolute best way to enjoy the incredible Kodi playback engine combined with the power of Jellyfin's centralized database. Features:&#10;* Direct integration with the Kodi library for native Kodi speed&#10;* Instant synchronization with the Jellyfin server&#10;* Full support for Movie, TV and Music collections&#10;* Jellyfin Server direct stream and transcoding support - use Kodi when you are away from home!</description>
     <news>
-    v0.5.8 (2020-06-15)
-      #322 Force filter parameter during incremental sync
     </news>
     <assets>
       <icon>resources/icon.png</icon>
diff --git a/.gitignore b/.gitignore
index c79bce8b..8e87645e 100644
--- a/.gitignore
+++ b/.gitignore
@@ -9,3 +9,4 @@ machine_guid
 .vscode/
 pyinstrument/
 pyinstrument_cext.so
+addon.xml
diff --git a/release.yaml b/release.yaml
new file mode 100644
index 00000000..432f05d3
--- /dev/null
+++ b/release.yaml
@@ -0,0 +1,3 @@
+version: '0.5.8'
+changelog: |
+  #322 Force filter parameter during incremental sync