mirror of
https://github.com/crewAIInc/crewAI.git
synced 2026-04-30 14:52:36 +00:00
feat: add enterprise release phase to devtools release
Some checks failed
CodeQL Advanced / Analyze (actions) (push) Has been cancelled
CodeQL Advanced / Analyze (python) (push) Has been cancelled
Check Documentation Broken Links / Check broken links (push) Has been cancelled
Nightly Canary Release / Check for new commits (push) Has been cancelled
Nightly Canary Release / Build nightly packages (push) Has been cancelled
Nightly Canary Release / Publish nightly to PyPI (push) Has been cancelled
Mark stale issues and pull requests / stale (push) Has been cancelled
Some checks failed
CodeQL Advanced / Analyze (actions) (push) Has been cancelled
CodeQL Advanced / Analyze (python) (push) Has been cancelled
Check Documentation Broken Links / Check broken links (push) Has been cancelled
Nightly Canary Release / Check for new commits (push) Has been cancelled
Nightly Canary Release / Build nightly packages (push) Has been cancelled
Nightly Canary Release / Publish nightly to PyPI (push) Has been cancelled
Mark stale issues and pull requests / stale (push) Has been cancelled
This commit is contained in:
@@ -8,18 +8,22 @@ Installed automatically via the workspace (`uv sync`). Requires:
|
||||
|
||||
- [GitHub CLI](https://cli.github.com/) (`gh`) — authenticated
|
||||
- `OPENAI_API_KEY` env var — for release note generation and translation
|
||||
- `ENTERPRISE_REPO` env var — GitHub repo for enterprise releases
|
||||
- `ENTERPRISE_VERSION_DIRS` env var — comma-separated directories to bump in the enterprise repo
|
||||
- `ENTERPRISE_CREWAI_DEP_PATH` env var — path to the pyproject.toml with the `crewai[tools]` pin in the enterprise repo
|
||||
|
||||
## Commands
|
||||
|
||||
### `devtools release <version>`
|
||||
|
||||
Full end-to-end release. Bumps versions, creates PRs, tags, and publishes a GitHub release.
|
||||
Full end-to-end release. Bumps versions, creates PRs, tags, publishes a GitHub release, and releases the enterprise repo.
|
||||
|
||||
```
|
||||
devtools release 1.10.3
|
||||
devtools release 1.10.3a1 # pre-release
|
||||
devtools release 1.10.3 --no-edit # skip editing release notes
|
||||
devtools release 1.10.3 --dry-run # preview without changes
|
||||
devtools release 1.10.3a1 # pre-release
|
||||
devtools release 1.10.3 --no-edit # skip editing release notes
|
||||
devtools release 1.10.3 --dry-run # preview without changes
|
||||
devtools release 1.10.3 --skip-enterprise # skip enterprise release phase
|
||||
```
|
||||
|
||||
**Flow:**
|
||||
@@ -31,6 +35,10 @@ devtools release 1.10.3 --dry-run # preview without changes
|
||||
5. Updates changelogs (en, pt-BR, ko) and docs version switcher
|
||||
6. Creates docs PR against main, polls until merged
|
||||
7. Tags main and creates GitHub release
|
||||
8. Triggers PyPI publish workflow
|
||||
9. Clones enterprise repo, bumps versions and `crewai[tools]` dep, runs `uv sync`
|
||||
10. Creates enterprise bump PR, polls until merged
|
||||
11. Tags and creates GitHub release on enterprise repo
|
||||
|
||||
### `devtools bump <version>`
|
||||
|
||||
|
||||
@@ -2,10 +2,13 @@
|
||||
|
||||
import os
|
||||
from pathlib import Path
|
||||
import re
|
||||
import subprocess
|
||||
import sys
|
||||
import tempfile
|
||||
import time
|
||||
from typing import Final, Literal
|
||||
from urllib.request import urlopen
|
||||
|
||||
import click
|
||||
from dotenv import load_dotenv
|
||||
@@ -153,12 +156,24 @@ def update_version_in_file(file_path: Path, new_version: str) -> bool:
|
||||
return False
|
||||
|
||||
|
||||
def update_pyproject_dependencies(file_path: Path, new_version: str) -> bool:
|
||||
_DEFAULT_WORKSPACE_PACKAGES: Final[list[str]] = [
|
||||
"crewai",
|
||||
"crewai-tools",
|
||||
"crewai-devtools",
|
||||
]
|
||||
|
||||
|
||||
def update_pyproject_dependencies(
|
||||
file_path: Path,
|
||||
new_version: str,
|
||||
extra_packages: list[str] | None = None,
|
||||
) -> bool:
|
||||
"""Update workspace dependency versions in pyproject.toml.
|
||||
|
||||
Args:
|
||||
file_path: Path to pyproject.toml file.
|
||||
new_version: New version string.
|
||||
extra_packages: Additional package names to update beyond the defaults.
|
||||
|
||||
Returns:
|
||||
True if any dependencies were updated, False otherwise.
|
||||
@@ -170,7 +185,7 @@ def update_pyproject_dependencies(file_path: Path, new_version: str) -> bool:
|
||||
lines = content.splitlines()
|
||||
updated = False
|
||||
|
||||
workspace_packages = ["crewai", "crewai-tools", "crewai-devtools"]
|
||||
workspace_packages = _DEFAULT_WORKSPACE_PACKAGES + (extra_packages or [])
|
||||
|
||||
for i, line in enumerate(lines):
|
||||
for pkg in workspace_packages:
|
||||
@@ -431,12 +446,29 @@ def update_changelog(
|
||||
return True
|
||||
|
||||
|
||||
def update_template_dependencies(templates_dir: Path, new_version: str) -> list[Path]:
|
||||
"""Update crewai dependency versions in CLI template pyproject.toml files.
|
||||
def _pin_crewai_deps(content: str, version: str) -> str:
|
||||
"""Replace crewai dependency version pins in a pyproject.toml string.
|
||||
|
||||
Handles both pinned (==) and minimum (>=) version specifiers,
|
||||
as well as extras like [tools].
|
||||
|
||||
Args:
|
||||
content: File content to transform.
|
||||
version: New version string.
|
||||
|
||||
Returns:
|
||||
Transformed content.
|
||||
"""
|
||||
return re.sub(
|
||||
r'"crewai(\[tools\])?(==|>=)[^"]*"',
|
||||
lambda m: f'"crewai{(m.group(1) or "")!s}=={version}"',
|
||||
content,
|
||||
)
|
||||
|
||||
|
||||
def update_template_dependencies(templates_dir: Path, new_version: str) -> list[Path]:
|
||||
"""Update crewai dependency versions in CLI template pyproject.toml files.
|
||||
|
||||
Args:
|
||||
templates_dir: Path to the CLI templates directory.
|
||||
new_version: New version string.
|
||||
@@ -444,16 +476,10 @@ def update_template_dependencies(templates_dir: Path, new_version: str) -> list[
|
||||
Returns:
|
||||
List of paths that were updated.
|
||||
"""
|
||||
import re
|
||||
|
||||
updated = []
|
||||
for pyproject in templates_dir.rglob("pyproject.toml"):
|
||||
content = pyproject.read_text()
|
||||
new_content = re.sub(
|
||||
r'"crewai(\[tools\])?(==|>=)[^"]*"',
|
||||
lambda m: f'"crewai{(m.group(1) or "")!s}=={new_version}"',
|
||||
content,
|
||||
)
|
||||
new_content = _pin_crewai_deps(content, new_version)
|
||||
if new_content != content:
|
||||
pyproject.write_text(new_content)
|
||||
updated.append(pyproject)
|
||||
@@ -607,24 +633,26 @@ def get_github_contributors(commit_range: str) -> list[str]:
|
||||
# ---------------------------------------------------------------------------
|
||||
|
||||
|
||||
def _poll_pr_until_merged(branch_name: str, label: str) -> None:
|
||||
"""Poll a GitHub PR until it is merged. Exit if closed without merging."""
|
||||
def _poll_pr_until_merged(
|
||||
branch_name: str, label: str, repo: str | None = None
|
||||
) -> None:
|
||||
"""Poll a GitHub PR until it is merged. Exit if closed without merging.
|
||||
|
||||
Args:
|
||||
branch_name: Branch name to look up the PR.
|
||||
label: Human-readable label for status messages.
|
||||
repo: Optional GitHub repo (owner/name) for cross-repo PRs.
|
||||
"""
|
||||
console.print(f"[cyan]Waiting for {label} to be merged...[/cyan]")
|
||||
cmd = ["gh", "pr", "view", branch_name]
|
||||
if repo:
|
||||
cmd.extend(["--repo", repo])
|
||||
cmd.extend(["--json", "state", "--jq", ".state"])
|
||||
|
||||
while True:
|
||||
time.sleep(10)
|
||||
try:
|
||||
state = run_command(
|
||||
[
|
||||
"gh",
|
||||
"pr",
|
||||
"view",
|
||||
branch_name,
|
||||
"--json",
|
||||
"state",
|
||||
"--jq",
|
||||
".state",
|
||||
]
|
||||
)
|
||||
state = run_command(cmd)
|
||||
except subprocess.CalledProcessError:
|
||||
state = ""
|
||||
|
||||
@@ -984,8 +1012,252 @@ def _create_tag_and_release(
|
||||
console.print(f"[green]✓[/green] Created GitHub {release_type} for {tag_name}")
|
||||
|
||||
|
||||
def _trigger_pypi_publish(tag_name: str) -> None:
|
||||
"""Trigger the PyPI publish GitHub Actions workflow."""
|
||||
_ENTERPRISE_REPO: Final[str | None] = os.getenv("ENTERPRISE_REPO")
|
||||
_ENTERPRISE_VERSION_DIRS: Final[tuple[str, ...]] = tuple(
|
||||
d.strip() for d in os.getenv("ENTERPRISE_VERSION_DIRS", "").split(",") if d.strip()
|
||||
)
|
||||
_ENTERPRISE_CREWAI_DEP_PATH: Final[str | None] = os.getenv("ENTERPRISE_CREWAI_DEP_PATH")
|
||||
_ENTERPRISE_EXTRA_PACKAGES: Final[tuple[str, ...]] = tuple(
|
||||
p.strip()
|
||||
for p in os.getenv("ENTERPRISE_EXTRA_PACKAGES", "").split(",")
|
||||
if p.strip()
|
||||
)
|
||||
|
||||
|
||||
def _update_enterprise_crewai_dep(pyproject_path: Path, version: str) -> bool:
|
||||
"""Update the crewai[tools] pin in an enterprise pyproject.toml.
|
||||
|
||||
Args:
|
||||
pyproject_path: Path to the pyproject.toml file.
|
||||
version: New crewai version string.
|
||||
|
||||
Returns:
|
||||
True if the file was modified.
|
||||
"""
|
||||
if not pyproject_path.exists():
|
||||
return 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
|
||||
|
||||
|
||||
_PYPI_POLL_INTERVAL: Final[int] = 15
|
||||
_PYPI_POLL_TIMEOUT: Final[int] = 600
|
||||
|
||||
|
||||
def _wait_for_pypi(package: str, version: str) -> None:
|
||||
"""Poll PyPI until a specific package version is available.
|
||||
|
||||
Args:
|
||||
package: PyPI package name.
|
||||
version: Version string to wait for.
|
||||
"""
|
||||
url = f"https://pypi.org/pypi/{package}/{version}/json"
|
||||
deadline = time.monotonic() + _PYPI_POLL_TIMEOUT
|
||||
|
||||
console.print(f"[cyan]Waiting for {package}=={version} to appear on PyPI...[/cyan]")
|
||||
while time.monotonic() < deadline:
|
||||
try:
|
||||
with urlopen(url) as resp: # noqa: S310
|
||||
if resp.status == 200:
|
||||
console.print(
|
||||
f"[green]✓[/green] {package}=={version} is available on PyPI"
|
||||
)
|
||||
return
|
||||
except Exception: # noqa: S110
|
||||
pass
|
||||
time.sleep(_PYPI_POLL_INTERVAL)
|
||||
|
||||
console.print(
|
||||
f"[red]Error:[/red] Timed out waiting for {package}=={version} on PyPI"
|
||||
)
|
||||
sys.exit(1)
|
||||
|
||||
|
||||
def _release_enterprise(version: str, is_prerelease: bool, dry_run: bool) -> None:
|
||||
"""Clone the enterprise repo, bump versions, and create a release PR.
|
||||
|
||||
Expects ENTERPRISE_REPO, ENTERPRISE_VERSION_DIRS, and
|
||||
ENTERPRISE_CREWAI_DEP_PATH to be validated before calling.
|
||||
|
||||
Args:
|
||||
version: New version string.
|
||||
is_prerelease: Whether this is a pre-release version.
|
||||
dry_run: Show what would be done without making changes.
|
||||
"""
|
||||
if (
|
||||
not _ENTERPRISE_REPO
|
||||
or not _ENTERPRISE_VERSION_DIRS
|
||||
or not _ENTERPRISE_CREWAI_DEP_PATH
|
||||
):
|
||||
console.print("[red]Error:[/red] Enterprise env vars not configured")
|
||||
sys.exit(1)
|
||||
|
||||
enterprise_repo: str = _ENTERPRISE_REPO
|
||||
enterprise_dep_path: str = _ENTERPRISE_CREWAI_DEP_PATH
|
||||
|
||||
console.print(
|
||||
f"\n[bold cyan]Phase 3: Releasing {enterprise_repo} {version}[/bold cyan]"
|
||||
)
|
||||
|
||||
if dry_run:
|
||||
console.print(f"[dim][DRY RUN][/dim] Would clone {enterprise_repo}")
|
||||
for d in _ENTERPRISE_VERSION_DIRS:
|
||||
console.print(f"[dim][DRY RUN][/dim] Would update versions in {d}")
|
||||
console.print(
|
||||
f"[dim][DRY RUN][/dim] Would update crewai[tools] dep in "
|
||||
f"{enterprise_dep_path}"
|
||||
)
|
||||
console.print(
|
||||
"[dim][DRY RUN][/dim] Would create bump PR, wait for merge, "
|
||||
"then tag and release"
|
||||
)
|
||||
return
|
||||
|
||||
with tempfile.TemporaryDirectory() as tmp:
|
||||
repo_dir = Path(tmp) / enterprise_repo.split("/")[-1]
|
||||
console.print(f"Cloning {enterprise_repo}...")
|
||||
run_command(["gh", "repo", "clone", enterprise_repo, str(repo_dir)])
|
||||
console.print(f"[green]✓[/green] Cloned {enterprise_repo}")
|
||||
|
||||
# --- bump versions ---
|
||||
for rel_dir in _ENTERPRISE_VERSION_DIRS:
|
||||
pkg_dir = repo_dir / rel_dir
|
||||
if not pkg_dir.exists():
|
||||
console.print(
|
||||
f"[yellow]Warning:[/yellow] {rel_dir} not found, skipping"
|
||||
)
|
||||
continue
|
||||
|
||||
for vfile in find_version_files(pkg_dir):
|
||||
if update_version_in_file(vfile, version):
|
||||
console.print(
|
||||
f"[green]✓[/green] Updated: {vfile.relative_to(repo_dir)}"
|
||||
)
|
||||
|
||||
pyproject = pkg_dir / "pyproject.toml"
|
||||
if pyproject.exists():
|
||||
if update_pyproject_dependencies(
|
||||
pyproject, version, extra_packages=list(_ENTERPRISE_EXTRA_PACKAGES)
|
||||
):
|
||||
console.print(
|
||||
f"[green]✓[/green] Updated deps in: "
|
||||
f"{pyproject.relative_to(repo_dir)}"
|
||||
)
|
||||
|
||||
# --- update crewai[tools] pin ---
|
||||
enterprise_pyproject = repo_dir / enterprise_dep_path
|
||||
if _update_enterprise_crewai_dep(enterprise_pyproject, version):
|
||||
console.print(
|
||||
f"[green]✓[/green] Updated crewai[tools] dep in {enterprise_dep_path}"
|
||||
)
|
||||
|
||||
_wait_for_pypi("crewai", version)
|
||||
|
||||
console.print("\nSyncing workspace...")
|
||||
run_command(["uv", "sync"], cwd=repo_dir)
|
||||
console.print("[green]✓[/green] Workspace synced")
|
||||
|
||||
# --- branch, commit, push, PR ---
|
||||
branch_name = f"feat/bump-version-{version}"
|
||||
run_command(["git", "checkout", "-b", branch_name], cwd=repo_dir)
|
||||
run_command(["git", "add", "."], cwd=repo_dir)
|
||||
run_command(
|
||||
["git", "commit", "-m", f"feat: bump versions to {version}"],
|
||||
cwd=repo_dir,
|
||||
)
|
||||
console.print("[green]✓[/green] Changes committed")
|
||||
|
||||
run_command(["git", "push", "-u", "origin", branch_name], cwd=repo_dir)
|
||||
console.print("[green]✓[/green] Branch pushed")
|
||||
|
||||
run_command(
|
||||
[
|
||||
"gh",
|
||||
"pr",
|
||||
"create",
|
||||
"--repo",
|
||||
enterprise_repo,
|
||||
"--base",
|
||||
"main",
|
||||
"--title",
|
||||
f"feat: bump versions to {version}",
|
||||
"--body",
|
||||
"",
|
||||
],
|
||||
cwd=repo_dir,
|
||||
)
|
||||
console.print("[green]✓[/green] Enterprise bump PR created")
|
||||
|
||||
_poll_pr_until_merged(branch_name, "enterprise bump PR", repo=enterprise_repo)
|
||||
|
||||
# --- tag and release ---
|
||||
run_command(["git", "checkout", "main"], cwd=repo_dir)
|
||||
run_command(["git", "pull"], cwd=repo_dir)
|
||||
|
||||
tag_name = version
|
||||
run_command(
|
||||
["git", "tag", "-a", tag_name, "-m", f"Release {version}"],
|
||||
cwd=repo_dir,
|
||||
)
|
||||
run_command(["git", "push", "origin", tag_name], cwd=repo_dir)
|
||||
console.print(f"[green]✓[/green] Pushed tag {tag_name}")
|
||||
|
||||
gh_cmd = [
|
||||
"gh",
|
||||
"release",
|
||||
"create",
|
||||
tag_name,
|
||||
"--repo",
|
||||
enterprise_repo,
|
||||
"--title",
|
||||
tag_name,
|
||||
"--notes",
|
||||
f"Release {version}",
|
||||
]
|
||||
if is_prerelease:
|
||||
gh_cmd.append("--prerelease")
|
||||
|
||||
run_command(gh_cmd)
|
||||
release_type = "prerelease" if is_prerelease else "release"
|
||||
console.print(
|
||||
f"[green]✓[/green] Created GitHub {release_type} for "
|
||||
f"{enterprise_repo} {tag_name}"
|
||||
)
|
||||
|
||||
|
||||
def _trigger_pypi_publish(tag_name: str, wait: bool = False) -> None:
|
||||
"""Trigger the PyPI publish GitHub Actions workflow.
|
||||
|
||||
Args:
|
||||
tag_name: The release tag to publish.
|
||||
wait: Block until the workflow run completes.
|
||||
"""
|
||||
# Capture the latest run ID before triggering so we can detect the new one
|
||||
prev_run_id = ""
|
||||
if wait:
|
||||
try:
|
||||
prev_run_id = run_command(
|
||||
[
|
||||
"gh",
|
||||
"run",
|
||||
"list",
|
||||
"--workflow=publish.yml",
|
||||
"--limit=1",
|
||||
"--json=databaseId",
|
||||
"--jq=.[0].databaseId",
|
||||
]
|
||||
)
|
||||
except subprocess.CalledProcessError:
|
||||
console.print(
|
||||
"[yellow]Note:[/yellow] Could not determine previous workflow run; "
|
||||
"continuing without previous run ID"
|
||||
)
|
||||
|
||||
with console.status("[cyan]Triggering PyPI publish workflow..."):
|
||||
try:
|
||||
run_command(
|
||||
@@ -1003,6 +1275,42 @@ def _trigger_pypi_publish(tag_name: str) -> None:
|
||||
sys.exit(1)
|
||||
console.print("[green]✓[/green] Triggered PyPI publish workflow")
|
||||
|
||||
if wait:
|
||||
console.print("[cyan]Waiting for PyPI publish workflow to complete...[/cyan]")
|
||||
run_id = ""
|
||||
deadline = time.monotonic() + 120
|
||||
while time.monotonic() < deadline:
|
||||
time.sleep(5)
|
||||
try:
|
||||
run_id = run_command(
|
||||
[
|
||||
"gh",
|
||||
"run",
|
||||
"list",
|
||||
"--workflow=publish.yml",
|
||||
"--limit=1",
|
||||
"--json=databaseId",
|
||||
"--jq=.[0].databaseId",
|
||||
]
|
||||
)
|
||||
except subprocess.CalledProcessError:
|
||||
continue
|
||||
if run_id and run_id != prev_run_id:
|
||||
break
|
||||
|
||||
if not run_id or run_id == prev_run_id:
|
||||
console.print(
|
||||
"[red]Error:[/red] Could not find the PyPI publish workflow run"
|
||||
)
|
||||
sys.exit(1)
|
||||
|
||||
try:
|
||||
run_command(["gh", "run", "watch", run_id, "--exit-status"])
|
||||
except subprocess.CalledProcessError as e:
|
||||
console.print(f"[red]✗[/red] PyPI publish workflow failed: {e}")
|
||||
sys.exit(1)
|
||||
console.print("[green]✓[/green] PyPI publish workflow completed")
|
||||
|
||||
|
||||
# ---------------------------------------------------------------------------
|
||||
# CLI commands
|
||||
@@ -1032,6 +1340,15 @@ def bump(version: str, dry_run: bool, no_push: bool, no_commit: bool) -> None:
|
||||
no_push: Don't push changes to remote.
|
||||
no_commit: Don't commit changes (just update files).
|
||||
"""
|
||||
console.print(
|
||||
f"\n[yellow]Note:[/yellow] [bold]devtools bump[/bold] only bumps versions "
|
||||
f"in this repo. It will not tag, publish to PyPI, or release enterprise.\n"
|
||||
f"If you want a full end-to-end release, run "
|
||||
f"[bold]devtools release {version}[/bold] instead."
|
||||
)
|
||||
if not Confirm.ask("Continue with bump only?", default=True):
|
||||
sys.exit(0)
|
||||
|
||||
try:
|
||||
check_gh_installed()
|
||||
|
||||
@@ -1136,6 +1453,16 @@ def tag(dry_run: bool, no_edit: bool) -> None:
|
||||
dry_run: Show what would be done without making changes.
|
||||
no_edit: Skip editing release notes.
|
||||
"""
|
||||
console.print(
|
||||
"\n[yellow]Note:[/yellow] [bold]devtools tag[/bold] only tags and creates "
|
||||
"a GitHub release for this repo. It will not bump versions, publish to "
|
||||
"PyPI, or release enterprise.\n"
|
||||
"If you want a full end-to-end release, run "
|
||||
"[bold]devtools release <version>[/bold] instead."
|
||||
)
|
||||
if not Confirm.ask("Continue with tag only?", default=True):
|
||||
sys.exit(0)
|
||||
|
||||
try:
|
||||
cwd = Path.cwd()
|
||||
lib_dir = cwd / "lib"
|
||||
@@ -1226,21 +1553,44 @@ def tag(dry_run: bool, no_edit: bool) -> None:
|
||||
"--dry-run", is_flag=True, help="Show what would be done without making changes"
|
||||
)
|
||||
@click.option("--no-edit", is_flag=True, help="Skip editing release notes")
|
||||
def release(version: str, dry_run: bool, no_edit: bool) -> None:
|
||||
@click.option(
|
||||
"--skip-enterprise",
|
||||
is_flag=True,
|
||||
help="Skip the enterprise release phase",
|
||||
)
|
||||
def release(version: str, dry_run: bool, no_edit: bool, skip_enterprise: bool) -> None:
|
||||
"""Full release: bump versions, tag, and publish a GitHub release.
|
||||
|
||||
Combines bump and tag into a single workflow. Creates a version bump PR,
|
||||
waits for it to be merged, then generates release notes, updates docs,
|
||||
creates the tag, and publishes a GitHub release.
|
||||
creates the tag, and publishes a GitHub release. Then bumps versions and
|
||||
releases the enterprise repo.
|
||||
|
||||
Args:
|
||||
version: New version to set (e.g., 1.0.0, 1.0.0a1).
|
||||
dry_run: Show what would be done without making changes.
|
||||
no_edit: Skip editing release notes.
|
||||
skip_enterprise: Skip the enterprise release phase.
|
||||
"""
|
||||
try:
|
||||
check_gh_installed()
|
||||
|
||||
if not skip_enterprise:
|
||||
missing: list[str] = []
|
||||
if not _ENTERPRISE_REPO:
|
||||
missing.append("ENTERPRISE_REPO")
|
||||
if not _ENTERPRISE_VERSION_DIRS:
|
||||
missing.append("ENTERPRISE_VERSION_DIRS")
|
||||
if not _ENTERPRISE_CREWAI_DEP_PATH:
|
||||
missing.append("ENTERPRISE_CREWAI_DEP_PATH")
|
||||
if missing:
|
||||
console.print(
|
||||
f"[red]Error:[/red] Missing required environment variable(s): "
|
||||
f"{', '.join(missing)}\n"
|
||||
f"Set them or pass --skip-enterprise to skip the enterprise release."
|
||||
)
|
||||
sys.exit(1)
|
||||
|
||||
cwd = Path.cwd()
|
||||
lib_dir = cwd / "lib"
|
||||
|
||||
@@ -1337,7 +1687,10 @@ def release(version: str, dry_run: bool, no_edit: bool) -> None:
|
||||
|
||||
if not dry_run:
|
||||
_create_tag_and_release(tag_name, release_notes, is_prerelease)
|
||||
_trigger_pypi_publish(tag_name)
|
||||
_trigger_pypi_publish(tag_name, wait=not skip_enterprise)
|
||||
|
||||
if not skip_enterprise:
|
||||
_release_enterprise(version, is_prerelease, dry_run)
|
||||
|
||||
console.print(f"\n[green]✓[/green] Release [bold]{version}[/bold] complete!")
|
||||
|
||||
|
||||
Reference in New Issue
Block a user