[skip ci] fix ots

This commit is contained in:
timka123 committed 2026-10-22 22:06:57 +03:00
1 parent 894f132e34
commit ff77d8f89f
3 files changed
+107 -6

No files matched your search

+1 -1
View File
@@ -149,7 +149,7 @@ jobs:
APKSIGNER="$(find "$ANDROID_HOME/build-tools" -name apksigner | sort | tail -1)" APKSIGNER="$(find "$ANDROID_HOME/build-tools" -name apksigner | sort | tail -1)"
SIGNER_SHA256="$("$APKSIGNER" verify --print-certs "$APK" \ SIGNER_SHA256="$("$APKSIGNER" verify --print-certs "$APK" \
| sed -n 's/^Signer #1 certificate SHA-256 digest: //p' | head -1)" | sed -n 's/.*certificate SHA-256 digest: //p' | head -1)"
printf '{\n "version_code": %s,\n "version_name": "%s",\n "commit": "%s",\n "built_at": "%s",\n "size_bytes": %s,\n "sha256": "%s",\n "signer_sha256": "%s"\n}\n' \ printf '{\n "version_code": %s,\n "version_name": "%s",\n "commit": "%s",\n "built_at": "%s",\n "size_bytes": %s,\n "sha256": "%s",\n "signer_sha256": "%s"\n}\n' \
"${{ gitea.run_number }}" \ "${{ gitea.run_number }}" \
+45 -5
View File
@@ -19,7 +19,7 @@ import tempfile
import threading import threading
import time import time
import zipfile import zipfile
from dataclasses import dataclass from dataclasses import dataclass, replace
from pathlib import Path from pathlib import Path
from typing import Any from typing import Any
@@ -139,8 +139,45 @@ def _artifact(raw: Any) -> Artifact | None:
) )
def _run(client: httpx.Client, settings: EnvSettings, run_id: int) -> dict[str, Any]:
try:
response = client.get(_api(settings, f"/actions/runs/{run_id}"))
response.raise_for_status()
payload = response.json()
except (httpx.HTTPError, ValueError) as exc:
raise UpdateUnavailable(f"Could not read Gitea run {run_id}: {exc}") from exc
return payload if isinstance(payload, dict) else {}
def _with_run(
client: httpx.Client,
settings: EnvSettings,
artifact: Artifact,
runs: dict[int, dict[str, Any]],
) -> Artifact:
"""Gitea's artifact list can omit the run's branch, number and conclusion."""
if artifact.run_number and artifact.branch and artifact.conclusion:
return artifact
if not artifact.run_id:
return artifact
run = runs.get(artifact.run_id)
if run is None:
run = _run(client, settings, artifact.run_id)
runs[artifact.run_id] = run
return replace(
artifact,
run_number=int(run.get("run_number") or artifact.run_number),
branch=str(run.get("head_branch") or artifact.branch),
commit=str(run.get("head_sha") or artifact.commit),
conclusion=str(run.get("conclusion") or artifact.conclusion),
)
def _list_artifacts( def _list_artifacts(
client: httpx.Client, settings: EnvSettings, name: str client: httpx.Client,
settings: EnvSettings,
name: str,
runs: dict[int, dict[str, Any]] | None = None,
) -> list[Artifact]: ) -> list[Artifact]:
try: try:
response = client.get(_api(settings, "/actions/artifacts"), params={"name": name}) response = client.get(_api(settings, "/actions/artifacts"), params={"name": name})
@@ -152,7 +189,9 @@ def _list_artifacts(
entries = payload.get("artifacts") if isinstance(payload, dict) else None entries = payload.get("artifacts") if isinstance(payload, dict) else None
if not isinstance(entries, list): if not isinstance(entries, list):
return [] return []
return [artifact for raw in entries if (artifact := _artifact(raw)) is not None] artifacts = [artifact for raw in entries if (artifact := _artifact(raw)) is not None]
run_cache = runs if runs is not None else {}
return [_with_run(client, settings, artifact, run_cache) for artifact in artifacts]
def _successful(artifacts: list[Artifact], branch: str) -> list[Artifact]: def _successful(artifacts: list[Artifact], branch: str) -> list[Artifact]:
@@ -268,12 +307,13 @@ def _resolve(settings: EnvSettings) -> ResolvedUpdate:
if cached is not None and now - cached[0] < _METADATA_TTL_SECONDS: if cached is not None and now - cached[0] < _METADATA_TTL_SECONDS:
return cached[1] return cached[1]
runs: dict[int, dict[str, Any]] = {}
with _client(settings) as client: with _client(settings) as client:
metadata_artifacts = _successful( metadata_artifacts = _successful(
_list_artifacts(client, settings, METADATA_ARTIFACT), _list_artifacts(client, settings, METADATA_ARTIFACT, runs),
settings.gitea_update_branch, settings.gitea_update_branch,
) )
apk_artifacts = _list_artifacts(client, settings, APK_ARTIFACT) apk_artifacts = _list_artifacts(client, settings, APK_ARTIFACT, runs)
usable_apk = _successful(apk_artifacts, settings.gitea_update_branch) usable_apk = _successful(apk_artifacts, settings.gitea_update_branch)
resolved: ResolvedUpdate | None = None resolved: ResolvedUpdate | None = None
+61
View File
@@ -8,6 +8,7 @@ import zipfile
import httpx import httpx
import pytest import pytest
from app.config import env_settings from app.config import env_settings
from app.services import android_updates from app.services import android_updates
@@ -200,3 +201,63 @@ def test_the_route_reports_503_when_updates_are_not_configured(client, monkeypat
assert response.status_code == 503 assert response.status_code == 503
assert "GITEA_TOKEN" in response.json()["detail"] assert "GITEA_TOKEN" in response.json()["detail"]
def test_sparse_artifact_run_metadata_is_fetched_from_the_run(monkeypatch):
_configure(monkeypatch)
metadata = _artifact(31, run_id=401, run_number=0, branch="", conclusion="")
metadata["workflow_run"] = {"id": 401, "head_sha": "sha-88"}
apk = _artifact(
32,
run_id=401,
run_number=0,
name=android_updates.APK_ARTIFACT,
branch="",
conclusion="",
)
apk["workflow_run"] = {"id": 401, "head_sha": "sha-88"}
zips = {
31: _zip({"update.json": _metadata_body(88, "0.1.0-master.88")}),
32: _zip({"app-release.apk": b"sparse apk"}),
}
run_requests = 0
def handler(request: httpx.Request) -> httpx.Response:
nonlocal run_requests
if request.url.path.endswith("/actions/artifacts"):
name = request.url.params.get("name")
return httpx.Response(
200,
json={
"total_count": 1,
"artifacts": [metadata]
if name == android_updates.METADATA_ARTIFACT
else [apk],
},
)
if request.url.path.endswith("/actions/runs/401"):
run_requests += 1
return httpx.Response(
200,
json={
"id": 401,
"run_number": 88,
"head_branch": "master",
"head_sha": "sha-88",
"conclusion": "success",
},
)
artifact_id = int(request.url.path.rstrip("/").split("/")[-2])
return httpx.Response(200, content=zips[artifact_id])
_install_transport(monkeypatch, handler)
metadata = android_updates.latest_android()
assert metadata["version_code"] == 88
assert metadata["version_name"] == "0.1.0-master.88"
assert metadata["commit"] == "sha-88"
assert run_requests == 1
path, same = android_updates.android_apk()
assert path.read_bytes() == b"sparse apk"
assert same == metadata