[config]
default_to_workspace = false
min_version = "0.36.0"
main_project_member = "."
[env]
CARGO_MAKE_EXTEND_WORKSPACE_MAKEFILE = true
CARGO_MAKE_WORKSPACE_MAKEFILE = true
RUST_BACKTRACE = 0
[tasks.default]
alias = "help"
[tasks.help]
description = "Show available tasks"
script = '''
echo "AllFrame Development Tasks"
echo ""
echo "Quality Gates:"
echo " cargo make lint - Check formatting and run clippy (CI mode)"
echo " cargo make lint-check - Check code formatting without modifying files"
echo " cargo make lint-sort - Check if Cargo.toml dependencies are sorted"
echo " cargo make format - Format all Rust code"
echo " cargo make format-sort - Sort Cargo.toml dependencies"
echo ""
echo "Testing:"
echo " cargo make test - Run all tests with main features"
echo " cargo make test-all - Run all tests with all features"
echo " cargo make test-minimal - Run tests with no features"
echo ""
echo "Building:"
echo " cargo make build - Build in debug mode"
echo " cargo make build-release - Build in release mode"
echo " cargo make clean - Clean build artifacts"
echo ""
echo "Tools:"
echo " cargo make install-tools - Install required development tools"
echo ""
echo "CI/CD:"
echo " cargo make ci - Run all CI checks (lint + test + build)"
echo ""
echo "Publishing:"
echo " cargo make version-check - Check which crates need publishing"
echo " cargo make version-sync-check - Verify internal crate versions are in sync"
echo " cargo make version-bump - Bump version (patch by default)"
echo " cargo make changelog-sync - Sync CHANGELOG.md to GitHub Pages"
echo " cargo make publish-dry-run - Verify all crates are ready to publish"
echo " cargo make publish-all - Publish all crates (parallel, skips published)"
'''
[tasks.lint-check]
description = "Check code formatting without modifying files"
cwd = "crates/allframe-core"
command = "cargo"
args = ["fmt", "--check"]
[tasks.lint-clippy]
description = "Run clippy with warnings as errors"
cwd = "crates/allframe-core"
command = "cargo"
args = ["clippy", "--features", "di,openapi,router,cqrs,otel", "--", "-D", "warnings"]
[tasks.lint]
description = "Run both format check and clippy (CI mode)"
dependencies = ["lint-check", "lint-clippy"]
[tasks.lint-sort]
description = "Check if Cargo.toml dependencies are sorted"
cwd = "crates/allframe-core"
command = "cargo"
args = ["sort", "--check"]
[tasks.format]
description = "Format all Rust code"
cwd = "crates/allframe-core"
command = "cargo"
args = ["fmt"]
[tasks.format-sort]
description = "Sort Cargo.toml dependencies"
cwd = "crates/allframe-core"
command = "cargo"
args = ["sort", "-w"]
[tasks.test]
description = "Run tests with main features"
cwd = "crates/allframe-core"
command = "cargo"
args = ["test", "--features", "di,openapi,router,cqrs"]
[tasks.test-all]
description = "Run tests with all features (excluding allsource)"
cwd = "crates/allframe-core"
command = "cargo"
args = ["test", "--features", "di,openapi,router,cqrs,otel"]
[tasks.test-minimal]
description = "Run tests with no features"
cwd = "crates/allframe-core"
command = "cargo"
args = ["test", "--no-default-features"]
[tasks.build]
description = "Build in debug mode"
cwd = "crates/allframe-core"
command = "cargo"
args = ["build"]
[tasks.build-release]
description = "Build in release mode"
cwd = "crates/allframe-core"
command = "cargo"
args = ["build", "--release"]
[tasks.clean]
description = "Clean build artifacts"
cwd = "crates/allframe-core"
command = "cargo"
args = ["clean"]
[tasks.install-tools]
description = "Install required development tools"
script = '''
echo "Installing development tools..."
cargo install cargo-sort --quiet || true
cargo install cargo-bloat --quiet || true
cargo install cargo-make --quiet || true
echo "✅ Tools installed!"
'''
[tasks.ci]
description = "Run all CI checks"
dependencies = ["lint", "lint-sort", "version-sync-check", "test", "build"]
script = '''
echo ""
echo "✅ All CI checks passed!"
'''
[tasks.size-minimal]
description = "Measure minimal binary size"
cwd = "crates/allframe-core"
command = "cargo"
args = ["bloat", "--release", "--example", "minimal", "--no-default-features", "--crates"]
[tasks.size-default]
description = "Measure default features binary size"
cwd = "crates/allframe-core"
command = "cargo"
args = ["bloat", "--release", "--example", "default_features", "--features", "di,openapi,router", "--crates"]
[tasks.size-all]
description = "Measure all features binary size"
cwd = "crates/allframe-core"
command = "cargo"
args = ["bloat", "--release", "--example", "all_features", "--features", "di,openapi,router,cqrs,otel", "--crates"]
[tasks.size]
description = "Measure binary sizes for all configurations"
dependencies = ["size-minimal", "size-default", "size-all"]
[tasks.check-size]
description = "Check binary sizes against limits"
script = '''\n#!/usr/bin/env bash
./scripts/check_size.sh
'''
[tasks.analyze-size]
description = "Analyze binary sizes in detail"
script = '''\n#!/usr/bin/env bash
./scripts/analyze_size.sh full
'''
[tasks.analyze-size-minimal]
description = "Analyze minimal binary size"
script = '''\n#!/usr/bin/env bash
./scripts/analyze_size.sh minimal
'''
[tasks.analyze-size-default]
description = "Analyze default binary size"
script = '''\n#!/usr/bin/env bash
./scripts/analyze_size.sh default
'''
[tasks.analyze-size-main]
description = "Analyze main features binary size"
script = '''\n#!/usr/bin/env bash
./scripts/analyze_size.sh all
'''
[tasks.version-sync-check]
description = "Check that all internal crate versions are in sync"
workspace = false
script_runner = "@shell"
script = '''
#!/usr/bin/env bash
set -e
# Navigate to workspace root
cd "$(git rev-parse --show-toplevel)"
# Get workspace.package version
WORKSPACE_VERSION=$(sed -n '/\[workspace\.package\]/,/\[/p' Cargo.toml | grep '^version' | cut -d'"' -f2)
echo "Workspace version: ${WORKSPACE_VERSION}"
echo ""
ERRORS=0
# Check root [package] version (allframe crate)
ROOT_VERSION=$(awk '/^\[package\]/{found=1} found && /^version/{print; exit}' Cargo.toml | cut -d'"' -f2)
echo "Checking root allframe crate:"
if [ "$ROOT_VERSION" != "$WORKSPACE_VERSION" ]; then
echo " ❌ allframe [package] version = ${ROOT_VERSION}, expected ${WORKSPACE_VERSION}"
ERRORS=$((ERRORS + 1))
else
echo " ✅ allframe [package] version = ${ROOT_VERSION}"
fi
# Check workspace.dependencies versions
check_workspace_dep() {
local crate=$1
local version=$(grep "^${crate} = " Cargo.toml | grep -o 'version = "[^"]*"' | cut -d'"' -f2)
if [ "$version" != "$WORKSPACE_VERSION" ]; then
echo " ❌ ${crate} = ${version}, expected ${WORKSPACE_VERSION}"
ERRORS=$((ERRORS + 1))
else
echo " ✅ ${crate} = ${version}"
fi
}
echo ""
echo "Checking workspace.dependencies:"
check_workspace_dep "allframe-core"
check_workspace_dep "allframe-macros"
check_workspace_dep "allframe-forge"
echo ""
if [ $ERRORS -gt 0 ]; then
echo "❌ Version sync check failed! Run 'cargo make version-bump' to fix."
exit 1
else
echo "✅ All versions in sync!"
fi
'''
[tasks.version-bump]
description = "Bump workspace version (patch, minor, or major)"
workspace = false
script_runner = "@shell"
script = '''
#!/usr/bin/env bash
set -e
# Navigate to workspace root
cd "$(git rev-parse --show-toplevel)"
BUMP_TYPE=${1:-patch}
CARGO_TOML="Cargo.toml"
# Get current workspace.package version
CURRENT=$(sed -n '/\[workspace\.package\]/,/\[/p' "$CARGO_TOML" | grep '^version' | cut -d'"' -f2)
IFS='.' read -r MAJOR MINOR PATCH <<< "$CURRENT"
case "$BUMP_TYPE" in
major)
MAJOR=$((MAJOR + 1))
MINOR=0
PATCH=0
;;
minor)
MINOR=$((MINOR + 1))
PATCH=0
;;
patch)
PATCH=$((PATCH + 1))
;;
*)
echo "Usage: cargo make version-bump [patch|minor|major]"
exit 1
;;
esac
NEW_VERSION="${MAJOR}.${MINOR}.${PATCH}"
TODAY=$(date +%Y-%m-%d)
echo "Bumping version: ${CURRENT} → ${NEW_VERSION}"
echo ""
# =============================================================================
# 1. Update Cargo.toml versions
# =============================================================================
echo "📦 Updating Cargo.toml..."
# Update workspace.package version (in [workspace.package] section only)
sed -i '' "/\[workspace\.package\]/,/\[.*\]/{s/^version = \"${CURRENT}\"/version = \"${NEW_VERSION}\"/;}" "$CARGO_TOML"
# Update root allframe crate version (in [package] section, before workspace.package)
sed -i '' "/^\[package\]/,/^\[/{s/^version = \"[0-9]*\.[0-9]*\.[0-9]*\"/version = \"${NEW_VERSION}\"/;}" "$CARGO_TOML"
# Update workspace.dependencies for internal crates
sed -i '' "s/allframe-core = { version = \"${CURRENT}\"/allframe-core = { version = \"${NEW_VERSION}\"/" "$CARGO_TOML"
sed -i '' "s/allframe-macros = { version = \"${CURRENT}\"/allframe-macros = { version = \"${NEW_VERSION}\"/" "$CARGO_TOML"
sed -i '' "s/allframe-forge = { version = \"${CURRENT}\"/allframe-forge = { version = \"${NEW_VERSION}\"/" "$CARGO_TOML"
echo " ✅ workspace.package.version = ${NEW_VERSION}"
echo " ✅ [package] version = ${NEW_VERSION} (root allframe crate)"
echo " ✅ workspace.dependencies updated"
# =============================================================================
# 2. Update documentation
# =============================================================================
echo ""
echo "📚 Updating documentation..."
# Update PROJECT_STATUS.md
if [ -f "docs/PROJECT_STATUS.md" ]; then
sed -i '' "s/\*\*Version\*\*: [0-9]*\.[0-9]*\.[0-9]*/\*\*Version\*\*: ${NEW_VERSION}/" "docs/PROJECT_STATUS.md"
sed -i '' "s/\*\*Last Updated\*\*: [0-9-]*/\*\*Last Updated\*\*: ${TODAY}/" "docs/PROJECT_STATUS.md"
echo " ✅ docs/PROJECT_STATUS.md"
fi
# Update docs/README.md
if [ -f "docs/README.md" ]; then
sed -i '' "s/\*\*Last Updated\*\*: [0-9-]*/\*\*Last Updated\*\*: ${TODAY}/" "docs/README.md"
echo " ✅ docs/README.md"
fi
# Update docs/INDEX.md
if [ -f "docs/INDEX.md" ]; then
sed -i '' "s/\*\*Last Updated\*\*: [0-9-]*/\*\*Last Updated\*\*: ${TODAY}/" "docs/INDEX.md"
echo " ✅ docs/INDEX.md"
fi
# Update README.md version references (dependency examples)
if [ -f "README.md" ]; then
# Update allframe = "X.Y.Z" patterns
sed -i '' "s/allframe = \"${CURRENT}\"/allframe = \"${NEW_VERSION}\"/g" "README.md"
# Update allframe = { version = "X.Y.Z" patterns
sed -i '' "s/allframe = { version = \"${CURRENT}\"/allframe = { version = \"${NEW_VERSION}\"/g" "README.md"
# Update allframe-mcp = "X.Y.Z" patterns
sed -i '' "s/allframe-mcp = \"${CURRENT}\"/allframe-mcp = \"${NEW_VERSION}\"/g" "README.md"
# Update current status line
sed -i '' "s/v${CURRENT}/v${NEW_VERSION}/g" "README.md"
echo " ✅ README.md"
fi
# Update GitHub Pages site (docs/site/index.html)
if [ -f "docs/site/index.html" ]; then
# Update version badges (e.g., <span class="badge green">v0.1.10</span>)
sed -i '' "s/>v${CURRENT}</>v${NEW_VERSION}</g" "docs/site/index.html"
# Update stats section version (e.g., <h3>v0.1.10</h3>)
sed -i '' "s/<h3>v${CURRENT}</<h3>v${NEW_VERSION}</g" "docs/site/index.html"
echo " ✅ docs/site/index.html (GitHub Pages)"
fi
# =============================================================================
# 3. Summary
# =============================================================================
echo ""
echo "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━"
echo "✅ Version bumped: ${CURRENT} → ${NEW_VERSION}"
echo ""
echo "Files updated:"
echo " 📦 Cargo.toml (workspace + allframe crate)"
echo " 📚 docs/PROJECT_STATUS.md"
echo " 📚 docs/README.md"
echo " 📚 docs/INDEX.md"
echo " 📚 README.md"
echo " 🌐 docs/site/index.html (GitHub Pages)"
echo ""
echo "Next steps:"
echo " 1. Update CHANGELOG.md with release notes for v${NEW_VERSION}"
echo " 2. Run: cargo make changelog-sync (regenerates docs/site/changelog.html)"
echo " 3. Run: cargo make ci"
echo " 4. Commit: git commit -am \"release: v${NEW_VERSION}\""
echo " 5. Tag: git tag v${NEW_VERSION}"
echo " 6. Push: git push && git push --tags (auto-deploys GitHub Pages)"
echo " 7. Publish: cargo make publish-all"
'''
[tasks.changelog-sync]
description = "Sync changelog from CHANGELOG.md to GitHub Pages site"
workspace = false
script_runner = "@shell"
script = '''
#!/usr/bin/env bash
set -e
# Navigate to workspace root
cd "$(git rev-parse --show-toplevel)"
echo "📝 Syncing changelog to GitHub Pages..."
# Generate the changelog HTML using the Python script
python3 scripts/generate_changelog_html.py CHANGELOG.md > docs/site/changelog.html
echo " ✅ docs/site/changelog.html updated from CHANGELOG.md"
echo ""
echo "Done! The changelog page has been regenerated from CHANGELOG.md"
'''
[tasks.version-check]
description = "Check which crates need publishing"
workspace = false
script_runner = "@shell"
script = '''
#!/usr/bin/env bash
# Navigate to workspace root
cd "$(git rev-parse --show-toplevel)"
# Get workspace.package version (after [workspace.package] section)
LOCAL_VERSION=$(sed -n '/\[workspace\.package\]/,/\[/p' Cargo.toml | grep '^version' | cut -d'"' -f2)
echo "Workspace version: ${LOCAL_VERSION}"
echo ""
check_crate() {
local crate=$1
local published=$(curl -s "https://crates.io/api/v1/crates/${crate}" | grep -o "\"${LOCAL_VERSION}\"" | head -1)
if [ -n "$published" ]; then
echo " ✅ ${crate}@${LOCAL_VERSION} - already published"
else
echo " 📦 ${crate}@${LOCAL_VERSION} - needs publishing"
fi
}
echo "Crate status:"
check_crate "allframe"
check_crate "allframe-macros"
check_crate "allframe-core"
check_crate "allframe-mcp"
check_crate "allframe-forge"
'''
[tasks.publish-macros]
description = "Publish allframe-macros to crates.io"
cwd = "crates/allframe-macros"
command = "cargo"
args = ["publish"]
[tasks.publish-core]
description = "Publish allframe-core to crates.io"
cwd = "crates/allframe-core"
command = "cargo"
args = ["publish"]
[tasks.publish-mcp]
description = "Publish allframe-mcp to crates.io"
cwd = "crates/allframe-mcp"
command = "cargo"
args = ["publish"]
[tasks.publish-forge]
description = "Publish allframe-forge to crates.io"
cwd = "crates/allframe-forge"
command = "cargo"
args = ["publish"]
[tasks.publish-wait]
description = "Wait for crates.io indexing"
script = '''
echo "⏳ Waiting 30s for crates.io indexing..."
sleep 30
echo "✅ Done waiting"
'''
[tasks.publish-all]
description = "Publish all crates to crates.io in dependency order (parallel where possible)"
workspace = false
script_runner = "@shell"
script = '''
#!/usr/bin/env bash
set -e
# Navigate to workspace root
cd "$(git rev-parse --show-toplevel)"
# Get workspace.package version
LOCAL_VERSION=$(sed -n '/\[workspace\.package\]/,/\[/p' Cargo.toml | grep '^version' | cut -d'"' -f2)
echo "🚀 Publishing AllFrame crates v${LOCAL_VERSION} to crates.io"
echo ""
# Track if anything was actually published (to decide if we need to wait)
PUBLISHED_SOMETHING=false
# Function to check if version is already published
is_published() {
local crate=$1
local version=$2
# Check crates.io API
local published=$(curl -s "https://crates.io/api/v1/crates/${crate}" | grep -o "\"${version}\"" | head -1)
[ -n "$published" ]
}
# Function to publish a crate if not already published
# Returns 0 if skipped, 1 if published
publish_crate() {
local crate=$1
local path=$2
if is_published "$crate" "$LOCAL_VERSION"; then
echo " ⏭️ ${crate} - already published"
return 0
fi
echo " 📦 Publishing ${crate}..."
cd "$path" && cargo publish --allow-dirty && cd - > /dev/null
echo " ✅ ${crate} published"
return 1 # Signal that we published something
}
# Wave 1: No internal dependencies (parallel)
echo "━━━ Wave 1: Independent crates ━━━"
WAVE1_PUBLISHED=false
if ! is_published "allframe-macros" "$LOCAL_VERSION"; then
echo " 📦 Publishing allframe-macros..."
cd crates/allframe-macros && cargo publish --allow-dirty && cd - > /dev/null
echo " ✅ allframe-macros published"
WAVE1_PUBLISHED=true
else
echo " ⏭️ allframe-macros - already published"
fi &
PID_MACROS=$!
if ! is_published "allframe-forge" "$LOCAL_VERSION"; then
echo " 📦 Publishing allframe-forge..."
cd crates/allframe-forge && cargo publish --allow-dirty && cd - > /dev/null
echo " ✅ allframe-forge published"
WAVE1_PUBLISHED=true
else
echo " ⏭️ allframe-forge - already published"
fi &
PID_FORGE=$!
# Wait for wave 1
wait $PID_MACROS || true
wait $PID_FORGE || true
# Only wait for indexing if we published something in wave 1
if ! is_published "allframe-macros" "$LOCAL_VERSION" || ! is_published "allframe-forge" "$LOCAL_VERSION"; then
# Re-check - if either still not published, we need to wait
:
fi
# Check if wave 1 published anything (need fresh check after parallel)
NEED_WAIT=false
if ! is_published "allframe-macros" "$LOCAL_VERSION" 2>/dev/null; then
NEED_WAIT=true
fi
# Wave 2: Depends on macros
echo ""
echo "━━━ Wave 2: allframe-core ━━━"
if ! is_published "allframe-core" "$LOCAL_VERSION"; then
# Need to wait for macros to be indexed first
echo " ⏳ Waiting 15s for crates.io indexing..."
sleep 15
echo " 📦 Publishing allframe-core..."
cd crates/allframe-core && cargo publish --allow-dirty && cd - > /dev/null
echo " ✅ allframe-core published"
PUBLISHED_SOMETHING=true
else
echo " ⏭️ allframe-core - already published"
fi
# Wave 3: Depends on core
echo ""
echo "━━━ Wave 3: allframe-mcp ━━━"
if ! is_published "allframe-mcp" "$LOCAL_VERSION"; then
if [ "$PUBLISHED_SOMETHING" = true ]; then
echo " ⏳ Waiting 15s for crates.io indexing..."
sleep 15
fi
echo " 📦 Publishing allframe-mcp..."
cd crates/allframe-mcp && cargo publish --allow-dirty && cd - > /dev/null
echo " ✅ allframe-mcp published"
PUBLISHED_SOMETHING=true
else
echo " ⏭️ allframe-mcp - already published"
fi
# Wave 4: Root allframe crate (depends on forge)
echo ""
echo "━━━ Wave 4: allframe (root crate) ━━━"
if ! is_published "allframe" "$LOCAL_VERSION"; then
if [ "$PUBLISHED_SOMETHING" = true ]; then
echo " ⏳ Waiting 15s for crates.io indexing..."
sleep 15
fi
echo " 📦 Publishing allframe..."
cargo publish --allow-dirty
echo " ✅ allframe published"
else
echo " ⏭️ allframe - already published"
fi
echo ""
echo "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━"
echo "✅ All crates at v${LOCAL_VERSION}"
echo ""
echo " allframe @ ${LOCAL_VERSION} (root - what users import)"
echo " allframe-macros @ ${LOCAL_VERSION}"
echo " allframe-core @ ${LOCAL_VERSION}"
echo " allframe-mcp @ ${LOCAL_VERSION}"
echo " allframe-forge @ ${LOCAL_VERSION}"
echo ""
echo "View at: https://crates.io/crates/allframe"
'''
[tasks.publish-dry-run]
description = "Dry-run publish all crates (no actual publish)"
script = '''
#!/usr/bin/env bash
set -e
echo "🔍 Dry-run publish for AllFrame crates"
echo ""
echo "📦 [1/5] Checking allframe-macros..."
cd crates/allframe-macros && cargo publish --dry-run && cd ../..
echo "📦 [2/5] Checking allframe-forge..."
cd crates/allframe-forge && cargo publish --dry-run && cd ../..
echo "📦 [3/5] Checking allframe-core..."
cd crates/allframe-core && cargo publish --dry-run && cd ../..
echo "📦 [4/5] Checking allframe-mcp..."
cd crates/allframe-mcp && cargo publish --dry-run && cd ../..
echo "📦 [5/5] Checking allframe (root)..."
cargo publish --dry-run
echo ""
echo "✅ All crates ready for publishing!"
'''