From 6afca1e82a31ad7c5426157de5c070ff6fc51ab4 Mon Sep 17 00:00:00 2001 From: orhtej2 <2871798+orhtej2@users.noreply.github.com> Date: Tue, 23 Jan 2024 23:37:24 +0100 Subject: [PATCH] Initial support for Gitlab --- .../autoupdate_app_sources.py | 10 ++-- autoupdate_app_sources/rest_api.py | 59 ++++++++++++++++++- 2 files changed, 64 insertions(+), 5 deletions(-) diff --git a/autoupdate_app_sources/autoupdate_app_sources.py b/autoupdate_app_sources/autoupdate_app_sources.py index 5ea2d3f..3b5f60a 100644 --- a/autoupdate_app_sources/autoupdate_app_sources.py +++ b/autoupdate_app_sources/autoupdate_app_sources.py @@ -8,7 +8,7 @@ import os import glob from datetime import datetime -from rest_api import GithubAPI, RefType +from rest_api import GithubAPI, GitlabAPI, RefType STRATEGIES = [ "latest_github_release", @@ -281,8 +281,10 @@ class AppAutoUpdater: "https://github.com/" ), f"When using strategy {strategy}, having a defined upstream code repo on github.com is required" api = GithubAPI(upstream, auth=auth) + elif "gitlab" in strategy: + api = GitlabAPI(upstream) - if strategy == "latest_github_release": + if strategy == "latest_github_release" or strategy == "latest_gitlab_release": releases = api.releases() tags = [ release["tag_name"] @@ -344,7 +346,7 @@ class AppAutoUpdater: matching_assets_dicts[asset_name] = matching_assets_urls[0] return latest_version.strip("v"), matching_assets_dicts - elif strategy == "latest_github_tag": + elif strategy == "latest_github_tag" or strategy == "latest_gitlab_tag": if asset != "tarball": raise Exception( "For the latest_github_tag strategy, only asset = 'tarball' is supported" @@ -356,7 +358,7 @@ class AppAutoUpdater: latest_tarball = api.url_for_ref(latest_version_orig, RefType.tags) return latest_version, latest_tarball - elif strategy == "latest_github_commit": + elif strategy == "latest_github_commit" or strategy == "latest_gitlab_commit": if asset != "tarball": raise Exception( "For the latest_github_release strategy, only asset = 'tarball' is supported" diff --git a/autoupdate_app_sources/rest_api.py b/autoupdate_app_sources/rest_api.py index e885f68..8a79f33 100644 --- a/autoupdate_app_sources/rest_api.py +++ b/autoupdate_app_sources/rest_api.py @@ -1,6 +1,7 @@ from enum import Enum -from typing import List +import re import requests +from typing import List class RefType(Enum): @@ -44,3 +45,59 @@ class GithubAPI: return f"{self.upstream}/archive/{ref}.tar.gz" else: raise NotImplementedError + + +class GitlabAPI: + def __init__(self, upstream: str): + split = re.search("(?Phttps?://.+)/(?P[^/]+)/(?P[^/]+)/?$", upstream) + self.upstream = split.group("host") + self.upstream_repo = f"{split.group('group')}/{split.group('project')}" + self.project_id = self.find_project_id(split.group('project')) + + def find_project_id(self, project: str) -> int: + projects = self.internal_api(f"projects?search={project}") + for project in projects: + if project["path_with_namespace"] == self.upstream_repo: + return project["id"] + raise ValueError(f"Project {project} not found") + + def internal_api(self, uri: str): + url = f"{self.upstream}/api/v4/{uri}" + r = requests.get(url) + assert r.status_code == 200, r + return r.json() + + def tags(self) -> List[str]: + """Get a list of tags for project.""" + return self.internal_api(f"projects/{self.project_id}/repository/tags") + + def commits(self) -> List[str]: + """Get a list of commits for project.""" + return [ + { + "sha": commit["id"], + "commit": { + "author": { + "date": commit["committed_date"] + } + } + } + for commit in self.internal_api(f"projects/{self.project_id}/repository/commits") + ] + + def releases(self) -> List[str]: + """Get a list of releases for project.""" + releases = self.internal_api(f"projects/{self.project_id}/releases") + return [{ + "tag_name": release["tag_name"], + "prerelease": False, + "draft": False, + "html_url": release["_links"]["self"], + "assets": [{ + "name": asset["name"], + "browser_download_url": asset["direct_asset_url"] + } for asset in release["assets"]["links"]], + } for release in releases] + + def url_for_ref(self, ref: str, ref_type: RefType) -> str: + return f"{self.upstream}/api/v4/projects/{self.project_id}/repository/archive.tar.gz/?sha={ref}"