77 lines
2.5 KiB
Python
77 lines
2.5 KiB
Python
#!/usr/bin/env python3
|
|
"""Create a Gitea issue when a CI workflow fails.
|
|
|
|
Used by the release and publish workflows to alert on failures that would
|
|
otherwise go unnoticed in the Actions tab.
|
|
|
|
Usage:
|
|
REPO_TOKEN=<token> python3 scripts/notify_failure.py \
|
|
--repo <owner/repo> \
|
|
--run-id <run_id> \
|
|
--workflow <workflow_name> \
|
|
--commit <commit_sha>
|
|
"""
|
|
|
|
from __future__ import annotations
|
|
|
|
import os
|
|
|
|
import click
|
|
from dotenv import load_dotenv # pyright: ignore[reportMissingImports,reportUnknownVariableType]
|
|
|
|
from gitea_runner_manager.api_clients import GiteaClient
|
|
from gitea_runner_manager.config import GITEA_API_URL
|
|
from gitea_runner_manager.exceptions import APIError
|
|
from gitea_runner_manager.i18n import _
|
|
|
|
load_dotenv(override=True)
|
|
|
|
|
|
@click.command()
|
|
@click.option("--repo", required=True, help="Repository in owner/name format.")
|
|
@click.option("--run-id", required=True, help="CI run ID.")
|
|
@click.option("--workflow", required=True, help="Workflow name.")
|
|
@click.option("--commit", required=True, help="Commit SHA.")
|
|
def main(repo: str, run_id: str, workflow: str, commit: str) -> None:
|
|
token = os.environ.get("REPO_TOKEN", "")
|
|
if not token:
|
|
raise click.ClickException(_("ERROR: REPO_TOKEN is not set."))
|
|
|
|
owner, repo_name = repo.split("/")
|
|
client = GiteaClient(GITEA_API_URL, token, owner, repo_name)
|
|
|
|
title = f"[CI] {workflow} workflow failed (run #{run_id})"
|
|
body = (
|
|
f"The **{workflow}** workflow failed.\n\n"
|
|
f"- **Run ID**: #{run_id}\n"
|
|
f"- **Commit**: `{commit[:8]}`\n"
|
|
f"- **Check the logs**: {GITEA_API_URL.replace('/api/v1', '')}/"
|
|
f"{repo}/actions/runs/{run_id}\n\n"
|
|
f"Please investigate and fix the issue."
|
|
)
|
|
|
|
try:
|
|
# Look up label IDs by name (Gitea API expects integer IDs, not strings)
|
|
label_ids: list[int] = []
|
|
for label in client.list_labels():
|
|
if label.get("name") == "bug":
|
|
label_ids.append(int(label["id"]))
|
|
break
|
|
issue = client.create_issue(title=title, body=body, labels=label_ids if label_ids else None)
|
|
except APIError as e:
|
|
raise click.ClickException(
|
|
_("Failed to create issue: HTTP {status} — {message}", status=e.status, message=e.message)
|
|
) from None
|
|
|
|
click.echo(
|
|
_(
|
|
"Created issue #{issue_id}: {title}",
|
|
issue_id=issue.get("id", "?"),
|
|
title=title,
|
|
)
|
|
)
|
|
|
|
|
|
if __name__ == "__main__": # pragma: no cover
|
|
main()
|