mirror of
https://github.com/niess/python-appimage.git
synced 2026-03-14 04:10:15 +01:00
Python AppImages updater
This commit is contained in:
14
python_appimage/utils/manylinux.py
Normal file
14
python_appimage/utils/manylinux.py
Normal file
@@ -0,0 +1,14 @@
|
||||
def format_appimage_name(abi, version, tag):
|
||||
'''Format the Python AppImage name using the ABI, python version and OS tags
|
||||
'''
|
||||
return 'python{:}-{:}-{:}.AppImage'.format(
|
||||
version, abi, format_tag(tag))
|
||||
|
||||
|
||||
def format_tag(tag):
|
||||
'''Format Manylinux tag
|
||||
'''
|
||||
if tag.startswith('2_'):
|
||||
return 'manylinux_' + tag
|
||||
else:
|
||||
return 'manylinux' + tag
|
||||
202
scripts/update-appimages.py
Executable file
202
scripts/update-appimages.py
Executable file
@@ -0,0 +1,202 @@
|
||||
#! /usr/bin/env python3
|
||||
import argparse
|
||||
from collections import defaultdict
|
||||
from dataclasses import dataclass
|
||||
import os
|
||||
import subprocess
|
||||
from typing import Optional
|
||||
|
||||
from github import Auth, Github
|
||||
|
||||
from python_appimage.commands.build.manylinux import execute as build_manylinux
|
||||
from python_appimage.commands.list import execute as list_pythons
|
||||
from python_appimage.utils.log import log
|
||||
from python_appimage.utils.manylinux import format_appimage_name
|
||||
|
||||
|
||||
# Build matrix
|
||||
ARCHS = ('x86_64', 'i686')
|
||||
MANYLINUSES = ('1', '2010', '2014', '2_24', '2_28')
|
||||
EXCLUDES = ('2_28_i686',)
|
||||
|
||||
# Build directory for AppImages
|
||||
APPIMAGES_DIR = 'build-appimages'
|
||||
|
||||
|
||||
@dataclass
|
||||
class ReleaseMeta:
|
||||
'''Metadata relative to a GitHub release
|
||||
'''
|
||||
|
||||
tag: str
|
||||
|
||||
release: Optional["github.GitRelease"] = None
|
||||
|
||||
def title(self):
|
||||
'''Returns release title'''
|
||||
version = self.tag[6:]
|
||||
return f'Python {version}'
|
||||
|
||||
|
||||
@dataclass
|
||||
class AssetMeta:
|
||||
'''Metadata relative to a release Asset
|
||||
'''
|
||||
|
||||
tag: str
|
||||
abi: str
|
||||
version: str
|
||||
|
||||
asset: Optional["github.GitReleaseAsset"] = None
|
||||
|
||||
@classmethod
|
||||
def from_appimage(cls, name):
|
||||
'''Returns an instance from a Python AppImage name
|
||||
'''
|
||||
tmp = name[6:-9]
|
||||
tmp, tag = tmp.split('-manylinux', 1)
|
||||
if tag.startswith('_'):
|
||||
tag = tag[1:]
|
||||
version, abi = tmp.split('-', 1)
|
||||
return cls(
|
||||
tag = tag,
|
||||
abi = abi,
|
||||
version = version
|
||||
)
|
||||
|
||||
def appimage_name(self):
|
||||
'''Returns Python AppImage name'''
|
||||
return format_appimage_name(self.abi, self.version, self.tag)
|
||||
|
||||
def release_tag(self):
|
||||
'''Returns release git tag'''
|
||||
version = self.version.rsplit('.', 1)[0]
|
||||
return f'python{version}'
|
||||
|
||||
|
||||
def update(args):
|
||||
'''Update Python AppImage GitHub releases
|
||||
'''
|
||||
|
||||
# Connect to GitHub
|
||||
if args.token is None:
|
||||
# Get token from gh app (e.g. for local runs)
|
||||
p = subprocess.run(
|
||||
'gh auth token',
|
||||
shell = True,
|
||||
capture_output = True,
|
||||
check = True
|
||||
)
|
||||
token = p.stdout.decode().strip()
|
||||
|
||||
auth = Auth.Token(token)
|
||||
session = Github(auth=auth)
|
||||
repo = session.get_repo('niess/python-appimage')
|
||||
|
||||
# Fetch currently released AppImages
|
||||
log('FETCH', 'Currently released AppImages')
|
||||
releases = {}
|
||||
assets = defaultdict(dict)
|
||||
n_assets = 0
|
||||
for release in repo.get_releases():
|
||||
if release.tag_name.startswith('python'):
|
||||
releases[release.tag_name] = ReleaseMeta(
|
||||
tag = release.tag_name,
|
||||
release = release
|
||||
)
|
||||
for asset in release.get_assets():
|
||||
if asset.name.endswith('.AppImage'):
|
||||
n_assets += 1
|
||||
meta = AssetMeta.from_appimage(asset.name)
|
||||
assert(meta.release_tag() == release.tag_name)
|
||||
meta.asset = asset
|
||||
assets[meta.tag][meta.abi] = meta
|
||||
|
||||
n_releases = len(releases)
|
||||
log('FETCH', f'Found {n_assets} AppImages in {n_releases} releases')
|
||||
|
||||
# Look for updates.
|
||||
new_releases = set()
|
||||
new_assets = []
|
||||
|
||||
for manylinux in MANYLINUSES:
|
||||
for arch in ARCHS:
|
||||
tag = f'{manylinux}_{arch}'
|
||||
if tag in EXCLUDES:
|
||||
continue
|
||||
|
||||
pythons = list_pythons(tag)
|
||||
for (abi, version) in pythons:
|
||||
try:
|
||||
meta = assets[tag][abi]
|
||||
except KeyError:
|
||||
meta = None
|
||||
|
||||
if meta is None or meta.version != version:
|
||||
new_meta = AssetMeta(
|
||||
tag = tag,
|
||||
abi = abi,
|
||||
version = version
|
||||
)
|
||||
if meta is not None:
|
||||
new_meta.asset = meta.asset
|
||||
new_assets.append(new_meta)
|
||||
|
||||
rtag = new_meta.release_tag()
|
||||
if rtag not in releases:
|
||||
new_releases.add(rtag)
|
||||
|
||||
if not new_assets:
|
||||
return
|
||||
|
||||
# Build new AppImage(s)
|
||||
cwd = os.getcwd()
|
||||
os.makedirs(APPIMAGES_DIR, exist_ok=True)
|
||||
try:
|
||||
os.chdir(APPIMAGES_DIR)
|
||||
for meta in new_assets:
|
||||
build_manylinux(meta.tag, meta.abi)
|
||||
finally:
|
||||
os.chdir(cwd)
|
||||
|
||||
# Create any new release(s).
|
||||
repo = session.get_repo('niess/test-releases') # XXX
|
||||
|
||||
for tag in new_releases:
|
||||
meta = ReleaseMeta(tag)
|
||||
title = meta.title()
|
||||
meta.release = repo.create_git_release(
|
||||
tag = meta.tag,
|
||||
name = title,
|
||||
message = f'Appimage distributions of {title} (see `Assets` below)',
|
||||
prerelease = True
|
||||
)
|
||||
releases[tag] = meta
|
||||
|
||||
# Update assets.
|
||||
for meta in new_assets:
|
||||
release = releases[meta.release_tag()].release
|
||||
appimage = meta.appimage_name()
|
||||
new_asset = release.upload_asset(
|
||||
path = f'{APPIMAGES_DIR}/{appimage}',
|
||||
label = appimage
|
||||
)
|
||||
if meta.asset:
|
||||
meta.asset.delete_asset()
|
||||
meta.asset = new_asset
|
||||
assets[meta.tag][meta.abi] = meta
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
parser = argparse.ArgumentParser(
|
||||
description = "Update GitHub releases of Python AppImages"
|
||||
)
|
||||
parser.add_argument("-t", "--token",
|
||||
help = "GitHub authentication token"
|
||||
)
|
||||
parser.add_argument("-s", "--sha",
|
||||
help = "Current commit SHA"
|
||||
)
|
||||
|
||||
args = parser.parse_args()
|
||||
update(args)
|
||||
Reference in New Issue
Block a user