Able to connect to github

This commit is contained in:
Stanislas Jouffroy 2024-09-23 23:45:22 +02:00
parent 9c4441ec63
commit a5c99c2d06
13 changed files with 313 additions and 0 deletions

35
pyproject.toml Normal file
View file

@ -0,0 +1,35 @@
[project]
name = "Booker"
version = "0.1.0"
dependencies = [
"pydantic>=2.8.2,<3.0.0",
"pydantic-settings>=2.4.0,<3.0.0",
"pyyaml>=6.0,<7.0",
"pendulum>=3.0.0,<4.0.0",
"requests>=2.32.3,<3.0.0",
"typer>=0.12.5,<0.13.0"
]
[project.optional-dependencies]
dev = [
"black>=24.4.2,<25.0.0",
"isort>=5.13.2,<6.0.0",
"ruff>=0.5.4,<0.6.0",
"pytest>=8.3.1,<9.0.0",
"pytest-icdiff>=0.9,<1.0",
"pytest-sugar>=1.0.0,<2.0.0",
]
[tool.ruff]
line-length = 88
[tool.isort]
profile = "black"
[tool.pytest.ini_options]
pythonpath = [
"src"
]
log_cli = 1
log_cli_level = "DEBUG"

0
src/__init__.py Normal file
View file

0
src/losoup/__init__.py Normal file
View file

View file

41
src/losoup/cvs/github.py Normal file
View file

@ -0,0 +1,41 @@
import requests
from losoup.models import Asset, GithubSoftware
from losoup.cvs.github_settings import GithubSettings
class GithubConnector:
def __init__(self, settings: GithubSettings):
self.settings = settings
def get_release_assets_list(self, release_url: str) -> list[Asset]:
headers = {
"Accept": "application/vnd.github+json",
"Authorization": f"token {self.settings.token}",
"X-Github-Api-Version": "2022-11-28",
}
response = requests.get(release_url, headers=headers)
assets = []
for asset in response.json().get("assets"):
assets.append(Asset(name=asset.get("name"), url=asset.get("url")))
return assets
def get_release_asset(self, software: GithubSoftware) -> Asset:
for asset in self.get_release_assets_list(software.release_url):
if asset.name == software.filename:
return asset
else:
continue
def download_release_asset(self, asset: Asset) -> bytes:
headers = {
"Accept": "application/octet-stream",
"Authorization": f"token {self.settings.token}",
"X-Github-Api-Version": "2022-11-28",
}
response = requests.get(asset.url, headers=headers)
return response.content
def download_software(self, software: GithubSoftware) -> bytes:
release_asset = self.get_release_asset(software)
return self.download_release_asset(release_asset)

View file

@ -0,0 +1,8 @@
from pydantic_settings import BaseSettings, SettingsConfigDict
class GithubSettings(BaseSettings):
model_config = SettingsConfigDict(env_prefix="GITHUB_")
token: str
url: str = "https://api.github.com/repos"

0
src/losoup/cvs/gitlab.py Normal file
View file

52
src/losoup/models.py Normal file
View file

@ -0,0 +1,52 @@
from pathlib import Path
from pydantic import BaseModel, Field, field_validator
class Software(BaseModel):
name: str
owner: str
repo: str
version: str
folder: str
filename_format: str = Field(..., alias="filenameFormat")
@field_validator("folder")
@classmethod
def replace_tilde(cls, value: str):
return value.replace("~", Path.home().as_posix())
@property
def filename(self) -> str:
return self.filename_format.replace("{{version}}", self.version)
@property
def absolute_path(self) -> Path:
return Path(self.folder, self.filename)
class GithubSoftware(Software):
base_url: str = "https://api.github.com"
@property
def release_url(self):
if self.version == "latest":
release_path = self.version
else:
release_path = f"tags/{self.version}"
return f"{self.base_url}/repos/{self.owner}/{self.repo}/releases/{release_path}"
class GitlabSoftware(Software):
base_url: str = Field(..., alias="baseUrl")
@property
def release_url(self):
return f"{self.base_url}/{self.owner}/{self.repo}/-/releases/{self.version}"
class Asset(BaseModel):
name: str
url: str
content: bytes | str | None = None

0
test/__init__.py Normal file
View file

0
test/losoup/__init__.py Normal file
View file

121
test/losoup/conftest.py Normal file
View file

