#!/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= python3 scripts/notify_failure.py \ --repo \ --run-id \ --workflow \ --commit """ 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()