1
0
Fork 0
mirror of https://github.com/borgbase/vorta synced 2024-12-23 00:07:58 +00:00
vorta/generate_appcast.py

102 lines
3.8 KiB
Python

import sys
import requests
from lxml import etree as ET
from xml.dom import minidom
import argparse
import markdown
# GitHub repository details (owner and repo name)
GITHUB_REPO_OWNER = "borgbase"
GITHUB_REPO_NAME = "vorta"
GITHUB_API_URL = f"https://api.github.com/repos/{GITHUB_REPO_OWNER}/{GITHUB_REPO_NAME}/releases"
# Function to fetch release information using the GitHub API
def fetch_github_releases():
response = requests.get(GITHUB_API_URL)
if response.status_code == 200:
return response.json()
else:
raise Exception(f"Failed to fetch releases: {response.status_code}")
# Function to create Appcast XML
def generate_appcast_xml(releases, include_prereleases=False):
nsmap = {
'sparkle': "http://www.andymatuschak.org/xml-namespaces/sparkle",
'dc': "http://purl.org/dc/elements/1.1/"
}
rss = ET.Element("rss", version="2.0", nsmap=nsmap)
channel = ET.SubElement(rss, "channel")
# Required fields for the Appcast
title = ET.SubElement(channel, "title")
title.text = "Vorta Updates"
link = ET.SubElement(channel, "link")
link.text = f"https://borgbase.github.io/vorta/{args.output}" # Change to your actual Appcast URL
description = ET.SubElement(channel, "description")
description.text = "Latest updates for the app."
language = ET.SubElement(channel, "language")
language.text = "en"
# Add release entries to the Appcast
for release in releases:
if not include_prereleases and release['prerelease']:
continue # Skip pre-releases if not requested
item = ET.SubElement(channel, "item")
item_title = ET.SubElement(item, "title")
item_title.text = release['tag_name']
item_description = ET.SubElement(item, "description")
item_description.text = ET.CDATA(markdown.markdown(release.get("body", "No release notes available")))
pub_date = ET.SubElement(item, "pubDate")
pub_date.text = release["published_at"]
# Add enclosure for attached assets (assuming one main asset per release)
for asset in release.get("assets", []):
enclosure = ET.SubElement(item, "enclosure", url=asset['browser_download_url'], length=str(asset['size']), type=asset['content_type'])
enclosure.set(f"{{{nsmap['sparkle']}}}version", release['tag_name'])
break # Include only one main file per release, remove break for multiple
# Convert the XML tree to a nicely formatted string
xml_str = ET.tostring(rss, encoding="utf-8", method="xml")
parsed = minidom.parseString(xml_str)
return parsed.toprettyxml(indent=" ")
# Function to handle the creation of the appcast XML file
def write_appcast_to_file(appcast_xml, filename):
with open(filename, "w") as file:
file.write(appcast_xml)
print(f"Appcast XML written to {filename}")
if __name__ == "__main__":
# Argument parser for handling command-line options
parser = argparse.ArgumentParser(description="Generate Appcast XML from GitHub releases.")
parser.add_argument(
'--include-prereleases',
action='store_true',
help='Include pre-releases'
)
parser.add_argument(
'output',
type=str,
help='Output file to write to. Usually appcast.xml or appcast-pre.xml'
)
try:
args = parser.parse_args()
except argparse.ArgumentError as exc:
print(f"Error: {exc}")
parser.print_help()
sys.exit(1)
# Step 1: Fetch GitHub releases using the GitHub API
releases = fetch_github_releases()
# Step 2: Generate Appcast XML for stable releases
appcast_xml = generate_appcast_xml(releases, include_prereleases=args.include_prereleases)
# Step 3: Write stable releases to the specified output file
write_appcast_to_file(appcast_xml, args.output)