diff --git a/providers/git/src/airflow/providers/git/bundles/git.py b/providers/git/src/airflow/providers/git/bundles/git.py index b10fc0e7f9489..1f0b0c56f6af0 100644 --- a/providers/git/src/airflow/providers/git/bundles/git.py +++ b/providers/git/src/airflow/providers/git/bundles/git.py @@ -99,9 +99,17 @@ def __init__( self.hook: GitHook | None = None try: self.hook = GitHook(git_conn_id=git_conn_id or "git_default", repo_url=self.repo_url) - except Exception: - # re raise so exception propagates immediately with clear error message - raise + except Exception as e: + if not self.repo_url: + # when repo_url is not provided, we need the connection to get it and if we fail here, we raise + raise + # if repo_url is provided, connection can be optional for auth, so we log and continue to enable + # public repos to work without connection + self._log.info( + "Connection not found but repo_url provided, continuing without Airflow connection", + git_conn_id=git_conn_id, + exc_info=str(e), + ) if self.hook and self.hook.repo_url: self.repo_url = self.hook.repo_url diff --git a/providers/git/tests/unit/git/bundles/test_git.py b/providers/git/tests/unit/git/bundles/test_git.py index ffeb3250bd7c0..5b64b3db33dd3 100644 --- a/providers/git/tests/unit/git/bundles/test_git.py +++ b/providers/git/tests/unit/git/bundles/test_git.py @@ -715,14 +715,15 @@ def test_clone_repo_no_such_path_error(self, mock_githook): @patch.dict(os.environ, {"AIRFLOW_CONN_MY_TEST_GIT": '{"host": "something", "conn_type": "git"}'}) @pytest.mark.parametrize( - ("conn_id", "expected_hook_type", "exception_expected"), + ("conn_id", "repo_url", "expected_hook_type", "exception_expected"), [ - ("my_test_git", GitHook, False), - ("something-else", None, True), + ("my_test_git", None, GitHook, False), + ("something-else", None, None, True), + ("something-else", "https://github.com/apache/airflow.git", None, False), ], ) def test_repo_url_access_missing_connection_raises_exception( - self, conn_id, expected_hook_type, exception_expected + self, conn_id, repo_url, expected_hook_type, exception_expected ): if exception_expected: with pytest.raises(Exception, match="The conn_id `something-else` isn't defined"): @@ -730,14 +731,30 @@ def test_repo_url_access_missing_connection_raises_exception( name="testa", tracking_ref="main", git_conn_id=conn_id, + repo_url=repo_url, ) else: bundle = GitDagBundle( name="testa", tracking_ref="main", git_conn_id=conn_id, + repo_url=repo_url, ) - assert isinstance(bundle.hook, expected_hook_type) + if expected_hook_type is None: + assert bundle.hook is None + else: + assert isinstance(bundle.hook, expected_hook_type) + + def test_public_repository_works_without_connection(self): + """Test that public repositories work without any connection defined.""" + bundle = GitDagBundle( + name="public-repo", + tracking_ref="main", + repo_url="https://github.com/apache/airflow.git", + git_conn_id="nonexistent_connection", + ) + assert bundle.hook is None + assert bundle.repo_url == "https://github.com/apache/airflow.git" @mock.patch("airflow.providers.git.bundles.git.GitHook") def test_lock_used(self, mock_githook, git_repo):