fix(devtools): cover missing crewai pin sites in release flow

This commit is contained in:
Greyson LaLonde
2026-05-02 03:26:56 +08:00
committed by GitHub
parent cd2b9ee38a
commit a071838e92

View File

@@ -1207,7 +1207,12 @@ _ENTERPRISE_WORKFLOW_PATHS: Final[tuple[str, ...]] = tuple(
def _update_enterprise_crewai_dep(pyproject_path: Path, version: str) -> bool:
"""Update the crewai[tools] pin in an enterprise pyproject.toml.
"""Update crewai pins in an enterprise pyproject.toml.
Pins ``crewai`` / ``crewai[extras]`` via ``_pin_crewai_deps`` and
additionally pins any dashed ``crewai-*`` packages configured via
``ENTERPRISE_EXTRA_PACKAGES`` (e.g. ``crewai-enterprise``), which
``_pin_crewai_deps`` does not cover.
Args:
pyproject_path: Path to the pyproject.toml file.
@@ -1219,20 +1224,57 @@ def _update_enterprise_crewai_dep(pyproject_path: Path, version: str) -> bool:
if not pyproject_path.exists():
return False
changed = False
content = pyproject_path.read_text()
new_content = _pin_crewai_deps(content, version)
if new_content != content:
pyproject_path.write_text(new_content)
return True
return False
changed = True
if update_pyproject_dependencies(
pyproject_path, version, extra_packages=list(_ENTERPRISE_EXTRA_PACKAGES)
):
changed = True
return changed
def _update_workflow_crewai_pins(workflow_path: Path, version: str) -> bool:
"""Rewrite ``crewai[extras]==<old>`` pins in a single workflow file.
Operates line-by-line on the raw file via ``_repin_crewai_install``
so only version numbers change and all formatting is preserved.
Args:
workflow_path: Path to a workflow YAML file.
version: New crewai version string.
Returns:
True if the file was modified.
"""
if not workflow_path.exists():
return False
raw = workflow_path.read_text()
lines = raw.splitlines(keepends=True)
changed = False
for i, line in enumerate(lines):
if "crewai[" not in line:
continue
new_line = _repin_crewai_install(line, version)
if new_line != line:
lines[i] = new_line
changed = True
if not changed:
return False
workflow_path.write_text("".join(lines))
return True
def _update_enterprise_workflows(repo_dir: Path, version: str) -> list[Path]:
"""Update crewai version pins in enterprise CI workflow files.
Applies ``_repin_crewai_install`` line-by-line on the raw file so
only version numbers change and all formatting is preserved.
Args:
repo_dir: Root of the cloned enterprise repo.
version: New crewai version string.
@@ -1243,29 +1285,31 @@ def _update_enterprise_workflows(repo_dir: Path, version: str) -> list[Path]:
updated: list[Path] = []
for rel_path in _ENTERPRISE_WORKFLOW_PATHS:
workflow = repo_dir / rel_path
if not workflow.exists():
continue
raw = workflow.read_text()
lines = raw.splitlines(keepends=True)
changed = False
for i, line in enumerate(lines):
if "crewai[" not in line:
continue
new_line = _repin_crewai_install(line, version)
if new_line != line:
lines[i] = new_line
changed = True
if changed:
new_raw = "".join(lines)
else:
new_raw = raw
if new_raw != raw:
workflow.write_text(new_raw)
if _update_workflow_crewai_pins(workflow, version):
updated.append(workflow)
return updated
def _update_repo_workflows_crewai_pins(repo_dir: Path, version: str) -> list[Path]:
"""Update crewai pins across all GitHub workflow files in a repo.
Args:
repo_dir: Root of the cloned repo.
version: New crewai version string.
Returns:
List of workflow paths that were modified.
"""
workflows_dir = repo_dir / ".github" / "workflows"
if not workflows_dir.exists():
return []
updated: list[Path] = []
for workflow in sorted(workflows_dir.iterdir()):
if workflow.suffix not in (".yml", ".yaml"):
continue
if _update_workflow_crewai_pins(workflow, version):
updated.append(workflow)
return updated
@@ -1314,9 +1358,10 @@ _PYPI_POLL_TIMEOUT: Final[int] = 600
def _update_deployment_test_repo(version: str, is_prerelease: bool) -> None:
"""Update the deployment test repo to pin the new crewai version.
Clones the repo, updates the crewai[tools] pin in pyproject.toml,
regenerates the lockfile, commits to a branch, pushes, opens a PR
against main, then polls until the PR is merged (or closed).
Clones the repo, updates the crewai[tools] pin in pyproject.toml
and any crewai[extras] pins in .github/workflows, regenerates the
lockfile, commits to a branch, pushes, opens a PR against main,
then polls until the PR is merged (or closed).
Args:
version: New crewai version string.
@@ -1334,47 +1379,64 @@ def _update_deployment_test_repo(version: str, is_prerelease: bool) -> None:
pyproject = repo_dir / "pyproject.toml"
content = pyproject.read_text()
new_content = _pin_crewai_deps(content, version)
if new_content == content:
pyproject_changed = new_content != content
if pyproject_changed:
pyproject.write_text(new_content)
console.print(f"[green]✓[/green] Updated crewai[tools] pin to {version}")
else:
console.print(
"[yellow]Warning:[/yellow] No crewai[tools] pin found to update"
)
updated_workflows = _update_repo_workflows_crewai_pins(repo_dir, version)
for wf in updated_workflows:
console.print(
f"[green]✓[/green] Updated crewai pin in {wf.relative_to(repo_dir)}"
)
if not pyproject_changed and not updated_workflows:
console.print("[yellow]Nothing to update; skipping commit and PR.[/yellow]")
return
pyproject.write_text(new_content)
console.print(f"[green]✓[/green] Updated crewai[tools] pin to {version}")
lock_cmd = [
"uv",
"lock",
"--refresh-package",
"crewai",
"--refresh-package",
"crewai-tools",
paths_to_add: list[str] = [
str(wf.relative_to(repo_dir)) for wf in updated_workflows
]
if is_prerelease:
lock_cmd.append("--prerelease=allow")
max_retries = 10
for attempt in range(1, max_retries + 1):
try:
run_command(lock_cmd, cwd=repo_dir)
break
except subprocess.CalledProcessError:
if attempt == max_retries:
if pyproject_changed:
lock_cmd = [
"uv",
"lock",
"--refresh-package",
"crewai",
"--refresh-package",
"crewai-tools",
]
if is_prerelease:
lock_cmd.append("--prerelease=allow")
max_retries = 10
for attempt in range(1, max_retries + 1):
try:
run_command(lock_cmd, cwd=repo_dir)
break
except subprocess.CalledProcessError:
if attempt == max_retries:
console.print(
f"[red]Error:[/red] uv lock failed after {max_retries} attempts"
)
raise
console.print(
f"[red]Error:[/red] uv lock failed after {max_retries} attempts"
f"[yellow]uv lock failed (attempt {attempt}/{max_retries}),"
f" retrying in {_PYPI_POLL_INTERVAL}s...[/yellow]"
)
raise
console.print(
f"[yellow]uv lock failed (attempt {attempt}/{max_retries}),"
f" retrying in {_PYPI_POLL_INTERVAL}s...[/yellow]"
)
time.sleep(_PYPI_POLL_INTERVAL)
console.print("[green]✓[/green] Lockfile updated")
time.sleep(_PYPI_POLL_INTERVAL)
console.print("[green]✓[/green] Lockfile updated")
paths_to_add.extend(["pyproject.toml", "uv.lock"])
branch = f"chore/bump-crewai-v{version}"
create_or_reset_branch(branch, cwd=repo_dir)
run_command(["git", "add", "pyproject.toml", "uv.lock"], cwd=repo_dir)
run_command(["git", "add", *paths_to_add], cwd=repo_dir)
run_command(
["git", "commit", "-m", f"chore: bump crewai to {version}"],
cwd=repo_dir,