|
14 | 14 |
|
15 | 15 | """Utilities for GitHub API integration.""" |
16 | 16 |
|
| 17 | +from typing import Any |
17 | 18 | import requests |
18 | 19 | from airflow.decorators import task |
19 | 20 | from airflow.exceptions import AirflowFailException |
|
22 | 23 |
|
23 | 24 | @task |
24 | 25 | def validate_git_trigger() -> None: |
25 | | - """Validates that the DAG run has required GitHub parameters. |
26 | | -
|
27 | | - Prevents manual runs from the Airflow UI by ensuring github_run_id, |
28 | | - github_repo, and github_token are present. |
29 | | - """ |
| 26 | + """Validates that the DAG run has required GitHub parameters and was externally triggered.""" |
30 | 27 | context = get_current_context() |
| 28 | + dag_run = context.get("dag_run") |
| 29 | + |
| 30 | + if not dag_run or not dag_run.external_trigger: |
| 31 | + raise AirflowFailException( |
| 32 | + "This DAG should not be run manually from the Airflow UI." |
| 33 | + ) |
| 34 | + |
31 | 35 | params = context.get("params", {}) |
32 | 36 | run_id = params.get("github_run_id") |
33 | 37 | repo = params.get("github_repo") |
34 | 38 | token = params.get("github_token") or params.get("github_callback_token") |
35 | 39 |
|
36 | 40 | if not run_id or not repo or not token: |
37 | 41 | raise AirflowFailException( |
38 | | - "Missing required GitHub parameters (run_id, repo, token). " |
39 | | - "This DAG should not be run manually from the Airflow UI." |
| 42 | + "Missing required GitHub parameters (run_id, repo, token)." |
40 | 43 | ) |
41 | 44 |
|
42 | 45 |
|
43 | 46 | @task |
44 | | -def fire_github_callback(test_type: str | None = None) -> None: |
| 47 | +def fire_github_callback( |
| 48 | + test_type: str | None = None, |
| 49 | + repo: str | None = None, |
| 50 | + token: str | None = None, |
| 51 | + event_type: str = "airflow-dag-complete", |
| 52 | + client_payload: dict[str, Any] | None = None, |
| 53 | +) -> None: |
45 | 54 | """Fires a GitHub repository_dispatch callback with the DAG run result.""" |
46 | 55 | context = get_current_context() |
47 | 56 | params = context.get("params", {}) |
48 | 57 | dag_run = context.get("dag_run") |
49 | 58 |
|
50 | | - repo = params.get("github_repo") |
51 | | - token = params.get("github_token") or params.get("github_callback_token") |
| 59 | + target_repo = repo or params.get("github_repo") |
| 60 | + target_token = ( |
| 61 | + token or params.get("github_token") or params.get("github_callback_token") |
| 62 | + ) |
52 | 63 |
|
53 | | - if not repo or not token: |
| 64 | + if not target_repo or not target_token: |
54 | 65 | raise AirflowFailException( |
55 | 66 | "Missing required GitHub parameters (repo, token) to fire callback." |
56 | 67 | ) |
57 | 68 |
|
58 | | - client_payload = { |
59 | | - "state": "success", |
60 | | - "dag_id": dag_run.dag_id if dag_run else None, |
61 | | - "dag_run_id": dag_run.run_id if dag_run else None, |
62 | | - "sha": params.get("commit_sha") or params.get("sha"), |
63 | | - "github_run_id": params.get("github_run_id"), |
64 | | - } |
65 | | - if test_type: |
66 | | - client_payload["test_type"] = test_type |
| 69 | + if client_payload is None: |
| 70 | + payload: dict[str, Any] = { |
| 71 | + "state": "success", |
| 72 | + "dag_id": dag_run.dag_id if dag_run else None, |
| 73 | + "dag_run_id": dag_run.run_id if dag_run else None, |
| 74 | + "sha": params.get("commit_sha") |
| 75 | + or params.get("maxtext_sha") |
| 76 | + or params.get("sha"), |
| 77 | + "github_run_id": params.get("github_run_id"), |
| 78 | + } |
| 79 | + if test_type: |
| 80 | + payload["test_type"] = test_type |
| 81 | + else: |
| 82 | + payload = dict(client_payload) |
| 83 | + if test_type and "test_type" not in payload: |
| 84 | + payload["test_type"] = test_type |
67 | 85 |
|
68 | 86 | response = requests.post( |
69 | | - f"https://api.github.com/repos/{repo}/dispatches", |
| 87 | + f"https://api.github.com/repos/{target_repo}/dispatches", |
70 | 88 | headers={ |
71 | | - "Authorization": f"Bearer {token}", |
| 89 | + "Authorization": f"Bearer {target_token}", |
72 | 90 | "Accept": "application/vnd.github+json", |
73 | 91 | "X-GitHub-Api-Version": "2022-11-28", |
74 | 92 | }, |
75 | 93 | json={ |
76 | | - "event_type": "airflow-dag-complete", |
77 | | - "client_payload": client_payload, |
| 94 | + "event_type": event_type, |
| 95 | + "client_payload": payload, |
78 | 96 | }, |
79 | 97 | timeout=30, |
80 | 98 | ) |
81 | 99 | response.raise_for_status() |
| 100 | + |
| 101 | + |
| 102 | +trigger_github_repository_dispatch = fire_github_callback |
0 commit comments