mirror of
https://gitlab.com/itsulu-odoo/runboat.git
synced 2026-05-30 23:41:27 +00:00
Merge pull request #114 from sbidoul/upgrade-deps
Upgrade dependencies, use Python 3.13
This commit is contained in:
commit
df8ae030fe
13 changed files with 69 additions and 63 deletions
2
.github/workflows/ci.yml
vendored
2
.github/workflows/ci.yml
vendored
|
|
@ -10,7 +10,7 @@ jobs:
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
strategy:
|
strategy:
|
||||||
matrix:
|
matrix:
|
||||||
python-version: ["3.12"]
|
python-version: ["3.13"]
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@v4
|
- uses: actions/checkout@v4
|
||||||
- uses: actions/setup-python@v4
|
- uses: actions/setup-python@v4
|
||||||
|
|
|
||||||
|
|
@ -2,14 +2,14 @@ default_language_version:
|
||||||
python: python3
|
python: python3
|
||||||
repos:
|
repos:
|
||||||
- repo: https://github.com/pre-commit/pre-commit-hooks
|
- repo: https://github.com/pre-commit/pre-commit-hooks
|
||||||
rev: v4.6.0
|
rev: v5.0.0
|
||||||
hooks:
|
hooks:
|
||||||
- id: check-toml
|
- id: check-toml
|
||||||
- id: check-yaml
|
- id: check-yaml
|
||||||
- id: end-of-file-fixer
|
- id: end-of-file-fixer
|
||||||
- id: trailing-whitespace
|
- id: trailing-whitespace
|
||||||
- repo: https://github.com/astral-sh/ruff-pre-commit
|
- repo: https://github.com/astral-sh/ruff-pre-commit
|
||||||
rev: v0.5.0
|
rev: v0.9.9
|
||||||
hooks:
|
hooks:
|
||||||
- id: ruff
|
- id: ruff
|
||||||
- id: ruff-format
|
- id: ruff-format
|
||||||
|
|
|
||||||
|
|
@ -1,4 +1,4 @@
|
||||||
FROM python:3.12
|
FROM python:3.13
|
||||||
|
|
||||||
LABEL maintainer="Stéphane Bidoul"
|
LABEL maintainer="Stéphane Bidoul"
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -60,7 +60,7 @@ For running the builds:
|
||||||
|
|
||||||
For running the controller (runboat itself):
|
For running the controller (runboat itself):
|
||||||
|
|
||||||
- Python 3.12
|
- Python 3.13
|
||||||
- sqlite3 >= 3.25
|
- sqlite3 >= 3.25
|
||||||
- `kubectl`
|
- `kubectl`
|
||||||
- A `KUBECONFIG` or an in-cluster service account that provides access to the namespace
|
- A `KUBECONFIG` or an in-cluster service account that provides access to the namespace
|
||||||
|
|
|
||||||
|
|
@ -11,7 +11,7 @@ classifiers = [
|
||||||
]
|
]
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"ansi2html",
|
"ansi2html",
|
||||||
"fastapi>=0.93",
|
"fastapi[all]>=0.112",
|
||||||
"gunicorn",
|
"gunicorn",
|
||||||
"httpx",
|
"httpx",
|
||||||
"jinja2",
|
"jinja2",
|
||||||
|
|
@ -22,7 +22,7 @@ dependencies = [
|
||||||
"sse-starlette",
|
"sse-starlette",
|
||||||
"uvicorn",
|
"uvicorn",
|
||||||
]
|
]
|
||||||
requires-python = "==3.12.*"
|
requires-python = "==3.13.*"
|
||||||
dynamic = ["version", "description"]
|
dynamic = ["version", "description"]
|
||||||
|
|
||||||
[project.optional-dependencies]
|
[project.optional-dependencies]
|
||||||
|
|
@ -58,6 +58,7 @@ select = [
|
||||||
"T20", # flake8-print
|
"T20", # flake8-print
|
||||||
"PLE", # pylint errors
|
"PLE", # pylint errors
|
||||||
"RUF",
|
"RUF",
|
||||||
|
"FAST", # fastapi
|
||||||
]
|
]
|
||||||
|
|
||||||
[tool.ruff.lint.mccabe]
|
[tool.ruff.lint.mccabe]
|
||||||
|
|
|
||||||
|
|
@ -1,4 +1,4 @@
|
||||||
# frozen requirements generated by pip-deepfreeze
|
# frozen requirements generated by pip-deepfreeze
|
||||||
mypy==1.10.1
|
mypy==1.15.0
|
||||||
mypy-extensions==1.0.0
|
mypy-extensions==1.0.0
|
||||||
types-urllib3==1.26.25.14
|
types-urllib3==1.26.25.14
|
||||||
|
|
|
||||||
|
|
@ -1,9 +1,9 @@
|
||||||
# frozen requirements generated by pip-deepfreeze
|
# frozen requirements generated by pip-deepfreeze
|
||||||
coverage==7.5.4
|
coverage==7.6.12
|
||||||
iniconfig==2.0.0
|
iniconfig==2.0.0
|
||||||
pluggy==1.5.0
|
pluggy==1.5.0
|
||||||
pytest==8.2.2
|
pytest==8.3.4
|
||||||
pytest-asyncio==0.23.7
|
pytest-asyncio==0.25.3
|
||||||
pytest-cov==5.0.0
|
pytest-cov==6.0.0
|
||||||
pytest-dotenv==0.5.2
|
pytest-dotenv==0.5.2
|
||||||
pytest-mock==3.14.0
|
pytest-mock==3.14.0
|
||||||
|
|
|
||||||
|
|
@ -1,55 +1,59 @@
|
||||||
# frozen requirements generated by pip-deepfreeze
|
# frozen requirements generated by pip-deepfreeze
|
||||||
annotated-types==0.7.0
|
annotated-types==0.7.0
|
||||||
ansi2html==1.9.2
|
ansi2html==1.9.2
|
||||||
anyio==4.4.0
|
anyio==4.8.0
|
||||||
cachetools==5.3.3
|
cachetools==5.5.2
|
||||||
certifi==2024.7.4
|
certifi==2025.1.31
|
||||||
charset-normalizer==3.3.2
|
charset-normalizer==3.4.1
|
||||||
click==8.1.7
|
click==8.1.8
|
||||||
dnspython==2.6.1
|
dnspython==2.7.0
|
||||||
|
durationpy==0.9
|
||||||
email-validator==2.2.0
|
email-validator==2.2.0
|
||||||
fastapi==0.111.0
|
fastapi==0.115.10
|
||||||
fastapi-cli==0.0.4
|
fastapi-cli==0.0.7
|
||||||
google-auth==2.31.0
|
google-auth==2.38.0
|
||||||
gunicorn==22.0.0
|
gunicorn==23.0.0
|
||||||
h11==0.14.0
|
h11==0.14.0
|
||||||
httpcore==1.0.5
|
httpcore==1.0.7
|
||||||
httptools==0.6.1
|
httptools==0.6.4
|
||||||
httpx==0.27.0
|
httpx==0.28.1
|
||||||
idna==3.7
|
idna==3.10
|
||||||
jinja2==3.1.4
|
itsdangerous==2.2.0
|
||||||
kubernetes==30.1.0
|
jinja2==3.1.5
|
||||||
|
kubernetes==32.0.1
|
||||||
markdown-it-py==3.0.0
|
markdown-it-py==3.0.0
|
||||||
markupsafe==2.1.5
|
markupsafe==3.0.2
|
||||||
mdurl==0.1.2
|
mdurl==0.1.2
|
||||||
oauthlib==3.2.2
|
oauthlib==3.2.2
|
||||||
orjson==3.10.6
|
orjson==3.10.15
|
||||||
packaging==24.1
|
packaging==24.2
|
||||||
pyasn1==0.6.0
|
pyasn1==0.6.1
|
||||||
pyasn1-modules==0.4.0
|
pyasn1-modules==0.4.1
|
||||||
pydantic==2.8.2
|
pydantic==2.10.6
|
||||||
pydantic-core==2.20.1
|
pydantic-core==2.27.2
|
||||||
pydantic-settings==2.3.4
|
pydantic-extra-types==2.10.2
|
||||||
pygments==2.18.0
|
pydantic-settings==2.8.1
|
||||||
|
pygments==2.19.1
|
||||||
python-dateutil==2.9.0.post0
|
python-dateutil==2.9.0.post0
|
||||||
python-dotenv==1.0.1
|
python-dotenv==1.0.1
|
||||||
python-multipart==0.0.9
|
python-multipart==0.0.20
|
||||||
pyyaml==6.0.1
|
pyyaml==6.0.2
|
||||||
requests==2.32.3
|
requests==2.32.3
|
||||||
requests-oauthlib==2.0.0
|
requests-oauthlib==2.0.0
|
||||||
rich==13.7.1
|
rich==13.9.4
|
||||||
|
rich-toolkit==0.13.2
|
||||||
rsa==4.9
|
rsa==4.9
|
||||||
shellingham==1.5.4
|
shellingham==1.5.4
|
||||||
six==1.16.0
|
six==1.17.0
|
||||||
sniffio==1.3.1
|
sniffio==1.3.1
|
||||||
sse-starlette==2.1.2
|
sse-starlette==2.2.1
|
||||||
starlette==0.37.2
|
starlette==0.46.0
|
||||||
typer==0.12.3
|
typer==0.15.2
|
||||||
typing-extensions==4.12.2
|
typing-extensions==4.12.2
|
||||||
ujson==5.10.0
|
ujson==5.10.0
|
||||||
urllib3==2.2.2
|
urllib3==2.3.0
|
||||||
uvicorn==0.30.1
|
uvicorn==0.34.0
|
||||||
uvloop==0.19.0
|
uvloop==0.21.0
|
||||||
watchfiles==0.22.0
|
watchfiles==1.0.4
|
||||||
websocket-client==1.8.0
|
websocket-client==1.8.0
|
||||||
websockets==12.0
|
websockets==15.0
|
||||||
|
|
|
||||||
|
|
@ -224,7 +224,7 @@ class BuildEventSource:
|
||||||
return
|
return
|
||||||
self.queue.put_nowait(self._serialize(event, build))
|
self.queue.put_nowait(self._serialize(event, build))
|
||||||
|
|
||||||
async def events(self) -> AsyncGenerator[str, None]:
|
async def events(self) -> AsyncGenerator[str]:
|
||||||
for build in controller.db.search(
|
for build in controller.db.search(
|
||||||
repo=self.repo,
|
repo=self.repo,
|
||||||
target_branch=self.target_branch,
|
target_branch=self.target_branch,
|
||||||
|
|
|
||||||
|
|
@ -7,7 +7,7 @@ from . import __version__, api, controller, k8s, webhooks, webui
|
||||||
|
|
||||||
|
|
||||||
@asynccontextmanager
|
@asynccontextmanager
|
||||||
async def lifespan(app: FastAPI) -> AsyncGenerator[None, None]:
|
async def lifespan(app: FastAPI) -> AsyncGenerator[None]:
|
||||||
await k8s.load_kube_config()
|
await k8s.load_kube_config()
|
||||||
await controller.controller.start()
|
await controller.controller.start()
|
||||||
yield
|
yield
|
||||||
|
|
|
||||||
|
|
@ -86,7 +86,7 @@ class WatchException(Exception):
|
||||||
|
|
||||||
def _watch(
|
def _watch(
|
||||||
list_method: Callable[..., Any], *args: Any, **kwargs: Any
|
list_method: Callable[..., Any], *args: Any, **kwargs: Any
|
||||||
) -> Generator[tuple[str | None, Any], None, None]:
|
) -> Generator[tuple[str | None, Any]]:
|
||||||
while True:
|
while True:
|
||||||
try:
|
try:
|
||||||
# perform a first query
|
# perform a first query
|
||||||
|
|
@ -121,7 +121,7 @@ def _watch(
|
||||||
|
|
||||||
|
|
||||||
@sync_to_async_iterator
|
@sync_to_async_iterator
|
||||||
def watch_deployments() -> Generator[V1Deployment, None, None]:
|
def watch_deployments() -> Generator[V1Deployment]:
|
||||||
appsv1 = client.AppsV1Api()
|
appsv1 = client.AppsV1Api()
|
||||||
yield from _watch(
|
yield from _watch(
|
||||||
appsv1.list_namespaced_deployment, namespace=settings.build_namespace
|
appsv1.list_namespaced_deployment, namespace=settings.build_namespace
|
||||||
|
|
@ -129,7 +129,7 @@ def watch_deployments() -> Generator[V1Deployment, None, None]:
|
||||||
|
|
||||||
|
|
||||||
@sync_to_async_iterator
|
@sync_to_async_iterator
|
||||||
def watch_jobs() -> Generator[V1Job, None, None]:
|
def watch_jobs() -> Generator[V1Job]:
|
||||||
batchv1 = client.BatchV1Api()
|
batchv1 = client.BatchV1Api()
|
||||||
yield from _watch(batchv1.list_namespaced_job, namespace=settings.build_namespace)
|
yield from _watch(batchv1.list_namespaced_job, namespace=settings.build_namespace)
|
||||||
|
|
||||||
|
|
@ -178,7 +178,7 @@ def make_deployment_vars(
|
||||||
|
|
||||||
|
|
||||||
@contextmanager
|
@contextmanager
|
||||||
def _get_kubefiles_path(kubefiles_path: Path | None) -> Generator[Path, None, None]:
|
def _get_kubefiles_path(kubefiles_path: Path | None) -> Generator[Path]:
|
||||||
if kubefiles_path:
|
if kubefiles_path:
|
||||||
yield kubefiles_path
|
yield kubefiles_path
|
||||||
else:
|
else:
|
||||||
|
|
@ -191,7 +191,7 @@ def _get_kubefiles_path(kubefiles_path: Path | None) -> Generator[Path, None, No
|
||||||
@contextmanager
|
@contextmanager
|
||||||
def _render_kubefiles(
|
def _render_kubefiles(
|
||||||
kubefiles_path: Path | None, deployment_vars: DeploymentVars
|
kubefiles_path: Path | None, deployment_vars: DeploymentVars
|
||||||
) -> Generator[Path, None, None]:
|
) -> Generator[Path]:
|
||||||
with (
|
with (
|
||||||
_get_kubefiles_path(kubefiles_path) as kubefiles_path,
|
_get_kubefiles_path(kubefiles_path) as kubefiles_path,
|
||||||
tempfile.TemporaryDirectory() as tmp_dir,
|
tempfile.TemporaryDirectory() as tmp_dir,
|
||||||
|
|
@ -299,7 +299,7 @@ def log(build_name: str, job_kind: DeploymentMode | None) -> str | None:
|
||||||
container=pod.metadata.annotations.get(
|
container=pod.metadata.annotations.get(
|
||||||
"kubectl.kubernetes.io/default-container"
|
"kubectl.kubernetes.io/default-container"
|
||||||
),
|
),
|
||||||
tail_lines=None if job_kind else None,
|
tail_lines=None,
|
||||||
follow=False,
|
follow=False,
|
||||||
),
|
),
|
||||||
)
|
)
|
||||||
|
|
|
||||||
|
|
@ -28,8 +28,8 @@ def sync_to_async(func: Callable[P, R]) -> Callable[P, Awaitable[R]]:
|
||||||
|
|
||||||
|
|
||||||
def sync_to_async_iterator(
|
def sync_to_async_iterator(
|
||||||
iterator_func: Callable[P, Generator[R, None, None]],
|
iterator_func: Callable[P, Generator[R]],
|
||||||
) -> Callable[P, AsyncGenerator[R, None]]:
|
) -> Callable[P, AsyncGenerator[R]]:
|
||||||
@sync_to_async
|
@sync_to_async
|
||||||
def async_next(iterator: Iterator[R]) -> R:
|
def async_next(iterator: Iterator[R]) -> R:
|
||||||
try:
|
try:
|
||||||
|
|
@ -38,11 +38,11 @@ def sync_to_async_iterator(
|
||||||
raise StopAsyncIteration() from e
|
raise StopAsyncIteration() from e
|
||||||
|
|
||||||
@sync_to_async
|
@sync_to_async
|
||||||
def async_iterator_func(*args: Any, **kwargs: Any) -> Generator[R, None, None]:
|
def async_iterator_func(*args: Any, **kwargs: Any) -> Generator[R]:
|
||||||
return iterator_func(*args, **kwargs)
|
return iterator_func(*args, **kwargs)
|
||||||
|
|
||||||
@wraps(iterator_func)
|
@wraps(iterator_func)
|
||||||
async def inner(*args: Any, **kwargs: Any) -> AsyncGenerator[R, None]:
|
async def inner(*args: Any, **kwargs: Any) -> AsyncGenerator[R]:
|
||||||
iterator = await async_iterator_func(*args, **kwargs)
|
iterator = await async_iterator_func(*args, **kwargs)
|
||||||
while True:
|
while True:
|
||||||
try:
|
try:
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,6 @@
|
||||||
import hmac
|
import hmac
|
||||||
import logging
|
import logging
|
||||||
|
from typing import Annotated
|
||||||
|
|
||||||
from fastapi import APIRouter, BackgroundTasks, Header, Request
|
from fastapi import APIRouter, BackgroundTasks, Header, Request
|
||||||
|
|
||||||
|
|
@ -31,8 +32,8 @@ def _verify_github_signature(
|
||||||
async def receive_payload(
|
async def receive_payload(
|
||||||
background_tasks: BackgroundTasks,
|
background_tasks: BackgroundTasks,
|
||||||
request: Request,
|
request: Request,
|
||||||
x_github_event: str = Header(...),
|
x_github_event: Annotated[str, Header(...)],
|
||||||
x_hub_signature_256: str | None = Header(None),
|
x_hub_signature_256: Annotated[str | None, Header(...)] = None,
|
||||||
) -> None:
|
) -> None:
|
||||||
body = await request.body()
|
body = await request.body()
|
||||||
if not _verify_github_signature(
|
if not _verify_github_signature(
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue