mirror of
https://github.com/crewAIInc/crewAI.git
synced 2026-06-17 14:18:10 +00:00
Compare commits
1 Commits
flow-scrip
...
luzk/docs-
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
93dafe2637 |
114
.github/workflows/docs-snapshots.yml
vendored
Normal file
114
.github/workflows/docs-snapshots.yml
vendored
Normal file
@@ -0,0 +1,114 @@
|
||||
name: Docs Snapshots Guard
|
||||
|
||||
on:
|
||||
pull_request:
|
||||
paths:
|
||||
- "docs/**"
|
||||
|
||||
permissions:
|
||||
contents: read
|
||||
pull-requests: read
|
||||
|
||||
jobs:
|
||||
guard:
|
||||
name: Protect frozen snapshots and append-only assets
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@34e114876b0b11c390a56381ad16ebd13914f8d5 # v4.3.1
|
||||
with:
|
||||
fetch-depth: 0
|
||||
|
||||
- name: Determine merge base
|
||||
id: base
|
||||
run: |
|
||||
base_sha="$(git merge-base "origin/${{ github.event.pull_request.base.ref }}" HEAD)"
|
||||
echo "sha=$base_sha" >> "$GITHUB_OUTPUT"
|
||||
|
||||
- name: Detect escape-hatch label
|
||||
id: escape
|
||||
env:
|
||||
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||
PR_NUMBER: ${{ github.event.pull_request.number }}
|
||||
PR_TITLE: ${{ github.event.pull_request.title }}
|
||||
run: |
|
||||
# The [docs-freeze] marker (in the PR title) is the only way to
|
||||
# legitimately modify frozen snapshots or remove published assets.
|
||||
# Detect it from the title since the workflow runs on
|
||||
# pull_request (not pull_request_target) and can't always read
|
||||
# labels reliably.
|
||||
if [[ "$PR_TITLE" == *"[docs-freeze]"* ]]; then
|
||||
echo "allowed=true" >> "$GITHUB_OUTPUT"
|
||||
else
|
||||
echo "allowed=false" >> "$GITHUB_OUTPUT"
|
||||
fi
|
||||
|
||||
- name: Guard frozen snapshots
|
||||
env:
|
||||
ALLOWED: ${{ steps.escape.outputs.allowed }}
|
||||
BASE_SHA: ${{ steps.base.outputs.sha }}
|
||||
run: |
|
||||
set -euo pipefail
|
||||
# Anything under docs/v<X.Y.Z>/ is a frozen release snapshot and
|
||||
# must not change after the release-cut PR that introduced it.
|
||||
# The release-cut PR uses the [docs-freeze] title prefix to opt
|
||||
# out of this guard. ``docs/v[0-9]*/**`` is the defensive form so
|
||||
# we never catch a hypothetical ``docs/vendor/`` etc.
|
||||
violations="$(git diff --name-only --diff-filter=AMDRT \
|
||||
"$BASE_SHA"..HEAD -- 'docs/v[0-9]*/**' || true)"
|
||||
|
||||
if [[ -z "$violations" ]]; then
|
||||
echo "OK: no changes under docs/v*/"
|
||||
exit 0
|
||||
fi
|
||||
|
||||
if [[ "$ALLOWED" == "true" ]]; then
|
||||
echo "OK: [docs-freeze] PR is allowed to touch docs/v*/:"
|
||||
echo "$violations"
|
||||
exit 0
|
||||
fi
|
||||
|
||||
echo "::error::This PR modifies frozen release snapshots under docs/v*/."
|
||||
echo "Frozen snapshots are immutable. To intentionally edit a snapshot"
|
||||
echo "(e.g. a release-cut PR generated by 'devtools release' or the"
|
||||
echo "manual 'scripts/docs/freeze_current_edge.py' wrapper), prefix"
|
||||
echo "the PR title with [docs-freeze]."
|
||||
echo
|
||||
echo "Offending files:"
|
||||
echo "$violations"
|
||||
exit 1
|
||||
|
||||
- name: Guard append-only images
|
||||
env:
|
||||
ALLOWED: ${{ steps.escape.outputs.allowed }}
|
||||
BASE_SHA: ${{ steps.base.outputs.sha }}
|
||||
run: |
|
||||
set -euo pipefail
|
||||
# Deleting or renaming an image breaks every frozen snapshot that
|
||||
# still references it (snapshots reuse docs/images/ at the docs
|
||||
# root). Only [docs-freeze] PRs are allowed to do that.
|
||||
deletions="$(git diff --name-only --diff-filter=DR \
|
||||
"$BASE_SHA"..HEAD -- 'docs/images/**' || true)"
|
||||
|
||||
if [[ -z "$deletions" ]]; then
|
||||
echo "OK: no images deleted or renamed."
|
||||
exit 0
|
||||
fi
|
||||
|
||||
if [[ "$ALLOWED" == "true" ]]; then
|
||||
echo "OK: [docs-freeze] PR is allowed to delete/rename images:"
|
||||
echo "$deletions"
|
||||
exit 0
|
||||
fi
|
||||
|
||||
echo "::error::This PR deletes or renames files under docs/images/."
|
||||
echo "Images are append-only because frozen snapshots in docs/v*/"
|
||||
echo "share a single docs/images/ directory and would break if an"
|
||||
echo "asset they reference disappears or moves."
|
||||
echo
|
||||
echo "If the asset is wrong, add a new file with a new name and"
|
||||
echo "reference the new name in Edge (docs/edge/<lang>/...). Leave"
|
||||
echo "the old file in place so historical snapshots keep rendering."
|
||||
echo
|
||||
echo "Offending files:"
|
||||
echo "$deletions"
|
||||
exit 1
|
||||
142
AGENTS.md
Normal file
142
AGENTS.md
Normal file
@@ -0,0 +1,142 @@
|
||||
# Docs contributor guide
|
||||
|
||||
The `docs/` directory is published at [docs.crewai.com](https://docs.crewai.com)
|
||||
by [Mintlify](https://www.mintlify.com/). Mintlify watches `docs/docs.json`
|
||||
and the MDX files referenced from it.
|
||||
|
||||
## TL;DR for editing docs
|
||||
|
||||
- Edit MDX under `docs/edge/<lang>/...` (e.g. `docs/edge/en/concepts/agents.mdx`).
|
||||
- Your change ships under the **Edge** version selector the moment it merges
|
||||
to `main`. Edge follows `main` and is the channel for unreleased work.
|
||||
- On release cut, the current Edge state is frozen into `docs/v<X.Y.Z>/` and
|
||||
that snapshot becomes the new default version in the selector (tag:
|
||||
`Latest`). Canonical URLs (`/<lang>/...`) auto-redirect to the new default.
|
||||
- Never modify files under `docs/v*/`. Those are frozen release snapshots
|
||||
and the `docs-snapshots` CI guard rejects writes. The only exception is a
|
||||
release-cut PR (auto-generated by `devtools release` or the manual
|
||||
`scripts/docs/freeze_current_edge.py` wrapper), which uses a
|
||||
`[docs-freeze]` title prefix to opt out.
|
||||
- Never delete or rename files under `docs/images/`. Images are append-only.
|
||||
See [Images](#images) below.
|
||||
|
||||
## The version model
|
||||
|
||||
The site has one rolling channel (Edge) plus one frozen snapshot per
|
||||
release.
|
||||
|
||||
```
|
||||
docs/
|
||||
edge/ <-- Edge sources (you edit here)
|
||||
en/...
|
||||
pt-BR/ ko/ ar/
|
||||
enterprise-api.*.yaml
|
||||
|
||||
v1.14.7/ <-- frozen snapshot of v1.14.7
|
||||
en/...
|
||||
pt-BR/ ko/ ar/
|
||||
enterprise-api.*.yaml
|
||||
v1.14.6/...
|
||||
...
|
||||
|
||||
images/ <-- shared, append-only
|
||||
docs.json <-- Mintlify config: navigation + redirects
|
||||
```
|
||||
|
||||
`docs/docs.json` lists one navigation block per version per language. Edge
|
||||
points at `docs/edge/<lang>/...`; every other version points at its own
|
||||
`docs/v<X.Y.Z>/<lang>/...` subtree. Mintlify scopes both the sidebar and the
|
||||
in-site search to whichever version the reader selects, so picking
|
||||
`v1.10.0` genuinely shows the v1.10.0 docs (and only those).
|
||||
|
||||
### URLs and canonical redirects
|
||||
|
||||
Each Mintlify version corresponds to its own URL prefix:
|
||||
|
||||
- Edge: `/edge/<lang>/<page>` (e.g. `/edge/en/concepts/agents`)
|
||||
- Frozen: `/v<X.Y.Z>/<lang>/<page>` (e.g. `/v1.14.7/en/concepts/agents`)
|
||||
|
||||
External links to the old, unversioned `/<lang>/<page>` URLs would 404 under
|
||||
this layout. To keep them working, `docs.json` ships wildcard redirects:
|
||||
|
||||
```jsonc
|
||||
{ "source": "/en/:slug*", "destination": "/v1.14.7/en/:slug*", "permanent": false }
|
||||
```
|
||||
|
||||
The release-cut step rewrites the destination on every release so canonical
|
||||
`/<lang>/...` URLs always resolve to the latest stable docs.
|
||||
|
||||
## Lifecycle
|
||||
|
||||
1. **During development.** You add or edit pages under
|
||||
`docs/edge/<lang>/...` in normal PRs. They land in Edge as soon as the PR
|
||||
merges. Both `/edge/<lang>/<page>` and the version selector's `Edge` entry
|
||||
reflect the change immediately.
|
||||
2. **Release cut.** The release engineer runs `devtools release X.Y.Z`. As
|
||||
part of that flow the CLI opens a `[docs-freeze]` PR that copies Edge into
|
||||
`docs/v<X.Y.Z>/`, rewrites internal OpenAPI references, updates
|
||||
`docs/docs.json` to make `v<X.Y.Z>` the new default + `Latest`, and rewires
|
||||
the canonical-URL redirects to the new default. The PR must merge before
|
||||
the tag and PyPI publish run.
|
||||
3. **After release.** Edge keeps rolling. Patch fixes to the just-released
|
||||
docs go into Edge and ship with the next release. We do not back-edit
|
||||
frozen snapshots.
|
||||
|
||||
See [`RELEASING.md`](RELEASING.md) for the full release runbook.
|
||||
|
||||
## Images
|
||||
|
||||
Snapshots share a single `docs/images/` directory. If an image is deleted
|
||||
or renamed, every frozen snapshot that referenced it breaks. So the rule
|
||||
is:
|
||||
|
||||
- Adding new images is always fine.
|
||||
- Deleting or renaming an existing image fails CI unless the PR is a
|
||||
`[docs-freeze]` release-cut PR.
|
||||
- If an asset is wrong, add a new file with a new name and reference the
|
||||
new name in the Edge MDX (`docs/edge/<lang>/...`). Leave the old file
|
||||
alone.
|
||||
|
||||
## Local preview
|
||||
|
||||
Install the Mintlify CLI and run from `docs/`:
|
||||
|
||||
```bash
|
||||
npm i -g mintlify
|
||||
mintlify dev
|
||||
```
|
||||
|
||||
Use the version selector at the top of the rendered page to switch between
|
||||
Edge and frozen versions.
|
||||
|
||||
To check links across every version:
|
||||
|
||||
```bash
|
||||
mintlify broken-links
|
||||
```
|
||||
|
||||
CI runs the broken-links check on every PR that touches `docs/**` via
|
||||
[`.github/workflows/docs-broken-links.yml`](.github/workflows/docs-broken-links.yml).
|
||||
|
||||
## Scripts
|
||||
|
||||
- `scripts/docs/freeze_historical_versions.py` — one-time migration that
|
||||
reconstructed `docs/v1.10.0/` through `docs/v1.14.7/` from git tags. You
|
||||
should not need to run this again.
|
||||
- `scripts/docs/prefix_version_paths.py` — one-time migration that switched
|
||||
`docs/docs.json` to directory-based versioning, inserted Edge, and added
|
||||
the canonical-URL redirects. You should not need to run this again.
|
||||
- `scripts/docs/freeze_current_edge.py` — thin CLI wrapper around
|
||||
`crewai_devtools.docs_versioning.freeze`. `devtools release` calls the
|
||||
same module during its docs PR step; this script is the manual escape
|
||||
hatch (e.g. retroactively freezing a forgotten release).
|
||||
|
||||
## CI guards
|
||||
|
||||
- [`.github/workflows/docs-snapshots.yml`](.github/workflows/docs-snapshots.yml)
|
||||
enforces the two rules above (frozen snapshots immutable, images
|
||||
append-only). Both checks accept the `[docs-freeze]` PR-title escape
|
||||
hatch.
|
||||
- [`.github/workflows/docs-broken-links.yml`](.github/workflows/docs-broken-links.yml)
|
||||
runs `mintlify broken-links` against the whole site, so adding a new
|
||||
page or moving a snapshot file that breaks a link will fail CI.
|
||||
13
README.md
13
README.md
@@ -601,6 +601,19 @@ CrewAI is open-source and we welcome contributions. If you're looking to contrib
|
||||
- Send a pull request.
|
||||
- We appreciate your input!
|
||||
|
||||
### Contributing to the docs
|
||||
|
||||
The site at [docs.crewai.com](https://docs.crewai.com) is published from
|
||||
`docs/` by [Mintlify](https://www.mintlify.com/). The docs use directory-based
|
||||
versioning: edits to `docs/edge/<lang>/...` (e.g.
|
||||
`docs/edge/en/concepts/agents.mdx`) land under the **Edge** version selector
|
||||
immediately and are frozen into a new versioned snapshot under
|
||||
`docs/v<X.Y.Z>/` at the next release cut. Frozen snapshots are immutable — CI
|
||||
rejects PRs that modify them without a `[docs-freeze]` title prefix. The
|
||||
release CLI (`devtools release`) handles the freeze automatically; see
|
||||
[`AGENTS.md`](AGENTS.md) for the full contributor guide and
|
||||
[`RELEASING.md`](RELEASING.md) for the release-cut runbook.
|
||||
|
||||
### Installing Dependencies
|
||||
|
||||
```bash
|
||||
|
||||
104
RELEASING.md
Normal file
104
RELEASING.md
Normal file
@@ -0,0 +1,104 @@
|
||||
# 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<X.Y.Z>/`, an `Edge` selector
|
||||
renders the rolling `main` state (`docs/edge/...`) for unreleased work,
|
||||
and the canonical `/<lang>/...` 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/<lang>/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 `/<lang>/:slug*` lands on
|
||||
`/v1.15.0/<lang>/: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<X.Y.Z>/` 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<X.Y.Z>/` 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/<lang>/...` 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.
|
||||
32682
docs/docs.json
32682
docs/docs.json
File diff suppressed because it is too large
Load Diff
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user