# Releasing crewai The release CLI (`devtools release`) drives the full end-to-end flow, including the docs-versioning step that has to happen at every release cut. This runbook is the human-facing summary; the canonical implementation lives in [`lib/devtools/src/crewai_devtools/cli.py`](lib/devtools/src/crewai_devtools/cli.py). ## Why a docs-versioning step exists Until the v1.15 series, `docs/docs.json` had 16 "versions" in its selector but every one of them rendered the same single-source MDX files. Picking v1.10.0 in the dropdown silently served the latest docs from `main`. We fixed that by adopting Mintlify's directory-based versioning: each release gets its own frozen snapshot under `docs/v/`, an `Edge` selector renders the rolling `main` state (`docs/edge/...`) for unreleased work, and the canonical `//...` URLs redirect to whichever version is currently `default` + `Latest`. The release-cut step keeps this model honest. Skip it and the new release will not appear in the selector and the canonical URLs will keep pointing at the previous default — i.e. users following a stale link land on docs that don't describe the version they just installed. ## Happy path: `devtools release` For a normal release: ```bash devtools release 1.15.0 ``` This runs the full pipeline: 1. Phase 1 — version bump PR, polls until merged. 2. Phase 2 — generates AI release notes, then opens the docs PR titled `[docs-freeze] docs: snapshot and changelog for v1.15.0`. That PR: - prepends a release entry to `docs/edge//changelog.mdx` for every supported locale, - copies `docs/edge/` into `docs/v1.15.0/`, - rewrites `openapi:` MDX refs inside the snapshot so each frozen page reads its own OpenAPI YAML instead of the live one, - inserts a `v1.15.0` entry into every language block in `docs/docs.json`, marks it `default: true` with tag `"Latest"`, and demotes the previous default, - rewires the wildcard redirects so `//:slug*` lands on `/v1.15.0//:slug*`. The CLI polls until you (or another reviewer) merge the docs PR. 3. Phase 2 (cont.) — tags `main`, creates the GitHub release, triggers `publish.yml`, and bumps the deployment_test repo. 4. Phase 3 — clones the enterprise repo, bumps versions, opens its bump PR, polls, then tags + releases enterprise. The `[docs-freeze]` PR title prefix is what the [`docs-snapshots.yml`](.github/workflows/docs-snapshots.yml) CI guard reads to allow the snapshot directory and any image deletions to land. The CLI sets it automatically. Pre-releases (e.g. `1.15.0a1`) skip the snapshot step — they ride Edge — and the docs PR title omits the `[docs-freeze]` prefix. ## Manual escape hatch: freeze script If you ever need to freeze without going through the full release flow (e.g. retroactively snapshotting a release that shipped without docs versioning, or testing the freeze locally): ```bash python scripts/docs/freeze_current_edge.py 1.15.0 ``` This is a thin wrapper around the same `crewai_devtools.docs_versioning.freeze` function used by `devtools release`. It updates the snapshot + `docs.json` + redirects but does not touch changelogs, open a PR, or coordinate with the rest of the release flow. Pair it with a manual PR titled `[docs-freeze] snapshot docs for v1.15.0`. ## Lifecycle reminders - Edge (`docs/edge/...`) always reflects `main`. After a release cut, fixes to the just-released docs go into Edge as normal PRs and ship with the next release. - We do not back-port docs fixes into older frozen snapshots. If a fix matters enough to publish on an older version, it is a deliberate `[docs-freeze]` PR — treat that as an exception. - The freeze function is idempotent. If you have to re-run it (e.g. you pushed a docs fix between snapshotting and merging the PR), delete the partially-built `docs/v/` directory first and run again. ## Troubleshooting - **The freeze step warned that the snapshot was already current.** Either someone else already cut this version, or a previous run left a stale `docs/v/` directory. Inspect it, then either keep going or delete the directory and re-run. - **CI fails on a non-`[docs-freeze]` PR claiming you modified frozen snapshots.** Check the diff — almost always this is an accidental edit under `docs/v*/`. Move the change to the matching path under `docs/edge//...` instead. If you truly need to edit a frozen snapshot, re-title the PR with the `[docs-freeze]` prefix and document the reason in the PR description. - **CI fails on a non-`[docs-freeze]` PR claiming you deleted an image.** Add a new image under a new filename and reference that from Edge. Leave the old file in place so older snapshots keep rendering.