test: Actions run scenario on an act_runner container
This commit is contained in:
1 parent
29b12bfe0d
commit
22c8157ca4
1 file changed
+117
@@ -0,0 +1,117 @@
|
||||
"""Scenario: a real Actions run on an act_runner container, read back through the tools."""
|
||||
|
||||
from __future__ import annotations
|
||||
|
||||
import asyncio
|
||||
import time
|
||||
from typing import Any
|
||||
|
||||
import pytest
|
||||
|
||||
from tests.integration.conftest import McpSession, RepoRef, b64
|
||||
from tests.integration.harness import GiteaInstance, HarnessError, runner_logs, start_runner
|
||||
|
||||
WORKFLOW_PATH = ".gitea/workflows/it.yml"
|
||||
WORKFLOW = """\
|
||||
name: it
|
||||
on: [push, workflow_dispatch]
|
||||
jobs:
|
||||
hello:
|
||||
runs-on: aegis-host
|
||||
steps:
|
||||
- name: Say hello
|
||||
run: echo hello
|
||||
"""
|
||||
RUNNER_ONLINE_TIMEOUT = 90.0
|
||||
RUN_TIMEOUT = 180.0
|
||||
|
||||
|
||||
async def _wait_for(probe: Any, *, timeout: float, interval: float = 2.0) -> Any:
|
||||
"""Await ``probe()`` until it returns something truthy; return it (or None on timeout)."""
|
||||
deadline = time.monotonic() + timeout
|
||||
while True:
|
||||
value = await probe()
|
||||
if value or time.monotonic() >= deadline:
|
||||
return value
|
||||
await asyncio.sleep(interval)
|
||||
|
||||
|
||||
async def test_workflow_run_on_act_runner(
|
||||
mcp: McpSession, gitea: GiteaInstance, fresh_repo: RepoRef
|
||||
) -> None:
|
||||
repo = fresh_repo.args
|
||||
token = await mcp.ok("gitea_actions_repo_create_runner_registration_token", **repo)
|
||||
assert isinstance(token.data["token"], str) and token.data["token"]
|
||||
try:
|
||||
runner = start_runner(gitea, token.data["token"])
|
||||
except HarnessError as exc:
|
||||
pytest.xfail(f"the act_runner container could not be started: {exc}")
|
||||
|
||||
async def online() -> dict[str, Any] | None:
|
||||
runners = await mcp.ok("gitea_actions_get_repo_runners", **repo)
|
||||
entries = runners.data["runners"] if isinstance(runners.data, dict) else runners.data
|
||||
for entry in entries or []:
|
||||
if entry.get("status") in ("online", "idle", "active"):
|
||||
found: dict[str, Any] = entry
|
||||
return found
|
||||
return None
|
||||
|
||||
registered = await _wait_for(online, timeout=RUNNER_ONLINE_TIMEOUT)
|
||||
if not registered:
|
||||
pytest.xfail(
|
||||
"the act_runner did not come online within "
|
||||
f"{RUNNER_ONLINE_TIMEOUT:.0f}s; runner log tail: {runner_logs(runner, 15)}"
|
||||
)
|
||||
assert token.data["token"] not in runner_logs(runner, 200)
|
||||
|
||||
# Commit the workflow through the contents tool, then dispatch it explicitly.
|
||||
await mcp.ok(
|
||||
"gitea_repo_create_file",
|
||||
status=201,
|
||||
filepath=WORKFLOW_PATH,
|
||||
body={"content": b64(WORKFLOW), "message": "add it workflow", "branch": "main"},
|
||||
**repo,
|
||||
)
|
||||
workflows = await mcp.ok("gitea_actions_list_repository_workflows", **repo)
|
||||
assert any(w["path"].endswith("it.yml") for w in workflows.data["workflows"])
|
||||
await mcp.ok(
|
||||
"gitea_actions_dispatch_workflow",
|
||||
status=(200, 204),
|
||||
workflow_id="it.yml",
|
||||
body={"ref": "main"},
|
||||
**repo,
|
||||
)
|
||||
|
||||
async def finished() -> list[dict[str, Any]] | None:
|
||||
runs = await mcp.ok("gitea_actions_get_workflow_runs", **repo)
|
||||
entries = runs.data["workflow_runs"]
|
||||
if len(entries) >= 2 and all(r["status"] == "completed" for r in entries):
|
||||
done: list[dict[str, Any]] = entries
|
||||
return done
|
||||
return None
|
||||
|
||||
runs = await _wait_for(finished, timeout=RUN_TIMEOUT)
|
||||
assert runs, (
|
||||
f"workflow runs did not complete within {RUN_TIMEOUT:.0f}s; "
|
||||
f"runner log tail: {runner_logs(runner, 20)}"
|
||||
)
|
||||
assert {r["event"] for r in runs} == {"push", "workflow_dispatch"}
|
||||
assert [r["conclusion"] for r in runs] == ["success", "success"]
|
||||
|
||||
run_id = runs[0]["id"]
|
||||
one = await mcp.ok("gitea_actions_get_workflow_run", run=run_id, **repo)
|
||||
assert one.data["status"] == "completed"
|
||||
jobs = await mcp.ok("gitea_actions_list_workflow_run_jobs", run=run_id, **repo)
|
||||
job = jobs.data["jobs"][0]
|
||||
assert job["conclusion"] == "success"
|
||||
job_id = str(job["id"]) # the job id is a string argument
|
||||
fetched = await mcp.ok("gitea_actions_get_workflow_job", job_id=job_id, **repo)
|
||||
assert fetched.data["id"] == job["id"]
|
||||
logs = await mcp.ok("gitea_actions_download_run_job_logs", job_id=job["id"], **repo)
|
||||
assert isinstance(logs.data, str)
|
||||
assert "hello" in logs.data
|
||||
artifacts = await mcp.ok("gitea_actions_get_artifacts_of_run", run=run_id, **repo)
|
||||
assert artifacts.data["artifacts"] == []
|
||||
assert (await mcp.ok("gitea_actions_get_artifacts", **repo)).data["total_count"] == 0
|
||||
tasks = await mcp.ok("gitea_actions_list_action_tasks", **repo)
|
||||
assert tasks.data["total_count"] >= 2
|
||||
Reference in new issue
Block a user