nebius/SWE-rebench-V2-PRs huggingface dataset:
Repository: rancher/fleet
Pull request #1913 (2023-10-30 10:41:13)

Fix flaky smoke test for cluster registration
Registering a cluster with a made up API server URL, not pointing to any actual server, will fail. Whether it fails with a timeout or a `connection refused` error is not relevant; what matters in this smoke test case is that the agent does not crash (see test case description).

See [this run](https://github.com/rancher/fleet/actions/runs/6646995070/job/18061545739?pr=1901) for an example of a failure fixed by this PR.

Refers to #1866.

## Test

To test this pull request, you can run the following commands:

```shell
go test ./internal/cmd/agent/register/...
```


Patch:
diff --git a/dev/setup-fleet b/dev/setup-fleet
index 4d3c7f7f..38b2832d 100755
--- a/dev/setup-fleet
+++ b/dev/setup-fleet
@@ -18,7 +18,7 @@ helm -n cattle-fleet-system upgrade --install --create-namespace --wait fleet-cr
 helm -n cattle-fleet-system upgrade --install --create-namespace --wait --reset-values \
   --set apiServerCA="$ca" \
   --set apiServerURL="$server" \
-  --set debug=true --set debugLevel=99 fleet charts/fleet
+  --set debug=true --set debugLevel=1 fleet charts/fleet
 
 # wait for controller and agent rollout
 kubectl -n cattle-fleet-system rollout status deploy/fleet-controller
diff --git a/dev/update-fleet-in-rancher-k3d b/dev/update-fleet-in-rancher-k3d
index 1e854266..be1a4725 100755
--- a/dev/update-fleet-in-rancher-k3d
+++ b/dev/update-fleet-in-rancher-k3d
@@ -28,4 +28,4 @@ helm upgrade fleet "$url" \
   --wait -n "$fleetns" \
   --set image.tag="$version" \
   --set agentImage.tag="$version" \
-  --set debug=true --set debugLevel=99
+  --set debug=true --set debugLevel=1


Test patch:
diff --git a/internal/cmd/agent/register/register_test.go b/internal/cmd/agent/register/register_test.go
index 540371ba..93cf214b 100644
--- a/internal/cmd/agent/register/register_test.go
+++ b/internal/cmd/agent/register/register_test.go
@@ -61,6 +61,7 @@ func TestRunRegistrationLabelSmokeTest(t *testing.T) {
 	agentSecret, err := runRegistration(context.Background(), mockCoreController, namespace, "my-clusterID")
 
 	assert.Nil(t, agentSecret)
-	// expecting a timeout at cluster registration creation time because the API server URL is a dummy.
-	assert.Regexp(t, regexp.MustCompile("cannot create clusterregistration.*timeout"), err.Error())
+	// expecting an error at cluster registration creation time because the API server URL is a dummy.
+	// this may be a timeout or a simple 'connection refused' error.
+	assert.Regexp(t, regexp.MustCompile("cannot create clusterregistration.*"), err.Error())
 }
Repository: rancher/fleet
Pull request #2072 (2024-01-15 10:40:00)

[v0.9] Update CI for k8s 1.29


Patch:
diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml
index b196b44a..f1c4a30a 100644
--- a/.github/workflows/ci.yml
+++ b/.github/workflows/ci.yml
@@ -41,6 +41,6 @@ jobs:
       -
         name: integration-tests
         env:
-          SETUP_ENVTEST_VER: v0.0.0-20221214170741-69f093833822
-          ENVTEST_K8S_VERSION: 1.25
+          SETUP_ENVTEST_VER: v0.0.0-20240115093953-9e6e3b144a69
+          ENVTEST_K8S_VERSION: 1.28
         run: ./.github/scripts/run-integration-tests.sh


Test patch:
diff --git a/.github/workflows/e2e-ci.yml b/.github/workflows/e2e-ci.yml
index e35206b0..bbe30972 100644
--- a/.github/workflows/e2e-ci.yml
+++ b/.github/workflows/e2e-ci.yml
@@ -27,7 +27,9 @@ jobs:
         k3s_version:
           # k3d version list k3s | sed 's/+/-/' | sort -h
           # https://hub.docker.com/r/rancher/k3s/tags
-          - v1.27.5-k3s1
+          - v1.29.0-k3s1
+          - v1.28.5-k3s1
+          #- v1.27.9-k3s1
           - v1.24.17-k3s1
     steps:
       -
Repository: TobikoData/sqlmesh
Pull request #3267 (2024-10-18 18:29:23)

Fix: ensure 'except' columns are always filtered out in star macro
Context: https://tobiko-data.slack.com/archives/C044BRE5W4S/p1729271791196899


Patch:
diff --git a/sqlmesh/core/macros.py b/sqlmesh/core/macros.py
index 975b81c6..5e5a48d8 100644
--- a/sqlmesh/core/macros.py
+++ b/sqlmesh/core/macros.py
@@ -890,7 +890,7 @@ def star(
         exp.column(column, table=table_identifier, quoted=quoted).as_(
             f"{prefix.this}{column}{suffix.this}", quoted=quoted
         )
-        for column, type_ in evaluator.columns_to_types(relation).items()
+        for column, type_ in columns_to_types.items()
     ]
 
 


Test patch:
diff --git a/tests/core/test_macros.py b/tests/core/test_macros.py
index 53063461..fdd85121 100644
--- a/tests/core/test_macros.py
+++ b/tests/core/test_macros.py
@@ -101,7 +101,7 @@ def macro_evaluator() -> MacroEvaluator:
 
 def test_star(assert_exp_eq) -> None:
     sql = """SELECT @STAR(foo) FROM foo"""
-    expected_sql = """SELECT CAST([foo].[a] AS DATETIMEOFFSET) AS [a], CAST([foo].[b] AS INTEGER) AS [b] FROM foo"""
+    expected_sql = "SELECT CAST([foo].[a] AS DATETIMEOFFSET) AS [a], CAST([foo].[b] AS INTEGER) AS [b] FROM foo"
     schema = MappingSchema(
         {
             "foo": {
@@ -114,7 +114,7 @@ def test_star(assert_exp_eq) -> None:
     evaluator = MacroEvaluator(schema=schema, dialect="tsql")
     assert_exp_eq(evaluator.transform(parse_one(sql, read="tsql")), expected_sql, dialect="tsql")
 
-    sql = """SELECT @STAR(foo, exclude := [SomeColumn]) FROM foo"""
+    sql = "SELECT @STAR(foo, exclude := [SomeColumn]) FROM foo"
     expected_sql = "SELECT CAST(`foo`.`a` AS STRING) AS `a` FROM foo"
     schema = MappingSchema(
         {
@@ -132,6 +132,20 @@ def test_star(assert_exp_eq) -> None:
         dialect="databricks",
     )
 
+    sql = "SELECT @STAR(foo, exclude := ARRAY(b)) FROM foo"
+    expected_sql = "SELECT [foo].[a] AS [a] FROM foo"
+    schema = MappingSchema(
+        {
+            "foo": {
+                "a": exp.DataType.build("unknown"),
+                "b": "int",
+            },
+        },
+        dialect="tsql",
+    )
+    evaluator = MacroEvaluator(schema=schema, dialect="tsql")
+    assert_exp_eq(evaluator.transform(parse_one(sql, read="tsql")), expected_sql, dialect="tsql")
+
 
 def test_start_no_column_types(assert_exp_eq) -> None:
     sql = """SELECT @STAR(foo) FROM foo"""
Repository: TobikoData/sqlmesh
Pull request #3320 (2024-10-31 18:20:22)

Fix: Only provide COPY GRANTS when replacing a view in Snowflake


Patch:
diff --git a/sqlmesh/core/engine_adapter/snowflake.py b/sqlmesh/core/engine_adapter/snowflake.py
index 43aa2b2e..7fae2f2e 100644
--- a/sqlmesh/core/engine_adapter/snowflake.py
+++ b/sqlmesh/core/engine_adapter/snowflake.py
@@ -172,7 +172,8 @@ class SnowflakeEngineAdapter(GetCurrentCatalogFromFunctionMixin, ClusteredByMixi
         properties = create_kwargs.pop("properties", None)
         if not properties:
             properties = exp.Properties(expressions=[])
-        properties.append("expressions", exp.CopyGrantsProperty())
+        if replace:
+            properties.append("expressions", exp.CopyGrantsProperty())
 
         super().create_view(
             view_name=view_name,


Test patch:
diff --git a/tests/core/engine_adapter/test_snowflake.py b/tests/core/engine_adapter/test_snowflake.py
index c9b8936e..b63f1f5d 100644
--- a/tests/core/engine_adapter/test_snowflake.py
+++ b/tests/core/engine_adapter/test_snowflake.py
@@ -621,3 +621,16 @@ SELECT a::INT;
     assert sql_calls == [
         'CREATE TRANSIENT TABLE IF NOT EXISTS "external"."test"."table" ("a" INT) REQUIRE_PARTITION_FILTER=TRUE'
     ]
+
+
+def test_create_view(make_mocked_engine_adapter: t.Callable):
+    adapter = make_mocked_engine_adapter(SnowflakeEngineAdapter)
+
+    adapter.create_view("test_view", parse_one("SELECT 1"))
+    adapter.create_view("test_view", parse_one("SELECT 1"), replace=False)
+
+    sql_calls = to_sql_calls(adapter)
+    assert sql_calls == [
+        'CREATE OR REPLACE VIEW "test_view" COPY GRANTS AS SELECT 1',
+        'CREATE VIEW "test_view" AS SELECT 1',
+    ]
Repository: TobikoData/sqlmesh
Pull request #3341 (2024-11-07 18:52:36)

Feat: expose batch_concurrency field for time range incremental dbt models


Patch:
diff --git a/sqlmesh/dbt/model.py b/sqlmesh/dbt/model.py
index c864cd7f..ed9e4a7f 100644
--- a/sqlmesh/dbt/model.py
+++ b/sqlmesh/dbt/model.py
@@ -74,6 +74,7 @@ class ModelConfig(BaseModelConfig):
     cron: t.Optional[str] = None
     interval_unit: t.Optional[str] = None
     batch_size: t.Optional[int] = None
+    batch_concurrency: t.Optional[int] = None
     lookback: t.Optional[int] = None
     forward_only: bool = True
     disable_restatement: t.Optional[bool] = None
@@ -208,7 +209,7 @@ class ModelConfig(BaseModelConfig):
             incremental_materialization_kwargs: t.Dict[str, t.Any] = {
                 "dialect": self.dialect(context)
             }
-            for field in ("batch_size", "lookback", "forward_only"):
+            for field in ("batch_size", "batch_concurrency", "lookback", "forward_only"):
                 field_val = getattr(self, field, None) or self.meta.get(field, None)
                 if field_val:
                     incremental_materialization_kwargs[field] = field_val


Test patch:
diff --git a/tests/dbt/test_config.py b/tests/dbt/test_config.py
index a5ac2aee..5b117a28 100644
--- a/tests/dbt/test_config.py
+++ b/tests/dbt/test_config.py
@@ -13,7 +13,12 @@ from sqlmesh.core.model.kind import OnDestructiveChange
 from sqlmesh.dbt.common import Dependencies
 from sqlmesh.dbt.context import DbtContext
 from sqlmesh.dbt.loader import sqlmesh_config
-from sqlmesh.dbt.model import IncrementalByUniqueKeyKind, Materialization, ModelConfig
+from sqlmesh.dbt.model import (
+    IncrementalByTimeRangeKind,
+    IncrementalByUniqueKeyKind,
+    Materialization,
+    ModelConfig,
+)
 from sqlmesh.dbt.project import Project
 from sqlmesh.dbt.relation import Policy
 from sqlmesh.dbt.source import SourceConfig
@@ -135,6 +140,24 @@ def test_model_to_sqlmesh_fields():
     model = model_config.to_sqlmesh(bq_default_context)
     assert model.dialect == "bigquery"
 
+    model_config = ModelConfig(
+        name="name",
+        package_name="package",
+        alias="model",
+        schema="custom",
+        database="database",
+        materialized=Materialization.INCREMENTAL,
+        sql="SELECT * FROM foo.table",
+        time_column="ds",
+        start="Jan 1 2023",
+        batch_size=5,
+        batch_concurrency=2,
+    )
+    model = model_config.to_sqlmesh(context)
+    assert isinstance(model.kind, IncrementalByTimeRangeKind)
+    assert model.kind.batch_concurrency == 2
+    assert model.kind.time_column.column.name == "ds"
+
 
 def test_test_to_sqlmesh_fields():
     sql = "SELECT * FROM FOO WHERE cost > 100"
Repository: TobikoData/sqlmesh
Pull request #2068 (2024-02-01 01:27:16)

Fix: Exclude non-model references from the selector's output


Patch:
diff --git a/sqlmesh/core/selector.py b/sqlmesh/core/selector.py
index f816146b..1ddbd9a8 100644
--- a/sqlmesh/core/selector.py
+++ b/sqlmesh/core/selector.py
@@ -134,11 +134,16 @@ class Selector:
         return value, include_upstream, include_downstream
 
     def _get_models(
-        self, model_name: str, include_upstream: bool, include_downstream: bool
+        self,
+        model_name: str,
+        include_upstream: bool,
+        include_downstream: bool,
+        models: t.Optional[t.Dict[str, Model]] = None,
     ) -> t.Set[str]:
         result = {model_name}
         if include_upstream:
-            result.update(self._dag.upstream(model_name))
+            models = models or self._models
+            result.update([u for u in self._dag.upstream(model_name) if u in models])
         if include_downstream:
             result.update(self._dag.downstream(model_name))
         return result
@@ -222,6 +227,8 @@ class Selector:
                 logger.warning(f"Expression '{selection}' doesn't match any models.")
 
             for model_fqn in matched_models:
-                results.update(self._get_models(model_fqn, include_upstream, include_downstream))
+                results.update(
+                    self._get_models(model_fqn, include_upstream, include_downstream, models=models)
+                )
 
         return results


Test patch:
diff --git a/tests/core/test_selector.py b/tests/core/test_selector.py
index d769b695..032fcca6 100644
--- a/tests/core/test_selector.py
+++ b/tests/core/test_selector.py
@@ -349,6 +349,36 @@ def test_expand_model_tags(mocker: MockerFixture, make_snapshot, tags, tag_selec
     assert selector.expand_model_selections(tag_selections) == output
 
 
+def test_select_models_with_external_parent(mocker: MockerFixture):
+    default_catalog = "test_catalog"
+    added_model = SqlModel(
+        name="db.added_model",
+        query=d.parse_one("SELECT 1 AS a FROM external"),
+        default_catalog=default_catalog,
+        tags=["tag1"],
+    )
+
+    env_name = "test_env"
+
+    state_reader_mock = mocker.Mock()
+    state_reader_mock.get_environment.return_value = Environment(
+        name=env_name,
+        snapshots=[],
+        start_at="2023-01-01",
+        end_at="2023-02-01",
+        plan_id="test_plan_id",
+    )
+    state_reader_mock.get_snapshots.return_value = {}
+
+    local_models: UniqueKeyDict[str, Model] = UniqueKeyDict("models")
+    local_models[added_model.fqn] = added_model
+
+    selector = Selector(state_reader_mock, local_models, default_catalog=default_catalog)
+
+    expanded_selections = selector.expand_model_selections(["+*added_model*"])
+    assert expanded_selections == {added_model.fqn}
+
+
 def _assert_models_equal(actual: t.Dict[str, Model], expected: t.Dict[str, Model]) -> None:
     assert set(actual) == set(expected)
     for name, model in actual.items():
Repository: TobikoData/sqlmesh
Pull request #2277 (2024-03-15 04:31:00)

Fix: Place LIMIT before ORDER BY for UNION queries when generating a CTAS query


Patch:
diff --git a/sqlmesh/core/model/definition.py b/sqlmesh/core/model/definition.py
index 948558dd..30f65bc4 100644
--- a/sqlmesh/core/model/definition.py
+++ b/sqlmesh/core/model/definition.py
@@ -424,13 +424,15 @@ class _Model(ModelMeta, frozen=True):
         """
         query = self.render_query_or_raise(**render_kwarg).copy()
 
-        for select in query.find_all(exp.Select):
-            if select.args.get("from"):
-                select.where(exp.false(), copy=False)
-                if not isinstance(select.parent, exp.Union) or (
-                    select.parent.parent is None and select.arg_key == "expression"
-                ):
-                    select.limit(0, copy=False)
+        for select_or_union in query.find_all(exp.Select, exp.Union):
+            if isinstance(select_or_union, exp.Select) and select_or_union.args.get("from"):
+                select_or_union.where(exp.false(), copy=False)
+                if not isinstance(select_or_union.parent, exp.Union):
+                    select_or_union.limit(0, copy=False)
+            elif isinstance(select_or_union, exp.Union) and not isinstance(
+                select_or_union.parent, exp.Union
+            ):
+                select_or_union.set("limit", exp.Limit(expression=exp.Literal.number(0)))
 
         if self.managed_columns:
             query.select(


Test patch:
diff --git a/tests/core/test_model.py b/tests/core/test_model.py
index 6c599b0c..4e9d6e0f 100644
--- a/tests/core/test_model.py
+++ b/tests/core/test_model.py
@@ -1799,6 +1799,18 @@ def test_model_ctas_query():
         == 'SELECT 1 AS "a" FROM "t" AS "t" WHERE FALSE UNION ALL SELECT 2 AS "a" FROM "t" AS "t" WHERE FALSE LIMIT 0'
     )
 
+    expressions = d.parse(
+        """
+        MODEL (name `a-b-c.table`, kind FULL, dialect bigquery);
+        SELECT 1 AS a FROM t UNION ALL SELECT 2 AS a FROM t ORDER BY 1
+    """
+    )
+
+    assert (
+        load_sql_based_model(expressions, dialect="bigquery").ctas_query().sql()
+        == 'SELECT 1 AS "a" FROM "t" AS "t" WHERE FALSE UNION ALL SELECT 2 AS "a" FROM "t" AS "t" WHERE FALSE ORDER BY 1 LIMIT 0'
+    )
+
 
 def test_is_breaking_change():
     model = create_external_model("a", columns={"a": "int", "limit": "int"})
Repository: TobikoData/sqlmesh
Pull request #2278 (2024-03-15 05:10:13)

fix: skip limit on recursive ctes


Patch:
diff --git a/sqlmesh/core/model/definition.py b/sqlmesh/core/model/definition.py
index 30f65bc4..11ae7598 100644
--- a/sqlmesh/core/model/definition.py
+++ b/sqlmesh/core/model/definition.py
@@ -425,12 +425,17 @@ class _Model(ModelMeta, frozen=True):
         query = self.render_query_or_raise(**render_kwarg).copy()
 
         for select_or_union in query.find_all(exp.Select, exp.Union):
+            cte = select_or_union.find_ancestor(exp.With, exp.Select, exp.Subquery)
+            skip_limit = isinstance(cte, exp.With) and cte.recursive
+
             if isinstance(select_or_union, exp.Select) and select_or_union.args.get("from"):
                 select_or_union.where(exp.false(), copy=False)
-                if not isinstance(select_or_union.parent, exp.Union):
+                if not skip_limit and not isinstance(select_or_union.parent, exp.Union):
                     select_or_union.limit(0, copy=False)
-            elif isinstance(select_or_union, exp.Union) and not isinstance(
-                select_or_union.parent, exp.Union
+            elif (
+                not skip_limit
+                and isinstance(select_or_union, exp.Union)
+                and not isinstance(select_or_union.parent, exp.Union)
             ):
                 select_or_union.set("limit", exp.Limit(expression=exp.Literal.number(0)))
 


Test patch:
diff --git a/tests/core/test_model.py b/tests/core/test_model.py
index 4e9d6e0f..ffa5eaaa 100644
--- a/tests/core/test_model.py
+++ b/tests/core/test_model.py
@@ -1811,6 +1811,24 @@ def test_model_ctas_query():
         == 'SELECT 1 AS "a" FROM "t" AS "t" WHERE FALSE UNION ALL SELECT 2 AS "a" FROM "t" AS "t" WHERE FALSE ORDER BY 1 LIMIT 0'
     )
 
+    expressions = d.parse(
+        """
+        MODEL (name `a-b-c.table`, kind FULL, dialect bigquery);
+        WITH RECURSIVE a AS (
+            SELECT * FROM x
+        ), b AS (
+            SELECT * FROM a UNION ALL SELECT * FROM a
+        )
+        SELECT * FROM b
+
+    """
+    )
+
+    assert (
+        load_sql_based_model(expressions, dialect="bigquery").ctas_query().sql()
+        == 'WITH RECURSIVE "a" AS (SELECT * FROM "x" AS "x" WHERE FALSE), "b" AS (SELECT * FROM "a" AS "a" WHERE FALSE UNION ALL SELECT * FROM "a" AS "a" WHERE FALSE) SELECT * FROM "b" AS "b" WHERE FALSE LIMIT 0'
+    )
+
 
 def test_is_breaking_change():
     model = create_external_model("a", columns={"a": "int", "limit": "int"})
Repository: TobikoData/sqlmesh
Pull request #2291 (2024-03-17 02:34:48)

Fix: Cache Trino catalog type lookup to reduce load
When running a bunch of incremental models with thousands of intervals across them, I noticed thousands of catalog type lookup queries being submitted (one for each interval).

It doesn't add a heap of load but I thought it was a bit unnecessary, so here's a patch to address it.

I notice other components within sqlmesh making use of `functools.lru_cache` so I wrapped `TrinoEngineAdapter.get_catalog_type` with it.

The core assumption is that the catalog type wont change within the same sqlmesh run. I think this is fine; to change a catalog type in Trino you have to restart the server, which would abort the current sqlmesh run anyway.


Patch:
diff --git a/sqlmesh/core/engine_adapter/trino.py b/sqlmesh/core/engine_adapter/trino.py
index 7b7a05da..62808c1b 100644
--- a/sqlmesh/core/engine_adapter/trino.py
+++ b/sqlmesh/core/engine_adapter/trino.py
@@ -1,6 +1,7 @@
 from __future__ import annotations
 
 import typing as t
+from functools import lru_cache
 
 import pandas as pd
 from pandas.api.types import is_datetime64_any_dtype  # type: ignore
@@ -60,6 +61,7 @@ class TrinoEngineAdapter(
         """Sets the catalog name of the current connection."""
         self.execute(exp.Use(this=schema_(db="information_schema", catalog=catalog)))
 
+    @lru_cache()
     def get_catalog_type(self, catalog: t.Optional[str]) -> str:
         row: t.Tuple = tuple()
         if catalog:


Test patch:
diff --git a/tests/core/engine_adapter/test_trino.py b/tests/core/engine_adapter/test_trino.py
index a8531f18..51b4f16d 100644
--- a/tests/core/engine_adapter/test_trino.py
+++ b/tests/core/engine_adapter/test_trino.py
@@ -1,4 +1,5 @@
 import typing as t
+from unittest.mock import MagicMock
 
 import pytest
 from pytest_mock.plugin import MockerFixture
@@ -55,6 +56,36 @@ def test_get_catalog_type(trino_mocked_engine_adapter: TrinoEngineAdapter, mocke
     assert adapter.current_catalog_type == "iceberg"
 
 
+def test_get_catalog_type_cached(
+    trino_mocked_engine_adapter: TrinoEngineAdapter, mocker: MockerFixture
+):
+    adapter = trino_mocked_engine_adapter
+
+    mocker.stop(t.cast(MagicMock, adapter.get_catalog_type))  # to make mypy happy
+
+    def mock_fetchone(sql):
+        if "iceberg" in sql:
+            return ("iceberg",)
+        return ("hive",)
+
+    mocker.patch(
+        "sqlmesh.core.engine_adapter.trino.TrinoEngineAdapter.fetchone", side_effect=mock_fetchone
+    )
+
+    fetchone_mock = t.cast(MagicMock, adapter.fetchone)  # to make mypy happy
+
+    adapter.get_catalog_type("datalake_iceberg")
+    adapter.get_catalog_type("datalake_iceberg")
+    adapter.get_catalog_type("datalake_iceberg")
+    assert fetchone_mock.call_count == 1
+
+    adapter.get_catalog_type("datalake")
+    assert fetchone_mock.call_count == 2
+
+    adapter.get_catalog_type("datalake_iceberg")
+    assert fetchone_mock.call_count == 2
+
+
 def test_partitioned_by_hive(
     trino_mocked_engine_adapter: TrinoEngineAdapter, mocker: MockerFixture
 ):
Repository: TobikoData/sqlmesh
Pull request #2311 (2024-03-20 15:53:38)

feat: support github enterprise url
Enterprise has a different URL start than non-enterprise but the tail of the URL is the same and that is all we care about so this updates the url parsing to be more flexible to accommodate enteprise. 


Patch:
diff --git a/sqlmesh/integrations/github/cicd/controller.py b/sqlmesh/integrations/github/cicd/controller.py
index 977e9bbf..c47be30d 100644
--- a/sqlmesh/integrations/github/cicd/controller.py
+++ b/sqlmesh/integrations/github/cicd/controller.py
@@ -67,7 +67,7 @@ class PullRequestInfo(PydanticModel):
 
     @classmethod
     def create_from_pull_request_url(cls, pull_request_url: str) -> PullRequestInfo:
-        _, _, _, _, owner, repo, _, pr_number = pull_request_url.split("/")
+        owner, repo, _, pr_number = pull_request_url.split("/")[-4:]
         return cls(
             owner=owner,
             repo=repo,


Test patch:
diff --git a/tests/fixtures/github/pull_request_synchronized_enterprise.json b/tests/fixtures/github/pull_request_synchronized_enterprise.json
new file mode 100644
index 00000000..7c2e1b73
--- /dev/null
+++ b/tests/fixtures/github/pull_request_synchronized_enterprise.json
@@ -0,0 +1,10 @@
+{
+  "action": "synchronized",
+  "pull_request": {
+    "_links": {
+      "self": {
+        "href": "https://github.my-company.com/api/v3/repos/org/repo/pulls/3"
+      }
+    }
+  }
+}
diff --git a/tests/integrations/github/cicd/test_github_event.py b/tests/integrations/github/cicd/test_github_event.py
index e1e85c05..719b60fb 100644
--- a/tests/integrations/github/cicd/test_github_event.py
+++ b/tests/integrations/github/cicd/test_github_event.py
@@ -32,3 +32,13 @@ def test_pull_request_synchronized_info(make_event_from_fixture, make_pull_reque
     assert pull_request_info.repo == "Hello-World"
     assert pull_request_info.pr_number == 2
     assert pull_request_info.full_repo_path == "Codertocat/Hello-World"
+
+
+def test_pull_request_synchronized_enterprise(make_event_from_fixture, make_pull_request_info):
+    pull_request_info = make_pull_request_info(
+        make_event_from_fixture("tests/fixtures/github/pull_request_synchronized_enterprise.json")
+    )
+    assert pull_request_info.owner == "org"
+    assert pull_request_info.repo == "repo"
+    assert pull_request_info.pr_number == 3
+    assert pull_request_info.full_repo_path == "org/repo"