@ -0,0 +1,121 @@
from pathlib import Path
import pytest
from losoup.file_operations.local_files import LocalFile
from losoup.models import GithubSoftware, Asset
from losoup.cvs.github import GithubConnector
from losoup.cvs.github_settings import GithubSettings
current_dir = Path(__file__).parent.absolute()
dotenv = current_dir / "test.env"
@pytest.fixture
def github_settings():
return GithubSettings(_env_file=dotenv)
@pytest.fixture
def github_connector(github_settings):
return GithubConnector(github_settings)
@pytest.fixture
def keepassxc():
return GithubSoftware(
name="KeepassXC",
owner="keepassxreboot",
repo="keepassxc",
version="2.7.9",
folder="~/Softwares",
filenameFormat="KeePassXC-{{version}}-x86_64.AppImage",
)
@pytest.fixture
def latest_keepassxc():
return GithubSoftware(
name="KeepassXC",
owner="keepassxreboot",
repo="keepassxc",
version="latest",
folder="~/Softwares",
filenameFormat="KeePassXC-{{version}}-x86_64.AppImage",
)
@pytest.fixture
def keepassxc_not_present():
return GithubSoftware(
name="KeepassXC",
owner="keepassxreboot",
repo="keepassxc",
version="2.79",
folder="~/Softwares",
filenameFormat="KeePassXC-{{version}}-x86_64.AppImage",
)
@pytest.fixture
def local_file(keepassxc):
return LocalFile(keepassxc)
@pytest.fixture
def local_file_not_present(keepassxc_not_present):
return LocalFile(keepassxc_not_present)
@pytest.fixture
def software_to_update():
return GithubSoftware(
name="KeepassXC",
owner="keepassxreboot",
repo="keepassxc",
version="2.8.1",
folder="~/Softwares",
filenameFormat="KeePassXC-{{version}}-x86_64.AppImage",
)
@pytest.fixture
def software_up_to_date(keepassxc):
return keepassxc
@pytest.fixture
def asset():
return Asset(
name="KeePassXC-2.7.9-x86_64.AppImage.DIGEST",
url="https://api.github.com/repos/keepassxreboot/keepassxc/releases/assets/1747"
"89149",
)
@pytest.fixture
def keepassxc_digest():
return GithubSoftware(
name="KeepassXC digest",
owner="keepassxreboot",
repo="keepassxc",
version="2.7.7",
folder="~/Softwares",
filenameFormat="KeePassXC-{{version}}-x86_64.AppImage.DIGEST",
)
@pytest.fixture
def keepassxc_digest_file(keepassxc_digest):
return LocalFile(keepassxc_digest)
@pytest.fixture
def asset_to_write():
return Asset(
name="KeePassXC-2.7.7-x86_64.AppImage.DIGEST",
url="https://api.github.com/repos/keepassxreboot/keepassxc/releases/assets/1747"
"89149",
content=b"2a868b681a8ec4e381ac14203aec3d80ff6fa7a535fa102265a3ec9329b4b846 Kee"
b"PassXC-2.7.9-x86_64.AppImage\n",
)

16
test/losoup/software.yaml Normal file
View file

@ -0,0 +1,16 @@
software:
- name: NextCloud
cvs: github
owner: nextcloud-releases
repo: desktop
version: latest
folder: /home/stan/Softwares
filenameFormat: KeePassXC-{{version}}-x86_64.AppImage
- name: KeePassXC
cvs: giTHub
owner: keepassxreboot
repo: keepassxc
version: latest
folder: /home/stan/Softwares
filenameFormat: Nextcloud-{{version}}-x86_64.AppImage

View file

@ -0,0 +1,40 @@
def test_github_connector_is_initialized(github_connector):
assert github_connector is not None
assert github_connector.settings.token is not None
def test_get_latest_release(github_connector, latest_keepassxc):
release_assets = github_connector.get_release_assets_list(
latest_keepassxc.release_url
)
assert len(release_assets) == 27
def test_get_some_release(github_connector, keepassxc):
release_asset_list = github_connector.get_release_assets_list(keepassxc.release_url)
assert len(release_asset_list) == 27
def test_get_release_asset(github_connector, keepassxc):
release_asset = github_connector.get_release_asset(keepassxc)
assert release_asset.name == keepassxc.filename
def test_download_release_asset(github_connector, asset):
release_asset_file = github_connector.download_release_asset(asset)
assert len(release_asset_file) == 98
assert (
release_asset_file
== b"2a868b681a8ec4e381ac14203aec3d80ff6fa7a535fa102265a3ec9329b4b846 KeePassX"
b"C-2.7.9-x86_64.AppImage\n"
)
def test_download_software(github_connector, keepassxc_digest):
release_asset_file = github_connector.download_software(keepassxc_digest)
assert len(release_asset_file) == 98
assert (
release_asset_file
== b"796c4c0ad20b124476195dacd7f86c75be51cace1c734174ec293c46f41c3d05 KeePassX"
b"C-2.7.7-x86_64.AppImage\n"
)