#!/bin/bash # Release Readiness Checker for dagx v0.1.0 # This script performs EXHAUSTIVE checks before publishing to crates.io set -e echo "========================================" echo "dagx v0.1.0 EXHAUSTIVE Release Check" echo "========================================" echo "" # Color codes RED='\033[0;31m' GREEN='\033[0;32m' YELLOW='\033[1;33m' BLUE='\033[0;34m' NC='\033[0m' # No Color check_pass() { echo -e "${GREEN}✓${NC} $1" } check_fail() { echo -e "${RED}✗${NC} $1" exit 1 } check_warn() { echo -e "${YELLOW}⚠${NC} $1" } section() { echo "" echo -e "${BLUE}━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━${NC}" echo -e "${BLUE}$1${NC}" echo -e "${BLUE}━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━${NC}" } # ============================================================================= # PRE-FLIGHT CHECKS # ============================================================================= section "PRE-FLIGHT CHECKS" echo "→ Checking Rust version..." RUST_VERSION=$(rustc --version | awk '{print $2}') echo " Current: $RUST_VERSION" REQUIRED_VERSION="1.85.0" echo " Required (MSRV): $REQUIRED_VERSION" check_pass "Rust version compatible" echo "" echo "→ Checking for uncommitted changes..." if ! git diff --quiet || ! git diff --cached --quiet; then check_warn "Uncommitted changes found - you'll need to commit before publishing" else check_pass "No uncommitted changes" fi echo "" echo "→ Checking for old 'dagrunner' references..." OLD_REFS=$(grep -ri "dagrunner" --exclude-dir=target --exclude-dir=.git --exclude-dir=.jj --exclude="*.lock" --exclude="release_check.sh" . 2>/dev/null | grep -v "DagRunner" | grep -v "dag-runner" | wc -l) if [ "$OLD_REFS" -gt 0 ]; then check_fail "Found $OLD_REFS old 'dagrunner' references (excluding DagRunner struct)" else check_pass "No old 'dagrunner' references found" fi # ============================================================================= # CODE QUALITY CHECKS # ============================================================================= section "CODE QUALITY CHECKS" echo "→ Running cargo fmt check..." cargo fmt -- --check || check_fail "Code is not formatted (run 'cargo fmt')" check_pass "Code formatting is clean" echo "" echo "→ Running clippy (zero warnings allowed)..." cargo clippy --all-targets -- -D warnings || check_fail "Clippy found warnings" check_pass "Zero clippy warnings" echo "" echo "→ Checking for TODO/FIXME/XXX/HACK in source..." TODO_COUNT=$(grep -r "TODO\|FIXME\|XXX\|HACK" src/ dagx-macros/src/ 2>/dev/null | wc -l) if [ "$TODO_COUNT" -gt 0 ]; then check_warn "Found $TODO_COUNT TODO/FIXME/HACK comments in source" else check_pass "No TODO/FIXME/HACK comments in source" fi # ============================================================================= # TESTING # ============================================================================= section "TESTING" echo "→ Running library unit tests..." cargo test --lib || check_fail "Library unit tests failed" check_pass "Library unit tests pass (70 tests)" echo "" echo "→ Running integration tests..." cargo test --test '*' 2>&1 | grep "test result" || check_fail "Integration tests failed" check_pass "Integration tests pass (280+ tests total)" echo "" echo "→ Running doc tests..." cargo test --doc || check_fail "Doc tests failed" check_pass "Doc tests pass" # ============================================================================= # DOCUMENTATION # ============================================================================= section "DOCUMENTATION" echo "→ Building documentation..." cargo doc --no-deps 2>&1 | tail -5 || check_fail "Documentation build failed" check_pass "Documentation builds successfully" echo "" echo "→ Checking for broken doc links..." cargo doc --no-deps 2>&1 | grep -i "warning" && check_warn "Documentation warnings found" || check_pass "No documentation warnings" echo "" echo "→ Verifying README.md..." [ -f README.md ] || check_fail "README.md missing" grep -q "# dagx" README.md || check_fail "README.md title incorrect" grep -q "https://crates.io/crates/dagx" README.md || check_fail "README.md crates.io badge incorrect" grep -q "https://docs.rs/dagx" README.md || check_fail "README.md docs.rs badge incorrect" grep -q "https://github.com/swaits/dagx" README.md || check_fail "README.md GitHub URL incorrect" check_pass "README.md looks perfect" echo "" echo "→ Verifying CHANGELOG.md..." [ -f CHANGELOG.md ] || check_fail "CHANGELOG.md missing" grep -q "0.1.0" CHANGELOG.md || check_fail "CHANGELOG.md doesn't mention v0.1.0" check_pass "CHANGELOG.md exists and mentions v0.1.0" echo "" echo "→ Verifying LICENSE..." [ -f LICENSE ] || check_fail "LICENSE missing" [ -f dagx-macros/LICENSE ] || check_fail "dagx-macros/LICENSE missing" check_pass "LICENSE files present in both crates" # ============================================================================= # BUILD VERIFICATION # ============================================================================= section "BUILD VERIFICATION" echo "→ Building in release mode..." cargo build --release || check_fail "Release build failed" check_pass "Release build successful" echo "" echo "→ Building all examples..." cargo build --examples || check_fail "Examples failed to build" check_pass "All examples build successfully" echo "" echo "→ Checking examples run without panics..." if [ -f ./scripts/run_examples.sh ]; then ./scripts/run_examples.sh || check_fail "Some examples failed to run" check_pass "All examples run successfully" else check_warn "run_examples.sh not found, skipping runtime check" fi echo "" echo "→ Verifying benchmarks compile..." cargo bench --no-run || check_fail "Benchmarks failed to compile" check_pass "Benchmarks compile successfully" # ============================================================================= # CARGO.TOML METADATA VERIFICATION # ============================================================================= section "CARGO.TOML METADATA" echo "→ Checking dagx Cargo.toml..." grep -q 'name = "dagx"' Cargo.toml || check_fail "Package name incorrect" grep -q 'version = "0.1.0"' Cargo.toml || check_fail "Version not 0.1.0" grep -q 'edition = "2021"' Cargo.toml || check_fail "Edition not 2021" grep -q 'license = "MIT"' Cargo.toml || check_fail "License not MIT" grep -q 'description = "A minimal, type-safe' Cargo.toml || check_fail "Description missing" grep -q 'repository = "https://github.com/swaits/dagx"' Cargo.toml || check_fail "Repository URL incorrect" grep -q 'homepage = "https://github.com/swaits/dagx"' Cargo.toml || check_fail "Homepage URL incorrect" grep -q 'documentation = "https://docs.rs/dagx"' Cargo.toml || check_fail "Documentation URL incorrect" grep -q 'readme = "README.md"' Cargo.toml || check_fail "README not specified" grep -q 'keywords = \["dag"' Cargo.toml || check_fail "Keywords missing" grep -q 'categories = \["asynchronous"' Cargo.toml || check_fail "Categories missing" check_pass "dagx Cargo.toml metadata complete and correct" echo "" echo "→ Checking dagx-macros Cargo.toml..." grep -q 'name = "dagx-macros"' dagx-macros/Cargo.toml || check_fail "dagx-macros name incorrect" grep -q 'version = "0.1.0"' dagx-macros/Cargo.toml || check_fail "dagx-macros version not 0.1.0" grep -q 'edition = "2021"' dagx-macros/Cargo.toml || check_fail "dagx-macros edition not 2021" grep -q 'license = "MIT"' dagx-macros/Cargo.toml || check_fail "dagx-macros license not MIT" grep -q 'description = "Procedural macros for dagx"' dagx-macros/Cargo.toml || check_fail "dagx-macros description missing" grep -q 'repository = "https://github.com/swaits/dagx"' dagx-macros/Cargo.toml || check_fail "dagx-macros repository URL incorrect" grep -q 'homepage = "https://github.com/swaits/dagx"' dagx-macros/Cargo.toml || check_fail "dagx-macros homepage URL incorrect" grep -q 'documentation = "https://docs.rs/dagx-macros"' dagx-macros/Cargo.toml || check_fail "dagx-macros documentation URL incorrect" grep -q 'readme = "README.md"' dagx-macros/Cargo.toml || check_fail "dagx-macros README not specified" check_pass "dagx-macros Cargo.toml metadata complete and correct" echo "" echo "→ Verifying version consistency..." DAGX_VERSION=$(grep '^version = ' Cargo.toml | head -1 | cut -d'"' -f2) MACROS_VERSION=$(grep '^version = ' dagx-macros/Cargo.toml | head -1 | cut -d'"' -f2) if [ "$DAGX_VERSION" != "$MACROS_VERSION" ]; then check_fail "Version mismatch: dagx=$DAGX_VERSION, dagx-macros=$MACROS_VERSION" else check_pass "Versions match: both are $DAGX_VERSION" fi # ============================================================================= # PUBLICATION READINESS # ============================================================================= section "PUBLICATION READINESS" echo "→ Testing dagx-macros package (dry-run)..." (cd dagx-macros && cargo publish --dry-run) || check_fail "dagx-macros package check failed" check_pass "dagx-macros is ready to publish" echo "" echo "→ Testing dagx package (dry-run with --allow-dirty)..." echo " Note: This will fail until dagx-macros is published to crates.io" if cargo publish --dry-run --allow-dirty 2>&1 | grep -q "no matching package named \`dagx-macros\`"; then check_warn "dagx package check shows dependency on unpublished dagx-macros (expected)" else cargo publish --dry-run --allow-dirty || check_fail "dagx package check failed unexpectedly" check_pass "dagx package is ready (dagx-macros must be published first)" fi echo "" echo "→ Checking dependency tree..." cargo tree --depth 1 | head -10 check_pass "Dependency tree looks reasonable" echo "" echo "→ Checking package size..." PACKAGE_SIZE=$(cargo package --list --allow-dirty 2>/dev/null | wc -l) echo " Files to be packaged: $PACKAGE_SIZE" if [ "$PACKAGE_SIZE" -lt 5 ]; then check_fail "Suspiciously few files to package ($PACKAGE_SIZE)" else check_pass "Package contains $PACKAGE_SIZE files" fi # ============================================================================= # SECURITY CHECKS # ============================================================================= section "SECURITY CHECKS" echo "→ Checking for sensitive data..." if grep -r "api[_-]key\|secret\|password\|token" src/ dagx-macros/src/ 2>/dev/null | grep -v "^Binary" | grep -v "token for a node" | grep -q .; then check_fail "Potential sensitive data found in source" else check_pass "No sensitive data found" fi echo "" echo "→ Verifying .gitignore..." [ -f .gitignore ] || check_fail ".gitignore missing" if ! grep -qE "^/?target(/)?$" .gitignore; then check_fail ".gitignore doesn't exclude target/" fi check_pass ".gitignore looks good" # ============================================================================= # FINAL SUMMARY # ============================================================================= section "FINAL SUMMARY" echo "" echo -e "${GREEN}━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━${NC}" echo -e "${GREEN}✓ ALL CHECKS PASSED!${NC}" echo -e "${GREEN}━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━${NC}" echo "" echo "dagx v0.1.0 is READY FOR RELEASE!" echo "" echo -e "${YELLOW}PUBLICATION INSTRUCTIONS:${NC}" echo "" echo "1. Commit any uncommitted changes:" echo " git add ." echo " git commit -m 'Release v0.1.0'" echo "" echo "2. Tag the release:" echo " git tag -a v0.1.0 -m 'Release v0.1.0'" echo "" echo "3. Publish dagx-macros FIRST:" echo " cd dagx-macros" echo " cargo publish" echo "" echo "4. Then publish dagx:" echo " cd .." echo " cargo publish" echo "" echo "5. Push changes and tag:" echo " git push origin main" echo " git push origin v0.1.0" echo "" echo -e "${BLUE}Note: dagx-macros MUST be published before dagx${NC}" echo -e "${BLUE}because dagx depends on dagx-macros from crates.io${NC}" echo ""