diff --git a/dev/breeze/src/airflow_breeze/commands/ci_commands.py b/dev/breeze/src/airflow_breeze/commands/ci_commands.py index 0441a5450f267..30f3fd123feb0 100644 --- a/dev/breeze/src/airflow_breeze/commands/ci_commands.py +++ b/dev/breeze/src/airflow_breeze/commands/ci_commands.py @@ -229,6 +229,13 @@ def get_changed_files(commit_ref: str | None) -> tuple[str, ...]: type=str, default="", ) +@click.option( + "--github-context", + help="Github context (JSON formatted) passed by Github Actions", + envvar="GITHUB_CONTEXT", + type=str, + default="", +) @option_verbose @option_dry_run def selective_check( @@ -239,9 +246,11 @@ def selective_check( github_event_name: str, github_repository: str, github_actor: str, + github_context: str, ): from airflow_breeze.utils.selective_checks import SelectiveChecks + github_context_dict = json.loads(github_context) if github_context else {} github_event = GithubEvents(github_event_name) if commit_ref is not None: changed_files = get_changed_files(commit_ref=commit_ref) @@ -256,6 +265,7 @@ def selective_check( github_event=github_event, github_repository=github_repository, github_actor=github_actor, + github_context_dict=github_context_dict, ) print(str(sc), file=sys.stderr) diff --git a/dev/breeze/src/airflow_breeze/commands/ci_commands_config.py b/dev/breeze/src/airflow_breeze/commands/ci_commands_config.py index d2dda5ff28751..a8b50246a3a48 100644 --- a/dev/breeze/src/airflow_breeze/commands/ci_commands_config.py +++ b/dev/breeze/src/airflow_breeze/commands/ci_commands_config.py @@ -52,6 +52,7 @@ "--github-event-name", "--github-repository", "--github-actor", + "--github-context", ], }, ], diff --git a/dev/breeze/src/airflow_breeze/utils/selective_checks.py b/dev/breeze/src/airflow_breeze/utils/selective_checks.py index 9257486b86cb4..3488b56e8802c 100644 --- a/dev/breeze/src/airflow_breeze/utils/selective_checks.py +++ b/dev/breeze/src/airflow_breeze/utils/selective_checks.py @@ -298,6 +298,7 @@ def __init__( github_event: GithubEvents = GithubEvents.PULL_REQUEST, github_repository: str = APACHE_AIRFLOW_GITHUB_REPOSITORY, github_actor: str = "", + github_context_dict: dict[str, Any] | None = None, ): self._files = files self._default_branch = default_branch @@ -307,6 +308,7 @@ def __init__( self._github_event = github_event self._github_repository = github_repository self._github_actor = github_actor + self._github_context_dict = github_context_dict or {} def __important_attributes(self) -> tuple[Any, ...]: return tuple(getattr(self, f) for f in self.__HASHABLE_FIELDS) @@ -776,7 +778,21 @@ def runs_on(self) -> str: if self._github_repository == APACHE_AIRFLOW_GITHUB_REPOSITORY: if self._github_event in [GithubEvents.SCHEDULE, GithubEvents.PUSH]: return RUNS_ON_SELF_HOSTED_RUNNER - if self._github_actor in COMMITTERS and USE_PUBLIC_RUNNERS_LABEL not in self._pr_labels: + actor = self._github_actor + if self._github_event in (GithubEvents.PULL_REQUEST, GithubEvents.PULL_REQUEST_TARGET): + try: + actor = self._github_context_dict["event"]["pull_request"]["user"]["login"] + get_console().print( + f"[warning]The actor: {actor} retrieved from GITHUB_CONTEXT's" + f" event.pull_request.user.login[/]" + ) + except Exception as e: + get_console().print(f"[warning]Exception when reading user login: {e}[/]") + get_console().print( + f"[info]Could not find the actor from pull request, " + f"falling back to the actor who triggered the PR: {actor}[/]" + ) + if actor in COMMITTERS and USE_PUBLIC_RUNNERS_LABEL not in self._pr_labels: return RUNS_ON_SELF_HOSTED_RUNNER return RUNS_ON_PUBLIC_RUNNER diff --git a/dev/breeze/tests/test_selective_checks.py b/dev/breeze/tests/test_selective_checks.py index 621c1009022df..06b404b284f12 100644 --- a/dev/breeze/tests/test_selective_checks.py +++ b/dev/breeze/tests/test_selective_checks.py @@ -17,10 +17,11 @@ from __future__ import annotations import re +from typing import Any import pytest -from airflow_breeze.global_constants import GithubEvents +from airflow_breeze.global_constants import COMMITTERS, GithubEvents from airflow_breeze.utils.selective_checks import SelectiveChecks ANSI_COLORS_MATCHER = re.compile(r"(?:\x1B[@-_]|[\x80-\x9F])[0-?]*[ -/]*[@-~]") @@ -1118,3 +1119,123 @@ def test_suspended_providers( assert failed == should_fail if not failed: assert_outputs_are_printed(expected_outputs, str(stderr)) + + +@pytest.mark.parametrize( + "github_event, github_actor, github_repository, pr_labels, github_context_dict, runs_on", + [ + pytest.param(GithubEvents.PUSH, "user", "apache/airflow", [], dict(), "self-hosted", id="Push event"), + pytest.param( + GithubEvents.PUSH, + "user", + "private/airflow", + [], + dict(), + "ubuntu-22.04", + id="Push event for private repo", + ), + pytest.param( + GithubEvents.PULL_REQUEST, "user", "apache/airflow", [], dict(), "ubuntu-22.04", id="Pull request" + ), + pytest.param( + GithubEvents.PULL_REQUEST, + "user", + "private/airflow", + [], + dict(), + "ubuntu-22.04", + id="Pull request private repo", + ), + pytest.param( + GithubEvents.PULL_REQUEST, + COMMITTERS[0], + "apache/airflow", + [], + dict(), + "self-hosted", + id="Pull request committer", + ), + pytest.param( + GithubEvents.PULL_REQUEST, + COMMITTERS[0], + "apache/airflow", + [], + dict(event=dict(pull_request=dict(user=dict(login="user")))), + "ubuntu-22.04", + id="Pull request committer pr non-committer", + ), + pytest.param( + GithubEvents.PULL_REQUEST, + COMMITTERS[0], + "private/airflow", + [], + dict(), + "ubuntu-22.04", + id="Pull request private repo committer", + ), + pytest.param( + GithubEvents.PULL_REQUEST_TARGET, + "user", + "apache/airflow", + [], + dict(), + "ubuntu-22.04", + id="Pull request target", + ), + pytest.param( + GithubEvents.PULL_REQUEST_TARGET, + "user", + "private/airflow", + [], + dict(), + "ubuntu-22.04", + id="Pull request target private repo", + ), + pytest.param( + GithubEvents.PULL_REQUEST_TARGET, + COMMITTERS[0], + "apache/airflow", + [], + dict(), + "self-hosted", + id="Pull request target committer", + ), + pytest.param( + GithubEvents.PULL_REQUEST, + COMMITTERS[0], + "apache/airflow", + [], + dict(event=dict(pull_request=dict(user=dict(login="user")))), + "ubuntu-22.04", + id="Pull request target committer pr non-committer", + ), + pytest.param( + GithubEvents.PULL_REQUEST_TARGET, + COMMITTERS[0], + "private/airflow", + [], + dict(), + "ubuntu-22.04", + id="Pull request targe private repo committer", + ), + ], +) +def test_runs_on( + github_event: GithubEvents, + github_actor: str, + github_repository: str, + pr_labels: list[str], + github_context_dict: dict[str, Any], + runs_on: str, +): + stderr = SelectiveChecks( + files=(), + commit_ref="", + github_repository=github_repository, + github_event=github_event, + github_actor=github_actor, + github_context_dict=github_context_dict, + pr_labels=(), + default_branch="main", + ) + assert_outputs_are_printed({"runs-on": runs_on}, str(stderr)) diff --git a/images/breeze/output-commands-hash.txt b/images/breeze/output-commands-hash.txt index e54da37d10002..2f487dd4f9775 100644 --- a/images/breeze/output-commands-hash.txt +++ b/images/breeze/output-commands-hash.txt @@ -7,8 +7,8 @@ ci:fix-ownership:fee2c9ec9ef19686792002ae054fecdd ci:free-space:47234aa0a60b0efd84972e6e797379f8 ci:get-workflow-info:01ee34c33ad62fa5dc33e0ac8773223f ci:resource-check:1d4fe47dff9fc64ac1648ec4beb2d85c -ci:selective-check:8a39978ee69d496dae2533d37a48b137 -ci:2868dbcdd482663e9d6ccd00055b9cac +ci:selective-check:f2f76d192723dfdf6cf0ada6aba05fee +ci:2f985ab2973ce0bbea558d6fa9111dd1 ci-image:build:0633b20a81c2d3ba6b35f73923b0e0d2 ci-image:pull:3b0789fe9ec4cf6131bbec69903334d2 ci-image:verify:49fdafafa8cc3c42e0a70a4cc3fbc14b diff --git a/images/breeze/output_ci_selective-check.svg b/images/breeze/output_ci_selective-check.svg index 882ed910fbde7..80986aebb4d3a 100644 --- a/images/breeze/output_ci_selective-check.svg +++ b/images/breeze/output_ci_selective-check.svg @@ -1,4 +1,4 @@ - +