From 6d1e8426f8055683e59fbff7cc7be8931c3f21ba Mon Sep 17 00:00:00 2001 From: eric-wang-1990 Date: Thu, 16 Jul 2026 17:36:07 -0700 Subject: [PATCH 1/2] fix(bots): revert poetry lock/pyproject churn before author/followup publish MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The engineer-bot author run on issue #860 failed at "Open / update fix PR": publish's leftover safety-net found poetry.lock + pyproject.toml unstaged and not in the agent's touched_files, so it refused to open the PR — even though the agent's fix + tests were correct (494 passed). Root cause: the shared setup-poetry action runs `poetry lock` (to reconcile the lock with the internal JFrog source it injects), which REWRITES the tracked poetry.lock / pyproject.toml in the working tree. That churn is harmless for the 5 real-CI consumers of the action (they commit nothing) but poisons the two engineer-bot workflows, which publish a PR from the working tree. Fix (engineer-bot side only — leave the shared action untouched): after the Poetry setup, `git checkout -- poetry.lock pyproject.toml` to drop the churn once the venv is built, so only the agent's edits remain in the tree at publish time. Applied to both engineer-bot.yml (author) and engineer-bot-followup.yml. Signed-off-by: eric-wang-1990 Co-authored-by: Isaac --- .github/workflows/engineer-bot-followup.yml | 9 +++++++++ .github/workflows/engineer-bot.yml | 9 +++++++++ 2 files changed, 18 insertions(+) diff --git a/.github/workflows/engineer-bot-followup.yml b/.github/workflows/engineer-bot-followup.yml index 230f8d0ef..13da1c6d6 100644 --- a/.github/workflows/engineer-bot-followup.yml +++ b/.github/workflows/engineer-bot-followup.yml @@ -94,6 +94,15 @@ jobs: with: python-version: '3.11' + # setup-poetry runs `poetry lock` (to reconcile the lock with the internal + # JFrog source it injects), which REWRITES tracked poetry.lock / pyproject.toml + # in the working tree. The venv is already built, so the tree no longer needs + # that churn — revert it, else the followup's fixup commit (or its leftover + # check) would sweep up these bot-untouched dirty files. Keep ONLY the + # agent's edits in the tree. + - name: Revert poetry lock/pyproject churn (keep only the agent's edits) + run: git checkout -- poetry.lock pyproject.toml || true + # Shared prelude: mint the engineer-bot token (pushes fixup commits, posts # replies) + the engine-scoped token, set up Node, install the engine. - name: Bot prelude (tokens + Node + engine install) diff --git a/.github/workflows/engineer-bot.yml b/.github/workflows/engineer-bot.yml index eee9d7784..740f22022 100644 --- a/.github/workflows/engineer-bot.yml +++ b/.github/workflows/engineer-bot.yml @@ -81,6 +81,15 @@ jobs: with: python-version: '3.11' + # setup-poetry runs `poetry lock` (to reconcile the lock with the internal + # JFrog source it injects), which REWRITES tracked poetry.lock / pyproject.toml + # in the working tree. The venv is already built, so the tree no longer needs + # that churn — revert it, else publish's leftover safety-net sees these + # bot-untouched dirty files and refuses to open the PR (they aren't in the + # agent's touched_files). Keep ONLY the agent's edits in the tree. + - name: Revert poetry lock/pyproject churn (keep only the agent's edits) + run: git checkout -- poetry.lock pyproject.toml || true + # Shared prelude: mint the engineer-bot token (pushes the fix branch, # comments) + the engine-scoped token, set up Node, install the pinned # engine (PAT-free). `token` output is used by the steps below. From d79414c623851b413709665eebb3dbb0e0d7cd63 Mon Sep 17 00:00:00 2001 From: "peco-engineer-bot[bot]" <3815206+peco-engineer-bot[bot]@users.noreply.github.com> Date: Fri, 17 Jul 2026 00:49:14 +0000 Subject: [PATCH 2/2] =?UTF-8?q?Retry:=20sleep=5Ffor=5Fretry=20uses=20max(w?= =?UTF-8?q?ait,=20delay=5Fmax)=20=E2=80=94=20inflates=20small=20Retry-Afte?= =?UTF-8?q?r=20to=20delay=5Fmax=20(60s=20floor)=20(#860)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: peco-engineer-bot[bot] <3815206+peco-engineer-bot[bot]@users.noreply.github.com> --- src/databricks/sql/auth/retry.py | 2 +- tests/unit/test_retry.py | 26 ++++++++++++++++---------- 2 files changed, 17 insertions(+), 11 deletions(-) diff --git a/src/databricks/sql/auth/retry.py b/src/databricks/sql/auth/retry.py index 9cb29fdce..62fc60a6b 100755 --- a/src/databricks/sql/auth/retry.py +++ b/src/databricks/sql/auth/retry.py @@ -297,7 +297,7 @@ def sleep_for_retry(self, response: BaseHTTPResponse) -> bool: else: proposed_wait = self.get_backoff_time() - proposed_wait = max(proposed_wait, self.delay_max) + proposed_wait = min(proposed_wait, self.delay_max) self.check_proposed_wait(proposed_wait) logger.debug(f"Retrying after {proposed_wait} seconds") time.sleep(proposed_wait) diff --git a/tests/unit/test_retry.py b/tests/unit/test_retry.py index 7abab509d..df1d3d513 100644 --- a/tests/unit/test_retry.py +++ b/tests/unit/test_retry.py @@ -39,14 +39,23 @@ def test_sleep__no_retry_after(self, t_mock, retry_policy, error_history): retry_policy.history = [error_history, error_history] retry_policy.sleep(HTTPResponse(status=503)) - expected_backoff_time = max( - self.calculate_backoff_time( - 0, retry_policy.delay_min, retry_policy.delay_max - ), - retry_policy.delay_max, + expected_backoff_time = self.calculate_backoff_time( + 0, retry_policy.delay_min, retry_policy.delay_max ) t_mock.assert_called_with(expected_backoff_time) + @patch("time.sleep") + def test_sleep__retry_after_header_honored_not_inflated( + self, t_mock, retry_policy, error_history + ): + # A small server Retry-After must be honored as-is (capped at delay_max), + # not inflated up to delay_max. + retry_policy._retry_start_time = time.time() + retry_policy.history = [error_history, error_history] + retry_policy.sleep(HTTPResponse(status=503, headers={"Retry-After": "2"})) + + t_mock.assert_called_with(2) + @patch("time.sleep") def test_sleep__no_retry_after_header__multiple_retries(self, t_mock, retry_policy): num_attempts = retry_policy.stop_after_attempts_count @@ -62,11 +71,8 @@ def test_sleep__no_retry_after_header__multiple_retries(self, t_mock, retry_poli expected_backoff_times = [] for attempt in range(num_attempts): expected_backoff_times.append( - max( - self.calculate_backoff_time( - attempt, retry_policy.delay_min, retry_policy.delay_max - ), - retry_policy.delay_max, + self.calculate_backoff_time( + attempt, retry_policy.delay_min, retry_policy.delay_max ) )